23 const size_t FFTW_FACTORS[] = {13, 11, 7, 5, 3, 2};
25 FFTW_FACTORS +
sizeof(FFTW_FACTORS) /
sizeof(FFTW_FACTORS[0]));
47 , p_forw_kernel(nullptr)
68 fftw_free((fftw_complex*)out_src);
76 fftw_free((fftw_complex*)out_kernel);
89 if (p_forw_src !=
nullptr)
90 fftw_destroy_plan(p_forw_src);
91 if (p_forw_kernel !=
nullptr)
92 fftw_destroy_plan(p_forw_kernel);
93 if (p_back !=
nullptr)
94 fftw_destroy_plan(p_back);
108 int h_src = (int)source.size();
109 int w_src = (int)(source.size() ? source[0].size() : 0);
110 int h_kernel = (int)kernel.size();
111 int w_kernel = (kernel.size() ? (int)kernel[0].size() : 0);
114 init(h_src, w_src, h_kernel, w_kernel);
121 for (
int i = 0; i <
ws.
h_dst; i++) {
123 for (
int j = 0; j <
ws.
w_dst; j++) {
142 source2d.push_back(source);
143 kernel2d.push_back(kernel);
147 if (result2d.size() != 1)
148 throw std::runtime_error(
"Convolve::fftconvolve -> Panic in 1d");
149 result = result2d[0];
157 if (!h_src || !w_src || !h_kernel || !w_kernel) {
158 std::ostringstream os;
159 os <<
"Convolve::init() -> Panic! Wrong dimensions " << h_src <<
" " << w_src <<
" "
160 << h_kernel <<
" " << w_kernel << std::endl;
161 throw std::runtime_error(os.str());
174 ws.
h_dst = h_src + h_kernel - 1;
175 ws.
w_dst = w_src + w_kernel - 1;
182 ws.
h_fftw = h_src + int(h_kernel / 2.0);
183 ws.
w_fftw = w_src + int(w_kernel / 2.0);
209 std::cout <<
"The 'valid' convolution results in an empty matrix" << std::endl;
210 throw std::runtime_error(
"The 'valid' convolution results in an empty matrix");
214 ws.
h_dst = h_src - h_kernel + 1;
215 ws.
w_dst = w_src - w_kernel + 1;
237 <<
"Unrecognized convolution mode, possible modes are "
238 <<
"FFTW_LINEAR_FULL, FFTW_LINEAR_SAME, FFTW_LINEAR_SAME_UNPADDED, FFTW_LINEAR_VALID, "
239 <<
"FFTW_CIRCULAR_SAME, FFTW_CIRCULAR_SHIFTED " << std::endl;
255 throw std::runtime_error(
"Convolve::init() -> Error! Can't initialise p_forw_src plan.");
260 throw std::runtime_error(
"Convolve::init() -> Error! Can't initialise p_forw_kernel plan.");
266 throw std::runtime_error(
"Convolve::init() -> Error! Can't initialise p_back plan.");
276 throw std::runtime_error(
"Convolve::fftw_convolve() -> Panic! Initialisation is missed.");
278 double *ptr, *ptr_end, *ptr2;
288 for (
int i = 0; i <
ws.
h_src; ++i)
289 for (
int j = 0; j <
ws.
w_src; ++j, ++ptr)
303 double re_s, im_s, re_k, im_k;
306 ptr != ptr_end; ++ptr, ++ptr2) {
311 *(ptr2 - 1) = re_s * re_k - im_s * im_k;
312 *ptr2 = re_s * im_k + im_s * re_k;
Defines class Math::Convolve.
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