STK++ 1.0
STK_RecursiveArray1D.h
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2007  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  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00028  **/
00029 
00038 #ifndef STK_RECURSIVEARRAY1D_H
00039 #define STK_RECURSIVEARRAY1D_H
00040 
00041 #include "STK_IArray1DBase.h"
00042 
00043 namespace STK
00044 {
00045 
00052 template<class TYPE, class Container1D >
00053 class RecursiveArray1D : public IArray1DBase<TYPE, TYPE, Container1D >
00054 {
00055   protected:
00057     typedef AllocatorBase<TYPE*> _AllocatorBaseType_;
00059     typedef IArray1DBase<TYPE, TYPE, Container1D > _IArray1DType;
00060 
00061   public:
00065     RecursiveArray1D( Range const& I = Range())
00066                     : _IArray1DType(I)
00067     { ;}
00068 
00073     RecursiveArray1D( Range const& I, TYPE const& v)
00074                    : _IArray1DType(I)
00075     {
00076       for (Integer i=this->first(); i<=this->last(); i++)
00077         this->setData(i, v);
00078     }
00079 
00084     RecursiveArray1D( const RecursiveArray1D &T, bool ref =false)
00085                    : _IArray1DType(T, ref)
00086     {
00087       // check if we want just a reference
00088       if (!ref)
00089       {
00090         for (Integer j=this->first(); j<=this->last(); j++)
00091           this->setData(j, T.data(j));
00092       }
00093     }
00094 
00099     RecursiveArray1D( RecursiveArray1D const& T, Range const& I)
00100                    : _IArray1DType(T, I)
00101     { ;}
00102 
00108     RecursiveArray1D( TYPE* q, Range const& I, Integer const& index =0)
00109                    : _IArray1DType(q, I, index)
00110     { ;}
00111 
00117      RecursiveArray1D( _AllocatorBaseType_ const& T, Range const& I, Integer const& index)
00118                     : _IArray1DType(T.data(index), I, index)
00119     { ;}
00120 
00124     virtual ~RecursiveArray1D() { }
00125 
00129     void clear()
00130     {
00131       if (this->isRef()) return;   // Nothing to do for ref
00132       this->freeMem();  // Free Mem
00133       this->setRange(); // Set dimension to default
00134     }
00135 
00139     virtual void pushBack( Integer const& n=1)
00140     {
00141       // if n<=0 nothing to do
00142       if (n <= 0) return;
00143 #ifdef STK_DEBUG
00144       // is this structure just a pointer?
00145       if (this->isRef())
00146       { throw runtime_error("Array1D::pushBack(n) "
00147                                  "can't operate on references.");
00148       }
00149 #endif
00150       // If the container is empty : create it
00151       if (this->empty())
00152         this->initialize(Range(this->first(), this->first()+n-1));
00153       else
00154         this->insertElt(this->last()+1, n);
00155     }
00156 
00160     virtual void popBack(Integer const& n = 1)
00161     {
00162       // if n<=0 nothing to do
00163       if (n <= 0) return;
00164 #ifdef STK_DEBUG
00165       // is this structure just a pointer?
00166       if (this->isRef())
00167       { throw runtime_error("Array1D::popBack() "
00168                             "can't operate on references.");
00169       }
00170 #endif
00171 #ifdef STK_BOUNDS_CHECK
00172       // if there is elts to erase
00173       if (this->size()<n)
00174       { throw out_of_range("Array1D::popBack(n) "
00175                            "this->size() < n");
00176       }
00177 #endif
00178       // update range
00179       this->decLast(n);
00180       // if there is no more elts
00181       if (this->size() == 0) this->freeMem();
00182     }
00183 
00188     virtual void erase(Integer const& pos, 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("Array1D::erase(pos, n) "
00195                                  "can't operate on references.");
00196       }
00197 #ifdef STK_BOUNDS_CHECK
00198       // check bounds
00199       if (this->first() > pos)
00200       { throw out_of_range("Array1D::erase(pos, n) "
00201                            "this->first() > pos");
00202       }
00203       if (this->last() < pos)
00204       { throw out_of_range("Array1D::erase(pos, n) "
00205                            "this->last() < pos");
00206       }
00207       if (this->last() < pos+n-1)
00208       { throw out_of_range("Array1D::erase(pos, n) "
00209                            "this->last() < pos+n-1");
00210       }
00211 #endif
00212       // translate remaining elts
00213       const Integer last = this->last()-n;
00214       for (Integer k=pos; k<=last; k++)
00215         this->setData(k, this->data(k+n));
00216       // update dimensions
00217       this->decLast(n);
00218       // if there is no more cols, free mem
00219       if (this->size() == 0) this->freeMem();
00220     }
00221 
00222   protected:
00228     void initialize(Range const& I)
00229     {
00230       // check if there is memory allocated
00231       this->clear();
00232       // if we initialize the memory the container is not a reference
00233       this->setRef(false);
00234       // try to allocate memory
00235       this->init1D(I);
00236       // set the range of the container if init1D is successful
00237       this->setRange(I);
00238     }
00239 
00243     void freeMem()
00244     {
00245       if (this->isRef()) return;   // Nothing to do for ref
00246       this->free1D();              // free the elts
00247     }
00248 
00255     virtual void insertElt( Integer const& pos, Integer const& n =1)
00256     {
00257       // if n<=0 nothing to do
00258       if (n <= 0) return;
00259       // is this structure just a pointer?
00260       if (this->isRef())
00261       { throw runtime_error("Array1D::insertElt(pos, n) "
00262                                  "can't operate on references.");
00263       }
00264 #ifdef STK_BOUNDS_CHECK
00265       // check indices
00266       if (this->first() > pos)
00267       { throw out_of_range("Array1D::insertElt(pos, n) "
00268                                 "this->first() > pos");
00269       }
00270       if (this->last()+1 < pos)
00271       { throw out_of_range("Array1D::insertElt(pos, n) "
00272                                 "this->last()+1 < pos");
00273       }
00274 #endif
00275       // allocate, if necessary, the mem for the elts
00276       if (this->capacity() < this->size()+n)
00277       {
00278         // temporary empty container
00279         RecursiveArray1D Taux;
00280         // save elts
00281         this->swap(Taux);
00282         // compute range of the container after insertion
00283         Range range(Taux.range());
00284         range.incLast(n);
00285         // initialize
00286         try
00287         {
00288           this->init1D(range);
00289         }
00290         catch (runtime_error & error)   // if an error occur
00291         {
00292           this->swap(Taux); // restore elts
00293           throw error;      // and send again the Exception
00294         }
00295         // reset initial stored in range
00296         this->setRange(Taux.range());
00297         // copy first elts
00298         for (Integer k=this->first(); k<pos; k++)
00299           this->setData(k, Taux.data(k));
00300         // translate and copy last elts
00301         for (Integer k=this->last(); k>=pos; k--)
00302           this->setData(k+n, Taux.data(k));
00303       }
00304       else // enough space -> shift the last elts
00305       {
00306         // translate data
00307         for (Integer k=this->last(); k>=pos; k--)
00308           this->setData(k+n, this->data(k));
00309       }
00310       // update range_
00311       this->incLast(n);
00312     }
00313 };
00314 
00315 } // namespace STK
00316 
00317 #endif
00318 // STK_RECURSIVEARRAY1D_H