pub fn is_prime(n: u64) -> bool {
if n < 2 {
return false;
}
if n == 2 || n == 3 {
return true;
}
if n % 2 == 0 {
return false;
}
if n < 1_000_000 {
return is_prime_small(n as i64);
}
miller_rabin_u64(n)
}
fn miller_rabin_u64(n: u64) -> bool {
let mut d = n - 1;
let mut s = 0;
while d % 2 == 0 {
d /= 2;
s += 1;
}
let witnesses = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
'witness: for &a in &witnesses {
if a >= n as i64 {
continue;
}
let mut x = powmod_u64(a as u64, d, n);
if x == 1 || x == n - 1 {
continue 'witness;
}
for _ in 0..s - 1 {
x = powmod_u64(x, 2, n);
if x == n - 1 {
continue 'witness;
}
}
return false;
}
true
}
fn is_prime_small(n: i64) -> bool {
if n < 2 {
return false;
}
if n <= 3 {
return true;
}
if n % 2 == 0 || n % 3 == 0 {
return false;
}
let mut i = 5;
while i * i <= n {
if n % i == 0 || n % (i + 2) == 0 {
return false;
}
i += 6;
}
true
}
fn powmod_u64(mut base: u64, mut exp: u64, modulus: u64) -> u64 {
if modulus == 1 {
return 0;
}
let mut result = 1u64;
base %= modulus;
while exp > 0 {
if exp % 2 == 1 {
result = result.wrapping_mul(base) % modulus;
}
exp /= 2;
base = base.wrapping_mul(base) % modulus;
}
result
}
pub fn next_prime(n: i64) -> i64 {
if n < 2 {
return 2;
}
let mut candidate = if n < 0 { 2 } else { n as u64 };
if candidate <= 2 {
return 2;
}
if candidate % 2 == 0 {
candidate += 1;
}
loop {
if is_prime(candidate) {
return candidate as i64;
}
candidate += 2;
}
}
pub fn prev_prime(n: i64) -> i64 {
if n <= 2 {
return 2;
}
let mut candidate = if n < 0 { 2 } else { n as u64 };
if candidate % 2 == 0 {
if candidate > 2 {
candidate -= 1;
} else {
return 2;
}
}
loop {
if candidate <= 2 {
return 2;
}
if is_prime(candidate) {
return candidate as i64;
}
candidate = candidate.saturating_sub(2);
}
}
pub fn nth_prime(n: u64) -> u64 {
assert!(n > 0, "n must be positive");
if n <= 10000 {
get_small_prime((n - 1) as usize)
} else {
let n_float = n as f64;
let ln_n = n_float.ln();
let ln_ln_n = ln_n.ln();
let estimate = (n_float * (ln_n + ln_ln_n)) as u64;
let mut candidate = estimate.max(2);
let upper = if n > 6 {
estimate + 1000
} else {
estimate + 10
};
loop {
if is_prime(candidate) {
return candidate;
}
candidate += 1;
if candidate > upper {
break;
}
}
let mut count = 0u64;
let mut i = 2u64;
loop {
if is_prime(i) {
count += 1;
if count == n {
return i;
}
}
i += 1;
}
}
}
fn get_small_prime(n: usize) -> u64 {
SMALL_PRIMES[n]
}
pub fn prime_count(x: i64) -> i64 {
if x < 2 {
return 0;
}
let x_abs = x.abs();
if x_abs <= 104_729 {
return count_primes_binary(x_abs);
}
prime_count_approx(x_abs)
}
fn prime_count_approx(x: i64) -> i64 {
if x < 2 {
return 0;
}
let x_float = x as f64;
if x_float > 1.0 {
(x_float / x_float.ln()) as i64
} else {
0
}
}
fn count_primes_binary(x: i64) -> i64 {
match SMALL_PRIMES.binary_search(&(x as u64)) {
Ok(i) => (i + 1) as i64,
Err(i) => i as i64,
}
}
pub fn primes_up_to(n: i64) -> Vec<i64> {
if n < 2 {
return Vec::new();
}
let n_usize = n as usize;
if n_usize > 10_000_000 {
return Vec::new();
}
let mut sieve = vec![true; n_usize + 1];
sieve[0] = false;
sieve[1] = false;
let mut i = 2;
while i * i <= n_usize {
if sieve[i] {
let mut j = i * i;
while j <= n_usize {
sieve[j] = false;
j += i;
}
}
i += 1;
}
sieve
.iter()
.enumerate()
.filter(|&(_, &is_prime)| is_prime)
.map(|(i, _)| i as i64)
.collect()
}
pub fn bernoulli(n: u64) -> Option<(i64, i64)> {
if n == 1 {
return Some((-1, 2));
}
if n == 0 {
return Some((1, 1));
}
if n % 2 == 1 && n > 1 {
return Some((0, 1));
}
let m = n as usize;
let mut a: Vec<(i64, i64)> = (0..=m).map(|j| (1, j as i64 + 1)).collect();
for m_curr in 1..=m {
for k in (1..=m_curr).rev() {
let (num1, den1) = a[k - 1];
let (num2, den2) = a[k];
let diff_num = num1 * den2 - num2 * den1;
let diff_den = den1 * den2;
let k_val = k as i64;
let new_num = k_val * diff_num;
let new_den = diff_den;
let g = gcd_int(new_num.abs(), new_den);
a[k - 1] = (new_num / g, new_den / g);
}
}
Some(a[0])
}
fn gcd_int(a: i64, b: i64) -> i64 {
if b == 0 {
a
} else {
gcd_int(b, a % b)
}
}
const SMALL_PRIMES: &[u64] = &include!("small_primes.inc");
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_prime() {
assert!(is_prime(2));
assert!(is_prime(3));
assert!(is_prime(17));
assert!(is_prime(7919)); assert!(!is_prime(1));
assert!(!is_prime(4));
assert!(!is_prime(100));
}
#[test]
fn test_miller_rabin() {
assert!(miller_rabin_u64(2));
assert!(miller_rabin_u64(3));
assert!(miller_rabin_u64(5));
assert!(miller_rabin_u64(7));
assert!(miller_rabin_u64(11));
assert!(miller_rabin_u64(13));
assert!(miller_rabin_u64(17));
assert!(miller_rabin_u64(19));
assert!(miller_rabin_u64(23));
assert!(miller_rabin_u64(29));
assert!(!miller_rabin_u64(4));
assert!(!miller_rabin_u64(6));
assert!(!miller_rabin_u64(8));
assert!(!miller_rabin_u64(9));
assert!(!miller_rabin_u64(10));
assert!(!miller_rabin_u64(12));
assert!(!miller_rabin_u64(15));
assert!(!miller_rabin_u64(21));
assert!(!miller_rabin_u64(25));
assert!(!miller_rabin_u64(27));
assert!(!miller_rabin_u64(561));
assert!(!miller_rabin_u64(1105));
assert!(!miller_rabin_u64(1729));
}
#[test]
fn test_next_prime() {
assert_eq!(next_prime(10), 11);
assert_eq!(next_prime(11), 11);
assert_eq!(next_prime(14), 17);
assert_eq!(next_prime(0), 2);
}
#[test]
fn test_prev_prime() {
assert_eq!(prev_prime(10), 7);
assert_eq!(prev_prime(7), 7);
assert_eq!(prev_prime(2), 2);
}
#[test]
fn test_nth_prime() {
assert_eq!(nth_prime(1), 2);
assert_eq!(nth_prime(2), 3);
assert_eq!(nth_prime(3), 5);
assert_eq!(nth_prime(5), 11);
assert_eq!(nth_prime(10), 29);
}
#[test]
fn test_prime_count() {
assert_eq!(prime_count(0), 0);
assert_eq!(prime_count(1), 0);
assert_eq!(prime_count(2), 1);
assert_eq!(prime_count(10), 4);
assert_eq!(prime_count(100), 25);
}
#[test]
fn test_primes_up_to() {
let primes = primes_up_to(20);
assert_eq!(primes, vec![2, 3, 5, 7, 11, 13, 17, 19]);
let primes_empty = primes_up_to(1);
assert!(primes_empty.is_empty());
}
#[test]
fn test_bernoulli() {
assert_eq!(bernoulli(0), Some((1, 1)));
assert_eq!(bernoulli(1), Some((-1, 2)));
assert_eq!(bernoulli(2), Some((1, 6)));
assert_eq!(bernoulli(3), Some((0, 1)));
assert_eq!(bernoulli(4), Some((-1, 30)));
}
}