|
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 * Purpose: Define the Interface for the Array classes. 00028 * Author: Serge Iovleff, serge.iovleff@stkpp.org 00029 * 00030 **/ 00031 00041 #ifndef STK_IARRAY2DBASE_H 00042 #define STK_IARRAY2DBASE_H 00043 00044 #include "../../Sdk/include/STK_ITContainer2D.h" 00045 00046 #include "STK_AllocatorBase.h" 00047 #include "STK_Array1D.h" 00048 00049 namespace STK 00050 { 00074 template < class TYPE 00075 , class PTRCOL 00076 , class TArray2D 00077 > 00078 class IArray2DBase : public ITContainer2D< TYPE, TArray2D> 00079 , public AllocatorBase<PTRCOL> 00080 { 00081 protected: 00085 Array1D<Integer> capacityCols_; 00086 00089 Array1D<Range> rangeCols_; 00090 00091 public: 00093 typedef AllocatorBase<PTRCOL> _AllocatorBaseType_; 00094 00096 typedef ITContainer2D<TYPE, TArray2D> _ITContainer2DType; 00097 00098 protected: 00103 IArray2DBase( Range const& I = Range(), Range const& J = Range()) 00104 : _ITContainer2DType(I, J) 00105 , _AllocatorBaseType_() 00106 , capacityCols_() 00107 , rangeCols_() 00108 , capacityHo_(0) 00109 { mallocHo(J);} 00110 00117 IArray2DBase( const IArray2DBase& T, bool ref =false) 00118 : _ITContainer2DType(T) 00119 , _AllocatorBaseType_(T, ref) 00120 , capacityCols_(T.capacityCols_) 00121 , rangeCols_(T.rangeCols_) 00122 , capacityHo_(T.capacityHo_) 00123 { 00124 if (!ref) 00125 mallocHo(T.rangeHo()); 00126 } 00127 00133 IArray2DBase( const IArray2DBase& T, Range const& I, Range const& J) 00134 : _ITContainer2DType(I, J) 00135 , _AllocatorBaseType_(T, true) 00136 , capacityCols_(J) 00137 , rangeCols_(J) 00138 , capacityHo_(T.capacityHo_) 00139 { 00140 #ifdef STK_BOUNDS_CHECK 00141 if (I.first() < T.firstRow()) 00142 { throw out_of_range("IArray2DBase::IArray2DBase(T, I, J) " 00143 "I.first() < T.firstRow()"); 00144 } 00145 if (I.last() > T.lastRow()) 00146 { throw out_of_range("IArray2DBase::IArray2DBase(T, I, J) " 00147 "I.last() > T.lastRow()"); 00148 } 00149 if (J.first() < T.firstCol()) 00150 { throw out_of_range("IArray2DBase::IArray2DBase(T, I, J) " 00151 "J.first() < T.firstCol()"); 00152 } 00153 if (J.last() > T.lastCol()) 00154 { throw out_of_range("IArray2DBase::IArray2DBase(T, I, J) " 00155 "J.last() > T.lastCol()"); 00156 } 00157 #endif 00158 // adjust capacity and range of each Cols 00159 for (Integer j=J.first(); j<=J.last(); j++) 00160 { 00161 // copy capacity of the column j (is it necessary ?) 00162 capacityCols_[j] = T.capacityCols_[j]; 00163 // compute available range of the column j 00164 rangeCols_[j] = Range::inf(I, T.rangeCols_[j]); 00165 } 00166 } 00167 00173 IArray2DBase( PTRCOL* q, Range const& I, Range const& J) 00174 : _ITContainer2DType(I, J) 00175 , _AllocatorBaseType_(q, J) 00176 , capacityCols_(J, I.size()) 00177 , rangeCols_(J, I) 00178 , capacityHo_(0) 00179 { ;} 00180 00181 public: 00185 virtual ~IArray2DBase() 00186 { ;} 00187 00191 inline Integer const& capacityHo() const 00192 { return capacityHo_;} 00193 00197 inline const Array1D<Integer> & capacityCols() const 00198 { return capacityCols_;} 00199 00203 inline Integer const& capacityCol(Integer const& col) const 00204 { return capacityCols_[col];} 00205 00208 inline Array1D<Range> const& rangeCols() const 00209 { return rangeCols_;} 00210 00214 inline Range const& rangeCol(Integer const& col) const 00215 { return rangeCols_[col];} 00216 00220 void shiftHo(Integer const& cbeg =1) 00221 { 00222 // compute increment 00223 Integer cinc = cbeg - this->firstCol(); 00224 // if there is something to do 00225 if (cinc != 0) 00226 { 00227 // is this structure just a pointer? 00228 if (this->isRef()) 00229 { throw runtime_error("IArray2DBase::shiftHo(cbeg) " 00230 "can't operate on references."); 00231 } 00232 // translate rangeHo_ 00233 this->incRangeHo(cinc); 00234 // translate data 00235 this->shiftPtrData(cbeg); 00236 // tranlate capacityCols_ 00237 capacityCols_.shift(cbeg); 00238 // translate rangeCols_ 00239 rangeCols_.shift(cbeg); 00240 } 00241 } 00242 00247 void swapCols(Integer const& pos1, Integer const& pos2) 00248 { 00249 #ifdef STK_BOUNDS_CHECK 00250 if (this->firstCol() > pos1) 00251 { throw out_of_range("IArray2D::swapCols(pos1, pos2) " 00252 "this->firstCol() >pos1"); 00253 } 00254 if (this->lastCol() < pos1) 00255 { throw out_of_range("IArray2D::swapCols(pos1, pos2) " 00256 "this->lastCol() <pos1"); 00257 } 00258 if (this->firstCol() > pos2) 00259 { throw out_of_range("IArray2D::swapCols(pos1, pos2) " 00260 "this->firstCol() >pos2"); 00261 } 00262 if (this->lastCol() < pos2) 00263 { throw out_of_range("IArray2D::swapCols(pos1, pos2) " 00264 "this->lastCol() <pos2"); 00265 } 00266 #endif 00267 // swap 00268 PTRCOL qaux(this->data(pos1)); 00269 this->setData(pos1, this->data(pos2)); 00270 this->setData(pos2, qaux); 00271 // update capacityCols_ 00272 STK::swap(capacityCols_[pos1], capacityCols_[pos2]); 00273 // update rangeCols_ 00274 STK::swap(rangeCols_[pos1], rangeCols_[pos2]); 00275 } 00276 00280 void swap(IArray2DBase &T) 00281 { 00282 // swap AllocatorBase part 00283 this->AllocatorBase<PTRCOL>::swap(T); 00284 00285 // swap ITContainer2D part 00286 this->_ITContainer2DType::swap(T); 00287 00288 // swap IArray2DBase part 00289 STK::swap(this->capacityHo_, T.capacityHo_); 00290 capacityCols_.swap(T.capacityCols_); 00291 rangeCols_.swap(T.rangeCols_); 00292 } 00293 00302 void pushBackByTransfer(IArray2DBase const& T) 00303 { 00304 // is this structure just a pointer? 00305 if (this->isRef()) 00306 { throw runtime_error("In IArray2DBase::pushBackByTransfer(T) " 00307 "(*this) is a reference."); 00308 } 00309 // is T just a pointer? 00310 if (T.isRef()) 00311 { throw runtime_error("In IArray2DBase::pushBackByTransfer(T) " 00312 "T is a reference."); 00313 } 00314 // if there is no columns, we can safely modify the vertical range 00315 if (this->sizeHo() <= 0) 00316 this->setRangeVe(T.rangeVe()); 00317 // Are ranges corrects ? 00318 if (this->rangeVe() != T.rangeVe()) 00319 { throw runtime_error("In IArray2DBase::pushBackByTransfer(T) " 00320 "this->rangeVe() != T.rangeVe()."); 00321 } 00322 // break const reference 00323 IArray2DBase& Tref = const_cast<IArray2DBase&>(T); 00324 // compute horizontal range of the container after insertion 00325 Range rangeHo(this->rangeHo()); 00326 // compute first index of the first column added 00327 const Integer first = rangeHo.last() + 1; 00328 // reallocate memory 00329 rangeHo.incLast(Tref.sizeHo()); 00330 reallocHo(rangeHo); 00331 this->setRangeHo(rangeHo); 00332 // align T range 00333 const Integer last = rangeHo.last(); 00334 Tref.shiftHo(first); 00335 // copy data from T 00336 for (Integer j=first; j<= last; j++) 00337 { 00338 copyColumn(Tref, j, j); 00339 } 00340 // release memory allocated for the columns 00341 Tref.freePtrData(); 00342 Tref.setPtrData(this->ptrData(), this->rangeData()); 00343 Tref.setRef(true); 00344 } 00345 00346 protected: 00351 inline void setCapacityHo(Integer const& capacity = 0) 00352 { capacityHo_ = capacity;} 00353 00362 void copyColumn( IArray2DBase const& T, Integer const& pos1, Integer const& pos2) 00363 { 00364 // copy column pos2 of T in pos1 of this 00365 this->setData(pos1, T.data(pos2)); 00366 // set capacityCols_ 00367 capacityCols_[pos1] = T.capacityCols_[pos2]; 00368 // set rangeCols_ 00369 rangeCols_[pos1] = T.rangeCols_[pos2]; 00370 } 00371 00381 void transferColumn( IArray2DBase& T, Integer const& pos1, Integer const& pos2) 00382 { 00383 // copy column pos2 of T in pos1 of this 00384 this->setData(pos1, T.data(pos2)); 00385 // set capacityCols_ 00386 capacityCols_[pos1] = T.capacityCols_[pos2]; 00387 // set rangeCols_ 00388 rangeCols_[pos1] = T.rangeCols_[pos2]; 00389 // set column of T to default 00390 T.setDefaultCol(pos2); 00391 } 00392 00399 void mallocHo(Range const& J) 00400 { 00401 // compute the size necessary (can be 0) 00402 Integer size = this->evalCapacity(J.size()); 00403 // try to allocate memory 00404 try 00405 { 00406 // initialize this->capacityCols_ 00407 capacityCols_.resize(J); 00408 // initialize this->rangeCols_ 00409 rangeCols_.resize(J); 00410 // allocate memory for the columns 00411 this->mallocPtrData(size, J.first()); 00412 } 00413 catch (runtime_error & error) // if an error occur 00414 { 00415 // set default capacity (0) 00416 setCapacityHo(); 00417 // set default range 00418 this->setRangeHo(); 00419 // clear this->capacityCols_ 00420 capacityCols_.clear(); 00421 // clear this->rangeCols_ 00422 rangeCols_.clear(); 00423 // throw the error 00424 throw error; 00425 } 00426 // set new capacity if no error occur 00427 this->setCapacityHo(size); 00428 } 00429 00436 void reallocHo(Range const& J) 00437 { 00438 // compute the size necessary (can be 0) 00439 Integer size = this->evalCapacity(J.size()); 00440 // try to allocate memory 00441 try 00442 { 00443 // allocate memory for the columns 00444 this->reallocPtrData(size, J.first()); 00445 // initialize this->capacityCols_ 00446 capacityCols_.resize(J); 00447 // initialize this->rangeCols_ 00448 rangeCols_.resize(J); 00449 } 00450 catch (runtime_error & error) // if an error occur 00451 { 00452 // set default capacity (0) 00453 this->setCapacityHo(); 00454 // set default range 00455 this->setRangeHo(); 00456 // clear this->capacityCols_ 00457 this->capacityCols_.clear(); 00458 // clear this->rangeCols_ 00459 this->rangeCols_.clear(); 00460 // throw the error 00461 throw error; 00462 } 00463 // set new capacity if no error occur 00464 this->setCapacityHo(size); 00465 } 00466 00473 void freeHo() 00474 { 00475 // Nothing to do for reference 00476 if (this->isRef()) return; 00477 // free memory allocated in AllocatorBase 00478 this->freePtrData(); 00479 // set capacity size to default 00480 this->setCapacityHo(); 00481 // set range of the Cols to default 00482 this->setRangeHo(Range(this->firstCol(), this->firstCol()-1)); 00483 // set capacityCols_ to default 00484 capacityCols_.clear(); 00485 // set rangeCols_ to default 00486 rangeCols_.clear(); 00487 } 00488 00489 private: 00493 Integer capacityHo_; 00494 00500 inline void setDefaultCol(Integer const& pos) 00501 { 00502 // set column of T to default 00503 this->setData(pos, (PTRCOL)NULL); 00504 // set capacityCols_ 00505 this->capacityCols_[pos] = 0; 00506 // set rangeCols_ 00507 this->rangeCols_[pos] = Range(); 00508 } 00509 }; 00510 00511 } // namespace STK 00512 00513 #endif 00514 // STK_IARRAY2DBASE_H