Skip to content

Commit d50b7ab

Browse files
committed
Remember per-prime state
1 parent 1c10dbb commit d50b7ab

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

cp-algo/math/sieve.hpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)