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

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

Correction bug initialisation vecteur ligne / colonne , Reza 9/2/2001

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