Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TFFTComplexReal.cxx
Go to the documentation of this file.
1// @(#)root/fft:$Id$
2// Author: Anna Kreshuk 07/4/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12////////////////////////////////////////////////////////////////////////////////
13/// \class TFFTComplexReal
14///
15/// One of the interface classes to the FFTW package, can be used directly
16/// or via the TVirtualFFT class. Only the basic interface of FFTW is implemented.
17///
18/// Computes the inverse of the real-to-complex transforms (class TFFTRealComplex)
19/// taking complex input (storing the non-redundant half of a logically Hermitian array)
20/// to real output (see FFTW manual for more details)
21///
22/// How to use it:
23/// 1. Create an instance of TFFTComplexReal - this will allocate input and output
24/// arrays (unless an in-place transform is specified)
25/// 2. Run the Init() function with the desired flags and settings
26/// 3. Set the data (via SetPoints(), SetPoint() or SetPointComplex() functions)
27/// 4. Run the Transform() function
28/// 5. Get the output (via GetPoints(), GetPoint() or GetPointReal() functions)
29/// 6. Repeat steps 3)-5) as needed
30///
31/// For a transform of the same size, but with different flags, rerun the Init()
32/// function and continue with steps 3)-5)
33///
34/// NOTE:
35/// 1. running Init() function will overwrite the input array! Don't set any data
36/// before running the Init() function
37/// 2. FFTW computes unnormalized transform, so doing a transform followed by
38/// its inverse will lead to the original array scaled by the transform size
39/// 3. In Complex to Real transform the input array is destroyed. It cannot then
40/// be retrieved when using the Get's methods.
41///
42////////////////////////////////////////////////////////////////////////////////
43
44#include "TFFTComplexReal.h"
45#include "fftw3.h"
46#include "TComplex.h"
47
48
49
50////////////////////////////////////////////////////////////////////////////////
51///default
52
54{
55 fIn = nullptr;
56 fOut = nullptr;
57 fPlan = nullptr;
58 fN = nullptr;
59 fTotalSize = 0;
60 fNdim = 0;
61}
62
63////////////////////////////////////////////////////////////////////////////////
64///For 1d transforms
65///Allocates memory for the input array, and, if inPlace = kFALSE, for the output array
66
68{
69 if (!inPlace){
70 fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
71 fOut = fftw_malloc(sizeof(Double_t)*n);
72
73 } else {
74 fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
75 fOut = nullptr;
76 }
77 fNdim = 1;
78 fN = new Int_t[1];
79 fN[0] = n;
80 fPlan = nullptr;
81 fTotalSize = n;
82}
83
84////////////////////////////////////////////////////////////////////////////////
85///For ndim-dimensional transforms
86///Second argument contains sizes of the transform in each dimension
87
89{
90 fNdim = ndim;
91 fTotalSize = 1;
92 fN = new Int_t[fNdim];
93 for (Int_t i=0; i<fNdim; i++){
94 fN[i] = n[i];
95 fTotalSize*=n[i];
96 }
97 Int_t sizein = Int_t(Double_t(fTotalSize)*(n[ndim-1]/2+1)/n[ndim-1]);
98 if (!inPlace){
101 } else {
103 fOut = nullptr;
104 }
105 fPlan = nullptr;
106}
107
108
109////////////////////////////////////////////////////////////////////////////////
110///Destroys the data arrays and the plan. However, some plan information stays around
111///until the root session is over, and is reused if other plans of the same size are
112///created
113
115{
117 fPlan = nullptr;
119 if (fOut)
121 fIn = nullptr;
122 fOut = nullptr;
123 if (fN)
124 delete [] fN;
125 fN = nullptr;
126}
127
128////////////////////////////////////////////////////////////////////////////////
129///Creates the fftw-plan
130///
131///NOTE: input and output arrays are overwritten during initialisation,
132/// so don't set any points, before running this function!!!!!
133///
134///Arguments sign and kind are dummy and not need to be specified
135///Possible flag_options:
136///
137/// - "ES" (from "estimate") - no time in preparing the transform, but probably sub-optimal
138/// performance
139/// - "M" (from "measure") - some time spend in finding the optimal way to do the transform
140/// - "P" (from "patient") - more time spend in finding the optimal way to do the transform
141/// - "EX" (from "exhaustive") - the most optimal way is found
142///
143///This option should be chosen depending on how many transforms of the same size and
144///type are going to be done. Planning is only done once, for the first transform of this
145///size and type.
146
147void TFFTComplexReal::Init( Option_t *flags, Int_t /*sign*/,const Int_t* /*kind*/)
148{
149 fFlags = flags;
150
151 if (fPlan)
153 fPlan = nullptr;
154
155 if (fOut)
157 else
159}
160
161////////////////////////////////////////////////////////////////////////////////
162///Computes the transform, specified in Init() function
163
165{
166 if (fPlan)
168 else {
169 Error("Transform", "transform was not initialized");
170 return;
171 }
172}
173
174////////////////////////////////////////////////////////////////////////////////
175///Fills the argument array with the computed transform
176/// Works only for output (input array is destroyed in a C2R transform)
177
179{
180 if (fromInput){
181 Error("GetPoints", "Input array has been destroyed");
182 return;
183 }
184 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
185 std::copy(array,array+fTotalSize, data);
186}
187
188////////////////////////////////////////////////////////////////////////////////
189///Returns the point `#ipoint`
190/// Works only for output (input array is destroyed in a C2R transform)
191
193{
194 if (fromInput){
195 Error("GetPointReal", "Input array has been destroyed");
196 return 0;
197 }
198 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
199 return array[ipoint];
200}
201
202////////////////////////////////////////////////////////////////////////////////
203///For multidimensional transforms. Returns the point `#ipoint`
204/// Works only for output (input array is destroyed in a C2R transform)
205
207{
208 if (fromInput){
209 Error("GetPointReal", "Input array has been destroyed");
210 return 0;
211 }
212 Int_t ireal = ipoint[0];
213 for (Int_t i=0; i<fNdim-1; i++)
214 ireal=fN[i+1]*ireal + ipoint[i+1];
215
216 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
217 return array[ireal];
218}
219
220
221////////////////////////////////////////////////////////////////////////////////
222/// Works only for output (input array is destroyed in a C2R transform)
223
225{
226 if (fromInput){
227 Error("GetPointComplex", "Input array has been destroyed");
228 return;
229 }
230 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
231 re = array[ipoint];
232 im = 0;
233}
234
235////////////////////////////////////////////////////////////////////////////////
236///For multidimensional transforms. Returns the point `#ipoint`
237/// Works only for output (input array is destroyed in a C2R transform)
238
240{
241 if (fromInput){
242 Error("GetPointComplex", "Input array has been destroyed");
243 return;
244 }
245 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
246
247 Int_t ireal = ipoint[0];
248 for (Int_t i=0; i<fNdim-1; i++)
249 ireal=fN[i+1]*ireal + ipoint[i+1];
250
251 re = array[ireal];
252 im = 0;
253}
254////////////////////////////////////////////////////////////////////////////////
255///Returns the array of computed transform
256/// Works only for output (input array is destroyed in a C2R transform)
257
259{
260 // we have 2 different cases
261 // fromInput = false; fOut = !NULL (transformed is not in place) : return fOut
262 // fromInput = false; fOut = NULL (transformed is in place) : return fIn
263
264 if (fromInput) {
265 Error("GetPointsReal","Input array was destroyed");
266 return nullptr;
267 }
268 return (Double_t*) ( (fOut) ? fOut : fIn );
269}
270
271////////////////////////////////////////////////////////////////////////////////
272///Fills the argument array with the computed transform
273/// Works only for output (input array is destroyed in a C2R transform)
274
276{
277 if (fromInput){
278 Error("GetPointsComplex", "Input array has been destroyed");
279 return;
280 }
281 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
282 for (Int_t i=0; i<fTotalSize; i++){
283 re[i] = array[i];
284 im[i] = 0;
285 }
286}
287
288////////////////////////////////////////////////////////////////////////////////
289///Fills the argument array with the computed transform.
290/// Works only for output (input array is destroyed in a C2R transform)
291
293{
294 if (fromInput){
295 Error("GetPointsComplex", "Input array has been destroyed");
296 return;
297 }
298 const Double_t * array = (const Double_t*) ( (fOut) ? fOut : fIn );
299 for (Int_t i=0; i<fTotalSize; i+=2){
300 data[i] = array[i/2];
301 data[i+1]=0;
302 }
303}
304
305////////////////////////////////////////////////////////////////////////////////
306///since the input must be complex-Hermitian, if the ipoint > n/2, the according
307///point before n/2 is set to (re, -im)
308
310{
311 if (ipoint <= fN[0]/2){
312 ((fftw_complex*)fIn)[ipoint][0] = re;
313 ((fftw_complex*)fIn)[ipoint][1] = im;
314 } else {
315 ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][0] = re;
316 ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][1] = -im;
317 }
318}
319
320////////////////////////////////////////////////////////////////////////////////
321///Set the point `#ipoint`. Since the input is Hermitian, only the first (roughly) half of
322///the points have to be set.
323
325{
326 Int_t ireal = ipoint[0];
327 for (Int_t i=0; i<fNdim-2; i++){
328 ireal=fN[i+1]*ireal + ipoint[i+1];
329 }
330 ireal = (fN[fNdim-1]/2+1)*ireal+ipoint[fNdim-1];
332
333 if (ireal > realN){
334 Error("SetPoint", "Illegal index value");
335 return;
336 }
337 ((fftw_complex*)fIn)[ireal][0] = re;
338 ((fftw_complex*)fIn)[ireal][1] = im;
339}
340
341////////////////////////////////////////////////////////////////////////////////
342///since the input must be complex-Hermitian, if the ipoint > n/2, the according
343///point before n/2 is set to (re, -im)
344
346{
347 if (ipoint <= fN[0]/2){
348 ((fftw_complex*)fIn)[ipoint][0] = c.Re();
349 ((fftw_complex*)fIn)[ipoint][1] = c.Im();
350 } else {
351 ((fftw_complex*)fIn)[2*(fN[0]/2)-ipoint][0] = c.Re();
352 ((fftw_complex*)fIn)[2*(fN[0]/2)-ipoint][1] = -c.Im();
353 }
354}
355
356////////////////////////////////////////////////////////////////////////////////
357///set all points. the values are copied. points should be ordered as follows:
358///[re_0, im_0, re_1, im_1, ..., re_n, im_n)
359
361{
363
364 for (Int_t i=0; i<2*(sizein); i+=2){
365 ((fftw_complex*)fIn)[i/2][0]=data[i];
366 ((fftw_complex*)fIn)[i/2][1]=data[i+1];
367 }
368}
369
370////////////////////////////////////////////////////////////////////////////////
371///Set all points. The values are copied.
372
374{
376 for (Int_t i=0; i<sizein; i++){
377 ((fftw_complex*)fIn)[i][0]=re[i];
378 ((fftw_complex*)fIn)[i][1]=im[i];
379 }
380}
381
382////////////////////////////////////////////////////////////////////////////////
383///allowed options:
384///"ES" - FFTW_ESTIMATE
385///"M" - FFTW_MEASURE
386///"P" - FFTW_PATIENT
387///"EX" - FFTW_EXHAUSTIVE
388
390{
391 TString opt = flag;
392 opt.ToUpper();
393 if (opt.Contains("ES"))
394 return FFTW_ESTIMATE;
395 if (opt.Contains("M"))
396 return FFTW_MEASURE;
397 if (opt.Contains("P"))
398 return FFTW_PATIENT;
399 if (opt.Contains("EX"))
400 return FFTW_EXHAUSTIVE;
401 return FFTW_ESTIMATE;
402}
#define c(i)
Definition RSha256.hxx:101
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
void GetPoints(Double_t *data, Bool_t fromInput=kFALSE) const override
Fills the argument array with the computed transform Works only for output (input array is destroyed ...
void SetPointComplex(Int_t ipoint, TComplex &c) override
since the input must be complex-Hermitian, if the ipoint > n/2, the according point before n/2 is set...
void SetPointsComplex(const Double_t *re, const Double_t *im) override
Set all points. The values are copied.
UInt_t MapFlag(Option_t *flag)
allowed options: "ES" - FFTW_ESTIMATE "M" - FFTW_MEASURE "P" - FFTW_PATIENT "EX" - FFTW_EXHAUSTIVE
void Transform() override
Computes the transform, specified in Init() function.
void GetPointsComplex(Double_t *re, Double_t *im, Bool_t fromInput=kFALSE) const override
Fills the argument array with the computed transform Works only for output (input array is destroyed ...
~TFFTComplexReal() override
Destroys the data arrays and the plan.
Double_t * GetPointsReal(Bool_t fromInput=kFALSE) const override
Returns the array of computed transform Works only for output (input array is destroyed in a C2R tran...
void SetPoints(const Double_t *data) override
set all points.
void SetPoint(Int_t ipoint, Double_t re, Double_t im=0) override
since the input must be complex-Hermitian, if the ipoint > n/2, the according point before n/2 is set...
void GetPointComplex(Int_t ipoint, Double_t &re, Double_t &im, Bool_t fromInput=kFALSE) const override
Works only for output (input array is destroyed in a C2R transform)
Double_t GetPointReal(Int_t ipoint, Bool_t fromInput=kFALSE) const override
Returns the point #ipoint Works only for output (input array is destroyed in a C2R transform)
void Init(Option_t *flags, Int_t, const Int_t *) override
Creates the fftw-plan.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
Basic string class.
Definition TString.h:138
void ToUpper()
Change string to upper case.
Definition TString.cxx:1202
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:640
const Int_t n
Definition legend1.C:16