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

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

doc pour preparation inverse logique de NDataBlock cmv 21/4/00

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