24 FourierTransform::FourierTransform() =
default;
26 FourierTransform::Workspace::Workspace()
27 : h_src(0), w_src(0), h_fftw(0), w_fftw(0), in_src(0), out_fftw(0), p_forw_src(nullptr)
31 FourierTransform::Workspace::~Workspace()
36 void FourierTransform::Workspace::clear()
47 fftw_free((fftw_complex*)out_fftw);
50 if (p_forw_src !=
nullptr)
51 fftw_destroy_plan(p_forw_src);
62 int h_src =
static_cast<int>(source.size());
63 int w_src =
static_cast<int>((source.size() ? source[0].size() : 0));
69 fftw_forward_FT(source);
71 double* ptr = ws.out_fftw;
75 result.resize(
static_cast<size_t>(ws.h_fftw),
76 std::vector<double>(
static_cast<size_t>(ws.w_fftw)));
79 for (
size_t i = 0; i < static_cast<size_t>(ws.h_fftw); i++) {
80 size_t k =
static_cast<size_t>(ws.h_fftw) - i;
82 k -=
static_cast<size_t>(ws.h_fftw);
83 for (
size_t j = 0; j < static_cast<size_t>(ws.w_fftw / 2 + 1); j++) {
85 size_t l =
static_cast<size_t>(ws.w_fftw) - j;
87 result[k][l] = result[i][j];
100 if (result.size() % 2 == 0)
101 row_shift = result.size() / 2;
103 row_shift = result.size() / 2 + 1;
106 if (result[0].size() % 2 == 0)
107 col_shift = result[0].size() / 2;
109 col_shift = result[0].size() / 2 + 1;
112 std::rotate(result.begin(), result.begin() +
static_cast<int>(row_shift), result.end());
115 for (
size_t i = 0; i < static_cast<size_t>(ws.h_fftw); i++) {
116 std::rotate(result[i].begin(), result[i].begin() +
static_cast<int>(col_shift),
128 source2d.push_back(source);
131 fft(source2d, result2d);
133 if (result2d.size() != 1)
136 result = result2d[0];
146 if (result.size() % 2 == 0)
147 col_shift = result.size() / 2;
149 col_shift = result.size() / 2 + 1;
151 std::rotate(result.begin(), result.begin() +
static_cast<int>(col_shift), result.end());
159 if (!h_src || !w_src) {
160 std::ostringstream os;
161 os <<
"FourierTransform::init() -> Panic! Wrong dimensions " << h_src <<
" " << w_src
173 ws.in_src =
new double[
static_cast<size_t>(ws.h_fftw * ws.w_fftw)];
174 ws.out_fftw =
static_cast<double*
>(
175 fftw_malloc(
sizeof(fftw_complex) *
static_cast<size_t>(ws.h_fftw * (ws.w_fftw / 2 + 1))));
178 ws.p_forw_src = fftw_plan_dft_r2c_2d(ws.h_fftw, ws.w_fftw, ws.in_src,
179 (fftw_complex*)ws.out_fftw, FFTW_ESTIMATE);
183 if (ws.p_forw_src ==
nullptr)
185 "FourierTransform::init() -> Error! Can't initialise p_forw_src plan.");
192 void FourierTransform::fftw_forward_FT(
const double2d_t& src)
194 if (ws.h_fftw <= 0 || ws.w_fftw <= 0)
196 "FourierTransform::fftw_forward_FT() -> Panic! Initialisation is missed.");
198 double *ptr, *ptr_end;
201 for (ptr = ws.in_src, ptr_end = ws.in_src + ws.h_fftw * ws.w_fftw; ptr != ptr_end; ++ptr)
205 for (
size_t row = 0; row < static_cast<size_t>(ws.h_src); ++row)
206 for (
size_t col = 0; col < static_cast<size_t>(ws.w_src); ++col)
207 ws.in_src[(
static_cast<int>(row) % ws.h_fftw) * ws.w_fftw
208 + (
static_cast<int>(col) % ws.w_fftw)] += src[row][col];
211 fftw_execute(ws.p_forw_src);
213 double re_out, im_out;
214 for (ptr = ws.out_fftw, ptr_end = ws.out_fftw + 2 * ws.h_fftw * (ws.w_fftw / 2 + 1);
215 ptr != ptr_end; ++ptr) {
220 *(ptr - 1) = sqrt(re_out * re_out + im_out * im_out);
222 *ptr = atan2(im_out, re_out);
Defines many exception classes in namespace Exceptionss.