@@ -17,8 +17,8 @@ namespace cp_algo::math {
1717 using cp_algo::structures::bit_array;
1818
1919 constexpr auto wheel_primes = std::array{2u , 3u , 5u , 7u };
20- constexpr uint32_t period = std::ranges::fold_left(wheel_primes, 1u , std::multiplies{});
21- constexpr uint32_t coprime = std::ranges::fold_left(wheel_primes, 1u , [](auto a, auto b){ return a * (b - 1 ); });
20+ constexpr uint8_t period = std::ranges::fold_left(wheel_primes, 1u , std::multiplies{});
21+ constexpr uint8_t coprime = std::ranges::fold_left(wheel_primes, 1u , [](auto a, auto b){ return a * (b - 1 ); });
2222 constexpr auto coprime_wheel = [](auto x) {
2323 return std::ranges::all_of (wheel_primes, [x](auto p){ return x % p; });
2424 };
@@ -76,7 +76,7 @@ namespace cp_algo::math {
7676 return (x / coprime) * period + res_wheel[x % coprime];
7777 }
7878
79- constexpr size_t sqrt_threshold = 1 << 15 ;
79+ constexpr size_t sqrt_threshold = 1 << 16 ;
8080 constexpr auto sqrt_prime_bits = []() {
8181 const int size = sqrt_threshold / 2 ;
8282 bit_array<size> prime;
@@ -151,7 +151,7 @@ namespace cp_algo::math {
151151 }
152152
153153 template <class BitArray >
154- constexpr void sieve_wheel (BitArray& prime, uint32_t l, uint32_t r, size_t i, int state) {
154+ constexpr auto sieve_wheel (BitArray& prime, uint32_t l, uint32_t r, size_t i, int state) {
155155 static const auto ord_step = []() {
156156 big_vector<std::array<uint32_t , 2 * coprime>> ord_steps (num_primes);
157157 for (uint32_t i = 0 ; i < size (sqrt_primes); i++) {
@@ -166,8 +166,9 @@ namespace cp_algo::math {
166166 }
167167 return ord_steps;
168168 }();
169+ auto &ords = ord_step[i];
169170 auto advance = [&]() {
170- prime.reset (std::exchange (l, l + ord_step[i] [state++]));
171+ prime.reset (std::exchange (l, l + ords [state++]));
171172 };
172173 uint32_t p = sqrt_primes[i];
173174 while (l + p * coprime <= r) {
@@ -180,6 +181,8 @@ namespace cp_algo::math {
180181 while (l < r) {
181182 advance ();
182183 }
184+ state = state >= coprime ? state - coprime : state;
185+ return std::pair{l, state};
183186 }
184187
185188 // Primes smaller or equal than N
@@ -218,15 +221,21 @@ namespace cp_algo::math {
218221 }
219222 }
220223 checkpoint (" dense sieve" );
221- static constexpr uint32_t sparse_block = 1 << 24 ;
224+ static constexpr uint32_t sparse_block = 1 << 22 ;
225+ auto [pos, state] = []() {
226+ big_vector<uint32_t > pos (num_primes);
227+ big_vector<uint8_t > state (num_primes);
228+ for (auto [i, p]: sqrt_primes | std::views::enumerate) {
229+ pos[i] = to_ord (p * p);
230+ state[i] = state_wheel[p % period];
231+ }
232+ return std::pair{pos, state};
233+ }();
222234 for (uint32_t start = 0 ; start < N; start += sparse_block) {
223- uint32_t r = std::min (start + sparse_block, N);
235+ uint32_t r = to_ord ( std::min (start + sparse_block, N) );
224236 for (size_t i = medium_primes_begin; i < size (sqrt_primes); i++) {
225- auto p = sqrt_primes[i];
226- if (p * p >= r) break ;
227- auto k = std::max (start / p, p);
228- if (!coprime_wheel (k)) {k += add_wheel[k % period];}
229- sieve_wheel (prime, to_ord (p * k), to_ord (r), i, state_wheel[k % period]);
237+ if (state[i] >= r) break ;
238+ std::tie (pos[i], state[i]) = sieve_wheel (prime, pos[i], r, i, state[i]);
230239 }
231240 }
232241 checkpoint (" sparse sieve" );
0 commit comments