STK++ 1.0
STK_ITContainer2D.h
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2011  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::Sdk::TContainer
00027  * created on: 26 nov. 2011
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  **/
00030 
00039 #ifndef STK_ITCONTAINER2D_H
00040 #define STK_ITCONTAINER2D_H
00041 
00042 #include "STK_IContainer2D.h"
00043 #include "STK_ITContainer1D.h"
00044 #include "../../STKernel/include/STK_Exceptions.h"
00045 
00046 namespace STK
00047 {
00048 template <class TYPE, class TContainer2D>
00049 class ContainerTraits;
00050 
00100 template <class TYPE, class TContainer2D>
00101 class ITContainer2D : public IContainerBase<TContainer2D>, public IContainer2D
00102 {
00103   protected:
00108     ITContainer2D( Range const& I = Range(), Range const& J = Range())
00109                  : IContainerBase<TContainer2D>(IContainerBase<TContainer2D>::_2D_)
00110                  , IContainer2D(I, J)
00111     { this->ranges_.push_back(&rangeVe_); this->ranges_.push_back(&rangeHo_);}
00112 
00116     ITContainer2D( const ITContainer2D &T)
00117                  : IContainerBase<TContainer2D>(IContainerBase<TContainer2D>::_2D_)
00118                  , IContainer2D(T)
00119     { this->ranges_.push_back(&rangeVe_); this->ranges_.push_back(&rangeHo_);}
00120 
00121   public:
00123     typedef TYPE Type;
00126     typedef typename ContainerTraits<TYPE, TContainer2D>::TContainerVe TContainerVe;
00129     typedef typename ContainerTraits<TYPE, TContainer2D>::TContainerHo TContainerHo;
00130 
00132     virtual ~ITContainer2D() { ;}
00133 
00139     inline TYPE& elt(Integer const& i, Integer const& j)
00140     { return this->asLeaf().elt(i,j);}
00141 
00147     inline TYPE const& elt(Integer const& i, Integer const& j) const
00148     { return this->asLeaf().elt(i,j);}
00149 
00155     inline TYPE& operator()(Integer const& i, Integer const& j)
00156     { return this->asLeaf().elt(i,j);}
00157 
00163     inline TYPE const& operator()(Integer const& i, Integer const& j) const
00164     { return this->asLeaf().elt(i,j);}
00165 
00170     inline TContainerVe operator[](Integer const& j) const
00171     { return this->asLeaf().col(j);}
00172 
00177     inline TContainerVe col(Integer const& j) const
00178     { return this->asLeaf().col(j);}
00179 
00186     inline TContainerVe operator()(Range const& I, Integer const& j) const
00187     { return this->asLeaf().col(I, j);}
00188 
00193     inline TContainerHo operator()(Integer const& i) const
00194     { return this->asLeaf().row(i);}
00195 
00200     inline TContainerHo row(Integer const& i) const
00201     { return this->asLeaf().row(i);}
00202 
00209     inline TContainerHo operator()(Integer const& i, Range const& J) const
00210     { return this->asLeaf().row(i, J);}
00211 
00217     inline TContainer2D operator()(Range const& I, Range const& J) const
00218     { return this->asLeaf().sub(I, J);}
00219 
00225     inline TContainer2D operator()(Range const& I) const
00226     { return this->asLeaf().sub(I, this->rangeHo());}
00227 
00233     inline TContainer2D operator[](Range const& J) const
00234     { return this->asLeaf().sub(this->rangeVe(), J);}
00235 
00241     TYPE& at(Integer const& i, Integer const& j)
00242     {
00243       if (this->firstRow() > i)
00244       { throw out_of_range("ITContainer2DBase::at(i, j) "
00245                                 "this->firstRow() > i");
00246       }
00247       if (this->lastRow() < i)
00248       { throw out_of_range("ITContainer2DBase::at(i, j) "
00249                                 "this->lastRow() < i");
00250       }
00251       if (this->firstCol() > j)
00252       { throw out_of_range("ITContainer2DBase::at(i, j) "
00253                                 "this->firstCol() > j");
00254       }
00255       if (this->lastCol() < j)
00256       { throw out_of_range("ITContainer2DBase::at(i, j) "
00257                                 "this->lastCol() < j");
00258       }
00259       return this->asLeaf().elt(i, j);
00260     }
00261 
00267     TYPE const& at(Integer const& i, Integer const& j) const
00268     {
00269       // check bounds
00270       if (this->firstRow() > i)
00271       { throw out_of_range("ITContainer2DBase::at(i, j) "
00272                                 "this->firstRow() > i");
00273       }
00274       if (this->lastRow() < i)
00275       { throw out_of_range("ITContainer2DBase::at(i, j) "
00276                                 "this->lastRow() < i");
00277       }
00278       if (this->firstCol() > j)
00279       { throw out_of_range("ITContainer2DBase::at(i, j) "
00280                                 "this->firstCol() > j");
00281       }
00282       if (this->lastCol() < j)
00283       { throw out_of_range("ITContainer2DBase::at(i, j) "
00284                                 "this->lastCol() < j");
00285       }
00286       // return element
00287       return this->asLeaf().elt(i, j);
00288     }
00289 
00294     inline TContainer2D at(Range const& I, Range const& J) const
00295     {
00296       if (this->firstRow() > I.first())
00297       { throw out_of_range("ITContainer2D::at(I, J) "
00298                                 "this->firstRow() > I.first()");
00299       }
00300       if (this->lastRow() < I.last())
00301       { throw out_of_range("ITContainer2D::at(I, J) "
00302                                 "this->lastRow() < I.last()");
00303       }
00304       if (this->firstCol() > J.first())
00305       { throw out_of_range("ITContainer2D::at(I, J) "
00306                                 "this->firstCol() > J.first()");
00307       }
00308       if (this->lastCol() < J.last())
00309       { throw out_of_range("ITContainer2D::at(I, J) "
00310                                 "this->lastCol() < J.last()");
00311       }
00312       return this->asLeaf().sub(I, J);
00313     }
00314 
00319     inline TContainerVe at(Range const& I, Integer const& j) const
00320     {
00321       if (this->firstRow() > I.first())
00322       { throw out_of_range("TContainer2D::at(I, j) "
00323                            "this->firstRow() > I.first()");
00324       }
00325       if (this->lastRow() < I.last())
00326       { throw out_of_range("TContainer2D::at(I, j) "
00327                            "this->lastRow() < I.last()");
00328       }
00329       if (this->firstCol() > j)
00330       { throw out_of_range("TContainer2D::at(I, j) "
00331                            "this->firstCol() > j");
00332       }
00333       if (this->lastCol() < j)
00334       { throw out_of_range("TContainer2D::at(I, j) "
00335                            "this->lastCol() < j");
00336       }
00337       return this->asLeaf().col(I, j);
00338     }
00339 
00344     inline TContainerHo at(Integer const& i, Range const& J) const
00345     {
00346       if (this->firstRow() > i)
00347       { throw out_of_range("TContainer2D::at(i, J) "
00348                                 "this->firstRow() > i");
00349       }
00350       if (this->lastRow() < i)
00351       { throw out_of_range("TContainer2D::at(i, J) "
00352                                 "this->lastRow() < i");
00353       }
00354       if (this->firstCol() > J.first())
00355       { throw out_of_range("TContainer2D::at(i, J) "
00356                                 "this->firstCol() > J.first()");
00357       }
00358       if (this->lastCol() < J.last())
00359       { throw out_of_range("TContainer2D::at(i, J) "
00360                                 "this->lastCol() < J.last()");
00361       }
00362       return this->asLeaf().row(J, i);
00363     }
00364 
00368     inline TContainerVe atCol(Integer const& j) const
00369     {
00370       if (this->firstCol() > j)
00371       { throw out_of_range("TContainer2D::atCol(j) "
00372                                 "this->firstCol() > j");
00373       }
00374       if (this->lastCol() < j)
00375       { throw out_of_range("TContainer2D::atCol(j) "
00376                                 "this->lastCol() < j");
00377       }
00378       return this->asLeaf().col(this->rangeVe(), j);
00379     }
00380 
00384     inline TContainer2D atCol(Range const& J) const
00385     {
00386       if (this->firstCol() > J.first())
00387       { throw out_of_range("TContainer2D::atCol(J) "
00388                                 "this->firstCol() > J.first()");
00389       }
00390       if (this->lastCol() < J.last())
00391       { throw out_of_range("TContainer2D::atCol(J) "
00392                                 "this->lastCol() < J.last()");
00393       }
00394       return this->asLeaf().sub(this->rangeVe(), J);
00395     }
00396 
00400     inline TContainerHo atRow(Integer const& i) const
00401     {
00402       if (this->firstRow() > i)
00403       { throw out_of_range("TContainer2D::atRow(i) "
00404                                 "this->firstRow() > i");
00405       }
00406       if (this->lastRow() < i)
00407       { throw out_of_range("TContainer2D::atRow(i) "
00408                                 "this->lastRow() < i");
00409       }
00410       return this->asLeaf().row(i, this->rangeHo());
00411     }
00412 
00416     inline TContainer2D atRow(Range const& I) const
00417     {
00418       if (this->firstRow() > I.first())
00419       { throw out_of_range("TContainer2D::atRow(I) "
00420                                 "this->firstRow() > I.first()");
00421       }
00422       if (this->lastRow() < I.last())
00423       { throw out_of_range("TContainer2D::atRow(I) "
00424                                 "this->lastRow() < I.last()");
00425       }
00426       return this->asLeaf().sub(I, this->rangeHo());
00427     }
00428 
00432     template<class Container1D>
00433     inline void pushBackCol(ITContainer1D<TYPE, Container1D> const& V)
00434     {
00435       const Integer firstRow = V.first(), lastRow = V.last();
00436       // check if the container is empty
00437       if (this->empty())
00438       {
00439         this->resize(V.range(), Range(1));
00440         for (Integer i=firstRow; i<=lastRow; i++)
00441           (*this)(i, 1) = V[i];
00442         return;
00443       }
00444 #ifdef STK_BOUNDS_CHECK
00445       if (V.range() != this->rangeVe())
00446       { throw runtime_error("TContainer2D::pushBackCol(V) "
00447                                  "V.range() != this->rangeVe()");
00448       }
00449 #endif
00450       // if the container is not empty we add a column and copy V inside
00451       this->asLeaf().pushBackCols();
00452       const Integer lastCol = this->lastCol();
00453       for (Integer i=firstRow; i<=lastRow; i++)
00454         (*this)(i, lastCol) = V[i];
00455     }
00456 };
00457 
00458 } // namespace STK
00459 
00460 #endif
00461 // STK_ITCONTAINER2D_H