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

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

remplacement template <> pour SGI-CC par DECL_TEMP_SPEC - Reza 10/03/2003

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