malachite_base/num/factorization/
prime_sieve.rs1use crate::num::basic::integers::PrimitiveInt;
16use crate::num::basic::unsigneds::PrimitiveUnsigned;
17use crate::num::conversion::traits::ExactFrom;
18use crate::num::logic::traits::CountOnes;
19
20pub const SIEVE_SEED_U32: u32 = 0x69128480;
21pub const SIEVE_MASK1_U32: u32 = 0x12148960;
23pub const SIEVE_MASK2_U32: u32 = 0x44a120cc;
24pub const SIEVE_MASKT_U32: u32 = 0x1a;
25pub const SEED_LIMIT_U32: u64 = 120;
26
27pub const SIEVE_SEED_U64: u64 = 0x3294C9E069128480;
28pub const SIEVE_MASK1_U64: u64 = 0x81214a1204892058;
30pub const SIEVE_MASKT_U64: u64 = 0xc8130681244;
31pub const SIEVE_2MSK1_U64: u64 = 0x9402180c40230184;
33pub const SIEVE_2MSK2_U64: u64 = 0x0285021088402120;
34pub const SIEVE_2MSKT_U64: u64 = 0xa41210084421;
35pub const SEED_LIMIT_U64: u64 = 210;
36
37const C70M2U32W: u64 = 70 - (u32::WIDTH << 1);
38const C70MU32W: u64 = 70 - u32::WIDTH;
39const C2U32W: u64 = u32::WIDTH << 1;
40const C3U32WM70: u64 = 3 * u32::WIDTH - 70;
41
42fn fill_bitpattern_u32(bit_array: &mut [u32], mut offset: u64) -> u64 {
51 let mut len = bit_array.len();
52 let (mut mask, mut mask2, mut tail) = if offset == 0 {
53 (SIEVE_MASK1_U32, SIEVE_MASK2_U32, SIEVE_MASKT_U32)
54 } else {
55 offset %= 70;
56 if offset != 0 {
57 if offset <= u32::WIDTH {
58 let offset_comp = u32::WIDTH - offset;
59 let mut mask = SIEVE_MASK2_U32 << offset_comp;
60 let mut mask2 = SIEVE_MASKT_U32 << offset_comp;
61 if offset != u32::WIDTH {
62 mask |= SIEVE_MASK1_U32 >> offset;
63 mask2 |= SIEVE_MASK2_U32 >> offset;
64 }
65 let tail = if offset <= C70M2U32W {
66 (SIEVE_MASK1_U32 << (C70M2U32W - offset)) | (SIEVE_MASKT_U32 >> offset)
67 } else {
68 mask2 |= SIEVE_MASK1_U32 << (C70MU32W - offset);
69 SIEVE_MASK1_U32 >> (offset - C70M2U32W)
70 };
71 (mask, mask2, tail)
72 } else if offset < C2U32W {
73 let mut mask = (SIEVE_MASK2_U32 >> (offset - u32::WIDTH))
74 | (SIEVE_MASKT_U32 << (C2U32W - offset));
75 if offset <= C70MU32W {
76 let mut tail = SIEVE_MASK2_U32 << (C70MU32W - offset);
77 if offset != C70MU32W {
78 tail |= SIEVE_MASK1_U32 >> (offset - C70M2U32W);
79 }
80 (
81 mask,
82 (SIEVE_MASKT_U32 >> (offset - u32::WIDTH))
83 | (SIEVE_MASK1_U32 << (C70MU32W - offset)),
84 tail,
85 )
86 } else {
87 let d70_offset = 70 - offset;
88 let width_m_d70_offset = u32::WIDTH - d70_offset;
89 mask |= SIEVE_MASK1_U32 << d70_offset;
90 (
91 mask,
92 (SIEVE_MASK2_U32 << d70_offset) | (SIEVE_MASK1_U32 >> width_m_d70_offset),
93 SIEVE_MASK2_U32 >> width_m_d70_offset,
94 )
95 }
96 } else {
97 let d70_offset = 70 - offset;
98 let width_m_d70_offset = u32::WIDTH - d70_offset;
99 (
100 (SIEVE_MASK1_U32 << d70_offset) | (SIEVE_MASKT_U32 >> (offset - C2U32W)),
101 (SIEVE_MASK2_U32 << d70_offset) | (SIEVE_MASK1_U32 >> width_m_d70_offset),
102 (SIEVE_MASKT_U32 << d70_offset) | (SIEVE_MASK2_U32 >> width_m_d70_offset),
103 )
104 }
105 } else {
106 (SIEVE_MASK1_U32, SIEVE_MASK2_U32, SIEVE_MASKT_U32)
107 }
108 };
109 for xs in bit_array.chunks_mut(2) {
110 xs[0] = mask;
111 len -= 1;
112 if len == 0 {
113 break;
114 }
115 xs[1] = mask2;
116 let temp = mask2 >> C3U32WM70;
117 mask2 = (mask2 << C70M2U32W) | (mask >> C3U32WM70);
118 mask = (mask << C70M2U32W) | tail;
119 tail = temp;
120 len -= 1;
121 if len == 0 {
122 break;
123 }
124 }
125 2
126}
127
128const C110MU64W: u64 = 110 - u64::WIDTH;
129const C2U64WM110: u64 = (u64::WIDTH << 1) - 110;
130const C182MU64W: u64 = 182 - u64::WIDTH;
131const C182M2U64W: u64 = 182 - (u64::WIDTH << 1);
132const C3U64WM182: u64 = 3 * u64::WIDTH - 182;
133const C2U64W: u64 = u64::WIDTH << 1;
134
135fn fill_bitpattern_u64(bit_array: &mut [u64], mut offset: u64) -> u64 {
144 let mut len = bit_array.len();
145 let ((mut m11, mut m12), (mut m21, mut m22, mut m23)) = if offset == 0 {
146 (
147 (SIEVE_MASK1_U64, SIEVE_MASKT_U64),
148 (SIEVE_2MSK1_U64, SIEVE_2MSK2_U64, SIEVE_2MSKT_U64),
149 )
150 } else {
151 let mut m21 = offset % 110;
153 let (m11, m12) = if m21 != 0 {
154 if m21 < u64::WIDTH {
155 let mut m11 = (SIEVE_MASK1_U64 >> m21) | (SIEVE_MASKT_U64 << (u64::WIDTH - m21));
156 if m21 <= C110MU64W {
157 (
158 m11,
159 (SIEVE_MASK1_U64 << (C110MU64W - m21)) | (SIEVE_MASKT_U64 >> m21),
160 )
161 } else {
162 m11 |= SIEVE_MASK1_U64 << (110 - m21);
163 (m11, SIEVE_MASK1_U64 >> (m21 - C110MU64W))
164 }
165 } else {
166 (
167 (SIEVE_MASK1_U64 << (110 - m21)) | (SIEVE_MASKT_U64 >> (m21 - u64::WIDTH)),
168 (SIEVE_MASKT_U64 << (110 - m21)) | (SIEVE_MASK1_U64 >> (m21 - C110MU64W)),
169 )
170 }
171 } else {
172 (SIEVE_MASK1_U64, SIEVE_MASKT_U64)
173 };
174 ((m11, m12), {
175 offset %= 182;
176 if offset != 0 {
177 if offset <= u64::WIDTH {
178 let mut m21 = SIEVE_2MSK2_U64 << (u64::WIDTH - offset);
179 let mut m22 = SIEVE_2MSKT_U64 << (u64::WIDTH - offset);
180 if offset != u64::WIDTH {
181 m21 |= SIEVE_2MSK1_U64 >> offset;
182 m22 |= SIEVE_2MSK2_U64 >> offset;
183 }
184 if offset <= C182M2U64W {
185 (
186 m21,
187 m22,
188 (SIEVE_2MSK1_U64 << (C182M2U64W - offset))
189 | (SIEVE_2MSKT_U64 >> offset),
190 )
191 } else {
192 m22 |= SIEVE_2MSK1_U64 << (C182MU64W - offset);
193 (m21, m22, SIEVE_2MSK1_U64 >> (offset - C182M2U64W))
194 }
195 } else if offset < C2U64W {
196 m21 = (SIEVE_2MSK2_U64 >> (offset - u64::WIDTH))
197 | (SIEVE_2MSKT_U64 << (C2U64W - offset));
198 if offset <= C182MU64W {
199 let mut m23 = SIEVE_2MSK2_U64 << (C182MU64W - offset);
200 if offset != C182MU64W {
201 m23 |= SIEVE_2MSK1_U64 >> (offset - C182M2U64W);
202 }
203 (
204 m21,
205 (SIEVE_2MSKT_U64 >> (offset - u64::WIDTH))
206 | (SIEVE_2MSK1_U64 << (C182MU64W - offset)),
207 m23,
208 )
209 } else {
210 m21 |= SIEVE_2MSK1_U64 << (182 - offset);
211 (
212 m21,
213 (SIEVE_2MSK2_U64 << (182 - offset))
214 | (SIEVE_2MSK1_U64 >> (offset - C182MU64W)),
215 SIEVE_2MSK2_U64 >> (offset - C182MU64W),
216 )
217 }
218 } else {
219 (
220 (SIEVE_2MSK1_U64 << (182 - offset))
221 | (SIEVE_2MSKT_U64 >> (offset - C2U64W)),
222 (SIEVE_2MSK2_U64 << (182 - offset))
223 | (SIEVE_2MSK1_U64 >> (offset - C182MU64W)),
224 (SIEVE_2MSKT_U64 << (182 - offset))
225 | (SIEVE_2MSK2_U64 >> (offset - C182MU64W)),
226 )
227 }
228 } else {
229 (SIEVE_2MSK1_U64, SIEVE_2MSK2_U64, SIEVE_2MSKT_U64)
230 }
231 })
232 };
233 for xs in bit_array.chunks_mut(2) {
234 xs[0] = m11 | m21;
235 len -= 1;
236 if len == 0 {
237 break;
238 }
239 let temp = m11 >> C2U64WM110;
240 m11 = (m11 << C110MU64W) | m12;
241 m12 = temp;
242 xs[1] = m11 | m22;
243 let temp = m11 >> C2U64WM110;
244 m11 = (m11 << C110MU64W) | m12;
245 m12 = temp;
246 let temp = m22 >> C3U64WM182;
247 m22 = (m22 << C182M2U64W) | (m21 >> C3U64WM182);
248 m21 = (m21 << C182M2U64W) | m23;
249 m23 = temp;
250 len -= 1;
251 if len == 0 {
252 break;
253 }
254 }
255 4
256}
257
258#[doc(hidden)]
259pub const fn n_to_bit(n: u64) -> u64 {
261 ((n - 5) | 1) / 3
262}
263
264#[doc(hidden)]
265pub const fn id_to_n(id: u64) -> u64 {
267 id * 3 + 1 + (id & 1)
268}
269
270fn first_block_primesieve<T: PrimitiveUnsigned, F: Fn(&mut [T], u64) -> u64>(
279 bit_array: &mut [T],
280 n: u64,
281 fill_bitpattern: F,
282 sieve_seed: T,
283 seed_limit: u64,
284) {
285 assert!(n > 4);
286 let bits = n_to_bit(n);
287 let limbs = usize::exact_from(bits >> T::LOG_WIDTH);
288 let mut i = if limbs == 0 {
289 0
290 } else {
291 fill_bitpattern(&mut bit_array[1..=limbs], 0)
292 };
293 bit_array[0] = sieve_seed;
294 if (bits + 1) & T::WIDTH_MASK != 0 {
295 bit_array[limbs] |= T::MAX << ((bits + 1) & T::WIDTH_MASK);
296 }
297 if n > seed_limit {
298 assert!(i < T::WIDTH);
299 if n_to_bit(seed_limit + 1) < T::WIDTH {
300 i = 0;
301 }
302 let mut mask = T::power_of_2(i);
303 let mut index = 0;
304 for i in i + 1.. {
305 if bit_array[index] & mask == T::ZERO {
306 let mut step = id_to_n(i);
307 let mut lindex = i * (step + 1) - 1 + ((i & 1).wrapping_neg() & (i + 1));
309 if lindex > bits {
311 break;
312 }
313 step <<= 1;
314 let maskrot = step & T::WIDTH_MASK;
315 let mut lmask = T::power_of_2(lindex & T::WIDTH_MASK);
316 while lindex <= bits {
317 bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask;
318 lmask.rotate_left_assign(maskrot);
319 lindex += step;
320 }
321 lindex = i * (i * 3 + 6) + (i & 1);
323 lmask = T::power_of_2(lindex & T::WIDTH_MASK);
324 while lindex <= bits {
325 bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask;
326 lmask.rotate_left_assign(maskrot);
327 lindex += step;
328 }
329 }
330 mask <<= 1;
331 if mask == T::ZERO {
332 mask = T::ONE;
333 index += 1;
334 }
335 }
336 }
337}
338
339fn block_resieve<T: PrimitiveUnsigned, F: Fn(&mut [T], u64) -> u64>(
348 bit_array: &mut [T],
349 offset: u64,
350 sieve: &[T],
351 fill_bitpattern: &F,
352) {
353 let limbs = bit_array.len();
354 let off = offset;
355 assert_ne!(limbs, 0);
356 assert!(offset >= T::WIDTH);
357 let bits = u64::exact_from(limbs << T::LOG_WIDTH) - 1;
358 let i = fill_bitpattern(&mut bit_array[..limbs], offset - T::WIDTH);
359 assert!(i < T::WIDTH);
360 let mut mask = T::power_of_2(i);
361 let mut index = 0;
362 for i in i + 1.. {
363 if sieve[index] & mask == T::ZERO {
364 let mut step = id_to_n(i);
365 let mut lindex = i * (step + 1) - 1 + ((i & 1).wrapping_neg() & (i + 1));
367 if lindex > bits + off {
369 break;
370 }
371 step <<= 1;
372 let maskrot = step & T::WIDTH_MASK;
373 if lindex < off {
374 lindex += step * ((off - lindex - 1) / step + 1);
375 }
376 lindex -= off;
377 let mut lmask = T::power_of_2(lindex & T::WIDTH_MASK);
378 while lindex <= bits {
379 bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask;
380 lmask.rotate_left_assign(maskrot);
381 lindex += step;
382 }
383 lindex = i * (i * 3 + 6) + (i & 1);
385 if lindex < off {
386 lindex += step * ((off - lindex - 1) / step + 1);
387 }
388 lindex -= off;
389 lmask = T::power_of_2(lindex & T::WIDTH_MASK);
390 while lindex <= bits {
391 bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask;
392 lmask.rotate_left_assign(maskrot);
393 lindex += step;
394 }
395 }
396 mask <<= 1;
397 if mask == T::ZERO {
398 mask = T::ONE;
399 index += 1;
400 }
401 }
402}
403
404#[doc(hidden)]
405#[inline]
406pub fn limbs_prime_sieve_size<T: PrimitiveUnsigned>(n: u64) -> usize {
408 assert!(n >= 5);
409 usize::exact_from((n_to_bit(n) >> T::LOG_WIDTH) + 1)
410}
411
412const BLOCK_SIZE: usize = 2048;
413
414pub_test! {limbs_count_ones<T: PrimitiveUnsigned>(xs: &[T]) -> u64 {
415 xs.iter().map(|&x| CountOnes::count_ones(x)).sum()
416}}
417
418fn limbs_prime_sieve_generic<T: PrimitiveUnsigned, F: Fn(&mut [T], u64) -> u64>(
435 bit_array: &mut [T],
436 n: u64,
437 fill_bitpattern: F,
438 sieve_seed: T,
439 seed_limit: u64,
440) -> u64 {
441 assert!(n > 4);
442 let bits = n_to_bit(n);
443 let size = usize::exact_from((bits >> T::LOG_WIDTH) + 1);
444 if size > BLOCK_SIZE << 1 {
445 let mut off = BLOCK_SIZE + (size % BLOCK_SIZE);
446 first_block_primesieve(
447 bit_array,
448 id_to_n(u64::exact_from(off) << T::LOG_WIDTH),
449 &fill_bitpattern,
450 sieve_seed,
451 seed_limit,
452 );
453 let (sieve, bit_array) = bit_array.split_at_mut(off);
454 for xs in bit_array.chunks_mut(BLOCK_SIZE) {
455 block_resieve(
456 xs,
457 u64::exact_from(off) << T::LOG_WIDTH,
458 sieve,
459 &fill_bitpattern,
460 );
461 off += BLOCK_SIZE;
462 if off >= size {
463 break;
464 }
465 }
466 } else {
467 first_block_primesieve(bit_array, n, &fill_bitpattern, sieve_seed, seed_limit);
468 }
469 if (bits + 1) & T::WIDTH_MASK != 0 {
470 bit_array[size - 1] |= T::MAX << ((bits + 1) & T::WIDTH_MASK);
471 }
472 (u64::exact_from(size) << T::LOG_WIDTH) - limbs_count_ones(&bit_array[..size])
473}
474
475#[doc(hidden)]
476#[inline]
478pub fn limbs_prime_sieve_u32(bit_array: &mut [u32], n: u64) -> u64 {
479 limbs_prime_sieve_generic(
480 bit_array,
481 n,
482 fill_bitpattern_u32,
483 SIEVE_SEED_U32,
484 SEED_LIMIT_U32,
485 )
486}
487
488#[doc(hidden)]
489#[inline]
491pub fn limbs_prime_sieve_u64(bit_array: &mut [u64], n: u64) -> u64 {
492 limbs_prime_sieve_generic(
493 bit_array,
494 n,
495 fill_bitpattern_u64,
496 SIEVE_SEED_U64,
497 SEED_LIMIT_U64,
498 )
499}