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

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

Ajout methodes ReSize(TArray &) - Reza 12/2/2001

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