fft.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include "simple/compress/fft.hpp"
  2. #include "simple/support/random.hpp"
  3. #include <cassert>
  4. #include <vector>
  5. #include <cmath>
  6. #include <algorithm>
  7. #include <numeric>
  8. #include <complex>
  9. #include <random>
  10. #include <iostream>
  11. #include <iomanip>
  12. using namespace simple::compress;
  13. const float tau = 2*std::acos(-1);
  14. template <typename Waveform>
  15. void DFT(std::size_t size, Waveform waveform)
  16. {
  17. std::vector<float> wave;
  18. wave.resize(size);
  19. std::iota(wave.begin(), wave.end(), 0);
  20. std::transform(wave.begin(), wave.end(), wave.begin(), [&](auto x) { return x/size; });
  21. std::transform(wave.begin(), wave.end(), wave.begin(), waveform);
  22. std::vector<std::complex<float>> control;
  23. control.resize(wave.size());
  24. for(std::size_t i = 0; i != wave.size(); ++i)
  25. {
  26. for(std::size_t j = 0; j != wave.size(); ++j)
  27. {
  28. control[i].real( control[i].real() + wave[j] * std::cos(tau*j*i/wave.size()) / control.size());
  29. control[i].imag( control[i].imag() + wave[j] * std::sin(tau*j*i/wave.size()) / control.size());
  30. }
  31. }
  32. std::vector<std::complex<float>> frequencies;
  33. frequencies.resize(wave.size());
  34. fft(std::multiplies<>{}, std::polar(1.f,tau/wave.size()), wave, frequencies);
  35. for(auto&& x : frequencies)
  36. x = std::conj(x) / float(frequencies.size());
  37. std::vector<std::complex<float>> aaanback;
  38. aaanback.resize(wave.size());
  39. fft(std::multiplies<>{}, std::polar(1.f,tau/wave.size()), frequencies, aaanback);
  40. for(std::size_t i = 0; i != aaanback.size(); ++i)
  41. {
  42. assert(std::abs(aaanback[i].real() - wave[i]) < 0.001);
  43. }
  44. for(std::size_t i = 0; i != frequencies.size(); ++i)
  45. {
  46. assert(std::abs(std::abs(frequencies[i]) - std::abs(control[i])) < 0.001);
  47. }
  48. #if defined SIMPLE_SUPPORT_DEBUG_HPP
  49. if(size <= 32)
  50. {
  51. std::cerr << std::fixed;
  52. std::cerr << std::setprecision(3);
  53. simple::support::print('\n');
  54. simple::support::print("IN : [ ");
  55. for(auto&& x : wave)
  56. simple::support::print(x, " ");
  57. simple::support::print("]\n");
  58. simple::support::print("DEC: [ ");
  59. for(auto&& x : aaanback)
  60. simple::support::print(x.real(), " ");
  61. simple::support::print("]\n");
  62. simple::support::print("ENC: [ ");
  63. for(auto&& x : frequencies)
  64. simple::support::print(std::abs(x), " ");
  65. simple::support::print("]\n");
  66. simple::support::print("CNR: [ ");
  67. for(auto&& x : control)
  68. simple::support::print(std::abs(x), " ");
  69. simple::support::print("]\n");
  70. }
  71. #endif
  72. }
  73. int main()
  74. {
  75. DFT(2, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  76. DFT(2, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  77. DFT(2, [&](auto x) { return std::sin(tau*x); });
  78. DFT(2, [&](auto x) { return std::cos(tau*x); });
  79. DFT(4, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  80. DFT(4, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  81. DFT(4, [&](auto x) { return std::sin(tau*x); });
  82. DFT(4, [&](auto x) { return std::cos(tau*x); });
  83. DFT(8, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  84. DFT(8, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  85. DFT(8, [&](auto x) { return std::sin(tau*x); });
  86. DFT(8, [&](auto x) { return std::cos(tau*x); });
  87. DFT(16, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  88. DFT(16, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  89. DFT(16, [&](auto x) { return std::sin(tau*x); });
  90. DFT(16, [&](auto x) { return std::cos(tau*x); });
  91. DFT(1024, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  92. DFT(1024, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  93. DFT(1024, [&](auto x) { return std::sin(tau*x); });
  94. DFT(1024, [&](auto x) { return std::cos(tau*x); });
  95. DFT(2048, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x*2); });
  96. DFT(2048, [&](auto x) { return std::sin(tau*x) + std::cos(tau*x); });
  97. DFT(2048, [&](auto x) { return std::sin(tau*x); });
  98. DFT(2048, [&](auto x) { return std::cos(tau*x); });
  99. DFT(2048, [&](auto x) { return std::sin(tau*13*x) + std::cos(tau*345*x); });
  100. DFT(2048, [&](auto x) { return std::sin(tau*134*x) + std::sin(tau*345*x) + std::cos(tau*789*x); });
  101. auto seed = std::random_device{}();
  102. std::cout << "DFT random test seed: " << std::hex << std::showbase << seed << std::dec << std::endl;
  103. simple::support::random::engine::tiny<unsigned long long> random{seed};
  104. std::uniform_real_distribution<double> number{};
  105. DFT(2048, [&](auto) { return number(random); });
  106. return 0;
  107. }