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

Last change on this file since 2608 was 2589, checked in by ansari, 21 years ago

Correction petite faute de frappe (bug) trouve par compilateur g++ / Reza 30 Juillet 2004

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