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

Last change on this file since 2149 was 2147, checked in by ansari, 23 years ago

Appel explicite de l'operateur de conversion sur objet MuTyV et Adaptation a fmath.h vide , Reza 31/7/2002

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