12 #include "alnumeric.h"
13 #include "math_defs.h"
16 void complex_fft(const al::span
<std::complex<double>> buffer
, const double sign
)
18 const size_t fftsize
{buffer
.size()};
19 /* Get the number of bits used for indexing. Simplifies bit-reversal and
20 * the main loop count.
22 const size_t log2_size
{static_cast<size_t>(al::countr_zero(fftsize
))};
24 /* Bit-reversal permutation applied to a sequence of fftsize items. */
25 for(size_t idx
{1u};idx
< fftsize
-1;++idx
)
27 size_t revidx
{0u}, imask
{idx
};
28 for(size_t i
{0};i
< log2_size
;++i
)
30 revidx
= (revidx
<<1) | (imask
&1);
35 std::swap(buffer
[idx
], buffer
[revidx
]);
38 /* Iterative form of Danielson-Lanczos lemma */
40 for(size_t i
{0};i
< log2_size
;++i
)
42 const double arg
{al::MathDefs
<double>::Pi() / static_cast<double>(step2
)};
44 const std::complex<double> w
{std::cos(arg
), std::sin(arg
)*sign
};
45 std::complex<double> u
{1.0, 0.0};
46 const size_t step
{step2
<< 1};
47 for(size_t j
{0};j
< step2
;j
++)
49 for(size_t k
{j
};k
< fftsize
;k
+=step
)
51 std::complex<double> temp
{buffer
[k
+step2
] * u
};
52 buffer
[k
+step2
] = buffer
[k
] - temp
;
63 void complex_hilbert(const al::span
<std::complex<double>> buffer
)
67 const double inverse_size
= 1.0/static_cast<double>(buffer
.size());
68 auto bufiter
= buffer
.begin();
69 const auto halfiter
= bufiter
+ (buffer
.size()>>1);
71 *bufiter
*= inverse_size
; ++bufiter
;
72 bufiter
= std::transform(bufiter
, halfiter
, bufiter
,
73 [inverse_size
](const std::complex<double> &c
) -> std::complex<double>
74 { return c
* (2.0*inverse_size
); });
75 *bufiter
*= inverse_size
; ++bufiter
;
77 std::fill(bufiter
, buffer
.end(), std::complex<double>{});