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

Last change on this file since 4024 was 2923, checked in by ansari, 20 years ago

Correction calcul sigma des tableaux (facteur N/N-1) - Reza 27/3/2006

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