From e6af368c7746cfa268ad4b702f462d99e0367aaf Mon Sep 17 00:00:00 2001 From: lpha-z Date: Mon, 12 Sep 2016 18:13:01 +0900 Subject: [PATCH] add C++11constexpr fft Stockham DIT fft algorithm written in C++11constexpr --- sprout/numeric/fft/coefficients.hpp | 81 ++++++++++++++++ sprout/numeric/fft/cxx14/fft.hpp | 137 ++++++++++++++++++++++++++++ sprout/numeric/fft/cxx14/ifft.hpp | 58 ++++++++++++ sprout/numeric/fft/fft.hpp | 127 +------------------------- sprout/numeric/fft/fit/fft.hpp | 55 +++++++++++ sprout/numeric/fft/fit/ifft.hpp | 55 +++++++++++ sprout/numeric/fft/fixed/fft.hpp | 118 ++++++++++++++++++++++++ sprout/numeric/fft/fixed/ifft.hpp | 65 +++++++++++++ sprout/numeric/fft/ifft.hpp | 48 +--------- 9 files changed, 575 insertions(+), 169 deletions(-) create mode 100644 sprout/numeric/fft/coefficients.hpp create mode 100644 sprout/numeric/fft/cxx14/fft.hpp create mode 100644 sprout/numeric/fft/cxx14/ifft.hpp create mode 100644 sprout/numeric/fft/fit/fft.hpp create mode 100644 sprout/numeric/fft/fit/ifft.hpp create mode 100644 sprout/numeric/fft/fixed/fft.hpp create mode 100644 sprout/numeric/fft/fixed/ifft.hpp diff --git a/sprout/numeric/fft/coefficients.hpp b/sprout/numeric/fft/coefficients.hpp new file mode 100644 index 00000000..ba33202e --- /dev/null +++ b/sprout/numeric/fft/coefficients.hpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_COEFFICIENT_ARRAY_HPP +#define SPROUT_NUMERIC_FFT_COEFFICIENT_ARRAY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail + { + template + inline SPROUT_CONSTEXPR sprout::array, sizeof...(Indexes)*2> + make_fft_coefficients_impl( + sprout::array, sizeof...(Indexes)> const& arr, + sprout::complex mul, sprout::index_tuple + ) + { + return sprout::array, sizeof...(Indexes)*2>{ { + arr[Indexes]..., (arr[Indexes] * mul)... + } }; + } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + N == 0, + typename sprout::array, 1> + >::type + make_fft_coefficients_loop( bool ) { + return typename sprout::array, 1>{ { + { static_cast( 1 ) } + } }; + } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + N != 0, + typename sprout::array, 1 << N> + >::type + make_fft_coefficients_loop(bool inverse) + { + return make_fft_coefficients_impl( + make_fft_coefficients_loop(inverse), + { + sprout::cos((inverse?-1:1)*sprout::math::two_pi() / (1 << Size >> (N - 1))), + sprout::sin((inverse?-1:1)*sprout::math::two_pi() / (1 << Size >> (N - 1))) + }, + sprout::make_index_tuple<1 << (N - 1)>() + ); + } + + template + inline SPROUT_CONSTEXPR sprout::array, 1 << Size> + make_fft_coefficients(bool inverse) { + return make_fft_coefficients_loop(inverse); + } + } // namespace detail + template + inline SPROUT_CONSTEXPR sprout::array, Size> + make_fft_coefficients() { + return sprout::detail::make_fft_coefficients(false); + } + template + inline SPROUT_CONSTEXPR sprout::array, Size> + make_ifft_coefficients() { + return sprout::detail::make_fft_coefficients(true); + } +} // namespce sprout + +#endif // SPROUT_NUMERIC_FFT_COEFFICIENT_ARRAY_HPP diff --git a/sprout/numeric/fft/cxx14/fft.hpp b/sprout/numeric/fft/cxx14/fft.hpp new file mode 100644 index 00000000..a873c543 --- /dev/null +++ b/sprout/numeric/fft/cxx14/fft.hpp @@ -0,0 +1,137 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_CXX14_FFT_HPP +#define SPROUT_NUMERIC_FFT_CXX14_FFT_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // fft + // + template + inline SPROUT_CXX14_CONSTEXPR void + fft(RandomAccessIterator first, RandomAccessIterator last) { + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::value_type value_type; + typedef typename value_type::value_type elem_type; + using sprout::real; + using sprout::imag; + difference_type const size = last - first; + // scrambler + for (difference_type i = 0, j = 1; j < size - 1; ++j) { + for (difference_type k = size >> 1; k > (i ^= k); k >>= 1) + ; + if (j < i) { + sprout::swap(first[i], first[j]); + } + } + // L shaped butterflies + elem_type const theta = -(sprout::math::half_pi() / size); + for (difference_type m = 4; m <= size; m <<= 1) { + difference_type mq = m >> 2; + // W == 1 + for (difference_type k = mq; k >= 1; k >>= 2) { + for (difference_type j = mq - k; j < mq - (k >> 1); ++j) { + difference_type j1 = j + mq; + difference_type j2 = j1 + mq; + difference_type j3 = j2 + mq; + value_type x1 = first[j] - first[j1]; + first[j] += first[j1]; + value_type x3 = first[j3] - first[j2]; + first[j2] += first[j3]; + first[j1] = value_type( + real(x1) - imag(x3), + imag(x1) + real(x3) + ); + first[j3] = value_type( + real(x1) + imag(x3), + imag(x1) - real(x3) + ); + } + } + if (m == size) { + continue; + } + difference_type irev = size >> 1; + elem_type w1r = sprout::cos(theta * irev); + for (difference_type k = mq; k >= 1; k >>= 2) { + for (difference_type j = m + mq - k; j < m + mq - (k >> 1); ++j) { + difference_type j1 = j + mq; + difference_type j2 = j1 + mq; + difference_type j3 = j2 + mq; + value_type x1 = first[j] - first[j1]; + first[j] += first[j1]; + value_type x3 = first[j3] - first[j2]; + first[j2] += first[j3]; + elem_type x0r = real(x1) - imag(x3); + elem_type x0i = imag(x1) + real(x3); + first[j1] = value_type( + w1r * (x0r + x0i), + w1r * (x0i - x0r) + ); + x0r = real(x1) + imag(x3); + x0i = imag(x1) - real(x3); + first[j3] = value_type( + w1r * (-x0r + x0i), + w1r * (-x0i - x0r) + ); + } + } + for (difference_type i = 2 * m; i < size; i += m) { + for (difference_type k = size >> 1; k > (irev ^= k); k >>= 1) + ; + elem_type w1r = sprout::cos(theta * irev); + elem_type w1i = sprout::sin(theta * irev); + elem_type w3r = sprout::cos(theta * 3 * irev); + elem_type w3i = sprout::sin(theta * 3 * irev); + for (difference_type k = mq; k >= 1; k >>= 2) { + for (difference_type j = i + mq - k; j < i + mq - (k >> 1); ++j) { + difference_type j1 = j + mq; + difference_type j2 = j1 + mq; + difference_type j3 = j2 + mq; + value_type x1 = first[j] - first[j1]; + first[j] += first[j1]; + value_type x3 = first[j3] - first[j2]; + first[j2] += first[j3]; + elem_type x0r = real(x1) - imag(x3); + elem_type x0i = imag(x1) + real(x3); + first[j1] = value_type( + w1r * x0r - w1i * x0i, + w1r * x0i + w1i * x0r + ); + x0r = real(x1) + imag(x3); + x0i = imag(x1) - real(x3); + first[j3] = value_type( + w3r * x0r - w3i * x0i, + w3r * x0i + w3i * x0r + ); + } + } + } + } + // radix 2 butterflies + difference_type mq = size >> 1; + for (difference_type k = mq; k >= 1; k >>= 2) { + for (difference_type j = mq - k; j < mq - (k >> 1); ++j) { + difference_type j1 = mq + j; + value_type x0 = first[j] - first[j1]; + first[j] += first[j1]; + first[j1] = x0; + } + } + } +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_CXX14_FFT_HPP diff --git a/sprout/numeric/fft/cxx14/ifft.hpp b/sprout/numeric/fft/cxx14/ifft.hpp new file mode 100644 index 00000000..6839173f --- /dev/null +++ b/sprout/numeric/fft/cxx14/ifft.hpp @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_CXX14_IFFT_HPP +#define SPROUT_NUMERIC_FFT_CXX14_IFFT_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + struct conj_value { + public: + template + SPROUT_CONSTEXPR Complex operator()(Complex const& x) const { + return conj(x); + } + }; + + template + struct conj_div_value { + private: + Size n_; + public: + explicit SPROUT_CONSTEXPR conj_div_value(Size n) + : n_(n) + {} + template + SPROUT_CONSTEXPR Complex operator()(Complex const& x) const { + return conj(x) / typename Complex::value_type(n_); + } + }; + template + SPROUT_CONSTEXPR sprout::detail::conj_div_value + conj_div(Size n) { + return sprout::detail::conj_div_value(n); + } + } // namespace detail + // + // ifft + // + template + inline SPROUT_CXX14_CONSTEXPR void + ifft(RandomAccessIterator first, RandomAccessIterator last) { + sprout::transform(first, last, first, sprout::detail::conj_value()); + sprout::fft(first, last); + sprout::transform(first, last, first, sprout::detail::conj_div(last - first)); + } +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_CXX14_IFFT_HPP diff --git a/sprout/numeric/fft/fft.hpp b/sprout/numeric/fft/fft.hpp index 02082656..4d31b61e 100644 --- a/sprout/numeric/fft/fft.hpp +++ b/sprout/numeric/fft/fft.hpp @@ -8,130 +8,9 @@ #ifndef SPROUT_NUMERIC_FFT_FFT_HPP #define SPROUT_NUMERIC_FFT_FFT_HPP -#include #include -#include -#include -#include -#include -#include - -namespace sprout { - // - // fft - // - template - inline SPROUT_CXX14_CONSTEXPR void - fft(RandomAccessIterator first, RandomAccessIterator last) { - typedef typename std::iterator_traits::difference_type difference_type; - typedef typename std::iterator_traits::value_type value_type; - typedef typename value_type::value_type elem_type; - using sprout::real; - using sprout::imag; - difference_type const size = last - first; - // scrambler - for (difference_type i = 0, j = 1; j < size - 1; ++j) { - for (difference_type k = size >> 1; k > (i ^= k); k >>= 1) - ; - if (j < i) { - sprout::swap(first[i], first[j]); - } - } - // L shaped butterflies - elem_type const theta = -(sprout::math::half_pi() / size); - for (difference_type m = 4; m <= size; m <<= 1) { - difference_type mq = m >> 2; - // W == 1 - for (difference_type k = mq; k >= 1; k >>= 2) { - for (difference_type j = mq - k; j < mq - (k >> 1); ++j) { - difference_type j1 = j + mq; - difference_type j2 = j1 + mq; - difference_type j3 = j2 + mq; - value_type x1 = first[j] - first[j1]; - first[j] += first[j1]; - value_type x3 = first[j3] - first[j2]; - first[j2] += first[j3]; - first[j1] = value_type( - real(x1) - imag(x3), - imag(x1) + real(x3) - ); - first[j3] = value_type( - real(x1) + imag(x3), - imag(x1) - real(x3) - ); - } - } - if (m == size) { - continue; - } - difference_type irev = size >> 1; - elem_type w1r = sprout::cos(theta * irev); - for (difference_type k = mq; k >= 1; k >>= 2) { - for (difference_type j = m + mq - k; j < m + mq - (k >> 1); ++j) { - difference_type j1 = j + mq; - difference_type j2 = j1 + mq; - difference_type j3 = j2 + mq; - value_type x1 = first[j] - first[j1]; - first[j] += first[j1]; - value_type x3 = first[j3] - first[j2]; - first[j2] += first[j3]; - elem_type x0r = real(x1) - imag(x3); - elem_type x0i = imag(x1) + real(x3); - first[j1] = value_type( - w1r * (x0r + x0i), - w1r * (x0i - x0r) - ); - x0r = real(x1) + imag(x3); - x0i = imag(x1) - real(x3); - first[j3] = value_type( - w1r * (-x0r + x0i), - w1r * (-x0i - x0r) - ); - } - } - for (difference_type i = 2 * m; i < size; i += m) { - for (difference_type k = size >> 1; k > (irev ^= k); k >>= 1) - ; - elem_type w1r = sprout::cos(theta * irev); - elem_type w1i = sprout::sin(theta * irev); - elem_type w3r = sprout::cos(theta * 3 * irev); - elem_type w3i = sprout::sin(theta * 3 * irev); - for (difference_type k = mq; k >= 1; k >>= 2) { - for (difference_type j = i + mq - k; j < i + mq - (k >> 1); ++j) { - difference_type j1 = j + mq; - difference_type j2 = j1 + mq; - difference_type j3 = j2 + mq; - value_type x1 = first[j] - first[j1]; - first[j] += first[j1]; - value_type x3 = first[j3] - first[j2]; - first[j2] += first[j3]; - elem_type x0r = real(x1) - imag(x3); - elem_type x0i = imag(x1) + real(x3); - first[j1] = value_type( - w1r * x0r - w1i * x0i, - w1r * x0i + w1i * x0r - ); - x0r = real(x1) + imag(x3); - x0i = imag(x1) - real(x3); - first[j3] = value_type( - w3r * x0r - w3i * x0i, - w3r * x0i + w3i * x0r - ); - } - } - } - } - // radix 2 butterflies - difference_type mq = size >> 1; - for (difference_type k = mq; k >= 1; k >>= 2) { - for (difference_type j = mq - k; j < mq - (k >> 1); ++j) { - difference_type j1 = mq + j; - value_type x0 = first[j] - first[j1]; - first[j] += first[j1]; - first[j1] = x0; - } - } - } -} // namespace sprout +#include +#include +#include #endif // #ifndef SPROUT_NUMERIC_FFT_FFT_HPP diff --git a/sprout/numeric/fft/fit/fft.hpp b/sprout/numeric/fft/fit/fft.hpp new file mode 100644 index 00000000..b1e0145f --- /dev/null +++ b/sprout/numeric/fft/fit/fft.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_FIT_FFT_HPP +#define SPROUT_NUMERIC_FFT_FIT_FFT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fit { + namespace detail { + template + inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm::type + fft_impl( + ForwardIterator const& first, ForwardIterator const& last, Result const& result, + typename sprout::container_traits::difference_type offset + ) + { + return sprout::sub_copy( + sprout::get_internal(sprout::fixed::fft(first, last, result)), + offset, + offset + sprout::fit_size(result, sprout::distance(first, last)) + ); + } + } // namespace detail + // + // fft + // + template + inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm::type + fft(ForwardIterator first, ForwardIterator last, Result const& result) { + return sprout::fit::detail::fft_impl(first, last, result, sprout::internal_begin_offset(result)); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + fft(ForwardIterator first, ForwardIterator last) { + return sprout::fit::fft(first, last, sprout::pit()); + } + } // namespace fit +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_FIT_FFT_HPP diff --git a/sprout/numeric/fft/fit/ifft.hpp b/sprout/numeric/fft/fit/ifft.hpp new file mode 100644 index 00000000..e1fc3258 --- /dev/null +++ b/sprout/numeric/fft/fit/ifft.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_FIT_IFFT_HPP +#define SPROUT_NUMERIC_FFT_FIT_IFFT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fit { + namespace detail { + template + inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm::type + ifft_impl( + ForwardIterator const& first, ForwardIterator const& last, Result const& result, + typename sprout::container_traits::difference_type offset + ) + { + return sprout::sub_copy( + sprout::get_internal(sprout::fixed::ifft(first, last, result)), + offset, + offset + sprout::fit_size(result, sprout::distance(first, last)) + ); + } + } // namespace detail + // + // ifft + // + template + inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm::type + ifft(ForwardIterator first, ForwardIterator last, Result const& result) { + return sprout::fit::detail::ifft_impl(first, last, result, sprout::internal_begin_offset(result)); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + ifft(ForwardIterator first, ForwardIterator last) { + return sprout::fit::ifft(first, last, sprout::pit()); + } + } // namespace fit +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_FIT_IFFT_HPP diff --git a/sprout/numeric/fft/fixed/fft.hpp b/sprout/numeric/fft/fixed/fft.hpp new file mode 100644 index 00000000..a8dde16a --- /dev/null +++ b/sprout/numeric/fft/fixed/fft.hpp @@ -0,0 +1,118 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_FIXED_FFT_HPP +#define SPROUT_NUMERIC_FFT_FIXED_FFT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fixed { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::complex + fft_element( + sprout::array, Size> const& arr, + std::size_t step, std::size_t i, std::size_t j, bool sub, + sprout::array, Size> const& coeffs + ) + { + return sub + ? arr[i * step + j] - coeffs[j * (Size / 2 / step)] * arr[i * step + j + Size / 2] + : arr[i * step + j] + coeffs[j * (Size / 2 / step)] * arr[i * step + j + Size / 2] + ; + } + + template + inline SPROUT_CONSTEXPR sprout::array, Size> + butterfly( + sprout::array, Size> const& arr, + std::size_t step, + sprout::array, Size> const& coeffs, + sprout::index_tuple + ) + { + return sprout::array, Size> { { + fft_element(arr, step, Indexes / (step * 2), Indexes%step, (Indexes&step) != 0, coeffs)... + } }; + } + + template + inline SPROUT_CONSTEXPR sprout::array, Size> + fft_loop( + sprout::array, Size> const& arr, + std::size_t step, + sprout::array, Size> const& coeffs + ) + { + return step == Size ? arr + : fft_loop(butterfly(arr, step, coeffs, sprout::make_index_tuple()), step * 2, coeffs); + } + + template + inline SPROUT_CONSTEXPR sprout::array, Size> + fft(sprout::array, Size> const& arr) { + return fft_loop(arr, 1, sprout::make_fft_coefficients()); + } + + + template + inline SPROUT_CONSTEXPR sprout::array::value_type, sizeof...(Indexes)> + make_input_impl(Container const& cont, sprout::index_tuple) { + return sprout::array::value_type, sizeof...(Indexes)> { { + (sprout::math::less(Indexes, cont.size()) + ? *sprout::next(sprout::begin(cont), Indexes) + : static_cast::value_type>(0) + )... + } }; + } + template + inline SPROUT_CONSTEXPR sprout::array::value_type, Size> + make_input(Container const& cont) { + return make_input_impl(cont, sprout::make_index_tuple()); + } + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + make_fft_result_impl(sprout::array, Size> const& cont, Result const& result, sprout::index_tuple) { + return remake(result, sprout::size(result), cont[Indexes]...); + } + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + make_fft_result(sprout::array, Size> const& cont, Result const& result) { + return make_fft_result_impl(cont, result, sprout::make_index_tuple::static_size>()); + } + } // namespace detail + // + // fft + // Algorithm: Stockham decimation-in-time + // + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + fft(Container const& cont, Result const& result) { + return sprout::fixed::detail::make_fft_result( + sprout::fixed::detail::fft(sprout::fixed::detail::make_input::static_size>(cont)), result + ); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + fft(Container const& cont) { + return sprout::fixed::fft(cont, sprout::pit()); + } + } // namespace fixed + + using sprout::fixed::fft; +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_FIXED_FFT_HPP diff --git a/sprout/numeric/fft/fixed/ifft.hpp b/sprout/numeric/fft/fixed/ifft.hpp new file mode 100644 index 00000000..698d3dbf --- /dev/null +++ b/sprout/numeric/fft/fixed/ifft.hpp @@ -0,0 +1,65 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NUMERIC_FFT_FIXED_IFFT_HPP +#define SPROUT_NUMERIC_FFT_FIXED_IFFT_HPP + +#include +#include +#include +#include +#include +#include + + +namespace sprout { + namespace fixed { + namespace detail { + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + make_ifft_result_impl(sprout::array, Size> const& container, Result const& result, sprout::index_tuple) { + return remake(result, sprout::size(result), (container[Indexes] / static_cast(Size))...); + } + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + make_ifft_result(sprout::array, Size> const& container, Result const& result) { + return make_ifft_result_impl(container, result, sprout::make_index_tuple::static_size>()); + } + + template + inline SPROUT_CONSTEXPR sprout::array, Size> + ifft(sprout::array, Size> const& arr) { + return sprout::fixed::detail::fft_loop(arr, 1, sprout::make_ifft_coefficients()); + } + } // namespace detail + // + // ifft + // Algorithm: Stockham decimation-in-time + // + template< + typename ForwardIterator, typename Result, + typename sprout::container_traits::size_type Size + = sprout::container_traits::static_size + > + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + ifft(ForwardIterator first, ForwardIterator last, Result const& result) { + return sprout::fixed::detail::make_ifft_result( + sprout::fixed::detail::ifft(sprout::fixed::detail::make_input(first, last)), result + ); + } + + template + inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm::type + ifft(ForwardIterator first, ForwardIterator last) { + return sprout::fixed::ifft(first, last, sprout::pit()); + } + } // namespace fixed + + using sprout::fixed::ifft; +} // namespace sprout + +#endif // #ifndef SPROUT_NUMERIC_FFT_FIXED_IFFT_HPP diff --git a/sprout/numeric/fft/ifft.hpp b/sprout/numeric/fft/ifft.hpp index 335fc765..24e88ef3 100644 --- a/sprout/numeric/fft/ifft.hpp +++ b/sprout/numeric/fft/ifft.hpp @@ -8,51 +8,9 @@ #ifndef SPROUT_NUMERIC_FFT_IFFT_HPP #define SPROUT_NUMERIC_FFT_IFFT_HPP -#include #include -#include -#include -#include - -namespace sprout { - namespace detail { - struct conj_value { - public: - template - SPROUT_CONSTEXPR Complex operator()(Complex const& x) const { - return conj(x); - } - }; - - template - struct conj_div_value { - private: - Size n_; - public: - explicit SPROUT_CONSTEXPR conj_div_value(Size n) - : n_(n) - {} - template - SPROUT_CONSTEXPR Complex operator()(Complex const& x) const { - return conj(x) / typename Complex::value_type(n_); - } - }; - template - SPROUT_CONSTEXPR sprout::detail::conj_div_value - conj_div(Size n) { - return sprout::detail::conj_div_value(n); - } - } // namespace detail - // - // ifft - // - template - inline SPROUT_CXX14_CONSTEXPR void - ifft(RandomAccessIterator first, RandomAccessIterator last) { - sprout::transform(first, last, first, sprout::detail::conj_value()); - sprout::fft(first, last); - sprout::transform(first, last, first, sprout::detail::conj_div(last - first)); - } -} // namespace sprout +#include +#include +#include #endif // #ifndef SPROUT_NUMERIC_FFT_IFFT_HPP