Convolution transformation using existing infrastructure with C++20 ranges (IN-PLACE)
139{
140 if (impulse_response.size() == 1) {
141 if (std::abs(impulse_response[0] - 1.0) < 1e-15) {
142 return input;
143 } else {
144 auto [target_data, structure_info] = OperationHelper::extract_structured_double(input);
145
146 std::vector<std::vector<double>> reconstructed_data(target_data.size());
147
148 for (size_t i = 0; i < target_data.size(); ++i) {
149 std::ranges::transform(target_data[i], reconstructed_data[i].begin(),
150 [gain = impulse_response[0]](double x) { return x * gain; });
151 }
152 return OperationHelper::reconstruct_from_double<DataType>(reconstructed_data, structure_info);
153 }
154 }
155
156 auto [target_data, structure_info] = OperationHelper::extract_structured_double(input);
157
158 auto convolution_op = [](const Eigen::VectorXcd& input_fft,
159 const Eigen::VectorXcd& kernel_fft,
160 Eigen::VectorXcd& result_fft) {
161 std::ranges::transform(input_fft, kernel_fft, result_fft.begin(),
162 [](const std::complex<double>& a, const std::complex<double>& b) {
163 return a * b;
164 });
165 };
166
167 for (auto& span : target_data) {
168 auto result =
fft_convolve_helper(span, std::span<const double>(impulse_response), convolution_op,
false);
169 std::copy(result.begin(), result.end(), span.begin());
170 }
171
172 auto reconstructed_data = target_data
173 | std::views::transform([](const auto& span) {
174 return std::vector<double>(span.begin(), span.end());
175 })
176 | std::ranges::to<std::vector>();
177
178 return OperationHelper::reconstruct_from_double<DataType>(reconstructed_data, structure_info);
179}
std::vector< double > fft_convolve_helper(std::span< const double > data_span, std::span< const double > kernel, OperationFunc &&operation, bool return_full_size=true)
Common FFT convolution helper to eliminate code duplication.