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

Last change on this file since 2788 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 14.6 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 sig = sig/dsz - mean*mean;
151 if (sig >= 0.) sig = sqrt(sig);
152 return(mean);
153}
154
155
156//-------------------------------------------------------------------------------
157// Definition utilitaire d'application de fonction
158inline complex<r_8> ApplyComplexDoubleFunction(complex<r_8> z,
159 Arr_ComplexDoubleFunctionOfX f)
160{
161 return(f(z));
162}
163
164inline complex<r_4> ApplyComplexDoubleFunction(complex<r_4> z,
165 Arr_ComplexDoubleFunctionOfX f)
166{
167 complex<r_8> zd((r_8)z.real(), (r_8)z.imag());
168 zd = f(zd);
169 complex<r_4> zr((r_4)zd.real(), (r_4)zd.imag());
170 return(zr);
171}
172
173//-------------------------------------------------------------------------------
174
175/*!
176 \class SOPHYA::ComplexMathArray
177 \ingroup TArray
178 Class for simple mathematical operation on arrays
179 \warning Instanciated only for \b real and \b double (r_4, r_8) complex arrays
180*/
181
182//! Apply Function In Place (complex arrays)
183/*!
184 \param a : complex array to be replaced in place
185 \param f : function for replacement
186 \return Return an array \b a filled with function f(a(i,j))
187*/
188template <class T>
189TArray< complex<T> >& ComplexMathArray<T>::ApplyFunctionInPlace(TArray< complex<T> > & a, Arr_ComplexDoubleFunctionOfX f)
190{
191 if (a.NbDimensions() < 1)
192 throw RangeCheckError("ComplexMathArray< complex<T> >::ApplyFunctionInPlace(TArray< complex<T> > & a..) Not Allocated Array a !");
193 complex<T> * pe;
194 sa_size_t j,k;
195 if (a.AvgStep() > 0) { // regularly spaced elements
196 sa_size_t step = a.AvgStep();
197 sa_size_t maxx = a.Size()*step;
198 pe = a.Data();
199 for(k=0; k<maxx; k+=step ) pe[k] = ApplyComplexDoubleFunction(pe[k],f);
200 }
201 else { // Non regular data spacing ...
202 int_4 ka = a.MaxSizeKA();
203 sa_size_t step = a.Step(ka);
204 sa_size_t gpas = a.Size(ka)*step;
205 sa_size_t naxa = a.Size()/a.Size(ka);
206 for(j=0; j<naxa; j++) {
207 pe = a.DataBlock().Begin()+a.Offset(ka,j);
208 for(k=0; k<gpas; k+=step) pe[k] = ApplyComplexDoubleFunction(pe[k],f);
209 }
210 }
211 return(a);
212}
213
214
215
216//! Apply Function (complex arrays)
217/*!
218 \param a : argument array of the function
219 \param f : function for replacement
220 \return Return a new array filled with function f(a(i,j))
221*/
222template <class T>
223TArray< complex<T> > ComplexMathArray<T>::ApplyFunction(TArray< complex<T> > const & a, Arr_ComplexDoubleFunctionOfX f)
224{
225 TArray< complex<T> > ra;
226 ra = a;
227 ApplyFunctionInPlace(ra, f);
228 return(ra);
229}
230
231//! Create a complex array, from a real and an imaginary arrays
232/*!
233 \param p_real : array containing the real part of the complex output array
234 \param p_imag : array containing the imaginary part of the complex output array
235 \return Return a new complex array build from \b p_real and \b p_imag
236*/
237template <class T>
238TArray< complex<T> > ComplexMathArray<T>::FillFrom(TArray<T> const & p_real,
239 TArray<T> const & p_imag)
240{
241 if (p_real.NbDimensions() < 1)
242 throw RangeCheckError("ComplexMathArray<T>::FillFrom() - Not Allocated Array ! ");
243 bool smo;
244 if (!p_real.CompareSizes(p_imag, smo))
245 throw(SzMismatchError("ComplexMathArray<T>::FillFrom() SizeMismatch")) ;
246
247 TArray< complex<T> > ra;
248 ra.ReSize(p_real);
249
250 complex<T> * pe;
251 const T * per;
252 const T * pei;
253 sa_size_t j,k,ka;
254 if (smo && (p_real.AvgStep() > 0) && (p_imag.AvgStep() > 0)) { // regularly spaced elements
255 sa_size_t step = p_real.AvgStep();
256 sa_size_t stepa = p_imag.AvgStep();
257 sa_size_t maxx = p_real.Size()*step;
258 per = p_real.Data();
259 pei = p_imag.Data();
260 pe = ra.Data();
261 for(k=0, ka=0; k<maxx; k+=step, ka+=stepa )
262 pe[k] = complex<T>(per[k], pei[ka]) ;
263 }
264 else { // Non regular data spacing ...
265 int_4 ax,axa;
266 sa_size_t step, stepa;
267 sa_size_t gpas, naxa;
268 p_real.GetOpeParams(p_imag, smo, ax, axa, step, stepa, gpas, naxa);
269 for(j=0; j<naxa; j++) {
270 per = p_real.Data()+p_real.Offset(ax,j);
271 pei = p_imag.Data()+p_imag.Offset(axa,j);
272 pe = ra.Data()+ra.Offset(ax,j);
273 for(k=0, ka=0; k<gpas; k+=step, ka+=stepa)
274 pe[k] = complex<T>(per[k], pei[ka]) ;
275 }
276 }
277 return(ra);
278}
279
280
281//! Returns the real part of the complex input array.
282/*!
283 \param a : input complex array
284 \return Return a new array filled with the real part of the input complex array elements
285*/
286
287template <class T>
288TArray<T> ComplexMathArray<T>::real(TArray< complex<T> > const & a)
289{
290 if (a.NbDimensions() < 1)
291 throw RangeCheckError("ComplexMathArray< complex<T> >::real(TArray< complex<T> >& a) Not Allocated Array a !");
292 TArray<T> ra;
293 ra.ReSize(a);
294
295 const complex<T> * pe;
296 T * po;
297 sa_size_t j,k;
298 if (a.AvgStep() > 0) { // regularly spaced elements
299 sa_size_t step = a.AvgStep();
300 sa_size_t maxx = a.Size()*step;
301 pe = a.Data();
302 po = ra.Data();
303 for(k=0; k<maxx; k+=step ) po[k] = pe[k].real();
304 }
305 else { // Non regular data spacing ...
306 int_4 ka = a.MaxSizeKA();
307 sa_size_t step = a.Step(ka);
308 sa_size_t gpas = a.Size(ka)*step;
309 sa_size_t naxa = a.Size()/a.Size(ka);
310 for(j=0; j<naxa; j++) {
311 pe = a.DataBlock().Begin()+a.Offset(ka,j);
312 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
313 for(k=0; k<gpas; k+=step) po[k] = pe[k].real();
314 }
315 }
316 return(ra);
317}
318
319//! Returns the imaginary part of the complex input array.
320/*!
321 \param a : input complex array
322 \return Return a new array filled with the imaginary part of the input complex array elements
323*/
324
325template <class T>
326TArray<T> ComplexMathArray<T>::imag(TArray< complex<T> > const & a)
327{
328 if (a.NbDimensions() < 1)
329 throw RangeCheckError("ComplexMathArray< complex<T> >::imag(TArray< complex<T> >& a) Not Allocated Array a !");
330 TArray<T> ra;
331 ra.ReSize(a);
332
333 const complex<T> * pe;
334 T * po;
335 sa_size_t j,k;
336 if (a.AvgStep() > 0) { // regularly spaced elements
337 sa_size_t step = a.AvgStep();
338 sa_size_t maxx = a.Size()*step;
339 pe = a.Data();
340 po = ra.Data();
341 for(k=0; k<maxx; k+=step ) po[k] = pe[k].imag();
342 }
343 else { // Non regular data spacing ...
344 int_4 ka = a.MaxSizeKA();
345 sa_size_t step = a.Step(ka);
346 sa_size_t gpas = a.Size(ka)*step;
347 sa_size_t naxa = a.Size()/a.Size(ka);
348 for(j=0; j<naxa; j++) {
349 pe = a.DataBlock().Begin()+a.Offset(ka,j);
350 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
351 for(k=0; k<gpas; k+=step) po[k] = pe[k].imag();
352 }
353 }
354 return(ra);
355}
356
357//! Returns the module squared of the complex input array.
358/*!
359 \param a : input complex array
360 \return Return a new array filled with the module squared of the input complex array elements
361*/
362
363template <class T>
364TArray<T> ComplexMathArray<T>::module2(TArray< complex<T> > const & a)
365{
366 if (a.NbDimensions() < 1)
367 throw RangeCheckError("ComplexMathArray< complex<T> >::module2(TArray< complex<T> >& a) Not Allocated Array a !");
368 TArray<T> ra;
369 ra.ReSize(a);
370
371 const complex<T> * pe;
372 T * po;
373 sa_size_t j,k;
374 if (a.AvgStep() > 0) { // regularly spaced elements
375 sa_size_t step = a.AvgStep();
376 sa_size_t maxx = a.Size()*step;
377 pe = a.Data();
378 po = ra.Data();
379 for(k=0; k<maxx; k+=step )
380 po[k] = (pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag());
381 }
382 else { // Non regular data spacing ...
383 int_4 ka = a.MaxSizeKA();
384 sa_size_t step = a.Step(ka);
385 sa_size_t gpas = a.Size(ka)*step;
386 sa_size_t naxa = a.Size()/a.Size(ka);
387 for(j=0; j<naxa; j++) {
388 pe = a.DataBlock().Begin()+a.Offset(ka,j);
389 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
390 for(k=0; k<gpas; k+=step)
391 po[k] = (pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag());
392 }
393 }
394 return(ra);
395}
396
397//! Returns the module of the complex input array.
398/*!
399 \param a : input complex array
400 \return Return a new array filled with the module of the input complex array elements
401*/
402
403template <class T>
404TArray<T> ComplexMathArray<T>::module(TArray< complex<T> > const & a)
405{
406 if (a.NbDimensions() < 1)
407 throw RangeCheckError("ComplexMathArray< complex<T> >::module(TArray< complex<T> >& a) Not Allocated Array a !");
408 TArray<T> ra;
409 ra.ReSize(a);
410
411 const complex<T> * pe;
412 T * po;
413 sa_size_t j,k;
414 if (a.AvgStep() > 0) { // regularly spaced elements
415 sa_size_t step = a.AvgStep();
416 sa_size_t maxx = a.Size()*step;
417 pe = a.Data();
418 po = ra.Data();
419 for(k=0; k<maxx; k+=step )
420 po[k] = sqrt((double)(pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag()));
421 }
422 else { // Non regular data spacing ...
423 int_4 ka = a.MaxSizeKA();
424 sa_size_t step = a.Step(ka);
425 sa_size_t gpas = a.Size(ka)*step;
426 sa_size_t naxa = a.Size()/a.Size(ka);
427 for(j=0; j<naxa; j++) {
428 pe = a.DataBlock().Begin()+a.Offset(ka,j);
429 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
430 for(k=0; k<gpas; k+=step)
431 po[k] = sqrt((double)(pe[k].real()*pe[k].real()+pe[k].imag()*pe[k].imag()));
432 }
433 }
434 return(ra);
435}
436
437
438//! Returns the phase of the complex input array.
439/*!
440 \param a : input complex array
441 \return Return a new array filled with the phase of the input complex array elements
442*/
443
444template <class T>
445TArray<T> ComplexMathArray<T>::phase(TArray< complex<T> > const & a)
446{
447 if (a.NbDimensions() < 1)
448 throw RangeCheckError("ComplexMathArray< complex<T> >::phase(TArray< complex<T> >& a) Not Allocated Array a !");
449 TArray<T> ra;
450 ra.ReSize(a);
451
452 const complex<T> * pe;
453 T * po;
454 sa_size_t j,k;
455 if (a.AvgStep() > 0) { // regularly spaced elements
456 sa_size_t step = a.AvgStep();
457 sa_size_t maxx = a.Size()*step;
458 pe = a.Data();
459 po = ra.Data();
460 for(k=0; k<maxx; k+=step )
461 po[k] = atan2((double)pe[k].imag(), (double)pe[k].real());
462 }
463 else { // Non regular data spacing ...
464 int_4 ka = a.MaxSizeKA();
465 sa_size_t step = a.Step(ka);
466 sa_size_t gpas = a.Size(ka)*step;
467 sa_size_t naxa = a.Size()/a.Size(ka);
468 for(j=0; j<naxa; j++) {
469 pe = a.DataBlock().Begin()+a.Offset(ka,j);
470 po = ra.DataBlock().Begin()+ra.Offset(ka,j);
471 for(k=0; k<gpas; k+=step)
472 po[k] = atan2((double)pe[k].imag(), (double)pe[k].real());
473 }
474 }
475 return(ra);
476}
477
478
479///////////////////////////////////////////////////////////////
480#ifdef __CXX_PRAGMA_TEMPLATES__
481#pragma define_template MathArray<r_4>
482#pragma define_template MathArray<r_8>
483#pragma define_template ComplexMathArray<r_4>
484#pragma define_template ComplexMathArray<r_8>
485#endif
486
487#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
488template class MathArray<r_4>;
489template class MathArray<r_8>;
490template class ComplexMathArray<r_4>;
491template class ComplexMathArray<r_8>;
492#endif
Note: See TracBrowser for help on using the repository browser.