add C++11constexpr fft

Stockham DIT fft algorithm written in C++11constexpr
This commit is contained in:
lpha-z 2016-09-12 18:13:01 +09:00
parent f08464943f
commit e6af368c77
9 changed files with 575 additions and 169 deletions

View file

@ -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 <sprout/config.hpp>
#include <sprout/array.hpp>
#include <sprout/bit/bit_length.hpp>
#include <sprout/index_tuple/make_index_tuple.hpp>
#include <sprout/complex.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/constants.hpp>
namespace sprout {
namespace detail
{
template<typename value_type, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, sizeof...(Indexes)*2>
make_fft_coefficients_impl(
sprout::array<sprout::complex<value_type>, sizeof...(Indexes)> const& arr,
sprout::complex<value_type> mul, sprout::index_tuple<Indexes...>
)
{
return sprout::array<sprout::complex<value_type>, sizeof...(Indexes)*2>{ {
arr[Indexes]..., (arr[Indexes] * mul)...
} };
}
template<typename value_type, std::size_t N, std::size_t Size>
inline SPROUT_CONSTEXPR typename std::enable_if<
N == 0,
typename sprout::array<sprout::complex<value_type>, 1>
>::type
make_fft_coefficients_loop( bool ) {
return typename sprout::array<sprout::complex<value_type>, 1>{ {
{ static_cast<value_type>( 1 ) }
} };
}
template<typename value_type, std::size_t N, std::size_t Size>
inline SPROUT_CONSTEXPR typename std::enable_if<
N != 0,
typename sprout::array<sprout::complex<value_type>, 1 << N>
>::type
make_fft_coefficients_loop(bool inverse)
{
return make_fft_coefficients_impl(
make_fft_coefficients_loop<value_type, N - 1, Size>(inverse),
{
sprout::cos((inverse?-1:1)*sprout::math::two_pi<value_type>() / (1 << Size >> (N - 1))),
sprout::sin((inverse?-1:1)*sprout::math::two_pi<value_type>() / (1 << Size >> (N - 1)))
},
sprout::make_index_tuple<1 << (N - 1)>()
);
}
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, 1 << Size>
make_fft_coefficients(bool inverse) {
return make_fft_coefficients_loop<value_type, Size, Size>(inverse);
}
} // namespace detail
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
make_fft_coefficients() {
return sprout::detail::make_fft_coefficients<value_type, sprout::bit_length(Size)-1>(false);
}
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
make_ifft_coefficients() {
return sprout::detail::make_fft_coefficients<value_type, sprout::bit_length(Size)-1>(true);
}
} // namespce sprout
#endif // SPROUT_NUMERIC_FFT_COEFFICIENT_ARRAY_HPP

View file

@ -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 <iterator>
#include <sprout/config.hpp>
#include <sprout/complex.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/utility/swap.hpp>
namespace sprout {
//
// fft
//
template<typename RandomAccessIterator>
inline SPROUT_CXX14_CONSTEXPR void
fft(RandomAccessIterator first, RandomAccessIterator last) {
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_type;
typedef typename std::iterator_traits<RandomAccessIterator>::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<elem_type>() / 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

View file

@ -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 <iterator>
#include <sprout/config.hpp>
#include <sprout/complex.hpp>
#include <sprout/algorithm/cxx14/transform.hpp>
#include <sprout/numeric/fft/cxx14/fft.hpp>
namespace sprout {
namespace detail {
struct conj_value {
public:
template<typename Complex>
SPROUT_CONSTEXPR Complex operator()(Complex const& x) const {
return conj(x);
}
};
template<typename Size>
struct conj_div_value {
private:
Size n_;
public:
explicit SPROUT_CONSTEXPR conj_div_value(Size n)
: n_(n)
{}
template<typename Complex>
SPROUT_CONSTEXPR Complex operator()(Complex const& x) const {
return conj(x) / typename Complex::value_type(n_);
}
};
template<typename Size>
SPROUT_CONSTEXPR sprout::detail::conj_div_value<Size>
conj_div(Size n) {
return sprout::detail::conj_div_value<Size>(n);
}
} // namespace detail
//
// ifft
//
template<typename RandomAccessIterator>
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

View file

@ -8,130 +8,9 @@
#ifndef SPROUT_NUMERIC_FFT_FFT_HPP
#define SPROUT_NUMERIC_FFT_FFT_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/complex.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/utility/swap.hpp>
namespace sprout {
//
// fft
//
template<typename RandomAccessIterator>
inline SPROUT_CXX14_CONSTEXPR void
fft(RandomAccessIterator first, RandomAccessIterator last) {
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_type;
typedef typename std::iterator_traits<RandomAccessIterator>::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<elem_type>() / 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 <sprout/numeric/fft/fixed/fft.hpp>
#include <sprout/numeric/fft/fit/fft.hpp>
#include <sprout/numeric/fft/cxx14/fft.hpp>
#endif // #ifndef SPROUT_NUMERIC_FFT_FFT_HPP

View file

@ -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 <sprout/config.hpp>
#include <sprout/iterator/distance.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/numeric/fft/fixed/fft.hpp>
#include <sprout/algorithm/fit/results.hpp>
#include <sprout/sub_array/sub_array.hpp>
#include <sprout/sub_array/sub.hpp>
#include <sprout/pit/pit.hpp>
namespace sprout {
namespace fit {
namespace detail {
template<typename ForwardIterator, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm<Result>::type
fft_impl(
ForwardIterator const& first, ForwardIterator const& last, Result const& result,
typename sprout::container_traits<Result>::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<typename ForwardIterator, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm<Result>::type
fft(ForwardIterator first, ForwardIterator last, Result const& result) {
return sprout::fit::detail::fft_impl(first, last, result, sprout::internal_begin_offset(result));
}
template<typename Result, typename ForwardIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
fft(ForwardIterator first, ForwardIterator last) {
return sprout::fit::fft(first, last, sprout::pit<Result>());
}
} // namespace fit
} // namespace sprout
#endif // #ifndef SPROUT_NUMERIC_FFT_FIT_FFT_HPP

View file

@ -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 <sprout/config.hpp>
#include <sprout/iterator/distance.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/numeric/fft/fixed/ifft.hpp>
#include <sprout/algorithm/fit/results.hpp>
#include <sprout/sub_array/sub_array.hpp>
#include <sprout/sub_array/sub.hpp>
#include <sprout/pit/pit.hpp>
namespace sprout {
namespace fit {
namespace detail {
template<typename ForwardIterator, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm<Result>::type
ifft_impl(
ForwardIterator const& first, ForwardIterator const& last, Result const& result,
typename sprout::container_traits<Result>::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<typename ForwardIterator, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fit::results::algorithm<Result>::type
ifft(ForwardIterator first, ForwardIterator last, Result const& result) {
return sprout::fit::detail::ifft_impl(first, last, result, sprout::internal_begin_offset(result));
}
template<typename Result, typename ForwardIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
ifft(ForwardIterator first, ForwardIterator last) {
return sprout::fit::ifft(first, last, sprout::pit<Result>());
}
} // namespace fit
} // namespace sprout
#endif // #ifndef SPROUT_NUMERIC_FFT_FIT_IFFT_HPP

View file

@ -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 <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

View file

@ -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 <sprout/config.hpp>
#include <sprout/array.hpp>
#include <sprout/algorithm/fixed/results.hpp>
#include <sprout/complex.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, typename Result, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
make_ifft_result_impl(sprout::array<sprout::complex<value_type>, Size> const& container, Result const& result, sprout::index_tuple<Indexes...>) {
return remake<Result>(result, sprout::size(result), (container[Indexes] / static_cast<value_type>(Size))...);
}
template<typename value_type, std::size_t Size, typename Result>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
make_ifft_result(sprout::array<sprout::complex<value_type>, Size> const& container, Result const& result) {
return make_ifft_result_impl(container, result, sprout::make_index_tuple<sprout::container_traits<Result>::static_size>());
}
template<typename value_type, std::size_t Size>
inline SPROUT_CONSTEXPR sprout::array<sprout::complex<value_type>, Size>
ifft(sprout::array<sprout::complex<value_type>, Size> const& arr) {
return sprout::fixed::detail::fft_loop(arr, 1, sprout::make_ifft_coefficients<value_type, Size>());
}
} // namespace detail
//
// ifft
// Algorithm: Stockham decimation-in-time
//
template<
typename ForwardIterator, typename Result,
typename sprout::container_traits<Result>::size_type Size
= sprout::container_traits<Result>::static_size
>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::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<Size>(first, last)), result
);
}
template<typename Result, typename ForwardIterator>
inline SPROUT_CONSTEXPR typename sprout::fixed::results::algorithm<Result>::type
ifft(ForwardIterator first, ForwardIterator last) {
return sprout::fixed::ifft(first, last, sprout::pit<Result>());
}
} // namespace fixed
using sprout::fixed::ifft;
} // namespace sprout
#endif // #ifndef SPROUT_NUMERIC_FFT_FIXED_IFFT_HPP

View file

@ -8,51 +8,9 @@
#ifndef SPROUT_NUMERIC_FFT_IFFT_HPP
#define SPROUT_NUMERIC_FFT_IFFT_HPP
#include <iterator>
#include <sprout/config.hpp>
#include <sprout/complex.hpp>
#include <sprout/algorithm/cxx14/transform.hpp>
#include <sprout/numeric/fft/fft.hpp>
namespace sprout {
namespace detail {
struct conj_value {
public:
template<typename Complex>
SPROUT_CONSTEXPR Complex operator()(Complex const& x) const {
return conj(x);
}
};
template<typename Size>
struct conj_div_value {
private:
Size n_;
public:
explicit SPROUT_CONSTEXPR conj_div_value(Size n)
: n_(n)
{}
template<typename Complex>
SPROUT_CONSTEXPR Complex operator()(Complex const& x) const {
return conj(x) / typename Complex::value_type(n_);
}
};
template<typename Size>
SPROUT_CONSTEXPR sprout::detail::conj_div_value<Size>
conj_div(Size n) {
return sprout::detail::conj_div_value<Size>(n);
}
} // namespace detail
//
// ifft
//
template<typename RandomAccessIterator>
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 <sprout/numeric/fft/fixed/ifft.hpp>
#include <sprout/numeric/fft/fit/ifft.hpp>
#include <sprout/numeric/fft/cxx14/ifft.hpp>
#endif // #ifndef SPROUT_NUMERIC_FFT_IFFT_HPP