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

Last change on this file since 4036 was 4035, checked in by ansari, 14 years ago

1/ modif mineure ds TArray<T>::::ReadASCII() au print level global de BaseArray
2/ Correction bug gestion memoire au niveau des constructeurs de copie TArray/TMatrix/TVector
avec un BaseArray en argument. Ajout argument optionnel bool pack a ces constructeurs
3/ On autorise desormais la creation des objets TArray/TMatrix/TVector par constructeur de
copie sur des objets non alloues

Reza, 14/11/2011

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