// template array class for numerical types // R. Ansari, C.Magneville 03/2000 #include "machdefs.h" #include #include #include #include "pexceptions.h" #include "tarray.h" /*! \class SOPHYA::TArray \ingroup TArray Class for template arrays This class implements arrays of dimensions up to \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS" */ // ------------------------------------------------------- // Methodes de la classe // ------------------------------------------------------- ////////////////////////// Les constructeurs / destructeurs //! Default constructor template TArray::TArray() : BaseArray() , mNDBlock() { } //! Constructor /*! \param ndim : number of dimensions (less or equal to \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS") \param siz[ndim] : size along each dimension \param step : step (same for all dimensions) */ template TArray::TArray(uint_4 ndim, const uint_4 * siz, uint_4 step) : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1)) { string exmsg = "TArray::TArray(uint_4, uint_4 *, uint_4)"; if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) ); } //! Constructor /*! \param nx,ny,nz,nt,nu : sizes along first, second, third, fourth and fifth dimension */ template TArray::TArray(uint_4 nx, uint_4 ny, uint_4 nz, uint_4 nt, uint_4 nu) : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1)) { uint_4 size[BASEARRAY_MAXNDIMS]; size[0] = nx; size[1] = ny; size[2] = nz; size[3] = nt; size[4] = nu; int ndim = 1; if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) && (size[4] > 0) ) ndim = 5; else if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) ) ndim = 4; else if ((size[1] > 0) && (size[2] > 0)) ndim = 3; else if (size[1] > 0) ndim = 2; else ndim = 1; string exmsg = "TArray::TArray(uint_4, uint_4, uint_4)"; if (!UpdateSizes(ndim, size, 1, 0, exmsg)) throw( ParmError(exmsg) ); } //! Constructor /*! \param ndim : number of dimensions \param siz[ndim] : size along each dimension \param db : datas are given by this NDataBlock \param share : if true, data are shared, if false they are copied \param step : step (same for all dimensions) in data block \param offset : offset for first element in data block */ template TArray::TArray(uint_4 ndim, const uint_4 * siz, NDataBlock & db, bool share, uint_4 step, uint_8 offset) : BaseArray() , mNDBlock(db, share) { string exmsg = "TArray::TArray(uint_4, uint_4 *, NDataBlock & ... )"; if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) ); } //! Constructor /*! \param ndim : number of dimensions \param siz[ndim] : size along each dimension \param values : datas are given by this pointer \param share : if true, data are shared, if false they are copied \param step : step (same for all dimensions) in data block \param offset : offset for first element in data block \param br : if not NULL, dats are bridge with other datas \sa NDataBlock */ template TArray::TArray(uint_4 ndim, const uint_4 * siz, T* values, uint_4 step, uint_8 offset, Bridge* br) : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br) { string exmsg = "TArray::TArray(uint_4, uint_4 *, T* ... )"; if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) ); } //! Constructor by copy template TArray::TArray(const TArray& a) : BaseArray() , mNDBlock(a.mNDBlock) { string exmsg = "TArray::TArray(const TArray&)"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Constructor by copy /*! \param share : if true, data are shared, if false they are copied */ template TArray::TArray(const TArray& a, bool share) : BaseArray() , mNDBlock(a.mNDBlock, share) { string exmsg = "TArray::TArray(const TArray&, bool)"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Destructor template TArray::~TArray() { } ////////////////////////// Les methodes de copie/share //! Set array equal to \b a and return *this template TArray& TArray::Set(const TArray& a) { if (this != &a) { CloneOrShare(a); if (mInfo) {delete mInfo; mInfo = NULL;} if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } return(*this); } //! Clone array \b a template void TArray::Clone(const TArray& a) { string exmsg = "TArray::Clone()"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); mNDBlock.Clone(a.mNDBlock); if (mInfo) {delete mInfo; mInfo = NULL;} if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Resize array /*! \param ndim : number of dimensions \param siz[ndim] : size along each dimension \param step : step (same for all dimensions) */ template void TArray::ReSize(uint_4 ndim, uint_4 * siz, uint_4 step) { string exmsg = "TArray::ReSize()"; if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) ); mNDBlock.ReSize(totsize_); } //! Re-allocate space for array /*! \param ndim : number of dimensions \param siz[ndim] : size along each dimension \param step : step (same for all dimensions) \param force : if true re-allocation is forced, if not it occurs only if the required space is greater than the old one. */ template void TArray::Realloc(uint_4 ndim, uint_4 * siz, uint_4 step, bool force) { string exmsg = "TArray::Realloc()"; if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) ); mNDBlock.ReSize(totsize_); } //! Compact dimensions in one or more is equal to 1. template TArray& TArray::CompactAllDimensions() { CompactAllDim(); return(*this); } //! Compact dimensions if the last one is equal to 1. template TArray& TArray::CompactTrailingDimensions() { CompactTrailingDim(); return(*this); } inline double _SqrtRz_(double x) { return sqrt(x); } // Pb avec SGI-CC - $CHECK$ - Reza 04/2000 //! Give value (in \b double) for element at position \b ip.. template double TArray::ValueAtPosition(uint_8 ip) const { #ifdef SO_BOUNDCHECKING if (ip >= totsize_) throw( ParmError("TArray::ValueAtPosition(uint_8 ip) Out-of-bound Error") ); #endif return( (double)(*(mNDBlock.Begin()+Offset(ip))) ); } //! Give value (in \b double) for element at position \b ip.. /*! For complex values, we return the module of the complex number */ double TArray< complex >::ValueAtPosition(uint_8 ip) const { #ifdef SO_BOUNDCHECKING if (ip >= totsize_) throw( ParmError("TArray::ValueAtPosition(uint_8 ip) Out-of-bound Error") ); #endif complex c = *(mNDBlock.Begin()+Offset(ip)); double cr = (double)(c.real()); double ci = (double)(c.imag()); return( _SqrtRz_(cr*cr+ci*ci) ); } //! Give value (in \b double) for element at position \b ip.. /*! For complex values, we return the module of the complex number */ double TArray< complex >::ValueAtPosition(uint_8 ip) const { #ifdef SO_BOUNDCHECKING if (ip >= totsize_) throw( ParmError("TArray::ValueAtPosition(uint_8 ip) Out-of-bound Error") ); #endif complex c = *(mNDBlock.Begin()+Offset(ip)); double cr = (double)(c.real()); double ci = (double)(c.imag()); return( _SqrtRz_(cr*cr+ci*ci) ); } //! Return array with elements packed /*! \param force : if true, pack elements in a new array. If false and array is already packed, return an array that share data with the current one. \return packed array */ template TArray TArray::PackElements(bool force) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::PackElements() - Not Allocated Array ! "); if ( !force && (AvgStep() == 1) ) { TArray ra(*this, true); ra.SetTemp(true); return(ra); } else { TArray ra(ndim_, size_, 1); ra.CopyElt(*this); ra.SetTemp(true); return(ra); } } // SubArrays // $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ? //! Extract a sub-array /*! \param rx,ry,rz,rt,ru : range of extraction along dimensions \sa Range */ template TArray TArray::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::operator () (Range, ...) - Not Allocated Array ! "); uint_4 ndim = 0; uint_4 size[BASEARRAY_MAXNDIMS]; uint_4 step[BASEARRAY_MAXNDIMS]; uint_4 pos[BASEARRAY_MAXNDIMS]; size[0] = rx.Size(); size[1] = ry.Size(); size[2] = rz.Size(); size[3] = rt.Size(); size[4] = ru.Size(); step[0] = rx.Step(); step[1] = ry.Step(); step[2] = rz.Step(); step[3] = rt.Step(); step[4] = ru.Step(); pos[0] = rx.Start(); pos[1] = ry.Start(); pos[2] = rz.Start(); pos[3] = rt.Start(); pos[4] = ru.Start(); ndim = ndim_; TArray ra; UpdateSubArraySizes(ra, ndim, size, pos, step); ra.DataBlock().Share(this->DataBlock()); ra.SetTemp(true); return(ra); } // ...... Operation de calcul sur les tableaux ...... // ------- Attention -------- // Boucles normales prenant en compte les steps .... // Possibilite de // , vectorisation //! Fill TArray with Sequence \b seq /*! \param seq : sequence to fill the array \sa Sequence */ template TArray& TArray::SetSeq(Sequence seq) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SetSeq(Sequence ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); pe = Data(); for(k=0; k>>> Operations avec 2nd membre de type scalaire //! Fill an array with a constant value \b x template TArray& TArray::SetT(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SetT(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::Add(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::Add(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::Sub(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::Sub(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::Mul(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::Mul(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::Div(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::Div(T ) - Not Allocated Array ! "); if (x == (T) 0 ) throw MathExc("TArray::Div(T ) - Divide by zero ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::SubInv(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SubInv(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::DivInv(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::DivInv(T ) - Not Allocated Array ! "); T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k>>> Operations avec 2nd membre de type tableau //! Add two TArrays template TArray& TArray::AddElt(const TArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::AddElt(const TArray& ) - Not Allocated Array ! "); if (!CompareSizes(a)) throw(SzMismatchError("TArray::AddElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; uint_8 j,k,ka; if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 stepa = a.AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0, ka=0; k TArray& TArray::SubElt(const TArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SubElt(const TArray& ) - Not Allocated Array ! "); if (!CompareSizes(a)) throw(SzMismatchError("TArray::SubElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; uint_8 j,k,ka; if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 stepa = a.AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0, ka=0; k TArray& TArray::MulElt(const TArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::MulElt(const TArray& ) - Not Allocated Array ! "); if (!CompareSizes(a)) throw(SzMismatchError("TArray::MulElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; uint_8 j,k,ka; if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 stepa = a.AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0, ka=0; k TArray& TArray::DivElt(const TArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::DivElt(const TArray& ) - Not Allocated Array ! "); if (!CompareSizes(a)) throw(SzMismatchError("TArray::DivElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; uint_8 j,k,ka; if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 stepa = a.AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0, ka=0; k TArray& TArray::CopyElt(const TArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::CopyElt(const TArray& ) - Not Allocated Array ! "); if (!CompareSizes(a)) throw(SzMismatchError("TArray::MultElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; uint_8 j,k,ka; if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 stepa = a.AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0, ka=0; k T TArray::Sum() const { if (NbDimensions() < 1) throw RangeCheckError("TArray::Sum() - Not Allocated Array ! "); T ret=0; const T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k T TArray::Product() const { if (NbDimensions() < 1) throw RangeCheckError("TArray::Product() - Not Allocated Array ! "); T ret=0; const T * pe; uint_8 j,k; if (AvgStep() > 0) { // regularly spaced elements uint_8 step = AvgStep(); uint_8 maxx = totsize_*step; pe = Data(); for(k=0; k string TArray::InfoString() const { string rs = "TArray<" ; rs += typeid(T).name(); rs += "> "; return(rs); } //! Print array /*! \param os : output stream \param maxprt : maximum numer of print \param si : if true, display attached DvList \sa SetMaxPrint */ template void TArray::Print(ostream& os, int_4 maxprt, bool si) const { if (maxprt < 0) maxprt = max_nprt_; uint_4 npr = 0; Show(os, si); if (ndim_ < 1) return; uint_4 k0,k1,k2,k3,k4; for(k4=0; k4 1) cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl; for(k3=0; k3 1) cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl; for(k2=0; k2 1) cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl; for(k1=0; k1 1) && (size_[0] > 10) ) cout << "----- Dimension 2 (Y) K1= " << k1 << endl; for(k0=0; k0 0) os << ", "; os << Elem(k0, k1, k2, k3, k4); npr++; if (npr >= (uint_4) maxprt) { if (npr < totsize_) os << "\n .... " << endl; return; } } os << endl; } } } } os << endl; } //! Clone if \b a is not temporary, share if temporary template void TArray::CloneOrShare(const TArray& a) { string exmsg = "TArray::CloneOrShare()"; if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) ); mNDBlock.CloneOrShare(a.mNDBlock); } //! Share data with a template void TArray::Share(const TArray& a) { string exmsg = "TArray::Share()"; if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) ); mNDBlock.Share(a.mNDBlock); } /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// #ifdef __CXX_PRAGMA_TEMPLATES__ /* #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray */ #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray #pragma define_template TArray< complex > #pragma define_template TArray< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) /* template class TArray; template class TArray; template class TArray; template class TArray; */ template class TArray; template class TArray; template class TArray; template class TArray; template class TArray; template class TArray< complex >; template class TArray< complex >; #endif