Guest User

Untitled

a guest
Jan 16th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.86 KB | None | 0 0
  1. #include <complex>
  2. #include <fftw3.h>
  3. #include <github.com/apronchenkov/perfmon/public/perfmon.h>
  4. #include <iostream>
  5. #include <vector>
  6.  
  7. using Real = double;
  8. using Complex = std::complex<Real>;
  9. using FFTWComplex = fftw_complex;
  10. using FFTWPlan = fftw_plan;
  11. template <class... Args>
  12. auto FFTWSetTimelimit(Args&&... args)
  13. -> decltype(fftw_set_timelimit(std::forward<Args>(args)...)) {
  14. return fftw_set_timelimit(std::forward<Args>(args)...);
  15. }
  16. template <class... Args>
  17. auto FFTWPlanDFT1D(Args&&... args)
  18. -> decltype(fftw_plan_dft_1d(std::forward<Args>(args)...)) {
  19. return fftw_plan_dft_1d(std::forward<Args>(args)...);
  20. }
  21. template <class... Args>
  22. auto FFTWDestroyPlan(Args&&... args)
  23. -> decltype(fftw_destroy_plan(std::forward<Args>(args)...)) {
  24. return fftw_destroy_plan(std::forward<Args>(args)...);
  25. }
  26. template <class... Args>
  27. auto FFTWExecutePlan(Args&&... args)
  28. -> decltype(fftw_execute(std::forward<Args>(args)...)) {
  29. return fftw_execute(std::forward<Args>(args)...);
  30. }
  31. //*/
  32. /*
  33. using Real = float;
  34. using Complex = std::complex<Real>;
  35. using FFTWComplex = fftwf_complex;
  36. using FFTWPlan = fftwf_plan;
  37. template <class... Args>
  38. auto FFTWSetTimelimit(Args&&... args)
  39. -> decltype(fftw_set_timelimit(std::forward<Args>(args)...)) {
  40. return fftwf_set_timelimit(std::forward<Args>(args)...);
  41. }
  42. template <class... Args>
  43. auto FFTWPlanDFT1D(Args&&... args)
  44. -> decltype(fftwf_plan_dft_1d(std::forward<Args>(args)...)) {
  45. return fftwf_plan_dft_1d(std::forward<Args>(args)...);
  46. }
  47. template <class... Args>
  48. auto FFTWDestroyPlan(Args&&... args)
  49. -> decltype(fftwf_destroy_plan(std::forward<Args>(args)...)) {
  50. return fftwf_destroy_plan(std::forward<Args>(args)...);
  51. }
  52. template <class... Args>
  53. auto FFTWExecutePlan(Args&&... args)
  54. -> decltype(fftwf_execute(std::forward<Args>(args)...)) {
  55. return fftwf_execute(std::forward<Args>(args)...);
  56. }
  57. //*/
  58.  
  59. class FFTEng {
  60. public:
  61. FFTEng() = default;
  62.  
  63. explicit FFTEng(int n) : FFTEng(n, FFTW_ESTIMATE) {}
  64.  
  65. FFTEng(int n, unsigned int fftwFlag) {
  66. PERFMON_SCOPE("FFTEng.ctor");
  67. x_.resize(n);
  68. y_.resize(n);
  69. forward_ = FFTWPlanDFT1D(n, reinterpret_cast<FFTWComplex*>(x_.data()),
  70. reinterpret_cast<FFTWComplex*>(y_.data()),
  71. FFTW_FORWARD, fftwFlag);
  72. backward_ = FFTWPlanDFT1D(n, reinterpret_cast<FFTWComplex*>(y_.data()),
  73. reinterpret_cast<FFTWComplex*>(x_.data()),
  74. FFTW_BACKWARD, fftwFlag);
  75. if (!forward_ || !backward_) {
  76. if (forward_) {
  77. FFTWDestroyPlan(forward_);
  78. forward_ = nullptr;
  79. }
  80. if (backward_) {
  81. FFTWDestroyPlan(backward_);
  82. backward_ = nullptr;
  83. }
  84. throw std::runtime_error("fftw_plan_dft_1d: Failed.");
  85. }
  86. }
  87.  
  88. FFTEng(FFTEng&& rhs) : FFTEng() {
  89. std::swap(x_, rhs.x_);
  90. std::swap(y_, rhs.y_);
  91. std::swap(forward_, rhs.forward_);
  92. std::swap(backward_, rhs.backward_);
  93. }
  94.  
  95. FFTEng(const FFTEng& rhs) = delete;
  96.  
  97. FFTEng& operator=(FFTEng&& rhs) {
  98. std::swap(x_, rhs.x_);
  99. std::swap(y_, rhs.y_);
  100. std::swap(forward_, rhs.forward_);
  101. std::swap(backward_, rhs.backward_);
  102. return *this;
  103. }
  104.  
  105. FFTEng& operator=(const FFTEng& rhs) = delete;
  106.  
  107. ~FFTEng() {
  108. if (forward_) {
  109. FFTWDestroyPlan(forward_);
  110. forward_ = nullptr;
  111. }
  112. if (backward_) {
  113. FFTWDestroyPlan(backward_);
  114. backward_ = nullptr;
  115. }
  116. }
  117.  
  118. void Forward() {
  119. PERFMON_SCOPE("FFTEng.Forward");
  120. FFTWExecutePlan(forward_);
  121. }
  122.  
  123. void Backward() {
  124. PERFMON_SCOPE("FFTEng.Backward");
  125. FFTWExecutePlan(backward_);
  126. const Real scale = 1.0 / x_.size();
  127. for (auto& x : x_) {
  128. x *= scale;
  129. }
  130. }
  131.  
  132. int size() const { return x_.size(); }
  133.  
  134. Complex& X(size_t i) { return x_[i]; }
  135. const Complex& X(size_t i) const { return x_[i]; }
  136. auto XBegin() { return x_.begin(); }
  137. auto XBegin() const { return x_.begin(); }
  138. auto XEnd() { return x_.end(); }
  139. auto XEend() const { return x_.end(); }
  140.  
  141. Complex& Y(size_t i) { return y_[i]; }
  142. const Complex& Y(size_t i) const { return y_[i]; }
  143. auto YBegin() { return y_.begin(); }
  144. auto YBegin() const { return y_.begin(); }
  145. auto YEnd() { return y_.end(); }
  146. auto YEend() const { return y_.end(); }
  147.  
  148. private:
  149. std::vector<Complex> x_;
  150. std::vector<Complex> y_;
  151. FFTWPlan forward_{nullptr};
  152. FFTWPlan backward_{nullptr};
  153. };
  154.  
  155. std::vector<int> GenPrimes(int nmax) {
  156. std::vector<int> result;
  157. std::vector<bool> sieve(nmax, true);
  158. sieve[0] = false;
  159. sieve[1] = false;
  160. for (int i = 2; i <= nmax; ++i) {
  161. if (!sieve[i]) {
  162. continue;
  163. }
  164. result.push_back(i);
  165. for (int j = i + i; j <= nmax; j += i) {
  166. sieve[j] = false;
  167. }
  168. }
  169. return result;
  170. }
  171.  
  172. template <class Container>
  173. bool Any(const Container& input) {
  174. for (const auto& x : input) {
  175. if (x) {
  176. return true;
  177. }
  178. }
  179. return false;
  180. }
  181.  
  182. void PrintBits(const std::vector<bool>& input) {
  183. const size_t kMaxSize = 100;
  184. for (size_t i = 0; i < kMaxSize && i < input.size(); ++i) {
  185. std::cout << input[i];
  186. }
  187. if (input.size() > kMaxSize) {
  188. std::cout << "...";
  189. }
  190. }
  191.  
  192. int main() {
  193. const int kNMax = 200000;
  194. FFTWSetTimelimit(.1);
  195. FFTEng eng(407680);
  196.  
  197. std::fill(eng.XBegin(), eng.XEnd(), 0);
  198. const auto primes = GenPrimes(kNMax);
  199. for (size_t i = 0; i < primes.size() && primes[i] <= kNMax; ++i) {
  200. eng.X(primes[i]) = 1;
  201. for (size_t j = i; j < primes.size() && primes[j] <= kNMax / primes[i];
  202. ++j) {
  203. eng.X(primes[i] * primes[j]) = 1;
  204. }
  205. }
  206. eng.Forward();
  207. const std::vector<Complex> aY(eng.YBegin(), eng.YEnd());
  208.  
  209. std::vector<bool> candidates(kNMax, true);
  210. for (int n = 0; Any(candidates); ++n) {
  211. std::vector<bool> isUndefined = candidates;
  212. std::vector<bool> g(isUndefined.size());
  213. while (Any(isUndefined)) {
  214. std::fill(eng.XBegin(), eng.XEnd(), 0);
  215. for (size_t i = 0; i < isUndefined.size(); ++i) {
  216. eng.X(i) = Complex(isUndefined[i], g[i]);
  217. }
  218. eng.Forward();
  219. for (size_t i = 0; i < aY.size(); ++i) {
  220. eng.Y(i) *= aY[i];
  221. }
  222. eng.Backward();
  223. for (size_t i = 0; i < isUndefined.size(); ++i) {
  224. isUndefined[i] = candidates[i] && (eng.X(i).real() > 0.5) &&
  225. !(eng.X(i).imag() > 0.5);
  226. g[i] = candidates[i] && !(eng.X(i).real() > 0.5) &&
  227. !(eng.X(i).imag() > 0.5);
  228. }
  229. }
  230. std::cout << n << ":\t";
  231. PrintBits(g);
  232. std::cout << '\n';
  233.  
  234. std::fill(eng.XBegin(), eng.XEnd(), 0);
  235. for (size_t i = 0; i < g.size(); ++i) {
  236. eng.X(i) = Complex(0, g[i]);
  237. }
  238. eng.Forward();
  239. for (size_t i = 0; i < aY.size(); ++i) {
  240. eng.Y(i) *= aY[i];
  241. }
  242. eng.Backward();
  243. for (int i = 0; i < kNMax; ++i) {
  244. candidates[i] = candidates[i] && !g[i] && (eng.X(i).imag() > 0.5);
  245. }
  246. }
  247.  
  248. for (const auto& counter : PERFMON_COUNTERS()) {
  249. std::cerr << counter.Name() << ": " << counter.Calls() << ' '
  250. << counter.AverageSeconds() << '\n';
  251. }
  252.  
  253. return 0;
  254. }
Add Comment
Please, Sign In to add comment