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

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

Protection integrite TMatrix,TVector - operateur = (BaseArray & pour TVector et operations entre matrices avec <> MemMapping (Pas termine) Reza 27/6/2000

File size: 27.0 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>
[804]41TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, uint_4 step)
42 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1))
[772]43{
44 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, uint_4)";
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>
[804]53TArray<T>::TArray(uint_4 nx, uint_4 ny, uint_4 nz, uint_4 nt, uint_4 nu)
54 : BaseArray() , mNDBlock(nx*((ny>0)?ny:1)*((nz>0)?nz:1)*((nt>0)?nt:1)*((nu>0)?nu:1))
[772]55{
[787]56 uint_4 size[BASEARRAY_MAXNDIMS];
[772]57 size[0] = nx; size[1] = ny; size[2] = nz;
[804]58 size[3] = nt; size[4] = nu;
[772]59 int 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;
65 string exmsg = "TArray<T>::TArray(uint_4, uint_4, uint_4)";
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>
[804]79TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, NDataBlock<T> & db, bool share, uint_4 step, uint_8 offset)
80 : BaseArray() , mNDBlock(db, share)
[772]81{
82 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, NDataBlock<T> & ... )";
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>
[804]99TArray<T>::TArray(uint_4 ndim, const uint_4 * siz, T* values, uint_4 step, uint_8 offset, Bridge* br)
100 : BaseArray() , mNDBlock(ComputeTotalSize(ndim, siz, step, 1), values, br)
[772]101{
102 string exmsg = "TArray<T>::TArray(uint_4, uint_4 *, T* ... )";
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()";
202 if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) );
203 mNDBlock.CloneOrShare(a.mNDBlock);
204}
205
206//! Share data with a
207template <class T>
208void TArray<T>::Share(const TArray<T>& a)
209{
210 string exmsg = "TArray<T>::Share()";
211 if (!UpdateSizes(a.ndim_, a.size_, a.step_, a.offset_, exmsg)) throw( ParmError(exmsg) );
212 mNDBlock.Share(a.mNDBlock);
213}
214
215
[894]216//! Resize array
217/*!
218 \param ndim : number of dimensions
219 \param siz[ndim] : size along each dimension
220 \param step : step (same for all dimensions)
221 */
[772]222template <class T>
223void TArray<T>::ReSize(uint_4 ndim, uint_4 * siz, uint_4 step)
224{
[1099]225 if (arrtype_ != 0) {
226 if (ndim != 2)
227 throw( ParmError("TArray<T>::ReSize(ndim!=2,...) for Matrix" ) );
228 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
229 throw( ParmError("TArray<T>::ReSize(,siz[0]>1 && size[1]>1) for Vector" ) );
230 }
[772]231 string exmsg = "TArray<T>::ReSize()";
232 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
233 mNDBlock.ReSize(totsize_);
234}
235
[894]236//! Re-allocate space for array
237/*!
238 \param ndim : number of dimensions
239 \param siz[ndim] : size along each dimension
240 \param step : step (same for all dimensions)
241 \param force : if true re-allocation is forced, if not it occurs
242 only if the required space is greater than the old one.
243 */
[772]244template <class T>
245void TArray<T>::Realloc(uint_4 ndim, uint_4 * siz, uint_4 step, bool force)
246{
[1099]247 if (arrtype_ != 0) {
248 if (ndim != 2)
249 throw( ParmError("TArray<T>::Realloc(ndim!=2,...) for Matrix" ) );
250 if ((arrtype_ == 2) && (siz[0] > 1) && (siz[1] > 1))
251 throw( ParmError("TArray<T>::Realloc(,siz[0]>1 && size[1]>1) for Vector" ) );
252 }
[772]253 string exmsg = "TArray<T>::Realloc()";
254 if (!UpdateSizes(ndim, siz, step, 0, exmsg)) throw( ParmError(exmsg) );
255 mNDBlock.ReSize(totsize_);
256}
257
[787]258
[894]259//! Compact dimensions in one or more is equal to 1.
[772]260template <class T>
[787]261TArray<T>& TArray<T>::CompactAllDimensions()
[772]262{
[787]263 CompactAllDim();
264 return(*this);
[772]265}
266
[894]267//! Compact dimensions if the last one is equal to 1.
[785]268template <class T>
[787]269TArray<T>& TArray<T>::CompactTrailingDimensions()
[785]270{
[787]271 CompactTrailingDim();
[785]272 return(*this);
273}
274
[894]275//! Give value (in \b double) for element at position \b ip..
[785]276template <class T>
[1081]277MuTyV & TArray<T>::ValueAtPosition(uint_8 ip) const
[785]278{
[787]279#ifdef SO_BOUNDCHECKING
280 if (ip >= totsize_) throw( ParmError("TArray<T>::ValueAtPosition(uint_8 ip) Out-of-bound Error") );
281#endif
[1081]282 my_mtv = *(mNDBlock.Begin()+Offset(ip));
283 return( my_mtv );
[785]284}
285
[894]286//! Return array with elements packed
287/*!
288 \param force : if true, pack elements in a new array.
289 If false and array is already packed, return
290 an array that share data with the current one.
291 \return packed array
292 */
[804]293template <class T>
294TArray<T> TArray<T>::PackElements(bool force) const
295{
296 if (NbDimensions() < 1)
297 throw RangeCheckError("TArray<T>::PackElements() - Not Allocated Array ! ");
298 if ( !force && (AvgStep() == 1) ) {
[970]299 TArray<T> ra;
300 ra.Share(*this);
[804]301 ra.SetTemp(true);
302 return(ra);
303 }
304 else {
305 TArray<T> ra(ndim_, size_, 1);
306 ra.CopyElt(*this);
307 ra.SetTemp(true);
308 return(ra);
309 }
310}
311
[785]312// SubArrays
[804]313// $CHECK$ Reza 03/2000 Doit-on declarer cette methode const ?
[894]314//! Extract a sub-array
315/*!
316 \param rx,ry,rz,rt,ru : range of extraction along dimensions
317 \sa Range
318 */
[785]319template <class T>
[804]320TArray<T> TArray<T>::SubArray(Range rx, Range ry, Range rz, Range rt, Range ru) const
[785]321{
[804]322 if (NbDimensions() < 1)
323 throw RangeCheckError("TArray<T>::operator () (Range, ...) - Not Allocated Array ! ");
[785]324 uint_4 ndim = 0;
[787]325 uint_4 size[BASEARRAY_MAXNDIMS];
326 uint_4 step[BASEARRAY_MAXNDIMS];
327 uint_4 pos[BASEARRAY_MAXNDIMS];
[785]328 size[0] = rx.Size();
329 size[1] = ry.Size();
330 size[2] = rz.Size();
331 size[3] = rt.Size();
332 size[4] = ru.Size();
333
334 step[0] = rx.Step();
335 step[1] = ry.Step();
336 step[2] = rz.Step();
337 step[3] = rt.Step();
338 step[4] = ru.Step();
339
340 pos[0] = rx.Start();
341 pos[1] = ry.Start();
342 pos[2] = rz.Start();
343 pos[3] = rt.Start();
344 pos[4] = ru.Start();
345
346 ndim = ndim_;
347 TArray<T> ra;
[804]348 UpdateSubArraySizes(ra, ndim, size, pos, step);
[787]349 ra.DataBlock().Share(this->DataBlock());
[785]350 ra.SetTemp(true);
351 return(ra);
352}
353
[772]354// ...... Operation de calcul sur les tableaux ......
355// ------- Attention --------
356// Boucles normales prenant en compte les steps ....
[894]357// Possibilite de // , vectorisation
358
359//! Fill TArray with Sequence \b seq
360/*!
361 \param seq : sequence to fill the array
362 \sa Sequence
363 */
[772]364template <class T>
[813]365TArray<T>& TArray<T>::SetSeq(Sequence seq)
[772]366{
[804]367 if (NbDimensions() < 1)
[813]368 throw RangeCheckError("TArray<T>::SetSeq(Sequence ) - Not Allocated Array ! ");
[785]369 T * pe;
370 uint_8 j,k;
371 if (AvgStep() > 0) { // regularly spaced elements
372 uint_8 step = AvgStep();
373 pe = Data();
[958]374 for(k=0; k<totsize_; k++ ) pe[k*step] = (T) seq(k);
[785]375 }
376 else { // Non regular data spacing ...
[813]377 // uint_4 ka = MaxSizeKA();
378 uint_4 ka = 0;
[785]379 uint_8 step = Step(ka);
380 uint_8 gpas = Size(ka);
[813]381 uint_8 naxa = Size()/Size(ka);
382 for(j=0; j<naxa; j++) {
383 pe = mNDBlock.Begin()+Offset(ka,j);
[958]384 for(k=0; k<gpas; k++) pe[k*step] = (T) seq(j*gpas+k);
[785]385 }
386 }
[772]387 return(*this);
388}
389
390// >>>> Operations avec 2nd membre de type scalaire
391
[894]392//! Fill an array with a constant value \b x
[772]393template <class T>
[813]394TArray<T>& TArray<T>::SetT(T x)
[772]395{
[804]396 if (NbDimensions() < 1)
[813]397 throw RangeCheckError("TArray<T>::SetT(T ) - Not Allocated Array ! ");
[785]398 T * pe;
399 uint_8 j,k;
400 if (AvgStep() > 0) { // regularly spaced elements
401 uint_8 step = AvgStep();
402 uint_8 maxx = totsize_*step;
403 pe = Data();
404 for(k=0; k<maxx; k+=step ) pe[k] = x;
405 }
406 else { // Non regular data spacing ...
407 uint_4 ka = MaxSizeKA();
408 uint_8 step = Step(ka);
409 uint_8 gpas = Size(ka)*step;
[813]410 uint_8 naxa = Size()/Size(ka);
411 for(j=0; j<naxa; j++) {
412 pe = mNDBlock.Begin()+Offset(ka,j);
[785]413 for(k=0; k<gpas; k+=step) pe[k] = x;
414 }
415 }
[772]416 return(*this);
417}
418
[894]419//! Add a constant value \b x to an array
[772]420template <class T>
[804]421TArray<T>& TArray<T>::Add(T x)
[772]422{
[804]423 if (NbDimensions() < 1)
424 throw RangeCheckError("TArray<T>::Add(T ) - Not Allocated Array ! ");
[785]425 T * pe;
426 uint_8 j,k;
427 if (AvgStep() > 0) { // regularly spaced elements
428 uint_8 step = AvgStep();
429 uint_8 maxx = totsize_*step;
430 pe = Data();
431 for(k=0; k<maxx; k+=step ) pe[k] += x;
432 }
433 else { // Non regular data spacing ...
434 uint_4 ka = MaxSizeKA();
435 uint_8 step = Step(ka);
436 uint_8 gpas = Size(ka)*step;
[813]437 uint_8 naxa = Size()/Size(ka);
438 for(j=0; j<naxa; j++) {
439 pe = mNDBlock.Begin()+Offset(ka,j);
[785]440 for(k=0; k<gpas; k+=step) pe[k] += x;
441 }
442 }
[772]443 return(*this);
444}
445
[894]446//! Substract a constant value \b x to an array
[970]447/*!
448Substract a constant from the *this = *this-x
449\param fginv == true : Perfoms the inverse subtraction (*this = x-(*this))
450*/
[772]451template <class T>
[970]452TArray<T>& TArray<T>::Sub(T x, bool fginv)
[772]453{
[804]454 if (NbDimensions() < 1)
455 throw RangeCheckError("TArray<T>::Sub(T ) - Not Allocated Array ! ");
[785]456 T * pe;
457 uint_8 j,k;
458 if (AvgStep() > 0) { // regularly spaced elements
459 uint_8 step = AvgStep();
460 uint_8 maxx = totsize_*step;
461 pe = Data();
[970]462 if (fginv)
463 for(k=0; k<maxx; k+=step ) pe[k] = x-pe[k];
464 else
465 for(k=0; k<maxx; k+=step ) pe[k] -= x;
[785]466 }
467 else { // Non regular data spacing ...
468 uint_4 ka = MaxSizeKA();
469 uint_8 step = Step(ka);
470 uint_8 gpas = Size(ka)*step;
[813]471 uint_8 naxa = Size()/Size(ka);
472 for(j=0; j<naxa; j++) {
473 pe = mNDBlock.Begin()+Offset(ka,j);
[970]474 if (fginv)
475 for(k=0; k<gpas; k+=step) pe[k] = x-pe[k];
476 else
477 for(k=0; k<gpas; k+=step) pe[k] -= x;
[785]478 }
479 }
[772]480 return(*this);
481}
482
[894]483//! Multiply an array by a constant value \b x
[772]484template <class T>
[804]485TArray<T>& TArray<T>::Mul(T x)
[772]486{
[804]487 if (NbDimensions() < 1)
488 throw RangeCheckError("TArray<T>::Mul(T ) - Not Allocated Array ! ");
[785]489 T * pe;
490 uint_8 j,k;
491 if (AvgStep() > 0) { // regularly spaced elements
492 uint_8 step = AvgStep();
493 uint_8 maxx = totsize_*step;
494 pe = Data();
495 for(k=0; k<maxx; k+=step ) pe[k] *= x;
496 }
497 else { // Non regular data spacing ...
498 uint_4 ka = MaxSizeKA();
499 uint_8 step = Step(ka);
500 uint_8 gpas = Size(ka)*step;
[813]501 uint_8 naxa = Size()/Size(ka);
502 for(j=0; j<naxa; j++) {
503 pe = mNDBlock.Begin()+Offset(ka,j);
[785]504 for(k=0; k<gpas; k+=step) pe[k] *= x;
505 }
506 }
[772]507 return(*this);
508}
509
[894]510//! Divide an array by a constant value \b x
[970]511/*!
512Divide the array by a constant *this = *this/x
513\param fginv == true : Perfoms the inverse division (*this = x/(*this))
514*/
[772]515template <class T>
[970]516TArray<T>& TArray<T>::Div(T x, bool fginv)
[772]517{
[804]518 if (NbDimensions() < 1)
519 throw RangeCheckError("TArray<T>::Div(T ) - Not Allocated Array ! ");
[970]520 if (!fginv && (x == (T) 0) )
[894]521 throw MathExc("TArray<T>::Div(T ) - Divide by zero ! ");
[785]522 T * pe;
523 uint_8 j,k;
524 if (AvgStep() > 0) { // regularly spaced elements
525 uint_8 step = AvgStep();
526 uint_8 maxx = totsize_*step;
527 pe = Data();
[970]528 if (fginv)
529 for(k=0; k<maxx; k+=step ) pe[k] = x/pe[k];
530 else
531 for(k=0; k<maxx; k+=step ) pe[k] /= x;
[785]532 }
533 else { // Non regular data spacing ...
534 uint_4 ka = MaxSizeKA();
535 uint_8 step = Step(ka);
536 uint_8 gpas = Size(ka)*step;
[813]537 uint_8 naxa = Size()/Size(ka);
538 for(j=0; j<naxa; j++) {
539 pe = mNDBlock.Begin()+Offset(ka,j);
[970]540 if (fginv)
541 for(k=0; k<gpas; k+=step) pe[k] = x/pe[k];
542 else
543 for(k=0; k<gpas; k+=step) pe[k] /= x;
[785]544 }
545 }
[772]546 return(*this);
547}
548
549
[804]550
551
[772]552// >>>> Operations avec 2nd membre de type tableau
[894]553//! Add two TArrays
[772]554template <class T>
[804]555TArray<T>& TArray<T>::AddElt(const TArray<T>& a)
[772]556{
[804]557 if (NbDimensions() < 1)
558 throw RangeCheckError("TArray<T>::AddElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]559 bool smo;
560 if (!CompareSizes(a, smo))
[813]561 throw(SzMismatchError("TArray<T>::AddElt(const TArray<T>&) SizeMismatch")) ;
[785]562
563 T * pe;
564 const T * pea;
565 uint_8 j,k,ka;
[1099]566 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0)) { // regularly spaced elements
[785]567 uint_8 step = AvgStep();
568 uint_8 stepa = a.AvgStep();
569 uint_8 maxx = totsize_*step;
570 pe = Data();
571 pea = a.Data();
572 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] += pea[ka] ;
[772]573 }
[785]574 else { // Non regular data spacing ...
[1099]575 int ax,axa;
576 uint_8 step, stepa;
577 uint_8 gpas, naxa;
578 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]579 for(j=0; j<naxa; j++) {
580 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]581 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[785]582 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] += pea[ka];
583 }
584 }
[772]585 return(*this);
586}
587
[894]588//! Substract two TArrays
[970]589/*!
590Substract two TArrays *this = *this-a
591\param fginv == true : Perfoms the inverse subtraction (*this = a-(*this))
592*/
[772]593template <class T>
[970]594TArray<T>& TArray<T>::SubElt(const TArray<T>& a, bool fginv)
[772]595{
[804]596 if (NbDimensions() < 1)
597 throw RangeCheckError("TArray<T>::SubElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]598 bool smo;
599 if (!CompareSizes(a, smo))
[813]600 throw(SzMismatchError("TArray<T>::SubElt(const TArray<T>&) SizeMismatch")) ;
[785]601
602 T * pe;
603 const T * pea;
604 uint_8 j,k,ka;
[1099]605 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[785]606 uint_8 step = AvgStep();
607 uint_8 stepa = a.AvgStep();
608 uint_8 maxx = totsize_*step;
609 pe = Data();
610 pea = a.Data();
[970]611 if (fginv)
612 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]-pe[k] ;
613 else
614 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] -= pea[ka] ;
[772]615 }
[785]616 else { // Non regular data spacing ...
[1099]617 int ax,axa;
618 uint_8 step, stepa;
619 uint_8 gpas, naxa;
620 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]621 for(j=0; j<naxa; j++) {
622 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]623 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[970]624 if (fginv)
625 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]-pe[k] ;
626 else
627 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] -= pea[ka];
[785]628 }
629 }
[772]630 return(*this);
631}
632
[970]633
[894]634//! Multiply two TArrays (elements by elements)
[772]635template <class T>
[804]636TArray<T>& TArray<T>::MulElt(const TArray<T>& a)
[772]637{
[804]638 if (NbDimensions() < 1)
639 throw RangeCheckError("TArray<T>::MulElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]640 bool smo;
641 if (!CompareSizes(a, smo))
[813]642 throw(SzMismatchError("TArray<T>::MulElt(const TArray<T>&) SizeMismatch")) ;
[785]643
644 T * pe;
645 const T * pea;
646 uint_8 j,k,ka;
[1099]647 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[785]648 uint_8 step = AvgStep();
649 uint_8 stepa = a.AvgStep();
650 uint_8 maxx = totsize_*step;
651 pe = Data();
652 pea = a.Data();
653 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] *= pea[ka] ;
[772]654 }
[785]655 else { // Non regular data spacing ...
[1099]656 int ax,axa;
657 uint_8 step, stepa;
658 uint_8 gpas, naxa;
659 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]660 for(j=0; j<naxa; j++) {
[1099]661 pe = mNDBlock.Begin()+Offset(axa,j);
662 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[785]663 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] *= pea[ka];
664 }
665 }
[772]666 return(*this);
667}
668
[804]669
[894]670//! Divide two TArrays (elements by elements)
[970]671/*!
672Divide two TArrays *this = (*this)/a
673\param fginv == true : Perfoms the inverse division (*this = a/(*this))
[1072]674\param divzero == true : if a(i)==0. result is set to zero: (*this)(i)==0.
[970]675*/
[772]676template <class T>
[1072]677TArray<T>& TArray<T>::DivElt(const TArray<T>& a, bool fginv, bool divzero)
[772]678{
[804]679 if (NbDimensions() < 1)
680 throw RangeCheckError("TArray<T>::DivElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]681 bool smo;
682 if (!CompareSizes(a, smo))
[813]683 throw(SzMismatchError("TArray<T>::DivElt(const TArray<T>&) SizeMismatch")) ;
[785]684
685 T * pe;
686 const T * pea;
687 uint_8 j,k,ka;
[1099]688 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[785]689 uint_8 step = AvgStep();
690 uint_8 stepa = a.AvgStep();
691 uint_8 maxx = totsize_*step;
692 pe = Data();
693 pea = a.Data();
[1072]694 if(divzero) {
695 if (fginv)
696 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
697 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
698 else
699 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
700 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka] ;}
701 } else {
702 if (fginv)
703 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka]/pe[k];
704 else
705 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] /= pea[ka] ;
706 }
[772]707 }
[785]708 else { // Non regular data spacing ...
[1099]709 int ax,axa;
710 uint_8 step, stepa;
711 uint_8 gpas, naxa;
712 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]713 for(j=0; j<naxa; j++) {
714 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]715 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[1072]716 if(divzero) {
717 if (fginv)
718 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
719 {if(pe[k]==(T)0) pe[k] = (T)0; else pe[k] = pea[ka]/pe[k];}
720 else
721 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
722 {if(pea[k]==(T)0) pe[k] = (T)0; else pe[k] /= pea[ka];}
723 } else {
724 if (fginv)
725 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka]/pe[k];
726 else
727 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] /= pea[ka];
728 }
[785]729 }
730 }
[772]731 return(*this);
732}
733
[894]734//! Copy elements of \b a
[804]735template <class T>
736TArray<T>& TArray<T>::CopyElt(const TArray<T>& a)
737{
738 if (NbDimensions() < 1)
739 throw RangeCheckError("TArray<T>::CopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]740 bool smo;
741 if (!CompareSizes(a, smo))
[1050]742 throw(SzMismatchError("TArray<T>::CopyElt(const TArray<T>&) SizeMismatch")) ;
[772]743
[804]744 T * pe;
745 const T * pea;
746 uint_8 j,k,ka;
[1099]747 if (smo && (AvgStep() > 0) && (a.AvgStep() > 0) ) { // regularly spaced elements
[804]748 uint_8 step = AvgStep();
749 uint_8 stepa = a.AvgStep();
750 uint_8 maxx = totsize_*step;
751 pe = Data();
752 pea = a.Data();
753 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa ) pe[k] = pea[ka] ;
754 }
755 else { // Non regular data spacing ...
[1099]756 int ax,axa;
757 uint_8 step, stepa;
758 uint_8 gpas, naxa;
759 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[813]760 for(j=0; j<naxa; j++) {
761 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]762 pea = a.DataBlock().Begin()+a.Offset(axa,j);
[804]763 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = pea[ka];
764 }
765 }
766 return(*this);
767}
768
[1081]769//! Converts and Copy elements of \b a
770template <class T>
771TArray<T>& TArray<T>::ConvertAndCopyElt(const BaseArray& a)
772{
773 if (NbDimensions() < 1)
774 throw RangeCheckError("TArray<T>::ConvertAndCopyElt(const TArray<T>& ) - Not Allocated Array ! ");
[1099]775 bool smo;
776 if (!CompareSizes(a, smo))
[1081]777 throw(SzMismatchError("TArray<T>::ConvertAndCopyElt(const TArray<T>&) SizeMismatch")) ;
[804]778
[1081]779 T * pe;
780 uint_8 j,k,ka;
781 uint_8 offa;
782 // Non regular data spacing ...
[1099]783 int ax,axa;
784 uint_8 step, stepa;
785 uint_8 gpas, naxa;
786 GetOpeParams(a, smo, ax, axa, step, stepa, gpas, naxa);
[1081]787 for(j=0; j<naxa; j++) {
788 pe = mNDBlock.Begin()+Offset(ax,j);
[1099]789 offa = a.Offset(axa,j);
[1085]790#if !defined(__GNUG__)
791 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = (T)a.ValueAtPosition(offa+ka);
792#else
793 // g++ (up to 2.95.1) se melange les pinceaux s'il y a le cast (T) pour l'instanciation des complexes
[1081]794 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa) pe[k] = a.ValueAtPosition(offa+ka);
[1085]795#endif
[1081]796 }
797 return(*this);
798}
799
800
[804]801// Somme et produit des elements
[894]802//! Sum all elements
[804]803template <class T>
804T TArray<T>::Sum() const
805{
806 if (NbDimensions() < 1)
807 throw RangeCheckError("TArray<T>::Sum() - Not Allocated Array ! ");
808 T ret=0;
809 const T * pe;
810 uint_8 j,k;
811 if (AvgStep() > 0) { // regularly spaced elements
812 uint_8 step = AvgStep();
813 uint_8 maxx = totsize_*step;
814 pe = Data();
815 for(k=0; k<maxx; k+=step ) ret += pe[k];
816 }
817 else { // Non regular data spacing ...
818 uint_4 ka = MaxSizeKA();
819 uint_8 step = Step(ka);
820 uint_8 gpas = Size(ka)*step;
[813]821 uint_8 naxa = Size()/Size(ka);
822 for(j=0; j<naxa; j++) {
823 pe = mNDBlock.Begin()+Offset(ka,j);
[804]824 for(k=0; k<gpas; k+=step) ret += pe[k] ;
825 }
826 }
827 return ret;
828}
829
[894]830//! Multiply all elements
[804]831template <class T>
832T TArray<T>::Product() const
833{
834 if (NbDimensions() < 1)
835 throw RangeCheckError("TArray<T>::Product() - Not Allocated Array ! ");
836 T ret=0;
837 const T * pe;
838 uint_8 j,k;
839 if (AvgStep() > 0) { // regularly spaced elements
840 uint_8 step = AvgStep();
841 uint_8 maxx = totsize_*step;
842 pe = Data();
843 for(k=0; k<maxx; k+=step ) ret *= pe[k];
844 }
845 else { // Non regular data spacing ...
846 uint_4 ka = MaxSizeKA();
847 uint_8 step = Step(ka);
848 uint_8 gpas = Size(ka)*step;
[813]849 uint_8 naxa = Size()/Size(ka);
850 for(j=0; j<naxa; j++) {
851 pe = mNDBlock.Begin()+Offset(ka,j);
[804]852 for(k=0; k<gpas; k+=step) ret *= pe[k] ;
853 }
854 }
855 return ret;
856}
857
858
859
[772]860// ----------------------------------------------------
861// Impression, etc ...
862// ----------------------------------------------------
863
[894]864//! Return a string that contain the type \b T of the array
[772]865template <class T>
[813]866string TArray<T>::InfoString() const
[772]867{
[813]868 string rs = "TArray<" ;
869 rs += typeid(T).name();
870 rs += "> ";
[787]871 return(rs);
[772]872}
873
[894]874//! Print array
875/*!
876 \param os : output stream
877 \param maxprt : maximum numer of print
878 \param si : if true, display attached DvList
879 \sa SetMaxPrint
880 */
[772]881template <class T>
882void TArray<T>::Print(ostream& os, int_4 maxprt, bool si) const
883{
884 if (maxprt < 0) maxprt = max_nprt_;
[958]885 uint_4 npr = 0;
[772]886 Show(os, si);
[850]887 if (ndim_ < 1) return;
[804]888 uint_4 k0,k1,k2,k3,k4;
[772]889 for(k4=0; k4<size_[4]; k4++) {
[785]890 if (size_[4] > 1) cout << "\n ----- Dimension 5 (U) K4= " << k4 << endl;
[772]891 for(k3=0; k3<size_[3]; k3++) {
[785]892 if (size_[3] > 1) cout << "\n ----- Dimension 4 (T) K3= " << k3 << endl;
[772]893 for(k2=0; k2<size_[2]; k2++) {
[785]894 if (size_[2] > 1) cout << "\n ----- Dimension 3 (Z) K2= " << k2 << endl;
[772]895 for(k1=0; k1<size_[1]; k1++) {
[785]896 if ( (size_[1] > 1) && (size_[0] > 10) ) cout << "----- Dimension 2 (Y) K1= " << k1 << endl;
[772]897 for(k0=0; k0<size_[0]; k0++) {
[785]898 if(k0 > 0) os << ", ";
899 os << Elem(k0, k1, k2, k3, k4); npr++;
[958]900 if (npr >= (uint_4) maxprt) {
[772]901 if (npr < totsize_) os << "\n .... " << endl; return;
902 }
903 }
904 os << endl;
905 }
906 }
907 }
908 }
[813]909 os << endl;
[772]910}
911
912
913
914///////////////////////////////////////////////////////////////
915///////////////////////////////////////////////////////////////
916#ifdef __CXX_PRAGMA_TEMPLATES__
[804]917/*
[772]918#pragma define_template TArray<uint_1>
[804]919#pragma define_template TArray<int_2>
920#pragma define_template TArray<uint_4>
921#pragma define_template TArray<uint_8>
922*/
[772]923#pragma define_template TArray<uint_2>
924#pragma define_template TArray<int_4>
925#pragma define_template TArray<int_8>
926#pragma define_template TArray<r_4>
927#pragma define_template TArray<r_8>
928#pragma define_template TArray< complex<r_4> >
929#pragma define_template TArray< complex<r_8> >
930#endif
931
932#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[804]933/*
934template class TArray<uint_1>;
935template class TArray<int_2>;
936template class TArray<uint_4>;
937template class TArray<uint_8>;
938*/
[772]939template class TArray<uint_2>;
940template class TArray<int_4>;
941template class TArray<int_8>;
942template class TArray<r_4>;
943template class TArray<r_8>;
944template class TArray< complex<r_4> >;
945template class TArray< complex<r_8> >;
946#endif
947
948
Note: See TracBrowser for help on using the repository browser.