17 constexpr std::complex< T >
imag = std::complex< T >{0, 1};
22 std::array< std::vector< std::complex< T > >, 16 > table;
25 for ( decltype( table.size() ) size_exp = 0; size_exp < table.size(); ++size_exp )
27 table[ size_exp ].resize( size );
28 for ( decltype( table[ size_exp ].size() ) k = 0; k < table[ size_exp ].size(); ++k )
30 table[ size_exp ][ k ] =
31 std::exp( minus_two_pi< T > * imag< T > * ( T( k ) / size ) );
42 static auto table = create_table< T >();
46 template <
class T,
class Size >
52 return gauss_table< T >()[ 0 ][ k ];
54 return gauss_table< T >()[ 1 ][ k ];
56 return gauss_table< T >()[ 2 ][ k ];
58 return gauss_table< T >()[ 3 ][ k ];
60 return gauss_table< T >()[ 4 ][ k ];
62 return gauss_table< T >()[ 5 ][ k ];
64 return gauss_table< T >()[ 6 ][ k ];
66 return gauss_table< T >()[ 7 ][ k ];
68 return gauss_table< T >()[ 8 ][ k ];
70 return gauss_table< T >()[ 9 ][ k ];
72 return gauss_table< T >()[ 10 ][ k ];
74 return gauss_table< T >()[ 11 ][ k ];
76 return gauss_table< T >()[ 12 ][ k ];
78 return gauss_table< T >()[ 13 ][ k ];
80 return gauss_table< T >()[ 14 ][ k ];
82 return gauss_table< T >()[ 15 ][ k ];
85 return std::exp( minus_two_pi< T > * imag< T > * ( T( k ) / size ) );
88 template <
class Container >
93 return std::vector{x[ 0 ]};
100 for (
typename Container::size_type k = 0; k < x.size() / 2; ++k )
102 using value_type =
typename Container::value_type::value_type;
103 const auto dy = compute_gauss< value_type >( k, x.size() ) * z[ k ];
104 y[ x.size() / 2 + k ] = y[ k ] - dy;
111 template <
class Container,
class Result >
112 void radix2(
const Container& x, Result& result )
116 result[ 0 ] = x[ 0 ];
125 for (
typename Container::size_type k = 0; k < x.size() / 2; ++k )
127 using value_type =
typename Container::value_type::value_type;
129 compute_gauss< value_type >( k, x.size() ) * result[ result.size() / 2 + k ];
130 result[ x.size() / 2 + k ] = result[ k ] - dy;
135 template <
class Container >
140 return std::vector{x[ 0 ]};
151 y.resize( x.size() );
152 using value_type =
typename Container::value_type::value_type;
153 const auto scale = value_type( 1.0 ) / y.size();
154 for (
typename Container::size_type k = 0; k < x.size() / 2; ++k )
156 using value_type =
typename Container::value_type::value_type;
157 const auto dy = compute_gauss< value_type >( k, x.size() ) * z[ k ];
158 y[ x.size() / 2 + k ] = scale * conj( y[ k ] - dy );
160 y[ k ] = scale * conj( y[ k ] );
166 template <
class T, std::enable_if_t< !is_complex_v< T > >* =
nullptr >
167 std::vector< std::complex< T > >
fft(
const std::vector< T >& x )
169 using size_type =
typename std::vector< std::complex< T > >::size_type;
172 const auto half_result =
174 radix2(
reinterpret_cast< const std::vector< std::complex< T >
>& >( x ) );
176 std::vector< std::complex< T > > result( half_result.size() );
177 for ( size_type k = 0; k < result.size(); ++k )
179 const auto s_k = ( k == 0 ) ? 0 : result.size() - k;
180 const auto z = conj( half_result[ s_k ] );
182 T( 0.5 ) * ( ( half_result[ k ] + z ) - imag< T > * ( half_result[ k ] - z ) *
183 compute_gauss< T >( k, x.size() ) );
189 template <
class T, std::enable_if_t< !is_complex_v< T > >* =
nullptr >
190 std::pair< std::vector< std::complex< T > >, std::vector< std::complex< T > > >
191 fft(
const std::vector< T >& x,
const std::vector< T >& y )
193 using size_type =
typename std::vector< std::complex< T > >::size_type;
197 std::vector< std::complex< T > > z( x.size() );
198 for ( size_type i = 0; i < x.size(); ++i )
200 z[ i ] = std::complex{x[ i ], y[ i ]};
202 const auto result =
radix2( z );
203 std::vector< std::complex< T > > x_result( result.size() / 2 );
204 std::vector< std::complex< T > > y_result( result.size() / 2 );
205 for ( size_type k = 0; k < x_result.size(); ++k )
207 auto z = conj( result[ x.size() - k ] );
208 x_result[ k ] = ( result[ k ] + z ) / 2.f;
209 y_result[ k ] = -imag< T > * ( result[ k ] - z ) / 2.f;
212 return std::make_pair( x_result, y_result );
215 template <
class T, std::enable_if_t< !is_complex_v< T > >* =
nullptr >
216 void fft(
const std::vector< T >& x, std::vector< std::complex< T > >& result )
218 using size_type =
typename std::vector< std::complex< T > >::size_type;
221 std::vector< std::complex< T > > half_result( x.size() / 2 );
223 radix2(
reinterpret_cast< const std::vector< std::complex< T >
>& >( x ), half_result );
225 for ( size_type k = 0; k < result.size(); ++k )
227 const auto s_k = ( k == 0 ) ? 0 : result.size() - k;
228 const auto z = conj( half_result[ s_k ] );
230 T( 0.5 ) * ( ( half_result[ k ] + z ) - imag< T > * ( half_result[ k ] - z ) *
231 compute_gauss< T >( k, x.size() ) );
235 template <
class T, std::enable_if_t< !is_complex_v< T > >* =
nullptr >
238 using size_type =
typename std::vector< std::complex< T > >::size_type;
241 const auto half_result =
243 radix2(
reinterpret_cast< const std::vector< std::complex< T >
>& >( x ) );
245 std::vector< T > result( half_result.size() );
246 const auto scale = T( 0.5 ) / result.size();
247 for ( size_type k = 0; k < result.size(); ++k )
249 const auto s_k = ( k == 0 ) ? 0 : result.size() - k;
250 const auto z = conj( half_result[ s_k ] );
252 scale * abs( ( half_result[ k ] + z ) - imag< T > * ( half_result[ k ] - z ) *
253 compute_gauss< T >( k, x.size() ) );
259 template <
class T, std::enable_if_t< !is_complex_v< T > >* =
nullptr >
260 std::vector< T >
inverse_fft(
const std::vector< std::complex< T > >& x )
262 using size_type =
typename std::vector< std::complex< T > >::size_type;
265 std::vector< std::complex< T > > y( x.size() );
266 for ( size_type k = 0; k < y.size(); ++k )
268 const auto s_k = ( k == 0 ) ? 0 : y.size() - k;
269 const auto z = conj( x[ s_k ] );
271 T( 0.5 ) * conj( ( x[ k ] + z ) - imag< T > * ( x[ k ] - z ) /
272 compute_gauss< T >( k, 2 * x.size() ) );
276 std::vector< T > result( 2 * complex_result.size() );
277 std::memcpy( result.data(), complex_result.data(), result.size() *
sizeof( T ) );
std::vector< std::complex< T > > fft(const std::vector< T > &x)
Definition: fft.hpp:167
size_type size() const noexcept
Definition: vector_view.hpp:32
#define SEQUENCER_ASSERT(cond)
Definition: assert.hpp:8
Definition: vector_view.hpp:85
std::vector< T > fft_abs_scaled(const std::vector< T > &x)
Definition: fft.hpp:236
auto create_table()
Definition: fft.hpp:20
std::complex< T > compute_gauss(Size k, Size size)
Definition: fft.hpp:47
constexpr std::complex< T > imag
Definition: fft.hpp:17
auto inverse_radix2(Container x)
Definition: fft.hpp:136
auto & gauss_table()
Definition: fft.hpp:40
Definition: vector_view.hpp:62
std::vector< T > inverse_fft(const std::vector< std::complex< T > > &x)
Definition: fft.hpp:260
auto radix2(const Container &x)
Definition: fft.hpp:89