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

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

Ajout documentation , Reza 22/12/2000

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