use num_bigint::BigInt;
use num_traits::One;
use symplex::ntheory::*;
use symplex::prelude::*;
fn main() {
let ctx = Context::new();
println!("=== Number Theory — Unified API ===\n");
println!("Primality testing:");
println!(" Is 104729 prime? {}", isprime(104729));
println!(" Is 104730 prime? {}", isprime(104730));
println!(" Is 2^31-1 (M31) prime? {}", isprime(2_147_483_647i64));
let m61 = BigInt::from(2u64.pow(61) - 1);
println!(" Is M61 = {} prime? {}", m61, isprime(m61.clone()));
let p1 = BigInt::from(1_000_000_007i64);
let p2 = BigInt::from(1_000_000_009i64);
let composite = &p1 * &p2;
let composite_is_prime = isprime(composite.clone());
println!(
" Is {} × {} = {} prime? {}",
p1, p2, composite, composite_is_prime
);
println!("\nNext / previous prime:");
println!(" nextprime(100) = {}", nextprime(100));
println!(" prevprime(100) = {}", prevprime(100).unwrap());
println!("\nPrimes up to 50: {:?}", primes_up_to(50));
println!("\nFactorization:");
for n in [60i64, 360, 2310, 100_000, 1_000_003] {
print_factors(n, &factorint(n));
}
println!("\n BigInt inputs:");
let m31_val = BigInt::from(2_147_483_647i64);
print_factors_big(&m31_val, &factorint(m31_val.clone()));
print_factors_big(&m61, &factorint(m61.clone()));
let pow2_40 = BigInt::from(1u64 << 40);
print_factors_big(&pow2_40, &factorint(pow2_40.clone()));
let beyond_f64 = BigInt::from(2u64.pow(53) + 1);
let factors = factorint(beyond_f64.clone());
print_factors_big(&beyond_f64, &factors);
let mut product = BigInt::one();
for (p, e) in &factors {
for _ in 0..*e {
product *= p;
}
}
assert_eq!(product, beyond_f64, "roundtrip must be exact beyond f64");
println!(" ✓ Roundtrip verified (no f64 truncation)");
println!("\nDivisors of 60: {:?}", divisors(60));
println!("Divisor count of 60: {}", divisor_count(60));
println!("Divisor sum of 60: {}", divisor_sum(60));
println!("\nEuler's totient:");
for n in [1i64, 6, 12, 36, 97] {
println!(" φ({n}) = {}", totient(n));
}
println!("\nMöbius function:");
for n in [1i64, 2, 4, 6, 30] {
println!(" μ({n}) = {}", mobius(n));
}
println!("\nGCD and LCM:");
println!(" gcd(12, 8) = {}", gcd(12, 8));
println!(" lcm(4, 6) = {}", lcm(4, 6));
println!(" coprime(8, 15)? {}", is_coprime(8, 15));
println!(" coprime(8, 12)? {}", is_coprime(8, 12));
println!("\nModular arithmetic:");
println!(" 3⁻¹ mod 7 = {}", mod_inverse(3, 7).unwrap());
println!(" 17⁻¹ mod 43 = {}", mod_inverse(17, 43).unwrap());
println!(" 2^10 mod 1000 = {}", mod_pow(2, 10, 1000));
let r: Vec<BigInt> = vec![2.into(), 3.into(), 2.into()];
let m: Vec<BigInt> = vec![3.into(), 5.into(), 7.into()];
println!(
" CRT: x ≡ 2 (mod 3), x ≡ 3 (mod 5), x ≡ 2 (mod 7) → x = {}",
crt(&r, &m).unwrap()
);
println!(
" CRT (i64): same → x = {}",
crt_i64(&[2, 3, 2], &[3, 5, 7]).unwrap()
);
println!("\nPerfect squares:");
println!(" is_square(144) = {}", is_square(144));
println!(" is_square(145) = {}", is_square(145));
println!(" isqrt(50) = {}", isqrt(50).unwrap());
println!("\nLegendre symbol (a/p):");
println!(" (2/7) = {}", legendre_symbol(2, 7));
println!(" (3/7) = {}", legendre_symbol(3, 7));
println!("\nExpression-level factorization:");
let n = ctx.int(360);
if let Some(factors) = n.factorize() {
let s: Vec<String> = factors
.iter()
.map(|(p, e)| {
if *e == 1 {
format!("{p}")
} else {
format!("{p}^{e}")
}
})
.collect();
println!(" 360 = {}", s.join(" × "));
}
println!("\nExpression-level primality:");
let n = ctx.int(104729);
println!(" Is 104729 prime? {:?}", n.is_prime_value());
let n = ctx.int(2_147_483_647);
println!(" Is 2147483647 (M31) prime? {:?}", n.is_prime_value());
let n = ctx.int(60);
println!(" Is 60 prime? {:?}", n.is_prime_value());
let half = ctx.rational(1, 2);
println!(" Is 1/2 prime? {:?}", half.is_prime_value());
println!("\n✓ Done!");
}
fn print_factors(n: i64, factors: &[(BigInt, u32)]) {
let s: Vec<String> = factors
.iter()
.map(|(p, e)| {
if *e == 1 {
format!("{p}")
} else {
format!("{p}^{e}")
}
})
.collect();
println!(" {n} = {}", s.join(" × "));
}
fn print_factors_big(n: &BigInt, factors: &[(BigInt, u32)]) {
let s: Vec<String> = factors
.iter()
.map(|(p, e)| {
if *e == 1 {
format!("{p}")
} else {
format!("{p}^{e}")
}
})
.collect();
println!(" {n} = {}", s.join(" × "));
}