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

Last change on this file since 2608 was 2589, checked in by ansari, 21 years ago

Correction petite faute de frappe (bug) trouve par compilateur g++ / Reza 30 Juillet 2004

File size: 45.3 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();
[2587]535 for(k=0; k<maxx; k++) *per++ = *pe++ + x;
[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)
[2587]579 for(k=0; k<maxx; k++) *per++ = *pe++ - x;
[2564]580 else
[2587]581 for(k=0; k<maxx; k++) *per++ = x - *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();
[2587]626 for(k=0; k<maxx; k++) *per++ = *pe++ * x;
[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;
[2589]666 sa_size_t j,k;
[2564]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)
[2587]672 for(k=0; k<maxx; k++) *per++ = *pe++ / x;
[970]673 else
[2587]674 for(k=0; k<maxx; k++) *per++ = x / *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();
[2587]717 for(k=0; k<maxx; k++) *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();
[2587]773 // for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe + *pea ;
774 for(k=0; k<maxx; k++) *per++ = *pe++ + *pea++ ;
[772]775 }
[785]776 else { // Non regular data spacing ...
[2575]777 int_4 ax,axa,axr;
[1156]778 sa_size_t step, stepa;
779 sa_size_t gpas, naxa;
[2575]780 sa_size_t stepr, stgpas;
781 if ( !smo && smora ) { // same mem-org for a,res , different from this
782 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
783 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
784 stgpas = stepa;
785 }
786 else { // same mem-org for all, or same (this,a) OR same(this,res)
787 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
788 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
789 stgpas = step;
790 }
[813]791 for(j=0; j<naxa; j++) {
792 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]793 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]794 per = res.DataBlock().Begin()+res.Offset(axr,j);
795 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe + *pea ;
[785]796 }
797 }
[2575]798 return(res);
[772]799}
800
[2575]801//! Two TArrays element by element subtraction
[970]802/*!
[2575]803Perform element by element subtraction of the source array (this) and the \b a array
804and the store result in \b res (res = *this-a or res=a-(*this)).
805The source and argument arrays (this, a) should have the same sizes.
806If not initially allocated, the output array \b res is automatically
807resized as a packed array with the same sizes as the source (this) array.
808Returns a reference to the output array \b res.
809\param a : Array to be added to the source array.
810\param res : Output array containing the result (res=*this+x).
811\param fginv == true : Invert subtraction argument order (res = a-(*this))
[970]812*/
[2575]813
[772]814template <class T>
[2575]815TArray<T>& TArray<T>::SubElt(const TArray<T>& a, TArray<T>& res, bool fginv) const
[772]816{
[804]817 if (NbDimensions() < 1)
[2575]818 throw RangeCheckError("TArray<T>::SubElt(...) - Not allocated source array ! ");
819 bool smoa;
820 if (!CompareSizes(a, smoa))
821 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,a)")) ;
822 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
823 bool smor;
824 if (!CompareSizes(res, smor))
825 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,res) ")) ;
[785]826
[2575]827 bool smora;
828 a.CompareSizes(res, smora);
829
830 bool smo = smoa && smor; // The three arrays have same memory organisation
831
832 const T * pe;
[785]833 const T * pea;
[2575]834 T * per;
835 sa_size_t j,k;
836 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
837 sa_size_t maxx = totsize_;
[785]838 pe = Data();
839 pea = a.Data();
[2575]840 per = res.Data();
841 if (!fginv)
[2587]842 for(k=0; k<maxx; k++) *per++ = *pe++ - *pea++ ;
[970]843 else
[2587]844 for(k=0; k<maxx; k++) *per++ = *pea++ - *pe++ ;
[772]845 }
[785]846 else { // Non regular data spacing ...
[2575]847 int_4 ax,axa,axr;
[1156]848 sa_size_t step, stepa;
849 sa_size_t gpas, naxa;
[2575]850 sa_size_t stepr, stgpas;
851 if ( !smo && smora ) { // same mem-org for a,res , different from this
852 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
853 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
854 stgpas = stepa;
855 }
856 else { // same mem-org for all, or same (this,a) OR same(this,res)
857 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
858 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
859 stgpas = step;
860 }
[813]861 for(j=0; j<naxa; j++) {
862 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]863 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]864 per = res.DataBlock().Begin()+res.Offset(axr,j);
865 if (!fginv)
866 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe - *pea ;
867 else
868 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pea - *pea ;
[785]869 }
870 }
[2575]871 return(res);
[772]872}
873
[970]874
[2575]875//! Two TArrays element by element multiplication
876/*!
877Perform element by element multiplication of the source array (this) and the \b a array
878and store the result in \b res (res = *this*a). The source and argument arrays (this, a)
879should have the same sizes.
880If not initially allocated, the output array \b res is automatically
881resized as a packed array with the same sizes as the source (this) array.
882Returns a reference to the output array \b res.
883\param a : Array to be added to the source array.
884\param res : Output array containing the result (res=(*this)*a).
885*/
[772]886template <class T>
[2575]887TArray<T>& TArray<T>::MulElt(const TArray<T>& a, TArray<T>& res) const
[772]888{
[804]889 if (NbDimensions() < 1)
[2575]890 throw RangeCheckError("TArray<T>::MulElt(...) - Not allocated source array ! ");
891 bool smoa;
892 if (!CompareSizes(a, smoa))
893 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,a)")) ;
894 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
895 bool smor;
896 if (!CompareSizes(res, smor))
897 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,res) ")) ;
[785]898
[2575]899 bool smora;
900 a.CompareSizes(res, smora);
901
902 bool smo = smoa && smor; // The three arrays have same memory organisation
903
904 const T * pe;
[785]905 const T * pea;
[2575]906 T * per;
907 sa_size_t j,k;
908 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
909 sa_size_t maxx = totsize_;
[785]910 pe = Data();
911 pea = a.Data();
[2575]912 per = res.Data();
[2587]913 for(k=0; k<maxx; k++) *per++ = *pe++ * *pea++ ;
[772]914 }
[785]915 else { // Non regular data spacing ...
[2575]916 int_4 ax,axa,axr;
[1156]917 sa_size_t step, stepa;
918 sa_size_t gpas, naxa;
[2575]919 sa_size_t stepr, stgpas;
920 if ( !smo && smora ) { // same mem-org for a,res , different from this
921 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
922 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
923 stgpas = stepa;
924 }
925 else { // same mem-org for all, or same (this,a) OR same(this,res)
926 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
927 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
928 stgpas = step;
929 }
[813]930 for(j=0; j<naxa; j++) {
[2575]931 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]932 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]933 per = res.DataBlock().Begin()+res.Offset(axr,j);
934 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = (*pe) * (*pea);
[785]935 }
936 }
[2575]937 return(res);
[772]938}
939
[804]940
[2575]941//! Two TArrays element by element division
[970]942/*!
[2575]943Perform element by element division of the source array (this) and the \b a array
944and store the result in \b res (res = *this/a). The source and argument arrays (this, a)
945should have the same sizes.
946If not initially allocated, the output array \b res is automatically
947resized as a packed array with the same sizes as the source (this) array.
948Returns a reference to the output array \b res.
949\param a : Array to be added to the source array.
950\param res : Output array containing the result (res=*this/a).
951\param fginv == true : Inverts the division argument order (res = a/(*this))
952\param divzero == true : Result is set to zero (res(i)=0) if the operation's
953second argument is equal to zero (a(i)/(*this)(i)==0)
[970]954*/
[772]955template <class T>
[2575]956TArray<T>& TArray<T>::DivElt(const TArray<T>& a, TArray<T>& res, bool fginv, bool divzero) const
[772]957{
[804]958 if (NbDimensions() < 1)
[2575]959 throw RangeCheckError("TArray<T>::DivElt(...) - Not allocated source array ! ");
960 bool smoa;
961 if (!CompareSizes(a, smoa))
962 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,a)")) ;
963 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
964 bool smor;
965 if (!CompareSizes(res, smor))
966 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,res) ")) ;
[785]967
[2575]968 bool smora;
969 a.CompareSizes(res, smora);
970
971 bool smo = smoa && smor; // The three arrays have same memory organisation
972
973 const T * pe;
[785]974 const T * pea;
[2575]975 T * per;
976 sa_size_t j,k;
977 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
978 sa_size_t maxx = totsize_;
[785]979 pe = Data();
980 pea = a.Data();
[2575]981 per = res.Data();
[1072]982 if(divzero) {
[2575]983 if (!fginv)
[2587]984 for(k=0; k<maxx; k++)
985 if (*pea==(T)0) *per = (T)0; else *per++ = *pe++ / *pea++ ;
[1072]986 else
[2587]987 for(k=0; k<maxx; k++)
988 if (*pe==(T)0) *per = (T)0; else *per++ = *pea++ / *pe++ ;
[1072]989 }
[2575]990 else {
991 if (!fginv)
[2587]992 for(k=0; k<maxx; k++) *per++ = *pe++ / *pea++ ;
[2575]993 else
[2587]994 for(k=0; k<maxx; k++) *per = *pea++ / *pe++ ;
[2575]995 }
[772]996 }
[785]997 else { // Non regular data spacing ...
[2575]998 int_4 ax,axa,axr;
[1156]999 sa_size_t step, stepa;
1000 sa_size_t gpas, naxa;
[2575]1001 sa_size_t stepr, stgpas;
1002 if ( !smo && smora ) { // same mem-org for a,res , different from this
1003 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
1004 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
1005 stgpas = stepa;
1006 }
1007 else { // same mem-org for all, or same (this,a) OR same(this,res)
1008 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1009 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
1010 stgpas = step;
1011 }
1012 // DBG cout << "DBG-A-DIVELT naxa=" << naxa << " gpas= " << gpas
1013 // << " step=" << step << " stepa=" << stepa << " stepr=" << stepr
1014 // << " ax= " << ax << " axa= " << axa << " axr= " << axr << endl;
[813]1015 for(j=0; j<naxa; j++) {
1016 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1017 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]1018 per = res.DataBlock().Begin()+res.Offset(axr,j);
[1072]1019 if(divzero) {
[2575]1020 if (!fginv)
1021 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1022 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
1023 else
1024 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1025 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
[1072]1026 }
[2575]1027 else {
1028 if (!fginv)
1029 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1030 *per = *pe / *pea ;
1031 else
1032 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1033 *per = *pea / *pe ;
1034 }
[785]1035 }
1036 }
[2575]1037 return(res);
[772]1038}
1039
[2575]1040
[894]1041//! Copy elements of \b a
[804]1042template <class T>
1043TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
1044{
1045 if (NbDimensions() < 1)
1046 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]1047 bool smo;
1048 if (!CompareSizes(a, smo))
[1050]1049 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
[772]1050
[804]1051 T * pe;
1052 const T * pea;
[2575]1053 sa_size_t j,k;
[1099]1054 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[2587]1055 if (IsPacked() && a.IsPacked()) memcpy(Data(), a.Data(), totsize_*sizeof(T)); // Packed arrays
1056 else {
1057 sa_size_t step = AvgStep();
1058 sa_size_t stepa = a.AvgStep();
1059 sa_size_t maxx = totsize_*step;
1060 pe = Data();
1061 pea = a.Data();
1062 for(k=0; k<maxx; k+=step, pe+=step, pea+=stepa ) *pe = *pea ;
1063 }
[804]1064 }
1065 else { // Non regular data spacing ...
[1156]1066 int_4 ax,axa;
1067 sa_size_t step, stepa;
1068 sa_size_t gpas, naxa;
[1099]1069 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]1070 for(j=0; j<naxa; j++) {
1071 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1072 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[2575]1073 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) *pe = *pea;
[804]1074 }
1075 }
1076 return(*this);
1077}
1078
[1081]1079//! Converts and Copy elements of \b a
1080template <class T>
1081TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
1082{
1083 if (NbDimensions() < 1)
1084 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]1085 bool smo;
1086 if (!CompareSizes(a, smo))
[1081]1087 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
[804]1088
[1081]1089 T * pe;
[1156]1090 sa_size_t j,k,ka;
1091 sa_size_t offa;
[1081]1092 // Non regular data spacing ...
[1156]1093 int_4 ax,axa;
1094 sa_size_t step, stepa;
1095 sa_size_t gpas, naxa;
[1099]1096 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[1081]1097 for(j=0; j<naxa; j++) {
1098 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]1099 offa = a.Offset(axa,j);
[2147]1100/*
1101 Appel explicite de l'operateur de conversion
1102 suite a la suggestion de M. Reinecke, Reza 31/7/2002
[1085]1103#if !defined(__GNUG__)
1104 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
1105#else
1106 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
[1081]1107 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
[1085]1108#endif
[2147]1109 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
1110*/
1111 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
1112 pe[k] = a.ValueAtPosition(offa+ka).operator T();
[1081]1113 }
1114 return(*this);
1115}
1116
[2575]1117//! Return the the scalar product of the two arrays (Sum_k[(*this)(k)*a(k)])
1118template <class T>
1119T TArray<T>::ScalarProduct(const TArray<T>& a) const
1120{
1121 if (NbDimensions() < 1)
1122 throw RangeCheckError("TArray<T>::ScalarProduct(...) - Not allocated source array ");
1123 bool smo;
1124 if (!CompareSizes(a, smo))
1125 throw(SzMismatchError("TArray<T>::ScalarProduct(...) SizeMismatch(this,a) ")) ;
[1081]1126
[2575]1127 T res = (T)(0);
1128 const T * pe;
1129 const T * pea;
1130 sa_size_t j,k;
1131 if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements
1132 sa_size_t maxx = totsize_;
1133 pe = Data();
1134 pea = a.Data();
[2587]1135 for(k=0; k<maxx; k++) res += *pe++ * *pea++;
[2575]1136 }
1137 else { // Non regular data spacing ...
1138 int_4 ax,axa;
1139 sa_size_t step, stepa;
1140 sa_size_t gpas, naxa;
1141 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1142 for(j=0; j<naxa; j++) {
1143 pe = mNDBlock.Begin()+Offset(ax,j);
1144 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1145 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) res += (*pe)*(*pea);
1146 }
1147 }
1148 return(res);
1149}
1150
1151
[804]1152// Somme et produit des elements
[2575]1153//! Returns the sum of all array elements
[804]1154template <class T>
1155T TArray<T>::Sum() const
1156{
1157 if (NbDimensions() < 1)
1158 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
1159 T ret=0;
1160 const T * pe;
[1156]1161 sa_size_t j,k;
[804]1162 if (AvgStep() > 0) { // regularly spaced elements
[1156]1163 sa_size_t step = AvgStep();
1164 sa_size_t maxx = totsize_*step;
[804]1165 pe = Data();
1166 for(k=0; k<maxx; k+=step ) ret += pe[k];
1167 }
1168 else { // Non regular data spacing ...
[1156]1169 int_4 ka = MaxSizeKA();
1170 sa_size_t step = Step(ka);
1171 sa_size_t gpas = Size(ka)*step;
1172 sa_size_t naxa = Size()/Size(ka);
[813]1173 for(j=0; j<naxa; j++) {
1174 pe = mNDBlock.Begin()+Offset(ka,j);
[804]1175 for(k=0; k<gpas; k+=step) ret += pe[k] ;
1176 }
1177 }
1178 return ret;
1179}
1180
[2575]1181//! Return the product of all elements
[804]1182template <class T>
1183T TArray<T>::Product() const
1184{
1185 if (NbDimensions() < 1)
1186 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
[1113]1187 T ret=(T)1;
[804]1188 const T * pe;
[1156]1189 sa_size_t j,k;
[804]1190 if (AvgStep() > 0) { // regularly spaced elements
[1156]1191 sa_size_t step = AvgStep();
1192 sa_size_t maxx = totsize_*step;
[804]1193 pe = Data();
1194 for(k=0; k<maxx; k+=step ) ret *= pe[k];
1195 }
1196 else { // Non regular data spacing ...
[1156]1197 int_4 ka = MaxSizeKA();
1198 sa_size_t step = Step(ka);
1199 sa_size_t gpas = Size(ka)*step;
1200 sa_size_t naxa = Size()/Size(ka);
[813]1201 for(j=0; j<naxa; j++) {
1202 pe = mNDBlock.Begin()+Offset(ka,j);
[804]1203 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
1204 }
1205 }
1206 return ret;
1207}
1208
[2575]1209//! Returns the sum of all array elements squared (Sum_k((*this)(k)*(*this)(k)).
[1113]1210template <class T>
1211T TArray<T>::SumX2() const
1212{
1213 if (NbDimensions() < 1)
1214 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
1215 T ret=0;
1216 const T * pe;
[1156]1217 sa_size_t j,k;
[1113]1218 if (AvgStep() > 0) { // regularly spaced elements
[1156]1219 sa_size_t step = AvgStep();
1220 sa_size_t maxx = totsize_*step;
[1113]1221 pe = Data();
1222 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
1223 }
1224 else { // Non regular data spacing ...
[1156]1225 int_4 ka = MaxSizeKA();
1226 sa_size_t step = Step(ka);
1227 sa_size_t gpas = Size(ka)*step;
1228 sa_size_t naxa = Size()/Size(ka);
[1113]1229 for(j=0; j<naxa; j++) {
1230 pe = mNDBlock.Begin()+Offset(ka,j);
1231 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
1232 }
1233 }
1234 return ret;
1235}
[804]1236
[1113]1237//! Return the minimum and the maximum values of the array elements
1238/*!
1239 This method generates an exception (\c MathExc) if called for complex arrays
1240*/
[2338]1241
[1113]1242template <class T>
1243void TArray<T>::MinMax(T& min, T& max) const
1244{
1245 const T * pe;
[1156]1246 sa_size_t j,k;
1247 int_4 ka = MaxSizeKA();
1248 sa_size_t step = Step(ka);
1249 sa_size_t gpas = Size(ka)*step;
1250 sa_size_t naxa = Size()/Size(ka);
[1113]1251 min = (*this)[0];
1252 max = (*this)[0];
1253 for(j=0; j<naxa; j++) {
1254 pe = mNDBlock.Begin()+Offset(ka,j);
1255 for(k=0; k<gpas; k+=step) {
1256 if (pe[k]<min) min = pe[k];
1257 else if (pe[k]>max) max = pe[k];
1258 }
1259 }
1260 return;
1261}
[804]1262
[2338]1263DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
[1113]1264void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
1265{
1266 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1267}
[2338]1268DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
[1113]1269void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
1270{
1271 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1272}
1273
[2338]1274
[772]1275// ----------------------------------------------------
1276// Impression, etc ...
1277// ----------------------------------------------------
1278
[894]1279//! Return a string that contain the type \b T of the array
[772]1280template <class T>
[813]1281string TArray<T>::InfoString() const
[772]1282{
[813]1283 string rs = "TArray<" ;
1284 rs += typeid(T).name();
1285 rs += "> ";
[787]1286 return(rs);
[772]1287}
1288
[894]1289//! Print array
1290/*!
1291 \param os : output stream
1292 \param maxprt : maximum numer of print
1293 \param si : if true, display attached DvList
[1550]1294 \param ascd : if true, suppresses the display of line numbers,
1295 suitable for ascii dump format.
[894]1296 \sa SetMaxPrint
[1550]1297 \sa WriteASCII
[894]1298 */
[772]1299template <class T>
[1550]1300void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
[772]1301{
1302 if (maxprt < 0) maxprt = max_nprt_;
[1156]1303 sa_size_t npr = 0;
[772]1304 Show(os, si);
[850]1305 if (ndim_ < 1) return;
[1156]1306 sa_size_t k0,k1,k2,k3,k4;
[772]1307 for(k4=0; k4<size_[4]; k4++) {
[1550]1308 if ((size_[4] > 1) && ascd)
1309 cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
[772]1310 for(k3=0; k3<size_[3]; k3++) {
[1550]1311 if ((size_[3] > 1) && ascd)
1312 cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
[772]1313 for(k2=0; k2<size_[2]; k2++) {
[1550]1314 if ((size_[2] > 1) & ascd)
1315 cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
[772]1316 for(k1=0; k1<size_[1]; k1++) {
[1550]1317 if ( (size_[1] > 1) && (size_[0] > 10) && ascd)
1318 cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
[772]1319 for(k0=0; k0<size_[0]; k0++) {
[1550]1320 if(k0 > 0) os << " ";
[785]1321 os << Elem(k0, k1, k2, k3, k4); npr++;
[1156]1322 if (npr >= (sa_size_t) maxprt) {
[772]1323 if (npr < totsize_) os << "\n .... " << endl; return;
1324 }
1325 }
1326 os << endl;
1327 }
1328 }
1329 }
1330 }
[813]1331 os << endl;
[772]1332}
1333
[1517]1334//! Fill the array, decoding the ASCII input stream
1335/*!
1336 \param is : input stream (ASCII)
[1558]1337 \param nr : Number of non empty (or comment) lines in stream (return value)
1338 \param nc : Number of columns (= ntot/nlines) (return value)
[2286]1339 \param clm : Lines starting with clm character are treated as comment lines
1340 \param sep : word separator in lines
[1558]1341 \return Number of decoded elements
[2286]1342*/
[1517]1343template <class T>
[2286]1344sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc,
1345 char clm, const char* sep)
[1517]1346{
[1550]1347 EnumeratedSequence es;
[2286]1348 sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep);
[1558]1349 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1350 if (!IsAllocated()) {
1351 sa_size_t sz[2];
1352 if (arrtype_ == 2) { // C'est un vecteur
1353 sz[0] = sz[1] = 1;
1354 sz[veceli_] = n;
1355 }
1356 else {
1357 sz[RowsKA()] = nr;
1358 sz[ColsKA()] = nc;
1359 }
1360 ReSize(2, sz);
1361 }
1362 SetSeq(es);
1363 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1364 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1365 return(n);
[1517]1366}
[772]1367
[1517]1368//! Writes the array content to the output stream, (in ASCII)
1369/*!
1370 \param os : output stream (ASCII)
[1558]1371 \sa Print
[1517]1372 */
1373template <class T>
1374void TArray<T>::WriteASCII(ostream& os) const
1375{
[1550]1376 Print(os, Size(), false, true);
[1517]1377}
[772]1378
[1517]1379
1380
[772]1381///////////////////////////////////////////////////////////////
1382///////////////////////////////////////////////////////////////
1383#ifdef __CXX_PRAGMA_TEMPLATES__
[804]1384/*
[772]1385#pragma define_template TArray<uint_1>
[804]1386#pragma define_template TArray<int_2>
1387#pragma define_template TArray<uint_4>
1388*/
[772]1389#pragma define_template TArray<uint_2>
[1543]1390#pragma define_template TArray<uint_8>
[772]1391#pragma define_template TArray<int_4>
1392#pragma define_template TArray<int_8>
1393#pragma define_template TArray<r_4>
1394#pragma define_template TArray<r_8>
1395#pragma define_template TArray< complex<r_4> >
1396#pragma define_template TArray< complex<r_8> >
1397#endif
1398
1399#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[804]1400/*
1401template class TArray<uint_1>;
1402template class TArray<int_2>;
1403template class TArray<uint_4>;
1404*/
[772]1405template class TArray<uint_2>;
[1543]1406template class TArray<uint_8>;
[772]1407template class TArray<int_4>;
1408template class TArray<int_8>;
1409template class TArray<r_4>;
1410template class TArray<r_8>;
1411template class TArray< complex<r_4> >;
1412template class TArray< complex<r_8> >;
1413#endif
1414
1415
Note: See TracBrowser for help on using the repository browser.