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

Last change on this file since 2917 was 2917, checked in by ansari, 20 years ago

Documentation + debug Range et extraction sous-tableaux , Reza 23/02/2006

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