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

Last change on this file since 3379 was 3332, checked in by ansari, 18 years ago

1- Methode TArray::SumX2() renommee en ::SumSq()
2- Methode TArray::Norm2() appelle maintenant SumSq() - sauf pour les
tableaux complexes, ou on calcule Sum[el x conj(el)]=Sum[module2]
3- Nettoyage fichier sopemtx.cc (utilisation sa_size_t pour supprimer
les warnings g++

Reza , 02/10/2007

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