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

Last change on this file since 2153 was 2153, checked in by ansari, 23 years ago

Un autre appel de l'operateur de conversion explicite ds tarray.cc , methode TArray<T>::SetSeq() , Reza 02/08/2002

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