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

Last change on this file since 2585 was 2575, checked in by ansari, 21 years ago

1/ Remplacement des methodes Add/Sub/Mul/DivElt(a) par

Add/Sub/Mul/DivElt(TArray a, TArray res)

2/ Operateurs += -= A+B A-B TArray et TMatrix/TVecteur modifies en consequence
3/ Ajout methode TArray::ScalarProduct()
4/ Methode TArray::SetT renomme en SetCst() SetT garde en alias
5/ Ajout parametre bool fzero (mise a zero) ajoute ds constructeur et

ReSize() de TMatrix et TVecteur.

Reza 29/07/2004

File size: 45.4 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; per++; pe++; }
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; per++; pe++; }
580 else
581 for(k=0; k<maxx; k++) { *per = x-(*pe); per++; 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; per++; pe++; }
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,kr;
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; per++; pe++; }
673 else
674 for(k=0; k<maxx; k++) { *per = x/(*pe); per++; 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); 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 }
775 else { // Non regular data spacing ...
776 int_4 ax,axa,axr;
777 sa_size_t step, stepa;
778 sa_size_t gpas, naxa;
779 sa_size_t stepr, stgpas;
780 if ( !smo && smora ) { // same mem-org for a,res , different from this
781 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
782 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
783 stgpas = stepa;
784 }
785 else { // same mem-org for all, or same (this,a) OR same(this,res)
786 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
787 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
788 stgpas = step;
789 }
790 for(j=0; j<naxa; j++) {
791 pe = mNDBlock.Begin()+Offset(ax,j);
792 pea = a.DataBlock().Begin()+a.Offset(axa,j);
793 per = res.DataBlock().Begin()+res.Offset(axr,j);
794 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe + *pea ;
795 }
796 }
797 return(res);
798}
799
800//! Two TArrays element by element subtraction
801/*!
802Perform element by element subtraction of the source array (this) and the \b a array
803and the store result in \b res (res = *this-a or res=a-(*this)).
804The source and argument arrays (this, a) should have the same sizes.
805If not initially allocated, the output array \b res is automatically
806resized as a packed array with the same sizes as the source (this) array.
807Returns a reference to the output array \b res.
808\param a : Array to be added to the source array.
809\param res : Output array containing the result (res=*this+x).
810\param fginv == true : Invert subtraction argument order (res = a-(*this))
811*/
812
813template <class T>
814TArray<T>& TArray<T>::SubElt(const TArray<T>& a, TArray<T>& res, bool fginv) const
815{
816 if (NbDimensions() < 1)
817 throw RangeCheckError("TArray<T>::SubElt(...) - Not allocated source array ! ");
818 bool smoa;
819 if (!CompareSizes(a, smoa))
820 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,a)")) ;
821 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
822 bool smor;
823 if (!CompareSizes(res, smor))
824 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,res) ")) ;
825
826 bool smora;
827 a.CompareSizes(res, smora);
828
829 bool smo = smoa && smor; // The three arrays have same memory organisation
830
831 const T * pe;
832 const T * pea;
833 T * per;
834 sa_size_t j,k;
835 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
836 sa_size_t maxx = totsize_;
837 pe = Data();
838 pea = a.Data();
839 per = res.Data();
840 if (!fginv)
841 for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe - *pea ;
842 else
843 for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pea - *pe ;
844 }
845 else { // Non regular data spacing ...
846 int_4 ax,axa,axr;
847 sa_size_t step, stepa;
848 sa_size_t gpas, naxa;
849 sa_size_t stepr, stgpas;
850 if ( !smo && smora ) { // same mem-org for a,res , different from this
851 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
852 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
853 stgpas = stepa;
854 }
855 else { // same mem-org for all, or same (this,a) OR same(this,res)
856 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
857 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
858 stgpas = step;
859 }
860 for(j=0; j<naxa; j++) {
861 pe = mNDBlock.Begin()+Offset(ax,j);
862 pea = a.DataBlock().Begin()+a.Offset(axa,j);
863 per = res.DataBlock().Begin()+res.Offset(axr,j);
864 if (!fginv)
865 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe - *pea ;
866 else
867 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pea - *pea ;
868 }
869 }
870 return(res);
871}
872
873
874//! Two TArrays element by element multiplication
875/*!
876Perform element by element multiplication of the source array (this) and the \b a array
877and store the result in \b res (res = *this*a). The source and argument arrays (this, a)
878should have the same sizes.
879If not initially allocated, the output array \b res is automatically
880resized as a packed array with the same sizes as the source (this) array.
881Returns a reference to the output array \b res.
882\param a : Array to be added to the source array.
883\param res : Output array containing the result (res=(*this)*a).
884*/
885template <class T>
886TArray<T>& TArray<T>::MulElt(const TArray<T>& a, TArray<T>& res) const
887{
888 if (NbDimensions() < 1)
889 throw RangeCheckError("TArray<T>::MulElt(...) - Not allocated source array ! ");
890 bool smoa;
891 if (!CompareSizes(a, smoa))
892 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,a)")) ;
893 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
894 bool smor;
895 if (!CompareSizes(res, smor))
896 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,res) ")) ;
897
898 bool smora;
899 a.CompareSizes(res, smora);
900
901 bool smo = smoa && smor; // The three arrays have same memory organisation
902
903 const T * pe;
904 const T * pea;
905 T * per;
906 sa_size_t j,k;
907 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
908 sa_size_t maxx = totsize_;
909 pe = Data();
910 pea = a.Data();
911 per = res.Data();
912 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = (*pe) * (*pea) ;
913 }
914 else { // Non regular data spacing ...
915 int_4 ax,axa,axr;
916 sa_size_t step, stepa;
917 sa_size_t gpas, naxa;
918 sa_size_t stepr, stgpas;
919 if ( !smo && smora ) { // same mem-org for a,res , different from this
920 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
921 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
922 stgpas = stepa;
923 }
924 else { // same mem-org for all, or same (this,a) OR same(this,res)
925 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
926 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
927 stgpas = step;
928 }
929 for(j=0; j<naxa; j++) {
930 pe = mNDBlock.Begin()+Offset(ax,j);
931 pea = a.DataBlock().Begin()+a.Offset(axa,j);
932 per = res.DataBlock().Begin()+res.Offset(axr,j);
933 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = (*pe) * (*pea);
934 }
935 }
936 return(res);
937}
938
939
940//! Two TArrays element by element division
941/*!
942Perform element by element division of the source array (this) and the \b a array
943and store the result in \b res (res = *this/a). The source and argument arrays (this, a)
944should have the same sizes.
945If not initially allocated, the output array \b res is automatically
946resized as a packed array with the same sizes as the source (this) array.
947Returns a reference to the output array \b res.
948\param a : Array to be added to the source array.
949\param res : Output array containing the result (res=*this/a).
950\param fginv == true : Inverts the division argument order (res = a/(*this))
951\param divzero == true : Result is set to zero (res(i)=0) if the operation's
952second argument is equal to zero (a(i)/(*this)(i)==0)
953*/
954template <class T>
955TArray<T>& TArray<T>::DivElt(const TArray<T>& a, TArray<T>& res, bool fginv, bool divzero) const
956{
957 if (NbDimensions() < 1)
958 throw RangeCheckError("TArray<T>::DivElt(...) - Not allocated source array ! ");
959 bool smoa;
960 if (!CompareSizes(a, smoa))
961 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,a)")) ;
962 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
963 bool smor;
964 if (!CompareSizes(res, smor))
965 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,res) ")) ;
966
967 bool smora;
968 a.CompareSizes(res, smora);
969
970 bool smo = smoa && smor; // The three arrays have same memory organisation
971
972 const T * pe;
973 const T * pea;
974 T * per;
975 sa_size_t j,k;
976 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
977 sa_size_t maxx = totsize_;
978 pe = Data();
979 pea = a.Data();
980 per = res.Data();
981 if(divzero) {
982 if (!fginv)
983 for(k=0; k<maxx; k++, pe++, pea++, per++ )
984 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
985 else
986 for(k=0; k<maxx; k++, pe++, pea++, per++ )
987 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
988 }
989 else {
990 if (!fginv)
991 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = *pe / *pea ;
992 else
993 for(k=0; k<maxx; k++, pe++, pea++, per++ ) *per = *pea / *pe ;
994 }
995 }
996 else { // Non regular data spacing ...
997 int_4 ax,axa,axr;
998 sa_size_t step, stepa;
999 sa_size_t gpas, naxa;
1000 sa_size_t stepr, stgpas;
1001 if ( !smo && smora ) { // same mem-org for a,res , different from this
1002 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
1003 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
1004 stgpas = stepa;
1005 }
1006 else { // same mem-org for all, or same (this,a) OR same(this,res)
1007 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1008 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
1009 stgpas = step;
1010 }
1011 // DBG cout << "DBG-A-DIVELT naxa=" << naxa << " gpas= " << gpas
1012 // << " step=" << step << " stepa=" << stepa << " stepr=" << stepr
1013 // << " ax= " << ax << " axa= " << axa << " axr= " << axr << endl;
1014 for(j=0; j<naxa; j++) {
1015 pe = mNDBlock.Begin()+Offset(ax,j);
1016 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1017 per = res.DataBlock().Begin()+res.Offset(axr,j);
1018 if(divzero) {
1019 if (!fginv)
1020 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1021 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
1022 else
1023 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1024 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
1025 }
1026 else {
1027 if (!fginv)
1028 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1029 *per = *pe / *pea ;
1030 else
1031 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1032 *per = *pea / *pe ;
1033 }
1034 }
1035 }
1036 return(res);
1037}
1038
1039
1040//! Copy elements of \b a
1041template <class T>
1042TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
1043{
1044 if (NbDimensions() < 1)
1045 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1046 bool smo;
1047 if (!CompareSizes(a, smo))
1048 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
1049
1050 T * pe;
1051 const T * pea;
1052 sa_size_t j,k;
1053 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
1054 sa_size_t step = AvgStep();
1055 sa_size_t stepa = a.AvgStep();
1056 sa_size_t maxx = totsize_*step;
1057 pe = Data();
1058 pea = a.Data();
1059 for(k=0; k<maxx; k+=step, pe+=step, pea+=stepa ) *pe = *pea ;
1060 }
1061 else { // Non regular data spacing ...
1062 int_4 ax,axa;
1063 sa_size_t step, stepa;
1064 sa_size_t gpas, naxa;
1065 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1066 for(j=0; j<naxa; j++) {
1067 pe = mNDBlock.Begin()+Offset(ax,j);
1068 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1069 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) *pe = *pea;
1070 }
1071 }
1072 return(*this);
1073}
1074
1075//! Converts and Copy elements of \b a
1076template <class T>
1077TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
1078{
1079 if (NbDimensions() < 1)
1080 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1081 bool smo;
1082 if (!CompareSizes(a, smo))
1083 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
1084
1085 T * pe;
1086 sa_size_t j,k,ka;
1087 sa_size_t offa;
1088 // Non regular data spacing ...
1089 int_4 ax,axa;
1090 sa_size_t step, stepa;
1091 sa_size_t gpas, naxa;
1092 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1093 for(j=0; j<naxa; j++) {
1094 pe = mNDBlock.Begin()+Offset(ax,j);
1095 offa = a.Offset(axa,j);
1096/*
1097 Appel explicite de l'operateur de conversion
1098 suite a la suggestion de M. Reinecke, Reza 31/7/2002
1099#if !defined(__GNUG__)
1100 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
1101#else
1102 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
1103 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
1104#endif
1105 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
1106*/
1107 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
1108 pe[k] = a.ValueAtPosition(offa+ka).operator T();
1109 }
1110 return(*this);
1111}
1112
1113//! Return the the scalar product of the two arrays (Sum_k[(*this)(k)*a(k)])
1114template <class T>
1115T TArray<T>::ScalarProduct(const TArray<T>& a) const
1116{
1117 if (NbDimensions() < 1)
1118 throw RangeCheckError("TArray<T>::ScalarProduct(...) - Not allocated source array ");
1119 bool smo;
1120 if (!CompareSizes(a, smo))
1121 throw(SzMismatchError("TArray<T>::ScalarProduct(...) SizeMismatch(this,a) ")) ;
1122
1123 T res = (T)(0);
1124 const T * pe;
1125 const T * pea;
1126 sa_size_t j,k;
1127 if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements
1128 sa_size_t maxx = totsize_;
1129 pe = Data();
1130 pea = a.Data();
1131 for(k=0; k<maxx; k++, pe++, pea++) res += (*pe)*(*pea);
1132 }
1133 else { // Non regular data spacing ...
1134 int_4 ax,axa;
1135 sa_size_t step, stepa;
1136 sa_size_t gpas, naxa;
1137 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1138 for(j=0; j<naxa; j++) {
1139 pe = mNDBlock.Begin()+Offset(ax,j);
1140 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1141 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) res += (*pe)*(*pea);
1142 }
1143 }
1144 return(res);
1145}
1146
1147
1148// Somme et produit des elements
1149//! Returns the sum of all array elements
1150template <class T>
1151T TArray<T>::Sum() const
1152{
1153 if (NbDimensions() < 1)
1154 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
1155 T ret=0;
1156 const T * pe;
1157 sa_size_t j,k;
1158 if (AvgStep() > 0) { // regularly spaced elements
1159 sa_size_t step = AvgStep();
1160 sa_size_t maxx = totsize_*step;
1161 pe = Data();
1162 for(k=0; k<maxx; k+=step ) ret += pe[k];
1163 }
1164 else { // Non regular data spacing ...
1165 int_4 ka = MaxSizeKA();
1166 sa_size_t step = Step(ka);
1167 sa_size_t gpas = Size(ka)*step;
1168 sa_size_t naxa = Size()/Size(ka);
1169 for(j=0; j<naxa; j++) {
1170 pe = mNDBlock.Begin()+Offset(ka,j);
1171 for(k=0; k<gpas; k+=step) ret += pe[k] ;
1172 }
1173 }
1174 return ret;
1175}
1176
1177//! Return the product of all elements
1178template <class T>
1179T TArray<T>::Product() const
1180{
1181 if (NbDimensions() < 1)
1182 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
1183 T ret=(T)1;
1184 const T * pe;
1185 sa_size_t j,k;
1186 if (AvgStep() > 0) { // regularly spaced elements
1187 sa_size_t step = AvgStep();
1188 sa_size_t maxx = totsize_*step;
1189 pe = Data();
1190 for(k=0; k<maxx; k+=step ) ret *= pe[k];
1191 }
1192 else { // Non regular data spacing ...
1193 int_4 ka = MaxSizeKA();
1194 sa_size_t step = Step(ka);
1195 sa_size_t gpas = Size(ka)*step;
1196 sa_size_t naxa = Size()/Size(ka);
1197 for(j=0; j<naxa; j++) {
1198 pe = mNDBlock.Begin()+Offset(ka,j);
1199 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
1200 }
1201 }
1202 return ret;
1203}
1204
1205//! Returns the sum of all array elements squared (Sum_k((*this)(k)*(*this)(k)).
1206template <class T>
1207T TArray<T>::SumX2() const
1208{
1209 if (NbDimensions() < 1)
1210 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
1211 T ret=0;
1212 const T * pe;
1213 sa_size_t j,k;
1214 if (AvgStep() > 0) { // regularly spaced elements
1215 sa_size_t step = AvgStep();
1216 sa_size_t maxx = totsize_*step;
1217 pe = Data();
1218 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
1219 }
1220 else { // Non regular data spacing ...
1221 int_4 ka = MaxSizeKA();
1222 sa_size_t step = Step(ka);
1223 sa_size_t gpas = Size(ka)*step;
1224 sa_size_t naxa = Size()/Size(ka);
1225 for(j=0; j<naxa; j++) {
1226 pe = mNDBlock.Begin()+Offset(ka,j);
1227 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
1228 }
1229 }
1230 return ret;
1231}
1232
1233//! Return the minimum and the maximum values of the array elements
1234/*!
1235 This method generates an exception (\c MathExc) if called for complex arrays
1236*/
1237
1238template <class T>
1239void TArray<T>::MinMax(T& min, T& max) const
1240{
1241 const T * pe;
1242 sa_size_t j,k;
1243 int_4 ka = MaxSizeKA();
1244 sa_size_t step = Step(ka);
1245 sa_size_t gpas = Size(ka)*step;
1246 sa_size_t naxa = Size()/Size(ka);
1247 min = (*this)[0];
1248 max = (*this)[0];
1249 for(j=0; j<naxa; j++) {
1250 pe = mNDBlock.Begin()+Offset(ka,j);
1251 for(k=0; k<gpas; k+=step) {
1252 if (pe[k]<min) min = pe[k];
1253 else if (pe[k]>max) max = pe[k];
1254 }
1255 }
1256 return;
1257}
1258
1259DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1260void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
1261{
1262 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1263}
1264DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1265void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
1266{
1267 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1268}
1269
1270
1271// ----------------------------------------------------
1272// Impression, etc ...
1273// ----------------------------------------------------
1274
1275//! Return a string that contain the type \b T of the array
1276template <class T>
1277string TArray<T>::InfoString() const
1278{
1279 string rs = "TArray<" ;
1280 rs += typeid(T).name();
1281 rs += "> ";
1282 return(rs);
1283}
1284
1285//! Print array
1286/*!
1287 \param os : output stream
1288 \param maxprt : maximum numer of print
1289 \param si : if true, display attached DvList
1290 \param ascd : if true, suppresses the display of line numbers,
1291 suitable for ascii dump format.
1292 \sa SetMaxPrint
1293 \sa WriteASCII
1294 */
1295template <class T>
1296void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
1297{
1298 if (maxprt < 0) maxprt = max_nprt_;
1299 sa_size_t npr = 0;
1300 Show(os, si);
1301 if (ndim_ < 1) return;
1302 sa_size_t k0,k1,k2,k3,k4;
1303 for(k4=0; k4<size_[4]; k4++) {
1304 if ((size_[4] > 1) && ascd)
1305 cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
1306 for(k3=0; k3<size_[3]; k3++) {
1307 if ((size_[3] > 1) && ascd)
1308 cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
1309 for(k2=0; k2<size_[2]; k2++) {
1310 if ((size_[2] > 1) & ascd)
1311 cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
1312 for(k1=0; k1<size_[1]; k1++) {
1313 if ( (size_[1] > 1) && (size_[0] > 10) && ascd)
1314 cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
1315 for(k0=0; k0<size_[0]; k0++) {
1316 if(k0 > 0) os << " ";
1317 os << Elem(k0, k1, k2, k3, k4); npr++;
1318 if (npr >= (sa_size_t) maxprt) {
1319 if (npr < totsize_) os << "\n .... " << endl; return;
1320 }
1321 }
1322 os << endl;
1323 }
1324 }
1325 }
1326 }
1327 os << endl;
1328}
1329
1330//! Fill the array, decoding the ASCII input stream
1331/*!
1332 \param is : input stream (ASCII)
1333 \param nr : Number of non empty (or comment) lines in stream (return value)
1334 \param nc : Number of columns (= ntot/nlines) (return value)
1335 \param clm : Lines starting with clm character are treated as comment lines
1336 \param sep : word separator in lines
1337 \return Number of decoded elements
1338*/
1339template <class T>
1340sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc,
1341 char clm, const char* sep)
1342{
1343 EnumeratedSequence es;
1344 sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep);
1345 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1346 if (!IsAllocated()) {
1347 sa_size_t sz[2];
1348 if (arrtype_ == 2) { // C'est un vecteur
1349 sz[0] = sz[1] = 1;
1350 sz[veceli_] = n;
1351 }
1352 else {
1353 sz[RowsKA()] = nr;
1354 sz[ColsKA()] = nc;
1355 }
1356 ReSize(2, sz);
1357 }
1358 SetSeq(es);
1359 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1360 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1361 return(n);
1362}
1363
1364//! Writes the array content to the output stream, (in ASCII)
1365/*!
1366 \param os : output stream (ASCII)
1367 \sa Print
1368 */
1369template <class T>
1370void TArray<T>::WriteASCII(ostream& os) const
1371{
1372 Print(os, Size(), false, true);
1373}
1374
1375
1376
1377///////////////////////////////////////////////////////////////
1378///////////////////////////////////////////////////////////////
1379#ifdef __CXX_PRAGMA_TEMPLATES__
1380/*
1381#pragma define_template TArray<uint_1>
1382#pragma define_template TArray<int_2>
1383#pragma define_template TArray<uint_4>
1384*/
1385#pragma define_template TArray<uint_2>
1386#pragma define_template TArray<uint_8>
1387#pragma define_template TArray<int_4>
1388#pragma define_template TArray<int_8>
1389#pragma define_template TArray<r_4>
1390#pragma define_template TArray<r_8>
1391#pragma define_template TArray< complex<r_4> >
1392#pragma define_template TArray< complex<r_8> >
1393#endif
1394
1395#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1396/*
1397template class TArray<uint_1>;
1398template class TArray<int_2>;
1399template class TArray<uint_4>;
1400*/
1401template class TArray<uint_2>;
1402template class TArray<uint_8>;
1403template class TArray<int_4>;
1404template class TArray<int_8>;
1405template class TArray<r_4>;
1406template class TArray<r_8>;
1407template class TArray< complex<r_4> >;
1408template class TArray< complex<r_8> >;
1409#endif
1410
1411
Note: See TracBrowser for help on using the repository browser.