// @(#)root/fft:$Id$ // 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. * *************************************************************************/ ////////////////////////////////////////////////////////////////////////// // // TFFTReal // 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 transforms called r2r in FFTW manual: // - transforms of real input and output in "halfcomplex" format i.e. // real and imaginary parts for a transform of size n stored as // (r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1) // - discrete Hartley transform // - sine and cosine transforms (DCT-I,II,III,IV and DST-I,II,III,IV) // 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 TFFTReal - 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 (see function // comments for possible kind parameters) // 3) Set the data (via SetPoints()or SetPoint() functions) // 4) Run the Transform() function // 5) Get the output (via GetPoints() or GetPoint() functions) // 6) Repeat steps 3)-5) as needed // For a transform of the same size, but of different kind (or with different flags), // 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: // - transform size (N) for R2HC, HC2R, DHT transforms // - 2*(N-1) for DCT-I (REDFT00) // - 2*(N+1) for DST-I (RODFT00) // - 2*N for the remaining transforms // Transform inverses: // R2HC<-->HC2R // DHT<-->DHT // DCT-I<-->DCT-I // DCT-II<-->DCT-III // DCT-IV<-->DCT-IV // DST-I<-->DST-I // DST-II<-->DST-III // DST-IV<-->DST-IV // ////////////////////////////////////////////////////////////////////////// #include "TFFTReal.h" #include "fftw3.h" ClassImp(TFFTReal) //_____________________________________________________________________________ TFFTReal::TFFTReal() { //default fIn = 0; fOut = 0; fPlan = 0; fN = 0; fKind = 0; fFlags = 0; fNdim = 0; fTotalSize = 0; } //_____________________________________________________________________________ TFFTReal::TFFTReal(Int_t n, Bool_t inPlace) { //For 1d transforms //n here is the physical size of the transform (see FFTW manual for more details) fIn = fftw_malloc(sizeof(Double_t)*n); if (inPlace) fOut = 0; else fOut = fftw_malloc(sizeof(Double_t)*n); fPlan = 0; fNdim = 1; fN = new Int_t[1]; fN[0] = n; fKind = 0; fTotalSize = n; fFlags = 0; } //_____________________________________________________________________________ TFFTReal::TFFTReal(Int_t ndim, Int_t *n, Bool_t inPlace) { //For multidimensional transforms //1st parameter is the # of dimensions, //2nd is the sizes (physical) of the transform in each dimension fTotalSize = 1; fNdim = ndim; fN = new Int_t[ndim]; fKind = 0; fPlan = 0; fFlags = 0; for (Int_t i=0; ifTotalSize){ Error("GetPointReal", "No such point"); return 0; } const Double_t * array = GetPointsReal(fromInput); return ( array ) ? array[ipoint] : 0; } //_____________________________________________________________________________ Double_t TFFTReal::GetPointReal(const Int_t *ipoint, Bool_t fromInput) const { //For multidim.transforms. Returns point #ipoint Int_t ireal = ipoint[0]; for (Int_t i=0; ifTotalSize){ Error("SetPoint", "illegal point index"); return; } if (((fftw_r2r_kind*)fKind)[0]==FFTW_HC2R){ if ((fN[0]%2)==0 && ipoint==fN[0]/2) ((Double_t*)fIn)[ipoint] = re; else { ((Double_t*)fIn)[ipoint] = re; ((Double_t*)fIn)[fN[0]-ipoint]=im; } } else ((Double_t*)fIn)[ipoint]=re; } //_____________________________________________________________________________ void TFFTReal::SetPoint(const Int_t *ipoint, Double_t re, Double_t /*im*/) { //Since multidimensional R2HC and HC2R transforms are not supported, //third parameter is dummy Int_t ireal = ipoint[0]; for (Int_t i=0; ifTotalSize){ Error("SetPoint", "illegal point index"); return; } ((Double_t*)fIn)[ireal]=re; } //_____________________________________________________________________________ void TFFTReal::SetPoints(const Double_t *data) { //Sets all points for (Int_t i=0; i1){ Error("Init", "Multidimensional R2HC transforms are not supported, use R2C interface instead"); return 0; } ((fftw_r2r_kind*)fKind)[0] = FFTW_R2HC; } else if (kind[0] == 11) { if (fNdim>1){ Error("Init", "Multidimensional HC2R transforms are not supported, use C2R interface instead"); return 0; } ((fftw_r2r_kind*)fKind)[0] = FFTW_HC2R; } else if (kind[0] == 12) { for (Int_t i=0; i