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

Last change on this file since 1941 was 1636, checked in by ansari, 24 years ago

Correction bugs ds UpdateSize (calcul AvgStep() et configuration Vecteur/Matrices + protection constructeur TArray() depuis NDataBlock - Reza 13/8/2001

File size: 32.6 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#if !defined(__GNUG__)
856 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
857#else
858 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
859 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
860#endif
861 }
862 return(*this);
863}
864
865
866// Somme et produit des elements
867//! Sum all elements
868template <class T>
869T TArray<T>::Sum() const
870{
871 if (NbDimensions() < 1)
872 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
873 T ret=0;
874 const T * pe;
875 sa_size_t j,k;
876 if (AvgStep() > 0) { // regularly spaced elements
877 sa_size_t step = AvgStep();
878 sa_size_t maxx = totsize_*step;
879 pe = Data();
880 for(k=0; k<maxx; k+=step ) ret += pe[k];
881 }
882 else { // Non regular data spacing ...
883 int_4 ka = MaxSizeKA();
884 sa_size_t step = Step(ka);
885 sa_size_t gpas = Size(ka)*step;
886 sa_size_t naxa = Size()/Size(ka);
887 for(j=0; j<naxa; j++) {
888 pe = mNDBlock.Begin()+Offset(ka,j);
889 for(k=0; k<gpas; k+=step) ret += pe[k] ;
890 }
891 }
892 return ret;
893}
894
895//! Multiply all elements
896template <class T>
897T TArray<T>::Product() const
898{
899 if (NbDimensions() < 1)
900 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
901 T ret=(T)1;
902 const T * pe;
903 sa_size_t j,k;
904 if (AvgStep() > 0) { // regularly spaced elements
905 sa_size_t step = AvgStep();
906 sa_size_t maxx = totsize_*step;
907 pe = Data();
908 for(k=0; k<maxx; k+=step ) ret *= pe[k];
909 }
910 else { // Non regular data spacing ...
911 int_4 ka = MaxSizeKA();
912 sa_size_t step = Step(ka);
913 sa_size_t gpas = Size(ka)*step;
914 sa_size_t naxa = Size()/Size(ka);
915 for(j=0; j<naxa; j++) {
916 pe = mNDBlock.Begin()+Offset(ka,j);
917 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
918 }
919 }
920 return ret;
921}
922
923//! Returns the sum of all elements squared (Sum
924template <class T>
925T TArray<T>::SumX2() const
926{
927 if (NbDimensions() < 1)
928 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
929 T ret=0;
930 const T * pe;
931 sa_size_t j,k;
932 if (AvgStep() > 0) { // regularly spaced elements
933 sa_size_t step = AvgStep();
934 sa_size_t maxx = totsize_*step;
935 pe = Data();
936 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
937 }
938 else { // Non regular data spacing ...
939 int_4 ka = MaxSizeKA();
940 sa_size_t step = Step(ka);
941 sa_size_t gpas = Size(ka)*step;
942 sa_size_t naxa = Size()/Size(ka);
943 for(j=0; j<naxa; j++) {
944 pe = mNDBlock.Begin()+Offset(ka,j);
945 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
946 }
947 }
948 return ret;
949}
950
951//! Return the minimum and the maximum values of the array elements
952/*!
953 This method generates an exception (\c MathExc) if called for complex arrays
954*/
955template <class T>
956void TArray<T>::MinMax(T& min, T& max) const
957{
958 const T * pe;
959 sa_size_t j,k;
960 int_4 ka = MaxSizeKA();
961 sa_size_t step = Step(ka);
962 sa_size_t gpas = Size(ka)*step;
963 sa_size_t naxa = Size()/Size(ka);
964 min = (*this)[0];
965 max = (*this)[0];
966 for(j=0; j<naxa; j++) {
967 pe = mNDBlock.Begin()+Offset(ka,j);
968 for(k=0; k<gpas; k+=step) {
969 if (pe[k]<min) min = pe[k];
970 else if (pe[k]>max) max = pe[k];
971 }
972 }
973 return;
974}
975
976void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
977{
978 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
979}
980
981void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
982{
983 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
984}
985
986// ----------------------------------------------------
987// Impression, etc ...
988// ----------------------------------------------------
989
990//! Return a string that contain the type \b T of the array
991template <class T>
992string TArray<T>::InfoString() const
993{
994 string rs = "TArray<" ;
995 rs += typeid(T).name();
996 rs += "> ";
997 return(rs);
998}
999
1000//! Print array
1001/*!
1002 \param os : output stream
1003 \param maxprt : maximum numer of print
1004 \param si : if true, display attached DvList
1005 \param ascd : if true, suppresses the display of line numbers,
1006 suitable for ascii dump format.
1007 \sa SetMaxPrint
1008 \sa WriteASCII
1009 */
1010template <class T>
1011void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
1012{
1013 if (maxprt < 0) maxprt = max_nprt_;
1014 sa_size_t npr = 0;
1015 Show(os, si);
1016 if (ndim_ < 1) return;
1017 sa_size_t k0,k1,k2,k3,k4;
1018 for(k4=0; k4<size_[4]; k4++) {
1019 if ((size_[4] > 1) && ascd)
1020 cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
1021 for(k3=0; k3<size_[3]; k3++) {
1022 if ((size_[3] > 1) && ascd)
1023 cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
1024 for(k2=0; k2<size_[2]; k2++) {
1025 if ((size_[2] > 1) & ascd)
1026 cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
1027 for(k1=0; k1<size_[1]; k1++) {
1028 if ( (size_[1] > 1) && (size_[0] > 10) && ascd)
1029 cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
1030 for(k0=0; k0<size_[0]; k0++) {
1031 if(k0 > 0) os << " ";
1032 os << Elem(k0, k1, k2, k3, k4); npr++;
1033 if (npr >= (sa_size_t) maxprt) {
1034 if (npr < totsize_) os << "\n .... " << endl; return;
1035 }
1036 }
1037 os << endl;
1038 }
1039 }
1040 }
1041 }
1042 os << endl;
1043}
1044
1045//! Fill the array, decoding the ASCII input stream
1046/*!
1047 \param is : input stream (ASCII)
1048 \param nr : Number of non empty (or comment) lines in stream (return value)
1049 \param nc : Number of columns (= ntot/nlines) (return value)
1050 \return Number of decoded elements
1051 */
1052template <class T>
1053sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc)
1054{
1055 EnumeratedSequence es;
1056 sa_size_t n = es.FillFromFile(is, nr, nc);
1057 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1058 if (!IsAllocated()) {
1059 sa_size_t sz[2];
1060 if (arrtype_ == 2) { // C'est un vecteur
1061 sz[0] = sz[1] = 1;
1062 sz[veceli_] = n;
1063 }
1064 else {
1065 sz[RowsKA()] = nr;
1066 sz[ColsKA()] = nc;
1067 }
1068 ReSize(2, sz);
1069 }
1070 SetSeq(es);
1071 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1072 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1073 return(n);
1074}
1075
1076//! Writes the array content to the output stream, (in ASCII)
1077/*!
1078 \param os : output stream (ASCII)
1079 \sa Print
1080 */
1081template <class T>
1082void TArray<T>::WriteASCII(ostream& os) const
1083{
1084 Print(os, Size(), false, true);
1085}
1086
1087
1088
1089///////////////////////////////////////////////////////////////
1090///////////////////////////////////////////////////////////////
1091#ifdef __CXX_PRAGMA_TEMPLATES__
1092/*
1093#pragma define_template TArray<uint_1>
1094#pragma define_template TArray<int_2>
1095#pragma define_template TArray<uint_4>
1096*/
1097#pragma define_template TArray<uint_2>
1098#pragma define_template TArray<uint_8>
1099#pragma define_template TArray<int_4>
1100#pragma define_template TArray<int_8>
1101#pragma define_template TArray<r_4>
1102#pragma define_template TArray<r_8>
1103#pragma define_template TArray< complex<r_4> >
1104#pragma define_template TArray< complex<r_8> >
1105#endif
1106
1107#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1108/*
1109template class TArray<uint_1>;
1110template class TArray<int_2>;
1111template class TArray<uint_4>;
1112*/
1113template class TArray<uint_2>;
1114template class TArray<uint_8>;
1115template class TArray<int_4>;
1116template class TArray<int_8>;
1117template class TArray<r_4>;
1118template class TArray<r_8>;
1119template class TArray< complex<r_4> >;
1120template class TArray< complex<r_8> >;
1121#endif
1122
1123
Note: See TracBrowser for help on using the repository browser.