Sprout/sprout/numeric/fft/fixed/fft.hpp
2017-07-26 15:22:14 +09:00

118 lines
5.1 KiB
C++

/*=============================================================================
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 <sprout/config.hpp>
#include <sprout/array.hpp>
#include <sprout/index_tuple/make_index_tuple.hpp>
#include <sprout/algorithm/fixed/results.hpp>
#include <sprout/complex.hpp>
#include <sprout/math/less.hpp>
#include <sprout/pit/pit.hpp>
#include <sprout/numeric/fft/coefficients.hpp>
namespace sprout {
namespace fixed {
namespace detail {
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::complex<value_type>
fft_element(
sprout::array<sprout::complex<value_type>, Size> const& arr,
std::size_t step, std::size_t i, std::size_t j, bool sub,
sprout::array<sprout::complex<value_type>, 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<typename value_type, std::size_t Size, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
butterfly(
sprout::array<sprout::complex<value_type>, Size> const& arr,
std::size_t step,
sprout::array<sprout::complex<value_type>, Size> const& coeffs,
sprout::index_tuple<Indexes...>
)
{
return sprout::array<sprout::complex<value_type>, Size> { {
fft_element(arr, step, Indexes / (step * 2), Indexes%step, (Indexes&step) != 0, coeffs)...
} };
}
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
fft_loop(
sprout::array<sprout::complex<value_type>, Size> const& arr,
std::size_t step,
sprout::array<sprout::complex<value_type>, Size> const& coeffs
)
{
return step == Size ? arr
: fft_loop(butterfly(arr, step, coeffs, sprout::make_index_tuple<Size>()), step * 2, coeffs);
}
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
fft(sprout::array<sprout::complex<value_type>, Size> const& arr) {
return fft_loop(arr, 1, sprout::make_fft_coefficients<value_type, Size>());
}
template<typename Container, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR sprout::array<typename sprout::container_traits<Container>::value_type, sizeof...(Indexes)>
make_input_impl(Container const& cont, sprout::index_tuple<Indexes...>) {
return sprout::array<typename sprout::container_traits<Container>::value_type, sizeof...(Indexes)> { {
(sprout::math::less(Indexes, cont.size())
? *sprout::next(sprout::begin(cont), Indexes)
: static_cast<typename sprout::container_traits<Container>::value_type>(0)
)...
} };
}
template<std::size_t Size, typename Container>
inline SPROUT_CONSTEXPR sprout::array<typename sprout::container_traits<Container>::value_type, Size>
make_input(Container const& cont) {
return make_input_impl(cont, sprout::make_index_tuple<Size>());
}
template<typename value_type, std::size_t Size, typename Result, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
make_fft_result_impl(sprout::array<sprout::complex<value_type>, Size> const& cont, Result const& result, sprout::index_tuple<Indexes...>) {
return remake<Result>(result, sprout::size(result), cont[Indexes]...);
}
template<typename value_type, std::size_t Size, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
make_fft_result(sprout::array<sprout::complex<value_type>, Size> const& cont, Result const& result) {
return make_fft_result_impl(cont, result, sprout::make_index_tuple<sprout::container_traits<Result>::static_size>());
}
} // namespace detail
//
// fft
// Algorithm: Stockham decimation-in-time
//
template<typename Container, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
fft(Container const& cont, Result const& result) {
return sprout::fixed::detail::make_fft_result(
sprout::fixed::detail::fft(sprout::fixed::detail::make_input<sprout::container_traits<Result>::static_size>(cont)), result
);
}
template<typename Result, typename Container>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
fft(Container const& cont) {
return sprout::fixed::fft(cont, sprout::pit<Result>());
}
} // namespace fixed
using sprout::fixed::fft;
} // namespace sprout
#endif // #ifndef SPROUT_NUMERIC_FFT_FIXED_FFT_HPP