ROOT logo
// @(#)root/fft:$Id: TFFTComplex.cxx 36024 2010-10-01 16:03:30Z moneta $
// Author: Anna Kreshuk   07/4/2006

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      
// TFFTComplex                                                           
// One of the interface classes to the FFTW package, can be used directly
// or via the TVirtualFFT class. Only the basic interface of FFTW is implemented.
// Computes complex input/output discrete Fourier transforms (DFT) 
// in one or more dimensions. For the detailed information on the computed
// transforms please refer to the FFTW manual, chapter "What FFTW really computes".
// 
// How to use it:
// 1) Create an instance of TFFTComplex - this will allocate input and output
//    arrays (unless an in-place transform is specified)
// 2) Run the Init() function with the desired flags and settings
// 3) Set the data (via SetPoints(), SetPoint() or SetPointComplex() functions)
// 4) Run the Transform() function
// 5) Get the output (via GetPoints(), GetPoint() or GetPointComplex() functions)
// 6) Repeat steps 3)-5) as needed
// 
// For a transform of the same size, but with different flags or sign, rerun the Init()
// function and continue with steps 3)-5)
// NOTE: 1) running Init() function will overwrite the input array! Don't set any data
//          before running the Init() function
//       2) FFTW computes unnormalized transform, so doing a transform followed by 
//          its inverse will lead to the original array scaled by the transform size
//                                                                     
//////////////////////////////////////////////////////////////////////////

#include "TFFTComplex.h"
#include "fftw3.h"
#include "TComplex.h"


ClassImp(TFFTComplex)

//_____________________________________________________________________________
TFFTComplex::TFFTComplex()
{
//default

   fIn   = 0;
   fOut  = 0;
   fPlan = 0;
   fN    = 0;
   fFlags = 0; 
   fNdim = 0;
   fTotalSize = 0; 
   fSign = 1;
}

//_____________________________________________________________________________
TFFTComplex::TFFTComplex(Int_t n, Bool_t inPlace)
{
//For 1d transforms
//Allocates memory for the input array, and, if inPlace = kFALSE, for the output array

   fIn = fftw_malloc(sizeof(fftw_complex) *n);
   if (!inPlace)
      fOut = fftw_malloc(sizeof(fftw_complex) * n);
   else
      fOut = 0;
   fN    = new Int_t[1];
   fN[0] = n;
   fTotalSize = n;
   fNdim = 1;
   fSign = 1;
   fPlan = 0;
   fFlags = 0; 
}

//_____________________________________________________________________________
TFFTComplex::TFFTComplex(Int_t ndim, Int_t *n, Bool_t inPlace)
{
//For multidim. transforms
//Allocates memory for the input array, and, if inPlace = kFALSE, for the output array

   fNdim = ndim;
   fTotalSize = 1;
   fN = new Int_t[fNdim];
   for (Int_t i=0; i<fNdim; i++){
      fN[i] = n[i];
      fTotalSize*=n[i];
   }
   fIn = fftw_malloc(sizeof(fftw_complex)*fTotalSize);
   if (!inPlace)
      fOut = fftw_malloc(sizeof(fftw_complex) * fTotalSize);
   else
      fOut = 0;
   fSign = 1;
   fPlan = 0;
   fFlags = 0; 
}

//_____________________________________________________________________________
TFFTComplex::~TFFTComplex()
{
//Destroys the data arrays and the plan. However, some plan information stays around
//until the root session is over, and is reused if other plans of the same size are
//created

   fftw_destroy_plan((fftw_plan)fPlan);
   fPlan = 0;
   fftw_free((fftw_complex*)fIn);
   if (fOut)
      fftw_free((fftw_complex*)fOut);
   if (fN)
      delete [] fN;
}

//_____________________________________________________________________________
void TFFTComplex::Init( Option_t *flags, Int_t sign,const Int_t* /*kind*/)
{
//Creates the fftw-plan
//
//NOTE:  input and output arrays are overwritten during initialisation,
//       so don't set any points, before running this function!!!!!
//
//2nd parameter: +1
//Argument kind is dummy and doesn't need to be specified
//Possible flag_options:
//"ES" (from "estimate") - no time in preparing the transform, but probably sub-optimal
//   performance
//"M" (from "measure") - some time spend in finding the optimal way to do the transform
//"P" (from "patient") - more time spend in finding the optimal way to do the transform
//"EX" (from "exhaustive") - the most optimal way is found
//This option should be chosen depending on how many transforms of the same size and
//type are going to be done. Planning is only done once, for the first transform of this
//size and type.

   fSign = sign;
   fFlags = flags;
   if (fOut)
      fPlan = (void*)fftw_plan_dft(fNdim, fN, (fftw_complex*)fIn, (fftw_complex*)fOut, sign,MapFlag(flags));
   else
      fPlan = (void*)fftw_plan_dft(fNdim, fN, (fftw_complex*)fIn, (fftw_complex*)fIn, sign, MapFlag(flags));
}

//_____________________________________________________________________________
void TFFTComplex::Transform()
{
//Computes the transform, specified in Init() function

   if (fPlan)
      fftw_execute((fftw_plan)fPlan);
   else {
      Error("Transform", "transform not initialised");
      return;
   }
}

//_____________________________________________________________________________
void TFFTComplex::GetPoints(Double_t *data, Bool_t fromInput) const
{
//Copies the output(or input) into the argument array

   if (!fromInput){
      for (Int_t i=0; i<2*fTotalSize; i+=2){
         data[i] = ((fftw_complex*)fOut)[i/2][0];
         data[i+1] = ((fftw_complex*)fOut)[i/2][1];
      }
   } else {
      for (Int_t i=0; i<2*fTotalSize; i+=2){
         data[i] = ((fftw_complex*)fIn)[i/2][0];
         data[i+1] = ((fftw_complex*)fIn)[i/2][1];
      }
   }
}

//_____________________________________________________________________________
void TFFTComplex::GetPointComplex(Int_t ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
//returns real and imaginary parts of the point #ipoint

   if (fOut && !fromInput){
      re = ((fftw_complex*)fOut)[ipoint][0];
      im = ((fftw_complex*)fOut)[ipoint][1];
   } else {
      re = ((fftw_complex*)fIn)[ipoint][0];
      im = ((fftw_complex*)fIn)[ipoint][1];
   }
}

//_____________________________________________________________________________
void TFFTComplex::GetPointComplex(const Int_t *ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
//For multidimensional transforms. Returns real and imaginary parts of the point #ipoint

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   if (fOut && !fromInput){
      re = ((fftw_complex*)fOut)[ireal][0];
      im = ((fftw_complex*)fOut)[ireal][1];
   } else {
      re = ((fftw_complex*)fIn)[ireal][0];
      im = ((fftw_complex*)fIn)[ireal][1];
   }
}

//_____________________________________________________________________________
void TFFTComplex::GetPointsComplex(Double_t *re, Double_t *im, Bool_t fromInput) const
{
//Copies real and imaginary parts of the output (input) into the argument arrays

   if (fOut && !fromInput){
      for (Int_t i=0; i<fTotalSize; i++){
         re[i] = ((fftw_complex*)fOut)[i][0];
         im[i] = ((fftw_complex*)fOut)[i][1];
      }
   } else {
      for (Int_t i=0; i<fTotalSize; i++){
         re[i] = ((fftw_complex*)fIn)[i][0];
         im[i] = ((fftw_complex*)fIn)[i][1];
      }
   }
}

//_____________________________________________________________________________
void TFFTComplex::GetPointsComplex(Double_t *data, Bool_t fromInput) const
{
//Copies the output(input) into the argument array

   if (fOut && !fromInput){
      for (Int_t i=0; i<fTotalSize; i+=2){
         data[i] = ((fftw_complex*)fOut)[i/2][0];
         data[i+1] = ((fftw_complex*)fOut)[i/2][1];
      }
   } else {
      for (Int_t i=0; i<fTotalSize; i+=2){
         data[i] = ((fftw_complex*)fIn)[i/2][0];
         data[i+1] = ((fftw_complex*)fIn)[i/2][1];
      }
   }
}

//_____________________________________________________________________________
void TFFTComplex::SetPoint(Int_t ipoint, Double_t re, Double_t im)
{
//sets real and imaginary parts of point # ipoint

   ((fftw_complex*)fIn)[ipoint][0]=re;
   ((fftw_complex*)fIn)[ipoint][1]=im;
}

//_____________________________________________________________________________
void TFFTComplex::SetPoint(const Int_t *ipoint, Double_t re, Double_t im)
{
//For multidim. transforms. Sets real and imaginary parts of point # ipoint

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   ((fftw_complex*)fIn)[ireal][0]=re;
   ((fftw_complex*)fIn)[ireal][1]=im;
}

//_____________________________________________________________________________
void TFFTComplex::SetPointComplex(Int_t ipoint, TComplex &c)
{
   ((fftw_complex*)fIn)[ipoint][0] = c.Re();
   ((fftw_complex*)fIn)[ipoint][1] = c.Im();
}

//_____________________________________________________________________________
void TFFTComplex::SetPoints(const Double_t *data)
{
//set all points. the values are copied. points should be ordered as follows:
//[re_0, im_0, re_1, im_1, ..., re_n, im_n)

   for (Int_t i=0; i<2*fTotalSize-1; i+=2){
      ((fftw_complex*)fIn)[i/2][0]=data[i];
      ((fftw_complex*)fIn)[i/2][1]=data[i+1];
   }
}

//_____________________________________________________________________________
void TFFTComplex::SetPointsComplex(const Double_t *re_data, const Double_t *im_data)
{
//set all points. the values are copied

   if (!fIn){
      Error("SetPointsComplex", "Size is not set yet");
      return;
   }
   for (Int_t i=0; i<fTotalSize; i++){
      ((fftw_complex*)fIn)[i][0]=re_data[i];
      ((fftw_complex*)fIn)[i][1]=im_data[i];
   }
}

//_____________________________________________________________________________
UInt_t TFFTComplex::MapFlag(Option_t *flag)
{
//allowed options:
//"ES" - FFTW_ESTIMATE
//"M" - FFTW_MEASURE
//"P" - FFTW_PATIENT
//"EX" - FFTW_EXHAUSTIVE

   TString opt = flag;
   opt.ToUpper();
   if (opt.Contains("ES"))
      return FFTW_ESTIMATE;
   if (opt.Contains("M"))
      return FFTW_MEASURE;
   if (opt.Contains("P"))
      return FFTW_PATIENT;
   if (opt.Contains("EX"))
      return FFTW_EXHAUSTIVE;
   return FFTW_ESTIMATE;
}
 TFFTComplex.cxx:1
 TFFTComplex.cxx:2
 TFFTComplex.cxx:3
 TFFTComplex.cxx:4
 TFFTComplex.cxx:5
 TFFTComplex.cxx:6
 TFFTComplex.cxx:7
 TFFTComplex.cxx:8
 TFFTComplex.cxx:9
 TFFTComplex.cxx:10
 TFFTComplex.cxx:11
 TFFTComplex.cxx:12
 TFFTComplex.cxx:13
 TFFTComplex.cxx:14
 TFFTComplex.cxx:15
 TFFTComplex.cxx:16
 TFFTComplex.cxx:17
 TFFTComplex.cxx:18
 TFFTComplex.cxx:19
 TFFTComplex.cxx:20
 TFFTComplex.cxx:21
 TFFTComplex.cxx:22
 TFFTComplex.cxx:23
 TFFTComplex.cxx:24
 TFFTComplex.cxx:25
 TFFTComplex.cxx:26
 TFFTComplex.cxx:27
 TFFTComplex.cxx:28
 TFFTComplex.cxx:29
 TFFTComplex.cxx:30
 TFFTComplex.cxx:31
 TFFTComplex.cxx:32
 TFFTComplex.cxx:33
 TFFTComplex.cxx:34
 TFFTComplex.cxx:35
 TFFTComplex.cxx:36
 TFFTComplex.cxx:37
 TFFTComplex.cxx:38
 TFFTComplex.cxx:39
 TFFTComplex.cxx:40
 TFFTComplex.cxx:41
 TFFTComplex.cxx:42
 TFFTComplex.cxx:43
 TFFTComplex.cxx:44
 TFFTComplex.cxx:45
 TFFTComplex.cxx:46
 TFFTComplex.cxx:47
 TFFTComplex.cxx:48
 TFFTComplex.cxx:49
 TFFTComplex.cxx:50
 TFFTComplex.cxx:51
 TFFTComplex.cxx:52
 TFFTComplex.cxx:53
 TFFTComplex.cxx:54
 TFFTComplex.cxx:55
 TFFTComplex.cxx:56
 TFFTComplex.cxx:57
 TFFTComplex.cxx:58
 TFFTComplex.cxx:59
 TFFTComplex.cxx:60
 TFFTComplex.cxx:61
 TFFTComplex.cxx:62
 TFFTComplex.cxx:63
 TFFTComplex.cxx:64
 TFFTComplex.cxx:65
 TFFTComplex.cxx:66
 TFFTComplex.cxx:67
 TFFTComplex.cxx:68
 TFFTComplex.cxx:69
 TFFTComplex.cxx:70
 TFFTComplex.cxx:71
 TFFTComplex.cxx:72
 TFFTComplex.cxx:73
 TFFTComplex.cxx:74
 TFFTComplex.cxx:75
 TFFTComplex.cxx:76
 TFFTComplex.cxx:77
 TFFTComplex.cxx:78
 TFFTComplex.cxx:79
 TFFTComplex.cxx:80
 TFFTComplex.cxx:81
 TFFTComplex.cxx:82
 TFFTComplex.cxx:83
 TFFTComplex.cxx:84
 TFFTComplex.cxx:85
 TFFTComplex.cxx:86
 TFFTComplex.cxx:87
 TFFTComplex.cxx:88
 TFFTComplex.cxx:89
 TFFTComplex.cxx:90
 TFFTComplex.cxx:91
 TFFTComplex.cxx:92
 TFFTComplex.cxx:93
 TFFTComplex.cxx:94
 TFFTComplex.cxx:95
 TFFTComplex.cxx:96
 TFFTComplex.cxx:97
 TFFTComplex.cxx:98
 TFFTComplex.cxx:99
 TFFTComplex.cxx:100
 TFFTComplex.cxx:101
 TFFTComplex.cxx:102
 TFFTComplex.cxx:103
 TFFTComplex.cxx:104
 TFFTComplex.cxx:105
 TFFTComplex.cxx:106
 TFFTComplex.cxx:107
 TFFTComplex.cxx:108
 TFFTComplex.cxx:109
 TFFTComplex.cxx:110
 TFFTComplex.cxx:111
 TFFTComplex.cxx:112
 TFFTComplex.cxx:113
 TFFTComplex.cxx:114
 TFFTComplex.cxx:115
 TFFTComplex.cxx:116
 TFFTComplex.cxx:117
 TFFTComplex.cxx:118
 TFFTComplex.cxx:119
 TFFTComplex.cxx:120
 TFFTComplex.cxx:121
 TFFTComplex.cxx:122
 TFFTComplex.cxx:123
 TFFTComplex.cxx:124
 TFFTComplex.cxx:125
 TFFTComplex.cxx:126
 TFFTComplex.cxx:127
 TFFTComplex.cxx:128
 TFFTComplex.cxx:129
 TFFTComplex.cxx:130
 TFFTComplex.cxx:131
 TFFTComplex.cxx:132
 TFFTComplex.cxx:133
 TFFTComplex.cxx:134
 TFFTComplex.cxx:135
 TFFTComplex.cxx:136
 TFFTComplex.cxx:137
 TFFTComplex.cxx:138
 TFFTComplex.cxx:139
 TFFTComplex.cxx:140
 TFFTComplex.cxx:141
 TFFTComplex.cxx:142
 TFFTComplex.cxx:143
 TFFTComplex.cxx:144
 TFFTComplex.cxx:145
 TFFTComplex.cxx:146
 TFFTComplex.cxx:147
 TFFTComplex.cxx:148
 TFFTComplex.cxx:149
 TFFTComplex.cxx:150
 TFFTComplex.cxx:151
 TFFTComplex.cxx:152
 TFFTComplex.cxx:153
 TFFTComplex.cxx:154
 TFFTComplex.cxx:155
 TFFTComplex.cxx:156
 TFFTComplex.cxx:157
 TFFTComplex.cxx:158
 TFFTComplex.cxx:159
 TFFTComplex.cxx:160
 TFFTComplex.cxx:161
 TFFTComplex.cxx:162
 TFFTComplex.cxx:163
 TFFTComplex.cxx:164
 TFFTComplex.cxx:165
 TFFTComplex.cxx:166
 TFFTComplex.cxx:167
 TFFTComplex.cxx:168
 TFFTComplex.cxx:169
 TFFTComplex.cxx:170
 TFFTComplex.cxx:171
 TFFTComplex.cxx:172
 TFFTComplex.cxx:173
 TFFTComplex.cxx:174
 TFFTComplex.cxx:175
 TFFTComplex.cxx:176
 TFFTComplex.cxx:177
 TFFTComplex.cxx:178
 TFFTComplex.cxx:179
 TFFTComplex.cxx:180
 TFFTComplex.cxx:181
 TFFTComplex.cxx:182
 TFFTComplex.cxx:183
 TFFTComplex.cxx:184
 TFFTComplex.cxx:185
 TFFTComplex.cxx:186
 TFFTComplex.cxx:187
 TFFTComplex.cxx:188
 TFFTComplex.cxx:189
 TFFTComplex.cxx:190
 TFFTComplex.cxx:191
 TFFTComplex.cxx:192
 TFFTComplex.cxx:193
 TFFTComplex.cxx:194
 TFFTComplex.cxx:195
 TFFTComplex.cxx:196
 TFFTComplex.cxx:197
 TFFTComplex.cxx:198
 TFFTComplex.cxx:199
 TFFTComplex.cxx:200
 TFFTComplex.cxx:201
 TFFTComplex.cxx:202
 TFFTComplex.cxx:203
 TFFTComplex.cxx:204
 TFFTComplex.cxx:205
 TFFTComplex.cxx:206
 TFFTComplex.cxx:207
 TFFTComplex.cxx:208
 TFFTComplex.cxx:209
 TFFTComplex.cxx:210
 TFFTComplex.cxx:211
 TFFTComplex.cxx:212
 TFFTComplex.cxx:213
 TFFTComplex.cxx:214
 TFFTComplex.cxx:215
 TFFTComplex.cxx:216
 TFFTComplex.cxx:217
 TFFTComplex.cxx:218
 TFFTComplex.cxx:219
 TFFTComplex.cxx:220
 TFFTComplex.cxx:221
 TFFTComplex.cxx:222
 TFFTComplex.cxx:223
 TFFTComplex.cxx:224
 TFFTComplex.cxx:225
 TFFTComplex.cxx:226
 TFFTComplex.cxx:227
 TFFTComplex.cxx:228
 TFFTComplex.cxx:229
 TFFTComplex.cxx:230
 TFFTComplex.cxx:231
 TFFTComplex.cxx:232
 TFFTComplex.cxx:233
 TFFTComplex.cxx:234
 TFFTComplex.cxx:235
 TFFTComplex.cxx:236
 TFFTComplex.cxx:237
 TFFTComplex.cxx:238
 TFFTComplex.cxx:239
 TFFTComplex.cxx:240
 TFFTComplex.cxx:241
 TFFTComplex.cxx:242
 TFFTComplex.cxx:243
 TFFTComplex.cxx:244
 TFFTComplex.cxx:245
 TFFTComplex.cxx:246
 TFFTComplex.cxx:247
 TFFTComplex.cxx:248
 TFFTComplex.cxx:249
 TFFTComplex.cxx:250
 TFFTComplex.cxx:251
 TFFTComplex.cxx:252
 TFFTComplex.cxx:253
 TFFTComplex.cxx:254
 TFFTComplex.cxx:255
 TFFTComplex.cxx:256
 TFFTComplex.cxx:257
 TFFTComplex.cxx:258
 TFFTComplex.cxx:259
 TFFTComplex.cxx:260
 TFFTComplex.cxx:261
 TFFTComplex.cxx:262
 TFFTComplex.cxx:263
 TFFTComplex.cxx:264
 TFFTComplex.cxx:265
 TFFTComplex.cxx:266
 TFFTComplex.cxx:267
 TFFTComplex.cxx:268
 TFFTComplex.cxx:269
 TFFTComplex.cxx:270
 TFFTComplex.cxx:271
 TFFTComplex.cxx:272
 TFFTComplex.cxx:273
 TFFTComplex.cxx:274
 TFFTComplex.cxx:275
 TFFTComplex.cxx:276
 TFFTComplex.cxx:277
 TFFTComplex.cxx:278
 TFFTComplex.cxx:279
 TFFTComplex.cxx:280
 TFFTComplex.cxx:281
 TFFTComplex.cxx:282
 TFFTComplex.cxx:283
 TFFTComplex.cxx:284
 TFFTComplex.cxx:285
 TFFTComplex.cxx:286
 TFFTComplex.cxx:287
 TFFTComplex.cxx:288
 TFFTComplex.cxx:289
 TFFTComplex.cxx:290
 TFFTComplex.cxx:291
 TFFTComplex.cxx:292
 TFFTComplex.cxx:293
 TFFTComplex.cxx:294
 TFFTComplex.cxx:295
 TFFTComplex.cxx:296
 TFFTComplex.cxx:297
 TFFTComplex.cxx:298
 TFFTComplex.cxx:299
 TFFTComplex.cxx:300
 TFFTComplex.cxx:301
 TFFTComplex.cxx:302
 TFFTComplex.cxx:303
 TFFTComplex.cxx:304
 TFFTComplex.cxx:305
 TFFTComplex.cxx:306
 TFFTComplex.cxx:307
 TFFTComplex.cxx:308
 TFFTComplex.cxx:309
 TFFTComplex.cxx:310
 TFFTComplex.cxx:311
 TFFTComplex.cxx:312
 TFFTComplex.cxx:313
 TFFTComplex.cxx:314
 TFFTComplex.cxx:315
 TFFTComplex.cxx:316
 TFFTComplex.cxx:317
 TFFTComplex.cxx:318
 TFFTComplex.cxx:319
 TFFTComplex.cxx:320
 TFFTComplex.cxx:321
 TFFTComplex.cxx:322
 TFFTComplex.cxx:323