Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TVirtualFFT.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Anna Kreshuk 10/04/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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/** \class TVirtualFFT
13\ingroup Base
14
15TVirtualFFT is an interface class for Fast Fourier Transforms.
16
17The default FFT library is FFTW. To use it, FFTW3 library should already
18be installed, and ROOT should be have fftw3 module enabled, with the directories
19of fftw3 include file and library specified (see installation instructions).
20Function SetDefaultFFT() allows to change the default library.
21
22## Available transform types:
23FFT:
24 - "C2CFORWARD" - a complex input/output discrete Fourier transform (DFT)
25 in one or more dimensions, -1 in the exponent
26 - "C2CBACKWARD"- a complex input/output discrete Fourier transform (DFT)
27 in one or more dimensions, +1 in the exponent
28 - "R2C" - a real-input/complex-output discrete Fourier transform (DFT)
29 in one or more dimensions,
30 - "C2R" - inverse transforms to "R2C", taking complex input
31 (storing the non-redundant half of a logically Hermitian array)
32 to real output
33 - "R2HC" - a real-input DFT with output in ¡Èhalfcomplex¡É format,
34 i.e. real and imaginary parts for a transform of size n stored as
35 r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1
36 - "HC2R" - computes the reverse of FFTW_R2HC, above
37 - "DHT" - computes a discrete Hartley transform
38
39## Sine/cosine transforms:
40Different types of transforms are specified by parameter kind of the SineCosine() static
41function. 4 different kinds of sine and cosine transforms are available
42
43 - DCT-I (REDFT00 in FFTW3 notation)- kind=0
44 - DCT-II (REDFT01 in FFTW3 notation)- kind=1
45 - DCT-III(REDFT10 in FFTW3 notation)- kind=2
46 - DCT-IV (REDFT11 in FFTW3 notation)- kind=3
47 - DST-I (RODFT00 in FFTW3 notation)- kind=4
48 - DST-II (RODFT01 in FFTW3 notation)- kind=5
49 - DST-III(RODFT10 in FFTW3 notation)- kind=6
50 - DST-IV (RODFT11 in FFTW3 notation)- kind=7
51
52Formulas and detailed descriptions can be found in the chapter
53"What FFTW really computes" of the FFTW manual
54
55NOTE: FFTW computes unnormalized transforms, so doing a transform, followed by its
56 inverse will give the original array, multiplied by normalization constant
57 (transform size(N) for FFT, 2*(N-1) for DCT-I, 2*(N+1) for DST-I, 2*N for
58 other sine/cosine transforms)
59
60## How to use it:
61Call to the static function FFT returns a pointer to a fast Fourier transform
62with requested parameters. Call to the static function SineCosine returns a
63pointer to a sine or cosine transform with requested parameters. Example:
64~~~ {.cpp}
65{
66 Int_t N = 10; Double_t *in = new Double_t[N];
67 TVirtualFFT *fftr2c = TVirtualFFT::FFT(1, &N, "R2C");
68 fftr2c->SetPoints(in);
69 fftr2c->Transform();
70 Double_t re, im;
71 for (Int_t i=0; i<N; i++)
72 fftr2c->GetPointComplex(i, re, im);
73 ...
74 fftr2c->SetPoints(in2);
75 ...
76 fftr2c->SetPoints(in3);
77 ...
78}
79~~~
80Different options are explained in the function comments
81*/
82
83#include "TROOT.h"
84#include "TVirtualFFT.h"
85#include "TPluginManager.h"
86#include "TError.h"
87
90
91
92////////////////////////////////////////////////////////////////////////////////
93///destructor
94
96{
97 if (this==fgFFT)
98 fgFFT = nullptr;
99}
100
101////////////////////////////////////////////////////////////////////////////////
102///Returns a pointer to the FFT of requested size and type.
103///
104/// \param[in] ndim number of transform dimensions
105/// \param[in] n sizes of each dimension (an array at least ndim long)
106/// \param [in] option consists of 3 parts - flag option and an option to create a new TVirtualFFT
107/// 1. transform type option:
108/// Available transform types are:
109/// C2CForward, C2CBackward, C2R, R2C, R2HC, HC2R, DHT
110/// see class description for details
111/// 2. flag option: choosing how much time should be spent in planning the transform:
112/// Possible options:
113/// - "ES" (from "estimate") - no time in preparing the transform,
114/// but probably sub-optimal performance
115/// - "M" (from "measure") - some time spend in finding the optimal way
116/// to do the transform
117/// - "P" (from "patient") - more time spend in finding the optimal way
118/// to do the transform
119/// - "EX" (from "exhaustive") - the most optimal way is found
120/// This option should be chosen depending on how many transforms of the
121/// same size and type are going to be done.
122/// Planning is only done once, for the first transform of this size and type.
123/// 3. option allowing to choose between the global fgFFT and a new TVirtualFFT object
124/// "" - default, changes and returns the global fgFFT variable
125/// "K" (from "keep")- without touching the global fgFFT,
126/// creates and returns a new TVirtualFFT*. User is then responsible for deleting it.
127///
128/// Examples of valid options: "R2C ES K", "C2CF M", "DHT P K", etc.
129
131{
132
134 TString opt = option;
135 opt.ToUpper();
136 //find the tranform flag
137 Option_t *flag;
138 flag = "ES";
139 if (opt.Contains("ES")) flag = "ES";
140 if (opt.Contains("M")) flag = "M";
141 if (opt.Contains("P")) flag = "P";
142 if (opt.Contains("EX")) flag = "EX";
143
144 Int_t ndiff = 0;
145
146 if (!opt.Contains("K")) {
147 if (fgFFT){
148 //if the global transform exists, check if it should be changed
149 if (fgFFT->GetNdim()!=ndim)
150 ndiff++;
151 else {
152 Int_t *ncurrent = fgFFT->GetN();
153 for (Int_t i=0; i<ndim; i++){
154 if (n[i]!=ncurrent[i])
155 ndiff++;
156 }
157 }
158 Option_t *t = fgFFT->GetType();
159 if (!opt.Contains(t)) {
160 if (opt.Contains("HC") || opt.Contains("DHT"))
161 inputtype = 1;
162 if (strcmp(t,"R2HC")==0 || strcmp(t,"HC2R")==0 || strcmp(t,"DHT")==0)
163 currenttype=1;
164
165 if (!(inputtype==1 && currenttype==1))
166 ndiff++;
167 }
168 if (ndiff>0){
169 delete fgFFT;
170 fgFFT = nullptr;
171 }
172 }
173 }
174
175 Int_t sign = 0;
176 if (opt.Contains("C2CB") || opt.Contains("C2R"))
177 sign = 1;
178 if (opt.Contains("C2CF") || opt.Contains("R2C"))
179 sign = -1;
180
181 TVirtualFFT *fft = nullptr;
182 if (opt.Contains("K") || !fgFFT) {
183
185
188 if (fgDefault.Length()==0) fgDefault="fftw";
189 if (strcmp(fgDefault.Data(),"fftw")==0) {
190 if (opt.Contains("C2C")) pluginname = "fftwc2c";
191 if (opt.Contains("C2R")) pluginname = "fftwc2r";
192 if (opt.Contains("R2C")) pluginname = "fftwr2c";
193 if (opt.Contains("HC") || opt.Contains("DHT")) pluginname = "fftwr2r";
194 if ((h=gROOT->GetPluginManager()->FindHandler("TVirtualFFT", pluginname))) {
195 if (h->LoadPlugin()==-1) {
196 ::Error("TVirtualFFT::FFT", "handler not found");
197 return nullptr;
198 }
199 fft = (TVirtualFFT*)h->ExecPlugin(3, ndim, n, kFALSE);
200 if (!fft) {
201 ::Error("TVirtualFFT::FFT", "plugin failed to create TVirtualFFT object");
202 return nullptr;
203 }
204 Int_t *kind = new Int_t[1];
205 if (pluginname=="fftwr2r") {
206 if (opt.Contains("R2HC")) kind[0] = 10;
207 if (opt.Contains("HC2R")) kind[0] = 11;
208 if (opt.Contains("DHT")) kind[0] = 12;
209 }
210 fft->Init(flag, sign, kind);
211 if (!opt.Contains("K")) {
212 fgFFT = fft;
213 }
214 delete [] kind;
215 return fft;
216 }
217 else {
218 ::Error("TVirtualFFT::FFT", "plugin not found");
219 return nullptr;
220 }
221 }
222 } else {
223
225
226 //if the global transform already exists and just needs to be reinitialised
227 //with different parameters
228 if (fgFFT->GetSign()!=sign || !opt.Contains(fgFFT->GetTransformFlag()) || !opt.Contains(fgFFT->GetType())) {
229 Int_t *kind = new Int_t[1];
230 if (inputtype==1) {
231 if (opt.Contains("R2HC")) kind[0] = 10;
232 if (opt.Contains("HC2R")) kind[0] = 11;
233 if (opt.Contains("DHT")) kind[0] = 12;
234 }
235 fgFFT->Init(flag, sign, kind);
236 delete [] kind;
237 }
238 }
239 return fgFFT;
240}
241
242////////////////////////////////////////////////////////////////////////////////
243///Returns a pointer to a sine or cosine transform of requested size and kind
244///
245///Parameters:
246/// \param [in] ndim number of transform dimensions
247/// \param [in] n sizes of each dimension (an array at least ndim long)
248/// \param [in] r2rkind transform kind for each dimension
249/// 4 different kinds of sine and cosine transforms are available
250/// - DCT-I - kind=0
251/// - DCT-II - kind=1
252/// - DCT-III - kind=2
253/// - DCT-IV - kind=3
254/// - DST-I - kind=4
255/// - DST-II - kind=5
256/// - DST-III - kind=6
257/// - DST-IV - kind=7
258/// \param [in] option : consists of 2 parts
259/// - flag option and an option to create a new TVirtualFFT
260/// - flag option: choosing how much time should be spent in planning the transform:
261/// Possible options:
262/// - "ES" (from "estimate") - no time in preparing the transform,
263/// but probably sub-optimal performance
264/// - "M" (from "measure") - some time spend in finding the optimal way
265/// to do the transform
266/// - "P" (from "patient") - more time spend in finding the optimal way
267/// to do the transform
268/// - "EX" (from "exhaustive") - the most optimal way is found
269/// This option should be chosen depending on how many transforms of the
270/// same size and type are going to be done.
271/// Planning is only done once, for the first transform of this size and type.
272/// - option allowing to choose between the global fgFFT and a new TVirtualFFT object
273/// - "" - default, changes and returns the global fgFFT variable
274/// - "K" (from "keep")- without touching the global fgFFT,
275/// creates and returns a new TVirtualFFT*. User is then responsible for deleting it.
276/// Examples of valid options: "ES K", "EX", etc
277
279{
280 TString opt = option;
281 //find the tranform flag
282 Option_t *flag;
283 flag = "ES";
284 if (opt.Contains("ES")) flag = "ES";
285 if (opt.Contains("M")) flag = "M";
286 if (opt.Contains("P")) flag = "P";
287 if (opt.Contains("EX")) flag = "EX";
288
289 if (!opt.Contains("K")) {
290 if (fgFFT){
291 Int_t ndiff = 0;
292 if (fgFFT->GetNdim()!=ndim || strcmp(fgFFT->GetType(),"R2R")!=0)
293 ndiff++;
294 else {
295 Int_t *ncurrent = fgFFT->GetN();
296 for (Int_t i=0; i<ndim; i++) {
297 if (n[i] != ncurrent[i])
298 ndiff++;
299 }
300
301 }
302 if (ndiff>0) {
303 delete fgFFT;
304 fgFFT = nullptr;
305 }
306 }
307 }
308 TVirtualFFT *fft = nullptr;
309
311
312 if (!fgFFT || opt.Contains("K")) {
315 if (fgDefault.Length()==0) fgDefault="fftw";
316 if (strcmp(fgDefault.Data(),"fftw")==0) {
317 pluginname = "fftwr2r";
318 if ((h=gROOT->GetPluginManager()->FindHandler("TVirtualFFT", pluginname))) {
319 if (h->LoadPlugin()==-1){
320 ::Error("TVirtualFFT::SineCosine", "handler not found");
321 return nullptr;
322 }
323 fft = (TVirtualFFT*)h->ExecPlugin(3, ndim, n, kFALSE);
324 if (!fft) {
325 ::Error("TVirtualFFT::SineCosine", "plugin failed to create TVirtualFFT object");
326 return nullptr;
327 }
328 fft->Init(flag, 0, r2rkind);
329 if (!opt.Contains("K"))
330 fgFFT = fft;
331 return fft;
332 } else {
333 ::Error("TVirtualFFT::SineCosine", "handler not found");
334 return nullptr;
335 }
336 }
337 }
338
339 //if (fgFFT->GetTransformFlag()!=flag)
340 fgFFT->Init(flag,0, r2rkind);
341 return fgFFT;
342}
343
344////////////////////////////////////////////////////////////////////////////////
345/// static: return current fgFFT
346
348{
349 if (fgFFT)
350 return fgFFT;
351 else{
352 ::Warning("TVirtualFFT::GetCurrentTransform", "fgFFT is not defined yet");
353 return nullptr;
354 }
355}
356
357////////////////////////////////////////////////////////////////////////////////
358/// static: set the current transfrom to parameter
359
364
365////////////////////////////////////////////////////////////////////////////////
366/// static: return the name of the default fft
367
369{
370 return fgDefault.Data();
371}
372
373////////////////////////////////////////////////////////////////////////////////
374/// static: set name of default fft
375
377{
378 if (fgDefault == name) return;
379 delete fgFFT;
380 fgFFT = nullptr;
381 fgDefault = name;
382}
#define h(i)
Definition RSha256.hxx:106
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
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 option
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:411
#define R__LOCKGUARD(mutex)
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
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
TVirtualFFT is an interface class for Fast Fourier Transforms.
Definition TVirtualFFT.h:88
virtual ~TVirtualFFT()
destructor
static void SetDefaultFFT(const char *name="")
static: set name of default fft
static void SetTransform(TVirtualFFT *fft)
static: set the current transfrom to parameter
static TVirtualFFT * FFT(Int_t ndim, Int_t *n, Option_t *option)
Returns a pointer to the FFT of requested size and type.
static TVirtualFFT * GetCurrentTransform()
static: return current fgFFT
static TVirtualFFT * SineCosine(Int_t ndim, Int_t *n, Int_t *r2rkind, Option_t *option)
Returns a pointer to a sine or cosine transform of requested size and kind.
static TString fgDefault
Definition TVirtualFFT.h:92
static TVirtualFFT * fgFFT
Definition TVirtualFFT.h:91
static const char * GetDefaultFFT()
static: return the name of the default fft
const Int_t n
Definition legend1.C:16