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

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

Modifs pour compilation avec g++ 4 (V >= 3.4) - Reza 4 Jan 2006

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