I have seen few examples on Eigen FFT library that I wanted to implement before moving on FFTW library. For some reason I am unable to get the correct 1D FFT along each row of an Eigen matrix. I get the 1D FFT along each column correctly, but not rows. I am comparing a very very simple C++ code with MATLAB for clarity.
In MATLAB:
Nx=8;
Ny=8;
u = eye(Ny+1,Nx); %very simple choice for now
%take FFT along columns
ucol = fft(u,[],1);
urow = fft(u,[],2);
In C++:
#include "fftw3.h"
#include<unsupported/Eigen/CXX11/Tensor>
static const int nx=8;
static const int ny=8;
using namespace std;
using namespace Eigen;
int main{
Eigen::FFT<double> fft;
Eigen::MatrixXcd u(ny+1,nx);
u.setIdentity();
//1D FFT along cols
Eigen::MatrixXcd ucol(ny+1,nx);
for (int k=0; k<u.cols(); k++){
ucol.col(k) = fft.fwd(u.col(k));
}
std::cout<<ucol<<endl; //correct compared to MATLAB: ucol = fft(u,[],1);
//1D FFT along rows
Eigen::MatrixXcd urow(ny+1,nx);
for (int k=0; k<u.rows(); k++){
urow.row(k) = fft.fwd(u.row(k));
}
std::cout<<urow<<endl; //**Incorrect** compared to MATLAB: urow = fft(u,[],2);
}
Why is the second 1D FFT incorrect compared to MATLAB??
MATLAB outputs:
ucol =
1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i
1.0000 + 0.0000i 0.7660 - 0.6428i 0.1736 - 0.9848i -0.5000 - 0.8660i -0.9397 - 0.3420i -0.9397 + 0.3420i -0.5000 + 0.8660i 0.1736 + 0.9848i
1.0000 + 0.0000i 0.1736 - 0.9848i -0.9397 - 0.3420i -0.5000 + 0.8660i 0.7660 + 0.6428i 0.7660 - 0.6428i -0.5000 - 0.8660i -0.9397 + 0.3420i
1.0000 + 0.0000i -0.5000 - 0.8660i -0.5000 + 0.8660i 1.0000 + 0.0000i -0.5000 - 0.8660i -0.5000 + 0.8660i 1.0000 + 0.0000i -0.5000 - 0.8660i
1.0000 + 0.0000i -0.9397 - 0.3420i 0.7660 + 0.6428i -0.5000 - 0.8660i 0.1736 + 0.9848i 0.1736 - 0.9848i -0.5000 + 0.8660i 0.7660 - 0.6428i
1.0000 + 0.0000i -0.9397 + 0.3420i 0.7660 - 0.6428i -0.5000 + 0.8660i 0.1736 - 0.9848i 0.1736 + 0.9848i -0.5000 - 0.8660i 0.7660 + 0.6428i
1.0000 + 0.0000i -0.5000 + 0.8660i -0.5000 - 0.8660i 1.0000 + 0.0000i -0.5000 + 0.8660i -0.5000 - 0.8660i 1.0000 + 0.0000i -0.5000 + 0.8660i
1.0000 + 0.0000i 0.1736 + 0.9848i -0.9397 + 0.3420i -0.5000 - 0.8660i 0.7660 - 0.6428i 0.7660 + 0.6428i -0.5000 + 0.8660i -0.9397 - 0.3420i
1.0000 + 0.0000i 0.7660 + 0.6428i 0.1736 + 0.9848i -0.5000 + 0.8660i -0.9397 + 0.3420i -0.9397 - 0.3420i -0.5000 - 0.8660i 0.1736 - 0.9848i
urow =
1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i 1.0000 + 0.0000i
1.0000 + 0.0000i 0.7071 - 0.7071i 0.0000 - 1.0000i -0.7071 - 0.7071i -1.0000 + 0.0000i -0.7071 + 0.7071i 0.0000 + 1.0000i 0.7071 + 0.7071i
1.0000 + 0.0000i 0.0000 - 1.0000i -1.0000 + 0.0000i 0.0000 + 1.0000i 1.0000 + 0.0000i 0.0000 - 1.0000i -1.0000 + 0.0000i 0.0000 + 1.0000i
1.0000 + 0.0000i -0.7071 - 0.7071i 0.0000 + 1.0000i 0.7071 - 0.7071i -1.0000 + 0.0000i 0.7071 + 0.7071i 0.0000 - 1.0000i -0.7071 + 0.7071i
1.0000 + 0.0000i -1.0000 + 0.0000i 1.0000 + 0.0000i -1.0000 + 0.0000i 1.0000 + 0.0000i -1.0000 + 0.0000i 1.0000 + 0.0000i -1.0000 + 0.0000i
1.0000 + 0.0000i -0.7071 + 0.7071i 0.0000 - 1.0000i 0.7071 + 0.7071i -1.0000 + 0.0000i 0.7071 - 0.7071i 0.0000 + 1.0000i -0.7071 - 0.7071i
1.0000 + 0.0000i 0.0000 + 1.0000i -1.0000 + 0.0000i 0.0000 - 1.0000i 1.0000 + 0.0000i 0.0000 + 1.0000i -1.0000 + 0.0000i 0.0000 - 1.0000i
1.0000 + 0.0000i 0.7071 + 0.7071i 0.0000 + 1.0000i -0.7071 + 0.7071i -1.0000 + 0.0000i -0.7071 - 0.7071i 0.0000 - 1.0000i 0.7071 - 0.7071i
0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i
C++ output:
ucol=
(1.000,0.000) (1.000,0.000) (1.000,0.000) (1.000,0.000) (1.000,0.000) (1.000,0.000) (1.000,0.000) (1.000,0.000)
(1.000,0.000) (0.766,-0.643) (0.174,-0.985) (-0.500,-0.866) (-0.940,-0.342) (-0.940,0.342) (-0.500,0.866) (0.174,0.985)
(1.000,0.000) (0.174,-0.985) (-0.940,-0.342) (-0.500,0.866) (0.766,0.643) (0.766,-0.643) (-0.500,-0.866) (-0.940,0.342)
(1.000,0.000) (-0.500,-0.866) (-0.500,0.866) (1.000,0.000) (-0.500,-0.866) (-0.500,0.866) (1.000,0.000) (-0.500,-0.866)
(1.000,0.000) (-0.940,-0.342) (0.766,0.643) (-0.500,-0.866) (0.174,0.985) (0.174,-0.985) (-0.500,0.866) (0.766,-0.643)
(1.000,-0.000) (-0.940,0.342) (0.766,-0.643) (-0.500,0.866) (0.174,-0.985) (0.174,0.985) (-0.500,-0.866) (0.766,0.643)
(1.000,-0.000) (-0.500,0.866) (-0.500,-0.866) (1.000,-0.000) (-0.500,0.866) (-0.500,-0.866) (1.000,-0.000) (-0.500,0.866)
(1.000,-0.000) (0.174,0.985) (-0.940,0.342) (-0.500,-0.866) (0.766,-0.643) (0.766,0.643) (-0.500,0.866) (-0.940,-0.342)
(1.000,-0.000) (0.766,0.643) (0.174,0.985) (-0.500,0.866) (-0.940,0.342) (-0.940,-0.342) (-0.500,-0.866) (0.174,-0.985)
urow=
(1.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,-0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,-0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,-0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(1.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
(0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000) (0.000,0.000)
why is urow
from the C++ code not matching the MATLAB output?? I am pretty sure the second loop is iterating over all rows of u
Thanks
Your usage of fft.fwd
is not correct. The documentation shows that the function expects the frequency vector and then the time vector. You are providing only one input.
Here is godbolt: https://www.godbolt.org/z/Mecfr487f
Here is just the code.
#include <Eigen/Core>
#include<unsupported/Eigen/CXX11/Tensor>
#include <unsupported/Eigen/FFT>
#include <iostream>
static const int nx=8;
static const int ny=8;
using namespace std;
using namespace Eigen;
int main(int argc, char * argv[]){
Eigen::FFT<double> fft;
Eigen::MatrixXcd u(ny+1,nx);
u.setIdentity();
//1D FFT along cols
Eigen::MatrixXcd ucol(ny+1,nx);
Eigen::VectorXcd col(ny+1);
for (int k=0; k<u.cols(); k++){
// ucol.col(k) = fft.fwd(u.col(k));
fft.fwd(col, u.col(k));
ucol.col(k) = col;
}
std::cout<<ucol<<endl;
//1D FFT along rows
Eigen::MatrixXcd urow(ny+1,nx);
Eigen::VectorXcd row(nx);
for (int k=0; k<u.rows(); k++){
// urow.row(k) = fft.fwd(u.row(k));
fft.fwd(row, u.row(k));
urow.row(k) = row;
}
std::cout<<urow<<endl;
}