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

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

Ajout de la methode BaseArray::ValueAtPositionDB() pour corriger un gros bug au niveau de la conversion de type (r_4 r_8 ...) des tableaux - Reza 4 Jan 2006

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