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

Last change on this file since 2421 was 2322, checked in by cmv, 23 years ago
  • passage xxstream.h en xxstream
  • compile avec gcc_3.2, gcc_2.96 et cxx En 3.2 le seek from ::end semble marcher (voir Eval/COS/pbseekios.cc)

rz+cmv 11/2/2003

File size: 14.6 KB
Line 
1// Usuall mathematical functions and operations on arrays
2// R. Ansari, C.Magneville 03/2000
3
4#include "machdefs.h"
5#include <math.h>
6#include "matharr.h"
7
8// ----------------------------------------------------
9// Application d'une fonction
10// ----------------------------------------------------
11
12/*!
13 \class SOPHYA::MathArray
14 \ingroup TArray
15 Class for simple mathematical operation on arrays
16 \warning Instanciated only for \b real and \b double (r_4, r_8) type arrays
17*/
18
19//! Apply Function In Place (function double version)
20/*!
21 \param a : array to be replaced in place
22 \param f : function for replacement
23 \return Return an array \b a filled with function f(a(i,j))
24*/
25template <class T>
26TArray<T>& MathArray<T>::ApplyFunctionInPlace(TArray<T> & a, Arr_DoubleFunctionOfX f)
27{
28 if (a.NbDimensions() < 1)
29 throw RangeCheckError("MathArray<T>::ApplyFunctionInPlace(TArray<T> & a..) Not Allocated Array a !");
30 T * pe;
31 sa_size_t j,k;
32 if (a.AvgStep() > 0) { // regularly spaced elements
33 sa_size_t step = a.AvgStep();
34 sa_size_t maxx = a.Size()*step;
35 pe = a.Data();
36 for(k=0; k<maxx; k+=step ) pe[k] = (T)(f((double)pe[k]));
37 }
38 else { // Non regular data spacing ...
39 int_4 ka = a.MaxSizeKA();
40 sa_size_t step = a.Step(ka);
41 sa_size_t gpas = a.Size(ka)*step;
42 sa_size_t naxa = a.Size()/a.Size(ka);
43 for(j=0; j<naxa; j++) {
44 pe = a.DataBlock().Begin()+a.Offset(ka,j);
45 for(k=0; k<gpas; k+=step) pe[k] = (T)(f((double)pe[k]));
46 }
47 }
48 return(a);
49}
50
51//! Apply Function In Place (function float version)
52/*!
53 \param a : array to be replaced in place
54 \param f : function for replacement
55 \return Return an array \b a filled with function f(a(i,j))
56*/
57template <class T>
58TArray<T>& MathArray<T>::ApplyFunctionInPlaceF(TArray<T> & a, Arr_FloatFunctionOfX f)
59{
60 if (a.NbDimensions() < 1)
61 throw RangeCheckError("MathArray<T>::ApplyFunctionInPlaceF(TArray<T> & a..) Not Allocated Array a !");
62 T * pe;
63 sa_size_t j,k;
64 if (a.AvgStep() > 0) { // regularly spaced elements
65 sa_size_t step = a.AvgStep();
66 sa_size_t maxx = a.Size()*step;
67 pe = a.Data();
68 for(k=0; k<maxx; k+=step ) pe[k] = (T)(f((float)pe[k]));
69 }
70 else { // Non regular data spacing ...
71 int_4 ka = a.MaxSizeKA();
72 sa_size_t step = a.Step(ka);
73 sa_size_t gpas = a.Size(ka)*step;
74 sa_size_t naxa = a.Size()/a.Size(ka);
75 for(j=0; j<naxa; j++) {
76 pe = a.DataBlock().Begin()+a.Offset(ka,j);
77 for(k=0; k<gpas; k+=step) pe[k] = (T)(f((float)pe[k]));
78 }
79 }
80 return(a);
81}
82
83
84//! Apply Function (function double version)
85/*!
86 \param a : argument array of the function
87 \param f : function for replacement
88 \return Return a new array filled with function f(a(i,j))
89*/
90template <class T>
91TArray<T> MathArray<T>::ApplyFunction(TArray<T> const & a, Arr_DoubleFunctionOfX f)
92{
93 TArray<T> ra;
94 ra = a;
95 ApplyFunctionInPlace(ra, f);
96 return(ra);
97}
98
99//! Apply Function (function float version)
100/*!
101 \param a : argument array of the function
102 \param f : function for replacement
103 \return Return a new array filled with function f(a(i,j))
104*/
105template <class T>
106TArray<T> MathArray<T>::ApplyFunctionF(TArray<T> const & a, Arr_FloatFunctionOfX f)
107{
108 TArray<T> ra;
109 ra = a;
110 ApplyFunctionInPlaceF(ra, f);
111 return(ra);
112}
113
114//! Compute \b mean and \b sigma of elements of array \b a, return \b mean
115template <class T>
116double MathArray<T>::MeanSigma(TArray<T> const & a, double & mean, double & sig)
117{
118 if (a.NbDimensions() < 1)
119 throw RangeCheckError("MathArray<T>::MeanSigma(TArray<T> const & a..) Not Allocated Array a !");
120 const T * pe;
121 sa_size_t j,k;
122 mean=0.;
123 sig = 0.;
124 double valok;
125 if (a.AvgStep() > 0) { // regularly spaced elements
126 sa_size_t step = a.AvgStep();
127 sa_size_t maxx = a.Size()*step;
128 pe = a.Data();
129 for(k=0; k<maxx; k+=step ) {
130 valok = (double) pe[k];
131 mean += valok; sig += valok*valok;
132 }
133 }
134 else { // Non regular data spacing ...
135 int_4 ka = a.MaxSizeKA();
136 sa_size_t step = a.Step(ka);
137 sa_size_t gpas = a.Size(ka)*step;
138 sa_size_t naxa = a.Size()/a.Size(ka);
139 for(j=0; j<naxa; j++) {
140 pe = a.DataBlock().Begin()+a.Offset(ka,j);
141 for(k=0; k<gpas; k+=step) {
142 valok = (double) pe[k];
143 mean += valok; sig += valok*valok;
144 }
145 }
146 }
147 double dsz = (double)(a.Size());
148 mean /= dsz;
149 sig = sig/dsz - mean*mean;
150 if (sig >= 0.) sig = sqrt(sig);
151 return(mean);
152}
153
154
155//-------------------------------------------------------------------------------
156// Definition utilitaire d'application de fonction
157inline complex<r_8> ApplyComplexDoubleFunction(complex<r_8> z,
158 Arr_ComplexDoubleFunctionOfX f)
159{
160 return(f(z));
161}
162
163inline complex<r_4> ApplyComplexDoubleFunction(complex<r_4> z,
164 Arr_ComplexDoubleFunctionOfX f)
165{
166 complex<r_8> zd((r_8)z.real(), (r_8)z.imag());
167 zd = f(zd);
168 complex<r_4> zr((r_4)zd.real(), (r_4)zd.imag());
169 return(zr);
170}
171
172//-------------------------------------------------------------------------------
173
174/*!
175 \class SOPHYA::ComplexMathArray
176 \ingroup TArray
177 Class for simple mathematical operation on arrays
178 \warning Instanciated only for \b real and \b double (r_4, r_8) complex arrays
179*/
180
181//! Apply Function In Place (complex arrays)
182/*!
183 \param a : complex array to be replaced in place
184 \param f : function for replacement
185 \return Return an array \b a filled with function f(a(i,j))
186*/
187template <class T>
188TArray< complex<T> >& ComplexMathArray<T>::ApplyFunctionInPlace(TArray< complex<T> > & a, Arr_ComplexDoubleFunctionOfX f)
189{
190 if (a.NbDimensions() < 1)
191 throw RangeCheckError("ComplexMathArray< complex<T> >::ApplyFunctionInPlace(TArray< complex<T> > & a..) Not Allocated Array a !");
192 complex<T> * pe;
193 sa_size_t j,k;
194 if (a.AvgStep() > 0) { // regularly spaced elements
195 sa_size_t step = a.AvgStep();
196 sa_size_t maxx = a.Size()*step;
197 pe = a.Data();
198 for(k=0; k<maxx; k+=step ) pe[k] = ApplyComplexDoubleFunction(pe[k],f);
199 }
200 else { // Non regular data spacing ...
201 int_4 ka = a.MaxSizeKA();
202 sa_size_t step = a.Step(ka);
203 sa_size_t gpas = a.Size(ka)*step;
204 sa_size_t naxa = a.Size()/a.Size(ka);
205 for(j=0; j<naxa; j++) {
206 pe = a.DataBlock().Begin()+a.Offset(ka,j);
207 for(k=0; k<gpas; k+=step) pe[k] = ApplyComplexDoubleFunction(pe[k],f);
208 }
209 }
210 return(a);
211}
212
213
214
215//! Apply Function (complex arrays)
216/*!
217 \param a : argument array of the function
218 \param f : function for replacement
219 \return Return a new array filled with function f(a(i,j))
220*/
221template <class T>
222TArray< complex<T> > ComplexMathArray<T>::ApplyFunction(TArray< complex<T> > const & a, Arr_ComplexDoubleFunctionOfX f)
223{
224 TArray< complex<T> > ra;
225 ra = a;
226 ApplyFunctionInPlace(ra, f);
227 return(ra);
228}
229
230//! Create a complex array, from a real and an imaginary arrays
231/*!
232 \param p_real : array containing the real part of the complex output array
233 \param p_imag : array containing the imaginary part of the complex output array
234 \return Return a new complex array build from \b p_real and \b p_imag
235*/
236template <class T>
237TArray< complex<T> > ComplexMathArray<T>::FillFrom(TArray<T> const & p_real,
238 TArray<T> const & p_imag)
239{
240 if (p_real.NbDimensions() < 1)
241 throw RangeCheckError("ComplexMathArray<T>::FillFrom() - Not Allocated Array ! ");
242 bool smo;
243 if (!p_real.CompareSizes(p_imag, smo))
244 throw(SzMismatchError("ComplexMathArray<T>::FillFrom() SizeMismatch")) ;
245
246 TArray< complex<T> > ra;
247 ra.ReSize(p_real);
248
249 complex<T> * pe;
250 const T * per;
251 const T * pei;
252 sa_size_t j,k,ka;
253 if (smo && (p_real.AvgStep() > 0) && (p_imag.AvgStep() > 0)) { // regularly spaced elements
254 sa_size_t step = p_real.AvgStep();
255 sa_size_t stepa = p_imag.AvgStep();
256 sa_size_t maxx = p_real.Size()*step;
257 per = p_real.Data();
258 pei = p_imag.Data();
259 pe = ra.Data();
260 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
261 pe[k] = complex<T>(per[k], pei[ka]) ;
262 }
263 else { // Non regular data spacing ...
264 int_4 ax,axa;
265 sa_size_t step, stepa;
266 sa_size_t gpas, naxa;
267 p_real.GetOpeParams(p_imag, smo, ax, axa, step, stepa, gpas, naxa);
268 for(j=0; j<naxa; j++) {
269 per = p_real.Data()+p_real.Offset(ax,j);
270 pei = p_imag.Data()+p_imag.Offset(axa,j);
271 pe = ra.Data()+ra.Offset(ax,j);
272 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
273 pe[k] = complex<T>(per[k], pei[ka]) ;
274 }
275 }
276 return(ra);
277}
278
279
280//! Returns the real part of the complex input array.
281/*!
282 \param a : input complex array
283 \return Return a new array filled with the real part of the input complex array elements
284*/
285
286template <class T>
287TArray<T> ComplexMathArray<T>::real(TArray< complex<T> > const & a)
288{
289 if (a.NbDimensions() < 1)
290 throw RangeCheckError("ComplexMathArray< complex<T> >::real(TArray< complex<T> >& a) Not Allocated Array a !");
291 TArray<T> ra;
292 ra.ReSize(a);
293
294 const complex<T> * pe;
295 T * po;
296 sa_size_t j,k;
297 if (a.AvgStep() > 0) { // regularly spaced elements
298 sa_size_t step = a.AvgStep();
299 sa_size_t maxx = a.Size()*step;
300 pe = a.Data();
301 po = ra.Data();
302 for(k=0; k<maxx; k+=step ) po[k] = pe[k].real();
303 }
304 else { // Non regular data spacing ...
305 int_4 ka = a.MaxSizeKA();
306 sa_size_t step = a.Step(ka);
307 sa_size_t gpas = a.Size(ka)*step;
308 sa_size_t naxa = a.Size()/a.Size(ka);
309 for(j=0; j<naxa; j++) {
310 pe = a.DataBlock().Begin()+a.Offset(ka,j);
311 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
312 for(k=0; k<gpas; k+=step) po[k] = pe[k].real();
313 }
314 }
315 return(ra);
316}
317
318//! Returns the imaginary part of the complex input array.
319/*!
320 \param a : input complex array
321 \return Return a new array filled with the imaginary part of the input complex array elements
322*/
323
324template <class T>
325TArray<T> ComplexMathArray<T>::imag(TArray< complex<T> > const & a)
326{
327 if (a.NbDimensions() < 1)
328 throw RangeCheckError("ComplexMathArray< complex<T> >::imag(TArray< complex<T> >& a) Not Allocated Array a !");
329 TArray<T> ra;
330 ra.ReSize(a);
331
332 const complex<T> * pe;
333 T * po;
334 sa_size_t j,k;
335 if (a.AvgStep() > 0) { // regularly spaced elements
336 sa_size_t step = a.AvgStep();
337 sa_size_t maxx = a.Size()*step;
338 pe = a.Data();
339 po = ra.Data();
340 for(k=0; k<maxx; k+=step ) po[k] = pe[k].imag();
341 }
342 else { // Non regular data spacing ...
343 int_4 ka = a.MaxSizeKA();
344 sa_size_t step = a.Step(ka);
345 sa_size_t gpas = a.Size(ka)*step;
346 sa_size_t naxa = a.Size()/a.Size(ka);
347 for(j=0; j<naxa; j++) {
348 pe = a.DataBlock().Begin()+a.Offset(ka,j);
349 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
350 for(k=0; k<gpas; k+=step) po[k] = pe[k].imag();
351 }
352 }
353 return(ra);
354}
355
356//! Returns the module squared of the complex input array.
357/*!
358 \param a : input complex array
359 \return Return a new array filled with the module squared of the input complex array elements
360*/
361
362template <class T>
363TArray<T> ComplexMathArray<T>::module2(TArray< complex<T> > const & a)
364{
365 if (a.NbDimensions() < 1)
366 throw RangeCheckError("ComplexMathArray< complex<T> >::module2(TArray< complex<T> >& a) Not Allocated Array a !");
367 TArray<T> ra;
368 ra.ReSize(a);
369
370 const complex<T> * pe;
371 T * po;
372 sa_size_t j,k;
373 if (a.AvgStep() > 0) { // regularly spaced elements
374 sa_size_t step = a.AvgStep();
375 sa_size_t maxx = a.Size()*step;
376 pe = a.Data();
377 po = ra.Data();
378 for(k=0; k<maxx; k+=step )
379 po[k] = (pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag());
380 }
381 else { // Non regular data spacing ...
382 int_4 ka = a.MaxSizeKA();
383 sa_size_t step = a.Step(ka);
384 sa_size_t gpas = a.Size(ka)*step;
385 sa_size_t naxa = a.Size()/a.Size(ka);
386 for(j=0; j<naxa; j++) {
387 pe = a.DataBlock().Begin()+a.Offset(ka,j);
388 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
389 for(k=0; k<gpas; k+=step)
390 po[k] = (pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag());
391 }
392 }
393 return(ra);
394}
395
396//! Returns the module of the complex input array.
397/*!
398 \param a : input complex array
399 \return Return a new array filled with the module of the input complex array elements
400*/
401
402template <class T>
403TArray<T> ComplexMathArray<T>::module(TArray< complex<T> > const & a)
404{
405 if (a.NbDimensions() < 1)
406 throw RangeCheckError("ComplexMathArray< complex<T> >::module(TArray< complex<T> >& a) Not Allocated Array a !");
407 TArray<T> ra;
408 ra.ReSize(a);
409
410 const complex<T> * pe;
411 T * po;
412 sa_size_t j,k;
413 if (a.AvgStep() > 0) { // regularly spaced elements
414 sa_size_t step = a.AvgStep();
415 sa_size_t maxx = a.Size()*step;
416 pe = a.Data();
417 po = ra.Data();
418 for(k=0; k<maxx; k+=step )
419 po[k] = sqrt((double)(pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag()));
420 }
421 else { // Non regular data spacing ...
422 int_4 ka = a.MaxSizeKA();
423 sa_size_t step = a.Step(ka);
424 sa_size_t gpas = a.Size(ka)*step;
425 sa_size_t naxa = a.Size()/a.Size(ka);
426 for(j=0; j<naxa; j++) {
427 pe = a.DataBlock().Begin()+a.Offset(ka,j);
428 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
429 for(k=0; k<gpas; k+=step)
430 po[k] = sqrt((double)(pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag()));
431 }
432 }
433 return(ra);
434}
435
436
437//! Returns the phase of the complex input array.
438/*!
439 \param a : input complex array
440 \return Return a new array filled with the phase of the input complex array elements
441*/
442
443template <class T>
444TArray<T> ComplexMathArray<T>::phase(TArray< complex<T> > const & a)
445{
446 if (a.NbDimensions() < 1)
447 throw RangeCheckError("ComplexMathArray< complex<T> >::phase(TArray< complex<T> >& a) Not Allocated Array a !");
448 TArray<T> ra;
449 ra.ReSize(a);
450
451 const complex<T> * pe;
452 T * po;
453 sa_size_t j,k;
454 if (a.AvgStep() > 0) { // regularly spaced elements
455 sa_size_t step = a.AvgStep();
456 sa_size_t maxx = a.Size()*step;
457 pe = a.Data();
458 po = ra.Data();
459 for(k=0; k<maxx; k+=step )
460 po[k] = atan2((double)pe[k].imag(), (double)pe[k].real());
461 }
462 else { // Non regular data spacing ...
463 int_4 ka = a.MaxSizeKA();
464 sa_size_t step = a.Step(ka);
465 sa_size_t gpas = a.Size(ka)*step;
466 sa_size_t naxa = a.Size()/a.Size(ka);
467 for(j=0; j<naxa; j++) {
468 pe = a.DataBlock().Begin()+a.Offset(ka,j);
469 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
470 for(k=0; k<gpas; k+=step)
471 po[k] = atan2((double)pe[k].imag(), (double)pe[k].real());
472 }
473 }
474 return(ra);
475}
476
477
478///////////////////////////////////////////////////////////////
479#ifdef __CXX_PRAGMA_TEMPLATES__
480#pragma define_template MathArray<r_4>
481#pragma define_template MathArray<r_8>
482#pragma define_template ComplexMathArray<r_4>
483#pragma define_template ComplexMathArray<r_8>
484#endif
485
486#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
487template class MathArray<r_4>;
488template class MathArray<r_8>;
489template class ComplexMathArray<r_4>;
490template class ComplexMathArray<r_8>;
491#endif
Note: See TracBrowser for help on using the repository browser.