I am looking for a C++ library for Fast Fourier Transform (FFT) in high precision (e.g., using high precision real data types similar to mpfr_t
in MPFR or cpp_dec_float
in BOOST). The preference is for open-source or, if not available, at least "free for academic research" libraries. I have tried standard precision optimized implementations such as FFTW in long double
, but that proved to be insufficient. An ideal solution would link to BOOST since I am using special function implementations from that library.
2 Answers
You might want to take a look at the Eigen C++ matrix class library.
http://eigen.tuxfamily.org/index.php?title=Main_Page
There is an FFT class in the unsupported section of the library but my impression is that it is relatively mature.
Here is a snippet of code using this FFT class with the BOOST multi-precision classes.
#include <vector>
#include <cmath>
#include <complex>
#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/FFT>
#include <boost/multiprecision/cpp_dec_float.hpp>
using boost::multiprecision::cpp_dec_float_50;
using std::cout;
using std::endl;
void twoSinTest() {
const double pi = 2.*std::acos(0.);
#if 0
typedef double FFTFloat;
#else
typedef cpp_dec_float_50 FFTFloat;
#endif
double Fs = 1000; // Sampling frequency
double T = 1 / Fs; // Sampling period
int L = 1000; // Length of signal
std::vector<FFTFloat> timebuf(L);
typedef std::complex<FFTFloat> C;
std::vector<C> freqbuf;
double t = 0;
for (int i = 0; i < L; i++) {
timebuf[i] = 0.7*std::sin(2 * pi * 50 * t) + std::sin(2 * pi * 120 * t);
t += T;
}
Eigen::FFT<FFTFloat> fft;
fft.fwd(freqbuf, timebuf);
cout << freqbuf.size() << endl;
for (int i = 0; i < freqbuf.size(); i++) {
const C &f = freqbuf[i];
cout << i << " " << f << endl;
}
}
-
$\begingroup$ Thanks much for the code! What compiler/STL/Boost versions have you used? I am running into some template instantiation errors and I think it is cpp_dec_float_50 assignment to std::complex<cpp_dec_float_50> someplace inside FFT code. $\endgroup$ Apr 29, 2016 at 22:19
-
$\begingroup$ I built the code above with Visual Studio Express 2013, x64. I used BOOST 1.57 and Eigen 3.2.6. $\endgroup$ Apr 29, 2016 at 22:37
-
$\begingroup$ Hmm, on gcc-5 (under Ubuntu) your code works with float128 bu not with ccp_dec_float50 or mpr_float_50. The issue seems to be related to stackoverflow.com/questions/21737186/… Any suggestions? $\endgroup$ Apr 29, 2016 at 23:57
ARPREC (http://crd-legacy.lbl.gov/~dhbailey/mpdist/) is an arbitrary-precision C++/Fortran package and contains an FFT implementation.
Apfloat (http://www.apfloat.org/apfloat/) is another C++ arbitrary-precision library which contains FFT.
Both of the above packages have been included in the FFTW benchmark (http://www.fftw.org/speed/)
-
$\begingroup$ I had an impression that the FFT subroutine in ARPREC was not multi-precision. And it does not seem to be maintained anymore. Let me mook into Apfloat though... $\endgroup$ Apr 29, 2016 at 8:05