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

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

documentation cmv 13/4/00

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