1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
use std::cmp;
use primal_bit::BitVec;
pub const BYTE_SIZE: usize = 8;
pub const BYTE_MODULO: usize = 30;
const WHEEL_OFFSETS: &'static [usize; BYTE_MODULO] = &[
0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 2,
0, 3, 0, 0, 0, 4,
0, 5, 0, 0, 0, 6,
0, 0, 0, 0, 0, 7,
];
pub fn small_for(x: usize) -> Option<BitVec> {
let bits = bits_for(x);
if bits < wheel30::SMALL_BITS {
let u64s = (bits + 64 - 1) / 64;
Some(BitVec::from_u64s(wheel30::SMALL[..u64s].to_owned(), bits))
} else {
None
}
}
pub fn bits_for(x: usize) -> usize {
let d = x / BYTE_MODULO;
let r = x % BYTE_MODULO;
d * BYTE_SIZE + (r * BYTE_SIZE + BYTE_MODULO - 1) / BYTE_MODULO
}
pub fn bit_index(n: usize) -> (bool, usize) {
const POS: &'static [(bool, u8); BYTE_MODULO] = &[
(false, 0), (true, 0), (false, 1), (false, 1), (false, 1), (false, 1),
(false, 1), (true, 1), (false, 2), (false, 2), (false, 2), (true, 2),
(false, 3), (true, 3), (false, 4), (false, 4), (false, 4), (true, 4),
(false, 5), (true, 5), (false, 6), (false, 6), (false, 6), (true, 6),
(false, 7), (false, 7), (false, 7), (false, 7), (false, 7), (true, 7),
];
let init = &POS[n % BYTE_MODULO];
(init.0, (n / BYTE_MODULO) * BYTE_SIZE + init.1 as usize)
}
pub fn upper_bound(nbits: usize) -> usize {
(nbits / BYTE_SIZE).checked_mul(BYTE_MODULO)
.and_then(|n| n.checked_add(TRUE_AT_BIT[nbits % BYTE_SIZE] - 1))
.unwrap_or(::std::usize::MAX)
}
pub fn from_bit_index(bit: usize) -> usize {
(bit / BYTE_SIZE) * BYTE_MODULO + TRUE_AT_BIT[bit % BYTE_SIZE]
}
const TRUE_AT_BIT: &'static [usize; 8] = &[
1, 7, 11, 13, 17, 19, 23, 29
];
pub const TRUE_AT_BIT_64: &'static [usize; 64] = &[
1 + 30*0, 7 + 30*0, 11 + 30*0, 13 + 30*0, 17 + 30*0, 19 + 30*0, 23 + 30*0, 29 + 30*0,
1 + 30*1, 7 + 30*1, 11 + 30*1, 13 + 30*1, 17 + 30*1, 19 + 30*1, 23 + 30*1, 29 + 30*1,
1 + 30*2, 7 + 30*2, 11 + 30*2, 13 + 30*2, 17 + 30*2, 19 + 30*2, 23 + 30*2, 29 + 30*2,
1 + 30*3, 7 + 30*3, 11 + 30*3, 13 + 30*3, 17 + 30*3, 19 + 30*3, 23 + 30*3, 29 + 30*3,
1 + 30*4, 7 + 30*4, 11 + 30*4, 13 + 30*4, 17 + 30*4, 19 + 30*4, 23 + 30*4, 29 + 30*4,
1 + 30*5, 7 + 30*5, 11 + 30*5, 13 + 30*5, 17 + 30*5, 19 + 30*5, 23 + 30*5, 29 + 30*5,
1 + 30*6, 7 + 30*6, 11 + 30*6, 13 + 30*6, 17 + 30*6, 19 + 30*6, 23 + 30*6, 29 + 30*6,
1 + 30*7, 7 + 30*7, 11 + 30*7, 13 + 30*7, 17 + 30*7, 19 + 30*7, 23 + 30*7, 29 + 30*7,
];
pub use self::wheel30::Wheel30;
pub use self::wheel210::Wheel210;
pub trait Wheel {
fn modulo(&self) -> usize;
fn size(&self) -> usize;
fn wheel(&self) -> &'static [WheelElem];
fn init(&self) -> &'static [WheelInit];
unsafe fn hardcoded_sieve(&self,
bytes: &mut [u8], si_: &mut usize, wi_: &mut usize, prime: usize);
}
type SI = u32;
type WI = u16;
#[derive(Debug)]
pub struct State<W> {
wheel: W,
prime: u32,
wheel_index: WI,
sieve_index: SI,
}
impl<W: Wheel> State<W> {
pub fn new(w: W, p: usize, low: usize) -> State<W> {
let q = cmp::max(low / p + 1, p);
let mut mult = p * q;
let init = &w.init()[q % w.modulo()];
mult += p * init.next_mult_factor as usize;
let low_offset = mult - low;
let sieve_index = low_offset / BYTE_MODULO;
let wheel_index = WHEEL_OFFSETS[p % BYTE_MODULO] * w.size() + init.wheel_index as usize;
let prime = p / BYTE_MODULO;
State {
wheel: w,
prime: prime as u32,
sieve_index: sieve_index as SI,
wheel_index: wheel_index as WI,
}
}
#[inline]
pub fn sieve(&mut self, bytes: &mut [u8]) {
let bytes = bytes;
let top = bytes.len();
let mut si = self.sieve_index as usize;
let mut wi = self.wheel_index as usize;
let p = self.prime as usize;
while si < top {
raw_set_bit(self.wheel.wheel(),
bytes, &mut si, &mut wi, p)
}
self.sieve_index = si.wrapping_sub(top) as SI;
self.wheel_index = wi as WI;
}
#[inline]
pub fn sieve_pair(&mut self, self2: &mut State<W>, bytes: &mut [u8]) {
let bytes = bytes;
let top = bytes.len();
let wheel = self.wheel.wheel();
let mut si1 = self.sieve_index as usize;
let mut wi1 = self.wheel_index as usize;
let p1 = self.prime as usize;
let mut si2 = self2.sieve_index as usize;
let mut wi2 = self2.wheel_index as usize;
let p2 = self2.prime as usize;
while si1 < top && si2 < top {
raw_set_bit(wheel,
bytes, &mut si1, &mut wi1, p1);
raw_set_bit(wheel,
bytes, &mut si2, &mut wi2, p2);
}
while si1 < top {
raw_set_bit(wheel,
bytes, &mut si1, &mut wi1, p1);
}
while si2 < top {
raw_set_bit(wheel,
bytes, &mut si2, &mut wi2, p2);
}
self.sieve_index = si1.wrapping_sub(top) as SI;
self.wheel_index = wi1 as WI;
self2.sieve_index = si2.wrapping_sub(top) as SI;
self2.wheel_index = wi2 as WI;
}
pub fn sieve_triple(&mut self, self2: &mut State<W>, self3: &mut State<W>,
bytes: &mut [u8]) {
let bytes = bytes;
let top = bytes.len();
let wheel = self.wheel.wheel();
let mut si1 = self.sieve_index as usize;
let mut wi1 = self.wheel_index as usize;
let p1 = self.prime as usize;
let mut si2 = self2.sieve_index as usize;
let mut wi2 = self2.wheel_index as usize;
let p2 = self2.prime as usize;
let mut si3 = self3.sieve_index as usize;
let mut wi3 = self3.wheel_index as usize;
let p3 = self3.prime as usize;
while si1 < top && si2 < top && si3 < top {
raw_set_bit(wheel,
bytes, &mut si1, &mut wi1, p1);
raw_set_bit(wheel,
bytes, &mut si2, &mut wi2, p2);
raw_set_bit(wheel,
bytes, &mut si3, &mut wi3, p3);
}
while si1 < top {
raw_set_bit(wheel,
bytes, &mut si1, &mut wi1, p1);
}
while si2 < top {
raw_set_bit(wheel,
bytes, &mut si2, &mut wi2, p2);
}
while si3 < top {
raw_set_bit(wheel,
bytes, &mut si3, &mut wi3, p3);
}
self.sieve_index = si1.wrapping_sub(top) as SI;
self.wheel_index = wi1 as WI;
self2.sieve_index = si2.wrapping_sub(top) as SI;
self2.wheel_index = wi2 as WI;
self3.sieve_index = si3.wrapping_sub(top) as SI;
self3.wheel_index = wi3 as WI;
}
pub fn sieve_hardcoded(&mut self, bytes: &mut [u8]) {
let mut si = self.sieve_index as usize;
let mut wi = self.wheel_index as usize;
unsafe {
self.wheel.hardcoded_sieve(bytes,
&mut si, &mut wi, self.prime as usize)
}
self.sieve_index = si as SI;
self.wheel_index = wi as WI;
}
}
#[derive(Debug)]
pub struct WheelInit {
next_mult_factor: u8,
wheel_index: u8,
}
#[derive(Debug)]
pub struct WheelElem {
unset_bit: u8,
next_mult_factor: u8,
correction: u8,
next: i8,
}
#[inline(always)]
#[cfg(not(feature = "safe"))]
fn raw_set_bit(wheel: &'static [WheelElem],
x: &mut [u8], si: &mut usize, wi: &mut usize, prime: usize) {
unsafe {
let WheelElem { unset_bit, next_mult_factor, correction, next } =
*wheel.get_unchecked(*wi);
*x.get_unchecked_mut(*si) &= unset_bit;
*si += prime * next_mult_factor as usize;
*si += correction as usize;
*wi = wi.wrapping_add(next as usize);
}
}
#[inline(always)]
#[cfg(feature = "safe")]
fn raw_set_bit(wheel: &'static [WheelElem],
x: &mut [u8], si: &mut usize, wi: &mut usize, prime: usize) {
let WheelElem { unset_bit, next_mult_factor, correction, next } = wheel[*wi];
x[*si] &= unset_bit;
*si += prime * next_mult_factor as usize;
*si += correction as usize;
*wi = wi.wrapping_add(next as usize);
}
mod wheel30;
mod wheel210;