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

Last change on this file since 2884 was 2884, checked in by ansari, 20 years ago

Modifs pour compilation avec g++ 4 (V >= 3.4) - Reza 4 Jan 2006

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