/*============================================================================= 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