STK++ 1.0
STK_IArrayBase.h
Go to the documentation of this file.
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 Base Interface for the Array classes.
00028  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00029  *
00030  **/
00031 
00036 #ifndef STK_IARRAYBASE_H
00037 #define STK_IARRAYBASE_H
00038 
00039 #include <stdexcept>
00040 
00041 #include "../../Sdk/include/STK_IContainerRef.h"
00042 #include "../../STKernel/include/STK_Range.h"
00043 
00044 namespace STK
00045 {
00046 
00058 template<class DATA>
00059 class IArrayBase : public IContainerRef
00060 {
00061   protected:
00065     IArrayBase( Range const& I = Range()) : IContainerRef(false)
00066                                           , p_data_(0)
00067                                           , rangeData_(I)
00068     { mallocPtrData( I.size(), I.first());}
00069 
00074     IArrayBase( const IArrayBase& T, bool ref = false)
00075               : IContainerRef(ref)
00076     {
00077       if (ref) // set T data
00078       {
00079         p_data_   = T.p_data_;
00080         rangeData_ = T.rangeData_;
00081       }
00082       else // Allocate memory in base class
00083       {
00084         setDefault();
00085       }
00086     }
00087 
00092     IArrayBase(DATA* q, Range const& I) : IContainerRef(true)
00093                                         , p_data_(q)
00094                                         , rangeData_(I)
00095     { ;}
00096 
00097   public:
00099     virtual ~IArrayBase()
00100     { if (!this->isRef()) this->freePtrData(); }
00101 
00105     inline Integer const& firstData() const { return rangeData_.first();}
00109     inline Integer const& lastData() const { return rangeData_.last();}
00113     inline Integer const& sizeData() const { return rangeData_.size();}
00117     inline Range const& rangeData() const { return rangeData_;}
00121     inline DATA const* const ptrData() const { return p_data_;}
00122 
00126     inline DATA const& data( Integer const& pos) const
00127     {
00128 #ifdef STK_BOUNDS_CHECK
00129       if (pos < firstData())
00130       { throw std::out_of_range("IArrayBase::data(pos) const "
00131                                 "IArrayBase::firstData() > pos");
00132       }
00133       if (pos > lastData())
00134       { throw std::out_of_range("IArrayBase::data(pos) const "
00135                                 "IArrayBase::lastData() < pos");
00136       }
00137 #endif
00138       return p_data_[pos];
00139     }
00140     
00145     static Integer evalCapacity(Integer const& m)
00146     {
00147       Integer n = 0;
00148       Integer b = m;
00149       for (Integer k=1 ; k <= b; n++, k <<= 1);
00150       return m+n;
00151     }
00152 
00153   protected:
00155     inline DATA* ptrData()
00156     { return p_data_;}
00157 
00161     inline DATA& data(Integer const& pos)
00162     {
00163 #ifdef STK_BOUNDS_CHECK
00164       if (pos < firstData())
00165       { throw std::out_of_range("IArrayBase::data(pos) "
00166                                 "IArrayBase::firstData() > pos");
00167       }
00168       if (pos > lastData())
00169       { throw std::out_of_range("IArrayBase::data(pos) "
00170                                 "IArrayBase::lastData() < pos");
00171       }
00172 #endif
00173       return p_data_[pos];
00174     }
00175         
00182    inline void setData( Integer const& pos, DATA const& data = DATA())
00183    {
00184 #ifdef STK_BOUNDS_CHECK
00185       if (pos < firstData())
00186       { throw std::out_of_range("IArrayBase::setData(pos, data) "
00187                                 "IArrayBase::firstData() > pos");
00188       }
00189       if (pos > lastData())
00190       { throw std::out_of_range("IArrayBase::setData(pos, data) "
00191                                 "IArrayBase::lastData() > pos");
00192       }
00193 #endif
00194      p_data_[pos] = data;
00195    }
00196 
00200     void swap(IArrayBase &T)
00201     {
00202       // copy main ptr data and range of this
00203       DATA*   auxMainPtr(p_data_);
00204       Range   auxRange(rangeData_);
00205       bool    auxRef(this->isRef());
00206 
00207       // overwrite main ptr data of this
00208       this->setPtrData(T.p_data_);
00209       this->setRangeData(T.rangeData_);
00210       this->setRef(T.isRef());
00211 
00212       // overwrite main PTRCOL of T
00213       T.setPtrData(auxMainPtr);
00214       T.setRangeData(auxRange);
00215       T.setRef(auxRef);
00216     }
00217 
00221     void shiftPtrData(Integer const& first)
00222     {
00223       // check if there is something to do
00224       if (first == firstData()) return;
00225       // check for reference
00226       if (this->isRef())
00227       { throw std::runtime_error("In IArrayBase::shiftPtrData(first)"
00228                                  " can't operate on reference.");
00229       }
00230       // compute increment
00231       Integer inc = first - firstData();
00232       // translate data
00233       decPtrData(inc);
00234     }
00239     void mallocPtrData( Integer const& size, Integer const& inc  = 0)
00240     {
00241       // check for reference
00242       if (this->isRef())
00243       { throw std::runtime_error("In IArrayBase::mallocPtrData(first)"
00244                                  " can't operate on reference.");
00245       }
00246       // delete any memory allocated
00247       freePtrData();
00248       // check size
00249       if (size <= 0)
00250       {
00251         // set initial values
00252         setRangeData(Range(0,size-1));
00253         // first index is 0
00254         return;
00255       }
00256       // allocate memory
00257       try
00258       {
00259         setPtrData(new DATA[size]);
00260       }
00261       catch (std::bad_alloc & error)  // if an alloc error occur
00262       {
00263         // initialize to default
00264         setDefault();
00265         // and throw an exception
00266         throw std::runtime_error("IArrayBase::mallocPtrData(size, inc) "
00267                                  "memory allocation failed.");
00268       }
00269       // set initial values
00270       setRangeData(Range(0,size-1));  // first index is 0
00271       // apply increment
00272       decPtrData(inc);
00273     }
00274 
00287     void reallocPtrData( Integer const& size, Integer const& inc  = 0)
00288     {
00289       // check for reference
00290       if (this->isRef())
00291       { throw std::runtime_error("In IArrayBase::reallocPtrData(first)"
00292                                  " can't operate on reference.");
00293       }
00294       // if there is no memory allocated, we use mallocPtrData
00295       if (!p_data_)
00296       {
00297         mallocPtrData(size, inc);
00298         return;
00299       }
00300       // if the new size is empty we can safely remove existing data
00301       if (size <= 0)
00302       {
00303         freePtrData();
00304         return;
00305       }
00306       // reset to zero increment and get data adress
00307       incPtrData(firstData());
00308       DATA* p_data = p_data_;
00309       // allocate memory
00310       try
00311       {
00312         setPtrData(new DATA[size]);
00313       }
00314       catch (std::bad_alloc & error)  // if an alloc error occur
00315       {
00316         // delete existing data
00317         delete [] p_data;
00318         // initialize members to default
00319         setDefault();
00320         // and throw an exception
00321         throw std::runtime_error("IArrayBase::reallocPtrData(size, inc) "
00322                                  "memory allocation failed.");
00323       }
00324       // copy existing data
00325       Integer nbData = min(size, sizeData());
00326       for (Integer i=0; i< nbData; i++)
00327       { p_data_[i] = p_data[i];}
00328       // delete previous allocated data
00329       // delete existing data
00330       delete [] p_data;
00331       // set initial values
00332       setRangeData(Range(0,size-1));     // first index is 0
00333       // apply increment
00334       decPtrData(inc);
00335     }
00336 
00338     void freePtrData()
00339     {
00340       // nothing to do for ref
00341       if (this->isRef()) return;
00342       // if there is elts
00343       if (p_data_)
00344       {
00345         incPtrData(firstData());  // translate
00346         delete [] p_data_;   // erase
00347         setPtrData();        // set default values
00348       }
00349     }
00350 
00355     inline void setPtrData( DATA* p_data = 0)
00356     { p_data_ = p_data;}
00357 
00362     inline void setRangeData( Range const& rangeData = Range())
00363     { rangeData_ = rangeData;}
00364 
00365   private:
00370     inline void incPtrData( Integer const& inc)
00371     {
00372       // translate p_data_ only if there exists data
00373       if (this->p_data_) { p_data_ += inc;}
00374       rangeData_.dec(inc);
00375     }
00376 
00381     inline void decPtrData( Integer const& dec)
00382     {
00383       // translate p_data_ only if there exists data
00384       if (this->p_data_) { p_data_  -= dec;}
00385       rangeData_.inc(dec);
00386     }
00387 
00389     inline void setDefault()
00390     {
00391       setPtrData();
00392       setRangeData();
00393     }
00394 
00395   private:
00397     DATA* p_data_;
00399     Range rangeData_;
00400 };
00401 
00402 } // namespace STK
00403 
00404 #endif
00405 // STK_IARRAYBASE_H