alcomplex.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include "config.h"
  2. #include "alcomplex.h"
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <cstddef>
  6. #include <utility>
  7. #include "albit.h"
  8. #include "alnumeric.h"
  9. #include "math_defs.h"
  10. void complex_fft(const al::span<std::complex<double>> buffer, const double sign)
  11. {
  12. const size_t fftsize{buffer.size()};
  13. /* Get the number of bits used for indexing. Simplifies bit-reversal and
  14. * the main loop count.
  15. */
  16. const size_t log2_size{static_cast<size_t>(al::countr_zero(fftsize))};
  17. /* Bit-reversal permutation applied to a sequence of fftsize items. */
  18. for(size_t idx{1u};idx < fftsize-1;++idx)
  19. {
  20. size_t revidx{0u}, imask{idx};
  21. for(size_t i{0};i < log2_size;++i)
  22. {
  23. revidx = (revidx<<1) | (imask&1);
  24. imask >>= 1;
  25. }
  26. if(idx < revidx)
  27. std::swap(buffer[idx], buffer[revidx]);
  28. }
  29. /* Iterative form of Danielson-Lanczos lemma */
  30. size_t step2{1u};
  31. for(size_t i{0};i < log2_size;++i)
  32. {
  33. const double arg{al::MathDefs<double>::Pi() / static_cast<double>(step2)};
  34. const std::complex<double> w{std::cos(arg), std::sin(arg)*sign};
  35. std::complex<double> u{1.0, 0.0};
  36. const size_t step{step2 << 1};
  37. for(size_t j{0};j < step2;j++)
  38. {
  39. for(size_t k{j};k < fftsize;k+=step)
  40. {
  41. std::complex<double> temp{buffer[k+step2] * u};
  42. buffer[k+step2] = buffer[k] - temp;
  43. buffer[k] += temp;
  44. }
  45. u *= w;
  46. }
  47. step2 <<= 1;
  48. }
  49. }
  50. void complex_hilbert(const al::span<std::complex<double>> buffer)
  51. {
  52. inverse_fft(buffer);
  53. const double inverse_size = 1.0/static_cast<double>(buffer.size());
  54. auto bufiter = buffer.begin();
  55. const auto halfiter = bufiter + (buffer.size()>>1);
  56. *bufiter *= inverse_size; ++bufiter;
  57. bufiter = std::transform(bufiter, halfiter, bufiter,
  58. [inverse_size](const std::complex<double> &c) -> std::complex<double>
  59. { return c * (2.0*inverse_size); });
  60. *bufiter *= inverse_size; ++bufiter;
  61. std::fill(bufiter, buffer.end(), std::complex<double>{});
  62. forward_fft(buffer);
  63. }