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

Last change on this file since 2938 was 2938, checked in by ansari, 19 years ago

Ajout operateur && et / (MulElt DivElt) pour TArray (.h) et partage (Share) lors des operations Add/Mul/Sub/DivCst et Add/Mul/Sub/DivElt (.cc) - Reza 24/4/2006

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