// @(#)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. * *************************************************************************/ //////////////////////////////////////////////////////////////////////////////// /// \class 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); //////////////////////////////////////////////////////////////////////////////// ///default TFFTReal::TFFTReal() { fIn = 0; fOut = 0; fPlan = 0; fN = 0; fKind = 0; fNdim = 0; fTotalSize = 0; } //////////////////////////////////////////////////////////////////////////////// ///For 1d transforms ///n here is the physical size of the transform (see FFTW manual for more details) TFFTReal::TFFTReal(Int_t n, Bool_t inPlace) { 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; } //////////////////////////////////////////////////////////////////////////////// ///For multidimensional transforms ///1st parameter is the # of dimensions, ///2nd is the sizes (physical) of the transform in each dimension TFFTReal::TFFTReal(Int_t ndim, Int_t *n, Bool_t inPlace) { fTotalSize = 1; fNdim = ndim; fN = new Int_t[ndim]; fKind = 0; fPlan = 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; } //////////////////////////////////////////////////////////////////////////////// ///For multidim.transforms. Returns point #ipoint Double_t TFFTReal::GetPointReal(const Int_t *ipoint, Bool_t fromInput) const { 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; } //////////////////////////////////////////////////////////////////////////////// ///Since multidimensional R2HC and HC2R transforms are not supported, ///third parameter is dummy void TFFTReal::SetPoint(const Int_t *ipoint, Double_t re, Double_t /*im*/) { Int_t ireal = ipoint[0]; for (Int_t i=0; ifTotalSize){ Error("SetPoint", "illegal point index"); return; } ((Double_t*)fIn)[ireal]=re; } //////////////////////////////////////////////////////////////////////////////// ///Sets all points void TFFTReal::SetPoints(const Double_t *data) { 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