Commit 88be8bd4 authored by BLANCHARD Pierre's avatar BLANCHARD Pierre
Browse files

Redesigned fftw wrapper to handle float and double (Important: Make sure float is enabled in fftw).

parent f3fb5e98
...@@ -26,14 +26,14 @@ ...@@ -26,14 +26,14 @@
#include <fstream> #include <fstream>
#include <typeinfo> #include <typeinfo>
#include "../../Utils/FBlas.hpp" #include "Utils/FBlas.hpp"
#include "../../Utils/FTic.hpp" #include "Utils/FTic.hpp"
#include "../../Utils/FDft.hpp" #include "Utils/FDft.hpp"
#include "../../Utils/FComplex.hpp" #include "Utils/FComplex.hpp"
#include "./FUnifTensor.hpp" #include "FUnifTensor.hpp"
/*! Precomputation of the 316 interactions by evaluation of the matrix kernel on the uniform grid and transformation into Fourier space. /*! Precomputation of the 316 interactions by evaluation of the matrix kernel on the uniform grid and transformation into Fourier space.
PB: Compute() does not belong to the M2LHandler like it does in the Chebyshev kernel. This allows much nicer specialization of the M2LHandler class with respect to the homogeneity of the kernel of interaction like in the ChebyshevSym kernel.*/ PB: Compute() does not belong to the M2LHandler like it does in the Chebyshev kernel. This allows much nicer specialization of the M2LHandler class with respect to the homogeneity of the kernel of interaction like in the ChebyshevSym kernel.*/
...@@ -67,9 +67,7 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, const FReal Cel ...@@ -67,9 +67,7 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, const FReal Cel
TensorType::setNodeIdsPairs(node_ids_pairs); TensorType::setNodeIdsPairs(node_ids_pairs);
// init Discrete Fourier Transformator // init Discrete Fourier Transformator
const int dimfft = 1; // unidim FFT since fully circulant embedding const int dimfft = 1; // unidim FFT since fully circulant embedding
const int steps[dimfft] = {rc}; FFftw<FReal,FComplex<FReal>,dimfft> Dft(rc);
FFft<FReal,dimfft> Dft;
Dft.buildDFT(steps);
// get first column of K via permutation // get first column of K via permutation
unsigned int perm[rc]; unsigned int perm[rc];
TensorType::setStoragePermutation(perm); TensorType::setStoragePermutation(perm);
...@@ -178,7 +176,7 @@ class FUnifM2LHandler<FReal, ORDER,HOMOGENEOUS> ...@@ -178,7 +176,7 @@ class FUnifM2LHandler<FReal, ORDER,HOMOGENEOUS>
/// DFT specific /// DFT specific
static const int dimfft = 1; // unidim FFT since fully circulant embedding static const int dimfft = 1; // unidim FFT since fully circulant embedding
typedef FFft<FReal,dimfft> DftClass; // Fast Discrete Fourier Transformator typedef FFftw<FReal,FComplex<FReal>,dimfft> DftClass; // Fast Discrete Fourier Transformator
DftClass Dft; DftClass Dft;
const unsigned int opt_rc; // specific to real valued kernel const unsigned int opt_rc; // specific to real valued kernel
...@@ -198,11 +196,8 @@ class FUnifM2LHandler<FReal, ORDER,HOMOGENEOUS> ...@@ -198,11 +196,8 @@ class FUnifM2LHandler<FReal, ORDER,HOMOGENEOUS>
public: public:
template <typename MatrixKernelClass> template <typename MatrixKernelClass>
FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal, const int inLeafLevelSeparationCriterion = 1) FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal, const int inLeafLevelSeparationCriterion = 1)
: FC(nullptr), Dft(), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion) : FC(nullptr), Dft(rc), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// initialize root node ids // initialize root node ids
TensorType::setNodeIdsDiff(node_diff); TensorType::setNodeIdsDiff(node_diff);
...@@ -216,11 +211,8 @@ public: ...@@ -216,11 +211,8 @@ public:
* Copy constructor * Copy constructor
*/ */
FUnifM2LHandler(const FUnifM2LHandler& other) FUnifM2LHandler(const FUnifM2LHandler& other)
: FC(other.FC), Dft(), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion) : FC(other.FC), Dft(other.Dft), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// copy node_diff // copy node_diff
memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes); memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes);
} }
...@@ -269,7 +261,7 @@ public: ...@@ -269,7 +261,7 @@ public:
FReal Px[rc]; FReal Px[rc];
FBlas::setzero(rc,Px); FBlas::setzero(rc,Px);
// Apply forward Discrete Fourier Transform // Apply forward Discrete Fourier Transform
Dft.applyIDFT(FX,Px); Dft.applyIDFTNorm(FX,Px);
// Unapply Zero Padding // Unapply Zero Padding
for (unsigned int j=0; j<nnodes; ++j) for (unsigned int j=0; j<nnodes; ++j)
x[j]+=Px[node_diff[nnodes-j-1]]; x[j]+=Px[node_diff[nnodes-j-1]];
...@@ -342,7 +334,7 @@ class FUnifM2LHandler<FReal,ORDER,NON_HOMOGENEOUS> ...@@ -342,7 +334,7 @@ class FUnifM2LHandler<FReal,ORDER,NON_HOMOGENEOUS>
unsigned int node_diff[nnodes*nnodes]; unsigned int node_diff[nnodes*nnodes];
/// DFT specific /// DFT specific
static const int dimfft = 1; // unidim FFT since fully circulant embedding static const int dimfft = 1; // unidim FFT since fully circulant embedding
typedef FFft<FReal,dimfft> DftClass; // Fast Discrete Fourier Transformator typedef FFftw<FReal,FComplex<FReal>,dimfft> DftClass; // Fast real-valued Discrete Fourier Transformator
DftClass Dft; DftClass Dft;
const unsigned int opt_rc; // specific to real valued kernel const unsigned int opt_rc; // specific to real valued kernel
...@@ -364,11 +356,8 @@ public: ...@@ -364,11 +356,8 @@ public:
FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int inTreeHeight, const FReal inRootCellWidth, const int inLeafLevelSeparationCriterion = 1) FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int inTreeHeight, const FReal inRootCellWidth, const int inLeafLevelSeparationCriterion = 1)
: TreeHeight(inTreeHeight), : TreeHeight(inTreeHeight),
RootCellWidth(inRootCellWidth), RootCellWidth(inRootCellWidth),
Dft(), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion) Dft(rc), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// initialize root node ids // initialize root node ids
TensorType::setNodeIdsDiff(node_diff); TensorType::setNodeIdsDiff(node_diff);
...@@ -390,11 +379,8 @@ public: ...@@ -390,11 +379,8 @@ public:
: FC(other.FC), : FC(other.FC),
TreeHeight(other.TreeHeight), TreeHeight(other.TreeHeight),
RootCellWidth(other.RootCellWidth), RootCellWidth(other.RootCellWidth),
Dft(), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion) Dft(other.Dft), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// copy node_diff // copy node_diff
memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes); memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes);
} }
...@@ -455,7 +441,7 @@ public: ...@@ -455,7 +441,7 @@ public:
FReal Px[rc]; FReal Px[rc];
FBlas::setzero(rc,Px); FBlas::setzero(rc,Px);
// Apply forward Discrete Fourier Transform // Apply forward Discrete Fourier Transform
Dft.applyIDFT(FX,Px); Dft.applyIDFTNorm(FX,Px);
// Unapply Zero Padding // Unapply Zero Padding
for (unsigned int j=0; j<nnodes; ++j) for (unsigned int j=0; j<nnodes; ++j)
x[j]+=Px[node_diff[nnodes-j-1]]; x[j]+=Px[node_diff[nnodes-j-1]];
......
...@@ -26,14 +26,14 @@ ...@@ -26,14 +26,14 @@
#include <fstream> #include <fstream>
#include <typeinfo> #include <typeinfo>
#include "../../Utils/FBlas.hpp" #include "Utils/FBlas.hpp"
#include "../../Utils/FTic.hpp" #include "Utils/FTic.hpp"
#include "../../Utils/FDft.hpp" #include "Utils/FDft.hpp"
#include "../../Utils/FComplex.hpp" #include "Utils/FComplex.hpp"
#include "./FUnifTensor.hpp" #include "FUnifTensor.hpp"
/*! Precomputation of the 316 interactions by evaluation of the matrix kernel on the uniform grid and transformation into Fourier space. These interactions can be tensorial (of size ncmp) and are computed blockwise /*! Precomputation of the 316 interactions by evaluation of the matrix kernel on the uniform grid and transformation into Fourier space. These interactions can be tensorial (of size ncmp) and are computed blockwise
...@@ -83,9 +83,7 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, ...@@ -83,9 +83,7 @@ static void Compute(const MatrixKernelClass *const MatrixKernel,
// init Discrete Fourier Transformator // init Discrete Fourier Transformator
const int dimfft = 1; // unidim FFT since fully circulant embedding const int dimfft = 1; // unidim FFT since fully circulant embedding
const int steps[dimfft] = {rc}; FFftw<FReal,FComplex<FReal>,dimfft> Dft(rc);
FFft<FReal,dimfft> Dft;
Dft.buildDFT(steps);
// get first column of K via permutation // get first column of K via permutation
unsigned int perm[rc]; unsigned int perm[rc];
...@@ -208,7 +206,7 @@ class FUnifTensorialM2LHandler<FReal, ORDER,MatrixKernelClass,HOMOGENEOUS> ...@@ -208,7 +206,7 @@ class FUnifTensorialM2LHandler<FReal, ORDER,MatrixKernelClass,HOMOGENEOUS>
/// DFT specific /// DFT specific
static const int dimfft = 1; // unidim FFT since fully circulant embedding static const int dimfft = 1; // unidim FFT since fully circulant embedding
typedef FFft<FReal,dimfft> DftClass; // Fast Discrete Fourier Transformator typedef FFftw<FReal,FComplex<FReal>,dimfft> DftClass; // Fast Discrete Fourier Transformator
DftClass Dft; DftClass Dft;
const unsigned int opt_rc; // specific to real valued kernel const unsigned int opt_rc; // specific to real valued kernel
...@@ -228,11 +226,8 @@ class FUnifTensorialM2LHandler<FReal, ORDER,MatrixKernelClass,HOMOGENEOUS> ...@@ -228,11 +226,8 @@ class FUnifTensorialM2LHandler<FReal, ORDER,MatrixKernelClass,HOMOGENEOUS>
public: public:
FUnifTensorialM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal, const FReal inCellWidthExtension, const int inLeafLevelSeparationCriterion = 1) FUnifTensorialM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal, const FReal inCellWidthExtension, const int inLeafLevelSeparationCriterion = 1)
: CellWidthExtension(inCellWidthExtension), : CellWidthExtension(inCellWidthExtension),
Dft(), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion) Dft(rc), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// allocate FC // allocate FC
FC = new FComplex<FReal>*[ncmp]; FC = new FComplex<FReal>*[ncmp];
...@@ -252,12 +247,8 @@ public: ...@@ -252,12 +247,8 @@ public:
FUnifTensorialM2LHandler(const FUnifTensorialM2LHandler& other) FUnifTensorialM2LHandler(const FUnifTensorialM2LHandler& other)
: FC(other.FC), : FC(other.FC),
CellWidthExtension(other.CellWidthExtension), CellWidthExtension(other.CellWidthExtension),
Dft(), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion) Dft(other.Dft), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// copy node_diff // copy node_diff
memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes); memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes);
} }
...@@ -311,7 +302,7 @@ public: ...@@ -311,7 +302,7 @@ public:
FReal Px[rc]; FReal Px[rc];
FBlas::setzero(rc,Px); FBlas::setzero(rc,Px);
// Apply forward Discrete Fourier Transform // Apply forward Discrete Fourier Transform
Dft.applyIDFT(FX,Px); Dft.applyIDFTNorm(FX,Px);
// Unapply Zero Padding // Unapply Zero Padding
for (unsigned int j=0; j<nnodes; ++j) for (unsigned int j=0; j<nnodes; ++j)
x[j]+=Px[node_diff[nnodes-j-1]]; x[j]+=Px[node_diff[nnodes-j-1]];
...@@ -403,7 +394,7 @@ class FUnifTensorialM2LHandler<FReal,ORDER,MatrixKernelClass,NON_HOMOGENEOUS> ...@@ -403,7 +394,7 @@ class FUnifTensorialM2LHandler<FReal,ORDER,MatrixKernelClass,NON_HOMOGENEOUS>
/// DFT specific /// DFT specific
static const int dimfft = 1; // unidim FFT since fully circulant embedding static const int dimfft = 1; // unidim FFT since fully circulant embedding
typedef FFft<FReal,dimfft> DftClass; // Fast Discrete Fourier Transformator typedef FFftw<FReal,FComplex<FReal>,dimfft> DftClass; // Fast Discrete Fourier Transformator
DftClass Dft; DftClass Dft;
const unsigned int opt_rc; // specific to real valued kernel const unsigned int opt_rc; // specific to real valued kernel
...@@ -425,11 +416,8 @@ public: ...@@ -425,11 +416,8 @@ public:
: TreeHeight(inTreeHeight), : TreeHeight(inTreeHeight),
RootCellWidth(inRootCellWidth), RootCellWidth(inRootCellWidth),
CellWidthExtension(inCellWidthExtension), CellWidthExtension(inCellWidthExtension),
Dft(), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion) Dft(rc), opt_rc(rc/2+1), LeafLevelSeparationCriterion(inLeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// allocate FC // allocate FC
FC = new FComplex<FReal>**[TreeHeight]; FC = new FComplex<FReal>**[TreeHeight];
...@@ -454,12 +442,8 @@ public: ...@@ -454,12 +442,8 @@ public:
TreeHeight(other.TreeHeight), TreeHeight(other.TreeHeight),
RootCellWidth(other.RootCellWidth), RootCellWidth(other.RootCellWidth),
CellWidthExtension(other.CellWidthExtension), CellWidthExtension(other.CellWidthExtension),
Dft(), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion) Dft(other.Dft), opt_rc(other.opt_rc), LeafLevelSeparationCriterion(other.LeafLevelSeparationCriterion)
{ {
// init DFT
const int steps[dimfft] = {rc};
Dft.buildDFT(steps);
// copy node_diff // copy node_diff
memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes); memcpy(node_diff,other.node_diff,sizeof(unsigned int)*nnodes*nnodes);
} }
...@@ -517,7 +501,7 @@ public: ...@@ -517,7 +501,7 @@ public:
FReal Px[rc]; FReal Px[rc];
FBlas::setzero(rc,Px); FBlas::setzero(rc,Px);
// Apply forward Discrete Fourier Transform // Apply forward Discrete Fourier Transform
Dft.applyIDFT(FX,Px); Dft.applyIDFTNorm(FX,Px);
// Unapply Zero Padding // Unapply Zero Padding
for (unsigned int j=0; j<nnodes; ++j) for (unsigned int j=0; j<nnodes; ++j)
x[j]+=Px[node_diff[nnodes-j-1]]; x[j]+=Px[node_diff[nnodes-j-1]];
......
This diff is collapsed.
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#include "Core/FFmmAlgorithm.hpp" #include "Core/FFmmAlgorithm.hpp"
#include "Core/FFmmAlgorithmThread.hpp" #include "Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Utils/FParameterNames.hpp" #include "Utils/FParameterNames.hpp"
/** /**
* This program runs the FMM Algorithm with the Uniform kernel and compares the results with a direct computation. * This program runs the FMM Algorithm with the Uniform kernel and compares the results with a direct computation.
......
// ===================================================================================
// Ce LOGICIEL "ScalFmm" est couvert par le copyright Inria 20xx-2012.
// Inria détient tous les droits de propriété sur le LOGICIEL, et souhaite que
// la communauté scientifique l'utilise afin de le tester et de l'évaluer.
// Inria donne gracieusement le droit d'utiliser ce LOGICIEL. Toute utilisation
// dans un but lucratif ou à des fins commerciales est interdite sauf autorisation
// expresse et préalable d'Inria.
// Toute utilisation hors des limites précisées ci-dessus et réalisée sans l'accord
// expresse préalable d'Inria constituerait donc le délit de contrefaçon.
// Le LOGICIEL étant un produit en cours de développement, Inria ne saurait assurer
// aucune responsabilité et notamment en aucune manière et en aucun cas, être tenu
// de répondre d'éventuels dommages directs ou indirects subits par l'utilisateur.
// Tout utilisateur du LOGICIEL s'engage à communiquer à Inria ses remarques
// relatives à l'usage du LOGICIEL
// ===================================================================================
// ==== CMAKE =====
// @FUSE_FFT
// ================
#include <iostream>
#include <stdlib.h>
#include <fftw3.h>
#include "Utils/FGlobal.hpp"
#include "Utils/FComplex.hpp"
#include "Utils/FTic.hpp"
#include "Utils/FParameterNames.hpp"
#include "Utils/FDft.hpp"
int main(int argc, char** argv)
{
FHelpDescribeAndExit(argc, argv, "Test the FFT wrapper.");
typedef float FReal;
const FReal FRandMax = FReal(RAND_MAX);
FTic time;
//////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
// dimension
static const int dim = 3;
// size (pick a power of 2 for better performance of the FFT algorithm)
const int size = 50;
int total_size = 1;
for(int d = 0; d<dim;++d) total_size *= size;
// input/output types
typedef FReal FftR2CInputType;
typedef FComplex<FReal> FftR2COutputType;
typedef FComplex<FReal> FftC2CInputType;
typedef FComplex<FReal> FftC2COutputType;
// fftw arrays
FftR2CInputType* FftR2CInput = new FftR2CInputType[total_size];
FftR2CInputType* FftR2CInvOut = new FftR2CInputType[total_size];
FftR2COutputType* FftR2COutput = new FftR2COutputType[total_size];
FftC2CInputType* FftC2CInput = new FftC2CInputType[total_size];
FftC2CInputType* FftC2CInvOut = new FftC2CInputType[total_size];
FftC2COutputType* FftC2COutput = new FftC2COutputType[total_size];
// fftw wrappers
typedef FFftw<FReal ,FComplex<FReal>,dim> FftwR2CClass;
typedef FFftw<FComplex<FReal>,FComplex<FReal>,dim> FftwC2CClass;
std::cout<< "Init FFTW wrappers: ";
time.tic();
FftwR2CClass FftwR2C(size);
FftwC2CClass FftwC2C(size);
std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl;
//////////////////////////////////////////////////////////////////////////////
// EXECUTION
// generate random physical data and set output to zero
for( int s=0; s<total_size; ++s){
FftR2CInput[s] = FftR2CInputType(FReal(rand())/FRandMax);
FftR2CInvOut[s] = FftR2CInputType(0.);
FftR2COutput[s] = FftR2COutputType(0.,0.);
FftC2CInput[s] = FftC2CInputType(FReal(rand())/FRandMax,FReal(rand())/FRandMax);
FftC2CInvOut[s] = FftC2CInputType(0.,0.);
FftC2COutput[s] = FftC2COutputType(0.,0.);
}
// // display data in physical space
// std::cout<< "Physical data (R2C): "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftR2CInput[s] << ", ";
// std::cout<<std::endl;
//
// std::cout<< "Physical data (C2C): "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftC2CInput[s] << ", ";
// std::cout<<std::endl;
// perform fft
std::cout<< "Perform Forward FFT: ";
time.tic();
FftwR2C.applyDFT(FftR2CInput,FftR2COutput);
FftwC2C.applyDFT(FftC2CInput,FftC2COutput);
std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl;
// // display transform in Fourier space
// // beware the real data FFT stores only N/2+1 complex output values
// std::cout<< "Transformed data (R2C): "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftR2COutput[s] << ", ";
// std::cout<<std::endl;
//
// std::cout<< "Transformed data (C2C): "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftC2COutput[s] << ", ";
// std::cout<<std::endl;
// perform ifft of transformed data (in order to get physical values back)
std::cout<< "Perform Normalized Backward FFT: ";
time.tic();
FftwR2C.applyIDFTNorm(FftR2COutput,FftR2CInvOut);
FftwC2C.applyIDFTNorm(FftC2COutput,FftC2CInvOut);
std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl;
// // display data in physical space
// std::cout<< "Physical data from 1/N*IFFT(FFT(Physical data)) (R2C) : "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftR2CInvOut[s] << ", ";
// std::cout<<std::endl;
//
// std::cout<< "Physical data from 1/N*IFFT(FFT(Physical data)) (C2C) : "<<std::endl;
// for( int s=0; s<total_size; ++s)
// std::cout<< FftC2CInvOut[s] << ", ";
// std::cout<<std::endl;
//////////////////////////////////////////////////////////////////////////////
// VALIDATION
bool isWorking = true;
FReal threshold = (sizeof(FReal)==8 ? FReal(1.e-12) : FReal(1.e-6));
FReal* FftC2CInvOutReal = new FReal[total_size]; FReal* FftC2CInputReal = new FReal[total_size];
FReal* FftC2CInvOutImag = new FReal[total_size]; FReal* FftC2CInputImag = new FReal[total_size];
for( int s=0; s<total_size; ++s){
FftC2CInvOutReal[s] = FftC2CInvOut[s].getReal(); FftC2CInputReal[s] = FftC2CInput[s].getReal();
FftC2CInvOutImag[s] = FftC2CInvOut[s].getImag(); FftC2CInputImag[s] = FftC2CInput[s].getImag();
}
if(FMath::FAccurater<FReal>(FftR2CInput, FftR2CInvOut, total_size).getRelativeInfNorm() > threshold) isWorking=false;
if(FMath::FAccurater<FReal>(FftR2CInput, FftR2CInvOut, total_size).getRelativeL2Norm() > threshold) isWorking=false;
if(FMath::FAccurater<FReal>(FftC2CInputReal, FftC2CInvOutReal, total_size).getRelativeInfNorm() > threshold) isWorking=false;
if(FMath::FAccurater<FReal>(FftC2CInputImag, FftC2CInvOutImag, total_size).getRelativeInfNorm() > threshold) isWorking=false;
if(FMath::FAccurater<FReal>(FftC2CInputReal, FftC2CInvOutReal, total_size).getRelativeL2Norm() > threshold) isWorking=false;
if(FMath::FAccurater<FReal>(FftC2CInputImag, FftC2CInvOutImag, total_size).getRelativeL2Norm() > threshold) isWorking=false;
if(isWorking) std::cout << "FFT Wrapper is working (errors < threshold = " << threshold << ")." << std::endl;
else std::cout << "FFT Wrapper is NOT working (errors > threshold = " << threshold << ")." << std::endl;
//free memory
delete[] FftR2CInput;
delete[] FftR2CInvOut;
delete[] FftR2COutput;
delete[] FftC2CInput;
delete[] FftC2CInvOut;
delete[] FftC2COutput;
delete[] FftC2CInvOutReal;
delete[] FftC2CInputReal;
delete[] FftC2CInvOutImag;
delete[] FftC2CInputImag;
}// end test
// ===================================================================================
// Ce LOGICIEL "ScalFmm" est couvert par le copyright Inria 20xx-2012.
// Inria détient tous les droits de propriété sur le LOGICIEL, et souhaite que
// la communauté scientifique l'utilise afin de le tester et de l'évaluer.
// Inria donne gracieusement le droit d'utiliser ce LOGICIEL. Toute utilisation
// dans un but lucratif ou à des fins commerciales est interdite sauf autorisation
// expresse et préalable d'Inria.
// Toute utilisation hors des limites précisées ci-dessus et réalisée sans l'accord
// expresse préalable d'Inria constituerait donc le délit de contrefaçon.
// Le LOGICIEL étant un produit en cours de développement, Inria ne saurait assurer
// aucune responsabilité et notamment en aucune manière et en aucun cas, être tenu
// de répondre d'éventuels dommages directs ou indirects subits par l'utilisateur.
// Tout utilisateur du LOGICIEL s'engage à communiquer à Inria ses remarques
// relatives à l'usage du LOGICIEL
// ===================================================================================
// ==== CMAKE =====
// @FUSE_FFT
// ================
#include <iostream>
#include <stdlib.h>
#include <fftw3.h>
#include "../../Src/Utils/FGlobal.hpp"
#include "../../Src/Utils/FComplex.hpp"
#include "../../Src/Utils/FTic.hpp"
#include "../../Src/Utils/FParameterNames.hpp"
//#include "../../Src/Utils/FDft.hpp"
int main(int argc, char** argv)
{
FHelpDescribeAndExit(argc, argv, "Test the FFTw (only the code is interesting).");
typedef double FReal;
const FReal FRandMax = FReal(RAND_MAX);
FTic time;
//////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
// size (pick a power of 2 for better performance of the FFT algorithm)
unsigned int nsteps_ = 500;
// fftw arrays
FReal* fftR_;
FComplex<FReal>* fftC_;
fftR_ = (FReal*) fftw_malloc(sizeof(FReal) * nsteps_);
fftC_ = (FComplex<FReal>*) fftw_malloc(sizeof(FComplex<FReal>) * nsteps_);
// fftw plans
// use routine defined in file:
// /PATH/TO/mkl/interfaces/fftw3xf/wrappers/fftw_plan_dft_c2r_1d.c
fftw_plan plan_c2r_; // backward FFT plan
fftw_plan plan_r2c_; // forward FFT plan
std::cout<< "Init FFTW plans: ";
time.tic();
plan_c2r_ =