|
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::Arrrays 00027 * Purpose: Define the Interface for the Array classes. 00028 * Author: Serge Iovleff, serge.iovleff@stkpp.org 00029 * 00030 **/ 00031 00041 #ifndef STK_IARRAY2D_H 00042 #define STK_IARRAY2D_H 00043 00044 #include "../../STKernel/include/STK_Range.h" 00045 #include "STK_IArray2DBase.h" 00046 00047 #include "STK_Array1D.h" 00048 #include "STK_ArrayHo.h" 00049 00050 namespace STK 00051 { 00052 00071 template < class TYPE, class TArray2D > 00072 class IArray2D : public IArray2DBase< TYPE, TYPE*, TArray2D> 00073 { 00075 typedef IArray2DBase< TYPE, TYPE*, TArray2D> _AllocatorBaseType_; 00076 00077 protected: 00082 IArray2D( Range const& I = Range(), Range const& J = Range()) 00083 : _AllocatorBaseType_(I, J) 00084 { ;} 00085 00090 IArray2D( const IArray2D& T, bool ref =false) 00091 : _AllocatorBaseType_(T, ref) 00092 { ;} 00093 00099 IArray2D( const IArray2D& T, Range const& I, Range const& J) 00100 : _AllocatorBaseType_(T, I, J) 00101 { ;} 00102 00108 IArray2D( TYPE** q, Range const& I, Range const& J) 00109 : _AllocatorBaseType_(q, I, J) 00110 { ;} 00111 00112 public: 00117 virtual ~IArray2D() 00118 { if (!this->isRef()) 00119 this->freeCols(this->rangeHo()); 00120 } 00121 00127 inline TYPE& elt(Integer const& i, Integer const& j) 00128 { return this->data(j)[i];} 00129 00135 inline TYPE const& elt(Integer const& i, Integer const& j) const 00136 { return this->data(j)[i];} 00137 00143 inline Array1D<TYPE> col(Range const& I, Integer const& j) const 00144 { return Array1D<TYPE>(this->data(j), I, j);} 00145 00150 inline Array1D<TYPE> col( Integer const& j) const 00151 { return Array1D<TYPE>(this->data(j), this->rangeVe(), j);} 00152 00158 inline ArrayHo<TYPE> row( Integer const& i, Range const& J) const 00159 { return ArrayHo<TYPE>(*this, J, i);} 00160 00165 inline ArrayHo<TYPE> row( Integer const& i) const 00166 { return ArrayHo<TYPE>(*this, this->rangeHo(), i);} 00167 00172 void clear() 00173 { 00174 // free allocated mem 00175 this->freeMem(); 00176 // Set dimensions to default 00177 this->setRange(); 00178 } 00179 00184 void shift(Integer const& rbeg =1, Integer const& cbeg =1) 00185 { 00186 // move begin of the col 00187 this->shiftHo(cbeg); 00188 // move begin of the row 00189 this->shiftVe(rbeg); 00190 } 00191 00195 void shiftVe(Integer const& rbeg =1) 00196 { 00197 // compute increment 00198 Integer rinc = rbeg - this->firstRow(); 00199 // if there is something to do 00200 if (rinc != 0) 00201 { 00202 // is this structure just a pointer? 00203 if (this->isRef()) 00204 { throw runtime_error("IArray2D::shiftVe(rbeg) " 00205 "can't operate on references."); 00206 } 00207 // translate rangeVe_() 00208 this->incRangeVe(rinc); 00209 // For all cols, move begin 00210 for (Integer j=this->firstCol(); j<=this->lastCol(); j++) 00211 { 00212 shiftCol(j, this->rangeCols_[j].first()+rinc); 00213 } 00214 } 00215 } 00216 00220 void pushBackRows(Integer const& n=1) 00221 { 00222 // if n<=0 nothing to do 00223 if (n <= 0) return; 00224 // is this structure just a pointer? 00225 if (this->isRef()) 00226 { throw runtime_error("IArray2D::pushBackRows(n) " 00227 "can't operate on references."); 00228 } 00229 // If the container have no rows : create its 00230 if (this->sizeVe() <=0) 00231 { 00232 // update the range of the container 00233 this->incLastVe(n); 00234 // initialize the container 00235 this->initializeCols(this->rangeHo()); 00236 } 00237 else 00238 { 00239 // update the range of the rows 00240 this->incLastVe(n); 00241 // allocate new Rows for each Col 00242 for (Integer j=this->firstCol(); j<=this->lastCol(); j++) 00243 { 00244 // compute range from the leaf 00245 Range range(this->asLeaf().compRangeVe(j)); 00246 // if there is no column or the end is less than the container 00247 // end 00248 if ((range.size()>0)&&(range.last()>this->lastRow()-n)) 00249 { 00250 // if the column is empty create it 00251 if (this->rangeCols_[j].size()<=0) 00252 { 00253 this->initializeCol(j, range); 00254 } 00255 else 00256 { 00257 // compute position 00258 Integer pos(this->lastRow()-n+1); 00259 // add elts 00260 insertRowsToCol(j, pos, range.last() - pos +1); 00261 } 00262 } 00263 } 00264 } 00265 } 00266 00273 void insertRows(Integer const& pos, Integer const& n =1) 00274 { 00275 // if n<=0 nothing to do 00276 if (n <= 0) return; 00277 #ifdef STK_BOUNDS_CHECK 00278 // check indices 00279 if (this->firstRow() > pos) 00280 { throw out_of_range("IArray2D::insertRows(pos, n) " 00281 "this->firstRow() > pos"); 00282 } 00283 if (this->lastRow()+1 < pos) 00284 { throw out_of_range("IArray2D::insertRows(pos, n) " 00285 "this->lastRow()+1 < pos"); 00286 } 00287 #endif 00288 // is this structure just a pointer? 00289 if (this->isRef()) 00290 { throw runtime_error("IArray2D::insertRows(pos, n) " 00291 "can't operate on references."); 00292 } 00293 // update the range of the rows 00294 this->incLastVe(n); 00295 // allocate new Rows for each Col 00296 for (Integer j=this->firstCol(); j<=this->lastCol(); j++) 00297 { 00298 // check position 00299 if ( (pos >= this->rangeCols_[j].first()) 00300 ||(pos <= this->rangeCols_[j].last()+1) 00301 ) 00302 { 00303 insertRowsToCol(j, pos, n); 00304 } 00305 } 00306 } 00307 00311 void popBackRows(Integer const& n = 1) 00312 { 00313 // if n<=0 nothing to do 00314 if (n <= 0) return; 00315 // is this structure just a pointer? 00316 if (this->isRef()) 00317 { throw runtime_error("IArray2D::popBackRows() " 00318 "can't operate on references."); 00319 } 00320 #ifdef STK_BOUNDS_CHECK 00321 // if there is Rows to erase 00322 if (this->sizeVe()<n) 00323 { throw out_of_range("IArray2D::popBackRows(n) " 00324 "this->sizeVe() < n"); 00325 } 00326 #endif 00327 // update range of the container 00328 this->decLastVe(n); 00329 // decrease range of each Col 00330 for (Integer j=this->firstCol(); j<=this->lastCol(); j++) 00331 eraseRowsToCol(j, this->lastRow()+1, n); 00332 } 00333 00338 void eraseRows(Integer const& pos, Integer const& n=1) 00339 { 00340 // if n==0 nothing to do 00341 if (n<=0) return; 00342 // is this structure just a pointer? 00343 if (this->isRef()) 00344 { throw runtime_error("IArray2D::eraseRows(pos, n) " 00345 "can't operate on references."); 00346 } 00347 #ifdef STK_BOUNDS_CHECK 00348 // check bounds 00349 if (this->firstRow() > pos) 00350 { throw out_of_range("IArray2D::eraseRows(pos, n) " 00351 "this->firstRow() > pos"); 00352 } 00353 if (this->lastRow() < pos) 00354 { throw out_of_range("IArray2D::eraseRows(pos, n)" 00355 " this->lastRow() < pos"); 00356 } 00357 if (this->lastRow() < pos+n-1) 00358 { throw out_of_range("IArray2D::eraseRows(pos, n)" 00359 " this->lastRow() < pos+n-1"); 00360 } 00361 #endif 00362 // save posistion and size 00363 Integer posRow = pos, nbRow = n; 00364 // update dimensions 00365 this->decLastVe(n); 00366 // update each Col 00367 for (Integer j=this->firstCol(); j<=this->lastCol(); j++) 00368 eraseRowsToCol(j, posRow, nbRow); 00369 } 00370 00374 void pushBackCols(Integer const& n = 1) 00375 { 00376 // if n<=0 nothing to do 00377 if (n <= 0) return; 00378 // is this structure just a pointer? 00379 if (this->isRef()) 00380 { throw runtime_error("IArray2D::pushBackCols(n) " 00381 "can't operate on references."); 00382 } 00383 // If the container have no Cols : create its 00384 if (this->sizeHo() <=0) 00385 { 00386 // update end col 00387 this->incLastHo(n); 00388 // initialize Horizontally the container 00389 this->mallocHo(this->rangeHo()); 00390 // initialize Vertically the container 00391 initializeCols( this->rangeHo()); 00392 } 00393 else // else insert to the end of the container 00394 insertCols(this->lastCol()+1, n); 00395 } 00396 00401 void insertCols(Integer const& pos, Integer const& n =1) 00402 { 00403 // if n<=0 nothing to do 00404 if (n <= 0) return; 00405 // is this structure just a pointer? 00406 if (this->isRef()) 00407 { throw runtime_error("IArray2D::insertCols(pos, n) " 00408 "can't operate on references."); 00409 } 00410 #ifdef STK_BOUNDS_CHECK 00411 // check bounds 00412 if (this->firstCol() > pos) 00413 { throw out_of_range("IArray2D::insertCols(pos, n) " 00414 "this->firstCol() > pos"); 00415 } 00416 if (this->lastCol()+1 < pos) 00417 { throw out_of_range("IArray2D::insertCols(pos, n) " 00418 "this->lastCol()+1 < pos"); 00419 } 00420 #endif 00421 // compute horizontal range of the container after insertion 00422 Range range_ho(this->rangeHo()); 00423 range_ho.incLast(n); 00424 // allocate, if necessary, the mem for the Cols 00425 if (this->capacityHo() < range_ho.size()) // not enough space 00426 { 00427 // temporary empty container (the number of Rows is the same) 00428 // but there is no Cols 00429 TArray2D Taux(this->rangeVe(), Range()); 00430 // swap with Taux 00431 this->swap(Taux); 00432 // initialize columns of the container 00433 try 00434 { 00435 this->mallocHo(range_ho); 00436 } 00437 catch (runtime_error & error) // if an error occur 00438 { 00439 this->swap(Taux); // restore container 00440 throw error; // and send again the stdexcept 00441 } 00442 // set the range of the Columns 00443 this->setRangeHo(range_ho); 00444 // move first Columns from Taux to this 00445 for (Integer k=this->firstCol(); k<pos; k++) 00446 this->transferColumn(Taux, k, k); 00447 // translate and copy last Cols from Taux to this 00448 for (Integer k=Taux.lastCol(); k>=pos; k--) 00449 this->transferColumn(Taux, k+n, k); 00450 } 00451 else // enough space -> shift the last Cols 00452 { 00453 Range addRange(this->lastCol()+1, this->lastCol()+n); 00454 // insert capacity for the new Cols 00455 this->capacityCols_.insert(addRange, 0); 00456 // insert range for the new Cols 00457 this->rangeCols_.insert(addRange, Range()); 00458 // update range_ 00459 this->incLastHo(n); 00460 // translate data 00461 for (Integer k=this->lastCol()-n; k>=pos; k--) 00462 this->transferColumn( this->asLeaf(), k+n, k); 00463 } 00464 // initialize the rows for the Cols, this->capacityCols_, this->rangeCols_ 00465 // in the range pos:pos+n-1 00466 this->initializeCols(Range(pos, pos+n-1)); 00467 } 00468 00472 void popBackCols(Integer const& n =1) 00473 { 00474 // if n<=0 nothing to do 00475 if (n<=0) return; 00476 // is this structure just a pointer? 00477 if (this->isRef()) 00478 { throw runtime_error("IArray2D::popBackCols(n) " 00479 "can't operate on references."); 00480 } 00481 #ifdef STK_BOUNDS_CHECK 00482 // check range 00483 if (this->sizeHo() < n) 00484 { throw out_of_range("IArray2D::popBackCols(n) " 00485 "this->sizeHo() < n"); 00486 } 00487 #endif 00488 // delete each col 00489 this->freeCols(Range(this->lastCol()-n+1, this->lastCol())); 00490 // update this->capacityCols_ 00491 this->capacityCols_.popBack(n); 00492 // update this->rangeCols_ 00493 this->rangeCols_.popBack(n); 00494 // update rangeHo 00495 this->decLastHo(n); 00496 // if there is no more Cols 00497 if (this->sizeHo() == 0) this->freeMem(); 00498 } 00499 00504 void eraseCols(Integer const& pos, Integer const& n = 1) 00505 { 00506 if (n<=0) return; // if n<=0 nothing to do 00507 #ifdef STK_BOUNDS_CHECK 00508 // check range 00509 if (this->firstCol() > pos) 00510 { throw out_of_range("IArray2D::eraseCols(pos, n) " 00511 "this->firstCol() > pos"); 00512 } 00513 if (this->lastCol() < pos) 00514 { throw out_of_range("IArray2D::eraseCols(pos, n) " 00515 "this->lastCol() < pos"); 00516 } 00517 if (this->lastCol() < pos+n-1) 00518 { throw out_of_range("IArray2D::eraseCols(pos, n) " 00519 "this->lastCol() < pos+n-1"); 00520 } 00521 #endif 00522 // is this structure just a pointer? 00523 if (this->isRef()) 00524 { throw runtime_error("IArray2D::eraseCols(pos, n) " 00525 "can't operate on references."); 00526 } 00527 // delete each col 00528 this->freeCols(Range(pos, pos+n-1)); 00529 // update rangeHo_ 00530 this->decLastHo(n); 00531 // shift Cols 00532 for (Integer k=pos; k<=this->lastCol(); k++) 00533 this->setData(k, this->data(k+n)); 00534 // update this->capacityCols_ 00535 this->capacityCols_.erase(pos, n); 00536 // update this->rangeCols_ 00537 this->rangeCols_.erase(pos, n); 00538 // if there is no more Cols 00539 if (this->sizeHo() == 0) this->freeMem(); 00540 } 00541 00545 void update(Range const& J) 00546 { 00547 #ifdef STK_BOUNDS_CHECK 00548 // check range 00549 if (this->firstCol() > J.first()) 00550 { throw out_of_range("IArray2D::update(J) " 00551 "this->firstCol() > J.first()"); 00552 } 00553 if (this->lastCol() < J.last()) 00554 { throw out_of_range("IArray2D::update(J) " 00555 "this->lastCol() < J.last()"); 00556 } 00557 #endif 00558 Integer firstCol(J.first()); 00559 Integer lastCol(J.last()); 00560 00561 for ( Integer icol = firstCol; icol <= lastCol ; ++icol) 00562 { 00563 if (this->asLeaf().compRangeVe(icol) != this->rangeCol(icol)) 00564 { this->resizeCol(icol, this->asLeaf().compRangeVe(icol));} 00565 } 00566 } 00567 00571 void update(Integer const& pos) 00572 { 00573 #ifdef STK_BOUNDS_CHECK 00574 // check range 00575 if (this->firstCol() > pos) 00576 { throw out_of_range("IArray2D::update(pos) " 00577 "this->firstCol() > pos"); 00578 } 00579 if (this->lastCol() < pos) 00580 { throw out_of_range("IArray2D::update(pos) " 00581 "this->lastCol() < pos"); 00582 } 00583 #endif 00584 if (this->asLeaf().compRangeVe(pos) != this->rangeCol(pos)) 00585 { this->resizeCol(pos, this->asLeaf().compRangeVe(pos));} 00586 } 00587 00588 protected: 00594 void freeMem() 00595 { 00596 // Nothing to do for reference 00597 if (this->isRef()) return; 00598 // free the Rows memory 00599 this->freeCols(this->rangeHo()); 00600 // liberate horizontally 00601 this->freeHo(); 00602 } 00603 00611 void initialize(Range const& I, Range const& J) 00612 { 00613 // check if there is memory allocated 00614 this->clear(); 00615 // if we initialize the memory the container is not a reference 00616 this->setRef(false); 00617 // create this->capacityCols_ 00618 this->capacityCols_.resize(J); 00619 // create this->rangeCols_ 00620 this->rangeCols_.resize(J); 00621 // set the Horizontal range of the container 00622 this->setRangeHo(J); 00623 // initialize Horizontally the container 00624 this->mallocHo(J); 00625 // set the vertical range of the container 00626 this->setRangeVe(I); 00627 // initialize Vertically the container 00628 this->initializeCols(J); 00629 } 00630 00636 void initializeCols(Range const& J) 00637 { 00638 // for each col 00639 for (Integer j=J.first(); j<=J.last(); j++) 00640 { 00641 // try to Allocate mem for the jth col 00642 try 00643 { 00644 // initialize the cols with the computed range 00645 // specific to the container 00646 this->initializeCol(j, this->asLeaf().compRangeVe(j)); 00647 } 00648 catch (runtime_error & error) // if an error occur 00649 { 00650 // free each column allocated 00651 for (Integer k=J.first(); k<j; k++) 00652 this->freeCol(k); 00653 // put default for the other Cols 00654 for (Integer k=j; k<=J.last(); k++) this->setData(k, 0); 00655 // and throw an stdexcept 00656 throw error; 00657 } 00658 } 00659 } 00660 00668 void initializeCol(Integer const& pos, Range const& I) 00669 { 00670 if (I.size() <=0) 00671 { 00672 // set default for ptr 00673 this->setData(pos, (TYPE*)NULL); 00674 // set default value for this->capacityCols_[pos] 00675 this->capacityCols_[pos] = 0; 00676 // set default value for this->rangeCols_[pos] 00677 this->rangeCols_[pos] = I; 00678 // return 00679 return; 00680 } 00681 // compute the size necessary (cannot be 0) 00682 Integer size = this->evalCapacity(I.size()); 00683 // try to allocate memory 00684 try 00685 { 00686 this->setData(pos, new TYPE[size]); 00687 } 00688 catch (std::bad_alloc & error) // if an alloc error occur 00689 { 00690 // set default for ptr 00691 this->setData(pos, (TYPE*)NULL); 00692 // set default value for this->capacityCols_[pos] 00693 this->capacityCols_[pos] = 0; 00694 // set default value for this->rangeCols_[pos] 00695 this->rangeCols_[pos] = Range(); 00696 // and throw an stdexcept 00697 throw runtime_error("IArray2D::initializeCol(pos, J) " 00698 "memory allocation failed."); 00699 } 00700 // increment ptr of the column 00701 this->data(pos) -= I.first(); 00702 // set size for this->capacityCols_[pos] 00703 this->capacityCols_[pos] = size; 00704 // set value for this->rangeCols_[pos] 00705 this->rangeCols_[pos] = I; 00706 } 00707 00711 void freeCols(Range const& J) 00712 { 00713 // for all Cols 00714 for (Integer j=J.first(); j<=J.last(); j++) 00715 this->freeCol(j); 00716 } 00717 00721 void freeCol(Integer const& pos) 00722 { 00723 if (this->data(pos)) // if there is cols 00724 { 00725 // increment the ptr 00726 this->data(pos) += this->rangeCols_[pos].first(); 00727 // delete allocated mem for the column pos 00728 delete [] this->data(pos); 00729 // set default value for ptr 00730 this->setData(pos, (TYPE*)NULL); 00731 // set default value for this->capacityCols_[pos] 00732 this->capacityCols_[pos] = 0; 00733 // set default value for this->rangeCols_[pos] 00734 this->rangeCols_[pos] = Range(); 00735 } 00736 } 00737 00745 void shiftCol( Integer const& pos, Integer const& beg) 00746 { 00747 #ifdef STK_BOUNDS_CHECK 00748 // check bounds 00749 if (this->firstCol() > pos) 00750 { throw out_of_range("IArray2D::shiftCol(pos, n) " 00751 "this->firstCol() > pos"); 00752 } 00753 if (this->lastCol() < pos) 00754 { throw out_of_range("IArray2D::shiftCol(pos, n) " 00755 "this->lastCol() < pos"); 00756 } 00757 #endif 00758 // compute increment 00759 Integer rinc = beg - this->rangeCols_[pos].first(); 00760 // check if there is data 00761 if (this->data(pos)) 00762 { 00763 // transate ptr 00764 this->data(pos) -= rinc; 00765 } 00766 // translate this->rangeCols_ 00767 this->rangeCols_[pos].inc(rinc); 00768 } 00769 00780 void resizeCol( Integer const& pos, Range const& I) 00781 { 00782 #ifdef STK_BOUNDS_CHECK 00783 // check bounds 00784 if (this->firstCol() > pos) 00785 { throw out_of_range("IArray2D::resizeCol(pos, I) " 00786 "this->firstCol() > pos"); 00787 } 00788 if (this->lastCol() < pos) 00789 { throw out_of_range("IArray2D::resizeCol(pos, I) " 00790 "this->lastCol() < pos"); 00791 } 00792 #endif 00793 // check if there is something to do 00794 if (this->rangeCol(pos) == I) return; 00795 // shift to the desired first index 00796 shiftCol(pos, I.first()); 00797 // compute difference of size 00798 Integer inc = this->rangeCol(pos).size() - I.size(); 00799 // nothing to do 00800 if (inc == 0) return; 00801 // add row 00802 if (inc < 0) 00803 { 00804 pushBackRowsToCol(pos, -inc); 00805 } 00806 else // delete rows 00807 { 00808 popBackRowsToCol(pos, inc); 00809 } 00810 } 00811 00820 void insertRowsToCol( Integer const& col 00821 , Integer const& pos 00822 , Integer const& n =1 00823 ) 00824 { 00825 #ifdef STK_BOUNDS_CHECK 00826 // check bounds 00827 if (this->firstCol() > col) 00828 { throw out_of_range("IArray2D::insertRowsToCol(col, n) " 00829 "this->firstCol() > col"); 00830 } 00831 if (this->lastCol() < col) 00832 { throw out_of_range("IArray2D::insertRowsToCol(col, n) " 00833 "this->lastCol() < col"); 00834 } 00835 if (this->rangeCols_[col].first() > pos) 00836 { throw out_of_range("IArray2D::insertRowsToCol(col, pos, n) " 00837 "this->rangeCols_[col].first() > pos"); 00838 } 00839 if (this->rangeCols_[col].last()+1 < pos) 00840 { throw out_of_range("IArray2D::insertRowsToCol(col, pos, n) " 00841 "this->rangeCols_[col].last()+1 < pos"); 00842 } 00843 #endif 00844 // wrap old Col 00845 TYPE* ptr_old_col(this->data(col)); 00846 // get vertical range of the Col 00847 Range range_ve(this->rangeCols_[col]); 00848 // update range 00849 this->rangeCols_[col].incLast(n); 00850 // allocate if necessary the Col 00851 if (this->capacityCols_[col] < this->rangeCols_[col].size()) 00852 { 00853 // create new Col 00854 this->initializeCol(col, this->rangeCols_[col]); 00855 // if there was data, copy and liberate 00856 if (ptr_old_col) 00857 { 00858 // get ptr on the new col 00859 TYPE* ptr_new_col(this->data(col)); 00860 // copy first Elts 00861 for (Integer k=range_ve.first(); k<pos; k++) 00862 ptr_new_col[k] = ptr_old_col[k]; 00863 // translate and copy last Elts 00864 for (Integer k=range_ve.last(); k>=pos; k--) 00865 ptr_new_col[k+n] = ptr_old_col[k]; 00866 // increment ptr_col 00867 ptr_old_col += range_ve.first(); 00868 // and free old col 00869 delete [] ptr_old_col; 00870 } 00871 } 00872 else // enough space 00873 { 00874 // translate last Elts 00875 for (Integer k=range_ve.last(); k>=pos; k--) 00876 ptr_old_col[k+n] = ptr_old_col[k]; 00877 } 00878 } 00879 00887 void pushBackRowsToCol( Integer const& col 00888 , Integer const& n =1 00889 ) 00890 { 00891 #ifdef STK_BOUNDS_CHECK 00892 // check bounds 00893 if (this->firstCol() > col) 00894 { throw out_of_range("IArray2D::pushBackRowsToCol(col, n) " 00895 "this->firstCol() > col"); 00896 } 00897 if (this->lastCol() < col) 00898 { throw out_of_range("IArray2D::pushBackRowsToCol(col, n) " 00899 "this->lastCol() < col"); 00900 } 00901 #endif 00902 // wrap old Col 00903 TYPE* ptr_old_col(this->data(col)); 00904 // get vertical range of the Col 00905 Range range_ve(this->rangeCol(col)); 00906 // compute vertical range of the Col after insertion 00907 //range_ve.incLast(n); 00908 this->rangeCols_[col].incLast(n); 00909 // allocate if necessary the Col 00910 if (this->capacityCols_[col] < range_ve.size()) 00911 { 00912 // create new Col 00913 this->initializeCol(col, this->rangeCols_[col]); 00914 // ger ptr on the new col 00915 TYPE* ptr_new_col(this->data(col)); 00916 // copy first Elts 00917 for (Integer k=range_ve.first(); k<=range_ve.last(); k++) 00918 ptr_new_col[k] = ptr_old_col[k]; 00919 // if there is data 00920 if (ptr_old_col) 00921 { 00922 // increment ptr_col 00923 ptr_old_col += range_ve.first(); 00924 // and free old col 00925 delete [] ptr_old_col; 00926 } 00927 } 00928 } 00929 00945 void eraseRowsToCol( Integer const& col 00946 , Integer const& pos 00947 , Integer const& n=1) 00948 { 00949 #ifdef STK_BOUNDS_CHECK 00950 // check bounds 00951 if (this->firstCol() > col) 00952 { throw out_of_range("IArray2D::eraseRowsToCol(col, pos, n) " 00953 "this->firstCol() > col"); 00954 } 00955 if (this->lastCol() < col) 00956 { throw out_of_range("IArray2D::eraseRowsToCol(col, pos, n) " 00957 "this->lastCol() < col"); 00958 } 00959 #endif 00960 // ptr on data 00961 TYPE* p_col(this->data(col)); 00962 // range of the data (can be different from the range of the container) 00963 Range rangeCol(this->rangeCols_[col]); 00964 // number of rows to delete 00965 Integer nRowsToDelete = n; 00966 // position of the row to delete 00967 Integer firstRowToDelete = pos; 00968 // if pos is after the data there is nothing to delete 00969 if (rangeCol.first()>rangeCol.last()) return; 00970 // if pos is before the data 00971 if (firstRowToDelete<rangeCol.first()) 00972 { 00973 // remove the not existing data ! 00974 nRowsToDelete -= nRowsToDelete -rangeCol.first(); 00975 // if there is no more rows to delete return 00976 if (nRowsToDelete<=0) return; 00977 // else shift data 00978 firstRowToDelete = rangeCol.first(); 00979 } 00980 // if pos+n is after the data 00981 if (firstRowToDelete+nRowsToDelete-1>rangeCol.last()) 00982 { 00983 // remove the not existing data ! 00984 nRowsToDelete = rangeCol.last()-firstRowToDelete+1; 00985 } 00986 // update range 00987 this->rangeCols_[col].decLast(nRowsToDelete); 00988 rangeCol.decLast(nRowsToDelete); 00989 // get range of the data to delete 00990 const Integer last = rangeCol.last(); 00991 // translate remaining Rows 00992 for ( Integer k=firstRowToDelete; k<=last; k++) 00993 { p_col[k] = p_col[k+nRowsToDelete];} 00994 // free mem if necessary 00995 if (this->rangeCols_[col].size()==0) freeCol(col); 00996 } 00997 01007 void popBackRowsToCol( Integer const& col, Integer const& n=1) 01008 { 01009 #ifdef STK_BOUNDS_CHECK 01010 // check bounds 01011 if (this->firstCol() > col) 01012 { throw out_of_range("IArray2D::popBackRowsToCol(col, n) " 01013 "this->firstCol() > col"); 01014 } 01015 if (this->lastCol() < col) 01016 { throw out_of_range("IArray2D::popBackRowsToCol(col, n) " 01017 "this->lastCol() < col"); 01018 } 01019 #endif 01020 // check if there is something to do 01021 if (n <= 0) return; 01022 // check argument error 01023 if (n > this->rangeCol(col).size()) 01024 { 01025 throw runtime_error("IArray2D::popBackRowsToCol(col, n) " 01026 "n > rangeCol(col).size()."); 01027 } 01028 // update range 01029 this->rangeCols_[col].decLast(n); 01030 // free mem if necessary 01031 if (this->rangeCols_[col].size()==0) 01032 freeCol(col); 01033 } 01034 }; 01035 01036 } // namespace STK 01037 01038 #endif 01039 // STK_IARRAY2D_H