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

Last change on this file since 2806 was 2788, checked in by ansari, 20 years ago

corrections pour impression/dump ascii des tableaux/matrices - Reza 30 Mai 2005

File size: 46.1 KB
Line 
1// template array class for numerical types
2// R. Ansari, C.Magneville 03/2000
3
4#include "sopnamsp.h"
5#include "machdefs.h"
6#include <stdio.h>
7#include <stdlib.h>
8#include <math.h>
9#include <iomanip>
10
11#include "pexceptions.h"
12#include "tarray.h"
13
14/*!
15 \class SOPHYA::TArray
16 \ingroup TArray
17 Class for template arrays with numerical data types (int, float, complex).
18
19 This class implements arrays with number of dimensions up to
20 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS"
21
22 Standard arithmetic operations on numerical arrays are implemented,
23 as well as sub-array manipulation services.
24 \b Array is a typedef for double precision floating point arrays ( TArray<r_8> )
25 \sa SOPHYA::Range
26 \sa SOPHYA::Sequence
27 \sa SOPHYA::MathArray
28
29 \code
30 #include "array.h"
31 // ...
32 // Creating and initialising a 1-D array of integers
33 TArray<int> ia(5);
34 EnumeratedSequence es;
35 es = 24, 35, 46, 57, 68;
36 ia = es;
37 cout << "Array<int> ia = " << ia;
38 // 2-D array of floats
39 TArray<r_4> b(6,4), c(6,4);
40 // Initializing b with a constant
41 b = 2.71828;
42 // Filling c with random numbers
43 c = RandomSequence();
44 // Arithmetic operations
45 TArray<r_4> d = b+0.3f*c;
46 cout << "Array<float> d = " << d;
47 \endcode
48
49*/
50
51/*! \ingroup TArray
52 \typedef sa_size_t
53 \brief Array index range and size, defined to be a 4-byte or 8-byte integer
54*/
55
56// -------------------------------------------------------
57// Methodes de la classe
58// -------------------------------------------------------
59
60////////////////////////// Les constructeurs / destructeurs
61
62//! Default constructor
63template <class T>
64TArray<T>::TArray()
65 : BaseArray() , mNDBlock()
66{
67}
68
69//! Constructor
70/*!
71 \param ndim : number of dimensions (less or equal to
72 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS")
73 \param siz[ndim] : size along each dimension
74 \param step : step (same for all dimensions)
75 \param fzero : if \b true , set array elements to zero
76 */
77template <class T>
78TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, sa_size_t step, bool fzero)
79 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), fzero)
80{
81 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, sa_size_t)";
82 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
83}
84
85//! Constructor
86/*!
87 \param nx,ny,nz,nt,nu : sizes along first, second, third, fourth and fifth dimension
88 \param fzero : if \b true , set array elements to zero
89 */
90template <class T>
91TArray<T>::TArray(sa_size_t nx, sa_size_t ny, sa_size_t nz, sa_size_t nt, sa_size_t nu, bool fzero)
92 : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1))
93{
94 sa_size_t size[BASEARRAY_MAXNDIMS];
95 size[0] = nx; size[1] = ny; size[2] = nz;
96 size[3] = nt; size[4] = nu;
97 int_4 ndim = 1;
98 if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) && (size[4] > 0) ) ndim = 5;
99 else if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) ) ndim = 4;
100 else if ((size[1] > 0) && (size[2] > 0)) ndim = 3;
101 else if (size[1] > 0) ndim = 2;
102 else ndim = 1;
103 string exmsg = "TArray<T>::TArray(sa_size_t, sa_size_t, sa_size_t, sa_size_t, sa_size_t)";
104 if (!UpdateSizes(ndim, size, 1, 0, exmsg)) throw( ParmError(exmsg) );
105}
106
107//! Constructor
108/*!
109 \param ndim : number of dimensions
110 \param siz[ndim] : size along each dimension
111 \param db : datas are given by this NDataBlock
112 \param share : if true, data are shared, if false they are copied
113 \param step : step (same for all dimensions) in data block
114 \param offset : offset for first element in data block
115 */
116template <class T>
117TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, NDataBlock<T> & db, bool share, sa_size_t step, sa_size_t offset)
118 : BaseArray() , mNDBlock(db, share)
119{
120 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, NDataBlock<T> & ... )";
121 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
122 if (mNDBlock.Size() < ComputeTotalSize(ndim, siz, step, offset)) {
123 exmsg += " DataBlock.Size() < ComputeTotalSize(...) " ;
124 throw( ParmError(exmsg) );
125 }
126}
127
128//! Constructor
129/*!
130 \param ndim : number of dimensions
131 \param siz[ndim] : size along each dimension
132 \param values : datas are given by this pointer
133 \param share : if true, data are shared, if false they are copied
134 \param step : step (same for all dimensions) in data block
135 \param offset : offset for first element in data block
136 \param br : if not NULL, dats are bridge with other datas
137 \sa NDataBlock
138 */
139template <class T>
140TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, T* values, sa_size_t step, sa_size_t offset, Bridge* br)
141 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br)
142{
143 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, T* ... )";
144 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
145}
146
147//! Constructor by copy
148/*!
149 \warning datas are \b SHARED with \b a.
150 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
151 */
152template <class T>
153TArray<T>::TArray(const TArray<T>& a)
154 : BaseArray() , mNDBlock(a.mNDBlock)
155{
156 string exmsg = "TArray<T>::TArray(const TArray<T>&)";
157 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
158 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
159}
160
161//! Constructor by copy
162/*!
163 \param share : if true, data are shared, if false they are copied
164 */
165template <class T>
166TArray<T>::TArray(const TArray<T>& a, bool share)
167 : BaseArray() , mNDBlock(a.mNDBlock, share)
168{
169 if (a.NbDimensions() == 0) return;
170 string exmsg = "TArray<T>::TArray(const TArray<T>&, bool)";
171 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
172 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
173}
174
175//! Constructor with size and contents copied (after conversion) from a different type TArray
176template <class T>
177TArray<T>::TArray(const BaseArray& a)
178 : BaseArray() , mNDBlock()
179{
180 if (a.NbDimensions() == 0) return;
181 string exmsg = "TArray<T>::TArray(const BaseArray&)";
182 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
183 mNDBlock.ReSize(totsize_);
184 // if (a.mInfo) mInfo = new DVList(*(a.mInfo)); - pb protected !
185 ConvertAndCopyElt(a);
186}
187
188//! Destructor
189template <class T>
190TArray<T>::~TArray()
191{
192}
193
194////////////////////////// Les methodes de copie/share
195
196//! Set array equal to \b a and return *this
197/*!
198 If the array is already allocated, CopyElt() is called
199 for checking that the two arrays have the same size and
200 for copying the array element values. For non allocated
201 arrays, CloneOrShare() is called. The array memory
202 organization is also copied from \b a.
203 \warning Datas are copied (cloned) from \b a.
204 \sa CopyElt
205 \sa CloneOrShare
206 \sa NDataBlock::operator=(const NDataBlock<T>&)
207*/
208template <class T>
209TArray<T>& TArray<T>::Set(const TArray<T>& a)
210{
211 if (this == &a) return(*this);
212 if (a.NbDimensions() < 1)
213 throw RangeCheckError("TArray<T>::Set(a ) - Array a not allocated ! ");
214 if (NbDimensions() < 1) CloneOrShare(a);
215 else CopyElt(a);
216 return(*this);
217}
218
219//! Set array elements equal to the \b a array elements, after conversion
220template <class T>
221TArray<T>& TArray<T>::SetBA(const BaseArray& a)
222{
223 if (this == &a) return(*this);
224 if (a.NbDimensions() < 1)
225 throw RangeCheckError("TArray<T>::SetBA(a ) - Array a not allocated ! ");
226 if (NbDimensions() < 1) {
227 string exmsg = "TArray<T>::SetBA(const BaseArray& a)";
228 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
229 mNDBlock.ReSize(totsize_);
230 }
231 ConvertAndCopyElt(a);
232 return(*this);
233}
234
235//! Clone array \b a
236template <class T>
237void TArray<T>::Clone(const TArray<T>& a)
238{
239 string exmsg = "TArray<T>::Clone()";
240 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
241 mNDBlock.Clone(a.mNDBlock);
242 if (mInfo) {delete mInfo; mInfo = NULL;}
243 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
244}
245
246//! Clone if \b a is not temporary, share if temporary
247/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
248template <class T>
249void TArray<T>::CloneOrShare(const TArray<T>& a)
250{
251 string exmsg = "TArray<T>::CloneOrShare()";
252 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
253 mNDBlock.CloneOrShare(a.mNDBlock);
254 if (mInfo) {delete mInfo; mInfo = NULL;}
255 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
256}
257
258//! Share data with a
259template <class T>
260void TArray<T>::Share(const TArray<T>& a)
261{
262 string exmsg = "TArray<T>::Share()";
263 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
264 mNDBlock.Share(a.mNDBlock);
265 if (mInfo) {delete mInfo; mInfo = NULL;}
266 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
267}
268
269
270//! Sets or changes the array size
271/*!
272 \param ndim : number of dimensions
273 \param siz[ndim] : size along each dimension
274 \param step : step (same for all dimensions)
275 \param fzero : if \b true , set array elements to zero
276 */
277template <class T>
278void TArray<T>::ReSize(int_4 ndim, sa_size_t * siz, sa_size_t step, bool fzero)
279{
280 if (arrtype_ != 0) {
281 if (ndim != 2)
282 throw( ParmError("TArray<T>::ReSize(ndim!=2,...) for Matrix" ) );
283 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
284 throw( ParmError("TArray<T>::ReSize(,siz[0]>1 && size[1]>1) for Vector" ) );
285 }
286 string exmsg = "TArray<T>::ReSize(int_4 ...)";
287 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
288 mNDBlock.ReSize(totsize_, fzero);
289}
290
291//! Sets or changes the array size.
292/*!
293 The array size and memory layout are copied from the array \b a.
294 \param a : Array used as template for setting the size and memory layout.
295 \param pack : if \b true , create a packed array, else same memory layout as \b a.
296 \param fzero : if \b true , set array elements to zero
297 */
298template <class T>
299void TArray<T>::ReSize(const BaseArray& a, bool pack, bool fzero)
300{
301 if (arrtype_ != 0) {
302 if (a.NbDimensions() != 2)
303 throw( ParmError("TArray<T>::ReSize(a.NbDimensions()!=2,...) for Matrix" ) );
304 if ((arrtype_ == 2) && (a.Size(0) > 1) && (a.Size(1) > 1))
305 throw( ParmError("TArray<T>::ReSize(a.Size(0)>1 && a.Size(1)>1) for Vector" ) );
306 }
307 string exmsg = "TArray<T>::ReSize(const TArray<T>&)";
308 if (pack) {
309 sa_size_t siz[BASEARRAY_MAXNDIMS];
310 int ksz;
311 for(ksz=0; ksz<a.NbDimensions(); ksz++) siz[ksz] = a.Size(ksz);
312 for(ksz=a.NbDimensions(); ksz<BASEARRAY_MAXNDIMS; ksz++) siz[ksz] = 1;
313 if (!UpdateSizes(a.NbDimensions(), siz, 1, 0, exmsg)) throw( ParmError(exmsg) );
314 SetMemoryMapping(a.GetMemoryMapping());
315 mNDBlock.ReSize(totsize_, fzero);
316 }
317 else {
318 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
319 mNDBlock.ReSize(totsize_);
320 }
321}
322
323//! Re-allocate space for array
324/*!
325 \param ndim : number of dimensions
326 \param siz[ndim] : size along each dimension
327 \param step : step (same for all dimensions)
328 \param force : if true re-allocation is forced, if not it occurs
329 only if the required space is greater than the old one.
330 */
331template <class T>
332void TArray<T>::Realloc(int_4 ndim, sa_size_t * siz, sa_size_t step, bool force)
333{
334 if (arrtype_ != 0) {
335 if (ndim != 2)
336 throw( ParmError("TArray<T>::Realloc(ndim!=2,...) for Matrix" ) );
337 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
338 throw( ParmError("TArray<T>::Realloc(,siz[0]>1 && size[1]>1) for Vector" ) );
339 }
340 string exmsg = "TArray<T>::Realloc()";
341 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
342 mNDBlock.Realloc(totsize_, force);
343}
344
345
346//! Compact dimensions in one or more is equal to 1.
347template <class T>
348TArray<T>& TArray<T>::CompactAllDimensions()
349{
350 CompactAllDim();
351 return(*this);
352}
353
354//! Compact dimensions if the last one is equal to 1.
355template <class T>
356TArray<T>& TArray<T>::CompactTrailingDimensions()
357{
358 CompactTrailingDim();
359 return(*this);
360}
361
362//! Give value (in \b double) for element at position \b ip..
363template <class T>
364MuTyV & TArray<T>::ValueAtPosition(sa_size_t ip) const
365{
366#ifdef SO_BOUNDCHECKING
367 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(sa_size_t ip) Out-of-bound Error") );
368#endif
369 my_mtv = *(mNDBlock.Begin()+Offset(ip));
370 return( my_mtv );
371}
372
373//! Return array with elements packed
374/*!
375 \param force : if true, pack elements in a new array.
376 If false and array is already packed, return
377 an array that share data with the current one.
378 \return packed array
379 */
380template <class T>
381TArray<T> TArray<T>::PackElements(bool force) const
382{
383 if (NbDimensions() < 1)
384 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
385 if ( !force && (AvgStep() == 1) ) {
386 TArray<T> ra;
387 ra.Share(*this);
388 ra.SetTemp(true);
389 return(ra);
390 }
391 else {
392 TArray<T> ra(ndim_, size_, 1);
393 ra.CopyElt(*this);
394 ra.SetTemp(true);
395 return(ra);
396 }
397}
398
399// SubArrays
400// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
401//! Extract a sub-array
402/*!
403 \param rx,ry,rz,rt,ru : range of extraction along dimensions
404 \sa Range
405 */
406template <class T>
407TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
408{
409 if (NbDimensions() < 1)
410 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
411 int_4 ndim = 0;
412 sa_size_t size[BASEARRAY_MAXNDIMS];
413 sa_size_t step[BASEARRAY_MAXNDIMS];
414 sa_size_t pos[BASEARRAY_MAXNDIMS];
415 size[0] = rx.Size();
416 size[1] = ry.Size();
417 size[2] = rz.Size();
418 size[3] = rt.Size();
419 size[4] = ru.Size();
420
421 step[0] = rx.Step();
422 step[1] = ry.Step();
423 step[2] = rz.Step();
424 step[3] = rt.Step();
425 step[4] = ru.Step();
426
427 pos[0] = rx.Start();
428 pos[1] = ry.Start();
429 pos[2] = rz.Start();
430 pos[3] = rt.Start();
431 pos[4] = ru.Start();
432
433 ndim = ndim_;
434 TArray<T> ra;
435 UpdateSubArraySizes(ra, ndim, size, pos, step);
436 ra.DataBlock().Share(this->DataBlock());
437 ra.SetTemp(true);
438 return(ra);
439}
440
441// ...... Operation de calcul sur les tableaux ......
442// ------- Attention --------
443// Boucles normales prenant en compte les steps ....
444// Possibilite de // , vectorisation
445
446//! Fill TArray with Sequence \b seq
447/*!
448 \param seq : sequence to fill the array
449 \sa Sequence
450 */
451template <class T>
452TArray<T>& TArray<T>::SetSeq(Sequence const & seq)
453{
454 if (NbDimensions() < 1)
455 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
456
457 T * pe;
458 sa_size_t j,k;
459 int_4 ka;
460 if (arrtype_ == 0) ka = 0;
461 else ka = macoli_;
462 sa_size_t step = Step(ka);
463 sa_size_t gpas = Size(ka);
464 sa_size_t naxa = Size()/Size(ka);
465 for(j=0; j<naxa; j++) {
466 pe = mNDBlock.Begin()+Offset(ka,j);
467/*
468 Appel explicite de l'operateur de conversion
469 suite a la suggestion de M. Reinecke, Reza 31/7/2002
470#if !defined(__GNUG__)
471 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
472#else
473 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
474 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k);
475#endif
476 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
477*/
478 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k).operator T();
479 }
480 return(*this);
481}
482
483// >>>> Operations avec 2nd membre de type scalaire
484
485//! Fill an array with a constant value \b x
486template <class T>
487TArray<T>& TArray<T>::SetCst(T x)
488{
489 if (NbDimensions() < 1)
490 throw RangeCheckError("TArray<T>::SetCst(T ) - Not Allocated Array ! ");
491 T * pe;
492 sa_size_t j,k;
493 if (AvgStep() > 0) { // regularly spaced elements
494 sa_size_t step = AvgStep();
495 sa_size_t maxx = totsize_*step;
496 pe = Data();
497 for(k=0; k<maxx; k+=step ) pe[k] = x;
498 }
499 else { // Non regular data spacing ...
500 int_4 ka = MaxSizeKA();
501 sa_size_t step = Step(ka);
502 sa_size_t gpas = Size(ka)*step;
503 sa_size_t naxa = Size()/Size(ka);
504 for(j=0; j<naxa; j++) {
505 pe = mNDBlock.Begin()+Offset(ka,j);
506 for(k=0; k<gpas; k+=step) pe[k] = x;
507 }
508 }
509 return(*this);
510}
511
512//! Add a constant value \b x to the source array and store the result in \b res.
513/*!
514Add a constant to the source array \b this and store the result in \b res (res = *this+x).
515If not initially allocated, the output array \b res is automatically
516resized as a packed array with the same sizes as the source (this) array.
517Returns a reference to the output array \b res.
518\param x : constant to add to the array elements
519\param res : Output array containing the result (res=this+x).
520*/
521template <class T>
522TArray<T>& TArray<T>::AddCst(T x, TArray<T>& res) const
523{
524 if (NbDimensions() < 1)
525 throw RangeCheckError("TArray<T>::AddCst(T,res) - Not allocated source array ");
526 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
527 bool smo;
528 if (!CompareSizes(res, smo))
529 throw(SzMismatchError("TArray<T>::AddCst(T, res) SizeMismatch(this,res) ")) ;
530
531 const T * pe;
532 T * per;
533 sa_size_t j,k;
534 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
535 sa_size_t maxx = totsize_;
536 pe = Data();
537 per = res.Data();
538 for(k=0; k<maxx; k++) *per++ = *pe++ + x;
539 }
540 else { // Non regular data spacing ...
541 int_4 ax,axr;
542 sa_size_t step, stepr;
543 sa_size_t gpas, naxa;
544 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
545 for(j=0; j<naxa; j++) {
546 pe = mNDBlock.Begin()+Offset(ax,j);
547 per = res.DataBlock().Begin()+res.Offset(axr,j);
548 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe+x;
549 }
550 }
551 return(res);
552}
553
554//! Subtract a constant value \b x from the source array and store the result in \b res.
555/*!
556Subtract a constant from the source array \b this and store the result in \b res (res = *this-x).
557If not initially allocated, the output array \b res is automatically
558resized as a packed array with the same sizes as the source (this) array.
559Returns a reference to the output array \b res.
560\param x : constant to subtract from the array elements
561\param res : Output array containing the result (res=this+x or res=x-this).
562\param fginv == true : Invert subtraction argument order (res = x-(*this))
563*/
564template <class T>
565TArray<T>& TArray<T>::SubCst(T x, TArray<T>& res, bool fginv) const
566{
567 if (NbDimensions() < 1)
568 throw RangeCheckError("TArray<T>::SubCst(T,res) - Not allocated source array ");
569 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
570 bool smo;
571 if (!CompareSizes(res, smo))
572 throw(SzMismatchError("TArray<T>::SubCst(T, res) SizeMismatch(this,res) ")) ;
573
574 const T * pe;
575 T * per;
576 sa_size_t j,k;
577 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
578 sa_size_t maxx = totsize_;
579 pe = Data();
580 per = res.Data();
581 if (!fginv)
582 for(k=0; k<maxx; k++) *per++ = *pe++ - x;
583 else
584 for(k=0; k<maxx; k++) *per++ = x - *pe++;
585 }
586 else { // Non regular data spacing ...
587 int_4 ax,axr;
588 sa_size_t step, stepr;
589 sa_size_t gpas, naxa;
590 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
591 for(j=0; j<naxa; j++) {
592 pe = mNDBlock.Begin()+Offset(ax,j);
593 per = res.DataBlock().Begin()+res.Offset(axr,j);
594 if (!fginv)
595 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe-x;
596 else
597 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x-*pe;
598 }
599 }
600 return(res);
601}
602
603//! Multiply the source array by a constant value \b x and store the result in \b res.
604/*!
605Multiply the source array \b this by a constant \b x and store the result in \b res (res = *this*x).
606If not initially allocated, the output array \b res is automatically
607resized as a packed array with the same sizes as the source (this) array.
608Returns a reference to the output array \b res.
609\param x : Array elements are multiplied by x
610\param res : Output array containing the result (res=this*x).
611*/
612template <class T>
613TArray<T>& TArray<T>::MulCst(T x, TArray<T>& res) const
614{
615 if (NbDimensions() < 1)
616 throw RangeCheckError("TArray<T>::MulCst(T,res) - Not allocated source array ");
617 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
618 bool smo;
619 if (!CompareSizes(res, smo))
620 throw(SzMismatchError("TArray<T>::MulCst(T, res) SizeMismatch(this,res) ")) ;
621
622 const T * pe;
623 T * per;
624 sa_size_t j,k;
625 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
626 sa_size_t maxx = totsize_;
627 pe = Data();
628 per = res.Data();
629 for(k=0; k<maxx; k++) *per++ = *pe++ * x;
630 }
631 else { // Non regular data spacing ...
632 int_4 ax,axr;
633 sa_size_t step, stepr;
634 sa_size_t gpas, naxa;
635 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
636 for(j=0; j<naxa; j++) {
637 pe = mNDBlock.Begin()+Offset(ax,j);
638 per = res.DataBlock().Begin()+res.Offset(axr,j);
639 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)*x;
640 }
641 }
642 return(res);
643}
644
645//! Divide the source array by a constant value \b x and store the result in \b res.
646/*!
647Divide the source array \b this by a constant \b x and store the result in \b res (res = *this/x).
648If not initially allocated, the output array \b res is automatically
649resized as a packed array with the same sizes as the source (this) array.
650Returns a reference to the output array \b res.
651\param x : Array elements are divied by x
652\param res : Output array containing the result (res=(*this)/x or res=x/(*this)).
653\param fginv == true : Invert the division argument order (res = x/(*this))
654*/
655template <class T>
656TArray<T>& TArray<T>::DivCst(T x, TArray<T>& res, bool fginv) const
657{
658 if (NbDimensions() < 1)
659 throw RangeCheckError("TArray<T>::DivCst(T,res) - Not allocated source array ! ");
660 if (!fginv && (x == (T) 0) )
661 throw MathExc("TArray<T>::DivCst(T,res) - Divide by zero ! ");
662 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
663 bool smo;
664 if (!CompareSizes(res, smo))
665 throw(SzMismatchError("TArray<T>::DivCst(T, res) SizeMismatch(this,res) ")) ;
666
667 const T * pe;
668 T * per;
669 sa_size_t j,k;
670 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
671 sa_size_t maxx = totsize_;
672 pe = Data();
673 per = res.Data();
674 if (!fginv)
675 for(k=0; k<maxx; k++) *per++ = *pe++ / x;
676 else
677 for(k=0; k<maxx; k++) *per++ = x / *pe++;
678 }
679 else { // Non regular data spacing ...
680 int_4 ax,axr;
681 sa_size_t step, stepr;
682 sa_size_t gpas, naxa;
683 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
684 for(j=0; j<naxa; j++) {
685 pe = mNDBlock.Begin()+Offset(ax,j);
686 per = res.DataBlock().Begin()+res.Offset(axr,j);
687 if (!fginv)
688 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)/x;
689 else
690 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x/(*pe);
691 }
692 }
693 return(res);
694}
695
696
697//! Stores the opposite of the source array in \b res (res=-(*this)).
698/*!
699If not initially allocated, the output array \b res is automatically
700resized as a packed array with the same sizes as the source (this) array.
701Returns a reference to the output array \b res.
702*/
703template <class T>
704TArray<T>& TArray<T>::NegateElt(TArray<T>& res) const
705{
706 if (NbDimensions() < 1)
707 throw RangeCheckError("TArray<T>::NegateElt(res) - Not allocated source array ");
708 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
709 bool smo;
710 if (!CompareSizes(res, smo))
711 throw(SzMismatchError("TArray<T>::NegateElt(res) SizeMismatch(this,res) ")) ;
712
713 const T * pe;
714 T * per;
715 sa_size_t j,k;
716 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
717 sa_size_t maxx = totsize_;
718 pe = Data();
719 per = res.Data();
720 for(k=0; k<maxx; k++) *per++ = -(*pe++);
721 }
722 else { // Non regular data spacing ...
723 int_4 ax,axr;
724 sa_size_t step, stepr;
725 sa_size_t gpas, naxa;
726 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
727 for(j=0; j<naxa; j++) {
728 pe = mNDBlock.Begin()+Offset(ax,j);
729 per = res.DataBlock().Begin()+res.Offset(axr,j);
730 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = -(*pe);
731 }
732 }
733 return(res);
734}
735
736// >>>> Operations avec 2nd membre de type tableau
737
738//! Two TArrays element by element addition
739/*!
740Perform element by element addition of the source array (this) and the \b a array
741and store the result in \b res (res = *this+a). The source and argument arrays (this, a)
742should have the same sizes.
743If not initially allocated, the output array \b res is automatically
744resized as a packed array with the same sizes as the source (this) array.
745Returns a reference to the output array \b res.
746\param a : Array to be added to the source array.
747\param res : Output array containing the result (res=this+a).
748*/
749template <class T>
750TArray<T>& TArray<T>::AddElt(const TArray<T>& a, TArray<T>& res) const
751{
752 if (NbDimensions() < 1)
753 throw RangeCheckError("TArray<T>::AddElt(...) - Not allocated source array ! ");
754 bool smoa;
755 if (!CompareSizes(a, smoa))
756 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,a)")) ;
757 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
758 bool smor;
759 if (!CompareSizes(res, smor))
760 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,res) ")) ;
761
762 bool smora;
763 a.CompareSizes(res, smora);
764
765 bool smo = smoa && smor; // The three arrays have same memory organisation
766
767 const T * pe;
768 const T * pea;
769 T * per;
770 sa_size_t j,k;
771 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
772 sa_size_t maxx = totsize_;
773 pe = Data();
774 pea = a.Data();
775 per = res.Data();
776 // for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe + *pea ;
777 for(k=0; k<maxx; k++) *per++ = *pe++ + *pea++ ;
778 }
779 else { // Non regular data spacing ...
780 int_4 ax,axa,axr;
781 sa_size_t step, stepa;
782 sa_size_t gpas, naxa;
783 sa_size_t stepr, stgpas;
784 if ( !smo && smora ) { // same mem-org for a,res , different from this
785 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
786 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
787 stgpas = stepa;
788 }
789 else { // same mem-org for all, or same (this,a) OR same(this,res)
790 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
791 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
792 stgpas = step;
793 }
794 for(j=0; j<naxa; j++) {
795 pe = mNDBlock.Begin()+Offset(ax,j);
796 pea = a.DataBlock().Begin()+a.Offset(axa,j);
797 per = res.DataBlock().Begin()+res.Offset(axr,j);
798 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe + *pea ;
799 }
800 }
801 return(res);
802}
803
804//! Two TArrays element by element subtraction
805/*!
806Perform element by element subtraction of the source array (this) and the \b a array
807and the store result in \b res (res = *this-a or res=a-(*this)).
808The source and argument arrays (this, a) should have the same sizes.
809If not initially allocated, the output array \b res is automatically
810resized as a packed array with the same sizes as the source (this) array.
811Returns a reference to the output array \b res.
812\param a : Array to be added to the source array.
813\param res : Output array containing the result (res=*this+x).
814\param fginv == true : Invert subtraction argument order (res = a-(*this))
815*/
816
817template <class T>
818TArray<T>& TArray<T>::SubElt(const TArray<T>& a, TArray<T>& res, bool fginv) const
819{
820 if (NbDimensions() < 1)
821 throw RangeCheckError("TArray<T>::SubElt(...) - Not allocated source array ! ");
822 bool smoa;
823 if (!CompareSizes(a, smoa))
824 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,a)")) ;
825 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
826 bool smor;
827 if (!CompareSizes(res, smor))
828 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,res) ")) ;
829
830 bool smora;
831 a.CompareSizes(res, smora);
832
833 bool smo = smoa && smor; // The three arrays have same memory organisation
834
835 const T * pe;
836 const T * pea;
837 T * per;
838 sa_size_t j,k;
839 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
840 sa_size_t maxx = totsize_;
841 pe = Data();
842 pea = a.Data();
843 per = res.Data();
844 if (!fginv)
845 for(k=0; k<maxx; k++) *per++ = *pe++ - *pea++ ;
846 else
847 for(k=0; k<maxx; k++) *per++ = *pea++ - *pe++ ;
848 }
849 else { // Non regular data spacing ...
850 int_4 ax,axa,axr;
851 sa_size_t step, stepa;
852 sa_size_t gpas, naxa;
853 sa_size_t stepr, stgpas;
854 if ( !smo && smora ) { // same mem-org for a,res , different from this
855 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
856 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
857 stgpas = stepa;
858 }
859 else { // same mem-org for all, or same (this,a) OR same(this,res)
860 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
861 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
862 stgpas = step;
863 }
864 for(j=0; j<naxa; j++) {
865 pe = mNDBlock.Begin()+Offset(ax,j);
866 pea = a.DataBlock().Begin()+a.Offset(axa,j);
867 per = res.DataBlock().Begin()+res.Offset(axr,j);
868 if (!fginv)
869 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe - *pea ;
870 else
871 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pea - *pea ;
872 }
873 }
874 return(res);
875}
876
877
878//! Two TArrays element by element multiplication
879/*!
880Perform element by element multiplication of the source array (this) and the \b a array
881and store the result in \b res (res = *this*a). The source and argument arrays (this, a)
882should have the same sizes.
883If not initially allocated, the output array \b res is automatically
884resized as a packed array with the same sizes as the source (this) array.
885Returns a reference to the output array \b res.
886\param a : Array to be added to the source array.
887\param res : Output array containing the result (res=(*this)*a).
888*/
889template <class T>
890TArray<T>& TArray<T>::MulElt(const TArray<T>& a, TArray<T>& res) const
891{
892 if (NbDimensions() < 1)
893 throw RangeCheckError("TArray<T>::MulElt(...) - Not allocated source array ! ");
894 bool smoa;
895 if (!CompareSizes(a, smoa))
896 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,a)")) ;
897 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
898 bool smor;
899 if (!CompareSizes(res, smor))
900 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,res) ")) ;
901
902 bool smora;
903 a.CompareSizes(res, smora);
904
905 bool smo = smoa && smor; // The three arrays have same memory organisation
906
907 const T * pe;
908 const T * pea;
909 T * per;
910 sa_size_t j,k;
911 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
912 sa_size_t maxx = totsize_;
913 pe = Data();
914 pea = a.Data();
915 per = res.Data();
916 for(k=0; k<maxx; k++) *per++ = *pe++ * *pea++ ;
917 }
918 else { // Non regular data spacing ...
919 int_4 ax,axa,axr;
920 sa_size_t step, stepa;
921 sa_size_t gpas, naxa;
922 sa_size_t stepr, stgpas;
923 if ( !smo && smora ) { // same mem-org for a,res , different from this
924 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
925 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
926 stgpas = stepa;
927 }
928 else { // same mem-org for all, or same (this,a) OR same(this,res)
929 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
930 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
931 stgpas = step;
932 }
933 for(j=0; j<naxa; j++) {
934 pe = mNDBlock.Begin()+Offset(ax,j);
935 pea = a.DataBlock().Begin()+a.Offset(axa,j);
936 per = res.DataBlock().Begin()+res.Offset(axr,j);
937 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = (*pe) * (*pea);
938 }
939 }
940 return(res);
941}
942
943
944//! Two TArrays element by element division
945/*!
946Perform element by element division of the source array (this) and the \b a array
947and store the result in \b res (res = *this/a). The source and argument arrays (this, a)
948should have the same sizes.
949If not initially allocated, the output array \b res is automatically
950resized as a packed array with the same sizes as the source (this) array.
951Returns a reference to the output array \b res.
952\param a : Array to be added to the source array.
953\param res : Output array containing the result (res=*this/a).
954\param fginv == true : Inverts the division argument order (res = a/(*this))
955\param divzero == true : Result is set to zero (res(i)=0) if the operation's
956second argument is equal to zero (a(i)/(*this)(i)==0)
957*/
958template <class T>
959TArray<T>& TArray<T>::DivElt(const TArray<T>& a, TArray<T>& res, bool fginv, bool divzero) const
960{
961 if (NbDimensions() < 1)
962 throw RangeCheckError("TArray<T>::DivElt(...) - Not allocated source array ! ");
963 bool smoa;
964 if (!CompareSizes(a, smoa))
965 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,a)")) ;
966 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
967 bool smor;
968 if (!CompareSizes(res, smor))
969 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,res) ")) ;
970
971 bool smora;
972 a.CompareSizes(res, smora);
973
974 bool smo = smoa && smor; // The three arrays have same memory organisation
975
976 const T * pe;
977 const T * pea;
978 T * per;
979 sa_size_t j,k;
980 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
981 sa_size_t maxx = totsize_;
982 pe = Data();
983 pea = a.Data();
984 per = res.Data();
985 if(divzero) {
986 if (!fginv)
987 for(k=0; k<maxx; k++)
988 if (*pea==(T)0) *per = (T)0; else *per++ = *pe++ / *pea++ ;
989 else
990 for(k=0; k<maxx; k++)
991 if (*pe==(T)0) *per = (T)0; else *per++ = *pea++ / *pe++ ;
992 }
993 else {
994 if (!fginv)
995 for(k=0; k<maxx; k++) *per++ = *pe++ / *pea++ ;
996 else
997 for(k=0; k<maxx; k++) *per = *pea++ / *pe++ ;
998 }
999 }
1000 else { // Non regular data spacing ...
1001 int_4 ax,axa,axr;
1002 sa_size_t step, stepa;
1003 sa_size_t gpas, naxa;
1004 sa_size_t stepr, stgpas;
1005 if ( !smo && smora ) { // same mem-org for a,res , different from this
1006 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
1007 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
1008 stgpas = stepa;
1009 }
1010 else { // same mem-org for all, or same (this,a) OR same(this,res)
1011 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1012 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
1013 stgpas = step;
1014 }
1015 // DBG cout << "DBG-A-DIVELT naxa=" << naxa << " gpas= " << gpas
1016 // << " step=" << step << " stepa=" << stepa << " stepr=" << stepr
1017 // << " ax= " << ax << " axa= " << axa << " axr= " << axr << endl;
1018 for(j=0; j<naxa; j++) {
1019 pe = mNDBlock.Begin()+Offset(ax,j);
1020 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1021 per = res.DataBlock().Begin()+res.Offset(axr,j);
1022 if(divzero) {
1023 if (!fginv)
1024 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1025 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
1026 else
1027 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1028 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
1029 }
1030 else {
1031 if (!fginv)
1032 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1033 *per = *pe / *pea ;
1034 else
1035 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1036 *per = *pea / *pe ;
1037 }
1038 }
1039 }
1040 return(res);
1041}
1042
1043
1044//! Copy elements of \b a
1045template <class T>
1046TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
1047{
1048 if (NbDimensions() < 1)
1049 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1050 bool smo;
1051 if (!CompareSizes(a, smo))
1052 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
1053
1054 T * pe;
1055 const T * pea;
1056 sa_size_t j,k;
1057 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
1058 if (IsPacked() && a.IsPacked()) memcpy(Data(), a.Data(), totsize_*sizeof(T)); // Packed arrays
1059 else {
1060 sa_size_t step = AvgStep();
1061 sa_size_t stepa = a.AvgStep();
1062 sa_size_t maxx = totsize_*step;
1063 pe = Data();
1064 pea = a.Data();
1065 for(k=0; k<maxx; k+=step, pe+=step, pea+=stepa ) *pe = *pea ;
1066 }
1067 }
1068 else { // Non regular data spacing ...
1069 int_4 ax,axa;
1070 sa_size_t step, stepa;
1071 sa_size_t gpas, naxa;
1072 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1073 for(j=0; j<naxa; j++) {
1074 pe = mNDBlock.Begin()+Offset(ax,j);
1075 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1076 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) *pe = *pea;
1077 }
1078 }
1079 return(*this);
1080}
1081
1082//! Converts and Copy elements of \b a
1083template <class T>
1084TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
1085{
1086 if (NbDimensions() < 1)
1087 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1088 bool smo;
1089 if (!CompareSizes(a, smo))
1090 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
1091
1092 T * pe;
1093 sa_size_t j,k,ka;
1094 sa_size_t offa;
1095 // Non regular data spacing ...
1096 int_4 ax,axa;
1097 sa_size_t step, stepa;
1098 sa_size_t gpas, naxa;
1099 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1100 for(j=0; j<naxa; j++) {
1101 pe = mNDBlock.Begin()+Offset(ax,j);
1102 offa = a.Offset(axa,j);
1103/*
1104 Appel explicite de l'operateur de conversion
1105 suite a la suggestion de M. Reinecke, Reza 31/7/2002
1106#if !defined(__GNUG__)
1107 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
1108#else
1109 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
1110 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
1111#endif
1112 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
1113*/
1114 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
1115 pe[k] = a.ValueAtPosition(offa+ka).operator T();
1116 }
1117 return(*this);
1118}
1119
1120//! Return the the scalar product of the two arrays (Sum_k[(*this)(k)*a(k)])
1121template <class T>
1122T TArray<T>::ScalarProduct(const TArray<T>& a) const
1123{
1124 if (NbDimensions() < 1)
1125 throw RangeCheckError("TArray<T>::ScalarProduct(...) - Not allocated source array ");
1126 bool smo;
1127 if (!CompareSizes(a, smo))
1128 throw(SzMismatchError("TArray<T>::ScalarProduct(...) SizeMismatch(this,a) ")) ;
1129
1130 T res = (T)(0);
1131 const T * pe;
1132 const T * pea;
1133 sa_size_t j,k;
1134 if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements
1135 sa_size_t maxx = totsize_;
1136 pe = Data();
1137 pea = a.Data();
1138 for(k=0; k<maxx; k++) res += *pe++ * *pea++;
1139 }
1140 else { // Non regular data spacing ...
1141 int_4 ax,axa;
1142 sa_size_t step, stepa;
1143 sa_size_t gpas, naxa;
1144 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1145 for(j=0; j<naxa; j++) {
1146 pe = mNDBlock.Begin()+Offset(ax,j);
1147 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1148 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) res += (*pe)*(*pea);
1149 }
1150 }
1151 return(res);
1152}
1153
1154
1155// Somme et produit des elements
1156//! Returns the sum of all array elements
1157template <class T>
1158T TArray<T>::Sum() const
1159{
1160 if (NbDimensions() < 1)
1161 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
1162 T ret=0;
1163 const T * pe;
1164 sa_size_t j,k;
1165 if (AvgStep() > 0) { // regularly spaced elements
1166 sa_size_t step = AvgStep();
1167 sa_size_t maxx = totsize_*step;
1168 pe = Data();
1169 for(k=0; k<maxx; k+=step ) ret += pe[k];
1170 }
1171 else { // Non regular data spacing ...
1172 int_4 ka = MaxSizeKA();
1173 sa_size_t step = Step(ka);
1174 sa_size_t gpas = Size(ka)*step;
1175 sa_size_t naxa = Size()/Size(ka);
1176 for(j=0; j<naxa; j++) {
1177 pe = mNDBlock.Begin()+Offset(ka,j);
1178 for(k=0; k<gpas; k+=step) ret += pe[k] ;
1179 }
1180 }
1181 return ret;
1182}
1183
1184//! Return the product of all elements
1185template <class T>
1186T TArray<T>::Product() const
1187{
1188 if (NbDimensions() < 1)
1189 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
1190 T ret=(T)1;
1191 const T * pe;
1192 sa_size_t j,k;
1193 if (AvgStep() > 0) { // regularly spaced elements
1194 sa_size_t step = AvgStep();
1195 sa_size_t maxx = totsize_*step;
1196 pe = Data();
1197 for(k=0; k<maxx; k+=step ) ret *= pe[k];
1198 }
1199 else { // Non regular data spacing ...
1200 int_4 ka = MaxSizeKA();
1201 sa_size_t step = Step(ka);
1202 sa_size_t gpas = Size(ka)*step;
1203 sa_size_t naxa = Size()/Size(ka);
1204 for(j=0; j<naxa; j++) {
1205 pe = mNDBlock.Begin()+Offset(ka,j);
1206 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
1207 }
1208 }
1209 return ret;
1210}
1211
1212//! Returns the sum of all array elements squared (Sum_k((*this)(k)*(*this)(k)).
1213template <class T>
1214T TArray<T>::SumX2() const
1215{
1216 if (NbDimensions() < 1)
1217 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
1218 T ret=0;
1219 const T * pe;
1220 sa_size_t j,k;
1221 if (AvgStep() > 0) { // regularly spaced elements
1222 sa_size_t step = AvgStep();
1223 sa_size_t maxx = totsize_*step;
1224 pe = Data();
1225 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
1226 }
1227 else { // Non regular data spacing ...
1228 int_4 ka = MaxSizeKA();
1229 sa_size_t step = Step(ka);
1230 sa_size_t gpas = Size(ka)*step;
1231 sa_size_t naxa = Size()/Size(ka);
1232 for(j=0; j<naxa; j++) {
1233 pe = mNDBlock.Begin()+Offset(ka,j);
1234 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
1235 }
1236 }
1237 return ret;
1238}
1239
1240//! Return the minimum and the maximum values of the array elements
1241/*!
1242 This method generates an exception (\c MathExc) if called for complex arrays
1243*/
1244
1245template <class T>
1246void TArray<T>::MinMax(T& min, T& max) const
1247{
1248 const T * pe;
1249 sa_size_t j,k;
1250 int_4 ka = MaxSizeKA();
1251 sa_size_t step = Step(ka);
1252 sa_size_t gpas = Size(ka)*step;
1253 sa_size_t naxa = Size()/Size(ka);
1254 min = (*this)[0];
1255 max = (*this)[0];
1256 for(j=0; j<naxa; j++) {
1257 pe = mNDBlock.Begin()+Offset(ka,j);
1258 for(k=0; k<gpas; k+=step) {
1259 if (pe[k]<min) min = pe[k];
1260 else if (pe[k]>max) max = pe[k];
1261 }
1262 }
1263 return;
1264}
1265
1266DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1267void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
1268{
1269 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1270}
1271DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1272void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
1273{
1274 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1275}
1276
1277
1278// ----------------------------------------------------
1279// Impression, etc ...
1280// ----------------------------------------------------
1281
1282//! Return a string that contain the type \b T of the array
1283template <class T>
1284string TArray<T>::InfoString() const
1285{
1286 string rs = "TArray<" ;
1287 rs += typeid(T).name();
1288 rs += "> ";
1289 return(rs);
1290}
1291
1292//! Print array
1293/*!
1294 \param os : output stream
1295 \param maxprt : maximum numer of print
1296 \param si : if true, display attached DvList
1297 \param ascd : if true, suppresses the display of line numbers,
1298 suitable for ascii dump format.
1299 \sa SetMaxPrint
1300 \sa WriteASCII
1301 */
1302template <class T>
1303void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
1304{
1305 if (maxprt < 0) maxprt = max_nprt_;
1306 sa_size_t npr = 0;
1307 // keep stream's io flags
1308 // ios_base::fmtflags ioflg = os.flags(); compile pas sur OSF-cxx
1309 // os << right ; compile pas sur OSF-cxx
1310
1311 Show(os, si);
1312 if (ndim_ < 1) return;
1313
1314 // Calcul de la largeur d'impression pour chaque element
1315 int fprtw = os.precision()+7;
1316 int prtw = 5;
1317
1318 if ( (typeid(T) == typeid( int_4 )) || (typeid(T) == typeid( uint_4 )) ) prtw = 8;
1319 else if ( (typeid(T) == typeid( int_8 )) || (typeid(T) == typeid( uint_8 )) ) prtw = 11;
1320 else if ( typeid(T) == typeid( r_4 ) ) prtw = fprtw;
1321 else if ( typeid(T) == typeid( r_8 ) ) prtw = fprtw;
1322 else if ( typeid(T) == typeid(complex<r_4>) ) prtw = fprtw;
1323 else if ( typeid(T) == typeid(complex<r_8>) ) prtw = fprtw;
1324
1325
1326 sa_size_t k0,k1,k2,k3,k4;
1327 for(k4=0; k4<size_[4]; k4++) {
1328 if ((size_[4] > 1) && !ascd)
1329 os << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
1330 for(k3=0; k3<size_[3]; k3++) {
1331 if ((size_[3] > 1) && !ascd)
1332 os << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
1333 for(k2=0; k2<size_[2]; k2++) {
1334 if ((size_[2] > 1) && !ascd)
1335 os << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
1336 for(k1=0; k1<size_[1]; k1++) {
1337 if ( (size_[1] > 1) && (size_[0] > 10) && !ascd)
1338 os << "----- Dimension 2 (Y) K1= " << k1 << endl;
1339 for(k0=0; k0<size_[0]; k0++) {
1340 if(k0 > 0) os << " ";
1341 os << setw(prtw) << Elem(k0, k1, k2, k3, k4); npr++;
1342 if (npr >= (sa_size_t) maxprt) {
1343 if (npr < totsize_) os << "\n .... " << endl; return;
1344 }
1345 }
1346 os << endl;
1347 }
1348 }
1349 }
1350 }
1351 os << endl;
1352 //compile pas sur OSF-cxx os.flags(ioflg); // reset stream io flags
1353}
1354
1355//! Fill the array, decoding the ASCII input stream
1356/*!
1357 \param is : input stream (ASCII)
1358 \param nr : Number of non empty (or comment) lines in stream (return value)
1359 \param nc : Number of columns (= ntot/nlines) (return value)
1360 \param clm : Lines starting with clm character are treated as comment lines
1361 \param sep : word separator in lines
1362 \return Number of decoded elements
1363*/
1364template <class T>
1365sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc,
1366 char clm, const char* sep)
1367{
1368 EnumeratedSequence es;
1369 sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep);
1370 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1371 if (!IsAllocated()) {
1372 sa_size_t sz[2];
1373 if (arrtype_ == 2) { // C'est un vecteur
1374 sz[0] = sz[1] = 1;
1375 sz[veceli_] = n;
1376 }
1377 else {
1378 sz[RowsKA()] = nr;
1379 sz[ColsKA()] = nc;
1380 }
1381 ReSize(2, sz);
1382 }
1383 SetSeq(es);
1384 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1385 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1386 return(n);
1387}
1388
1389//! Writes the array content to the output stream, (in ASCII)
1390/*!
1391 \param os : output stream (ASCII)
1392 \sa Print
1393 */
1394template <class T>
1395void TArray<T>::WriteASCII(ostream& os) const
1396{
1397 Print(os, Size(), false, true);
1398}
1399
1400
1401
1402///////////////////////////////////////////////////////////////
1403///////////////////////////////////////////////////////////////
1404#ifdef __CXX_PRAGMA_TEMPLATES__
1405/*
1406#pragma define_template TArray<uint_1>
1407#pragma define_template TArray<int_2>
1408#pragma define_template TArray<uint_4>
1409*/
1410#pragma define_template TArray<uint_2>
1411#pragma define_template TArray<uint_8>
1412#pragma define_template TArray<int_4>
1413#pragma define_template TArray<int_8>
1414#pragma define_template TArray<r_4>
1415#pragma define_template TArray<r_8>
1416#pragma define_template TArray< complex<r_4> >
1417#pragma define_template TArray< complex<r_8> >
1418#endif
1419
1420#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1421/*
1422template class TArray<uint_1>;
1423template class TArray<int_2>;
1424template class TArray<uint_4>;
1425*/
1426template class TArray<uint_2>;
1427template class TArray<uint_8>;
1428template class TArray<int_4>;
1429template class TArray<int_8>;
1430template class TArray<r_4>;
1431template class TArray<r_8>;
1432template class TArray< complex<r_4> >;
1433template class TArray< complex<r_8> >;
1434#endif
1435
1436
Note: See TracBrowser for help on using the repository browser.