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

Last change on this file since 3613 was 3567, checked in by ansari, 17 years ago

Suppression de SetTemp() intempestive provoquant sur-ecriture tableaux lors d'operation avec des SubArray - Reza 06/02/2009

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