diff --git a/Src/Kernels/Uniform/FUnifM2LHandler.hpp b/Src/Kernels/Uniform/FUnifM2LHandler.hpp index b550a1c9fbba28086af46429031b4ed49fda8ddb..e2cf8063cfed7c672e626a99bf12768594ac2b7b 100644 --- a/Src/Kernels/Uniform/FUnifM2LHandler.hpp +++ b/Src/Kernels/Uniform/FUnifM2LHandler.hpp @@ -66,8 +66,10 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, const FReal Cel TensorType::setNodeIdsPairs(node_ids_pairs); // init Discrete Fourier Transformator + const int dimfft = 1; // unidim FFT since fully circulant embedding + const int steps[dimfft] = {rc}; // FDft Dft(rc); - FFft<1> Dft(rc); + FFft Dft(steps); // get first column of K via permutation unsigned int perm[rc]; @@ -177,15 +179,17 @@ class FUnifM2LHandler : FNoCopyable FComplexe *FC; - // for real valued kernel only n/2+1 complex values are stored - // after performing the DFT (the rest is deduced by conjugation) - unsigned int opt_rc; - typedef FUnifTensor TensorType; unsigned int node_diff[nnodes*nnodes]; - // FDft Dft; // Direct Discrete Fourier Transformator - FFft<1> Dft; // Fast Discrete Fourier Transformator + /// DFT specific + static const int dimfft = 1; // unidim FFT since fully circulant embedding +// FDft Dft; // Direct Discrete Fourier Transformator + typedef FFft DftClass; // Fast Discrete Fourier Transformator + FSmartPointer Dft; + + const unsigned int opt_rc; // specific to real valued kernel + static const std::string getFileName() { @@ -201,9 +205,12 @@ public: template FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal) : FC(NULL), - opt_rc(rc/2+1), - Dft(rc) // initialize Discrete Fourier Transformator + opt_rc(rc/2+1) { + // init DFT + const int steps[dimfft] = {rc}; + Dft = new DftClass(steps); + // initialize root node ids TensorType::setNodeIdsDiff(node_diff); @@ -253,7 +260,7 @@ public: FReal Px[rc]; FBlas::setzero(rc,Px); // Apply forward Discrete Fourier Transform - Dft.applyIDFT(FX,Px); + Dft->applyIDFT(FX,Px); // Unapply Zero Padding for (unsigned int j=0; japplyDFT(Py,FY); } @@ -342,15 +349,17 @@ class FUnifM2LHandler : FNoCopyable const unsigned int TreeHeight; const FReal RootCellWidth; - // for real valued kernel only n/2+1 complex values are stored - // after performing the DFT (the rest is deduced by conjugation) - unsigned int opt_rc; - typedef FUnifTensor TensorType; unsigned int node_diff[nnodes*nnodes]; - // FDft Dft; // Direct Discrete Fourier Transformator - FFft<1> Dft; // Fast Discrete Fourier Transformator + // DFT specific + static const int dimfft = 1; // unidim FFT since fully circulant embedding +// FDft Dft; // Direct Discrete Fourier Transformator + typedef FFft DftClass; // Fast Discrete Fourier Transformator + FSmartPointer Dft; + + const unsigned int opt_rc; // specific to real valued kernel + static const std::string getFileName() { @@ -367,9 +376,12 @@ public: FUnifM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int inTreeHeight, const FReal inRootCellWidth) : TreeHeight(inTreeHeight), RootCellWidth(inRootCellWidth), - opt_rc(rc/2+1), - Dft(rc) // initialize Discrete Fourier Transformator - { + opt_rc(rc/2+1) + { + // init DFT + const int steps[dimfft] = {rc}; + Dft = new DftClass(steps); + // initialize root node ids TensorType::setNodeIdsDiff(node_diff); @@ -431,7 +443,7 @@ public: FReal Px[rc]; FBlas::setzero(rc,Px); // Apply forward Discrete Fourier Transform - Dft.applyIDFT(FX,Px); + Dft->applyIDFT(FX,Px); // Unapply Zero Padding for (unsigned int j=0; japplyDFT(Py,FY); } diff --git a/Src/Kernels/Uniform/FUnifSymM2LHandler.hpp b/Src/Kernels/Uniform/FUnifSymM2LHandler.hpp index a7e4843b651eadebe7ae35815815213ffee0f982..4fa1f77011420e34eb29a64679c63ec99d1cca6c 100755 --- a/Src/Kernels/Uniform/FUnifSymM2LHandler.hpp +++ b/Src/Kernels/Uniform/FUnifSymM2LHandler.hpp @@ -60,8 +60,10 @@ static void precompute(const MatrixKernelClass *const MatrixKernel, const FReal _FC = new FComplexe [rc]; // TODO: do it in the non-sym version!!! // init Discrete Fourier Transformator + const int dimfft = 1; // unidim FFT since fully circulant embedding + const int steps[dimfft] = {rc}; // FDft Dft(rc); - FFft Dft(rc); + FFft Dft(steps); // reduce storage if real valued kernel const unsigned int opt_rc = rc/2+1; diff --git a/Src/Kernels/Uniform/FUnifTensorialKernel.hpp b/Src/Kernels/Uniform/FUnifTensorialKernel.hpp index 74f1cc760cb78ea1e3ec7c2b3fd58b5d95fea000..5734d70a0dec1b2a4d5b7472251b5536c5484b7b 100644 --- a/Src/Kernels/Uniform/FUnifTensorialKernel.hpp +++ b/Src/Kernels/Uniform/FUnifTensorialKernel.hpp @@ -48,9 +48,9 @@ class FTreeCoordinate; * In fact, in the ChebyshevSym variant the matrix kernel needs to be * evaluated compo-by-compo since we currently use a scalar ACA. * - * 3) We currently use multiple 1D FFT instead of multidim FFT. - * TODO switch to multidim if relevant in considered range of size - * (see testFFTW and testFFTWMultidim). + * 3) We currently use multiple 1D FFT instead of multidim FFT since embedding + * is circulant. Multidim FFT could be used if embedding were block circulant. + * TODO investigate possibility of block circulant embedding * * @tparam CellClass Type of cell * @tparam ContainerClass Type of container to store particles diff --git a/Src/Kernels/Uniform/FUnifTensorialM2LHandler.hpp b/Src/Kernels/Uniform/FUnifTensorialM2LHandler.hpp index a4c1d62db8ca62ab5873fc2de13ba452ef99fe2b..84c9dfa68a0bfba21d2c9b3256fc3d4b5b252345 100644 --- a/Src/Kernels/Uniform/FUnifTensorialM2LHandler.hpp +++ b/Src/Kernels/Uniform/FUnifTensorialM2LHandler.hpp @@ -75,8 +75,10 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, TensorType::setNodeIdsPairs(node_ids_pairs); // init Discrete Fourier Transformator + const int dimfft = 1; // unidim FFT since fully circulant embedding + const int steps[dimfft] = {rc}; // FDft Dft(rc); - FFft<1> Dft(rc); + FFft Dft(steps); // get first column of K via permutation unsigned int perm[rc]; @@ -198,15 +200,17 @@ class FUnifTensorialM2LHandler : FNoCopyabl // Tensorial MatrixKernel specific FComplexe** FC; - // for real valued kernel only n/2+1 complex values are stored - // after performing the DFT (the rest is deduced by conjugation) - unsigned int opt_rc; - typedef FUnifTensor TensorType; unsigned int node_diff[nnodes*nnodes]; - // FDft Dft; // Direct Discrete Fourier Transformator - FFft<1> Dft; // Fast Discrete Fourier Transformator + // DFT specific + static const int dimfft = 1; // unidim FFT since fully circulant embedding +// FDft Dft; // Direct Discrete Fourier Transformator + typedef FFft DftClass; // Fast Discrete Fourier Transformator + FSmartPointer Dft; + + const unsigned int opt_rc; // specific to real valued kernel + static const std::string getFileName() { @@ -220,9 +224,12 @@ class FUnifTensorialM2LHandler : FNoCopyabl public: FUnifTensorialM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int, const FReal) - : opt_rc(rc/2+1), - Dft(rc) // initialize Discrete Fourier Transformator + : opt_rc(rc/2+1) { + // init DFT + const int steps[dimfft] = {rc}; + Dft = new DftClass(steps); + // allocate FC FC = new FComplexe*[dim]; for (unsigned int d=0; dapplyIDFT(FX,Px); // Unapply Zero Padding for (unsigned int j=0; japplyDFT(Py,FY); } @@ -369,15 +376,17 @@ class FUnifTensorialM2LHandler : FNoCop const unsigned int TreeHeight; const FReal RootCellWidth; - // for real valued kernel only n/2+1 complex values are stored - // after performing the DFT (the rest is deduced by conjugation) - unsigned int opt_rc; - typedef FUnifTensor TensorType; unsigned int node_diff[nnodes*nnodes]; - // FDft Dft; // Direct Discrete Fourier Transformator - FFft<1> Dft; // Fast Discrete Fourier Transformator + // DFT specific + static const int dimfft = 1; // unidim FFT since fully circulant embedding +// FDft Dft; // Direct Discrete Fourier Transformator + typedef FFft DftClass; // Fast Discrete Fourier Transformator + FSmartPointer Dft; + + const unsigned int opt_rc; // specific to real valued kernel + static const std::string getFileName() { @@ -393,9 +402,12 @@ public: FUnifTensorialM2LHandler(const MatrixKernelClass *const MatrixKernel, const unsigned int inTreeHeight, const FReal inRootCellWidth) : TreeHeight(inTreeHeight), RootCellWidth(inRootCellWidth), - opt_rc(rc/2+1), - Dft(rc) // initialize Discrete Fourier Transformator + opt_rc(rc/2+1) { + // init DFT + const int steps[dimfft] = {rc}; + Dft = new DftClass(steps); + // allocate FC FC = new FComplexe**[TreeHeight]; for (unsigned int l=0; lapplyIDFT(FX,Px); // Unapply Zero Padding for (unsigned int j=0; japplyDFT(Py,FY); } diff --git a/Src/Utils/FBlas.hpp b/Src/Utils/FBlas.hpp index 01fea5dd01a4e61e9ce93e145a29955ab127eae2..fe1731a8958ab8d7f5fbcc6e22c8cac605915f2c 100755 --- a/Src/Utils/FBlas.hpp +++ b/Src/Utils/FBlas.hpp @@ -70,6 +70,7 @@ extern "C" double*, double*, const unsigned*, int*); void dorgqr_(const unsigned*, const unsigned*, const unsigned*, double*, const unsigned*, double*, double*, const unsigned*, int*); + void dpotrf_(const char*, const unsigned*, double*, const unsigned*, int*); #ifdef ScalFMM_USE_MKL_AS_BLAS // mkl: hadamard product is not implemented in mkl_blas @@ -103,6 +104,7 @@ extern "C" float*, float*, const unsigned*, int*); void sorgqr_(const unsigned*, const unsigned*, const unsigned*, float*, const unsigned*, float*, float*, const unsigned*, int*); + void spotrf_(const char*, const unsigned*, float*, const unsigned*, int*); // double complex ////////////////////////////////////////////////// // blas 1 @@ -119,7 +121,7 @@ extern "C" double*, const unsigned*, const double*, double*, const unsigned*); void zgeqrf_(const unsigned*, const unsigned*, double*, const unsigned*, double*, double*, const unsigned*, int*); - + void zpotrf_(const char*, const unsigned*, double*, const unsigned*, int*); // single complex ////////////////////////////////////////////////// // blas 1 @@ -136,7 +138,7 @@ extern "C" float*, const unsigned*, const float*, float*, const unsigned*); void cgeqrf_(const unsigned*, const unsigned*, float*, const unsigned*, float*, float*, const unsigned*, int*); - + void cpotrf_(const char*, const unsigned*, float*, const unsigned*, int*); } @@ -506,6 +508,19 @@ namespace FBlas { + // Cholesky decomposition: A=LL^T (if A is symmetric definite positive) + inline int potrf(const unsigned m, double* A, const unsigned n) + { + int INF; + dpotrf_("L", &m, A, &n, &INF); + return INF; + } + inline int potrf(const unsigned m, float* A, const unsigned n) + { + int INF; + spotrf_("L", &m, A, &n, &INF); + return INF; + } } // end namespace FCBlas diff --git a/Src/Utils/FDft.hpp b/Src/Utils/FDft.hpp index ce9c0b86b73febacafca80e8a8a74f74abb42e38..7d81afed087c1f2d0977d20161c0acf32d07f0cb 100644 --- a/Src/Utils/FDft.hpp +++ b/Src/Utils/FDft.hpp @@ -36,7 +36,7 @@ /** * @author Pierre Blanchard (pierre.blanchard@inria.fr) - * @class FDft and @class FFft + * @class FDft, @class FFft and @class FCFft * Please read the license * * These classes handle the forward and backward Discete Fourier Transform @@ -45,6 +45,10 @@ * Fourier Transform (FFT). The FFT algorithm can either be provided by the * FFTW(3) library itself or a version that is wrapped in Intel MKL. * + * The direct DFT is templatized with the input value type (FReal or FComplexe), + * while 2 distinct classes resp. @class FFft and @class FCFft are defined + * resp. for the real and complex valued FFT. + * * The aim of writing these specific classes is to allow further customization * of the DFT such as implementing a tensorial variant, a weighted variant * or any other feature. @@ -59,25 +63,25 @@ * * @tparam nsteps number of sampled values \f$N\f$ */ - +template class FDft { - FReal* fftR_; - FComplexe* fftC_; + ValueType* data_; //< data in physical space + FComplexe* dataF_; //< data in Fourier space FReal *cosRS_, *sinRS_; private: - unsigned int nsteps_; + unsigned int nsteps_; //< number of steps public: FDft(const unsigned int nsteps) : nsteps_(nsteps) { - fftR_ = new FReal[nsteps_]; - fftC_ = new FComplexe[nsteps_]; + data_ = new ValueType[nsteps_]; + dataF_ = new FComplexe[nsteps_]; // Beware this is extremely HEAVY to store!!! => Use FDft only for debug! cosRS_ = new FReal[nsteps_*nsteps_]; @@ -93,67 +97,104 @@ public: virtual ~FDft() { - delete [] fftR_; - delete [] fftC_; + delete [] data_; + delete [] dataF_; delete [] cosRS_; delete [] sinRS_; } + /// Forward DFT + // Real valued DFT void applyDFT(const FReal* sampledData, FComplexe* transformedData) const { -// FTic time; - // read sampled data -// std::cout<< "copy("; -// time.tic(); - FBlas::c_setzero(nsteps_,reinterpret_cast(fftC_)); - FBlas::copy(nsteps_, sampledData,fftR_); -// std::cout << time.tacAndElapsed() << ")"; - -// std::cout<< " - exe("; -// time.tic(); + FBlas::c_setzero(nsteps_,reinterpret_cast(dataF_)); + FBlas::copy(nsteps_, sampledData,data_); + + // perform direct forward transformation for(unsigned int r=0; r(fftC_), + FBlas::c_copy(nsteps_,reinterpret_cast(dataF_), reinterpret_cast(transformedData)); -// std::cout << time.tacAndElapsed() << ") "; - } + // Complexe valued DFT + void applyDFT(const FComplexe* sampledData, + FComplexe* transformedData) const + { + // read sampled data + FBlas::c_setzero(nsteps_,reinterpret_cast(dataF_)); + FBlas::c_copy(nsteps_,reinterpret_cast(sampledData), + reinterpret_cast(data_)); + + // perform direct forward transformation + for(unsigned int r=0; r(dataF_), + reinterpret_cast(transformedData)); + } + /// Backward DFT + // Real valued IDFT void applyIDFT(const FComplexe* transformedData, FReal* sampledData) const { // read transformed data - FBlas::setzero(nsteps_,fftR_); + FBlas::setzero(nsteps_,data_); FBlas::c_copy(nsteps_,reinterpret_cast(transformedData), - reinterpret_cast(fftC_)); + reinterpret_cast(dataF_)); + // perform direct backward transformation for(unsigned int r=0; r(data_)); + FBlas::c_copy(nsteps_,reinterpret_cast(transformedData), + reinterpret_cast(dataF_)); -}; + // perform direct backward transformation + for(unsigned int r=0; r(data_), + reinterpret_cast(sampledData)); + } + +}; /** @@ -167,50 +208,56 @@ class FFft enum{dim = DIM}; // arrays - FReal* fftR_; - FComplexe* fftC_; + FReal* data_; //< data in physical space + FComplexe* dataF_; //< data in Fourier space // plans - fftw_plan plan_c2r_; // backward FFT plan - fftw_plan plan_r2c_; // forward FFT plan + fftw_plan plan_c2r_; //< backward FFT plan + fftw_plan plan_r2c_; //< forward FFT plan private: - /*unsigned*/ int nsteps_; // all dimensions have same nb of steps - /*unsigned*/ int nsteps_opt_; + int steps_[dim]; //< number of steps per dimension + int nsteps_; //< total number of steps + int nsteps_opt_; //< reduced number of steps for real valued FFT public: - FFft(const unsigned int nsteps) - : nsteps_(nsteps), - nsteps_opt_(nsteps/2+1) // SPECIFIC TO REAL VALUED FTT + FFft(const int steps[dim]) { + // init number of steps + nsteps_=1; nsteps_opt_=1; + for(int d = 0; d(fftC_), -// fftR_, +// reinterpret_cast(dataF_), +// data_, // FFTW_MEASURE);// TODO: test FFTW_ESTIMATE // plan_r2c_ = // fftw_plan_dft_r2c_1d(nsteps_, -// fftR_, -// reinterpret_cast(fftC_), +// data_, +// reinterpret_cast(dataF_), // FFTW_MEASURE); // multidim fftw plans - const int steps[2] = {dim, nsteps_}; plan_c2r_ = - fftw_plan_dft_c2r(2, steps, - reinterpret_cast(fftC_), - fftR_, + fftw_plan_dft_c2r(dim, steps_, + reinterpret_cast(dataF_), + data_, FFTW_MEASURE);// TODO: test FFTW_ESTIMATE plan_r2c_ = - fftw_plan_dft_r2c(2, steps, - fftR_, - reinterpret_cast(fftC_), + fftw_plan_dft_r2c(dim, steps_, + data_, + reinterpret_cast(dataF_), FFTW_MEASURE); } @@ -219,38 +266,22 @@ public: { fftw_destroy_plan(plan_c2r_); fftw_destroy_plan(plan_r2c_); - fftw_free(fftR_); - fftw_free(fftC_); + fftw_free(data_); + fftw_free(dataF_); } void applyDFT(const FReal* sampledData, FComplexe* transformedData) const { -// FTic time; - - // read sampled data -// std::cout<< "copy("; -// time.tic(); - FBlas::c_setzero(dim*nsteps_opt_,reinterpret_cast(fftC_)); - FBlas::copy(dim*nsteps_, sampledData,fftR_); -// std::cout << time.tacAndElapsed() << ")"; + FBlas::c_setzero(nsteps_opt_,reinterpret_cast(dataF_)); + FBlas::copy(nsteps_, sampledData,data_); // perform fft -// std::cout<< " - exe("; -// time.tic(); fftw_execute( plan_r2c_ ); -// std::cout << time.tacAndElapsed() << ")"; // write transformed data -// std::cout<< " - copy("; -// time.tic(); - FBlas::c_copy(dim*nsteps_opt_,reinterpret_cast(fftC_), + FBlas::c_copy(nsteps_opt_,reinterpret_cast(dataF_), reinterpret_cast(transformedData)); -// for(unsigned int s=0; s(transformedData), - reinterpret_cast(fftC_)); + FBlas::setzero(nsteps_,data_); + FBlas::c_copy(nsteps_opt_,reinterpret_cast(transformedData), + reinterpret_cast(dataF_)); // perform ifft fftw_execute( plan_c2r_ ); for(unsigned int s=0; s +class FCFft +{ + enum{dim = DIM}; + + // arrays + FComplexe* data_; //< data in physical space + FComplexe* dataF_; //< data in Fourier space + + // plans + fftw_plan plan_b_; // backward FFT plan + fftw_plan plan_f_; // forward FFT plan + +private: + int steps_[dim]; //< number of steps per dimension + int nsteps_; //< total number of steps +public: + + FCFft(const int steps[dim]) + { + // init number of steps + nsteps_=1; + for(int d = 0; d(dataF_), + reinterpret_cast(data_), + FFTW_BACKWARD, + FFTW_MEASURE);// TODO: test FFTW_ESTIMATE + plan_f_ = + fftw_plan_dft(dim, steps_, + reinterpret_cast(data_), + reinterpret_cast(dataF_), + FFTW_FORWARD, + FFTW_MEASURE); + + } + + virtual ~FCFft() + { + fftw_destroy_plan(plan_b_); + fftw_destroy_plan(plan_f_); + fftw_free(data_); + fftw_free(dataF_); + } + + void applyDFT(const FComplexe* sampledData, + FComplexe* transformedData) const + { + FBlas::c_setzero(nsteps_,reinterpret_cast(dataF_)); + FBlas::c_copy(nsteps_, reinterpret_cast(sampledData), + reinterpret_cast(data_)); + + // perform fft + fftw_execute( plan_f_ ); + + // write transformed data + FBlas::c_copy(nsteps_,reinterpret_cast(dataF_), + reinterpret_cast(transformedData)); + } + + + void applyIDFT(const FComplexe* transformedData, + FComplexe* sampledData) const + { + // read transformed data + FBlas::c_setzero(nsteps_,reinterpret_cast(data_)); + FBlas::c_copy(nsteps_,reinterpret_cast(transformedData), + reinterpret_cast(dataF_)); + + // perform ifft + fftw_execute( plan_b_ ); + + for(unsigned int s=0; s(data_), + reinterpret_cast(sampledData)); } diff --git a/Tests/Kernels/testChebTensorialAlgorithm.cpp b/Tests/Kernels/testChebTensorialAlgorithm.cpp index 2d522bbac4608331d40121344884815003b81462..876f365bc5e1bc0aeaf966d3deeaca5d7712b4f5 100644 --- a/Tests/Kernels/testChebTensorialAlgorithm.cpp +++ b/Tests/Kernels/testChebTensorialAlgorithm.cpp @@ -15,7 +15,7 @@ // =================================================================================== // ==== CMAKE ===== -// @FUSE_FFT +// @FUSE_BLAS // ================ #include diff --git a/Tests/Utils/testFFTWMultidim.cpp b/Tests/Utils/testFFTWMultidim.cpp index da668758ce1a2a4a498d6c08788f2c3a856a8129..44290c78be973e4d7f6d7fd9988085e4614fcd99 100644 --- a/Tests/Utils/testFFTWMultidim.cpp +++ b/Tests/Utils/testFFTWMultidim.cpp @@ -44,23 +44,24 @@ int main() ////////////////////////////////////////////////////////////////////////////// // INITIALIZATION - // size (pick a power of 2 for better performance of the FFT algorithm) - unsigned int rank = 2; - unsigned int nsteps_ = 500; - unsigned int dim = 10; - const int steps[2]={static_cast(dim), - static_cast(nsteps_)}; - unsigned int size = dim*nsteps_; - + const int dim=2; + const int pow_nsteps_=8; + int steps_[dim]; + int nsteps_=1; + for(int d=0; d(fftC_), fftR_, FFTW_MEASURE); plan_r2c_ = - fftw_plan_dft_r2c(rank, steps, + fftw_plan_dft_r2c(dim, steps_, fftR_, reinterpret_cast(fftC_), FFTW_MEASURE); @@ -87,20 +88,20 @@ int main() ////////////////////////////////////////////////////////////////////////////// // EXECUTION // generate random physical data - for(unsigned int s=0; s Dft(N);// fast version + FFft Dft(steps);// fast version std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; // Initialize manually @@ -135,7 +137,8 @@ int main(int, char **){ // Transform first column of K FReal tK[N]; - for(unsigned int i=0; iFK: "; time.tic(); Dft.applyDFT(tK,FK); diff --git a/Tests/Utils/testLapack.cpp b/Tests/Utils/testLapack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecf3f327e5ebf0b835a23933767fb6d2eb8f1f63 --- /dev/null +++ b/Tests/Utils/testLapack.cpp @@ -0,0 +1,121 @@ +// =================================================================================== +// 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_BLAS +// ================ + +#include +#include + +#include "../../Src/Utils/FBlas.hpp" +#include "../../Src/Utils/FTic.hpp" + +/** + * Test functionality of C - interfaced LAPACK functions + */ + +int main() +{ + FTic time; + + /* + * List of tested functions: + * Cholesky decomposition: FBlas::potrf() + * TODO SVD: FBlas::gesvd() + * TODO QR decomposition: FBlas::geqrf() + */ + + const unsigned int m = 4, n = 4; + FReal* A = new FReal [m * n]; // matrix: column major ordering + + // A= LL^T //////////////////////////////////// + // define symmetric definite positive matrix A + A[0]=5; A[10]=4; A[15]=7; + A[1]=A[3]=A[4]=A[12]=2; + A[6]=A[7]=A[9]=A[13]=1; + A[2]=A[5]=A[8]=3; + A[11]=A[14]=-1; + + // copy A in C + FReal* C = new FReal [m * n]; // matrix: column major ordering + for (unsigned int ii=0; ii