|
21 | 21 | #pragma once |
22 | 22 |
|
23 | 23 | #include <algorithm> |
24 | | -#include <cmath> |
25 | 24 | #include <cstddef> |
26 | 25 | #include <cstdint> |
27 | 26 | #include <string> |
28 | | -#include <thread> |
29 | 27 | #include <type_traits> |
30 | 28 | #include <vector> |
31 | 29 |
|
|
36 | 34 | template <typename T, typename Ret = T> |
37 | 35 | using enable_if_integral = typename std::enable_if< |
38 | 36 | std::is_integral<T>::value && !std::is_same<T, bool>::value, Ret>::type; |
39 | | -template <typename T, typename Ret = T> |
40 | | -using enable_if_arithmetic = typename std::enable_if< |
41 | | - std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, Ret>::type; |
42 | | - |
43 | | -template <typename T, enable_if_arithmetic<T> = 0> |
44 | | -class Prime { |
45 | | - private: |
46 | | - std::vector<T> lastResults; |
47 | | - T lastLimit = 0; |
48 | | - T lastSize = 0; |
49 | | - inline static int maxThread = std::thread::hardware_concurrency(); |
50 | | - |
51 | | - void main_sieve(std::vector<uint64_t> &sieve, T limit, int offset) { |
52 | | - for (T p = 3 + offset * 2; p * p <= limit; p += 2 * maxThread) { |
53 | | - const size_t i = (p - 3) >> 1; |
54 | | - if (!(sieve[i >> 6] & (1ULL << (i & 63)))) continue; |
55 | | - for (T j = p * p; j <= limit; j += 2 * p) { |
56 | | - const size_t idx = (j - 3) >> 1; |
57 | | - sieve[idx >> 6] &= ~(1ULL << (idx & 63)); |
58 | | - } |
59 | | - } |
60 | | - } |
61 | | - |
62 | | - std::vector<uint64_t> create_sieve(T limit) { |
63 | | - if (limit < 3) return {}; |
64 | | - const size_t num_odds = ((limit - 3) >> 1) + 1; |
65 | | - const size_t array_size = (num_odds + 63) >> 6; |
66 | | - std::vector<uint64_t> sieve(array_size, uint64_t(~0)); |
67 | | - std::vector<std::thread> threads; |
68 | | - for (int i = 1; i < maxThread; ++i) |
69 | | - threads.emplace_back( |
70 | | - [this, &sieve, limit, i]() { main_sieve(sieve, limit, i); }); |
71 | | - main_sieve(sieve, limit, 0); |
72 | | - for (auto &t : threads) t.join(); |
73 | | - return sieve; |
74 | | - } |
75 | | - |
76 | | - T estimate_limit_from_size(size_t size) { |
77 | | - if (size < 6) return (1 << 4) - 1; |
78 | | - double n = static_cast<double>(size); |
79 | | - return static_cast<T>(n * (std::log(n) + std::log(std::log(n)))) + 10; |
80 | | - } |
81 | | - |
82 | | - public: |
83 | | - std::vector<T> from_size(size_t size) { |
84 | | - if (size <= lastSize) { |
85 | | - this->lastResults.resize(size); |
86 | | - return this->lastResults; |
87 | | - } |
88 | | - if (size == 0) return {}; |
89 | | - std::vector<T> primes; |
90 | | - primes.push_back(2); |
91 | | - if (size == 1) return primes; |
92 | | - T limit = estimate_limit_from_size(size); |
93 | | - lastLimit = limit; |
94 | | - auto sieve = create_sieve(limit); |
95 | | - const size_t num_odds = ((limit - 3) >> 1) + 1; |
96 | | - |
97 | | - for (size_t i = 0; i < num_odds && primes.size() < size; ++i) |
98 | | - if (sieve[i >> 6] & (1ULL << (i & 63))) primes.emplace_back(3 + 2 * i); |
99 | | - |
100 | | - lastResults = primes; |
101 | | - return primes; |
102 | | - } |
103 | | - |
104 | | - std::vector<T> from_range_limit(T limit) { |
105 | | - if (limit == lastLimit) return this->lastResults; |
106 | | - std::vector<T> primes; |
107 | | - if (limit < 2) return primes; |
108 | | - primes.push_back(2); |
109 | | - if (limit < 3) return primes; |
110 | | - lastLimit = limit; |
111 | | - auto sieve = create_sieve(limit); |
112 | | - const size_t num_odds = ((limit - 3) >> 1) + 1; |
113 | | - |
114 | | - for (size_t i = 0; i < num_odds; ++i) |
115 | | - if (sieve[i >> 6] & (1ULL << (i & 63))) primes.emplace_back(3 + 2 * i); |
116 | | - |
117 | | - lastResults = primes; |
118 | | - return primes; |
119 | | - } |
120 | | - |
121 | | - bool is_prime(T n) { |
122 | | - if (n <= 1) return false; |
123 | | - if (n == 2) return true; |
124 | | - if ((n & 1) == 0) return false; |
125 | | - T sqrt_n = static_cast<T>(std::sqrt(n)); |
126 | | - auto sieve = from_range_limit(sqrt_n); |
127 | | - for (T p : sieve) |
128 | | - if (n % p == 0) return false; |
129 | | - return true; |
130 | | - } |
131 | | - static int max_thread() { return Prime::maxThread; } |
132 | | -}; |
133 | 37 |
|
134 | 38 | class Fibonacci { |
135 | 39 | private: |
|
0 commit comments