// template array class for numerical types // R. Ansari, C.Magneville 03/2000 #include "machdefs.h" #include #include #include #include #include #include "pexceptions.h" #define TARRAY_CC_BFILE // avoid extern template declarations #include "tarray.h" namespace SOPHYA { /*! \class TArray \ingroup TArray Class for template arrays with numerical data types (int, float, complex). This class handles arrays with number of dimensions up to \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS" (=5). The class has a performant memory management system, including reference sharing for the array data. (copy constructor and sub-arrays (or slices)). An important feature of this class is the transparent handling of sub-arrays, or slices. Arbitrary sub-arrays or slices can be defined, provided regular spacing along each array axe (or dimension). The second example below illustrate the use of this possibility. Standard arithmetic operations, sum or product as well as application of usual math functions (Sin, Cos ...) on numerical arrays are implemented. These operations usually provide high performance, despite of the complex memory management pattern. ASCII input/output (or read write) and binary I/O (persistence) in different formats are also provided through helper (or handler) classes. This class is mainly intented for arrays with large number of data elements. (Size() \> 100 .. 1000). Arrays with few data elements (\< 10) have significant memory overhead, due to variables describing array shape and memory organisation. However, a single higher dimensional array can be used to represent a large number of identical size small arrays. For example, TArray tab(2,2, 1000) can be used to hold 1000 2x2 matrices. \warning Notice that array elements along the X axis are contiguous in memory, independent of the array rank (number of dimensions), for packed arrays. \b Array is a typedef for double precision floating point arrays ( TArray ) \sa SOPHYA::Range \sa SOPHYA::Sequence \sa SOPHYA::MathArray \sa SOPHYA::NDataBlock \code #include "array.h" // ... // Creating and initialising a 1-D array of integers TArray ia(5); EnumeratedSequence es; es = 24, 35, 46, 57, 68; ia = es; cout << "Array ia = \n" << ia; // 2-D array of floats TArray b(6,4), c(6,4); // Initializing b with a constant b = 2.71828; // Filling c with random numbers c = RandomSequence(); // Arithmetic operations TArray d = b+0.3f*c; cout << "Array d = \n" << d; \endcode Example for sub-arrays, or slices \code // Creating and initialising a 2-D (6 x 4) array of integers TArray iaa(6, 4); iaa = RegularSequence(1,2); cout << "Array iaa = \n" << iaa; // We extract a sub-array - data is shared with iaa TArray iae = iaa(Range(1, Range::lastIndex(), 3) , Range::all(), Range::first() ); cout << "Array iae=subarray(iaa) = \n" << iae; // Changing iae elements changes corresponding iaa elements iae = 0; cout << "Array iae=0 --> iaa = \n" << iaa; \endcode */ /*! \ingroup TArray \typedef sa_size_t \brief Array index range and size, defined to be a 4-byte or 8-byte integer */ // ------------------------------------------------------- // 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) \param fzero : if \b true , set array elements to zero */ template TArray::TArray(int_4 ndim, const sa_size_t * siz, sa_size_t step, bool fzero) : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), fzero) { string exmsg = "TArray::TArray(int_4, sa_size_t *, sa_size_t)"; 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 \param fzero : if \b true , set array elements to zero */ template TArray::TArray(sa_size_t nx, sa_size_t ny, sa_size_t nz, sa_size_t nt, sa_size_t nu, bool fzero) : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1)) { sa_size_t size[BASEARRAY_MAXNDIMS]; size[0] = nx; size[1] = ny; size[2] = nz; size[3] = nt; size[4] = nu; int_4 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(sa_size_t, sa_size_t, sa_size_t, sa_size_t, sa_size_t)"; 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(int_4 ndim, const sa_size_t * siz, NDataBlock & db, bool share, sa_size_t step, sa_size_t offset) : BaseArray() , mNDBlock(db, share) { string exmsg = "TArray::TArray(int_4, sa_size_t *, NDataBlock & ... )"; if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) ); if (mNDBlock.Size() < (size_t)ComputeTotalSize(ndim, siz, step, offset)) { exmsg += " DataBlock.Size() < ComputeTotalSize(...) " ; 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(int_4 ndim, const sa_size_t * siz, T* values, sa_size_t step, sa_size_t offset, Bridge* br) : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br) { string exmsg = "TArray::TArray(int_4, sa_size_t *, T* ... )"; if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) ); } //! Constructor by copy /*! \warning datas are \b SHARED with \b a. \sa NDataBlock::NDataBlock(const NDataBlock&) */ template TArray::TArray(const TArray& a) : BaseArray() , mNDBlock(a.mNDBlock) { if (a.NbDimensions() == 0) return; // Reza-Nov 2011: we allow copy contrsuctor on non allocated arrays 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) { if (a.NbDimensions() == 0) return; // Reza-Nov 2011: we allow copy contrsuctor on non allocated arrays string exmsg = "TArray::TArray(const TArray&, bool)"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Constructor with size and contents copied (after conversion) from an array with different data type. /*! The array size and memory layout are copied from the array \b a, or a packed array is created if \b pack==true. \param a : original array, to copy sizes and data from \param pack : if \b true , create a packed array, else same memory layout as \b a. */ template TArray::TArray(const BaseArray& a, bool pack) : BaseArray() , mNDBlock() { if (a.NbDimensions() == 0) return; string exmsg = "TArray::TArray(const BaseArray&,bool)"; ReSize(a,pack,false); ConvertAndCopyElt(a); if (a.HasInfoObject()) mInfo = new DVList(*(a.getInfoPointer())); } //! Destructor template TArray::~TArray() { } ////////////////////////// Les methodes de copie/share //! Set array equal to \b a and return *this /*! If the array is already allocated, CopyElt() is called for checking that the two arrays have the same size and for copying the array element values. For non allocated arrays, CloneOrShare() is called. The array memory organization is also copied from \b a. \warning Datas are copied (cloned) from \b a. \sa CopyElt \sa CloneOrShare \sa NDataBlock::operator=(const NDataBlock&) */ template TArray& TArray::Set(const TArray& a) { if (this == &a) return(*this); if (a.NbDimensions() < 1) throw RangeCheckError("TArray::Set(a ) - Array a not allocated ! "); if (NbDimensions() < 1) CloneOrShare(a); else CopyElt(a); return(*this); } //! Set array elements equal to the \b a array elements, after conversion template TArray& TArray::SetBA(const BaseArray& a) { if (this == &a) return(*this); if (a.NbDimensions() < 1) throw RangeCheckError("TArray::SetBA(a ) - Array a not allocated ! "); if (NbDimensions() < 1) { string exmsg = "TArray::SetBA(const BaseArray& a)"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); mNDBlock.ReSize(totsize_); } ConvertAndCopyElt(a); 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)); } //! Clone if \b a is not temporary, share if temporary /*! \sa NDataBlock::CloneOrShare(const NDataBlock&) */ template void TArray::CloneOrShare(const TArray& a) { string exmsg = "TArray::CloneOrShare()"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); mNDBlock.CloneOrShare(a.mNDBlock); if (mInfo) {delete mInfo; mInfo = NULL;} if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Share data with a template void TArray::Share(const TArray& a) { string exmsg = "TArray::Share()"; if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) ); mNDBlock.Share(a.mNDBlock); if (mInfo) {delete mInfo; mInfo = NULL;} if (a.mInfo) mInfo = new DVList(*(a.mInfo)); } //! Sets or changes the array size /*! \param ndim : number of dimensions \param siz[ndim] : size along each dimension \param step : step (same for all dimensions) \param fzero : if \b true , set array elements to zero */ template void TArray::ReSize(int_4 ndim, sa_size_t * siz, sa_size_t step, bool fzero) { if (arrtype_ != 0) { if (ndim != 2) throw( ParmError("TArray::ReSize(ndim!=2,...) for Matrix" ) ); if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1)) throw( ParmError("TArray::ReSize(,siz[0]>1 && size[1]>1) for Vector" ) ); } string exmsg = "TArray::ReSize(int_4 ...)"; if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) ); mNDBlock.ReSize(totsize_, fzero); } //! Sets or changes the array size. /*! The array size and memory layout are copied from the array \b a. \param a : Array used as template for setting the size and memory layout. \param pack : if \b true , create a packed array, else same memory layout as \b a. \param fzero : if \b true , set array elements to zero */ template void TArray::ReSize(const BaseArray& a, bool pack, bool fzero) { if (arrtype_ != 0) { if (a.NbDimensions() != 2) throw( ParmError("TArray::ReSize(a.NbDimensions()!=2,...) for Matrix" ) ); if ((arrtype_ == 2) && (a.Size(0) > 1) && (a.Size(1) > 1)) throw( ParmError("TArray::ReSize(a.Size(0)>1 && a.Size(1)>1) for Vector" ) ); } string exmsg = "TArray::ReSize(const TArray&)"; if (pack) { sa_size_t siz[BASEARRAY_MAXNDIMS]; int ksz; for(ksz=0; ksz void TArray::Realloc(int_4 ndim, sa_size_t * siz, sa_size_t step, bool force) { if (arrtype_ != 0) { if (ndim != 2) throw( ParmError("TArray::Realloc(ndim!=2,...) for Matrix" ) ); if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1)) throw( ParmError("TArray::Realloc(,siz[0]>1 && size[1]>1) for Vector" ) ); } string exmsg = "TArray::Realloc()"; if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) ); mNDBlock.Realloc(totsize_, force); } //! To clear the array sizes - corresponding to an unallocated array. template TArray& TArray::ZeroSize() { if (NbDimensions() == 0) return (*this); SetZeroSize(); mNDBlock.Dealloc(); return (*this); } /*! \brief Compact arrays - supresses size=1 axes. Changes the array rank (number of dimensions), suppressing all axes with size equal 1. Example: Compacting Rank=NDim=5 Sizes=3x1x6x1x1 =====\> Rank=NDim=2 Sizes=3x6 */ template TArray& TArray::CompactAllDimensions() { CompactAllDim(); return(*this); } /*! \brief Compact array taling dimensions, for size=1 traling axes. Changes the array rank (number of dimensions), suppressing all axes with size equal 1, after the last axe with size \> 1 Example: Compacting Rank=NDim=5 Sizes=3x1x6x1x1 =====\> Rank=NDim=3 Sizes=3x1x6 */ template TArray& TArray::CompactTrailingDimensions() { CompactTrailingDim(); return(*this); } /*! \brief Return the value (as a MuTyV) for element at position \b ip in the array. This method is used for conversion between arrays of different types. \param ip : element position in the array */ template MuTyV & TArray::ValueAtPosition(sa_size_t ip) const { #ifdef SO_BOUNDCHECKING if ( (ip >= totsize_) || (ip < 0) ) throw( ParmError("TArray::ValueAtPosition(sa_size_t ip) Out-of-bound Error") ); #endif my_mtv = *(mNDBlock.Begin()+Offset(ip)); return( my_mtv ); } /*! \brief Return the value (as a MuTyV) for element at position \b ip in the datablock. This method is used for conversion between arrays of different types. \param ip : element position in the array DataBlock, regardless of the array memory organisation */ template MuTyV & TArray::ValueAtPositionDB(sa_size_t ip) const { #ifdef SO_BOUNDCHECKING if ( (ip >= mNDBlock.Size() ) || (ip < 0) ) throw( ParmError("TArray::ValueAtPositionDB(sa_size_t ip) Out-of-bound Error") ); #endif my_mtv = *(mNDBlock.Begin()+ip); return( my_mtv ); } /*! \brief Return a new array with elements packed in memory \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; ra.Share(*this); return(ra); } else { TArray ra(ndim_, size_, 1); ra.CopyElt(*this); 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 \param compact : if \b compact == true, compact trailing dimensions (suppressed if =1) (See CompactTrailingDimensions() ) \sa SOPHYA::Range */ template TArray TArray::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru, bool compact) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::operator () (Range, ...) - Not Allocated Array ! "); int_4 ndim = 0; // Updating Range objects using actual array size rx.Update(SizeX()); ry.Update(SizeY()); rz.Update(SizeZ()); if (NbDimensions() > 3) rt.Update(Size(3)); else rt.Update(0); if (NbDimensions() > 4) ru.Update(Size(4)); else ru.Update(0); sa_size_t size[BASEARRAY_MAXNDIMS]; sa_size_t step[BASEARRAY_MAXNDIMS]; sa_size_t 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()); if (compact) ra.CompactTrailingDim(); 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 const & seq) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SetSeq(Sequence ) - Not Allocated Array ! "); T * pe; sa_size_t j,k; int_4 ka; if (arrtype_ == 0) ka = 0; else ka = macoli_; sa_size_t step = Step(ka); sa_size_t gpas = Size(ka); sa_size_t naxa = Size()/Size(ka); for(j=0; j>>> Operations avec 2nd membre de type scalaire //! Fill an array with a constant value \b x template TArray& TArray::SetCst(T x) { if (NbDimensions() < 1) throw RangeCheckError("TArray::SetCst(T ) - Not Allocated Array ! "); T * pe; sa_size_t j,k; if (AvgStep() > 0) { // regularly spaced elements sa_size_t step = AvgStep(); sa_size_t maxx = totsize_*step; pe = Data(); for(k=0; k TArray& TArray::AddCst(T x, TArray& res) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::AddCst(T,res) - Not allocated source array "); if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else res.SetSize(*this, true, false); } bool smo; if (!CompareSizes(res, smo)) throw(SzMismatchError("TArray::AddCst(T, res) SizeMismatch(this,res) ")) ; const T * pe; T * per; sa_size_t j,k; if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); per = res.Data(); for(k=0; k TArray& TArray::SubCst(T x, TArray& res, bool fginv) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::SubCst(T,res) - Not allocated source array "); if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else res.SetSize(*this, true, false); } bool smo; if (!CompareSizes(res, smo)) throw(SzMismatchError("TArray::SubCst(T, res) SizeMismatch(this,res) ")) ; const T * pe; T * per; sa_size_t j,k; if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); per = res.Data(); if (!fginv) for(k=0; k TArray& TArray::MulCst(T x, TArray& res) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::MulCst(T,res) - Not allocated source array "); if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else res.SetSize(*this, true, false); } bool smo; if (!CompareSizes(res, smo)) throw(SzMismatchError("TArray::MulCst(T, res) SizeMismatch(this,res) ")) ; const T * pe; T * per; sa_size_t j,k; if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); per = res.Data(); for(k=0; k TArray& TArray::DivCst(T x, TArray& res, bool fginv) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::DivCst(T,res) - Not allocated source array ! "); if (!fginv && (x == (T) 0) ) throw MathExc("TArray::DivCst(T,res) - Divide by zero ! "); if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else res.SetSize(*this, true, false); } bool smo; if (!CompareSizes(res, smo)) throw(SzMismatchError("TArray::DivCst(T, res) SizeMismatch(this,res) ")) ; const T * pe; T * per; sa_size_t j,k; if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); per = res.Data(); if (!fginv) for(k=0; k TArray& TArray::NegateElt(TArray& res) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::NegateElt(res) - Not allocated source array "); if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else res.SetSize(*this, true, false); } bool smo; if (!CompareSizes(res, smo)) throw(SzMismatchError("TArray::NegateElt(res) SizeMismatch(this,res) ")) ; const T * pe; T * per; sa_size_t j,k; if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); per = res.Data(); for(k=0; k>>> Operations avec 2nd membre de type tableau //! Two TArrays element by element addition /*! Perform element by element addition of the source array (this) and the \b a array and store the result in \b res (res = *this+a). The source and argument arrays (this, a) should have the same sizes. If not initially allocated, and if none of the source arrays is flagged as temporary, the output array \b res is automatically resized as a packed array with the same sizes as the source (this) array. If \b res is not allocated and one of the source array is temporary, data is shared between \b res and the temporary source array. Returns a reference to the output array \b res. \param a : Array to be added to the source array. \param res : Output array containing the result (res=this+a). */ template TArray& TArray::AddElt(const TArray& a, TArray& res) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::AddElt(...) - Not allocated source array ! "); bool smoa; if (!CompareSizes(a, smoa)) throw(SzMismatchError("TArray::AddElt(...) SizeMismatch(this,a)")) ; if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else if ( a.IsTemp() ) res.Share(a); else res.SetSize(*this, true, false); } bool smor; if (!CompareSizes(res, smor)) throw(SzMismatchError("TArray::AddElt(...) SizeMismatch(this,res) ")) ; bool smora; a.CompareSizes(res, smora); bool smo = smoa && smor; // The three arrays have same memory organisation const T * pe; const T * pea; T * per; sa_size_t j,k; if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays sa_size_t maxx = totsize_; pe = Data(); pea = a.Data(); per = res.Data(); // for(k=0; k TArray& TArray::SubElt(const TArray& a, TArray& res, bool fginv) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::SubElt(...) - Not allocated source array ! "); bool smoa; if (!CompareSizes(a, smoa)) throw(SzMismatchError("TArray::SubElt(...) SizeMismatch(this,a)")) ; if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else if ( a.IsTemp() ) res.Share(a); else res.SetSize(*this, true, false); } bool smor; if (!CompareSizes(res, smor)) throw(SzMismatchError("TArray::SubElt(...) SizeMismatch(this,res) ")) ; bool smora; a.CompareSizes(res, smora); bool smo = smoa && smor; // The three arrays have same memory organisation const T * pe; const T * pea; T * per; sa_size_t j,k; if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays sa_size_t maxx = totsize_; pe = Data(); pea = a.Data(); per = res.Data(); if (!fginv) for(k=0; k TArray& TArray::MulElt(const TArray& a, TArray& res) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::MulElt(...) - Not allocated source array ! "); bool smoa; if (!CompareSizes(a, smoa)) throw(SzMismatchError("TArray::MulElt(...) SizeMismatch(this,a)")) ; if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else if ( a.IsTemp() ) res.Share(a); else res.SetSize(*this, true, false); } bool smor; if (!CompareSizes(res, smor)) throw(SzMismatchError("TArray::MulElt(...) SizeMismatch(this,res) ")) ; bool smora; a.CompareSizes(res, smora); bool smo = smoa && smor; // The three arrays have same memory organisation const T * pe; const T * pea; T * per; sa_size_t j,k; if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays sa_size_t maxx = totsize_; pe = Data(); pea = a.Data(); per = res.Data(); for(k=0; k TArray& TArray::DivElt(const TArray& a, TArray& res, bool fginv, bool divzero) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::DivElt(...) - Not allocated source array ! "); bool smoa; if (!CompareSizes(a, smoa)) throw(SzMismatchError("TArray::DivElt(...) SizeMismatch(this,a)")) ; if (res.NbDimensions() < 1) { if ( IsTemp() ) res.Share(*this); else if ( a.IsTemp() ) res.Share(a); else res.SetSize(*this, true, false); } bool smor; if (!CompareSizes(res, smor)) throw(SzMismatchError("TArray::DivElt(...) SizeMismatch(this,res) ")) ; bool smora; a.CompareSizes(res, smora); bool smo = smoa && smor; // The three arrays have same memory organisation const T * pe; const T * pea; T * per; sa_size_t j,k; if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays sa_size_t maxx = totsize_; pe = Data(); pea = a.Data(); per = res.Data(); if(divzero) { if (!fginv) for(k=0; k::CopyElt(const TArray& ) - Not Allocated Array ! "); bool smo; if (!CompareSizes(a, smo)) throw(SzMismatchError("TArray::CopyElt(const TArray&) SizeMismatch")) ; T * pe; const T * pea; sa_size_t j,k; if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements if (IsPacked() && a.IsPacked()) memcpy(Data(), a.Data(), totsize_*sizeof(T)); // Packed arrays else { sa_size_t step = AvgStep(); sa_size_t stepa = a.AvgStep(); sa_size_t maxx = totsize_*step; pe = Data(); pea = a.Data(); for(k=0; k TArray& TArray::ConvertAndCopyElt(const BaseArray& a) { if (NbDimensions() < 1) throw RangeCheckError("TArray::ConvertAndCopyElt(const TArray& ) - Not Allocated Array ! "); bool smo; if (!CompareSizes(a, smo)) throw(SzMismatchError("TArray::ConvertAndCopyElt(const TArray&) SizeMismatch")) ; T * pe; sa_size_t j,k,ka; sa_size_t offa; // Non regular data spacing ... int_4 ax,axa; sa_size_t step, stepa; sa_size_t gpas, naxa; GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa); for(j=0; j T TArray::ScalarProduct(const TArray& a) const { if (NbDimensions() < 1) throw RangeCheckError("TArray::ScalarProduct(...) - Not allocated source array "); bool smo; if (!CompareSizes(a, smo)) throw(SzMismatchError("TArray::ScalarProduct(...) SizeMismatch(this,a) ")) ; T res = (T)(0); const T * pe; const T * pea; sa_size_t j,k; if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements sa_size_t maxx = totsize_; pe = Data(); pea = a.Data(); for(k=0; k T TArray::Sum() const { if (NbDimensions() < 1) throw RangeCheckError("TArray::Sum() - Not Allocated Array ! "); T ret=0; const T * pe; sa_size_t j,k; if (AvgStep() > 0) { // regularly spaced elements sa_size_t step = AvgStep(); sa_size_t 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=(T)1; const T * pe; sa_size_t j,k; if (AvgStep() > 0) { // regularly spaced elements sa_size_t step = AvgStep(); sa_size_t maxx = totsize_*step; pe = Data(); for(k=0; k T TArray::SumSq() const { if (NbDimensions() < 1) throw RangeCheckError("TArray::SumSq() - Not Allocated Array ! "); T ret=0; const T * pe; sa_size_t j,k; if (AvgStep() > 0) { // regularly spaced elements sa_size_t step = AvgStep(); sa_size_t maxx = totsize_*step; pe = Data(); for(k=0; k T TArray::Norm2() const { return SumSq(); } // Fonction auxiliaire pour specialisation de la methode Norm2() pour tableaux complexes template complex _ComputeComplexNorm_Private_(TArray< complex > const & ca) { if (ca.NbDimensions() < 1) throw RangeCheckError("TArray< complex >::Norm2() - Not Allocated Array ! "); complex ret= complex(0., 0.); const complex * pe; sa_size_t j,k; if (ca.AvgStep() > 0) { // regularly spaced elements sa_size_t step = ca.AvgStep(); sa_size_t maxx = ca.Size()*step; pe = ca.Data(); for(k=0; k , pour SGI-CC en particulier */ complex TArray< complex >::Norm2() const { return _ComputeComplexNorm_Private_(*this); } DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ complex TArray< complex >::Norm2() const { return _ComputeComplexNorm_Private_(*this); } //------------------- //! Return the minimum and the maximum values of the array elements /*! This method generates an exception (\c MathExc) if called for complex arrays */ template void TArray::MinMax(T& min, T& max) const { const T * pe; sa_size_t j,k; int_4 ka = MaxSizeKA(); sa_size_t step = Step(ka); sa_size_t gpas = Size(ka)*step; sa_size_t naxa = Size()/Size(ka); min = (*this)[0]; max = (*this)[0]; for(j=0; jmax) max = pe[k]; } } return; } DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ void TArray< complex >::MinMax(complex& min, complex& max) const { throw MathExc("TArray< complex >::MinMax(...) - No order in complex"); } DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ void TArray< complex >::MinMax(complex& min, complex& max) const { throw MathExc("TArray< complex >::MinMax(...) - No order in complex"); } #ifdef SO_LDBLE128 DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ void TArray< complex >::MinMax(complex& min, complex& max) const { throw MathExc("TArray< complex >::MinMax(...) - No order in complex"); } #endif // ---------------------------------------------------- // Impression, etc ... // ---------------------------------------------------- //! Return a string that contain the type \b T of the array template string TArray::InfoString() const { string rs = "TArray<" ; rs += typeid(T).name(); rs += "> "; return(rs); } //! Print array /*! \param os : output stream \param maxprt : maximum number of elements printed \param si : if true, display attached DvList \param ascd : if true, suppresses the display of line numbers, suitable for ascii dump format. \sa SetMaxPrint \sa WriteASCII */ template void TArray::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const { if (maxprt < 0) maxprt = max_nprt_; sa_size_t npr = 0; // keep stream's io flags // ios_base::fmtflags ioflg = os.flags(); compile pas sur OSF-cxx // os << right ; compile pas sur OSF-cxx Show(os, si); if (ndim_ < 1) return; // Calcul de la largeur d'impression pour chaque element int fprtw = os.precision()+7; int prtw = 5; if ( (typeid(T) == typeid( int_4 )) || (typeid(T) == typeid( uint_4 )) ) prtw = 8; else if ( (typeid(T) == typeid( int_8 )) || (typeid(T) == typeid( uint_8 )) ) prtw = 11; else if ( typeid(T) == typeid( r_4 ) ) prtw = fprtw; else if ( typeid(T) == typeid( r_8 ) ) prtw = fprtw; else if ( typeid(T) == typeid(complex) ) prtw = fprtw; else if ( typeid(T) == typeid(complex) ) prtw = fprtw; sa_size_t k0,k1,k2,k3,k4; for(k4=0; k4 1) && !ascd) os << "\n ----- Dimension 5 (U) K4= " << k4 << endl; for(k3=0; k3 1) && !ascd) os << "\n ----- Dimension 4 (T) K3= " << k3 << endl; for(k2=0; k2 1) && !ascd) os << "\n ----- Dimension 3 (Z) K2= " << k2 << endl; for(k1=0; k1 1) && (size_[0] > 10) && !ascd) os << "----- Dimension 2 (Y) K1= " << k1 << endl; for(k0=0; k0 0) os << " "; os << setw(prtw) << Elem(k0, k1, k2, k3, k4); npr++; if (npr >= (sa_size_t) maxprt) { if (npr < totsize_) os << "\n .... " << endl; return; } } os << endl; } } } } os << endl; //compile pas sur OSF-cxx os.flags(ioflg); // reset stream io flags } //! Fill the array, decoding the ASCII input stream /*! \param is : input stream (ASCII) \param nr : Number of non empty (or comment) lines in stream (return value) \param nc : Number of columns (= ntot/nlines) (return value) \param clm : Lines starting with clm character are treated as comment lines \param sep : word separator in lines \return Number of decoded elements */ template sa_size_t TArray::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc, char clm, const char* sep) { EnumeratedSequence es; sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep); if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n); if (!IsAllocated()) { sa_size_t sz[2]; if (arrtype_ == 2) { // C'est un vecteur sz[0] = sz[1] = 1; sz[veceli_] = n; } else { sz[RowsKA()] = nr; sz[ColsKA()] = nc; } ReSize(2, sz); } SetSeq(es); if (BaseArray::GetPrintLevel()>0) cout << "TArray::ReadASCII()/Info: " << n << " elements read from stream " << " (Row,Col= " << nr << "," << nc << ")" << endl; return(n); } //! Writes the array content to the output stream, (in ASCII) /*! \param os : output stream (ASCII) \sa Print */ template void TArray::WriteASCII(ostream& os) const { Print(os, Size(), false, true); } /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// #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 #pragma define_template TArray< complex > #pragma define_template TArray< complex > #ifdef SO_LDBLE128 #pragma define_template TArray #pragma define_template TArray< complex > #endif #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; template class TArray< complex >; template class TArray< complex >; #ifdef SO_LDBLE128 template class TArray; template class TArray< complex >; #endif #endif } // FIN namespace SOPHYA