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

Last change on this file since 1554 was 1550, checked in by ansari, 24 years ago

Extension de l'interface TArray/BaseArray/EnumeratedSequence pour permettre la lecture de fichier ASCII - Reza 27/6/2001

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