|
STK++ 1.0
|
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