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

Last change on this file since 3175 was 3173, checked in by ansari, 19 years ago

Ajout methodes TArray::ZeroSize() RenewObjId() - Reza 05/02/2007

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