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

Last change on this file since 3107 was 3101, checked in by ansari, 19 years ago

Petits ajouts ds les commentaires pour doxygen TArray, TMatrix - Reza 02/11/2006

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