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

Last change on this file since 1327 was 1156, checked in by ansari, 25 years ago

Introduction du type sa_size_t (taille des tableaux), operateur - (TArray::operator - et NegateElt()) - Reza 29/8/2000

File size: 29.9 KB
RevLine 
[772]1// template array class for numerical types
2// R. Ansari, C.Magneville 03/2000
3
4#include "machdefs.h"
5#include <stdio.h>
6#include <stdlib.h>
[922]7#include <math.h>
[772]8#include "pexceptions.h"
9#include "tarray.h"
10
[926]11/*!
12 \class SOPHYA::TArray
13 \ingroup TArray
14 Class for template arrays
[772]15
[926]16 This class implements arrays of dimensions up to
17 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS"
18*/
[772]19
20// -------------------------------------------------------
21// Methodes de la classe
22// -------------------------------------------------------
23
[894]24////////////////////////// Les constructeurs / destructeurs
25
26//! Default constructor
[772]27template <class T>
28TArray<T>::TArray()
[804]29 : BaseArray() , mNDBlock()
[772]30{
31}
32
[894]33//! Constructor
34/*!
35 \param ndim : number of dimensions (less or equal to
36 \ref BASEARRAY_MAXNDIMS "BASEARRAY_MAXNDIMS")
37 \param siz[ndim] : size along each dimension
38 \param step : step (same for all dimensions)
39 */
[772]40template <class T>
[1156]41TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, sa_size_t step)
[804]42 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1))
[772]43{
[1156]44 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, sa_size_t)";
[772]45 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
46}
47
[894]48//! Constructor
49/*!
50 \param nx,ny,nz,nt,nu : sizes along first, second, third, fourth and fifth dimension
51 */
[772]52template <class T>
[1156]53TArray<T>::TArray(sa_size_t nx, sa_size_t ny, sa_size_t nz, sa_size_t nt, sa_size_t nu)
[804]54 : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1))
[772]55{
[1156]56 sa_size_t size[BASEARRAY_MAXNDIMS];
[772]57 size[0] = nx; size[1] = ny; size[2] = nz;
[804]58 size[3] = nt; size[4] = nu;
[1156]59 int_4 ndim = 1;
[804]60 if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) && (size[4] > 0) ) ndim = 5;
61 else if ((size[1] > 0) && (size[2] > 0) && (size[3] > 0) ) ndim = 4;
62 else if ((size[1] > 0) && (size[2] > 0)) ndim = 3;
[772]63 else if (size[1] > 0) ndim = 2;
64 else ndim = 1;
[1156]65 string exmsg = "TArray<T>::TArray(sa_size_t, sa_size_t, sa_size_t, sa_size_t, sa_size_t)";
[772]66 if (!UpdateSizes(ndim, size, 1, 0, exmsg)) throw( ParmError(exmsg) );
67}
68
[894]69//! Constructor
70/*!
71 \param ndim : number of dimensions
72 \param siz[ndim] : size along each dimension
73 \param db : datas are given by this NDataBlock
74 \param share : if true, data are shared, if false they are copied
75 \param step : step (same for all dimensions) in data block
76 \param offset : offset for first element in data block
77 */
[772]78template <class T>
[1156]79TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, NDataBlock<T> & db, bool share, sa_size_t step, sa_size_t offset)
[804]80 : BaseArray() , mNDBlock(db, share)
[772]81{
[1156]82 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, NDataBlock<T> & ... )";
[772]83 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
84
85}
86
[894]87//! Constructor
88/*!
89 \param ndim : number of dimensions
90 \param siz[ndim] : size along each dimension
91 \param values : datas are given by this pointer
92 \param share : if true, data are shared, if false they are copied
93 \param step : step (same for all dimensions) in data block
94 \param offset : offset for first element in data block
95 \param br : if not NULL, dats are bridge with other datas
96 \sa NDataBlock
97 */
[772]98template <class T>
[1156]99TArray<T>::TArray(int_4 ndim, const sa_size_t * siz, T* values, sa_size_t step, sa_size_t offset, Bridge* br)
[804]100 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br)
[772]101{
[1156]102 string exmsg = "TArray<T>::TArray(int_4, sa_size_t *, T* ... )";
[772]103 if (!UpdateSizes(ndim, siz, step, offset, exmsg)) throw( ParmError(exmsg) );
104}
105
[894]106//! Constructor by copy
[976]107/*!
108 \warning datas are \b SHARED with \b a.
109 \sa NDataBlock::NDataBlock(const NDataBlock<T>&)
110 */
[772]111template <class T>
112TArray<T>::TArray(const TArray<T>& a)
[804]113 : BaseArray() , mNDBlock(a.mNDBlock)
[772]114{
115 string exmsg = "TArray<T>::TArray(const TArray<T>&)";
116 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
117 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
118}
119
[894]120//! Constructor by copy
121/*!
122 \param share : if true, data are shared, if false they are copied
123 */
[772]124template <class T>
125TArray<T>::TArray(const TArray<T>& a, bool share)
[804]126 : BaseArray() , mNDBlock(a.mNDBlock, share)
[772]127{
128 string exmsg = "TArray<T>::TArray(const TArray<T>&, bool)";
129 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
130 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
131}
132
[1081]133//! Constructor with size and contents copied (after conversion) from a different type TArray
134template <class T>
135TArray<T>::TArray(const BaseArray& a)
136 : BaseArray() , mNDBlock()
137{
138 string exmsg = "TArray<T>::TArray(const BaseArray&)";
139 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
140 mNDBlock.ReSize(totsize_);
141 // if (a.mInfo) mInfo = new DVList(*(a.mInfo)); - pb protected !
142 ConvertAndCopyElt(a);
143}
144
[894]145//! Destructor
[772]146template <class T>
147TArray<T>::~TArray()
148{
149}
150
[894]151////////////////////////// Les methodes de copie/share
152
153//! Set array equal to \b a and return *this
[976]154/*!
155 \warning Datas are copied (cloned) from \b a.
156 \sa NDataBlock::operator=(const NDataBlock<T>&)
157*/
[772]158template <class T>
[804]159TArray<T>& TArray<T>::Set(const TArray<T>& a)
[772]160{
[970]161 if (this == &a) return(*this);
162 if (a.NbDimensions() < 1)
163 throw RangeCheckError("TArray<T>::Set(a ) - Array a not allocated ! ");
164 if (NbDimensions() < 1) CloneOrShare(a);
165 else CopyElt(a);
[772]166 return(*this);
167}
168
[1081]169//! Set array elements equal to the \b a array elements, after conversion
170template <class T>
171TArray<T>& TArray<T>::SetBA(const BaseArray& a)
172{
173 if (this == &a) return(*this);
174 if (a.NbDimensions() < 1)
175 throw RangeCheckError("TArray<T>::SetBA(a ) - Array a not allocated ! ");
176 if (NbDimensions() < 1) {
177 string exmsg = "TArray<T>::SetBA(const BaseArray& a)";
178 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
179 mNDBlock.ReSize(totsize_);
180 }
181 ConvertAndCopyElt(a);
182 return(*this);
183}
184
[894]185//! Clone array \b a
[772]186template <class T>
187void TArray<T>::Clone(const TArray<T>& a)
188{
189 string exmsg = "TArray<T>::Clone()";
190 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
191 mNDBlock.Clone(a.mNDBlock);
[894]192 if (mInfo) {delete mInfo; mInfo = NULL;}
[772]193 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
194}
195
[970]196//! Clone if \b a is not temporary, share if temporary
[976]197/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
[970]198template <class T>
199void TArray<T>::CloneOrShare(const TArray<T>& a)
200{
201 string exmsg = "TArray<T>::CloneOrShare()";
[1103]202 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
[970]203 mNDBlock.CloneOrShare(a.mNDBlock);
[1103]204 if (mInfo) {delete mInfo; mInfo = NULL;}
205 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
[970]206}
207
208//! Share data with a
209template <class T>
210void TArray<T>::Share(const TArray<T>& a)
211{
212 string exmsg = "TArray<T>::Share()";
[1103]213 if (!UpdateSizes(a, exmsg)) throw( ParmError(exmsg) );
[970]214 mNDBlock.Share(a.mNDBlock);
[1103]215 if (mInfo) {delete mInfo; mInfo = NULL;}
216 if (a.mInfo) mInfo = new DVList(*(a.mInfo));
[970]217}
218
219
[894]220//! Resize array
221/*!
222 \param ndim : number of dimensions
223 \param siz[ndim] : size along each dimension
224 \param step : step (same for all dimensions)
225 */
[772]226template <class T>
[1156]227void TArray<T>::ReSize(int_4 ndim, sa_size_t * siz, sa_size_t step)
[772]228{
[1099]229 if (arrtype_ != 0) {
230 if (ndim != 2)
231 throw( ParmError("TArray<T>::ReSize(ndim!=2,...) for Matrix" ) );
232 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
233 throw( ParmError("TArray<T>::ReSize(,siz[0]>1 && size[1]>1) for Vector" ) );
234 }
[772]235 string exmsg = "TArray<T>::ReSize()";
236 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
237 mNDBlock.ReSize(totsize_);
238}
239
[894]240//! Re-allocate space for array
241/*!
242 \param ndim : number of dimensions
243 \param siz[ndim] : size along each dimension
244 \param step : step (same for all dimensions)
245 \param force : if true re-allocation is forced, if not it occurs
246 only if the required space is greater than the old one.
247 */
[772]248template <class T>
[1156]249void TArray<T>::Realloc(int_4 ndim, sa_size_t * siz, sa_size_t step, bool force)
[772]250{
[1099]251 if (arrtype_ != 0) {
252 if (ndim != 2)
253 throw( ParmError("TArray<T>::Realloc(ndim!=2,...) for Matrix" ) );
254 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
255 throw( ParmError("TArray<T>::Realloc(,siz[0]>1 && size[1]>1) for Vector" ) );
256 }
[772]257 string exmsg = "TArray<T>::Realloc()";
258 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
259 mNDBlock.ReSize(totsize_);
260}
261
[787]262
[894]263//! Compact dimensions in one or more is equal to 1.
[772]264template <class T>
[787]265TArray<T>& TArray<T>::CompactAllDimensions()
[772]266{
[787]267 CompactAllDim();
268 return(*this);
[772]269}
270
[894]271//! Compact dimensions if the last one is equal to 1.
[785]272template <class T>
[787]273TArray<T>& TArray<T>::CompactTrailingDimensions()
[785]274{
[787]275 CompactTrailingDim();
[785]276 return(*this);
277}
278
[894]279//! Give value (in \b double) for element at position \b ip..
[785]280template <class T>
[1156]281MuTyV & TArray<T>::ValueAtPosition(sa_size_t ip) const
[785]282{
[787]283#ifdef SO_BOUNDCHECKING
[1156]284 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(sa_size_t ip) Out-of-bound Error") );
[787]285#endif
[1081]286 my_mtv = *(mNDBlock.Begin()+Offset(ip));
287 return( my_mtv );
[785]288}
289
[894]290//! Return array with elements packed
291/*!
292 \param force : if true, pack elements in a new array.
293 If false and array is already packed, return
294 an array that share data with the current one.
295 \return packed array
296 */
[804]297template <class T>
298TArray<T> TArray<T>::PackElements(bool force) const
299{
300 if (NbDimensions() < 1)
301 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
302 if ( !force && (AvgStep() == 1) ) {
[970]303 TArray<T> ra;
304 ra.Share(*this);
[804]305 ra.SetTemp(true);
306 return(ra);
307 }
308 else {
309 TArray<T> ra(ndim_, size_, 1);
310 ra.CopyElt(*this);
311 ra.SetTemp(true);
312 return(ra);
313 }
314}
315
[785]316// SubArrays
[804]317// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
[894]318//! Extract a sub-array
319/*!
320 \param rx,ry,rz,rt,ru : range of extraction along dimensions
321 \sa Range
322 */
[785]323template <class T>
[804]324TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
[785]325{
[804]326 if (NbDimensions() < 1)
327 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
[1156]328 int_4 ndim = 0;
329 sa_size_t size[BASEARRAY_MAXNDIMS];
330 sa_size_t step[BASEARRAY_MAXNDIMS];
331 sa_size_t pos[BASEARRAY_MAXNDIMS];
[785]332 size[0] = rx.Size();
333 size[1] = ry.Size();
334 size[2] = rz.Size();
335 size[3] = rt.Size();
336 size[4] = ru.Size();
337
338 step[0] = rx.Step();
339 step[1] = ry.Step();
340 step[2] = rz.Step();
341 step[3] = rt.Step();
342 step[4] = ru.Step();
343
344 pos[0] = rx.Start();
345 pos[1] = ry.Start();
346 pos[2] = rz.Start();
347 pos[3] = rt.Start();
348 pos[4] = ru.Start();
349
350 ndim = ndim_;
351 TArray<T> ra;
[804]352 UpdateSubArraySizes(ra, ndim, size, pos, step);
[787]353 ra.DataBlock().Share(this->DataBlock());
[785]354 ra.SetTemp(true);
355 return(ra);
356}
357
[772]358// ...... Operation de calcul sur les tableaux ......
359// ------- Attention --------
360// Boucles normales prenant en compte les steps ....
[894]361// Possibilite de // , vectorisation
362
363//! Fill TArray with Sequence \b seq
364/*!
365 \param seq : sequence to fill the array
366 \sa Sequence
367 */
[772]368template <class T>
[1103]369TArray<T>& TArray<T>::SetSeq(Sequence const & seq)
[772]370{
[804]371 if (NbDimensions() < 1)
[813]372 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
[1103]373
[785]374 T * pe;
[1156]375 sa_size_t j,k;
376 int_4 ka;
[1103]377 if (arrtype_ == 0) ka = 0;
378 else ka = macoli_;
[1156]379 sa_size_t step = Step(ka);
380 sa_size_t gpas = Size(ka);
381 sa_size_t naxa = Size()/Size(ka);
[1103]382 for(j=0; j<naxa; j++) {
383 pe = mNDBlock.Begin()+Offset(ka,j);
384#if !defined(__GNUG__)
385 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
386#else
387 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
388 for(k=0; k<gpas; k++) pe[k*step] = seq(j*gpas+k);
389#endif
[785]390 }
[772]391 return(*this);
392}
393
394// >>>> Operations avec 2nd membre de type scalaire
395
[894]396//! Fill an array with a constant value \b x
[772]397template <class T>
[813]398TArray<T>& TArray<T>::SetT(T x)
[772]399{
[804]400 if (NbDimensions() < 1)
[813]401 throw RangeCheckError("TArray<T>::SetT(T ) - Not Allocated Array ! ");
[785]402 T * pe;
[1156]403 sa_size_t j,k;
[785]404 if (AvgStep() > 0) { // regularly spaced elements
[1156]405 sa_size_t step = AvgStep();
406 sa_size_t maxx = totsize_*step;
[785]407 pe = Data();
408 for(k=0; k<maxx; k+=step ) pe[k] = x;
409 }
410 else { // Non regular data spacing ...
[1156]411 int_4 ka = MaxSizeKA();
412 sa_size_t step = Step(ka);
413 sa_size_t gpas = Size(ka)*step;
414 sa_size_t naxa = Size()/Size(ka);
[813]415 for(j=0; j<naxa; j++) {
416 pe = mNDBlock.Begin()+Offset(ka,j);
[785]417 for(k=0; k<gpas; k+=step) pe[k] = x;
418 }
419 }
[772]420 return(*this);
421}
422
[894]423//! Add a constant value \b x to an array
[772]424template <class T>
[804]425TArray<T>& TArray<T>::Add(T x)
[772]426{
[804]427 if (NbDimensions() < 1)
428 throw RangeCheckError("TArray<T>::Add(T ) - Not Allocated Array ! ");
[785]429 T * pe;
[1156]430 sa_size_t j,k;
[785]431 if (AvgStep() > 0) { // regularly spaced elements
[1156]432 sa_size_t step = AvgStep();
433 sa_size_t maxx = totsize_*step;
[785]434 pe = Data();
435 for(k=0; k<maxx; k+=step ) pe[k] += x;
436 }
437 else { // Non regular data spacing ...
[1156]438 int_4 ka = MaxSizeKA();
439 sa_size_t step = Step(ka);
440 sa_size_t gpas = Size(ka)*step;
441 sa_size_t naxa = Size()/Size(ka);
[813]442 for(j=0; j<naxa; j++) {
443 pe = mNDBlock.Begin()+Offset(ka,j);
[785]444 for(k=0; k<gpas; k+=step) pe[k] += x;
445 }
446 }
[772]447 return(*this);
448}
449
[894]450//! Substract a constant value \b x to an array
[970]451/*!
452Substract a constant from the *this = *this-x
453\param fginv == true : Perfoms the inverse subtraction (*this = x-(*this))
454*/
[772]455template <class T>
[970]456TArray<T>& TArray<T>::Sub(T x, bool fginv)
[772]457{
[804]458 if (NbDimensions() < 1)
459 throw RangeCheckError("TArray<T>::Sub(T ) - Not Allocated Array ! ");
[785]460 T * pe;
[1156]461 sa_size_t j,k;
[785]462 if (AvgStep() > 0) { // regularly spaced elements
[1156]463 sa_size_t step = AvgStep();
464 sa_size_t maxx = totsize_*step;
[785]465 pe = Data();
[970]466 if (fginv)
467 for(k=0; k<maxx; k+=step ) pe[k] = x-pe[k];
468 else
469 for(k=0; k<maxx; k+=step ) pe[k] -= x;
[785]470 }
471 else { // Non regular data spacing ...
[1156]472 int_4 ka = MaxSizeKA();
473 sa_size_t step = Step(ka);
474 sa_size_t gpas = Size(ka)*step;
475 sa_size_t naxa = Size()/Size(ka);
[813]476 for(j=0; j<naxa; j++) {
477 pe = mNDBlock.Begin()+Offset(ka,j);
[970]478 if (fginv)
479 for(k=0; k<gpas; k+=step) pe[k] = x-pe[k];
480 else
481 for(k=0; k<gpas; k+=step) pe[k] -= x;
[785]482 }
483 }
[772]484 return(*this);
485}
486
[894]487//! Multiply an array by a constant value \b x
[772]488template <class T>
[804]489TArray<T>& TArray<T>::Mul(T x)
[772]490{
[804]491 if (NbDimensions() < 1)
492 throw RangeCheckError("TArray<T>::Mul(T ) - Not Allocated Array ! ");
[785]493 T * pe;
[1156]494 sa_size_t j,k;
[785]495 if (AvgStep() > 0) { // regularly spaced elements
[1156]496 sa_size_t step = AvgStep();
497 sa_size_t maxx = totsize_*step;
[785]498 pe = Data();
499 for(k=0; k<maxx; k+=step ) pe[k] *= x;
500 }
501 else { // Non regular data spacing ...
[1156]502 int_4 ka = MaxSizeKA();
503 sa_size_t step = Step(ka);
504 sa_size_t gpas = Size(ka)*step;
505 sa_size_t naxa = Size()/Size(ka);
[813]506 for(j=0; j<naxa; j++) {
507 pe = mNDBlock.Begin()+Offset(ka,j);
[785]508 for(k=0; k<gpas; k+=step) pe[k] *= x;
509 }
510 }
[772]511 return(*this);
512}
513
[894]514//! Divide an array by a constant value \b x
[970]515/*!
516Divide the array by a constant *this = *this/x
517\param fginv == true : Perfoms the inverse division (*this = x/(*this))
518*/
[772]519template <class T>
[970]520TArray<T>& TArray<T>::Div(T x, bool fginv)
[772]521{
[804]522 if (NbDimensions() < 1)
523 throw RangeCheckError("TArray<T>::Div(T ) - Not Allocated Array ! ");
[970]524 if (!fginv && (x == (T) 0) )
[894]525 throw MathExc("TArray<T>::Div(T ) - Divide by zero ! ");
[785]526 T * pe;
[1156]527 sa_size_t j,k;
[785]528 if (AvgStep() > 0) { // regularly spaced elements
[1156]529 sa_size_t step = AvgStep();
530 sa_size_t maxx = totsize_*step;
[785]531 pe = Data();
[970]532 if (fginv)
533 for(k=0; k<maxx; k+=step ) pe[k] = x/pe[k];
534 else
535 for(k=0; k<maxx; k+=step ) pe[k] /= x;
[785]536 }
537 else { // Non regular data spacing ...
[1156]538 int_4 ka = MaxSizeKA();
539 sa_size_t step = Step(ka);
540 sa_size_t gpas = Size(ka)*step;
541 sa_size_t naxa = Size()/Size(ka);
[813]542 for(j=0; j<naxa; j++) {
543 pe = mNDBlock.Begin()+Offset(ka,j);
[970]544 if (fginv)
545 for(k=0; k<gpas; k+=step) pe[k] = x/pe[k];
546 else
547 for(k=0; k<gpas; k+=step) pe[k] /= x;
[785]548 }
549 }
[772]550 return(*this);
551}
552
553
[1156]554//! Replace array elements values by their opposite ( a(i) -> -a(i) )
555template <class T>
556TArray<T>& TArray<T>::NegateElt()
557{
558 if (NbDimensions() < 1)
559 throw RangeCheckError("TArray<T>::NegateElt() - Not Allocated Array ! ");
560 T * pe;
561 sa_size_t j,k;
562 if (AvgStep() > 0) { // regularly spaced elements
563 sa_size_t step = AvgStep();
564 sa_size_t maxx = totsize_*step;
565 pe = Data();
566 for(k=0; k<maxx; k+=step ) pe[k] = -pe[k];
567 }
568 else { // Non regular data spacing ...
569 int_4 ka = MaxSizeKA();
570 sa_size_t step = Step(ka);
571 sa_size_t gpas = Size(ka)*step;
572 sa_size_t naxa = Size()/Size(ka);
573 for(j=0; j<naxa; j++) {
574 pe = mNDBlock.Begin()+Offset(ka,j);
575 for(k=0; k<gpas; k+=step) pe[k] = -pe[k];
576 }
577 }
578 return(*this);
579}
[804]580
[772]581// >>>> Operations avec 2nd membre de type tableau
[894]582//! Add two TArrays
[772]583template <class T>
[804]584TArray<T>& TArray<T>::AddElt(const TArray<T>& a)
[772]585{
[804]586 if (NbDimensions() < 1)
587 throw RangeCheckError("TArray<T>::AddElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]588 bool smo;
589 if (!CompareSizes(a, smo))
[813]590 throw(SzMismatchError("TArray<T>::AddElt(const TArray<T>&) SizeMismatch")) ;
[785]591
592 T * pe;
593 const T * pea;
[1156]594 sa_size_t j,k,ka;
[1099]595 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0)) { // regularly spaced elements
[1156]596 sa_size_t step = AvgStep();
597 sa_size_t stepa = a.AvgStep();
598 sa_size_t maxx = totsize_*step;
[785]599 pe = Data();
600 pea = a.Data();
601 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] += pea[ka] ;
[772]602 }
[785]603 else { // Non regular data spacing ...
[1156]604 int_4 ax,axa;
605 sa_size_t step, stepa;
606 sa_size_t gpas, naxa;
[1099]607 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]608 for(j=0; j<naxa; j++) {
609 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]610 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[785]611 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] += pea[ka];
612 }
613 }
[772]614 return(*this);
615}
616
[894]617//! Substract two TArrays
[970]618/*!
619Substract two TArrays *this = *this-a
620\param fginv == true : Perfoms the inverse subtraction (*this = a-(*this))
621*/
[772]622template <class T>
[970]623TArray<T>& TArray<T>::SubElt(const TArray<T>& a, bool fginv)
[772]624{
[804]625 if (NbDimensions() < 1)
626 throw RangeCheckError("TArray<T>::SubElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]627 bool smo;
628 if (!CompareSizes(a, smo))
[813]629 throw(SzMismatchError("TArray<T>::SubElt(const TArray<T>&) SizeMismatch")) ;
[785]630
631 T * pe;
632 const T * pea;
[1156]633 sa_size_t j,k,ka;
[1099]634 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[1156]635 sa_size_t step = AvgStep();
636 sa_size_t stepa = a.AvgStep();
637 sa_size_t maxx = totsize_*step;
[785]638 pe = Data();
639 pea = a.Data();
[970]640 if (fginv)
641 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]-pe[k] ;
642 else
643 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] -= pea[ka] ;
[772]644 }
[785]645 else { // Non regular data spacing ...
[1156]646 int_4 ax,axa;
647 sa_size_t step, stepa;
648 sa_size_t gpas, naxa;
[1099]649 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]650 for(j=0; j<naxa; j++) {
651 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]652 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[970]653 if (fginv)
654 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]-pe[k] ;
655 else
656 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] -= pea[ka];
[785]657 }
658 }
[772]659 return(*this);
660}
661
[970]662
[894]663//! Multiply two TArrays (elements by elements)
[772]664template <class T>
[804]665TArray<T>& TArray<T>::MulElt(const TArray<T>& a)
[772]666{
[804]667 if (NbDimensions() < 1)
668 throw RangeCheckError("TArray<T>::MulElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]669 bool smo;
670 if (!CompareSizes(a, smo))
[813]671 throw(SzMismatchError("TArray<T>::MulElt(const TArray<T>&) SizeMismatch")) ;
[785]672
673 T * pe;
674 const T * pea;
[1156]675 sa_size_t j,k,ka;
[1099]676 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[1156]677 sa_size_t step = AvgStep();
678 sa_size_t stepa = a.AvgStep();
679 sa_size_t maxx = totsize_*step;
[785]680 pe = Data();
681 pea = a.Data();
682 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] *= pea[ka] ;
[772]683 }
[785]684 else { // Non regular data spacing ...
[1156]685 int_4 ax,axa;
686 sa_size_t step, stepa;
687 sa_size_t gpas, naxa;
[1099]688 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]689 for(j=0; j<naxa; j++) {
[1099]690 pe = mNDBlock.Begin()+Offset(axa,j);
691 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[785]692 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] *= pea[ka];
693 }
694 }
[772]695 return(*this);
696}
697
[804]698
[894]699//! Divide two TArrays (elements by elements)
[970]700/*!
701Divide two TArrays *this = (*this)/a
702\param fginv == true : Perfoms the inverse division (*this = a/(*this))
[1072]703\param divzero == true : if a(i)==0. result is set to zero: (*this)(i)==0.
[970]704*/
[772]705template <class T>
[1072]706TArray<T>& TArray<T>::DivElt(const TArray<T>& a, bool fginv, bool divzero)
[772]707{
[804]708 if (NbDimensions() < 1)
709 throw RangeCheckError("TArray<T>::DivElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]710 bool smo;
711 if (!CompareSizes(a, smo))
[813]712 throw(SzMismatchError("TArray<T>::DivElt(const TArray<T>&) SizeMismatch")) ;
[785]713
714 T * pe;
715 const T * pea;
[1156]716 sa_size_t j,k,ka;
[1099]717 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[1156]718 sa_size_t step = AvgStep();
719 sa_size_t stepa = a.AvgStep();
720 sa_size_t maxx = totsize_*step;
[785]721 pe = Data();
722 pea = a.Data();
[1072]723 if(divzero) {
724 if (fginv)
725 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
726 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
727 else
728 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
729 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka] ;}
730 } else {
731 if (fginv)
732 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]/pe[k];
733 else
734 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] /= pea[ka] ;
735 }
[772]736 }
[785]737 else { // Non regular data spacing ...
[1156]738 int_4 ax,axa;
739 sa_size_t step, stepa;
740 sa_size_t gpas, naxa;
[1099]741 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]742 for(j=0; j<naxa; j++) {
743 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]744 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[1072]745 if(divzero) {
746 if (fginv)
747 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
748 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
749 else
750 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
751 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka];}
752 } else {
753 if (fginv)
754 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]/pe[k];
755 else
756 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] /= pea[ka];
757 }
[785]758 }
759 }
[772]760 return(*this);
761}
762
[894]763//! Copy elements of \b a
[804]764template <class T>
765TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
766{
767 if (NbDimensions() < 1)
768 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]769 bool smo;
770 if (!CompareSizes(a, smo))
[1050]771 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
[772]772
[804]773 T * pe;
774 const T * pea;
[1156]775 sa_size_t j,k,ka;
[1099]776 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[1156]777 sa_size_t step = AvgStep();
778 sa_size_t stepa = a.AvgStep();
779 sa_size_t maxx = totsize_*step;
[804]780 pe = Data();
781 pea = a.Data();
782 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka] ;
783 }
784 else { // Non regular data spacing ...
[1156]785 int_4 ax,axa;
786 sa_size_t step, stepa;
787 sa_size_t gpas, naxa;
[1099]788 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]789 for(j=0; j<naxa; j++) {
790 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]791 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[804]792 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka];
793 }
794 }
795 return(*this);
796}
797
[1081]798//! Converts and Copy elements of \b a
799template <class T>
800TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
801{
802 if (NbDimensions() < 1)
803 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]804 bool smo;
805 if (!CompareSizes(a, smo))
[1081]806 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
[804]807
[1081]808 T * pe;
[1156]809 sa_size_t j,k,ka;
810 sa_size_t offa;
[1081]811 // Non regular data spacing ...
[1156]812 int_4 ax,axa;
813 sa_size_t step, stepa;
814 sa_size_t gpas, naxa;
[1099]815 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[1081]816 for(j=0; j<naxa; j++) {
817 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]818 offa = a.Offset(axa,j);
[1085]819#if !defined(__GNUG__)
820 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
821#else
822 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
[1081]823 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
[1085]824#endif
[1081]825 }
826 return(*this);
827}
828
829
[804]830// Somme et produit des elements
[894]831//! Sum all elements
[804]832template <class T>
833T TArray<T>::Sum() const
834{
835 if (NbDimensions() < 1)
836 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
837 T ret=0;
838 const T * pe;
[1156]839 sa_size_t j,k;
[804]840 if (AvgStep() > 0) { // regularly spaced elements
[1156]841 sa_size_t step = AvgStep();
842 sa_size_t maxx = totsize_*step;
[804]843 pe = Data();
844 for(k=0; k<maxx; k+=step ) ret += pe[k];
845 }
846 else { // Non regular data spacing ...
[1156]847 int_4 ka = MaxSizeKA();
848 sa_size_t step = Step(ka);
849 sa_size_t gpas = Size(ka)*step;
850 sa_size_t naxa = Size()/Size(ka);
[813]851 for(j=0; j<naxa; j++) {
852 pe = mNDBlock.Begin()+Offset(ka,j);
[804]853 for(k=0; k<gpas; k+=step) ret += pe[k] ;
854 }
855 }
856 return ret;
857}
858
[894]859//! Multiply all elements
[804]860template <class T>
861T TArray<T>::Product() const
862{
863 if (NbDimensions() < 1)
864 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
[1113]865 T ret=(T)1;
[804]866 const T * pe;
[1156]867 sa_size_t j,k;
[804]868 if (AvgStep() > 0) { // regularly spaced elements
[1156]869 sa_size_t step = AvgStep();
870 sa_size_t maxx = totsize_*step;
[804]871 pe = Data();
872 for(k=0; k<maxx; k+=step ) ret *= pe[k];
873 }
874 else { // Non regular data spacing ...
[1156]875 int_4 ka = MaxSizeKA();
876 sa_size_t step = Step(ka);
877 sa_size_t gpas = Size(ka)*step;
878 sa_size_t naxa = Size()/Size(ka);
[813]879 for(j=0; j<naxa; j++) {
880 pe = mNDBlock.Begin()+Offset(ka,j);
[804]881 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
882 }
883 }
884 return ret;
885}
886
[1113]887//! Returns the sum of all elements squared (Sum
888template <class T>
889T TArray<T>::SumX2() const
890{
891 if (NbDimensions() < 1)
892 throw RangeCheckError("TArray<T>::SumX2() - Not Allocated Array ! ");
893 T ret=0;
894 const T * pe;
[1156]895 sa_size_t j,k;
[1113]896 if (AvgStep() > 0) { // regularly spaced elements
[1156]897 sa_size_t step = AvgStep();
898 sa_size_t maxx = totsize_*step;
[1113]899 pe = Data();
900 for(k=0; k<maxx; k+=step ) ret += pe[k]*pe[k];
901 }
902 else { // Non regular data spacing ...
[1156]903 int_4 ka = MaxSizeKA();
904 sa_size_t step = Step(ka);
905 sa_size_t gpas = Size(ka)*step;
906 sa_size_t naxa = Size()/Size(ka);
[1113]907 for(j=0; j<naxa; j++) {
908 pe = mNDBlock.Begin()+Offset(ka,j);
909 for(k=0; k<gpas; k+=step) ret += pe[k]*pe[k] ;
910 }
911 }
912 return ret;
913}
[804]914
[1113]915//! Return the minimum and the maximum values of the array elements
916/*!
917 This method generates an exception (\c MathExc) if called for complex arrays
918*/
919template <class T>
920void TArray<T>::MinMax(T& min, T& max) const
921{
922 const T * pe;
[1156]923 sa_size_t j,k;
924 int_4 ka = MaxSizeKA();
925 sa_size_t step = Step(ka);
926 sa_size_t gpas = Size(ka)*step;
927 sa_size_t naxa = Size()/Size(ka);
[1113]928 min = (*this)[0];
929 max = (*this)[0];
930 for(j=0; j<naxa; j++) {
931 pe = mNDBlock.Begin()+Offset(ka,j);
932 for(k=0; k<gpas; k+=step) {
933 if (pe[k]<min) min = pe[k];
934 else if (pe[k]>max) max = pe[k];
935 }
936 }
937 return;
938}
[804]939
[1113]940void TArray< complex<r_4> >::MinMax(complex<r_4>& min, complex<r_4>& max) const
941{
942 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
943}
944
945void TArray< complex<r_8> >::MinMax(complex<r_8>& min, complex<r_8>& max) const
946{
947 throw MathExc("TArray< complex<r_4> >::MinMax(...) - No order in complex");
948}
949
[772]950// ----------------------------------------------------
951// Impression, etc ...
952// ----------------------------------------------------
953
[894]954//! Return a string that contain the type \b T of the array
[772]955template <class T>
[813]956string TArray<T>::InfoString() const
[772]957{
[813]958 string rs = "TArray<" ;
959 rs += typeid(T).name();
960 rs += "> ";
[787]961 return(rs);
[772]962}
963
[894]964//! Print array
965/*!
966 \param os : output stream
967 \param maxprt : maximum numer of print
968 \param si : if true, display attached DvList
969 \sa SetMaxPrint
970 */
[772]971template <class T>
972void TArray<T>::Print(ostream& os, int_4 maxprt, bool si) const
973{
974 if (maxprt < 0) maxprt = max_nprt_;
[1156]975 sa_size_t npr = 0;
[772]976 Show(os, si);
[850]977 if (ndim_ < 1) return;
[1156]978 sa_size_t k0,k1,k2,k3,k4;
[772]979 for(k4=0; k4<size_[4]; k4++) {
[785]980 if (size_[4] > 1) cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
[772]981 for(k3=0; k3<size_[3]; k3++) {
[785]982 if (size_[3] > 1) cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
[772]983 for(k2=0; k2<size_[2]; k2++) {
[785]984 if (size_[2] > 1) cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
[772]985 for(k1=0; k1<size_[1]; k1++) {
[785]986 if ( (size_[1] > 1) && (size_[0] > 10) ) cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
[772]987 for(k0=0; k0<size_[0]; k0++) {
[785]988 if(k0 > 0) os << ", ";
989 os << Elem(k0, k1, k2, k3, k4); npr++;
[1156]990 if (npr >= (sa_size_t) maxprt) {
[772]991 if (npr < totsize_) os << "\n .... " << endl; return;
992 }
993 }
994 os << endl;
995 }
996 }
997 }
998 }
[813]999 os << endl;
[772]1000}
1001
1002
1003
1004///////////////////////////////////////////////////////////////
1005///////////////////////////////////////////////////////////////
1006#ifdef __CXX_PRAGMA_TEMPLATES__
[804]1007/*
[772]1008#pragma define_template TArray<uint_1>
[804]1009#pragma define_template TArray<int_2>
1010#pragma define_template TArray<uint_4>
1011#pragma define_template TArray<uint_8>
1012*/
[772]1013#pragma define_template TArray<uint_2>
1014#pragma define_template TArray<int_4>
1015#pragma define_template TArray<int_8>
1016#pragma define_template TArray<r_4>
1017#pragma define_template TArray<r_8>
1018#pragma define_template TArray< complex<r_4> >
1019#pragma define_template TArray< complex<r_8> >
1020#endif
1021
1022#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[804]1023/*
1024template class TArray<uint_1>;
1025template class TArray<int_2>;
1026template class TArray<uint_4>;
1027template class TArray<uint_8>;
1028*/
[772]1029template class TArray<uint_2>;
1030template class TArray<int_4>;
1031template class TArray<int_8>;
1032template class TArray<r_4>;
1033template class TArray<r_8>;
1034template class TArray< complex<r_4> >;
1035template class TArray< complex<r_8> >;
1036#endif
1037
1038
Note: See TracBrowser for help on using the repository browser.