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

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

Ajout Methodes TArray::MinMax() et TArray::SumX2() - Reza 28/7/2000

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