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

Last change on this file since 3661 was 3661, checked in by cmv, 16 years ago
  • ajout des TArray/TMatrix/TVector <uint_1> et <int_1>
  • cet ajout n'a pas ete porte dans Image<T>
  • correction petit bug:

inline int_4 Convert(int_2& x) const {...}
-> inline int_2 Convert(int_2& x) const {...}

cmv 23/10/2009

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