STK++ 1.0
STK_IArray2D.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::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