ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 TVirtualFFT is an interface class for Fast Fourier Transforms.
14 
15 The default FFT library is FFTW. To use it, FFTW3 library should already
16 be installed, and ROOT should be have fftw3 module enabled, with the directories
17 of fftw3 include file and library specified (see installation instructions).
18 Function SetDefaultFFT() allows to change the default library.
19 
20 ## Available transform types:
21 FFT:
22  - "C2CFORWARD" - a complex input/output discrete Fourier transform (DFT)
23  in one or more dimensions, -1 in the exponent
24  - "C2CBACKWARD"- a complex input/output discrete Fourier transform (DFT)
25  in one or more dimensions, +1 in the exponent
26  - "R2C" - a real-input/complex-output discrete Fourier transform (DFT)
27  in one or more dimensions,
28  - "C2R" - inverse transforms to "R2C", taking complex input
29  (storing the non-redundant half of a logically Hermitian array)
30  to real output
31  - "R2HC" - a real-input DFT with output in ¡Èhalfcomplex¡É format,
32  i.e. real and imaginary parts for a transform of size n stored as
33  r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1
34  - "HC2R" - computes the reverse of FFTW_R2HC, above
35  - "DHT" - computes a discrete Hartley transform
36 
37 ## Sine/cosine transforms:
38 Different types of transforms are specified by parameter kind of the SineCosine() static
39 function. 4 different kinds of sine and cosine transforms are available
40 
41  - DCT-I (REDFT00 in FFTW3 notation)- kind=0
42  - DCT-II (REDFT01 in FFTW3 notation)- kind=1
43  - DCT-III(REDFT10 in FFTW3 notation)- kind=2
44  - DCT-IV (REDFT11 in FFTW3 notation)- kind=3
45  - DST-I (RODFT00 in FFTW3 notation)- kind=4
46  - DST-II (RODFT01 in FFTW3 notation)- kind=5
47  - DST-III(RODFT10 in FFTW3 notation)- kind=6
48  - DST-IV (RODFT11 in FFTW3 notation)- kind=7
49 
50 Formulas and detailed descriptions can be found in the chapter
51 "What FFTW really computes" of the FFTW manual
52 
53 NOTE: FFTW computes unnormalized transforms, so doing a transform, followed by its
54  inverse will give the original array, multiplied by normalization constant
55  (transform size(N) for FFT, 2*(N-1) for DCT-I, 2*(N+1) for DST-I, 2*N for
56  other sine/cosine transforms)
57 
58 ## How to use it:
59 Call to the static function FFT returns a pointer to a fast Fourier transform
60 with requested parameters. Call to the static function SineCosine returns a
61 pointer to a sine or cosine transform with requested parameters. Example:
62 ~~~ {.cpp}
63 {
64  Int_t N = 10; Double_t *in = new Double_t[N];
65  TVirtualFFT *fftr2c = TVirtualFFT::FFT(1, &N, "R2C");
66  fftr2c->SetPoints(in);
67  fftr2c->Transform();
68  Double_t re, im;
69  for (Int_t i=0; i<N; i++)
70  fftr2c->GetPointComplex(i, re, im);
71  ...
72  fftr2c->SetPoints(in2);
73  ...
74  fftr2c->SetPoints(in3);
75  ...
76 }
77 ~~~
78 Different options are explained in the function comments
79 */
80 
81 #include "TROOT.h"
82 #include "TVirtualFFT.h"
83 #include "TPluginManager.h"
84 #include "TEnv.h"
85 #include "TError.h"
86 
87 TVirtualFFT *TVirtualFFT::fgFFT = 0;
88 TString TVirtualFFT::fgDefault = "";
89 
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 ///destructor
94 
96 {
97  if (this==fgFFT)
98  fgFFT = 0;
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 
133  Int_t inputtype=0, currenttype=0;
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 = 0;
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 = 0;
182  if (opt.Contains("K") || !fgFFT) {
183 
185 
186  TPluginHandler *h;
187  TString pluginname;
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 0;
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 0;
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 0;
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 = 0;
305  }
306  }
307  }
308  TVirtualFFT *fft = 0;
309 
311 
312  if (!fgFFT || opt.Contains("K")) {
313  TPluginHandler *h;
314  TString pluginname;
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 0;
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 0;
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 0;
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 0;
354  }
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 /// static: set the current transfrom to parameter
359 
361 {
362  fgFFT = fft;
363 }
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 = 0;
381  fgDefault = name;
382 }
static void SetTransform(TVirtualFFT *fft)
static: set the current transfrom to parameter
static const char * GetDefaultFFT()
static: return the name of the default fft
Ssiz_t Length() const
Definition: TString.h:390
const char Option_t
Definition: RtypesCore.h:62
TH1 * h
Definition: legend2.C:5
static TVirtualFFT * GetCurrentTransform()
static: return current fgFFT
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1088
#define gROOT
Definition: TROOT.h:344
Int_t LoadPlugin()
Load the plugin library for this handler.
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
Long_t ExecPlugin(int nargs, const T &...params)
static TString fgDefault
Definition: TVirtualFFT.h:96
static void SetDefaultFFT(const char *name="")
static: set name of default fft
const char * Data() const
Definition: TString.h:349
static TVirtualFFT * fgFFT
Definition: TVirtualFFT.h:95
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
virtual Int_t * GetN() const =0
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
TThread * t[5]
Definition: threadsh1.C:13
virtual void Init(Option_t *flag, Int_t sign, const Int_t *kind)=0
static TVirtualFFT * FFT(Int_t ndim, Int_t *n, Option_t *option)
Returns a pointer to the FFT of requested size and type.
virtual Option_t * GetTransformFlag() const =0
TVirtualFFT is an interface class for Fast Fourier Transforms.
Definition: TVirtualFFT.h:92
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.
ClassImp(TVirtualFFT) TVirtualFFT
destructor
Definition: TVirtualFFT.cxx:90
virtual Int_t GetSign() const =0
#define name(a, b)
Definition: linkTestLib0.cpp:5
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual Int_t GetNdim() const =0
Int_t sign(Double_t x)
Definition: CsgOps.cxx:89
const Int_t n
Definition: legend1.C:16
virtual Option_t * GetType() const =0
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904