24 const size_t FFTW_FACTORS[] = {13, 11, 7, 5, 3, 2};
26 FFTW_FACTORS +
sizeof(FFTW_FACTORS) /
sizeof(FFTW_FACTORS[0]));
30 : h_src(0), w_src(0), h_kernel(0), w_kernel(0), w_fftw(0), h_fftw(0), in_src(0), out_src(0),
31 in_kernel(0), out_kernel(0), dst_fft(0), h_dst(0), w_dst(0),
33 h_offset(0), w_offset(0), p_forw_src(nullptr), p_forw_kernel(nullptr), p_back(nullptr)
53 fftw_free((fftw_complex*)out_src);
61 fftw_free((fftw_complex*)out_kernel);
74 if (p_forw_src !=
nullptr)
75 fftw_destroy_plan(p_forw_src);
76 if (p_forw_kernel !=
nullptr)
77 fftw_destroy_plan(p_forw_kernel);
78 if (p_back !=
nullptr)
79 fftw_destroy_plan(p_back);
93 int h_src = (int)source.size();
94 int w_src = (int)(source.size() ? source[0].size() : 0);
95 int h_kernel = (int)kernel.size();
96 int w_kernel = (kernel.size() ? (int)kernel[0].size() : 0);
99 init(h_src, w_src, h_kernel, w_kernel);
106 for (
int i = 0; i <
ws.
h_dst; i++) {
108 for (
int j = 0; j <
ws.
w_dst; j++) {
127 source2d.push_back(source);
128 kernel2d.push_back(kernel);
132 if (result2d.size() != 1)
134 result = result2d[0];
142 if (!h_src || !w_src || !h_kernel || !w_kernel) {
143 std::ostringstream os;
144 os <<
"Convolve::init() -> Panic! Wrong dimensions " << h_src <<
" " << w_src <<
" "
145 << h_kernel <<
" " << w_kernel << std::endl;
159 ws.
h_dst = h_src + h_kernel - 1;
160 ws.
w_dst = w_src + w_kernel - 1;
167 ws.
h_fftw = h_src + int(h_kernel / 2.0);
168 ws.
w_fftw = w_src + int(w_kernel / 2.0);
194 std::cout <<
"The 'valid' convolution results in an empty matrix" << std::endl;
195 throw std::runtime_error(
"The 'valid' convolution results in an empty matrix");
199 ws.
h_dst = h_src - h_kernel + 1;
200 ws.
w_dst = w_src - w_kernel + 1;
222 <<
"Unrecognized convolution mode, possible modes are "
223 <<
"FFTW_LINEAR_FULL, FFTW_LINEAR_SAME, FFTW_LINEAR_SAME_UNPADDED, FFTW_LINEAR_VALID, "
224 <<
"FFTW_CIRCULAR_SAME, FFTW_CIRCULAR_SHIFTED " << std::endl;
241 "Convolve::init() -> Error! Can't initialise p_forw_src plan.");
247 "Convolve::init() -> Error! Can't initialise p_forw_kernel plan.");
254 "Convolve::init() -> Error! Can't initialise p_back plan.");
265 "Convolve::fftw_convolve() -> Panic! Initialisation is missed.");
267 double *ptr, *ptr_end, *ptr2;
277 for (
int i = 0; i <
ws.
h_src; ++i)
278 for (
int j = 0; j <
ws.
w_src; ++j, ++ptr)
292 double re_s, im_s, re_k, im_k;
295 ptr != ptr_end; ++ptr, ++ptr2) {
300 *(ptr2 - 1) = re_s * re_k - im_s * im_k;
301 *ptr2 = re_s * im_k + im_s * re_k;
Defines class MathFunctions::Convolve.
Defines many exception classes in namespace Exceptionss.
double * out_src
result of Fourier transformation of source
double * in_src
adjusted input 'source' array
double * in_kernel
adjusted input 'kernel' array
double * dst_fft
result of product of FFT(source) and FFT(kernel)
double * out_kernel
result of Fourier transformation of kernel
EConvolutionMode m_mode
convolution mode
Workspace ws
input and output data for fftw3
std::vector< double1d_t > double2d_t
definition of 2d vector of double
std::vector< size_t > m_implemented_factors
std::vector< double > double1d_t
definition of 1d vector of double
@ FFTW_CIRCULAR_SAME_SHIFTED
@ FFTW_LINEAR_SAME_UNPADDED
void init(int h_src, int w_src, int h_kernel, int w_kernel)
prepare arrays for 2D convolution of given vectors
void setMode(EConvolutionMode mode)
Sets convolution mode.
void fftconvolve(const double1d_t &source, const double1d_t &kernel, double1d_t &result)
convolution in 1D
bool is_optimal(int n)
if a number can be factorised using only favorite fftw3 factors
void fftw_circular_convolution(const double2d_t &source, const double2d_t &kernel)
compute circual convolution of source and kernel using fast Fourier transformation
int find_closest_factor(int n)
find closest number X>n that can be factorised according to fftw3 favorite factorisation