fft.hpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #ifndef SIMPLE_COMPRESS_FFT_HPP
  2. #define SIMPLE_COMPRESS_FFT_HPP
  3. #include <iterator> // std::begin std::end
  4. #include <cassert> // assert
  5. #include <cstddef> // std::size_t
  6. #include "simple/support/algorithm/utils.hpp" // support::distance
  7. #include "simple/support/algorithm/numeric.hpp" // support::midpoint
  8. #include "simple/support/range.hpp" // support::range
  9. namespace simple::compress
  10. {
  11. template <typename I, typename O, typename Rotate, typename RotationStep>
  12. constexpr void fft(Rotate rotate, RotationStep r_step, I in, std::size_t in_step, O&& out)
  13. {
  14. using std::begin; using std::end;
  15. assert(support::distance(out) != 0);
  16. if(support::distance(out) == 1)
  17. {
  18. *begin(out) = *in;
  19. return;
  20. }
  21. auto even_out = support::range{begin(out), support::midpoint(out)};
  22. auto odd_out = support::range{support::midpoint(out), end(out)};
  23. fft(rotate, rotate(r_step, r_step), in, in_step*2, even_out);
  24. fft(rotate, rotate(r_step, r_step), in + in_step, in_step*2, odd_out);
  25. auto even = begin(even_out);
  26. auto odd = begin(odd_out);
  27. // NOTE: do first step of the loop manually so that we don't need to initialize identity, don't have powerful enough type system for that yet
  28. {
  29. auto odd_ = *odd;
  30. *odd = *even - odd_;
  31. *even = *even + odd_;
  32. ++even; ++odd;
  33. }
  34. for(auto r = r_step; even != end(even_out); ++even, ++odd, r = rotate(r, r_step))
  35. {
  36. auto odd_ = rotate(*odd, r);
  37. *odd = *even - odd_;
  38. *even = *even + odd_;
  39. }
  40. }
  41. template <typename I, typename O, typename Rotate, typename RotationStep>
  42. constexpr void fft(Rotate rotate, RotationStep step, const I& in, O&& out)
  43. {
  44. using std::begin;
  45. // TODO
  46. // assert distance(in) = distance(out) and is power of 2
  47. // assert rstep is tau / distance(in) ??
  48. fft(rotate, step, begin(in), 1, out);
  49. }
  50. } // namespace simple::compress
  51. #endif /* end of include guard */