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

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

Amelioration de la classe Range - permettant une valeur symbolique pour specifier le dernier index (last()) - Reza 22/02/2006

File size: 47.7 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/*!
363 \brief Return the value (as a MuTyV) for element at position \b ip in the array.
364 This method is used for conversion between arrays of different types.
365 \param ip : element position in the array
366 */
367template <class T>
368MuTyV & TArray<T>::ValueAtPosition(sa_size_t ip) const
369{
370#ifdef SO_BOUNDCHECKING
371 if ( (ip >= totsize_) || (ip < 0) )
372 throw( ParmError("TArray<T>::ValueAtPosition(sa_size_t ip) Out-of-bound Error") );
373#endif
374 my_mtv = *(mNDBlock.Begin()+Offset(ip));
375 return( my_mtv );
376}
377
378/*!
379 \brief Return the value (as a MuTyV) for element at position \b ip in the datablock.
380 This method is used for conversion between arrays of different types.
381 \param ip : element position in the array DataBlock, regardless of
382 the array memory organisation
383 */
384template <class T>
385MuTyV & TArray<T>::ValueAtPositionDB(sa_size_t ip) const
386{
387#ifdef SO_BOUNDCHECKING
388 if ( (ip >= mNDBlock.Size() ) || (ip < 0) )
389 throw( ParmError("TArray<T>::ValueAtPositionDB(sa_size_t ip) Out-of-bound Error") );
390#endif
391 my_mtv = *(mNDBlock.Begin()+ip);
392 return( my_mtv );
393}
394
395//! Return array with elements packed
396/*!
397 \param force : if true, pack elements in a new array.
398 If false and array is already packed, return
399 an array that share data with the current one.
400 \return packed array
401 */
402template <class T>
403TArray<T> TArray<T>::PackElements(bool force) const
404{
405 if (NbDimensions() < 1)
406 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
407 if ( !force && (AvgStep() == 1) ) {
408 TArray<T> ra;
409 ra.Share(*this);
410 ra.SetTemp(true);
411 return(ra);
412 }
413 else {
414 TArray<T> ra(ndim_, size_, 1);
415 ra.CopyElt(*this);
416 ra.SetTemp(true);
417 return(ra);
418 }
419}
420
421// SubArrays
422// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
423//! Extract a sub-array
424/*!
425 \param rx,ry,rz,rt,ru : range of extraction along dimensions
426 \sa SOPHYA::Range
427 */
428template <class T>
429TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
430{
431 if (NbDimensions() < 1)
432 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
433 int_4 ndim = 0;
434
435 // Updating Range objects using actual array size
436 rx.Update(SizeX());
437 ry.Update(SizeY());
438 rz.Update(SizeZ());
439 if (NbDimensions() > 3) rt.Update(Size(3));
440 else rt.Update(0);
441 if (NbDimensions() > 4) ru.Update(Size(4));
442 else ru.Update(0);
443
444 sa_size_t size[BASEARRAY_MAXNDIMS];
445 sa_size_t step[BASEARRAY_MAXNDIMS];
446 sa_size_t pos[BASEARRAY_MAXNDIMS];
447 size[0] = rx.Size();
448 size[1] = ry.Size();
449 size[2] = rz.Size();
450 size[3] = rt.Size();
451 size[4] = ru.Size();
452
453 step[0] = rx.Step();
454 step[1] = ry.Step();
455 step[2] = rz.Step();
456 step[3] = rt.Step();
457 step[4] = ru.Step();
458
459 pos[0] = rx.Start();
460 pos[1] = ry.Start();
461 pos[2] = rz.Start();
462 pos[3] = rt.Start();
463 pos[4] = ru.Start();
464
465 ndim = ndim_;
466 TArray<T> ra;
467 UpdateSubArraySizes(ra, ndim, size, pos, step);
468 ra.DataBlock().Share(this->DataBlock());
469 ra.SetTemp(true);
470 return(ra);
471}
472
473// ...... Operation de calcul sur les tableaux ......
474// ------- Attention --------
475// Boucles normales prenant en compte les steps ....
476// Possibilite de // , vectorisation
477
478//! Fill TArray with Sequence \b seq
479/*!
480 \param seq : sequence to fill the array
481 \sa Sequence
482 */
483template <class T>
484TArray<T>& TArray<T>::SetSeq(Sequence const & seq)
485{
486 if (NbDimensions() < 1)
487 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
488
489 T * pe;
490 sa_size_t j,k;
491 int_4 ka;
492 if (arrtype_ == 0) ka = 0;
493 else ka = macoli_;
494 sa_size_t step = Step(ka);
495 sa_size_t gpas = Size(ka);
496 sa_size_t naxa = Size()/Size(ka);
497 for(j=0; j<naxa; j++) {
498 pe = mNDBlock.Begin()+Offset(ka,j);
499/*
500 Appel explicite de l'operateur de conversion
501 suite a la suggestion de M. Reinecke, Reza 31/7/2002
502#if !defined(__GNUG__)
503 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
504#else
505 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
506 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k);
507#endif
508 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
509*/
510 for(k=0; k<gpas; k++) seq(j*gpas+k).Convert(pe[k*step]);
511//REMPLACE suite pb compil gcc4 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k).operator T();
512 }
513 return(*this);
514}
515
516// >>>> Operations avec 2nd membre de type scalaire
517
518//! Fill an array with a constant value \b x
519template <class T>
520TArray<T>& TArray<T>::SetCst(T x)
521{
522 if (NbDimensions() < 1)
523 throw RangeCheckError("TArray<T>::SetCst(T ) - Not Allocated Array ! ");
524 T * pe;
525 sa_size_t j,k;
526 if (AvgStep() > 0) { // regularly spaced elements
527 sa_size_t step = AvgStep();
528 sa_size_t maxx = totsize_*step;
529 pe = Data();
530 for(k=0; k<maxx; k+=step ) pe[k] = x;
531 }
532 else { // Non regular data spacing ...
533 int_4 ka = MaxSizeKA();
534 sa_size_t step = Step(ka);
535 sa_size_t gpas = Size(ka)*step;
536 sa_size_t naxa = Size()/Size(ka);
537 for(j=0; j<naxa; j++) {
538 pe = mNDBlock.Begin()+Offset(ka,j);
539 for(k=0; k<gpas; k+=step) pe[k] = x;
540 }
541 }
542 return(*this);
543}
544
545//! Add a constant value \b x to the source array and store the result in \b res.
546/*!
547Add a constant to the source array \b this and store the result in \b res (res = *this+x).
548If not initially allocated, the output array \b res is automatically
549resized as a packed array with the same sizes as the source (this) array.
550Returns a reference to the output array \b res.
551\param x : constant to add to the array elements
552\param res : Output array containing the result (res=this+x).
553*/
554template <class T>
555TArray<T>& TArray<T>::AddCst(T x, TArray<T>& res) const
556{
557 if (NbDimensions() < 1)
558 throw RangeCheckError("TArray<T>::AddCst(T,res) - Not allocated source array ");
559 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
560 bool smo;
561 if (!CompareSizes(res, smo))
562 throw(SzMismatchError("TArray<T>::AddCst(T, res) SizeMismatch(this,res) ")) ;
563
564 const T * pe;
565 T * per;
566 sa_size_t j,k;
567 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
568 sa_size_t maxx = totsize_;
569 pe = Data();
570 per = res.Data();
571 for(k=0; k<maxx; k++) *per++ = *pe++ + x;
572 }
573 else { // Non regular data spacing ...
574 int_4 ax,axr;
575 sa_size_t step, stepr;
576 sa_size_t gpas, naxa;
577 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
578 for(j=0; j<naxa; j++) {
579 pe = mNDBlock.Begin()+Offset(ax,j);
580 per = res.DataBlock().Begin()+res.Offset(axr,j);
581 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe+x;
582 }
583 }
584 return(res);
585}
586
587//! Subtract a constant value \b x from the source array and store the result in \b res.
588/*!
589Subtract a constant from the source array \b this and store the result in \b res (res = *this-x).
590If not initially allocated, the output array \b res is automatically
591resized as a packed array with the same sizes as the source (this) array.
592Returns a reference to the output array \b res.
593\param x : constant to subtract from the array elements
594\param res : Output array containing the result (res=this+x or res=x-this).
595\param fginv == true : Invert subtraction argument order (res = x-(*this))
596*/
597template <class T>
598TArray<T>& TArray<T>::SubCst(T x, TArray<T>& res, bool fginv) const
599{
600 if (NbDimensions() < 1)
601 throw RangeCheckError("TArray<T>::SubCst(T,res) - Not allocated source array ");
602 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
603 bool smo;
604 if (!CompareSizes(res, smo))
605 throw(SzMismatchError("TArray<T>::SubCst(T, res) SizeMismatch(this,res) ")) ;
606
607 const T * pe;
608 T * per;
609 sa_size_t j,k;
610 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
611 sa_size_t maxx = totsize_;
612 pe = Data();
613 per = res.Data();
614 if (!fginv)
615 for(k=0; k<maxx; k++) *per++ = *pe++ - x;
616 else
617 for(k=0; k<maxx; k++) *per++ = x - *pe++;
618 }
619 else { // Non regular data spacing ...
620 int_4 ax,axr;
621 sa_size_t step, stepr;
622 sa_size_t gpas, naxa;
623 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
624 for(j=0; j<naxa; j++) {
625 pe = mNDBlock.Begin()+Offset(ax,j);
626 per = res.DataBlock().Begin()+res.Offset(axr,j);
627 if (!fginv)
628 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = *pe-x;
629 else
630 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x-*pe;
631 }
632 }
633 return(res);
634}
635
636//! Multiply the source array by a constant value \b x and store the result in \b res.
637/*!
638Multiply the source array \b this by a constant \b x and store the result in \b res (res = *this*x).
639If not initially allocated, the output array \b res is automatically
640resized as a packed array with the same sizes as the source (this) array.
641Returns a reference to the output array \b res.
642\param x : Array elements are multiplied by x
643\param res : Output array containing the result (res=this*x).
644*/
645template <class T>
646TArray<T>& TArray<T>::MulCst(T x, TArray<T>& res) const
647{
648 if (NbDimensions() < 1)
649 throw RangeCheckError("TArray<T>::MulCst(T,res) - Not allocated source array ");
650 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
651 bool smo;
652 if (!CompareSizes(res, smo))
653 throw(SzMismatchError("TArray<T>::MulCst(T, res) SizeMismatch(this,res) ")) ;
654
655 const T * pe;
656 T * per;
657 sa_size_t j,k;
658 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
659 sa_size_t maxx = totsize_;
660 pe = Data();
661 per = res.Data();
662 for(k=0; k<maxx; k++) *per++ = *pe++ * x;
663 }
664 else { // Non regular data spacing ...
665 int_4 ax,axr;
666 sa_size_t step, stepr;
667 sa_size_t gpas, naxa;
668 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
669 for(j=0; j<naxa; j++) {
670 pe = mNDBlock.Begin()+Offset(ax,j);
671 per = res.DataBlock().Begin()+res.Offset(axr,j);
672 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)*x;
673 }
674 }
675 return(res);
676}
677
678//! Divide the source array by a constant value \b x and store the result in \b res.
679/*!
680Divide the source array \b this by a constant \b x and store the result in \b res (res = *this/x).
681If not initially allocated, the output array \b res is automatically
682resized as a packed array with the same sizes as the source (this) array.
683Returns a reference to the output array \b res.
684\param x : Array elements are divied by x
685\param res : Output array containing the result (res=(*this)/x or res=x/(*this)).
686\param fginv == true : Invert the division argument order (res = x/(*this))
687*/
688template <class T>
689TArray<T>& TArray<T>::DivCst(T x, TArray<T>& res, bool fginv) const
690{
691 if (NbDimensions() < 1)
692 throw RangeCheckError("TArray<T>::DivCst(T,res) - Not allocated source array ! ");
693 if (!fginv && (x == (T) 0) )
694 throw MathExc("TArray<T>::DivCst(T,res) - Divide by zero ! ");
695 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
696 bool smo;
697 if (!CompareSizes(res, smo))
698 throw(SzMismatchError("TArray<T>::DivCst(T, res) SizeMismatch(this,res) ")) ;
699
700 const T * pe;
701 T * per;
702 sa_size_t j,k;
703 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
704 sa_size_t maxx = totsize_;
705 pe = Data();
706 per = res.Data();
707 if (!fginv)
708 for(k=0; k<maxx; k++) *per++ = *pe++ / x;
709 else
710 for(k=0; k<maxx; k++) *per++ = x / *pe++;
711 }
712 else { // Non regular data spacing ...
713 int_4 ax,axr;
714 sa_size_t step, stepr;
715 sa_size_t gpas, naxa;
716 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
717 for(j=0; j<naxa; j++) {
718 pe = mNDBlock.Begin()+Offset(ax,j);
719 per = res.DataBlock().Begin()+res.Offset(axr,j);
720 if (!fginv)
721 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = (*pe)/x;
722 else
723 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = x/(*pe);
724 }
725 }
726 return(res);
727}
728
729
730//! Stores the opposite of the source array in \b res (res=-(*this)).
731/*!
732If not initially allocated, the output array \b res is automatically
733resized as a packed array with the same sizes as the source (this) array.
734Returns a reference to the output array \b res.
735*/
736template <class T>
737TArray<T>& TArray<T>::NegateElt(TArray<T>& res) const
738{
739 if (NbDimensions() < 1)
740 throw RangeCheckError("TArray<T>::NegateElt(res) - Not allocated source array ");
741 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
742 bool smo;
743 if (!CompareSizes(res, smo))
744 throw(SzMismatchError("TArray<T>::NegateElt(res) SizeMismatch(this,res) ")) ;
745
746 const T * pe;
747 T * per;
748 sa_size_t j,k;
749 if (smo && (IsPacked() > 0) && (res.IsPacked() > 0)) { // regularly spaced elements
750 sa_size_t maxx = totsize_;
751 pe = Data();
752 per = res.Data();
753 for(k=0; k<maxx; k++) *per++ = -(*pe++);
754 }
755 else { // Non regular data spacing ...
756 int_4 ax,axr;
757 sa_size_t step, stepr;
758 sa_size_t gpas, naxa;
759 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
760 for(j=0; j<naxa; j++) {
761 pe = mNDBlock.Begin()+Offset(ax,j);
762 per = res.DataBlock().Begin()+res.Offset(axr,j);
763 for(k=0; k<gpas; k+=step, pe+=step, per+=stepr) *per = -(*pe);
764 }
765 }
766 return(res);
767}
768
769// >>>> Operations avec 2nd membre de type tableau
770
771//! Two TArrays element by element addition
772/*!
773Perform element by element addition of the source array (this) and the \b a array
774and store the result in \b res (res = *this+a). The source and argument arrays (this, a)
775should have the same sizes.
776If not initially allocated, the output array \b res is automatically
777resized as a packed array with the same sizes as the source (this) array.
778Returns a reference to the output array \b res.
779\param a : Array to be added to the source array.
780\param res : Output array containing the result (res=this+a).
781*/
782template <class T>
783TArray<T>& TArray<T>::AddElt(const TArray<T>& a, TArray<T>& res) const
784{
785 if (NbDimensions() < 1)
786 throw RangeCheckError("TArray<T>::AddElt(...) - Not allocated source array ! ");
787 bool smoa;
788 if (!CompareSizes(a, smoa))
789 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,a)")) ;
790 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
791 bool smor;
792 if (!CompareSizes(res, smor))
793 throw(SzMismatchError("TArray<T>::AddElt(...) SizeMismatch(this,res) ")) ;
794
795 bool smora;
796 a.CompareSizes(res, smora);
797
798 bool smo = smoa && smor; // The three arrays have same memory organisation
799
800 const T * pe;
801 const T * pea;
802 T * per;
803 sa_size_t j,k;
804 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
805 sa_size_t maxx = totsize_;
806 pe = Data();
807 pea = a.Data();
808 per = res.Data();
809 // for(k=0; k<maxx; k++, pe++, pea++, per++) *per = *pe + *pea ;
810 for(k=0; k<maxx; k++) *per++ = *pe++ + *pea++ ;
811 }
812 else { // Non regular data spacing ...
813 int_4 ax,axa,axr;
814 sa_size_t step, stepa;
815 sa_size_t gpas, naxa;
816 sa_size_t stepr, stgpas;
817 if ( !smo && smora ) { // same mem-org for a,res , different from this
818 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
819 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
820 stgpas = stepa;
821 }
822 else { // same mem-org for all, or same (this,a) OR same(this,res)
823 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
824 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
825 stgpas = step;
826 }
827 for(j=0; j<naxa; j++) {
828 pe = mNDBlock.Begin()+Offset(ax,j);
829 pea = a.DataBlock().Begin()+a.Offset(axa,j);
830 per = res.DataBlock().Begin()+res.Offset(axr,j);
831 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe + *pea ;
832 }
833 }
834 return(res);
835}
836
837//! Two TArrays element by element subtraction
838/*!
839Perform element by element subtraction of the source array (this) and the \b a array
840and the store result in \b res (res = *this-a or res=a-(*this)).
841The source and argument arrays (this, a) should have the same sizes.
842If not initially allocated, the output array \b res is automatically
843resized as a packed array with the same sizes as the source (this) array.
844Returns a reference to the output array \b res.
845\param a : Array to be added to the source array.
846\param res : Output array containing the result (res=*this+x).
847\param fginv == true : Invert subtraction argument order (res = a-(*this))
848*/
849
850template <class T>
851TArray<T>& TArray<T>::SubElt(const TArray<T>& a, TArray<T>& res, bool fginv) const
852{
853 if (NbDimensions() < 1)
854 throw RangeCheckError("TArray<T>::SubElt(...) - Not allocated source array ! ");
855 bool smoa;
856 if (!CompareSizes(a, smoa))
857 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,a)")) ;
858 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
859 bool smor;
860 if (!CompareSizes(res, smor))
861 throw(SzMismatchError("TArray<T>::SubElt(...) SizeMismatch(this,res) ")) ;
862
863 bool smora;
864 a.CompareSizes(res, smora);
865
866 bool smo = smoa && smor; // The three arrays have same memory organisation
867
868 const T * pe;
869 const T * pea;
870 T * per;
871 sa_size_t j,k;
872 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
873 sa_size_t maxx = totsize_;
874 pe = Data();
875 pea = a.Data();
876 per = res.Data();
877 if (!fginv)
878 for(k=0; k<maxx; k++) *per++ = *pe++ - *pea++ ;
879 else
880 for(k=0; k<maxx; k++) *per++ = *pea++ - *pe++ ;
881 }
882 else { // Non regular data spacing ...
883 int_4 ax,axa,axr;
884 sa_size_t step, stepa;
885 sa_size_t gpas, naxa;
886 sa_size_t stepr, stgpas;
887 if ( !smo && smora ) { // same mem-org for a,res , different from this
888 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
889 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
890 stgpas = stepa;
891 }
892 else { // same mem-org for all, or same (this,a) OR same(this,res)
893 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
894 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
895 stgpas = step;
896 }
897 for(j=0; j<naxa; j++) {
898 pe = mNDBlock.Begin()+Offset(ax,j);
899 pea = a.DataBlock().Begin()+a.Offset(axa,j);
900 per = res.DataBlock().Begin()+res.Offset(axr,j);
901 if (!fginv)
902 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pe - *pea ;
903 else
904 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = *pea - *pea ;
905 }
906 }
907 return(res);
908}
909
910
911//! Two TArrays element by element multiplication
912/*!
913Perform element by element multiplication of the source array (this) and the \b a array
914and store the result in \b res (res = *this*a). The source and argument arrays (this, a)
915should have the same sizes.
916If not initially allocated, the output array \b res is automatically
917resized as a packed array with the same sizes as the source (this) array.
918Returns a reference to the output array \b res.
919\param a : Array to be added to the source array.
920\param res : Output array containing the result (res=(*this)*a).
921*/
922template <class T>
923TArray<T>& TArray<T>::MulElt(const TArray<T>& a, TArray<T>& res) const
924{
925 if (NbDimensions() < 1)
926 throw RangeCheckError("TArray<T>::MulElt(...) - Not allocated source array ! ");
927 bool smoa;
928 if (!CompareSizes(a, smoa))
929 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,a)")) ;
930 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
931 bool smor;
932 if (!CompareSizes(res, smor))
933 throw(SzMismatchError("TArray<T>::MulElt(...) SizeMismatch(this,res) ")) ;
934
935 bool smora;
936 a.CompareSizes(res, smora);
937
938 bool smo = smoa && smor; // The three arrays have same memory organisation
939
940 const T * pe;
941 const T * pea;
942 T * per;
943 sa_size_t j,k;
944 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
945 sa_size_t maxx = totsize_;
946 pe = Data();
947 pea = a.Data();
948 per = res.Data();
949 for(k=0; k<maxx; k++) *per++ = *pe++ * *pea++ ;
950 }
951 else { // Non regular data spacing ...
952 int_4 ax,axa,axr;
953 sa_size_t step, stepa;
954 sa_size_t gpas, naxa;
955 sa_size_t stepr, stgpas;
956 if ( !smo && smora ) { // same mem-org for a,res , different from this
957 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
958 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
959 stgpas = stepa;
960 }
961 else { // same mem-org for all, or same (this,a) OR same(this,res)
962 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
963 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
964 stgpas = step;
965 }
966 for(j=0; j<naxa; j++) {
967 pe = mNDBlock.Begin()+Offset(ax,j);
968 pea = a.DataBlock().Begin()+a.Offset(axa,j);
969 per = res.DataBlock().Begin()+res.Offset(axr,j);
970 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr) *per = (*pe) * (*pea);
971 }
972 }
973 return(res);
974}
975
976
977//! Two TArrays element by element division
978/*!
979Perform element by element division of the source array (this) and the \b a array
980and store the result in \b res (res = *this/a). The source and argument arrays (this, a)
981should have the same sizes.
982If not initially allocated, the output array \b res is automatically
983resized as a packed array with the same sizes as the source (this) array.
984Returns a reference to the output array \b res.
985\param a : Array to be added to the source array.
986\param res : Output array containing the result (res=*this/a).
987\param fginv == true : Inverts the division argument order (res = a/(*this))
988\param divzero == true : Result is set to zero (res(i)=0) if the operation's
989second argument is equal to zero (a(i)/(*this)(i)==0)
990*/
991template <class T>
992TArray<T>& TArray<T>::DivElt(const TArray<T>& a, TArray<T>& res, bool fginv, bool divzero) const
993{
994 if (NbDimensions() < 1)
995 throw RangeCheckError("TArray<T>::DivElt(...) - Not allocated source array ! ");
996 bool smoa;
997 if (!CompareSizes(a, smoa))
998 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,a)")) ;
999 if (res.NbDimensions() < 1) res.SetSize(*this, true, false);
1000 bool smor;
1001 if (!CompareSizes(res, smor))
1002 throw(SzMismatchError("TArray<T>::DivElt(...) SizeMismatch(this,res) ")) ;
1003
1004 bool smora;
1005 a.CompareSizes(res, smora);
1006
1007 bool smo = smoa && smor; // The three arrays have same memory organisation
1008
1009 const T * pe;
1010 const T * pea;
1011 T * per;
1012 sa_size_t j,k;
1013 if (smo && IsPacked() && a.IsPacked() && res.IsPacked() ) { // All packed arrays
1014 sa_size_t maxx = totsize_;
1015 pe = Data();
1016 pea = a.Data();
1017 per = res.Data();
1018 if(divzero) {
1019 if (!fginv)
1020 for(k=0; k<maxx; k++)
1021 if (*pea==(T)0) *per = (T)0; else *per++ = *pe++ / *pea++ ;
1022 else
1023 for(k=0; k<maxx; k++)
1024 if (*pe==(T)0) *per = (T)0; else *per++ = *pea++ / *pe++ ;
1025 }
1026 else {
1027 if (!fginv)
1028 for(k=0; k<maxx; k++) *per++ = *pe++ / *pea++ ;
1029 else
1030 for(k=0; k<maxx; k++) *per = *pea++ / *pe++ ;
1031 }
1032 }
1033 else { // Non regular data spacing ...
1034 int_4 ax,axa,axr;
1035 sa_size_t step, stepa;
1036 sa_size_t gpas, naxa;
1037 sa_size_t stepr, stgpas;
1038 if ( !smo && smora ) { // same mem-org for a,res , different from this
1039 a.GetOpeParams(*this, smo, axa, ax, stepa, step, gpas, naxa);
1040 a.GetOpeParams(res, smo, axa, axr, stepa, stepr, gpas, naxa);
1041 stgpas = stepa;
1042 }
1043 else { // same mem-org for all, or same (this,a) OR same(this,res)
1044 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1045 GetOpeParams(res, smo, ax, axr, step, stepr, gpas, naxa);
1046 stgpas = step;
1047 }
1048 // DBG cout << "DBG-A-DIVELT naxa=" << naxa << " gpas= " << gpas
1049 // << " step=" << step << " stepa=" << stepa << " stepr=" << stepr
1050 // << " ax= " << ax << " axa= " << axa << " axr= " << axr << endl;
1051 for(j=0; j<naxa; j++) {
1052 pe = mNDBlock.Begin()+Offset(ax,j);
1053 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1054 per = res.DataBlock().Begin()+res.Offset(axr,j);
1055 if(divzero) {
1056 if (!fginv)
1057 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1058 if (*pea==(T)0) *per = (T)0; else *per = *pe / *pea ;
1059 else
1060 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1061 if (*pe==(T)0) *per = (T)0; else *per = *pea / *pe ;
1062 }
1063 else {
1064 if (!fginv)
1065 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1066 *per = *pe / *pea ;
1067 else
1068 for(k=0; k<gpas; k+=stgpas, pe+=step, pea+=stepa, per+=stepr)
1069 *per = *pea / *pe ;
1070 }
1071 }
1072 }
1073 return(res);
1074}
1075
1076
1077//! Copy elements of \b a
1078template <class T>
1079TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
1080{
1081 if (NbDimensions() < 1)
1082 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1083 bool smo;
1084 if (!CompareSizes(a, smo))
1085 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
1086
1087 T * pe;
1088 const T * pea;
1089 sa_size_t j,k;
1090 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
1091 if (IsPacked() && a.IsPacked()) memcpy(Data(), a.Data(), totsize_*sizeof(T)); // Packed arrays
1092 else {
1093 sa_size_t step = AvgStep();
1094 sa_size_t stepa = a.AvgStep();
1095 sa_size_t maxx = totsize_*step;
1096 pe = Data();
1097 pea = a.Data();
1098 for(k=0; k<maxx; k+=step, pe+=step, pea+=stepa ) *pe = *pea ;
1099 }
1100 }
1101 else { // Non regular data spacing ...
1102 int_4 ax,axa;
1103 sa_size_t step, stepa;
1104 sa_size_t gpas, naxa;
1105 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1106 for(j=0; j<naxa; j++) {
1107 pe = mNDBlock.Begin()+Offset(ax,j);
1108 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1109 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) *pe = *pea;
1110 }
1111 }
1112 return(*this);
1113}
1114
1115//! Converts and Copy elements of \b a
1116template <class T>
1117TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
1118{
1119 if (NbDimensions() < 1)
1120 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
1121 bool smo;
1122 if (!CompareSizes(a, smo))
1123 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
1124
1125 T * pe;
1126 sa_size_t j,k,ka;
1127 sa_size_t offa;
1128 // Non regular data spacing ...
1129 int_4 ax,axa;
1130 sa_size_t step, stepa;
1131 sa_size_t gpas, naxa;
1132 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1133 for(j=0; j<naxa; j++) {
1134 pe = mNDBlock.Begin()+Offset(ax,j);
1135 offa = a.Offset(axa,j);
1136/*
1137 Appel explicite de l'operateur de conversion
1138 suite a la suggestion de M. Reinecke, Reza 31/7/2002
1139#if !defined(__GNUG__)
1140 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
1141#else
1142 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
1143 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
1144#endif
1145 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
1146*/
1147 /* ----- Janvier 2006 ------
1148 Un bug important etait semble-t-il present depuis longtemps
1149 On appelait a.ValueAtPosition(ip) qui renvoie l'element ip en tenant compte
1150 de la structure du tableau , alors qu'on veut acceder l'element ip du datablock
1151 Methode ValueAtPositionDB(ip) ajoute et utilisee a la place de ValueAtPosition(ip)
1152 */
1153 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
1154 a.ValueAtPositionDB(offa+ka).Convert(pe[k]);
1155 //REMPLACE Suite pb compil gcc4 pe[k] = a.ValueAtPosition(offa+ka).operator T();
1156 }
1157 return(*this);
1158}
1159
1160//! Return the the scalar product of the two arrays (Sum_k[(*this)(k)*a(k)])
1161template <class T>
1162T TArray<T>::ScalarProduct(const TArray<T>& a) const
1163{
1164 if (NbDimensions() < 1)
1165 throw RangeCheckError("TArray<T>::ScalarProduct(...) - Not allocated source array ");
1166 bool smo;
1167 if (!CompareSizes(a, smo))
1168 throw(SzMismatchError("TArray<T>::ScalarProduct(...) SizeMismatch(this,a) ")) ;
1169
1170 T res = (T)(0);
1171 const T * pe;
1172 const T * pea;
1173 sa_size_t j,k;
1174 if (smo && (IsPacked() > 0) && (a.IsPacked() > 0)) { // regularly spaced elements
1175 sa_size_t maxx = totsize_;
1176 pe = Data();
1177 pea = a.Data();
1178 for(k=0; k<maxx; k++) res += *pe++ * *pea++;
1179 }
1180 else { // Non regular data spacing ...
1181 int_4 ax,axa;
1182 sa_size_t step, stepa;
1183 sa_size_t gpas, naxa;
1184 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
1185 for(j=0; j<naxa; j++) {
1186 pe = mNDBlock.Begin()+Offset(ax,j);
1187 pea = a.DataBlock().Begin()+a.Offset(axa,j);
1188 for(k=0; k<gpas; k+=step, pe+=step, pea+=stepa) res += (*pe)*(*pea);
1189 }
1190 }
1191 return(res);
1192}
1193
1194
1195// Somme et produit des elements
1196//! Returns the sum of all array elements
1197template <class T>
1198T TArray<T>::Sum() const
1199{
1200 if (NbDimensions() < 1)
1201 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
1202 T ret=0;
1203 const T * pe;
1204 sa_size_t j,k;
1205 if (AvgStep() > 0) { // regularly spaced elements
1206 sa_size_t step = AvgStep();
1207 sa_size_t maxx = totsize_*step;
1208 pe = Data();
1209 for(k=0; k<maxx; k+=step ) ret += pe[k];
1210 }
1211 else { // Non regular data spacing ...
1212 int_4 ka = MaxSizeKA();
1213 sa_size_t step = Step(ka);
1214 sa_size_t gpas = Size(ka)*step;
1215 sa_size_t naxa = Size()/Size(ka);
1216 for(j=0; j<naxa; j++) {
1217 pe = mNDBlock.Begin()+Offset(ka,j);
1218 for(k=0; k<gpas; k+=step) ret += pe[k] ;
1219 }
1220 }
1221 return ret;
1222}
1223
1224//! Return the product of all elements
1225template <class T>
1226T TArray<T>::Product() const
1227{
1228 if (NbDimensions() < 1)
1229 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
1230 T ret=(T)1;
1231 const T * pe;
1232 sa_size_t j,k;
1233 if (AvgStep() > 0) { // regularly spaced elements
1234 sa_size_t step = AvgStep();
1235 sa_size_t maxx = totsize_*step;
1236 pe = Data();
1237 for(k=0; k<maxx; k+=step ) ret *= pe[k];
1238 }
1239 else { // Non regular data spacing ...
1240 int_4 ka = MaxSizeKA();
1241 sa_size_t step = Step(ka);
1242 sa_size_t gpas = Size(ka)*step;
1243 sa_size_t naxa = Size()/Size(ka);
1244 for(j=0; j<naxa; j++) {
1245 pe = mNDBlock.Begin()+Offset(ka,j);
1246 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
1247 }
1248 }
1249 return ret;
1250}
1251
1252//! Returns the sum of all array elements squared (Sum_k((*this)(k)*(*this)(k)).
1253template <class T>
1254T TArray<T>::SumX2() const
1255{
1256 if (NbDimensions() < 1)
1257 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
1258 T ret=0;
1259 const T * pe;
1260 sa_size_t j,k;
1261 if (AvgStep() > 0) { // regularly spaced elements
1262 sa_size_t step = AvgStep();
1263 sa_size_t maxx = totsize_*step;
1264 pe = Data();
1265 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
1266 }
1267 else { // Non regular data spacing ...
1268 int_4 ka = MaxSizeKA();
1269 sa_size_t step = Step(ka);
1270 sa_size_t gpas = Size(ka)*step;
1271 sa_size_t naxa = Size()/Size(ka);
1272 for(j=0; j<naxa; j++) {
1273 pe = mNDBlock.Begin()+Offset(ka,j);
1274 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
1275 }
1276 }
1277 return ret;
1278}
1279
1280//! Return the minimum and the maximum values of the array elements
1281/*!
1282 This method generates an exception (\c MathExc) if called for complex arrays
1283*/
1284
1285template <class T>
1286void TArray<T>::MinMax(T& min, T& max) const
1287{
1288 const T * pe;
1289 sa_size_t j,k;
1290 int_4 ka = MaxSizeKA();
1291 sa_size_t step = Step(ka);
1292 sa_size_t gpas = Size(ka)*step;
1293 sa_size_t naxa = Size()/Size(ka);
1294 min = (*this)[0];
1295 max = (*this)[0];
1296 for(j=0; j<naxa; j++) {
1297 pe = mNDBlock.Begin()+Offset(ka,j);
1298 for(k=0; k<gpas; k+=step) {
1299 if (pe[k]<min) min = pe[k];
1300 else if (pe[k]>max) max = pe[k];
1301 }
1302 }
1303 return;
1304}
1305
1306DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1307void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
1308{
1309 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1310}
1311DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1312void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
1313{
1314 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
1315}
1316
1317
1318// ----------------------------------------------------
1319// Impression, etc ...
1320// ----------------------------------------------------
1321
1322//! Return a string that contain the type \b T of the array
1323template <class T>
1324string TArray<T>::InfoString() const
1325{
1326 string rs = "TArray<" ;
1327 rs += typeid(T).name();
1328 rs += "> ";
1329 return(rs);
1330}
1331
1332//! Print array
1333/*!
1334 \param os : output stream
1335 \param maxprt : maximum numer of print
1336 \param si : if true, display attached DvList
1337 \param ascd : if true, suppresses the display of line numbers,
1338 suitable for ascii dump format.
1339 \sa SetMaxPrint
1340 \sa WriteASCII
1341 */
1342template <class T>
1343void TArray<T>::Print(ostream& os, sa_size_t maxprt, bool si, bool ascd) const
1344{
1345 if (maxprt < 0) maxprt = max_nprt_;
1346 sa_size_t npr = 0;
1347 // keep stream's io flags
1348 // ios_base::fmtflags ioflg = os.flags(); compile pas sur OSF-cxx
1349 // os << right ; compile pas sur OSF-cxx
1350
1351 Show(os, si);
1352 if (ndim_ < 1) return;
1353
1354 // Calcul de la largeur d'impression pour chaque element
1355 int fprtw = os.precision()+7;
1356 int prtw = 5;
1357
1358 if ( (typeid(T) == typeid( int_4 )) || (typeid(T) == typeid( uint_4 )) ) prtw = 8;
1359 else if ( (typeid(T) == typeid( int_8 )) || (typeid(T) == typeid( uint_8 )) ) prtw = 11;
1360 else if ( typeid(T) == typeid( r_4 ) ) prtw = fprtw;
1361 else if ( typeid(T) == typeid( r_8 ) ) prtw = fprtw;
1362 else if ( typeid(T) == typeid(complex<r_4>) ) prtw = fprtw;
1363 else if ( typeid(T) == typeid(complex<r_8>) ) prtw = fprtw;
1364
1365
1366 sa_size_t k0,k1,k2,k3,k4;
1367 for(k4=0; k4<size_[4]; k4++) {
1368 if ((size_[4] > 1) && !ascd)
1369 os << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
1370 for(k3=0; k3<size_[3]; k3++) {
1371 if ((size_[3] > 1) && !ascd)
1372 os << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
1373 for(k2=0; k2<size_[2]; k2++) {
1374 if ((size_[2] > 1) && !ascd)
1375 os << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
1376 for(k1=0; k1<size_[1]; k1++) {
1377 if ( (size_[1] > 1) && (size_[0] > 10) && !ascd)
1378 os << "----- Dimension 2 (Y) K1= " << k1 << endl;
1379 for(k0=0; k0<size_[0]; k0++) {
1380 if(k0 > 0) os << " ";
1381 os << setw(prtw) << Elem(k0, k1, k2, k3, k4); npr++;
1382 if (npr >= (sa_size_t) maxprt) {
1383 if (npr < totsize_) os << "\n .... " << endl; return;
1384 }
1385 }
1386 os << endl;
1387 }
1388 }
1389 }
1390 }
1391 os << endl;
1392 //compile pas sur OSF-cxx os.flags(ioflg); // reset stream io flags
1393}
1394
1395//! Fill the array, decoding the ASCII input stream
1396/*!
1397 \param is : input stream (ASCII)
1398 \param nr : Number of non empty (or comment) lines in stream (return value)
1399 \param nc : Number of columns (= ntot/nlines) (return value)
1400 \param clm : Lines starting with clm character are treated as comment lines
1401 \param sep : word separator in lines
1402 \return Number of decoded elements
1403*/
1404template <class T>
1405sa_size_t TArray<T>::ReadASCII(istream& is, sa_size_t & nr, sa_size_t & nc,
1406 char clm, const char* sep)
1407{
1408 EnumeratedSequence es;
1409 sa_size_t n = es.FillFromFile(is, nr, nc, clm, sep);
1410 if ( (n < 1) || (nr < 1) || (nc < 1) ) return(n);
1411 if (!IsAllocated()) {
1412 sa_size_t sz[2];
1413 if (arrtype_ == 2) { // C'est un vecteur
1414 sz[0] = sz[1] = 1;
1415 sz[veceli_] = n;
1416 }
1417 else {
1418 sz[RowsKA()] = nr;
1419 sz[ColsKA()] = nc;
1420 }
1421 ReSize(2, sz);
1422 }
1423 SetSeq(es);
1424 cout << "TArray<T>::ReadASCII()/Info: " << n << " elements read from stream "
1425 << " (Row,Col= " << nr << "," << nc << ")" << endl;
1426 return(n);
1427}
1428
1429//! Writes the array content to the output stream, (in ASCII)
1430/*!
1431 \param os : output stream (ASCII)
1432 \sa Print
1433 */
1434template <class T>
1435void TArray<T>::WriteASCII(ostream& os) const
1436{
1437 Print(os, Size(), false, true);
1438}
1439
1440
1441
1442///////////////////////////////////////////////////////////////
1443///////////////////////////////////////////////////////////////
1444#ifdef __CXX_PRAGMA_TEMPLATES__
1445/*
1446#pragma define_template TArray<uint_1>
1447#pragma define_template TArray<int_2>
1448#pragma define_template TArray<uint_4>
1449*/
1450#pragma define_template TArray<uint_2>
1451#pragma define_template TArray<uint_8>
1452#pragma define_template TArray<int_4>
1453#pragma define_template TArray<int_8>
1454#pragma define_template TArray<r_4>
1455#pragma define_template TArray<r_8>
1456#pragma define_template TArray< complex<r_4> >
1457#pragma define_template TArray< complex<r_8> >
1458#endif
1459
1460#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1461namespace SOPHYA {
1462/*
1463template class TArray<uint_1>;
1464template class TArray<int_2>;
1465template class TArray<uint_4>;
1466*/
1467template class TArray<uint_2>;
1468template class TArray<uint_8>;
1469template class TArray<int_4>;
1470template class TArray<int_8>;
1471template class TArray<r_4>;
1472template class TArray<r_8>;
1473template class TArray< complex<r_4> >;
1474template class TArray< complex<r_8> >;
1475}
1476#endif
1477
1478
Note: See TracBrowser for help on using the repository browser.