factor.rs

4.9 kB · rust · 235 lines

1// SIEVES23pub fn small_primes(limit: usize) -> Vec<u64> {4    let mut comp = vec![false; limit + 1];5    let mut primes = Vec::new();6    for i in 2..=limit {7        if !comp[i] {8            primes.push(i as u64);9            let mut j = i * i;10            while j <= limit {11                comp[j] = true;12                j += i;13            }14        }15    }16    primes17}1819pub fn mu_sieve(limit: usize) -> Vec<i8> {20    let mut mu = vec![0i8; limit + 1];21    let mut comp = vec![false; limit + 1];22    let mut primes: Vec<u32> = Vec::new();23    if limit >= 1 {24        mu[1] = 1;25    }26    for i in 2..=limit {27        if !comp[i] {28            primes.push(i as u32);29            mu[i] = -1;30        }31        for &p in &primes {32            let ip = i * p as usize;33            if ip > limit {34                break;35            }36            comp[ip] = true;37            if i % p as usize == 0 {38                mu[ip] = 0;39                break;40            }41            mu[ip] = -mu[i];42        }43    }44    mu45}4647// MODULAR ARITHMETIC4849fn mulmod(a: u64, b: u64, n: u64) -> u64 {50    ((a as u128 * b as u128) % n as u128) as u6451}5253fn powmod(mut a: u64, mut e: u64, n: u64) -> u64 {54    let mut r = 1u64 % n;55    a %= n;56    while e > 0 {57        if e & 1 == 1 {58            r = mulmod(r, a, n);59        }60        a = mulmod(a, a, n);61        e >>= 1;62    }63    r64}6566fn gcd(mut a: u64, mut b: u64) -> u64 {67    while b != 0 {68        let t = a % b;69        a = b;70        b = t;71    }72    a73}7475// PRIMALITY7677const WITNESSES: [u64; 12] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];7879pub fn is_prime(n: u64) -> bool {80    if n < 2 {81        return false;82    }83    for p in WITNESSES {84        if n == p {85            return true;86        }87        if n % p == 0 {88            return false;89        }90    }91    let mut d = n - 1;92    let mut s = 0;93    while d & 1 == 0 {94        d >>= 1;95        s += 1;96    }97    'witness: for a in WITNESSES {98        let mut x = powmod(a, d, n);99        if x == 1 || x == n - 1 {100            continue;101        }102        for _ in 1..s {103            x = mulmod(x, x, n);104            if x == n - 1 {105                continue 'witness;106            }107        }108        return false;109    }110    true111}112113// FACTOR SPLITTING114115pub fn isqrt(n: u64) -> u64 {116    let mut r = (n as f64).sqrt() as u64;117    while r > 0 && r as u128 * r as u128 > n as u128 {118        r -= 1;119    }120    while (r as u128 + 1) * (r as u128 + 1) <= n as u128 {121        r += 1;122    }123    r124}125126fn brent(n: u64) -> u64 {127    if n & 1 == 0 {128        return 2;129    }130    let mut c = 1u64;131    loop {132        let step = |x: u64| {133            let y = mulmod(x, x, n) + c;134            if y >= n {135                y - n136            } else {137                y138            }139        };140        let mut y = 2u64;141        let mut x = y;142        let mut ys = y;143        let mut q = 1u64;144        let mut d = 1u64;145        let mut r = 1u64;146        let m = 128u64;147        while d == 1 {148            x = y;149            for _ in 0..r {150                y = step(y);151            }152            let mut k = 0u64;153            while k < r && d == 1 {154                ys = y;155                for _ in 0..m.min(r - k) {156                    y = step(y);157                    q = mulmod(q, x.abs_diff(y), n);158                }159                d = gcd(q, n);160                k += m;161            }162            r <<= 1;163        }164        if d == n {165            loop {166                ys = step(ys);167                d = gcd(x.abs_diff(ys), n);168                if d > 1 {169                    break;170                }171            }172        }173        if d < n {174            return d;175        }176        c += 1;177    }178}179180// MOBIUS181182pub fn mobius(n: u64, primes: &[u64]) -> i8 {183    if n == 1 {184        return 1;185    }186    let mut m = n;187    let mut parity = 0u32;188    let mut settled = false;189    for &p in primes {190        if m == 1 || p * p > m {191            settled = true;192            break;193        }194        if m % p == 0 {195            m /= p;196            if m % p == 0 {197                return 0;198            }199            parity ^= 1;200        }201    }202    if m > 1 {203        if settled {204            parity ^= 1;205        } else {206            let mut stack = vec![m];207            let mut found: Vec<u64> = Vec::new();208            while let Some(x) = stack.pop() {209                if is_prime(x) {210                    found.push(x);211                    continue;212                }213                let r = isqrt(x);214                if r * r == x {215                    return 0;216                }217                let d = brent(x);218                stack.push(d);219                stack.push(x / d);220            }221            found.sort_unstable();222            for w in found.windows(2) {223                if w[0] == w[1] {224                    return 0;225                }226            }227            parity ^= found.len() as u32 & 1;228        }229    }230    if parity & 1 == 0 {231        1232    } else {233        -1234    }235}