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