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

Last change on this file since 2743 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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