mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-12-23 21:25:49 +00:00
add C++11constexpr fft
Stockham DIT fft algorithm written in C++11constexpr
This commit is contained in:
parent
f08464943f
commit
e6af368c77
9 changed files with 575 additions and 169 deletions
81
sprout/numeric/fft/coefficients.hpp
Normal file
81
sprout/numeric/fft/coefficients.hpp
Normal 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
|
137
sprout/numeric/fft/cxx14/fft.hpp
Normal file
137
sprout/numeric/fft/cxx14/fft.hpp
Normal 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
|
58
sprout/numeric/fft/cxx14/ifft.hpp
Normal file
58
sprout/numeric/fft/cxx14/ifft.hpp
Normal 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
|
|
@ -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
|
||||
|
|
55
sprout/numeric/fft/fit/fft.hpp
Normal file
55
sprout/numeric/fft/fit/fft.hpp
Normal 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
|
55
sprout/numeric/fft/fit/ifft.hpp
Normal file
55
sprout/numeric/fft/fit/ifft.hpp
Normal 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
|
118
sprout/numeric/fft/fixed/fft.hpp
Normal file
118
sprout/numeric/fft/fixed/fft.hpp
Normal 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
|
65
sprout/numeric/fft/fixed/ifft.hpp
Normal file
65
sprout/numeric/fft/fixed/ifft.hpp
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue