STK++ 1.0
STK_Point.h
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project:  stkpp::Arrays
00027  * Purpose:  Define the Point classe.
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  *
00030  **/
00031 
00037 #ifndef STK_POINT_H
00038 #define STK_POINT_H
00039 
00040 // ArrayHo Class
00041 #include "STK_ArrayHo.h"
00042 
00043 namespace STK
00044 {
00051 typedef ArrayHo<Real> Point;
00052 
00058 template<>
00059 class ArrayHo<Real> : public IArray1DBase<Real, Real*, ArrayHo<Real> >
00060 {
00061   public:
00063     typedef AllocatorBase<Real*> _AllocatorBaseType_;
00064 
00066     typedef IArray1DBase<Real, Real*, ArrayHo<Real> > _IArrayHoType;
00067 
00071     ArrayHo( Range const& I = Range())
00072            : _IArrayHoType(I)
00073     { this->initElts(I);}
00074 
00079     ArrayHo( Range const& I, Real const& v)
00080            : _IArrayHoType(I)
00081     {
00082       this->initElts(I);
00083       // set value v
00084       for (Integer i=this->first(); i<=this->last(); i++)
00085         this->elt(i) = v;
00086     }
00087 
00092     ArrayHo( const ArrayHo &T, bool ref =false)
00093            : _IArrayHoType(T, ref)
00094     {
00095       // check if we want just a reference
00096       if (!ref)
00097       {
00098         // if this is not a reference, initialize the container
00099         this->initElts(T.range());
00100         // this and T have the same row : save time
00101         const Integer row(T.getIndex());
00102         // and copy the data
00103         for (Integer j=this->first(); j<=this->last(); j++)
00104           this->data(j)[row] = T.data(j)[row];
00105       }
00106     }
00107 
00112     ArrayHo( const ArrayHo<Real>& T, Range const& I)
00113            : _IArrayHoType(T, I)
00114     { ;}
00115 
00121      ArrayHo( const _AllocatorBaseType_& T, Range const& I, Integer row)
00122             : _IArrayHoType(T, I, row)
00123     { ;}
00124 
00126     virtual ~ArrayHo()
00127     { if (!this->isRef())
00128       { freeElts(this->range());}
00129     }
00130 
00134     inline Real const & elt(Integer const& pos) const
00135     { return this->data(pos)[this->getIndex()];}
00136 
00140     inline Real& elt(Integer const& pos)
00141     { return this->data(pos)[this->getIndex()];}
00142 
00146     inline ArrayHo elt(Range const& J) const
00147     { return ArrayHo(*this, J, this->getIndex());}
00148 
00150     void clear()
00151     {
00152       this->freeMem();  // Free Mem
00153       this->setRange(); // Set dimension to default
00154     }
00155 
00159     void freeMem()
00160     {
00161       if (this->isRef()) return;        // Nothing to do for ref
00162       this->freeElts(this->range()); // free the ptr of elts
00163       this->free1D();                   // free the elts
00164     }
00165 
00171     void initialize(Range const& I)
00172     {
00173       // check if there is memory allocated
00174       this->clear();
00175       // if we initialize the memory the container is not a reference
00176       this->setRef(false);
00177       // try to allocate memory
00178       this->init1D(I);
00179       // initialize Horizontally the container
00180       this->initElts(I);
00181       // set the range of the container if init1D is successful
00182       this->setRange(I);
00183     }
00184 
00188     void pushBack( Integer const& n=1)
00189     {
00190       // if n<=0 nothing to do
00191       if (n <= 0) return;
00192       // is this structure just a pointer?
00193       if (this->isRef())
00194       { throw runtime_error("ArrayHo::pushBack(n) "
00195                             "can't operate on references.");
00196       }
00197       // If the container is empty : create it
00198       if (this->empty())
00199         this->initialize(Range(this->first(), this->first()+n-1));
00200       else
00201         this->insertElt(this->last()+1, n);
00202     }
00203 
00207     void popBack(Integer const& n = 1)
00208     {
00209       // if n<=0 nothing to do
00210       if (n <= 0) return;
00211       // is this structure just a pointer?
00212       if (this->isRef())
00213       { throw runtime_error("ArrayHo::popBack() "
00214                             "can't operate on references.");
00215       }
00216 #ifdef STK_BOUNDS_CHECK
00217       // if there is elts to erase
00218       if (this->size()<n)
00219       { throw out_of_range("ArrayHo::popBack(n) "
00220                            "this->size() < n");
00221       }
00222 #endif
00223       // delete each elt
00224       this->freeElts(Range(this->last()-n+1, this->last()));
00225       // update range
00226       this->decLast(n);
00227       // if there is no more Elts
00228       if (this->size() == 0) this->freeMem();
00229     }
00230 
00235     void erase( Integer const& pos, Integer const& n=1)
00236     {
00237       // if n==0 nothing to do
00238       if (n<=0) return;
00239       // is this structure just a pointer?
00240       if (this->isRef())
00241       { throw runtime_error("ArrayHo::erase(pos, n) "
00242                             "can't operate on references.");
00243       }
00244 #ifdef STK_BOUNDS_CHECK
00245       // check bounds
00246       if (this->first() > pos)
00247       { throw out_of_range("ArrayHo::erase(pos, n) "
00248                            "this->first() > pos");
00249       }
00250       if (this->last() < pos)
00251       { throw out_of_range("ArrayHo::erase(pos, n)"
00252                            " this->last() < pos");
00253       }
00254       if (this->last() < pos+n-1)
00255       { throw out_of_range("ArrayHo::erase(pos, n)"
00256                            " this->last() < pos+n-1");
00257       }
00258 #endif
00259       // delete each col
00260       freeElts(Range(pos, pos+n-1));
00261       // shift Elts
00262       const Integer last = this->last()-n;
00263       for (Integer k=pos; k<=last; k++)
00264         this->setData(k, this->data(k+n));
00265       // update rangeHo_
00266       this->decLast(n);
00267       // if there is no more Elts
00268       if (this->size() == 0) this->freeMem();
00269     }
00270  
00277     inline ArrayHo& operator=(const ArrayHo &T)
00278     { // We have to resize if this and T does not have the same size
00279       // but if they have the same size, we don't scale the index
00280       if (this->size()!=T.size()) this->resize(T.range());
00281 
00282       // copy without ovelapping
00283       if (this->first() < T.first())
00284       { for (Integer j=this->first(), i=T.first(); i<=T.last(); j++, i++)
00285           elt(j) = T.elt(i);
00286       }
00287       else
00288       { for (Integer j=this->last(), i=T.last(); i>=T.first(); j--, i--)
00289           elt(j) = T.elt(i);
00290       }
00291       return *this;
00292     }
00293 
00297     inline ArrayHo& operator=(Real const& v)
00298     {
00299       const Integer first =this->first(), last = this->last();
00300       for (Integer i=first; i<=last; i++)
00301         this->elt(i) = v;
00302       return *this;
00303     }
00304 
00308     inline ArrayHo& operator+=(Real const& v)
00309     {
00310       const Integer first =this->first(), last = this->last();
00311       for (Integer i=first; i<=last; i++)
00312         this->elt(i) += v;
00313       return *this;
00314     }
00315 
00319     inline ArrayHo& operator-=(Real const& v)
00320     {
00321       const Integer first =this->first(), last = this->last();
00322       for (Integer i=first; i<=last; i++)
00323         this->elt(i) -= v;
00324       return *this;
00325     }
00326 
00330     inline ArrayHo& operator/=(Real const& v)
00331     {
00332       const Integer first =this->first(), last = this->last();
00333       for (Integer i=first; i<=last; i++)
00334         this->elt(i) /= v;
00335       return *this;
00336     }
00337 
00341     inline ArrayHo& operator*=(Real const& v)
00342     {
00343       const Integer first =this->first(), last = this->last();
00344       for (Integer i=first; i<=last; i++)
00345         this->elt(i) *= v;
00346       return *this;
00347     }
00348 
00355     template <class LEAF>
00356     inline ArrayHo& operator=(const ITContainer1D<Real, LEAF> &T)
00357     { // We have to resize if this and T does not have the same size
00358       // but if they have the same size, we don't scale the index
00359       if (this->size()!=T.size()) this->resize(T.range());
00360 
00361       // copy without ovelapping
00362       if (this->first() < T.first())
00363       { for (Integer j=this->first(), i=T.first(); i<=T.last(); j++, i++)
00364           elt(j) = T[i];
00365       }
00366       else
00367       { for (Integer j=this->last(), i=T.last(); i>=T.first(); j--, i--)
00368           elt(j) = T[i];
00369       }
00370       return *this;
00371     }
00372     
00376     template< class Exp>
00377     inline ArrayHo& operator=(const Exp& rhs)
00378     {
00379       const Integer first =this->first(), last = this->last();
00380       for (Integer i=first; i<=last; i++)
00381         this->elt(i) = rhs[i];
00382       return *this;
00383     }
00384 
00388     template< class Exp>
00389     inline ArrayHo& operator+=(const Exp& rhs)
00390     {
00391       const Integer first =this->first(), last = this->last();
00392       for (Integer i=first; i<=last; i++)
00393         this->elt(i) += rhs[i];
00394       return *this;
00395     }
00396 
00400     template< class Exp>
00401     inline ArrayHo& operator-=(const Exp& rhs)
00402     {
00403       const Integer first =this->first(), last = this->last();
00404       for (Integer i=first; i<=last; i++)
00405         this->elt(i) -= rhs[i];
00406       return *this;
00407     }
00408 
00412     template< class Exp>
00413     inline ArrayHo& operator/=(const Exp& rhs)
00414     {
00415       const Integer first =this->first(), last = this->last();
00416       for (Integer i=first; i<=last; i++)
00417         this->elt(i) /= rhs[i];
00418       return *this;
00419     }
00420 
00424     template< class Exp>
00425     inline ArrayHo& operator*=(const Exp& rhs)
00426     {
00427       const Integer first =this->first(), last = this->last();
00428       for (Integer i=first; i<=last; i++)
00429         this->elt(i) *= rhs[i];
00430       return *this;
00431     }
00432 
00433   protected:
00437     void initElts(Range const& J)
00438     {
00439       // for each col
00440       for (Integer j=J.first(); j<=J.last(); j++)
00441       {
00442         // try to Allocate mem for the jth elt
00443         try
00444         {
00445           this->initElt(j);
00446         }
00447         catch (runtime_error & error)   // if an error occur
00448         {
00449           // for each column allocated
00450           for (Integer k=J.first(); k<j; k++)
00451             this->freeElt(k);
00452           // put default parameters for the elts j to end
00453           for (Integer k=j; k<=J.last(); k++)
00454             this->setData(k, 0);
00455           // and throw an Exception
00456           throw error;
00457         }
00458       }
00459     }
00460 
00464     void freeElts(Range const& J)
00465     { 
00466       // for all elts
00467       for (Integer j=J.first(); j<=J.last(); j++)
00468         this->freeElt(j);
00469     }
00470 
00475     void initElt(Integer const& pos)
00476     {
00477       // try to Allocate mem for each col
00478       try
00479       {
00480         this->setData(pos, new Real);
00481         this->data(pos) -= this->getIndex();
00482       }
00483       catch (std::bad_alloc & error)        // if an alloc error occur
00484       {
00485         // set default
00486         this->setData(pos, 0);
00487         // throw an Exception
00488         throw runtime_error("ArrayHo::initElt(pos) "
00489                             "memory allocation failed.");
00490       }
00491     }
00492 
00497     void freeElt(Integer const& pos)
00498     {
00499       if (this->data(pos))  // if there is an elt
00500       {
00501         this->data(pos) += this->getIndex();
00502         delete this->data(pos);  // erase
00503         this->setData(pos, 0);         // set default
00504       }
00505     }
00506   protected:
00513     void insertElt( Integer const& pos, Integer const& n =1)
00514     {
00515       // if n<=0 nothing to do
00516       if (n <= 0) return;
00517       // is this structure just a pointer?
00518       if (this->isRef())
00519       { throw runtime_error("ArrayHo<Real>::insertElt(pos, n) "
00520                                  "can't operate on references.");
00521       }
00522 #ifdef STK_BOUNDS_CHECK
00523       // check indices
00524       if (this->first() > pos)
00525       { throw out_of_range("ArrayHo<Real>::insertElt(pos, n) "
00526                                 "this->first() > pos");
00527       }
00528       if (this->last()+1 < pos)
00529       { throw out_of_range("ArrayHo<Real>::insertElt(pos, n) "
00530                                 "this->last()+1 < pos");
00531       }
00532 #endif
00533       // allocate, if necessary, the mem for the elts
00534       if (this->capacity() < this->size()+n)
00535       {
00536         // compute range of the container after insertion
00537         Range range(this->range());
00538         range.incLast(n);
00539         // temporary empty container
00540         ArrayHo Taux;
00541         // save Elts in Taux
00542         this->swap(Taux);
00543         // initialize Elts of the container
00544         try
00545         {
00546           this->init1D(range);
00547         }
00548         catch (runtime_error & error)   // if an error occur
00549         {
00550           this->swap(Taux);   // restore container
00551           throw error;        // and send again the Exception
00552         }
00553         // reset initial stored in range
00554         this->setRange(Taux.range());
00555         // move first Elts from Taux to this
00556         for (Integer k=this->first(); k<pos; k++)
00557           this->moveElt(k,  Taux, k);
00558         // translate and copy last Elts from Taux to this
00559         for (Integer k=this->last(); k>=pos; k--)
00560           this->moveElt(k+n, Taux, k);
00561       }
00562       else // enough space -> initialize and shift the last elts
00563       {
00564         // translate data
00565         for (Integer k=this->last(); k>=pos; k--)
00566           this->moveElt(k+n, *this, k);
00567       }
00568       // initialize the Elts in the range pos:pos+n-1
00569       initElts(Range(pos, pos+n-1));
00570       // update range
00571       this->incLast(n);
00572     }
00573 };
00574 
00575 } // namespace STK
00576 
00577 #endif // STK_POINT_H