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

Last change on this file since 1072 was 1072, checked in by ansari, 25 years ago

protection conditionnelle DivElts par zero cmv 16/7/00

File size: 25.7 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
14 Class for template arrays
[772]15
[926]16 This class implements arrays of dimensions up to
17 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS"
18*/
[772]19
20// -------------------------------------------------------
21// Methodes de la classe
22// -------------------------------------------------------
23
[894]24////////////////////////// Les constructeurs / destructeurs
25
26//! Default constructor
[772]27template <class T>
28TArray<T>::TArray()
[804]29 : BaseArray() , mNDBlock()
[772]30{
31}
32
[894]33//! Constructor
34/*!
35 \param ndim : number of dimensions (less or equal to
36 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS")
37 \param siz[ndim] : size along each dimension
38 \param step : step (same for all dimensions)
39 */
[772]40template <class T>
[804]41TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, uint_4 step)
42 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1))
[772]43{
44 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, uint_4)";
45 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
46}
47
[894]48//! Constructor
49/*!
50 \param nx,ny,nz,nt,nu : sizes along first, second, third, fourth and fifth dimension
51 */
[772]52template <class T>
[804]53TArray<T>::TArray(uint_4 nx, uint_4 ny, uint_4 nz, uint_4 nt, uint_4 nu)
54 : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1))
[772]55{
[787]56 uint_4 size[BASEARRAY_MAXNDIMS];
[772]57 size[0] = nx; size[1] = ny; size[2] = nz;
[804]58 size[3] = nt; size[4] = nu;
[772]59 int ndim = 1;
[804]60 if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) && (size[4] > 0) ) ndim = 5;
61 else if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) ) ndim = 4;
62 else if ((size[1] > 0) && (size[2] > 0)) ndim = 3;
[772]63 else if (size[1] > 0) ndim = 2;
64 else ndim = 1;
65 string exmsg = "TArray<T>::TArray(uint_4, uint_4, uint_4)";
66 if (!UpdateSizes(ndim, size, 1, 0, exmsg)) throw( ParmError(exmsg) );
67}
68
[894]69//! Constructor
70/*!
71 \param ndim : number of dimensions
72 \param siz[ndim] : size along each dimension
73 \param db : datas are given by this NDataBlock
74 \param share : if true, data are shared, if false they are copied
75 \param step : step (same for all dimensions) in data block
76 \param offset : offset for first element in data block
77 */
[772]78template <class T>
[804]79TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, NDataBlock<T> & db, bool share, uint_4 step, uint_8 offset)
80 : BaseArray() , mNDBlock(db, share)
[772]81{
82 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, NDataBlock<T> & ... )";
83 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
84
85}
86
[894]87//! Constructor
88/*!
89 \param ndim : number of dimensions
90 \param siz[ndim] : size along each dimension
91 \param values : datas are given by this pointer
92 \param share : if true, data are shared, if false they are copied
93 \param step : step (same for all dimensions) in data block
94 \param offset : offset for first element in data block
95 \param br : if not NULL, dats are bridge with other datas
96 \sa NDataBlock
97 */
[772]98template <class T>
[804]99TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, T* values, uint_4 step, uint_8 offset, Bridge* br)
100 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br)
[772]101{
102 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, T* ... )";
103 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
104}
105
[894]106//! Constructor by copy
[976]107/*!
108 \warning datas are \b SHARED with \b a.
109 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
110 */
[772]111template <class T>
112TArray<T>::TArray(const TArray<T>& a)
[804]113 : BaseArray() , mNDBlock(a.mNDBlock)
[772]114{
115 string exmsg = "TArray<T>::TArray(const TArray<T>&)";
116 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
117 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
118}
119
[894]120//! Constructor by copy
121/*!
122 \param share : if true, data are shared, if false they are copied
123 */
[772]124template <class T>
125TArray<T>::TArray(const TArray<T>& a, bool share)
[804]126 : BaseArray() , mNDBlock(a.mNDBlock, share)
[772]127{
128 string exmsg = "TArray<T>::TArray(const TArray<T>&, bool)";
129 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
130 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
131}
132
[894]133//! Destructor
[772]134template <class T>
135TArray<T>::~TArray()
136{
137}
138
[894]139////////////////////////// Les methodes de copie/share
140
141//! Set array equal to \b a and return *this
[976]142/*!
143 \warning Datas are copied (cloned) from \b a.
144 \sa NDataBlock::operator=(const NDataBlock<T>&)
145*/
[772]146template <class T>
[804]147TArray<T>& TArray<T>::Set(const TArray<T>& a)
[772]148{
[970]149 if (this == &a) return(*this);
150 if (a.NbDimensions() < 1)
151 throw RangeCheckError("TArray<T>::Set(a ) - Array a not allocated ! ");
152 if (NbDimensions() < 1) CloneOrShare(a);
153 else CopyElt(a);
[772]154 return(*this);
155}
156
[894]157//! Clone array \b a
[772]158template <class T>
159void TArray<T>::Clone(const TArray<T>& a)
160{
161 string exmsg = "TArray<T>::Clone()";
162 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
163 mNDBlock.Clone(a.mNDBlock);
[894]164 if (mInfo) {delete mInfo; mInfo = NULL;}
[772]165 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
166}
167
[970]168//! Clone if \b a is not temporary, share if temporary
[976]169/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
[970]170template <class T>
171void TArray<T>::CloneOrShare(const TArray<T>& a)
172{
173 string exmsg = "TArray<T>::CloneOrShare()";
174 if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) );
175 mNDBlock.CloneOrShare(a.mNDBlock);
176}
177
178//! Share data with a
179template <class T>
180void TArray<T>::Share(const TArray<T>& a)
181{
182 string exmsg = "TArray<T>::Share()";
183 if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) );
184 mNDBlock.Share(a.mNDBlock);
185}
186
187
[894]188//! Resize array
189/*!
190 \param ndim : number of dimensions
191 \param siz[ndim] : size along each dimension
192 \param step : step (same for all dimensions)
193 */
[772]194template <class T>
195void TArray<T>::ReSize(uint_4 ndim, uint_4 * siz, uint_4 step)
196{
197 string exmsg = "TArray<T>::ReSize()";
198 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
199 mNDBlock.ReSize(totsize_);
200}
201
[894]202//! Re-allocate space for array
203/*!
204 \param ndim : number of dimensions
205 \param siz[ndim] : size along each dimension
206 \param step : step (same for all dimensions)
207 \param force : if true re-allocation is forced, if not it occurs
208 only if the required space is greater than the old one.
209 */
[772]210template <class T>
211void TArray<T>::Realloc(uint_4 ndim, uint_4 * siz, uint_4 step, bool force)
212{
213 string exmsg = "TArray<T>::Realloc()";
214 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
215 mNDBlock.ReSize(totsize_);
216}
217
[787]218
[894]219//! Compact dimensions in one or more is equal to 1.
[772]220template <class T>
[787]221TArray<T>& TArray<T>::CompactAllDimensions()
[772]222{
[787]223 CompactAllDim();
224 return(*this);
[772]225}
226
[894]227//! Compact dimensions if the last one is equal to 1.
[785]228template <class T>
[787]229TArray<T>& TArray<T>::CompactTrailingDimensions()
[785]230{
[787]231 CompactTrailingDim();
[785]232 return(*this);
233}
234
[922]235inline double _SqrtRz_(double x) { return sqrt(x); } // Pb avec SGI-CC - $CHECK$ - Reza 04/2000
236
[894]237//! Give value (in \b double) for element at position \b ip..
[785]238template <class T>
[787]239double TArray<T>::ValueAtPosition(uint_8 ip) const
[785]240{
[787]241#ifdef SO_BOUNDCHECKING
242 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(uint_8 ip) Out-of-bound Error") );
243#endif
244 return( (double)(*(mNDBlock.Begin()+Offset(ip))) );
[785]245}
246
[894]247//! Give value (in \b double) for element at position \b ip..
248/*!
249 For complex values, we return the module of the complex number
250*/
[787]251double TArray< complex<r_4> >::ValueAtPosition(uint_8 ip) const
[785]252{
[787]253#ifdef SO_BOUNDCHECKING
254 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(uint_8 ip) Out-of-bound Error") );
255#endif
256 complex<r_4> c = *(mNDBlock.Begin()+Offset(ip));
257 double cr = (double)(c.real());
258 double ci = (double)(c.imag());
[922]259 return( _SqrtRz_(cr*cr+ci*ci) );
[785]260}
261
[894]262//! Give value (in \b double) for element at position \b ip..
263/*!
264 For complex values, we return the module of the complex number
265*/
[787]266double TArray< complex<r_8> >::ValueAtPosition(uint_8 ip) const
[785]267{
[787]268#ifdef SO_BOUNDCHECKING
269 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(uint_8 ip) Out-of-bound Error") );
270#endif
271 complex<r_8> c = *(mNDBlock.Begin()+Offset(ip));
272 double cr = (double)(c.real());
273 double ci = (double)(c.imag());
[922]274 return( _SqrtRz_(cr*cr+ci*ci) );
[785]275}
276
[894]277//! Return array with elements packed
278/*!
279 \param force : if true, pack elements in a new array.
280 If false and array is already packed, return
281 an array that share data with the current one.
282 \return packed array
283 */
[804]284template <class T>
285TArray<T> TArray<T>::PackElements(bool force) const
286{
287 if (NbDimensions() < 1)
288 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
289 if ( !force && (AvgStep() == 1) ) {
[970]290 TArray<T> ra;
291 ra.Share(*this);
[804]292 ra.SetTemp(true);
293 return(ra);
294 }
295 else {
296 TArray<T> ra(ndim_, size_, 1);
297 ra.CopyElt(*this);
298 ra.SetTemp(true);
299 return(ra);
300 }
301}
302
[785]303// SubArrays
[804]304// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
[894]305//! Extract a sub-array
306/*!
307 \param rx,ry,rz,rt,ru : range of extraction along dimensions
308 \sa Range
309 */
[785]310template <class T>
[804]311TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
[785]312{
[804]313 if (NbDimensions() < 1)
314 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
[785]315 uint_4 ndim = 0;
[787]316 uint_4 size[BASEARRAY_MAXNDIMS];
317 uint_4 step[BASEARRAY_MAXNDIMS];
318 uint_4 pos[BASEARRAY_MAXNDIMS];
[785]319 size[0] = rx.Size();
320 size[1] = ry.Size();
321 size[2] = rz.Size();
322 size[3] = rt.Size();
323 size[4] = ru.Size();
324
325 step[0] = rx.Step();
326 step[1] = ry.Step();
327 step[2] = rz.Step();
328 step[3] = rt.Step();
329 step[4] = ru.Step();
330
331 pos[0] = rx.Start();
332 pos[1] = ry.Start();
333 pos[2] = rz.Start();
334 pos[3] = rt.Start();
335 pos[4] = ru.Start();
336
337 ndim = ndim_;
338 TArray<T> ra;
[804]339 UpdateSubArraySizes(ra, ndim, size, pos, step);
[787]340 ra.DataBlock().Share(this->DataBlock());
[785]341 ra.SetTemp(true);
342 return(ra);
343}
344
[772]345// ...... Operation de calcul sur les tableaux ......
346// ------- Attention --------
347// Boucles normales prenant en compte les steps ....
[894]348// Possibilite de // , vectorisation
349
350//! Fill TArray with Sequence \b seq
351/*!
352 \param seq : sequence to fill the array
353 \sa Sequence
354 */
[772]355template <class T>
[813]356TArray<T>& TArray<T>::SetSeq(Sequence seq)
[772]357{
[804]358 if (NbDimensions() < 1)
[813]359 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
[785]360 T * pe;
361 uint_8 j,k;
362 if (AvgStep() > 0) { // regularly spaced elements
363 uint_8 step = AvgStep();
364 pe = Data();
[958]365 for(k=0; k<totsize_; k++ ) pe[k*step] = (T) seq(k);
[785]366 }
367 else { // Non regular data spacing ...
[813]368 // uint_4 ka = MaxSizeKA();
369 uint_4 ka = 0;
[785]370 uint_8 step = Step(ka);
371 uint_8 gpas = Size(ka);
[813]372 uint_8 naxa = Size()/Size(ka);
373 for(j=0; j<naxa; j++) {
374 pe = mNDBlock.Begin()+Offset(ka,j);
[958]375 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
[785]376 }
377 }
[772]378 return(*this);
379}
380
381// >>>> Operations avec 2nd membre de type scalaire
382
[894]383//! Fill an array with a constant value \b x
[772]384template <class T>
[813]385TArray<T>& TArray<T>::SetT(T x)
[772]386{
[804]387 if (NbDimensions() < 1)
[813]388 throw RangeCheckError("TArray<T>::SetT(T ) - Not Allocated Array ! ");
[785]389 T * pe;
390 uint_8 j,k;
391 if (AvgStep() > 0) { // regularly spaced elements
392 uint_8 step = AvgStep();
393 uint_8 maxx = totsize_*step;
394 pe = Data();
395 for(k=0; k<maxx; k+=step ) pe[k] = x;
396 }
397 else { // Non regular data spacing ...
398 uint_4 ka = MaxSizeKA();
399 uint_8 step = Step(ka);
400 uint_8 gpas = Size(ka)*step;
[813]401 uint_8 naxa = Size()/Size(ka);
402 for(j=0; j<naxa; j++) {
403 pe = mNDBlock.Begin()+Offset(ka,j);
[785]404 for(k=0; k<gpas; k+=step) pe[k] = x;
405 }
406 }
[772]407 return(*this);
408}
409
[894]410//! Add a constant value \b x to an array
[772]411template <class T>
[804]412TArray<T>& TArray<T>::Add(T x)
[772]413{
[804]414 if (NbDimensions() < 1)
415 throw RangeCheckError("TArray<T>::Add(T ) - Not Allocated Array ! ");
[785]416 T * pe;
417 uint_8 j,k;
418 if (AvgStep() > 0) { // regularly spaced elements
419 uint_8 step = AvgStep();
420 uint_8 maxx = totsize_*step;
421 pe = Data();
422 for(k=0; k<maxx; k+=step ) pe[k] += x;
423 }
424 else { // Non regular data spacing ...
425 uint_4 ka = MaxSizeKA();
426 uint_8 step = Step(ka);
427 uint_8 gpas = Size(ka)*step;
[813]428 uint_8 naxa = Size()/Size(ka);
429 for(j=0; j<naxa; j++) {
430 pe = mNDBlock.Begin()+Offset(ka,j);
[785]431 for(k=0; k<gpas; k+=step) pe[k] += x;
432 }
433 }
[772]434 return(*this);
435}
436
[894]437//! Substract a constant value \b x to an array
[970]438/*!
439Substract a constant from the *this = *this-x
440\param fginv == true : Perfoms the inverse subtraction (*this = x-(*this))
441*/
[772]442template <class T>
[970]443TArray<T>& TArray<T>::Sub(T x, bool fginv)
[772]444{
[804]445 if (NbDimensions() < 1)
446 throw RangeCheckError("TArray<T>::Sub(T ) - Not Allocated Array ! ");
[785]447 T * pe;
448 uint_8 j,k;
449 if (AvgStep() > 0) { // regularly spaced elements
450 uint_8 step = AvgStep();
451 uint_8 maxx = totsize_*step;
452 pe = Data();
[970]453 if (fginv)
454 for(k=0; k<maxx; k+=step ) pe[k] = x-pe[k];
455 else
456 for(k=0; k<maxx; k+=step ) pe[k] -= x;
[785]457 }
458 else { // Non regular data spacing ...
459 uint_4 ka = MaxSizeKA();
460 uint_8 step = Step(ka);
461 uint_8 gpas = Size(ka)*step;
[813]462 uint_8 naxa = Size()/Size(ka);
463 for(j=0; j<naxa; j++) {
464 pe = mNDBlock.Begin()+Offset(ka,j);
[970]465 if (fginv)
466 for(k=0; k<gpas; k+=step) pe[k] = x-pe[k];
467 else
468 for(k=0; k<gpas; k+=step) pe[k] -= x;
[785]469 }
470 }
[772]471 return(*this);
472}
473
[894]474//! Multiply an array by a constant value \b x
[772]475template <class T>
[804]476TArray<T>& TArray<T>::Mul(T x)
[772]477{
[804]478 if (NbDimensions() < 1)
479 throw RangeCheckError("TArray<T>::Mul(T ) - Not Allocated Array ! ");
[785]480 T * pe;
481 uint_8 j,k;
482 if (AvgStep() > 0) { // regularly spaced elements
483 uint_8 step = AvgStep();
484 uint_8 maxx = totsize_*step;
485 pe = Data();
486 for(k=0; k<maxx; k+=step ) pe[k] *= x;
487 }
488 else { // Non regular data spacing ...
489 uint_4 ka = MaxSizeKA();
490 uint_8 step = Step(ka);
491 uint_8 gpas = Size(ka)*step;
[813]492 uint_8 naxa = Size()/Size(ka);
493 for(j=0; j<naxa; j++) {
494 pe = mNDBlock.Begin()+Offset(ka,j);
[785]495 for(k=0; k<gpas; k+=step) pe[k] *= x;
496 }
497 }
[772]498 return(*this);
499}
500
[894]501//! Divide an array by a constant value \b x
[970]502/*!
503Divide the array by a constant *this = *this/x
504\param fginv == true : Perfoms the inverse division (*this = x/(*this))
505*/
[772]506template <class T>
[970]507TArray<T>& TArray<T>::Div(T x, bool fginv)
[772]508{
[804]509 if (NbDimensions() < 1)
510 throw RangeCheckError("TArray<T>::Div(T ) - Not Allocated Array ! ");
[970]511 if (!fginv && (x == (T) 0) )
[894]512 throw MathExc("TArray<T>::Div(T ) - Divide by zero ! ");
[785]513 T * pe;
514 uint_8 j,k;
515 if (AvgStep() > 0) { // regularly spaced elements
516 uint_8 step = AvgStep();
517 uint_8 maxx = totsize_*step;
518 pe = Data();
[970]519 if (fginv)
520 for(k=0; k<maxx; k+=step ) pe[k] = x/pe[k];
521 else
522 for(k=0; k<maxx; k+=step ) pe[k] /= x;
[785]523 }
524 else { // Non regular data spacing ...
525 uint_4 ka = MaxSizeKA();
526 uint_8 step = Step(ka);
527 uint_8 gpas = Size(ka)*step;
[813]528 uint_8 naxa = Size()/Size(ka);
529 for(j=0; j<naxa; j++) {
530 pe = mNDBlock.Begin()+Offset(ka,j);
[970]531 if (fginv)
532 for(k=0; k<gpas; k+=step) pe[k] = x/pe[k];
533 else
534 for(k=0; k<gpas; k+=step) pe[k] /= x;
[785]535 }
536 }
[772]537 return(*this);
538}
539
540
[804]541
542
[772]543// >>>> Operations avec 2nd membre de type tableau
[894]544//! Add two TArrays
[772]545template <class T>
[804]546TArray<T>& TArray<T>::AddElt(const TArray<T>& a)
[772]547{
[804]548 if (NbDimensions() < 1)
549 throw RangeCheckError("TArray<T>::AddElt(const TArray<T>& ) - Not Allocated Array ! ");
[813]550 if (!CompareSizes(a))
551 throw(SzMismatchError("TArray<T>::AddElt(const TArray<T>&) SizeMismatch")) ;
[785]552
553 T * pe;
554 const T * pea;
555 uint_8 j,k,ka;
556 if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
557 uint_8 step = AvgStep();
558 uint_8 stepa = a.AvgStep();
559 uint_8 maxx = totsize_*step;
560 pe = Data();
561 pea = a.Data();
562 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] += pea[ka] ;
[772]563 }
[785]564 else { // Non regular data spacing ...
565 uint_4 ax = MaxSizeKA();
566 uint_8 step = Step(ax);
567 uint_8 stepa = a.Step(ax);
568 uint_8 gpas = Size(ax)*step;
[813]569 uint_8 naxa = Size()/Size(ax);
570 for(j=0; j<naxa; j++) {
571 pe = mNDBlock.Begin()+Offset(ax,j);
572 pea = a.DataBlock().Begin()+a.Offset(ax,j);
[785]573 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] += pea[ka];
574 }
575 }
[772]576 return(*this);
577}
578
[894]579//! Substract two TArrays
[970]580/*!
581Substract two TArrays *this = *this-a
582\param fginv == true : Perfoms the inverse subtraction (*this = a-(*this))
583*/
[772]584template <class T>
[970]585TArray<T>& TArray<T>::SubElt(const TArray<T>& a, bool fginv)
[772]586{
[804]587 if (NbDimensions() < 1)
588 throw RangeCheckError("TArray<T>::SubElt(const TArray<T>& ) - Not Allocated Array ! ");
[813]589 if (!CompareSizes(a))
590 throw(SzMismatchError("TArray<T>::SubElt(const TArray<T>&) SizeMismatch")) ;
[785]591
592 T * pe;
593 const T * pea;
594 uint_8 j,k,ka;
595 if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
596 uint_8 step = AvgStep();
597 uint_8 stepa = a.AvgStep();
598 uint_8 maxx = totsize_*step;
599 pe = Data();
600 pea = a.Data();
[970]601 if (fginv)
602 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]-pe[k] ;
603 else
604 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] -= pea[ka] ;
[772]605 }
[785]606 else { // Non regular data spacing ...
607 uint_4 ax = MaxSizeKA();
608 uint_8 step = Step(ax);
609 uint_8 stepa = a.Step(ax);
610 uint_8 gpas = Size(ax)*step;
[813]611 uint_8 naxa = Size()/Size(ax);
612 for(j=0; j<naxa; j++) {
613 pe = mNDBlock.Begin()+Offset(ax,j);
614 pea = a.DataBlock().Begin()+a.Offset(ax,j);
[970]615 if (fginv)
616 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]-pe[k] ;
617 else
618 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] -= pea[ka];
[785]619 }
620 }
[772]621 return(*this);
622}
623
[970]624
[894]625//! Multiply two TArrays (elements by elements)
[772]626template <class T>
[804]627TArray<T>& TArray<T>::MulElt(const TArray<T>& a)
[772]628{
[804]629 if (NbDimensions() < 1)
630 throw RangeCheckError("TArray<T>::MulElt(const TArray<T>& ) - Not Allocated Array ! ");
[813]631 if (!CompareSizes(a))
632 throw(SzMismatchError("TArray<T>::MulElt(const TArray<T>&) SizeMismatch")) ;
[785]633
634 T * pe;
635 const T * pea;
636 uint_8 j,k,ka;
637 if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
638 uint_8 step = AvgStep();
639 uint_8 stepa = a.AvgStep();
640 uint_8 maxx = totsize_*step;
641 pe = Data();
642 pea = a.Data();
643 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] *= pea[ka] ;
[772]644 }
[785]645 else { // Non regular data spacing ...
646 uint_4 ax = MaxSizeKA();
647 uint_8 step = Step(ax);
648 uint_8 stepa = a.Step(ax);
649 uint_8 gpas = Size(ax)*step;
[813]650 uint_8 naxa = Size()/Size(ax);
651 for(j=0; j<naxa; j++) {
652 pe = mNDBlock.Begin()+Offset(ax,j);
653 pea = a.DataBlock().Begin()+a.Offset(ax,j);
[785]654 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] *= pea[ka];
655 }
656 }
[772]657 return(*this);
658}
659
[804]660
[894]661//! Divide two TArrays (elements by elements)
[970]662/*!
663Divide two TArrays *this = (*this)/a
664\param fginv == true : Perfoms the inverse division (*this = a/(*this))
[1072]665\param divzero == true : if a(i)==0. result is set to zero: (*this)(i)==0.
[970]666*/
[772]667template <class T>
[1072]668TArray<T>& TArray<T>::DivElt(const TArray<T>& a, bool fginv, bool divzero)
[772]669{
[804]670 if (NbDimensions() < 1)
671 throw RangeCheckError("TArray<T>::DivElt(const TArray<T>& ) - Not Allocated Array ! ");
[813]672 if (!CompareSizes(a))
673 throw(SzMismatchError("TArray<T>::DivElt(const TArray<T>&) SizeMismatch")) ;
[785]674
675 T * pe;
676 const T * pea;
677 uint_8 j,k,ka;
678 if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
679 uint_8 step = AvgStep();
680 uint_8 stepa = a.AvgStep();
681 uint_8 maxx = totsize_*step;
682 pe = Data();
683 pea = a.Data();
[1072]684 if(divzero) {
685 if (fginv)
686 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
687 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
688 else
689 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
690 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka] ;}
691 } else {
692 if (fginv)
693 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]/pe[k];
694 else
695 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] /= pea[ka] ;
696 }
[772]697 }
[785]698 else { // Non regular data spacing ...
699 uint_4 ax = MaxSizeKA();
700 uint_8 step = Step(ax);
701 uint_8 stepa = a.Step(ax);
702 uint_8 gpas = Size(ax)*step;
[813]703 uint_8 naxa = Size()/Size(ax);
704 for(j=0; j<naxa; j++) {
705 pe = mNDBlock.Begin()+Offset(ax,j);
706 pea = a.DataBlock().Begin()+a.Offset(ax,j);
[1072]707 if(divzero) {
708 if (fginv)
709 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
710 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
711 else
712 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
713 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka];}
714 } else {
715 if (fginv)
716 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]/pe[k];
717 else
718 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] /= pea[ka];
719 }
[785]720 }
721 }
[772]722 return(*this);
723}
724
[894]725//! Copy elements of \b a
[804]726template <class T>
727TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
728{
729 if (NbDimensions() < 1)
730 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[813]731 if (!CompareSizes(a))
[1050]732 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
[772]733
[804]734 T * pe;
735 const T * pea;
736 uint_8 j,k,ka;
737 if ((AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
738 uint_8 step = AvgStep();
739 uint_8 stepa = a.AvgStep();
740 uint_8 maxx = totsize_*step;
741 pe = Data();
742 pea = a.Data();
743 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka] ;
744 }
745 else { // Non regular data spacing ...
746 uint_4 ax = MaxSizeKA();
747 uint_8 step = Step(ax);
748 uint_8 stepa = a.Step(ax);
749 uint_8 gpas = Size(ax)*step;
[813]750 uint_8 naxa = Size()/Size(ax);
751 for(j=0; j<naxa; j++) {
752 pe = mNDBlock.Begin()+Offset(ax,j);
753 pea = a.DataBlock().Begin()+a.Offset(ax,j);
[804]754 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka];
755 }
756 }
757 return(*this);
758}
759
760
761// Somme et produit des elements
[894]762//! Sum all elements
[804]763template <class T>
764T TArray<T>::Sum() const
765{
766 if (NbDimensions() < 1)
767 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
768 T ret=0;
769 const T * pe;
770 uint_8 j,k;
771 if (AvgStep() > 0) { // regularly spaced elements
772 uint_8 step = AvgStep();
773 uint_8 maxx = totsize_*step;
774 pe = Data();
775 for(k=0; k<maxx; k+=step ) ret += pe[k];
776 }
777 else { // Non regular data spacing ...
778 uint_4 ka = MaxSizeKA();
779 uint_8 step = Step(ka);
780 uint_8 gpas = Size(ka)*step;
[813]781 uint_8 naxa = Size()/Size(ka);
782 for(j=0; j<naxa; j++) {
783 pe = mNDBlock.Begin()+Offset(ka,j);
[804]784 for(k=0; k<gpas; k+=step) ret += pe[k] ;
785 }
786 }
787 return ret;
788}
789
[894]790//! Multiply all elements
[804]791template <class T>
792T TArray<T>::Product() const
793{
794 if (NbDimensions() < 1)
795 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
796 T ret=0;
797 const T * pe;
798 uint_8 j,k;
799 if (AvgStep() > 0) { // regularly spaced elements
800 uint_8 step = AvgStep();
801 uint_8 maxx = totsize_*step;
802 pe = Data();
803 for(k=0; k<maxx; k+=step ) ret *= pe[k];
804 }
805 else { // Non regular data spacing ...
806 uint_4 ka = MaxSizeKA();
807 uint_8 step = Step(ka);
808 uint_8 gpas = Size(ka)*step;
[813]809 uint_8 naxa = Size()/Size(ka);
810 for(j=0; j<naxa; j++) {
811 pe = mNDBlock.Begin()+Offset(ka,j);
[804]812 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
813 }
814 }
815 return ret;
816}
817
818
819
[772]820// ----------------------------------------------------
821// Impression, etc ...
822// ----------------------------------------------------
823
[894]824//! Return a string that contain the type \b T of the array
[772]825template <class T>
[813]826string TArray<T>::InfoString() const
[772]827{
[813]828 string rs = "TArray<" ;
829 rs += typeid(T).name();
830 rs += "> ";
[787]831 return(rs);
[772]832}
833
[894]834//! Print array
835/*!
836 \param os : output stream
837 \param maxprt : maximum numer of print
838 \param si : if true, display attached DvList
839 \sa SetMaxPrint
840 */
[772]841template <class T>
842void TArray<T>::Print(ostream& os, int_4 maxprt, bool si) const
843{
844 if (maxprt < 0) maxprt = max_nprt_;
[958]845 uint_4 npr = 0;
[772]846 Show(os, si);
[850]847 if (ndim_ < 1) return;
[804]848 uint_4 k0,k1,k2,k3,k4;
[772]849 for(k4=0; k4<size_[4]; k4++) {
[785]850 if (size_[4] > 1) cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
[772]851 for(k3=0; k3<size_[3]; k3++) {
[785]852 if (size_[3] > 1) cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
[772]853 for(k2=0; k2<size_[2]; k2++) {
[785]854 if (size_[2] > 1) cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
[772]855 for(k1=0; k1<size_[1]; k1++) {
[785]856 if ( (size_[1] > 1) && (size_[0] > 10) ) cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
[772]857 for(k0=0; k0<size_[0]; k0++) {
[785]858 if(k0 > 0) os << ", ";
859 os << Elem(k0, k1, k2, k3, k4); npr++;
[958]860 if (npr >= (uint_4) maxprt) {
[772]861 if (npr < totsize_) os << "\n .... " << endl; return;
862 }
863 }
864 os << endl;
865 }
866 }
867 }
868 }
[813]869 os << endl;
[772]870}
871
872
873
874///////////////////////////////////////////////////////////////
875///////////////////////////////////////////////////////////////
876#ifdef __CXX_PRAGMA_TEMPLATES__
[804]877/*
[772]878#pragma define_template TArray<uint_1>
[804]879#pragma define_template TArray<int_2>
880#pragma define_template TArray<uint_4>
881#pragma define_template TArray<uint_8>
882*/
[772]883#pragma define_template TArray<uint_2>
884#pragma define_template TArray<int_4>
885#pragma define_template TArray<int_8>
886#pragma define_template TArray<r_4>
887#pragma define_template TArray<r_8>
888#pragma define_template TArray< complex<r_4> >
889#pragma define_template TArray< complex<r_8> >
890#endif
891
892#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[804]893/*
894template class TArray<uint_1>;
895template class TArray<int_2>;
896template class TArray<uint_4>;
897template class TArray<uint_8>;
898*/
[772]899template class TArray<uint_2>;
900template class TArray<int_4>;
901template class TArray<int_8>;
902template class TArray<r_4>;
903template class TArray<r_8>;
904template class TArray< complex<r_4> >;
905template class TArray< complex<r_8> >;
906#endif
907
908
Note: See TracBrowser for help on using the repository browser.