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

Last change on this file since 3853 was 3850, checked in by ansari, 15 years ago

petite correction ds commentaires/autodoc, Reza 11/08/2010

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