a/math/numbers/prime.rs
1//! Primality of [`Number`]s: [`Number::is_probable_prime`], the Baillie–PSW test, and
2//! [`Number::next_prime`], the next probable prime.
3//!
4//! A number is first divided by the small primes, in groups whose products fit in a limb: one pass
5//! of the long number for each group, four groups a pass, and a multiplication for each prime of a
6//! group to tell whether it divides the remainder. What is left is tested by Baillie–PSW
7//! ([`bpsw`]): a strong test to base 2 and a strong Lucas test with Selfridge's parameters, in
8//! Montgomery's form, in registers up to seven limbs. Numbers below `2^64` take a path of their own,
9//! all in registers.
10//!
11//! The next prime is searched for in intervals of odd numbers, first sieved by the small primes, as
12//! GMP's `mpz_nextprime` does ([`next`]).
13
14mod bpsw;
15mod next;
16mod tables;
17
18use super::add::{SMALL, read_small};
19use super::mul::{Operand, STACK_LIMBS, on_heap, on_stack, to_limbs};
20use super::pow::montgomery::{Mont1, Mont2, MontN, even};
21use super::{ByteOrder, Number};
22use bpsw::{Bits, LimbField, bpsw, bpsw_limbs, bpsw_limbs_itch, reciprocal, rem_by};
23use core::mem::MaybeUninit;
24use tables::{GROUP, Group, PRIMES, groups_below};
25
26impl Number {
27 /// Returns whether the number is a probable prime, by the Baillie–PSW test: `false` for
28 /// everything below 2, negative numbers included, and for every composite number it finds
29 /// a factor of or that fails the test; `true` for every prime.
30 ///
31 /// Small factors are found by trial division; the rest is a strong (Miller–Rabin) test to base 2
32 /// and a strong Lucas test with Selfridge's parameters. The answer is exact below `2^64`, where
33 /// the test has been checked against every composite that passes Fermat's test to base 2, which
34 /// Feitsma and Galway listed (2009), by Gilchrist: none passes both.
35 /// Above, no composite is known that passes it, though such numbers are believed to exist; GMP's
36 /// `mpz_probab_prime_p(n, 24)` is the same test.
37 ///
38 /// # Examples
39 ///
40 /// ```
41 /// use a::math::numbers::{ByteOrder, Number};
42 ///
43 /// assert!(Number::new_from_u64(1_000_000_007, ByteOrder::BigEndian).is_probable_prime());
44 /// // 2047 = 23 * 89 passes the strong test to base 2, but not the Lucas test.
45 /// assert!(!Number::new_from_u32(2047, ByteOrder::LittleEndian).is_probable_prime());
46 /// assert!(!Number::new_from_i32(-7, ByteOrder::BigEndian).is_probable_prime());
47 /// ```
48 pub fn is_probable_prime(&self) -> bool {
49 if self.value.len() <= SMALL {
50 // SAFETY: the vector holds at most 16 bytes.
51 let x = unsafe { read_small(&self.value, self.byte_order) };
52 if x == 0 || self.negative {
53 return false;
54 }
55 if x >> 64 == 0 {
56 return is_prime_u64(x as u64);
57 }
58 return x & 1 == 1 && is_prime_limbs_small(&[x as u64, (x >> 64) as u64]);
59 }
60 let n = Operand::of(self);
61 if n.significant == 0 || self.negative {
62 return false;
63 }
64 let nn = n.significant.div_ceil(8);
65 let compute = |s: *mut MaybeUninit<u64>| {
66 let s = s.cast::<u64>();
67 // SAFETY: the working memory holds the limbs of `n` and what the test needs.
68 unsafe {
69 to_limbs(n, s);
70 if nn == 1 {
71 return is_prime_u64(*s);
72 }
73 *s & 1 == 1 && is_prime_odd(s, nn, s.add(even(nn)))
74 }
75 };
76 let need = even(nn) + prime_itch(nn);
77 if need <= STACK_LIMBS {
78 on_stack(compute)
79 } else {
80 on_heap(need, compute)
81 }
82 }
83
84 /// Returns the smallest probable prime above `self`, in the byte order of `self`, in one new
85 /// vector of exactly its length: 2 for anything below 2, negative numbers included.
86 ///
87 /// "Probable prime" is that of [`is_probable_prime`](Self::is_probable_prime): exact below
88 /// `2^64`, and with no known exception above. The odd numbers above `self` are sieved by the
89 /// small primes in intervals, and those left are tested in order.
90 ///
91 /// # Examples
92 ///
93 /// ```
94 /// use a::math::numbers::{ByteOrder, Number};
95 ///
96 /// let p = Number::new_from_u32(1_000_000_000, ByteOrder::BigEndian).next_prime();
97 /// assert_eq!(p.value, 1_000_000_007u32.to_be_bytes());
98 /// assert_eq!(Number::new_from_i32(-5, ByteOrder::BigEndian).next_prime().value, [2]);
99 /// ```
100 pub fn next_prime(&self) -> Number {
101 next::next_prime(self)
102 }
103}
104
105// Below 2^64
106
107/// The primes up to which a number below `2^64` is divided before the test: each costs a
108/// multiplication, and saves the test of the composites it finds. Measured on an Apple M4 Max,
109/// random odd numbers of 64 bits took 311 cycles with the primes to 64, 286 to 128, 271 to 256 and
110/// 259 to 512, and primes 2480 to 2550, 2540, 2550 to 2580 and 2605 to 2670.
111const TRIAL_64: u64 = 256;
112
113/// The index in [`PRIMES`] of the first prime above [`TRIAL_64`].
114const TRIAL_64_END: usize = {
115 let mut i = 0;
116 while PRIMES[i].p <= TRIAL_64 {
117 i += 1;
118 }
119 i
120};
121
122/// Whether `n` is a probable prime, exactly as it is below `2^64`.
123fn is_prime_u64(n: u64) -> bool {
124 if n < 4 {
125 return n >= 2;
126 }
127 if n & 1 == 0 {
128 return false;
129 }
130 for p in &PRIMES[..TRIAL_64_END] {
131 if p.divides(n) {
132 return n == p.p;
133 }
134 }
135 // A composite has a prime factor at most its square root, and none is below the next prime.
136 let next = PRIMES[TRIAL_64_END].p;
137 if n < next * next {
138 return true;
139 }
140 let f = Mont1::new(n);
141 let bits = Bits {
142 n: &n,
143 len: 64 - n.leading_zeros() as usize,
144 };
145 // SAFETY: the bits are those of `n`, odd and without factors up to `TRIAL_64`.
146 unsafe { bpsw(&f, bits, || selfridge_u64(n)) }
147}
148
149/// Selfridge's `D` for the odd `n`, at least 5, or `None` when `n` is a square or shares a factor
150/// with the `D`s before it.
151fn selfridge_u64(n: u64) -> Option<i64> {
152 if is_square_u64(n) {
153 return None;
154 }
155 let mut a = 5u64;
156 loop {
157 if a >= n {
158 // Every `D` below `n` has a symbol of 1 or a factor in common, which for a number
159 // without a small factor means it is prime; not reached for numbers beyond the trial
160 // primes' squares, kept for safety.
161 return Some(0);
162 }
163 let d = if a & 2 == 0 { a as i64 } else { -(a as i64) };
164 match symbol(d, n % a, n & 3) {
165 -1 => return Some(d),
166 0 => return None,
167 _ => a += 2,
168 }
169 }
170}
171
172/// Whether `n` is a perfect square.
173fn is_square_u64(n: u64) -> bool {
174 // Squares are 0, 1, 4 or 9 modulo 16.
175 if (0x0213 >> (n & 15)) & 1 == 0 {
176 return false;
177 }
178 let mut r = (n as f64).sqrt() as u64;
179 while u128::from(r) * u128::from(r) > u128::from(n) {
180 r -= 1;
181 }
182 while u128::from(r + 1) * u128::from(r + 1) <= u128::from(n) {
183 r += 1;
184 }
185 r * r == n
186}
187
188/// The Jacobi symbol `(D/n)` for `|D| = a`, from `n mod a` and `n mod 4`, `n` odd and positive: by
189/// reciprocity, `(a/n) = (n/a)` unless both are 3 modulo 4, and `(-1/n) = -1` when `n` is.
190fn symbol(d: i64, n_mod_a: u64, n_mod_4: u64) -> i32 {
191 let a = d.unsigned_abs();
192 let mut j = jacobi(n_mod_a, a);
193 if a & 3 == 3 && n_mod_4 == 3 {
194 j = -j;
195 }
196 if d < 0 && n_mod_4 == 3 {
197 j = -j;
198 }
199 j
200}
201
202/// The Jacobi symbol `(x/a)` for an odd `a`, by the binary method: the factors of two of `x` taken
203/// out (each turns the sign over when `a` is 3 or 5 modulo 8), then the larger of the two odd
204/// numbers less the smaller, swapped by reciprocity (which turns it over when both are 3 modulo 4).
205pub(super) fn jacobi(mut x: u64, mut a: u64) -> i32 {
206 debug_assert!(a & 1 == 1);
207 let mut t = 1;
208 if x >= a {
209 x %= a;
210 }
211 while x != 0 {
212 let z = x.trailing_zeros();
213 x >>= z;
214 if z & 1 == 1 && matches!(a & 7, 3 | 5) {
215 t = -t;
216 }
217 if x < a {
218 if x & a & 2 != 0 {
219 t = -t;
220 }
221 core::mem::swap(&mut x, &mut a);
222 }
223 x -= a;
224 }
225 if a == 1 { t } else { 0 }
226}
227
228// Long numbers
229
230/// The primes up to which a number of `bits` bits is divided before the test: four times its bits,
231/// from 256 to the table's 8192. Measured on an Apple M4 Max, random odd numbers of 512 bits took
232/// 20,500 cycles with the primes to its bits, 19,000 to twice and 16,000 to four times; of 1024
233/// bits 131,000, 94,000 and 94,600; primes the same.
234fn trial_bound(bits: usize) -> u64 {
235 (bits as u64 * 4).clamp(256, tables::LIMIT as u64)
236}
237
238/// The limbs of working memory of [`is_prime_odd`] for `nn` limbs.
239fn prime_itch(nn: usize) -> usize {
240 if nn >= 8 { bpsw_limbs_itch(nn) } else { 0 }
241}
242
243/// Whether the odd number of two limbs `n`, at least `2^64`, is a probable prime.
244fn is_prime_limbs_small(n: &[u64; 2]) -> bool {
245 // SAFETY: two limbs need no working memory.
246 unsafe { is_prime_odd(n.as_ptr(), 2, core::ptr::null_mut()) }
247}
248
249/// The remainders of the `nn` limbs at `n` by four groups' `d`s at once, four independent chains a
250/// limb.
251///
252/// # Safety
253///
254/// The limbs must be valid for reads.
255#[inline]
256unsafe fn rem_by_4(n: *const u64, nn: usize, g: &[Group; 4]) -> [u64; 4] {
257 let mut r = [0u64; 4];
258 // SAFETY: as the caller guarantees.
259 unsafe {
260 for i in (0..nn).rev() {
261 let x = *n.add(i);
262 for k in 0..4 {
263 r[k] = super::div::limbs::div_2by1(r[k], x, g[k].d, g[k].v).1;
264 }
265 }
266 }
267 r
268}
269
270/// Whether one of the primes of the groups `g` divides the `nn` limbs at `n`.
271///
272/// # Safety
273///
274/// The limbs must be valid for reads.
275unsafe fn has_factor_in(n: *const u64, nn: usize, groups: &[Group]) -> bool {
276 let (chunks, rest) = groups.as_chunks::<4>();
277 for g in chunks {
278 // SAFETY: as the caller guarantees.
279 let r = unsafe { rem_by_4(n, nn, g) };
280 for k in 0..4 {
281 let primes = &PRIMES[g[k].first as usize..g[k].end as usize];
282 if primes.iter().any(|p| p.divides(r[k])) {
283 return true;
284 }
285 }
286 }
287 for g in rest {
288 // SAFETY: as the caller guarantees.
289 let r = unsafe { rem_by(n, nn, g.d, g.v) };
290 let primes = &PRIMES[g.first as usize..g.end as usize];
291 if primes.iter().any(|p| p.divides(r)) {
292 return true;
293 }
294 }
295 false
296}
297
298/// Whether the odd number of `nn >= 2` limbs at `n`, at least `2^64`, is a probable prime: trial
299/// division, then Baillie–PSW, in registers up to seven limbs and in the [`prime_itch`] limbs at
300/// `s` beyond.
301///
302/// # Safety
303///
304/// The limbs must be valid for reads, the top one not zero, and `s` for the working memory,
305/// starting on 16 bytes.
306unsafe fn is_prime_odd(n: *const u64, nn: usize, s: *mut u64) -> bool {
307 // SAFETY: as the caller guarantees.
308 unsafe {
309 let bits = Bits {
310 n,
311 len: 64 * nn - (*n.add(nn - 1)).leading_zeros() as usize,
312 };
313 let g = groups_below(trial_bound(bits.len));
314 if has_factor_in(n, nn, &GROUP[..g]) {
315 return false;
316 }
317 probable_prime_odd(n, nn, bits, s)
318 }
319}
320
321/// Baillie–PSW for the odd number of `nn >= 2` limbs at `n`, at least `2^64` and with no prime
322/// factor up to 47, in registers up to seven limbs and in the [`prime_itch`] limbs at `s` beyond.
323///
324/// # Safety
325///
326/// As for [`is_prime_odd`].
327unsafe fn probable_prime_odd(n: *const u64, nn: usize, bits: Bits, s: *mut u64) -> bool {
328 let select = || {
329 // SAFETY: as the caller guarantees.
330 unsafe { selfridge(n, nn) }
331 };
332 // SAFETY: as the caller guarantees.
333 unsafe {
334 match nn {
335 2 => bpsw(&Mont2::new([*n, *n.add(1)]), bits, select),
336 3 => bpsw(&MontN::<3>::new(limbs(n)), bits, select),
337 4 => bpsw(&MontN::<4>::new(limbs(n)), bits, select),
338 5 => bpsw(&MontN::<5>::new(limbs(n)), bits, select),
339 6 => bpsw(&MontN::<6>::new(limbs(n)), bits, select),
340 7 => bpsw(&MontN::<7>::new(limbs(n)), bits, select),
341 _ => {
342 let f = LimbField::new(n, nn, s);
343 bpsw_limbs(&f, bits, s.add(LimbField::itch(nn)), select)
344 }
345 }
346 }
347}
348
349/// The `N` limbs at `n`.
350///
351/// # Safety
352///
353/// The limbs must be valid for reads.
354#[inline(always)]
355unsafe fn limbs<const N: usize>(n: *const u64) -> [u64; N] {
356 let mut a = [0; N];
357 // SAFETY: as the caller guarantees.
358 unsafe { core::ptr::copy_nonoverlapping(n, a.as_mut_ptr(), N) };
359 a
360}
361
362/// `3^2 5 7 11 ... 47`, the product of the odd primes to 47 and of 3 once more, below `2^64`: one
363/// remainder by it gives those by the first `|D|`s of Selfridge's search and by the primes that
364/// tell most squares apart.
365const SELFRIDGE: u64 = 9 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37 * 41 * 43 * 47;
366
367/// [`SELFRIDGE`] shifted so that its top bit is set.
368const SELFRIDGE_D: u64 = SELFRIDGE << SELFRIDGE.leading_zeros();
369
370/// The reciprocal of [`SELFRIDGE_D`].
371const SELFRIDGE_V: u64 = (u128::MAX / SELFRIDGE_D as u128) as u64;
372
373/// The odd primes to 47, for the squares.
374const SQUARE_PRIMES: [u64; 14] = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];
375
376/// Selfridge's `D` for the odd `n` of `nn >= 2` limbs, or `None` when `n` is a square or shares a
377/// factor with the `D`s before it: the first of `5, -7, 9, -11, ...` whose Jacobi symbol `(D/n)`
378/// is -1. A square's symbols are never -1, so squares are told apart first: the odd squares are 1
379/// modulo 8 and squares modulo every prime, which leaves the square root to check for few others.
380///
381/// # Safety
382///
383/// The limbs must be valid for reads, the top one not zero.
384unsafe fn selfridge(n: *const u64, nn: usize) -> Option<i64> {
385 // SAFETY: as the caller guarantees.
386 unsafe {
387 let r = rem_by(n, nn, SELFRIDGE_D, SELFRIDGE_V) % SELFRIDGE;
388 let low = *n;
389 if low & 7 == 1
390 && SQUARE_PRIMES
391 .iter()
392 .all(|&p| is_quadratic_residue(r % p, p))
393 && is_square(n, nn)
394 {
395 return None;
396 }
397 let mut a = 5u64;
398 loop {
399 let d = if a & 2 == 0 { a as i64 } else { -(a as i64) };
400 let n_mod_a = if SELFRIDGE.is_multiple_of(a) {
401 r % a
402 } else {
403 let s = a.leading_zeros();
404 rem_by(n, nn, a << s, reciprocal(a << s)) % a
405 };
406 match symbol(d, n_mod_a, low & 3) {
407 -1 => return Some(d),
408 0 => return None,
409 _ => a += 2,
410 }
411 }
412 }
413}
414
415/// Whether `r` is a square modulo the odd prime `p`, or zero: Euler's criterion, `r^((p-1)/2)`.
416fn is_quadratic_residue(r: u64, p: u64) -> bool {
417 r == 0 || jacobi(r, p) == 1
418}
419
420/// Whether the `nn` limbs at `n` are a perfect square: Newton's steps for the square root on
421/// numbers, from a power of two above it. Called for the few numbers that look like squares.
422///
423/// # Safety
424///
425/// The limbs must be valid for reads, the top one not zero.
426#[cold]
427#[inline(never)]
428unsafe fn is_square(n: *const u64, nn: usize) -> bool {
429 // SAFETY: as the caller guarantees.
430 let bytes: Vec<u8> = (0..nn)
431 .flat_map(|i| unsafe { *n.add(i) }.to_le_bytes())
432 .collect();
433 let x = Number::new(bytes, ByteOrder::LittleEndian);
434 // SAFETY: as the caller guarantees.
435 let bits = 64 * nn - unsafe { *n.add(nn - 1) }.leading_zeros() as usize;
436 let mut r = &Number::new_from_u8(1, ByteOrder::LittleEndian) << bits.div_ceil(2);
437 loop {
438 let next = &(&r + &(&x / &r)) >> 1;
439 if !(&next - &r).is_negative() {
440 break;
441 }
442 r = next;
443 }
444 (&r * &r).value == x.value
445}