source: Sophya/trunk/SophyaLib/TArray/tarray.cc@ 2583

Last change on this file since 2583 was 2575, checked in by ansari, 21 years ago

1/ Remplacement des methodes Add/Sub/Mul/DivElt(a) par

Add/Sub/Mul/DivElt(TArray a, TArray res)

2/ Operateurs += -= A+B A-B TArray et TMatrix/TVecteur modifies en consequence
3/ Ajout methode TArray::ScalarProduct()
4/ Methode TArray::SetT renomme en SetCst() SetT garde en alias
5/ Ajout parametre bool fzero (mise a zero) ajoute ds constructeur et

ReSize() de TMatrix et TVecteur.

Reza 29/07/2004

File size: 45.4 KB
RevLine 
[772]1// template array class for numerical types
2// R. Ansari, C.Magneville 03/2000
3
4#include "machdefs.h"
5#include <stdio.h>
6#include <stdlib.h>
[922]7#include <math.h>
[772]8#include "pexceptions.h"
9#include "tarray.h"
10
[926]11/*!
12 \class SOPHYA::TArray
13 \ingroup TArray
[2267]14 Class for template arrays with numerical data types (int, float, complex).
[772]15
[2267]16 This class implements arrays with number of dimensions up to
[926]17 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS"
[2267]18
19 Standard arithmetic operations on numerical arrays are implemented,
20 as well as sub-array manipulation services.
21 \b Array is a typedef for double precision floating point arrays ( TArray<r_8> )
22 \sa SOPHYA::Range
23 \sa SOPHYA::Sequence
24 \sa SOPHYA::MathArray
25
26 \code
27 #include "array.h"
28 // ...
29 // Creating and initialising a 1-D array of integers
30 TArray<int> ia(5);
31 EnumeratedSequence es;
32 es = 24, 35, 46, 57, 68;
33 ia = es;
34 cout << "Array<int> ia = " << ia;
35 // 2-D array of floats
36 TArray<r_4> b(6,4), c(6,4);
37 // Initializing b with a constant
38 b = 2.71828;
39 // Filling c with random numbers
40 c = RandomSequence();
41 // Arithmetic operations
42 TArray<r_4> d = b+0.3f*c;
43 cout << "Array<float> d = " << d;
44 \endcode
45
[926]46*/
[772]47
[1389]48/*! \ingroup TArray
49 \typedef sa_size_t
50 \brief Array index range and size, defined to be a 4-byte or 8-byte integer
51*/
52
[772]53// -------------------------------------------------------
54// Methodes de la classe
55// -------------------------------------------------------
56
[894]57////////////////////////// Les constructeurs / destructeurs
58
59//! Default constructor
[772]60template <class T>
61TArray<T>::TArray()
[804]62 : BaseArray() , mNDBlock()
[772]63{
64}
65
[894]66//! Constructor
67/*!
68 \param ndim : number of dimensions (less or equal to
69 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS")
70 \param siz[ndim] : size along each dimension
71 \param step : step (same for all dimensions)
[2564]72 \param fzero : if \b true , set array elements to zero
[894]73 */
[772]74template <class T>
[2564]75TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, sa_size_t step, bool fzero)
76 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), fzero)
[772]77{
[1156]78 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, sa_size_t)";
[772]79 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
80}
81
[894]82//! Constructor
83/*!
84 \param nx,ny,nz,nt,nu : sizes along first, second, third, fourth and fifth dimension
[2564]85 \param fzero : if \b true , set array elements to zero
[894]86 */
[772]87template <class T>
[2564]88TArray<T>::TArray(sa_size_t nx, sa_size_t ny, sa_size_t nz, sa_size_t nt, sa_size_t nu, bool fzero)
[804]89 : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1))
[772]90{
[1156]91 sa_size_t size[BASEARRAY_MAXNDIMS];
[772]92 size[0] = nx; size[1] = ny; size[2] = nz;
[804]93 size[3] = nt; size[4] = nu;
[1156]94 int_4 ndim = 1;
[804]95 if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) && (size[4] > 0) ) ndim = 5;
96 else if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) ) ndim = 4;
97 else if ((size[1] > 0) && (size[2] > 0)) ndim = 3;
[772]98 else if (size[1] > 0) ndim = 2;
99 else ndim = 1;
[1156]100 string exmsg = "TArray<T>::TArray(sa_size_t, sa_size_t, sa_size_t, sa_size_t, sa_size_t)";
[772]101 if (!UpdateSizes(ndim, size, 1, 0, exmsg)) throw( ParmError(exmsg) );
102}
103
[894]104//! Constructor
105/*!
106 \param ndim : number of dimensions
107 \param siz[ndim] : size along each dimension
108 \param db : datas are given by this NDataBlock
109 \param share : if true, data are shared, if false they are copied
110 \param step : step (same for all dimensions) in data block
111 \param offset : offset for first element in data block
112 */
[772]113template <class T>
[1156]114TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, NDataBlock<T> & db, bool share, sa_size_t step, sa_size_t offset)
[804]115 : BaseArray() , mNDBlock(db, share)
[772]116{
[1156]117 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, NDataBlock<T> & ... )";
[772]118 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
[1636]119 if (mNDBlock.Size() < ComputeTotalSize(ndim, siz, step, offset)) {
120 exmsg += " DataBlock.Size() < ComputeTotalSize(...) " ;
121 throw( ParmError(exmsg) );
122 }
[772]123}
124
[894]125//! Constructor
126/*!
127 \param ndim : number of dimensions
128 \param siz[ndim] : size along each dimension
129 \param values : datas are given by this pointer
130 \param share : if true, data are shared, if false they are copied
131 \param step : step (same for all dimensions) in data block
132 \param offset : offset for first element in data block
133 \param br : if not NULL, dats are bridge with other datas
134 \sa NDataBlock
135 */
[772]136template <class T>
[1156]137TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, T* values, sa_size_t step, sa_size_t offset, Bridge* br)
[804]138 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br)
[772]139{
[1156]140 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, T* ... )";
[772]141 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
142}
143
[894]144//! Constructor by copy
[976]145/*!
146 \warning datas are \b SHARED with \b a.
147 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
148 */
[772]149template <class T>
150TArray<T>::TArray(const TArray<T>& a)
[804]151 : BaseArray() , mNDBlock(a.mNDBlock)
[772]152{
153 string exmsg = "TArray<T>::TArray(const TArray<T>&)";
154 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
155 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
156}
157
[894]158//! Constructor by copy
159/*!
160 \param share : if true, data are shared, if false they are copied
161 */
[772]162template <class T>
163TArray<T>::TArray(const TArray<T>& a, bool share)
[804]164 : BaseArray() , mNDBlock(a.mNDBlock, share)
[772]165{
[1517]166 if (a.NbDimensions() == 0) return;
[772]167 string exmsg = "TArray<T>::TArray(const TArray<T>&, bool)";
168 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
169 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
170}
171
[1081]172//! Constructor with size and contents copied (after conversion) from a different type TArray
173template <class T>
174TArray<T>::TArray(const BaseArray& a)
175 : BaseArray() , mNDBlock()
176{
[1517]177 if (a.NbDimensions() == 0) return;
[1081]178 string exmsg = "TArray<T>::TArray(const BaseArray&)";
179 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
180 mNDBlock.ReSize(totsize_);
181 // if (a.mInfo) mInfo = new DVList(*(a.mInfo)); - pb protected !
182 ConvertAndCopyElt(a);
183}
184
[894]185//! Destructor
[772]186template <class T>
187TArray<T>::~TArray()
188{
189}
190
[894]191////////////////////////// Les methodes de copie/share
192
193//! Set array equal to \b a and return *this
[976]194/*!
[1364]195 If the array is already allocated, CopyElt() is called
196 for checking that the two arrays have the same size and
197 for copying the array element values. For non allocated
198 arrays, CloneOrShare() is called. The array memory
199 organization is also copied from \b a.
[976]200 \warning Datas are copied (cloned) from \b a.
[1364]201 \sa CopyElt
202 \sa CloneOrShare
[976]203 \sa NDataBlock::operator=(const NDataBlock<T>&)
204*/
[772]205template <class T>
[804]206TArray<T>& TArray<T>::Set(const TArray<T>& a)
[772]207{
[970]208 if (this == &a) return(*this);
209 if (a.NbDimensions() < 1)
210 throw RangeCheckError("TArray<T>::Set(a ) - Array a not allocated ! ");
211 if (NbDimensions() < 1) CloneOrShare(a);
212 else CopyElt(a);
[772]213 return(*this);
214}
215
[1081]216//! Set array elements equal to the \b a array elements, after conversion
217template <class T>
218TArray<T>& TArray<T>::SetBA(const BaseArray& a)
219{
220 if (this == &a) return(*this);
221 if (a.NbDimensions() < 1)
222 throw RangeCheckError("TArray<T>::SetBA(a ) - Array a not allocated ! ");
223 if (NbDimensions() < 1) {
224 string exmsg = "TArray<T>::SetBA(const BaseArray& a)";
225 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
226 mNDBlock.ReSize(totsize_);
227 }
228 ConvertAndCopyElt(a);
229 return(*this);
230}
231
[894]232//! Clone array \b a
[772]233template <class T>
234void TArray<T>::Clone(const TArray<T>& a)
235{
236 string exmsg = "TArray<T>::Clone()";
237 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
238 mNDBlock.Clone(a.mNDBlock);
[894]239 if (mInfo) {delete mInfo; mInfo = NULL;}
[772]240 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
241}
242
[970]243//! Clone if \b a is not temporary, share if temporary
[976]244/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
[970]245template <class T>
246void TArray<T>::CloneOrShare(const TArray<T>& a)
247{
248 string exmsg = "TArray<T>::CloneOrShare()";
[1103]249 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
[970]250 mNDBlock.CloneOrShare(a.mNDBlock);
[1103]251 if (mInfo) {delete mInfo; mInfo = NULL;}
252 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
[970]253}
254
255//! Share data with a
256template <class T>
257void TArray<T>::Share(const TArray<T>& a)
258{
259 string exmsg = "TArray<T>::Share()";
[1103]260 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
[970]261 mNDBlock.Share(a.mNDBlock);
[1103]262 if (mInfo) {delete mInfo; mInfo = NULL;}
263 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
[970]264}
265
266
[1393]267//! Sets or changes the array size
[894]268/*!
269 \param ndim : number of dimensions
270 \param siz[ndim] : size along each dimension
271 \param step : step (same for all dimensions)
[2564]272 \param fzero : if \b true , set array elements to zero
[894]273 */
[772]274template <class T>
[2564]275void TArray<T>::ReSize(int_4 ndim, sa_size_t * siz, sa_size_t step, bool fzero)
[772]276{
[1099]277 if (arrtype_ != 0) {
278 if (ndim != 2)
279 throw( ParmError("TArray<T>::ReSize(ndim!=2,...) for Matrix" ) );
280 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
281 throw( ParmError("TArray<T>::ReSize(,siz[0]>1 && size[1]>1) for Vector" ) );
282 }
[1393]283 string exmsg = "TArray<T>::ReSize(int_4 ...)";
[772]284 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
[2564]285 mNDBlock.ReSize(totsize_, fzero);
[772]286}
287
[1393]288//! Sets or changes the array size.
289/*!
290 The array size and memory layout are copied from the array \b a.
291 \param a : Array used as template for setting the size and memory layout.
[2564]292 \param pack : if \b true , create a packed array, else same memory layout as \b a.
293 \param fzero : if \b true , set array elements to zero
[1393]294 */
295template <class T>
[2564]296void TArray<T>::ReSize(const BaseArray& a, bool pack, bool fzero)
[1393]297{
298 if (arrtype_ != 0) {
299 if (a.NbDimensions() != 2)
300 throw( ParmError("TArray<T>::ReSize(a.NbDimensions()!=2,...) for Matrix" ) );
301 if ((arrtype_ == 2) && (a.Size(0) > 1) && (a.Size(1) > 1))
302 throw( ParmError("TArray<T>::ReSize(a.Size(0)>1 && a.Size(1)>1) for Vector" ) );
303 }
304 string exmsg = "TArray<T>::ReSize(const TArray<T>&)";
[2564]305 if (pack) {
306 sa_size_t siz[BASEARRAY_MAXNDIMS];
[2569]307 int ksz;
308 for(ksz=0; ksz<a.NbDimensions(); ksz++) siz[ksz] = a.Size(ksz);
309 for(ksz=a.NbDimensions(); ksz<BASEARRAY_MAXNDIMS; ksz++) siz[ksz] = 1;
[2564]310 if (!UpdateSizes(a.NbDimensions(), siz, 1, 0, exmsg)) throw( ParmError(exmsg) );
[2569]311 SetMemoryMapping(a.GetMemoryMapping());
[2564]312 mNDBlock.ReSize(totsize_, fzero);
313 }
314 else {
315 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
316 mNDBlock.ReSize(totsize_);
317 }
[1393]318}
319
[894]320//! Re-allocate space for array
321/*!
322 \param ndim : number of dimensions
323 \param siz[ndim] : size along each dimension
324 \param step : step (same for all dimensions)
325 \param force : if true re-allocation is forced, if not it occurs
326 only if the required space is greater than the old one.
327 */
[772]328template <class T>
[1156]329void TArray<T>::Realloc(int_4 ndim, sa_size_t * siz, sa_size_t step, bool force)
[772]330{
[1099]331 if (arrtype_ != 0) {
332 if (ndim != 2)
333 throw( ParmError("TArray<T>::Realloc(ndim!=2,...) for Matrix" ) );
334 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
335 throw( ParmError("TArray<T>::Realloc(,siz[0]>1 && size[1]>1) for Vector" ) );
336 }
[772]337 string exmsg = "TArray<T>::Realloc()";
338 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
[1389]339 mNDBlock.Realloc(totsize_, force);
[772]340}
341
[787]342
[894]343//! Compact dimensions in one or more is equal to 1.
[772]344template <class T>
[787]345TArray<T>& TArray<T>::CompactAllDimensions()
[772]346{
[787]347 CompactAllDim();
348 return(*this);
[772]349}
350
[894]351//! Compact dimensions if the last one is equal to 1.
[785]352template <class T>
[787]353TArray<T>& TArray<T>::CompactTrailingDimensions()
[785]354{
[787]355 CompactTrailingDim();
[785]356 return(*this);
357}
358
[894]359//! Give value (in \b double) for element at position \b ip..
[785]360template <class T>
[1156]361MuTyV & TArray<T>::ValueAtPosition(sa_size_t ip) const
[785]362{
[787]363#ifdef SO_BOUNDCHECKING
[1156]364 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(sa_size_t ip) Out-of-bound Error") );
[787]365#endif
[1081]366 my_mtv = *(mNDBlock.Begin()+Offset(ip));
367 return( my_mtv );
[785]368}
369
[894]370//! Return array with elements packed
371/*!
372 \param force : if true, pack elements in a new array.
373 If false and array is already packed, return
374 an array that share data with the current one.
375 \return packed array
376 */
[804]377template <class T>
378TArray<T> TArray<T>::PackElements(bool force) const
379{
380 if (NbDimensions() < 1)
381 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
382 if ( !force && (AvgStep() == 1) ) {
[970]383 TArray<T> ra;
384 ra.Share(*this);
[804]385 ra.SetTemp(true);
386 return(ra);
387 }
388 else {
389 TArray<T> ra(ndim_, size_, 1);
390 ra.CopyElt(*this);
391 ra.SetTemp(true);
392 return(ra);
393 }
394}
395
[785]396// SubArrays
[804]397// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
[894]398//! Extract a sub-array
399/*!
400 \param rx,ry,rz,rt,ru : range of extraction along dimensions
401 \sa Range
402 */
[785]403template <class T>
[804]404TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
[785]405{
[804]406 if (NbDimensions() < 1)
407 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
[1156]408 int_4 ndim = 0;
409 sa_size_t size[BASEARRAY_MAXNDIMS];
410 sa_size_t step[BASEARRAY_MAXNDIMS];
411 sa_size_t pos[BASEARRAY_MAXNDIMS];
[785]412 size[0] = rx.Size();
413 size[1] = ry.Size();
414 size[2] = rz.Size();
415 size[3] = rt.Size();
416 size[4] = ru.Size();
417
418 step[0] = rx.Step();
419 step[1] = ry.Step();
420 step[2] = rz.Step();
421 step[3] = rt.Step();
422 step[4] = ru.Step();
423
424 pos[0] = rx.Start();
425 pos[1] = ry.Start();
426 pos[2] = rz.Start();
427 pos[3] = rt.Start();
428 pos[4] = ru.Start();
429
430 ndim = ndim_;
431 TArray<T> ra;
[804]432 UpdateSubArraySizes(ra, ndim, size, pos, step);
[787]433 ra.DataBlock().Share(this->DataBlock());
[785]434 ra.SetTemp(true);
435 return(ra);
436}
437
[772]438// ...... Operation de calcul sur les tableaux ......
439// ------- Attention --------
440// Boucles normales prenant en compte les steps ....
[894]441// Possibilite de // , vectorisation
442
443//! Fill TArray with Sequence \b seq
444/*!
445 \param seq : sequence to fill the array
446 \sa Sequence
447 */
[772]448template <class T>
[1103]449TArray<T>& TArray<T>::SetSeq(Sequence const & seq)
[772]450{
[804]451 if (NbDimensions() < 1)
[813]452 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
[1103]453
[785]454 T * pe;
[1156]455 sa_size_t j,k;
456 int_4 ka;
[1103]457 if (arrtype_ == 0) ka = 0;
458 else ka = macoli_;
[1156]459 sa_size_t step = Step(ka);
460 sa_size_t gpas = Size(ka);
461 sa_size_t naxa = Size()/Size(ka);
[1103]462 for(j=0; j<naxa; j++) {
463 pe = mNDBlock.Begin()+Offset(ka,j);
[2153]464/*
465 Appel explicite de l'operateur de conversion
466 suite a la suggestion de M. Reinecke, Reza 31/7/2002
[1103]467#if !defined(__GNUG__)
468 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
469#else
470 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
471 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k);
472#endif
[2153]473 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
474*/
475 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k).operator T();
[785]476 }
[772]477 return(*this);
478}
479
480// >>>> Operations avec 2nd membre de type scalaire
481
[894]482//! Fill an array with a constant value \b x
[772]483template <class T>
[2575]484TArray<T>& TArray<T>::SetCst(T x)
[772]485{
[804]486 if (NbDimensions() < 1)
[2575]487 throw RangeCheckError("TArray<T>::SetCst(T ) - Not Allocated Array ! ");
[785]488 T * pe;
[1156]489 sa_size_t j,k;
[785]490 if (AvgStep() > 0) { // regularly spaced elements
[1156]491 sa_size_t step = AvgStep();
492 sa_size_t maxx = totsize_*step;
[785]493 pe = Data();
494 for(k=0; k<maxx; k+=step ) pe[k] = x;
495 }
496 else { // Non regular data spacing ...
[1156]497 int_4 ka = MaxSizeKA();
498 sa_size_t step = Step(ka);
499 sa_size_t gpas = Size(ka)*step;
500 sa_size_t naxa = Size()/Size(ka);
[813]501 for(j=0; j<naxa; j++) {
502 pe = mNDBlock.Begin()+Offset(ka,j);
[785]503 for(k=0; k<gpas; k+=step) pe[k] = x;
504 }
505 }
[772]506 return(*this);
507}
508
[2564]509//! Add a constant value \b x to the source array and store the result in \b res.
510/*!
511Add a constant to the source array \b this and store the result in \b res (res = *this+x).
512If not initially allocated, the output array \b res is automatically
513resized as a packed array with the same sizes as the source (this) array.
514Returns a reference to the output array \b res.
515\param x : constant to add to the array elements
516\param res : Output array containing the result (res=this+x).
517*/
[772]518template <class T>
[2564]519TArray<T>& TArray<T>::AddCst(T x, TArray<T>& res) const
[772]520{
[804]521 if (NbDimensions() < 1)
[2564]522 throw RangeCheckError("TArray<T>::AddCst(T,res) - Not allocated source array ");
523 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
524 bool smo;
525 if (!CompareSizes(res, smo))
526 throw(SzMismatchError("TArray<T>::AddCst(T, res) SizeMismatch(this,res) ")) ;
527
528 const T * pe;
529 T * per;
[2575]530 sa_size_t j,k;
[2564]531 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
532 sa_size_t maxx = totsize_;
[785]533 pe = Data();
[2564]534 per = res.Data();
535 for(k=0; k<maxx; k++) { *per = (*pe)+x; per++; pe++; }
[785]536 }
537 else { // Non regular data spacing ...
[2564]538 int_4 ax,axr;
539 sa_size_t step, stepr;
[2575]540 sa_size_t gpas, naxa;
541 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
542 for(j=0; j<naxa; j++) {
[2564]543 pe = mNDBlock.Begin()+Offset(ax,j);
544 per = res.DataBlock().Begin()+res.Offset(axr,j);
[2575]545 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe+x;
[785]546 }
547 }
[2564]548 return(res);
[772]549}
550
[2564]551//! Subtract a constant value \b x from the source array and store the result in \b res.
[970]552/*!
[2564]553Subtract a constant from the source array \b this and store the result in \b res (res = *this-x).
554If not initially allocated, the output array \b res is automatically
555resized as a packed array with the same sizes as the source (this) array.
556Returns a reference to the output array \b res.
557\param x : constant to subtract from the array elements
558\param res : Output array containing the result (res=this+x or res=x-this).
[2575]559\param fginv == true : Invert subtraction argument order (res = x-(*this))
[970]560*/
[772]561template <class T>
[2564]562TArray<T>& TArray<T>::SubCst(T x, TArray<T>& res, bool fginv) const
[772]563{
[804]564 if (NbDimensions() < 1)
[2564]565 throw RangeCheckError("TArray<T>::SubCst(T,res) - Not allocated source array ");
566 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
567 bool smo;
568 if (!CompareSizes(res, smo))
569 throw(SzMismatchError("TArray<T>::SubCst(T, res) SizeMismatch(this,res) ")) ;
570
571 const T * pe;
572 T * per;
[2575]573 sa_size_t j,k;
[2564]574 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
575 sa_size_t maxx = totsize_;
[785]576 pe = Data();
[2564]577 per = res.Data();
578 if (!fginv)
579 for(k=0; k<maxx; k++) { *per = (*pe)-x; per++; pe++; }
580 else
581 for(k=0; k<maxx; k++) { *per = x-(*pe); per++; pe++; }
[785]582 }
583 else { // Non regular data spacing ...
[2564]584 int_4 ax,axr;
585 sa_size_t step, stepr;
[2575]586 sa_size_t gpas, naxa;
587 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
588 for(j=0; j<naxa; j++) {
[2564]589 pe = mNDBlock.Begin()+Offset(ax,j);
590 per = res.DataBlock().Begin()+res.Offset(axr,j);
591 if (!fginv)
[2575]592 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe-x;
593 else
594 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x-*pe;
[785]595 }
596 }
[2564]597 return(res);
[772]598}
599
[2564]600//! Multiply the source array by a constant value \b x and store the result in \b res.
601/*!
602Multiply the source array \b this by a constant \b x and store the result in \b res (res = *this*x).
603If not initially allocated, the output array \b res is automatically
604resized as a packed array with the same sizes as the source (this) array.
605Returns a reference to the output array \b res.
606\param x : Array elements are multiplied by x
607\param res : Output array containing the result (res=this*x).
608*/
[772]609template <class T>
[2564]610TArray<T>& TArray<T>::MulCst(T x, TArray<T>& res) const
[772]611{
[804]612 if (NbDimensions() < 1)
[2564]613 throw RangeCheckError("TArray<T>::MulCst(T,res) - Not allocated source array ");
614 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
615 bool smo;
616 if (!CompareSizes(res, smo))
617 throw(SzMismatchError("TArray<T>::MulCst(T, res) SizeMismatch(this,res) ")) ;
618
619 const T * pe;
620 T * per;
[2575]621 sa_size_t j,k;
[2564]622 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
623 sa_size_t maxx = totsize_;
[785]624 pe = Data();
[2564]625 per = res.Data();
626 for(k=0; k<maxx; k++) { *per = (*pe)*x; per++; pe++; }
[785]627 }
628 else { // Non regular data spacing ...
[2564]629 int_4 ax,axr;
630 sa_size_t step, stepr;
[2575]631 sa_size_t gpas, naxa;
632 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
633 for(j=0; j<naxa; j++) {
[2564]634 pe = mNDBlock.Begin()+Offset(ax,j);
635 per = res.DataBlock().Begin()+res.Offset(axr,j);
[2575]636 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)*x;
[785]637 }
638 }
[2564]639 return(res);
[772]640}
641
[2564]642//! Divide the source array by a constant value \b x and store the result in \b res.
[970]643/*!
[2564]644Divide the source array \b this by a constant \b x and store the result in \b res (res = *this/x).
645If not initially allocated, the output array \b res is automatically
646resized as a packed array with the same sizes as the source (this) array.
647Returns a reference to the output array \b res.
648\param x : Array elements are divied by x
649\param res : Output array containing the result (res=(*this)/x or res=x/(*this)).
[2575]650\param fginv == true : Invert the division argument order (res = x/(*this))
[970]651*/
[772]652template <class T>
[2564]653TArray<T>& TArray<T>::DivCst(T x, TArray<T>& res, bool fginv) const
[772]654{
[804]655 if (NbDimensions() < 1)
[2564]656 throw RangeCheckError("TArray<T>::DivCst(T,res) - Not allocated source array ! ");
[970]657 if (!fginv && (x == (T) 0) )
[2564]658 throw MathExc("TArray<T>::DivCst(T,res) - Divide by zero ! ");
659 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
660 bool smo;
661 if (!CompareSizes(res, smo))
662 throw(SzMismatchError("TArray<T>::DivCst(T, res) SizeMismatch(this,res) ")) ;
663
664 const T * pe;
665 T * per;
666 sa_size_t j,k,kr;
667 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
668 sa_size_t maxx = totsize_;
[785]669 pe = Data();
[2564]670 per = res.Data();
671 if (!fginv)
672 for(k=0; k<maxx; k++) { *per = (*pe)/x; per++; pe++; }
[970]673 else
[2564]674 for(k=0; k<maxx; k++) { *per = x/(*pe); per++; pe++; }
[785]675 }
676 else { // Non regular data spacing ...
[2564]677 int_4 ax,axr;
678 sa_size_t step, stepr;
[2575]679 sa_size_t gpas, naxa;
680 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
681 for(j=0; j<naxa; j++) {
[2564]682 pe = mNDBlock.Begin()+Offset(ax,j);
683 per = res.DataBlock().Begin()+res.Offset(axr,j);
684 if (!fginv)
[2575]685 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)/x;
686 else
687 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x/(*pe);
[785]688 }
689 }
[2564]690 return(res);
[772]691}
692
693
[2564]694//! Stores the opposite of the source array in \b res (res=-(*this)).
695/*!
696If not initially allocated, the output array \b res is automatically
697resized as a packed array with the same sizes as the source (this) array.
698Returns a reference to the output array \b res.
699*/
[1156]700template <class T>
[2564]701TArray<T>& TArray<T>::NegateElt(TArray<T>& res) const
[1156]702{
703 if (NbDimensions() < 1)
[2564]704 throw RangeCheckError("TArray<T>::NegateElt(res) - Not allocated source array ");
705 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
706 bool smo;
707 if (!CompareSizes(res, smo))
708 throw(SzMismatchError("TArray<T>::NegateElt(res) SizeMismatch(this,res) ")) ;
709
710 const T * pe;
711 T * per;
[2575]712 sa_size_t j,k;
[2564]713 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
714 sa_size_t maxx = totsize_;
[1156]715 pe = Data();
[2564]716 per = res.Data();
717 for(k=0; k<maxx; k++) { *per = -(*pe); per++; pe++; }
[1156]718 }
719 else { // Non regular data spacing ...
[2564]720 int_4 ax,axr;
721 sa_size_t step, stepr;
[2575]722 sa_size_t gpas, naxa;
723 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
724 for(j=0; j<naxa; j++) {
[2564]725 pe = mNDBlock.Begin()+Offset(ax,j);
726 per = res.DataBlock().Begin()+res.Offset(axr,j);
[2575]727 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = -(*pe);
[1156]728 }
729 }
[2564]730 return(res);
[1156]731}
[804]732
[772]733// >>>> Operations avec 2nd membre de type tableau
[2575]734
735//! Two TArrays element by element addition
736/*!
737Perform element by element addition of the source array (this) and the \b a array
738and store the result in \b res (res = *this+a). The source and argument arrays (this, a)
739should have the same sizes.
740If not initially allocated, the output array \b res is automatically
741resized as a packed array with the same sizes as the source (this) array.
742Returns a reference to the output array \b res.
743\param a : Array to be added to the source array.
744\param res : Output array containing the result (res=this+a).
745*/
[772]746template <class T>
[2575]747TArray<T>& TArray<T>::AddElt(const TArray<T>& a, TArray<T>& res) const
[772]748{
[804]749 if (NbDimensions() < 1)
[2575]750 throw RangeCheckError("TArray<T>::AddElt(...) - Not allocated source array ! ");
751 bool smoa;
752 if (!CompareSizes(a, smoa))
753 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,a)")) ;
754 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
755 bool smor;
756 if (!CompareSizes(res, smor))
757 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,res) ")) ;
[785]758
[2575]759 bool smora;
760 a.CompareSizes(res, smora);
761
762 bool smo = smoa && smor; // The three arrays have same memory organisation
763
764 const T * pe;
[785]765 const T * pea;
[2575]766 T * per;
767 sa_size_t j,k;
768 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
769 sa_size_t maxx = totsize_;
[785]770 pe = Data();
771 pea = a.Data();
[2575]772 per = res.Data();
773 for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe + *pea ;
[772]774 }
[785]775 else { // Non regular data spacing ...
[2575]776 int_4 ax,axa,axr;
[1156]777 sa_size_t step, stepa;
778 sa_size_t gpas, naxa;
[2575]779 sa_size_t stepr, stgpas;
780 if ( !smo && smora ) { // same mem-org for a,res , different from this
781 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
782 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
783 stgpas = stepa;
784 }
785 else { // same mem-org for all, or same (this,a) OR same(this,res)
786 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
787 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
788 stgpas = step;
789 }
[813]790 for(j=0; j<naxa; j++) {
791 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]792 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]793 per = res.DataBlock().Begin()+res.Offset(axr,j);
794 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe + *pea ;
[785]795 }
796 }
[2575]797 return(res);
[772]798}
799
[2575]800//! Two TArrays element by element subtraction
[970]801/*!
[2575]802Perform element by element subtraction of the source array (this) and the \b a array
803and the store result in \b res (res = *this-a or res=a-(*this)).
804The source and argument arrays (this, a) should have the same sizes.
805If not initially allocated, the output array \b res is automatically
806resized as a packed array with the same sizes as the source (this) array.
807Returns a reference to the output array \b res.
808\param a : Array to be added to the source array.
809\param res : Output array containing the result (res=*this+x).
810\param fginv == true : Invert subtraction argument order (res = a-(*this))
[970]811*/
[2575]812
[772]813template <class T>
[2575]814TArray<T>& TArray<T>::SubElt(const TArray<T>& a, TArray<T>& res, bool fginv) const
[772]815{
[804]816 if (NbDimensions() < 1)
[2575]817 throw RangeCheckError("TArray<T>::SubElt(...) - Not allocated source array ! ");
818 bool smoa;
819 if (!CompareSizes(a, smoa))
820 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,a)")) ;
821 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
822 bool smor;
823 if (!CompareSizes(res, smor))
824 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,res) ")) ;
[785]825
[2575]826 bool smora;
827 a.CompareSizes(res, smora);
828
829 bool smo = smoa && smor; // The three arrays have same memory organisation
830
831 const T * pe;
[785]832 const T * pea;
[2575]833 T * per;
834 sa_size_t j,k;
835 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
836 sa_size_t maxx = totsize_;
[785]837 pe = Data();
838 pea = a.Data();
[2575]839 per = res.Data();
840 if (!fginv)
841 for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe - *pea ;
[970]842 else
[2575]843 for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pea - *pe ;
[772]844 }
[785]845 else { // Non regular data spacing ...
[2575]846 int_4 ax,axa,axr;
[1156]847 sa_size_t step, stepa;
848 sa_size_t gpas, naxa;
[2575]849 sa_size_t stepr, stgpas;
850 if ( !smo && smora ) { // same mem-org for a,res , different from this
851 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
852 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
853 stgpas = stepa;
854 }
855 else { // same mem-org for all, or same (this,a) OR same(this,res)
856 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
857 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
858 stgpas = step;
859 }
[813]860 for(j=0; j<naxa; j++) {
861 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]862 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]863 per = res.DataBlock().Begin()+res.Offset(axr,j);
864 if (!fginv)
865 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe - *pea ;
866 else
867 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pea - *pea ;
[785]868 }
869 }
[2575]870 return(res);
[772]871}
872
[970]873
[2575]874//! Two TArrays element by element multiplication
875/*!
876Perform element by element multiplication of the source array (this) and the \b a array
877and store the result in \b res (res = *this*a). The source and argument arrays (this, a)
878should have the same sizes.
879If not initially allocated, the output array \b res is automatically
880resized as a packed array with the same sizes as the source (this) array.
881Returns a reference to the output array \b res.
882\param a : Array to be added to the source array.
883\param res : Output array containing the result (res=(*this)*a).
884*/
[772]885template <class T>
[2575]886TArray<T>& TArray<T>::MulElt(const TArray<T>& a, TArray<T>& res) const
[772]887{
[804]888 if (NbDimensions() < 1)
[2575]889 throw RangeCheckError("TArray<T>::MulElt(...) - Not allocated source array ! ");
890 bool smoa;
891 if (!CompareSizes(a, smoa))
892 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,a)")) ;
893 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
894 bool smor;
895 if (!CompareSizes(res, smor))
896 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,res) ")) ;
[785]897
[2575]898 bool smora;
899 a.CompareSizes(res, smora);
900
901 bool smo = smoa && smor; // The three arrays have same memory organisation
902
903 const T * pe;
[785]904 const T * pea;
[2575]905 T * per;
906 sa_size_t j,k;
907 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
908 sa_size_t maxx = totsize_;
[785]909 pe = Data();
910 pea = a.Data();
[2575]911 per = res.Data();
912 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = (*pe) * (*pea) ;
[772]913 }
[785]914 else { // Non regular data spacing ...
[2575]915 int_4 ax,axa,axr;
[1156]916 sa_size_t step, stepa;
917 sa_size_t gpas, naxa;
[2575]918 sa_size_t stepr, stgpas;
919 if ( !smo && smora ) { // same mem-org for a,res , different from this
920 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
921 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
922 stgpas = stepa;
923 }
924 else { // same mem-org for all, or same (this,a) OR same(this,res)
925 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
926 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
927 stgpas = step;
928 }
[813]929 for(j=0; j<naxa; j++) {
[2575]930 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]931 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]932 per = res.DataBlock().Begin()+res.Offset(axr,j);
933 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = (*pe) * (*pea);
[785]934 }
935 }
[2575]936 return(res);
[772]937}
938
[804]939
[2575]940//! Two TArrays element by element division
[970]941/*!
[2575]942Perform element by element division of the source array (this) and the \b a array
943and store the result in \b res (res = *this/a). The source and argument arrays (this, a)
944should have the same sizes.
945If not initially allocated, the output array \b res is automatically
946resized as a packed array with the same sizes as the source (this) array.
947Returns a reference to the output array \b res.
948\param a : Array to be added to the source array.
949\param res : Output array containing the result (res=*this/a).
950\param fginv == true : Inverts the division argument order (res = a/(*this))
951\param divzero == true : Result is set to zero (res(i)=0) if the operation's
952second argument is equal to zero (a(i)/(*this)(i)==0)
[970]953*/
[772]954template <class T>
[2575]955TArray<T>& TArray<T>::DivElt(const TArray<T>& a, TArray<T>& res, bool fginv, bool divzero) const
[772]956{
[804]957 if (NbDimensions() < 1)
[2575]958 throw RangeCheckError("TArray<T>::DivElt(...) - Not allocated source array ! ");
959 bool smoa;
960 if (!CompareSizes(a, smoa))
961 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,a)")) ;
962 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
963 bool smor;
964 if (!CompareSizes(res, smor))
965 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,res) ")) ;
[785]966
[2575]967 bool smora;
968 a.CompareSizes(res, smora);
969
970 bool smo = smoa && smor; // The three arrays have same memory organisation
971
972 const T * pe;
[785]973 const T * pea;
[2575]974 T * per;
975 sa_size_t j,k;
976 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
977 sa_size_t maxx = totsize_;
[785]978 pe = Data();
979 pea = a.Data();
[2575]980 per = res.Data();
[1072]981 if(divzero) {
[2575]982 if (!fginv)
983 for(k=0; k<maxx; k++, pe++, pea++, per++ )
984 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
[1072]985 else
[2575]986 for(k=0; k<maxx; k++, pe++, pea++, per++ )
987 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
[1072]988 }
[2575]989 else {
990 if (!fginv)
991 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = *pe / *pea ;
992 else
993 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = *pea / *pe ;
994 }
[772]995 }
[785]996 else { // Non regular data spacing ...
[2575]997 int_4 ax,axa,axr;
[1156]998 sa_size_t step, stepa;
999 sa_size_t gpas, naxa;
[2575]1000 sa_size_t stepr, stgpas;
1001 if ( !smo && smora ) { // same mem-org for a,res , different from this
1002 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
1003 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
1004 stgpas = stepa;
1005 }
1006 else { // same mem-org for all, or same (this,a) OR same(this,res)
1007 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1008 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
1009 stgpas = step;
1010 }
1011 // DBG cout << "DBG-A-DIVELT naxa=" << naxa << " gpas= " << gpas
1012 // << " step=" << step << " stepa=" << stepa << " stepr=" << stepr
1013 // << " ax= " << ax << " axa= " << axa << " axr= " << axr << endl;
[813]1014 for(j=0; j<naxa; j++) {
1015 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1016 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]1017 per = res.DataBlock().Begin()+res.Offset(axr,j);
[1072]1018 if(divzero) {
[2575]1019 if (!fginv)
1020 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1021 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
1022 else
1023 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1024 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
[1072]1025 }
[2575]1026 else {
1027 if (!fginv)
1028 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1029 *per = *pe / *pea ;
1030 else
1031 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1032 *per = *pea / *pe ;
1033 }
[785]1034 }
1035 }
[2575]1036 return(res);
[772]1037}
1038
[2575]1039
[894]1040//! Copy elements of \b a
[804]1041template <class T>
1042TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
1043{
1044 if (NbDimensions() < 1)
1045 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]1046 bool smo;
1047 if (!CompareSizes(a, smo))
[1050]1048 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
[772]1049
[804]1050 T * pe;
1051 const T * pea;
[2575]1052 sa_size_t j,k;
[1099]1053 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[1156]1054 sa_size_t step = AvgStep();
1055 sa_size_t stepa = a.AvgStep();
1056 sa_size_t maxx = totsize_*step;
[804]1057 pe = Data();
1058 pea = a.Data();
[2575]1059 for(k=0; k<maxx; k+=step, pe+=step, pea+=stepa ) *pe = *pea ;
[804]1060 }
1061 else { // Non regular data spacing ...
[1156]1062 int_4 ax,axa;
1063 sa_size_t step, stepa;
1064 sa_size_t gpas, naxa;
[1099]1065 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]1066 for(j=0; j<naxa; j++) {
1067 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1068 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]1069 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) *pe = *pea;
[804]1070 }
1071 }
1072 return(*this);
1073}
1074
[1081]1075//! Converts and Copy elements of \b a
1076template <class T>
1077TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
1078{
1079 if (NbDimensions() < 1)
1080 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]1081 bool smo;
1082 if (!CompareSizes(a, smo))
[1081]1083 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
[804]1084
[1081]1085 T * pe;
[1156]1086 sa_size_t j,k,ka;
1087 sa_size_t offa;
[1081]1088 // Non regular data spacing ...
[1156]1089 int_4 ax,axa;
1090 sa_size_t step, stepa;
1091 sa_size_t gpas, naxa;
[1099]1092 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[1081]1093 for(j=0; j<naxa; j++) {
1094 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1095 offa = a.Offset(axa,j);
[2147]1096/*
1097 Appel explicite de l'operateur de conversion
1098 suite a la suggestion de M. Reinecke, Reza 31/7/2002
[1085]1099#if !defined(__GNUG__)
1100 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
1101#else
1102 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
[1081]1103 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
[1085]1104#endif
[2147]1105 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
1106*/
1107 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
1108 pe[k] = a.ValueAtPosition(offa+ka).operator T();
[1081]1109 }
1110 return(*this);
1111}
1112
[2575]1113//! Return the the scalar product of the two arrays (Sum_k[(*this)(k)*a(k)])
1114template <class T>
1115T TArray<T>::ScalarProduct(const TArray<T>& a) const
1116{
1117 if (NbDimensions() < 1)
1118 throw RangeCheckError("TArray<T>::ScalarProduct(...) - Not allocated source array ");
1119 bool smo;
1120 if (!CompareSizes(a, smo))
1121 throw(SzMismatchError("TArray<T>::ScalarProduct(...) SizeMismatch(this,a) ")) ;
[1081]1122
[2575]1123 T res = (T)(0);
1124 const T * pe;
1125 const T * pea;
1126 sa_size_t j,k;
1127 if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements
1128 sa_size_t maxx = totsize_;
1129 pe = Data();
1130 pea = a.Data();
1131 for(k=0; k<maxx; k++, pe++, pea++) res += (*pe)*(*pea);
1132 }
1133 else { // Non regular data spacing ...
1134 int_4 ax,axa;
1135 sa_size_t step, stepa;
1136 sa_size_t gpas, naxa;
1137 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1138 for(j=0; j<naxa; j++) {
1139 pe = mNDBlock.Begin()+Offset(ax,j);
1140 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1141 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) res += (*pe)*(*pea);
1142 }
1143 }
1144 return(res);
1145}
1146
1147
[804]1148// Somme et produit des elements
[2575]1149//! Returns the sum of all array elements
[804]1150template <class T>
1151T TArray<T>::Sum() const
1152{
1153 if (NbDimensions() < 1)
1154 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
1155 T ret=0;
1156 const T * pe;
[1156]1157 sa_size_t j,k;
[804]1158 if (AvgStep() > 0) { // regularly spaced elements
[1156]1159 sa_size_t step = AvgStep();
1160 sa_size_t maxx = totsize_*step;
[804]1161 pe = Data();
1162 for(k=0; k<maxx; k+=step ) ret += pe[k];
1163 }
1164 else { // Non regular data spacing ...
[1156]1165 int_4 ka = MaxSizeKA();
1166 sa_size_t step = Step(ka);
1167 sa_size_t gpas = Size(ka)*step;
1168 sa_size_t naxa = Size()/Size(ka);
[813]1169 for(j=0; j<naxa; j++) {
1170 pe = mNDBlock.Begin()+Offset(ka,j);
[804]1171 for(k=0; k<gpas; k+=step) ret += pe[k] ;
1172 }
1173 }
1174 return ret;
1175}
1176
[2575]1177//! Return the product of all elements
[804]1178template <class T>
1179T TArray<T>::Product() const
1180{
1181 if (NbDimensions() < 1)
1182 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
[1113]1183 T ret=(T)1;
[804]1184 const T * pe;
[1156]1185 sa_size_t j,k;
[804]1186 if (AvgStep() > 0) { // regularly spaced elements
[1156]1187 sa_size_t step = AvgStep();
1188 sa_size_t maxx = totsize_*step;
[804]1189 pe = Data();
1190 for(k=0; k<maxx; k+=step ) ret *= pe[k];
1191 }
1192 else { // Non regular data spacing ...
[1156]1193 int_4 ka = MaxSizeKA();
1194 sa_size_t step = Step(ka);
1195 sa_size_t gpas = Size(ka)*step;
1196 sa_size_t naxa = Size()/Size(ka);
[813]1197 for(j=0; j<naxa; j++) {
1198 pe = mNDBlock.Begin()+Offset(ka,j);
[804]1199 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
1200 }
1201 }
1202 return ret;
1203}
1204
[2575]1205//! Returns the sum of all array elements squared (Sum_k((*this)(k)*(*this)(k)).
[1113]1206template <class T>
1207T TArray<T>::SumX2() const
1208{
1209 if (NbDimensions() < 1)
1210 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
1211 T ret=0;
1212 const T * pe;
[1156]1213 sa_size_t j,k;
[1113]1214 if (AvgStep() > 0) { // regularly spaced elements
[1156]1215 sa_size_t step = AvgStep();
1216 sa_size_t maxx = totsize_*step;
[1113]1217 pe = Data();
1218 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
1219 }
1220 else { // Non regular data spacing ...
[1156]1221 int_4 ka = MaxSizeKA();
1222 sa_size_t step = Step(ka);
1223 sa_size_t gpas = Size(ka)*step;
1224 sa_size_t naxa = Size()/Size(ka);
[1113]1225 for(j=0; j<naxa; j++) {
1226 pe = mNDBlock.Begin()+Offset(ka,j);
1227 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
1228 }
1229 }
1230 return ret;
1231}
[804]1232
[1113]1233//! Return the minimum and the maximum values of the array elements
1234/*!
1235 This method generates an exception (\c MathExc) if called for complex arrays
1236*/
[2338]1237
[1113]1238template <class T>
1239void TArray<T>::MinMax(T& min, T& max) const
1240{
1241 const T * pe;
[1156]1242 sa_size_t j,k;
1243 int_4 ka = MaxSizeKA();
1244 sa_size_t step = Step(ka);
1245 sa_size_t gpas = Size(ka)*step;
1246 sa_size_t naxa = Size()/Size(ka);
[1113]1247 min = (*this)[0];
1248 max = (*this)[0];
1249 for(j=0; j<naxa; j++) {
1250 pe = mNDBlock.Begin()+Offset(ka,j);
1251 for(k=0; k<gpas; k+=step) {
1252 if (pe[k]<min) min = pe[k];
1253 else if (pe[k]>max) max = pe[k];
1254 }
1255 }
1256 return;
1257}
[804]1258
[2338]1259DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
[1113]1260void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
1261{
1262 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1263}
[2338]1264DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
[1113]1265void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
1266{
1267 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1268}
1269
[2338]1270
[772]1271// ----------------------------------------------------
1272// Impression, etc ...
1273// ----------------------------------------------------
1274
[894]1275//! Return a string that contain the type \b T of the array
[772]1276template <class T>
[813]1277string TArray<T>::InfoString() const
[772]1278{
[813]1279 string rs = "TArray<" ;
1280 rs += typeid(T).name();
1281 rs += "> ";
[787]1282 return(rs);
[772]1283}
1284
[894]1285//! Print array
1286/*!
1287 \param os : output stream
1288 \param maxprt : maximum numer of print
1289 \param si : if true, display attached DvList
[1550]1290 \param ascd : if true, suppresses the display of line numbers,
1291 suitable for ascii dump format.
[894]1292 \sa SetMaxPrint
[1550]1293 \sa WriteASCII
[894]1294 */
[772]1295template <class T>
[1550]1296void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
[772]1297{
1298 if (maxprt < 0) maxprt = max_nprt_;
[1156]1299 sa_size_t npr = 0;
[772]1300 Show(os, si);
[850]1301 if (ndim_ < 1) return;
[1156]1302 sa_size_t k0,k1,k2,k3,k4;
[772]1303 for(k4=0; k4<size_[4]; k4++) {
[1550]1304 if ((size_[4] > 1) && ascd)
1305 cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
[772]1306 for(k3=0; k3<size_[3]; k3++) {
[1550]1307 if ((size_[3] > 1) && ascd)
1308 cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
[772]1309 for(k2=0; k2<size_[2]; k2++) {
[1550]1310 if ((size_[2] > 1) & ascd)
1311 cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
[772]1312 for(k1=0; k1<size_[1]; k1++) {
[1550]1313 if ( (size_[1] > 1) && (size_[0] > 10) && ascd)
1314 cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
[772]1315 for(k0=0; k0<size_[0]; k0++) {
[1550]1316 if(k0 > 0) os << " ";
[785]1317 os << Elem(k0, k1, k2, k3, k4); npr++;
[1156]1318 if (npr >= (sa_size_t) maxprt) {
[772]1319 if (npr < totsize_) os << "\n .... " << endl; return;
1320 }
1321 }
1322 os << endl;
1323 }
1324 }
1325 }
1326 }
[813]1327 os << endl;
[772]1328}
1329
[1517]1330//! Fill the array, decoding the ASCII input stream
1331/*!
1332 \param is : input stream (ASCII)
[1558]1333 \param nr : Number of non empty (or comment) lines in stream (return value)
1334 \param nc : Number of columns (= ntot/nlines) (return value)
[2286]1335 \param clm : Lines starting with clm character are treated as comment lines
1336 \param sep : word separator in lines
[1558]1337 \return Number of decoded elements
[2286]1338*/
[1517]1339template <class T>
[2286]1340sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc,
1341 char clm, const char* sep)
[1517]1342{
[1550]1343 EnumeratedSequence es;
[2286]1344 sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep);
[1558]1345 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1346 if (!IsAllocated()) {
1347 sa_size_t sz[2];
1348 if (arrtype_ == 2) { // C'est un vecteur
1349 sz[0] = sz[1] = 1;
1350 sz[veceli_] = n;
1351 }
1352 else {
1353 sz[RowsKA()] = nr;
1354 sz[ColsKA()] = nc;
1355 }
1356 ReSize(2, sz);
1357 }
1358 SetSeq(es);
1359 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1360 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1361 return(n);
[1517]1362}
[772]1363
[1517]1364//! Writes the array content to the output stream, (in ASCII)
1365/*!
1366 \param os : output stream (ASCII)
[1558]1367 \sa Print
[1517]1368 */
1369template <class T>
1370void TArray<T>::WriteASCII(ostream& os) const
1371{
[1550]1372 Print(os, Size(), false, true);
[1517]1373}
[772]1374
[1517]1375
1376
[772]1377///////////////////////////////////////////////////////////////
1378///////////////////////////////////////////////////////////////
1379#ifdef __CXX_PRAGMA_TEMPLATES__
[804]1380/*
[772]1381#pragma define_template TArray<uint_1>
[804]1382#pragma define_template TArray<int_2>
1383#pragma define_template TArray<uint_4>
1384*/
[772]1385#pragma define_template TArray<uint_2>
[1543]1386#pragma define_template TArray<uint_8>
[772]1387#pragma define_template TArray<int_4>
1388#pragma define_template TArray<int_8>
1389#pragma define_template TArray<r_4>
1390#pragma define_template TArray<r_8>
1391#pragma define_template TArray< complex<r_4> >
1392#pragma define_template TArray< complex<r_8> >
1393#endif
1394
1395#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[804]1396/*
1397template class TArray<uint_1>;
1398template class TArray<int_2>;
1399template class TArray<uint_4>;
1400*/
[772]1401template class TArray<uint_2>;
[1543]1402template class TArray<uint_8>;
[772]1403template class TArray<int_4>;
1404template class TArray<int_8>;
1405template class TArray<r_4>;
1406template class TArray<r_8>;
1407template class TArray< complex<r_4> >;
1408template class TArray< complex<r_8> >;
1409#endif
1410
1411
Note: See TracBrowser for help on using the repository browser.