Skip to main content

mathverse_core/
integer.rs

1//! Core integer algorithms: GCD, LCM, modular arithmetic, root-finding,
2//! prime utilities, combinatorics, digit operations, and special numbers.
3//!
4//! These are the fundamental building blocks used across number theory,
5//! combinatorics, and cryptography. Canonical home for all integer math —
6//! `algorithms.rs` re-exports from here.
7
8use alloc::vec;
9use alloc::vec::Vec;
10
11/// Greatest common divisor (Euclidean algorithm).
12///
13/// # Examples
14///
15/// ```
16/// use mathverse_core::integer::gcd;
17///
18/// assert_eq!(gcd(48, 18), 6);
19/// assert_eq!(gcd(17, 5), 1);
20/// assert_eq!(gcd(0, 5), 5);
21/// ```
22#[must_use]
23pub fn gcd(mut a: u64, mut b: u64) -> u64 {
24    while b != 0 {
25        let t = b;
26        b = a % b;
27        a = t;
28    }
29    a
30}
31
32/// Greatest common divisor of `n` numbers.
33///
34/// # Examples
35///
36/// ```
37/// use mathverse_core::integer::gcd_n;
38///
39/// assert_eq!(gcd_n(&[48, 18, 24]), 6);
40/// ```
41#[must_use]
42pub fn gcd_n(xs: &[u64]) -> u64 {
43    xs.iter().copied().fold(0, gcd)
44}
45
46/// Least common multiple. Returns 0 for `lcm(0, x)`.
47///
48/// # Examples
49///
50/// ```
51/// use mathverse_core::integer::lcm;
52///
53/// assert_eq!(lcm(4, 6), 12);
54/// assert_eq!(lcm(0, 5), 0);
55/// ```
56#[must_use]
57pub fn lcm(a: u64, b: u64) -> u64 {
58    if a == 0 || b == 0 {
59        0
60    } else {
61        a / gcd(a, b) * b
62    }
63}
64
65/// Least common multiple of `n` numbers.
66///
67/// # Examples
68///
69/// ```
70/// use mathverse_core::integer::lcm_n;
71///
72/// assert_eq!(lcm_n(&[4, 6, 8]), 24);
73/// ```
74#[must_use]
75pub fn lcm_n(xs: &[u64]) -> u64 {
76    xs.iter().copied().fold(1, lcm)
77}
78
79/// Extended Euclidean algorithm: returns `(g, x, y)` such that
80/// `a*x + b*y = g = gcd(a, b)`.
81///
82/// # Examples
83///
84/// ```
85/// use mathverse_core::integer::extended_gcd;
86///
87/// let (g, x, y) = extended_gcd(48, 18);
88/// assert_eq!(g, 6);
89/// assert_eq!(48 * x + 18 * y, 6);
90/// ```
91#[must_use]
92pub fn extended_gcd(a: i64, b: i64) -> (u64, i64, i64) {
93    if b == 0 {
94        return (u64::try_from(a).unwrap_or(0), 1, 0);
95    }
96    let (g, x1, y1) = extended_gcd(b, a % b);
97    (g, y1, x1 - (a / b) * y1)
98}
99
100/// Bezout coefficients: returns `(x, y)` such that `a*x + b*y = gcd(a, b)`.
101///
102/// # Examples
103///
104/// ```
105/// use mathverse_core::integer::bezout_coefficients;
106///
107/// let (x, y) = bezout_coefficients(48, 18);
108/// assert_eq!(48 * x + 18 * y, 6);
109/// ```
110#[must_use]
111#[inline]
112pub fn bezout_coefficients(a: i64, b: i64) -> (i64, i64) {
113    let (_, x, y) = extended_gcd(a, b);
114    (x, y)
115}
116
117/// Modular multiplicative inverse: `a^-1 mod m`.
118///
119/// Returns `None` if `a` and `m` are not coprime.
120///
121/// # Examples
122///
123/// ```
124/// use mathverse_core::integer::modular_inverse;
125///
126/// assert_eq!(modular_inverse(3, 11), Some(4)); // 3 * 4 = 12 ≡ 1 (mod 11)
127/// assert_eq!(modular_inverse(2, 4), None);
128/// ```
129#[must_use]
130pub fn modular_inverse(a: u64, m: u64) -> Option<u64> {
131    if m == 0 {
132        return None;
133    }
134    let a = a % m;
135    let (g, x, _) = extended_gcd(a as i64, m as i64);
136    if g != 1 {
137        return None;
138    }
139    let result = ((x % m as i64) + m as i64) % m as i64;
140    Some(result as u64)
141}
142
143/// Modular exponentiation: `base^exp mod m` (exponentiation by squaring).
144///
145/// `m == 0` returns 0.
146///
147/// # Examples
148///
149/// ```
150/// use mathverse_core::integer::mod_pow;
151///
152/// assert_eq!(mod_pow(2, 10, 1000), 24);
153/// assert_eq!(mod_pow(3, 0, 7), 1);
154/// ```
155#[must_use]
156pub fn mod_pow(base: u64, mut exp: u64, m: u64) -> u64 {
157    if m == 0 {
158        return 0;
159    }
160    let m = u128::from(m);
161    let mut base = u128::from(base) % m;
162    let mut result: u128 = 1 % m;
163    while exp > 0 {
164        if exp & 1 == 1 {
165            result = result * base % m;
166        }
167        base = base * base % m;
168        exp >>= 1;
169    }
170    result as u64
171}
172
173/// Integer square root: `floor(sqrt(n))`.
174///
175/// # Examples
176///
177/// ```
178/// use mathverse_core::integer::isqrt;
179///
180/// assert_eq!(isqrt(16), 4);
181/// assert_eq!(isqrt(17), 4);
182/// assert_eq!(isqrt(0), 0);
183/// ```
184#[must_use]
185pub fn isqrt(n: u64) -> u64 {
186    if n == 0 {
187        return 0;
188    }
189    let mut x = n;
190    let mut y = x.div_ceil(2);
191    while y < x {
192        x = y;
193        y = u64::midpoint(x, n / x);
194    }
195    x
196}
197
198/// Integer square root with remainder: returns `(floor(sqrt(n)), n - floor(sqrt(n))^2)`.
199///
200/// # Examples
201///
202/// ```
203/// use mathverse_core::integer::isqrt_rem;
204///
205/// assert_eq!(isqrt_rem(17), (4, 1));
206/// assert_eq!(isqrt_rem(16), (4, 0));
207/// ```
208#[must_use]
209#[inline]
210pub fn isqrt_rem(n: u64) -> (u64, u64) {
211    let s = isqrt(n);
212    (s, n - s * s)
213}
214
215/// Check if `n` is a perfect square.
216///
217/// # Examples
218///
219/// ```
220/// use mathverse_core::integer::is_square;
221///
222/// assert!(is_square(16));
223/// assert!(!is_square(15));
224/// ```
225#[must_use]
226#[inline]
227pub fn is_square(n: u64) -> bool {
228    if n == 0 {
229        return true;
230    }
231    let s = isqrt(n);
232    s * s == n
233}
234
235/// Binomial coefficient `n choose k`. `k > n` returns 0.
236///
237/// For overflow-safe computation, use [`checked_binomial`].
238///
239/// # Examples
240///
241/// ```
242/// use mathverse_core::integer::binomial;
243///
244/// assert_eq!(binomial(10, 3), 120);
245/// assert_eq!(binomial(5, 0), 1);
246/// ```
247#[must_use]
248pub fn binomial(n: u64, k: u64) -> u128 {
249    checked_binomial(n, k).unwrap_or(u128::MAX)
250}
251
252/// Binomial coefficient `n choose k`, returning `None` on overflow.
253/// `k > n` returns `Some(0)`.
254///
255/// # Examples
256///
257/// ```
258/// use mathverse_core::integer::checked_binomial;
259///
260/// assert_eq!(checked_binomial(10, 3), Some(120));
261/// assert_eq!(checked_binomial(5, 0), Some(1));
262/// assert_eq!(checked_binomial(5, 6), Some(0));
263/// ```
264#[must_use]
265pub fn checked_binomial(n: u64, k: u64) -> Option<u128> {
266    if k > n {
267        return Some(0);
268    }
269    let k = k.min(n - k);
270    let mut acc: u128 = 1;
271    for i in 1..=k {
272        acc = acc.checked_mul(u128::from(n - k + i))?;
273        acc /= u128::from(i);
274    }
275    Some(acc)
276}
277
278/// `n!` as `u128` (exact up to `n = 34`; larger wraps silently).
279///
280/// For overflow-safe computation, use [`checked_factorial`].
281///
282/// # Examples
283///
284/// ```
285/// use mathverse_core::integer::factorial;
286///
287/// assert_eq!(factorial(5), 120);
288/// assert_eq!(factorial(0), 1);
289/// ```
290#[must_use]
291pub fn factorial(n: u64) -> u128 {
292    checked_factorial(n).unwrap_or(u128::MAX)
293}
294
295/// `n!` as `u128`, returning `None` on overflow.
296/// Exact for `n <= 34`; returns `None` for `n >= 35`.
297///
298/// # Examples
299///
300/// ```
301/// use mathverse_core::integer::checked_factorial;
302///
303/// assert_eq!(checked_factorial(5), Some(120));
304/// assert_eq!(checked_factorial(0), Some(1));
305/// assert_eq!(checked_factorial(35), None);
306/// ```
307#[must_use]
308pub fn checked_factorial(n: u64) -> Option<u128> {
309    let mut acc: u128 = 1;
310    for i in 2..=n {
311        acc = acc.checked_mul(u128::from(i))?;
312    }
313    Some(acc)
314}
315
316/// Ceiling integer log base 2: smallest `k` such that `2^k >= n`.
317/// Returns 0 for `n == 0`.
318///
319/// # Examples
320///
321/// ```
322/// use mathverse_core::integer::log2_ceil;
323///
324/// assert_eq!(log2_ceil(1), 0);
325/// assert_eq!(log2_ceil(2), 1);
326/// assert_eq!(log2_ceil(3), 2);
327/// assert_eq!(log2_ceil(8), 3);
328/// assert_eq!(log2_ceil(9), 4);
329/// ```
330#[must_use]
331pub const fn log2_ceil(n: u64) -> u32 {
332    if n <= 1 {
333        return 0;
334    }
335    64 - (n - 1).leading_zeros()
336}
337
338/// Returns `true` if `n` is even.
339///
340/// # Examples
341///
342/// ```
343/// use mathverse_core::integer::is_even;
344///
345/// assert!(is_even(4));
346/// assert!(!is_even(7));
347/// assert!(is_even(0));
348/// ```
349#[must_use]
350#[inline]
351pub const fn is_even(n: u64) -> bool {
352    n.is_multiple_of(2)
353}
354
355/// Returns `true` if `n` is odd.
356///
357/// # Examples
358///
359/// ```
360/// use mathverse_core::integer::is_odd;
361///
362/// assert!(is_odd(7));
363/// assert!(!is_odd(4));
364/// assert!(!is_odd(0));
365/// ```
366#[must_use]
367#[inline]
368pub const fn is_odd(n: u64) -> bool {
369    !n.is_multiple_of(2)
370}
371
372/// Check if `n` is a perfect cube: `n = k^3` for some integer `k`.
373///
374/// # Examples
375///
376/// ```
377/// use mathverse_core::integer::is_cube;
378///
379/// assert!(is_cube(27));
380/// assert!(is_cube(0));
381/// assert!(!is_cube(10));
382/// ```
383#[must_use]
384pub fn is_cube(n: u64) -> bool {
385    if n == 0 {
386        return true;
387    }
388    let mut lo = 1u64;
389    let mut hi = n.min(u64::MAX / 2 + 1);
390    while lo <= hi {
391        let mid = u64::midpoint(lo, hi);
392        let cube = mid.saturating_mul(mid).saturating_mul(mid);
393        if cube == n {
394            return true;
395        } else if cube < n {
396            lo = mid + 1;
397        } else if mid == 0 {
398            break;
399        } else {
400            hi = mid - 1;
401        }
402    }
403    false
404}
405
406/// Smallest power of two `>= n`. Returns 0 for `n == 0`.
407///
408/// # Examples
409///
410/// ```
411/// use mathverse_core::integer::next_power_of_two;
412///
413/// assert_eq!(next_power_of_two(5), 8);
414/// assert_eq!(next_power_of_two(8), 8);
415/// ```
416#[must_use]
417#[inline]
418pub const fn next_power_of_two(n: u64) -> u64 {
419    n.next_power_of_two()
420}
421
422/// Nearest power of two to `n`. Ties round toward even (e.g. 3 -> 4, 5 -> 4).
423///
424/// # Examples
425///
426/// ```
427/// use mathverse_core::integer::nearest_power_of_two;
428///
429/// assert_eq!(nearest_power_of_two(1), 1);
430/// assert_eq!(nearest_power_of_two(3), 4);
431/// assert_eq!(nearest_power_of_two(5), 4);
432/// assert_eq!(nearest_power_of_two(6), 8);
433/// assert_eq!(nearest_power_of_two(0), 1);
434/// ```
435#[must_use]
436pub fn nearest_power_of_two(n: u64) -> u64 {
437    if n <= 1 {
438        return 1;
439    }
440    let floor = 1u64 << (n - 1).ilog2();
441    let ceil = floor.saturating_mul(2);
442    let d_floor = n - floor;
443    let d_ceil = ceil - n;
444    match d_floor.cmp(&d_ceil) {
445        core::cmp::Ordering::Less => floor,
446        _ => ceil,
447    }
448}
449
450/// Floor integer log base 2: largest `k` such that `2^k <= n`.
451/// Returns 0 for `n == 0`.
452///
453/// # Examples
454///
455/// ```
456/// use mathverse_core::integer::log2_floor;
457///
458/// assert_eq!(log2_floor(0), 0);
459/// assert_eq!(log2_floor(1), 0);
460/// assert_eq!(log2_floor(2), 1);
461/// assert_eq!(log2_floor(3), 1);
462/// assert_eq!(log2_floor(7), 2);
463/// assert_eq!(log2_floor(8), 3);
464/// ```
465#[must_use]
466pub const fn log2_floor(n: u64) -> u32 {
467    if n == 0 {
468        return 0;
469    }
470    n.ilog2()
471}
472
473/// Integer log base `base`: largest `k` such that `base^k <= n`.
474/// Returns 0 for `n == 0` or `base <= 1`.
475///
476/// # Examples
477///
478/// ```
479/// use mathverse_core::integer::log_base;
480///
481/// assert_eq!(log_base(0, 10), 0);
482/// assert_eq!(log_base(100, 10), 2);
483/// assert_eq!(log_base(26, 26), 1);
484/// assert_eq!(log_base(27, 3), 3);
485/// ```
486#[must_use]
487pub fn log_base(n: u64, base: u64) -> u32 {
488    if n == 0 || base <= 1 {
489        return 0;
490    }
491    let mut count = 0u32;
492    let mut val = n;
493    while val >= base {
494        val /= base;
495        count += 1;
496    }
497    count
498}
499
500/// Population count: number of set bits (1-bits) in `n`.
501///
502/// # Examples
503///
504/// ```
505/// use mathverse_core::integer::popcount;
506///
507/// assert_eq!(popcount(0), 0);
508/// assert_eq!(popcount(7), 3);
509/// assert_eq!(popcount(u64::MAX), 64);
510/// ```
511#[must_use]
512#[inline]
513pub const fn popcount(n: u64) -> u32 {
514    n.count_ones()
515}
516
517/// Number of digits of `n` in the given `base` (2-36).
518/// `digit_count_base(0, 10)` returns 1.
519///
520/// # Examples
521///
522/// ```
523/// use mathverse_core::integer::digit_count_base;
524///
525/// assert_eq!(digit_count_base(0, 10), 1);
526/// assert_eq!(digit_count_base(255, 16), 2);
527/// assert_eq!(digit_count_base(8, 2), 4);
528/// ```
529#[must_use]
530pub fn digit_count_base(n: u64, base: u32) -> usize {
531    if base < 2 {
532        return 0;
533    }
534    if n == 0 {
535        return 1;
536    }
537    let mut count = 0;
538    let mut val = n;
539    while val > 0 {
540        val /= u64::from(base);
541        count += 1;
542    }
543    count
544}
545
546/// Reverse the digits of `n` in the given `base` (2-36).
547///
548/// # Examples
549///
550/// ```
551/// use mathverse_core::integer::reverse_digits_base;
552///
553/// assert_eq!(reverse_digits_base(123, 10), 321);
554/// assert_eq!(reverse_digits_base(0b1101, 2), 0b1011);
555/// ```
556#[must_use]
557pub fn reverse_digits_base(mut n: u64, base: u32) -> u64 {
558    if base < 2 {
559        return n;
560    }
561    let mut reversed = 0u64;
562    while n > 0 {
563        reversed = reversed * u64::from(base) + n % u64::from(base);
564        n /= u64::from(base);
565    }
566    reversed
567}
568
569/// Check if `n` is a palindrome in the given `base` (2-36).
570///
571/// # Examples
572///
573/// ```
574/// use mathverse_core::integer::is_palindrome_base;
575///
576/// assert!(is_palindrome_base(121, 10));
577/// assert!(!is_palindrome_base(123, 10));
578/// assert!(is_palindrome_base(9, 2)); // 1001 in binary
579/// ```
580#[must_use]
581#[inline]
582pub fn is_palindrome_base(n: u64, base: u32) -> bool {
583    n == reverse_digits_base(n, base)
584}
585
586/// Sum of squares without overflow: `a^2 + b^2` computed in `u128`.
587///
588/// # Examples
589///
590/// ```
591/// use mathverse_core::integer::sum_of_squares;
592///
593/// assert_eq!(sum_of_squares(3, 4), 25);
594/// assert_eq!(sum_of_squares(0, 5), 25);
595/// assert_eq!(sum_of_squares(u64::MAX, 1), u64::MAX as u128 * u64::MAX as u128 + 1);
596/// ```
597#[must_use]
598#[inline]
599pub fn sum_of_squares(a: u64, b: u64) -> u128 {
600    u128::from(a) * u128::from(a) + u128::from(b) * u128::from(b)
601}
602
603/// `true` if `n` is a power of two (1, 2, 4, ...). `0` is not.
604///
605/// # Examples
606///
607/// ```
608/// use mathverse_core::integer::is_power_of_two;
609///
610/// assert!(is_power_of_two(16));
611/// assert!(!is_power_of_two(10));
612/// ```
613#[must_use]
614#[inline]
615pub const fn is_power_of_two(n: u64) -> bool {
616    n.is_power_of_two()
617}
618
619/// `n`-th Mersenne number: `2^n - 1`.
620///
621/// # Examples
622///
623/// ```
624/// use mathverse_core::integer::mersenne_number;
625///
626/// assert_eq!(mersenne_number(3), 7);
627/// ```
628#[must_use]
629#[inline]
630pub const fn mersenne_number(n: u32) -> u64 {
631    (1u64 << n) - 1
632}
633
634/// `n`-th Fermat number: `2^(2^n) + 1`.
635///
636/// # Examples
637///
638/// ```
639/// use mathverse_core::integer::fermat_number;
640///
641/// assert_eq!(fermat_number(0), 3);
642/// assert_eq!(fermat_number(1), 5);
643/// ```
644#[must_use]
645#[inline]
646pub const fn fermat_number(n: u32) -> u128 {
647    (1u128 << (1u32 << n)) + 1
648}
649
650/// Check if `n` is a power of `base`.
651///
652/// # Examples
653///
654/// ```
655/// use mathverse_core::integer::is_power_of;
656///
657/// assert!(is_power_of(8, 2));
658/// assert!(is_power_of(27, 3));
659/// assert!(!is_power_of(10, 2));
660/// ```
661#[must_use]
662pub const fn is_power_of(n: u64, base: u64) -> bool {
663    if n == 0 || base == 0 {
664        return false;
665    }
666    if n == 1 {
667        return true;
668    }
669    let mut n = n;
670    while n.is_multiple_of(base) {
671        n /= base;
672    }
673    n == 1
674}
675
676/// Euler's totient function phi(n): count of integers <= n that are coprime to n.
677///
678/// # Examples
679///
680/// ```
681/// use mathverse_core::integer::euler_phi;
682///
683/// assert_eq!(euler_phi(9), 6);
684/// assert_eq!(euler_phi(7), 6);
685/// ```
686#[must_use]
687pub fn euler_phi(n: u64) -> u64 {
688    if n == 0 {
689        return 0;
690    }
691    let mut result = n;
692    let mut temp = n;
693    let mut p = 2u64;
694    while p * p <= temp {
695        if temp.is_multiple_of(p) {
696            while temp.is_multiple_of(p) {
697                temp /= p;
698            }
699            result -= result / p;
700        }
701        p += 1;
702    }
703    if temp > 1 {
704        result -= result / temp;
705    }
706    result
707}
708
709/// Check if `a` and `b` are coprime (gcd == 1).
710///
711/// # Examples
712///
713/// ```
714/// use mathverse_core::integer::is_coprime;
715///
716/// assert!(is_coprime(8, 9));
717/// assert!(!is_coprime(8, 12));
718/// ```
719#[must_use]
720#[inline]
721pub fn is_coprime(a: u64, b: u64) -> bool {
722    gcd(a, b) == 1
723}
724
725/// Chinese Remainder Theorem solver.
726///
727/// Given residues `r` and moduli `m`, find `x` such that `x ≡ r_i (mod m_i)`.
728/// Returns `None` if moduli are not pairwise coprime.
729///
730/// # Examples
731///
732/// ```
733/// use mathverse_core::integer::chinese_remainder;
734///
735/// let r = chinese_remainder(&[2, 3, 2], &[3, 5, 7]);
736/// assert_eq!(r, Some(23));
737/// ```
738#[must_use]
739pub fn chinese_remainder(residues: &[u64], moduli: &[u64]) -> Option<u64> {
740    if residues.len() != moduli.len() || moduli.is_empty() {
741        return None;
742    }
743    let total_mod: u128 = moduli.iter().map(|&m| u128::from(m)).product();
744    let mut result: u128 = 0;
745    for i in 0..moduli.len() {
746        let m_i = u128::from(moduli[i]);
747        let r_i = u128::from(residues[i]);
748        let m_div = total_mod / m_i;
749        let inv = modular_inverse(m_div as u64, moduli[i])?;
750        result = (result + r_i * m_div % total_mod * u128::from(inv) % total_mod) % total_mod;
751    }
752    Some(result as u64)
753}
754
755/// `n`-th Fibonacci number (`F_0 = 0, F_1 = 1`) as `u128` (exact up to n = 184).
756///
757/// # Examples
758///
759/// ```
760/// use mathverse_core::integer::fibonacci;
761///
762/// assert_eq!(fibonacci(0), 0);
763/// assert_eq!(fibonacci(1), 1);
764/// assert_eq!(fibonacci(10), 55);
765/// ```
766#[must_use]
767pub fn fibonacci(n: u64) -> u128 {
768    if n == 0 {
769        return 0;
770    }
771    let (mut a, mut b) = (0u128, 1u128);
772    for _ in 1..n {
773        let t = a + b;
774        a = b;
775        b = t;
776    }
777    b
778}
779
780/// Trial-division primality test.
781///
782/// For large-scale primality testing, prefer [`is_prime_miller_rabin`].
783///
784/// # Examples
785///
786/// ```
787/// use mathverse_core::integer::is_prime;
788///
789/// assert!(is_prime(7));
790/// assert!(!is_prime(4));
791/// assert!(!is_prime(1));
792/// ```
793// ponytail: naive O(sqrt(n)); swap to Miller-Rabin when big primes matter.
794#[must_use]
795pub fn is_prime(n: u64) -> bool {
796    if n < 2 {
797        return false;
798    }
799    if n.is_multiple_of(2) {
800        return n == 2;
801    }
802    let mut d = 3u64;
803    while u128::from(d) * u128::from(d) <= u128::from(n) {
804        if n.is_multiple_of(d) {
805            return false;
806        }
807        d += 2;
808    }
809    true
810}
811
812/// All primes `<= n`.
813///
814/// # Examples
815///
816/// ```
817/// use mathverse_core::integer::sieve_of_eratosthenes;
818///
819/// assert_eq!(sieve_of_eratosthenes(20).len(), 8);
820/// assert_eq!(sieve_of_eratosthenes(2), vec![2]);
821/// ```
822#[must_use]
823pub fn sieve_of_eratosthenes(n: usize) -> Vec<u64> {
824    let mut prime = vec![true; n + 1];
825    prime[0] = false;
826    if n >= 1 {
827        prime[1] = false;
828    }
829    let mut p = 2usize;
830    while p * p <= n {
831        if prime[p] {
832            let mut m = p * p;
833            while m <= n {
834                prime[m] = false;
835                m += p;
836            }
837        }
838        p += 1;
839    }
840    (2..=n)
841        .filter(|&i| prime[i])
842        .map(|i| i as u64)
843        .collect()
844}
845
846/// Prime factorization of `n`: returns a vector of `(prime, exponent)` pairs.
847///
848/// # Examples
849///
850/// ```
851/// use mathverse_core::integer::prime_factorization;
852///
853/// assert_eq!(prime_factorization(60), vec![(2, 2), (3, 1), (5, 1)]);
854/// assert_eq!(prime_factorization(1), vec![]);
855/// ```
856#[must_use]
857pub fn prime_factorization(n: u64) -> Vec<(u64, u32)> {
858    if n <= 1 {
859        return vec![];
860    }
861    let mut factors = vec![];
862    let mut n = n;
863    let mut p = 2u64;
864    while p * p <= n {
865        if n.is_multiple_of(p) {
866            let mut count = 0u32;
867            while n.is_multiple_of(p) {
868                n /= p;
869                count += 1;
870            }
871            factors.push((p, count));
872        }
873        p += 1;
874    }
875    if n > 1 {
876        factors.push((n, 1));
877    }
878    factors
879}
880
881/// Distinct prime factors of `n`.
882///
883/// # Examples
884///
885/// ```
886/// use mathverse_core::integer::prime_factors;
887///
888/// assert_eq!(prime_factors(60), vec![2, 3, 5]);
889/// ```
890#[must_use]
891#[inline]
892pub fn prime_factors(n: u64) -> Vec<u64> {
893    prime_factorization(n).into_iter().map(|(p, _)| p).collect()
894}
895
896/// Count of primes <= `n` (prime-counting function pi(n)).
897///
898/// # Examples
899///
900/// ```
901/// use mathverse_core::integer::prime_count;
902///
903/// assert_eq!(prime_count(20), 8);
904/// ```
905#[must_use]
906#[inline]
907pub fn prime_count(n: u64) -> usize {
908    sieve_of_eratosthenes(n as usize).len()
909}
910
911/// Next prime after `n`.
912///
913/// # Examples
914///
915/// ```
916/// use mathverse_core::integer::next_prime;
917///
918/// assert_eq!(next_prime(10), 11);
919/// assert_eq!(next_prime(2), 3);
920/// assert_eq!(next_prime(1), 2);
921/// ```
922#[must_use]
923pub fn next_prime(n: u64) -> u64 {
924    if n < 2 {
925        return 2;
926    }
927    let mut candidate = if n.is_multiple_of(2) { n + 1 } else { n + 2 };
928    while !is_prime(candidate) {
929        candidate += 2;
930    }
931    candidate
932}
933
934/// Largest prime strictly less than `n`.
935///
936/// # Examples
937///
938/// ```
939/// use mathverse_core::integer::prev_prime;
940///
941/// assert_eq!(prev_prime(13), Some(11));
942/// assert_eq!(prev_prime(2), None);
943/// ```
944#[must_use]
945pub fn prev_prime(n: u64) -> Option<u64> {
946    if n <= 2 {
947        return None;
948    }
949    let mut candidate = if n.is_multiple_of(2) { n - 1 } else { n - 2 };
950    loop {
951        if is_prime(candidate) {
952            return Some(candidate);
953        }
954        if candidate <= 2 {
955            return Some(2);
956        }
957        candidate -= 2;
958    }
959}
960
961/// The `n`-th prime (1-indexed: 1st prime = 2).
962///
963/// # Examples
964///
965/// ```
966/// use mathverse_core::integer::nth_prime;
967///
968/// assert_eq!(nth_prime(1), Some(2));
969/// assert_eq!(nth_prime(6), Some(13));
970/// assert_eq!(nth_prime(0), None);
971/// ```
972#[must_use]
973pub fn nth_prime(n: usize) -> Option<u64> {
974    if n == 0 {
975        return None;
976    }
977    let mut count = 0;
978    let mut candidate = 1u64;
979    while count < n {
980        candidate = next_prime(candidate);
981        count += 1;
982    }
983    Some(candidate)
984}
985
986/// Check if `n` is a triangular number: `n = k(k+1)/2`.
987///
988/// # Examples
989///
990/// ```
991/// use mathverse_core::integer::is_triangular;
992///
993/// assert!(is_triangular(6));
994/// assert!(is_triangular(0));
995/// assert!(!is_triangular(5));
996/// ```
997#[must_use]
998pub fn is_triangular(n: u64) -> bool {
999    if n == 0 {
1000        return true;
1001    }
1002    let d = 8 * n + 1;
1003    is_square(d) && {
1004        let s = isqrt(d);
1005        (s - 1).is_multiple_of(2)
1006    }
1007}
1008
1009/// Check if `n` is a Harshad (Niven) number: divisible by sum of its digits.
1010///
1011/// # Examples
1012///
1013/// ```
1014/// use mathverse_core::integer::is_harshad;
1015///
1016/// assert!(is_harshad(18));
1017/// assert!(!is_harshad(16));
1018/// ```
1019#[must_use]
1020#[inline]
1021pub fn is_harshad(n: u64) -> bool {
1022    if n == 0 {
1023        return false;
1024    }
1025    let s = digit_sum(n);
1026    n.is_multiple_of(s)
1027}
1028
1029/// Check if `n` is an Armstrong (Narcissistic) number:
1030/// `n = sum of its digits each raised to the power of the number of digits`.
1031///
1032/// # Examples
1033///
1034/// ```
1035/// use mathverse_core::integer::is_armstrong;
1036///
1037/// assert!(is_armstrong(153));
1038/// assert!(!is_armstrong(154));
1039/// ```
1040#[must_use]
1041pub fn is_armstrong(n: u64) -> bool {
1042    let digits = to_digits(n);
1043    let k = digits.len() as u32;
1044    let sum: u64 = digits.iter().map(|&d| d.pow(k)).sum();
1045    sum == n
1046}
1047
1048/// Check if `n` is a perfect number: sum of its proper divisors equals `n`.
1049///
1050/// # Examples
1051///
1052/// ```
1053/// use mathverse_core::integer::is_perfect_number;
1054///
1055/// assert!(is_perfect_number(6));
1056/// assert!(is_perfect_number(28));
1057/// ```
1058#[must_use]
1059pub fn is_perfect_number(n: u64) -> bool {
1060    if n < 2 {
1061        return false;
1062    }
1063    divisor_sum(n) - n == n
1064}
1065
1066/// Check if `n` is an abundant number: sum of proper divisors > `n`.
1067///
1068/// # Examples
1069///
1070/// ```
1071/// use mathverse_core::integer::is_abundant;
1072///
1073/// assert!(is_abundant(12));
1074/// ```
1075#[must_use]
1076pub fn is_abundant(n: u64) -> bool {
1077    if n < 2 {
1078        return false;
1079    }
1080    divisor_sum(n) - n > n
1081}
1082
1083/// Check if `n` is a deficient number: sum of proper divisors < `n`.
1084///
1085/// # Examples
1086///
1087/// ```
1088/// use mathverse_core::integer::is_deficient;
1089///
1090/// assert!(is_deficient(8));
1091/// ```
1092#[must_use]
1093pub fn is_deficient(n: u64) -> bool {
1094    if n < 2 {
1095        return false;
1096    }
1097    divisor_sum(n) - n < n
1098}
1099
1100/// Check if `n` is a semiprime: product of exactly two primes (not necessarily distinct).
1101///
1102/// # Examples
1103///
1104/// ```
1105/// use mathverse_core::integer::is_semiprime;
1106///
1107/// assert!(is_semiprime(6));
1108/// assert!(is_semiprime(9));
1109/// assert!(!is_semiprime(8));
1110/// ```
1111#[must_use]
1112pub fn is_semiprime(n: u64) -> bool {
1113    let factors = prime_factorization(n);
1114    let total: u32 = factors.iter().map(|(_, e)| e).sum();
1115    total == 2
1116}
1117
1118/// Check if `n` is squarefree: no repeated prime factors.
1119///
1120/// # Examples
1121///
1122/// ```
1123/// use mathverse_core::integer::is_squarefree;
1124///
1125/// assert!(is_squarefree(30));
1126/// assert!(!is_squarefree(18));
1127/// ```
1128#[must_use]
1129pub fn is_squarefree(n: u64) -> bool {
1130    prime_factorization(n).iter().all(|(_, e)| *e == 1)
1131}
1132
1133/// Sum of decimal digits of `n`.
1134///
1135/// # Examples
1136///
1137/// ```
1138/// use mathverse_core::integer::digit_sum;
1139///
1140/// assert_eq!(digit_sum(12345), 15);
1141/// ```
1142#[must_use]
1143#[inline]
1144pub fn digit_sum(n: u64) -> u64 {
1145    to_digits(n).iter().sum()
1146}
1147
1148/// Number of decimal digits in `n`.
1149///
1150/// # Examples
1151///
1152/// ```
1153/// use mathverse_core::integer::digit_count;
1154///
1155/// assert_eq!(digit_count(0), 1);
1156/// assert_eq!(digit_count(999), 3);
1157/// ```
1158#[must_use]
1159pub fn digit_count(n: u64) -> usize {
1160    if n == 0 {
1161        1
1162    } else {
1163        n.ilog10() as usize + 1
1164    }
1165}
1166
1167/// Reverse the decimal digits of `n`.
1168///
1169/// # Examples
1170///
1171/// ```
1172/// use mathverse_core::integer::reverse_digits;
1173///
1174/// assert_eq!(reverse_digits(12345), 54321);
1175/// ```
1176#[must_use]
1177pub fn reverse_digits(n: u64) -> u64 {
1178    let digits = to_digits(n);
1179    from_digits(&digits.iter().rev().copied().collect::<Vec<_>>())
1180}
1181
1182/// Check if `n` is a decimal palindrome.
1183///
1184/// # Examples
1185///
1186/// ```
1187/// use mathverse_core::integer::is_palindrome;
1188///
1189/// assert!(is_palindrome(12321));
1190/// assert!(!is_palindrome(12345));
1191/// ```
1192#[must_use]
1193#[inline]
1194pub fn is_palindrome(n: u64) -> bool {
1195    n == reverse_digits(n)
1196}
1197
1198/// Convert `n` to a vector of decimal digits (most significant first).
1199///
1200/// # Examples
1201///
1202/// ```
1203/// use mathverse_core::integer::to_digits;
1204///
1205/// assert_eq!(to_digits(123), vec![1, 2, 3]);
1206/// assert_eq!(to_digits(0), vec![0]);
1207/// ```
1208#[must_use]
1209pub fn to_digits(n: u64) -> Vec<u64> {
1210    if n == 0 {
1211        return vec![0];
1212    }
1213    let mut digits = vec![];
1214    let mut n = n;
1215    while n > 0 {
1216        digits.insert(0, n % 10);
1217        n /= 10;
1218    }
1219    digits
1220}
1221
1222/// Reconstruct a number from decimal digits (most significant first).
1223///
1224/// # Examples
1225///
1226/// ```
1227/// use mathverse_core::integer::from_digits;
1228///
1229/// assert_eq!(from_digits(&[1, 2, 3]), 123);
1230/// ```
1231#[must_use]
1232pub fn from_digits(digits: &[u64]) -> u64 {
1233    digits.iter().fold(0u64, |acc, &d| acc * 10 + d)
1234}
1235
1236/// Convert `n` to a string in the given `base` (2-36).
1237///
1238/// # Examples
1239///
1240/// ```
1241/// use mathverse_core::integer::to_base;
1242///
1243/// assert_eq!(to_base(255, 16), "ff");
1244/// assert_eq!(to_base(10, 2), "1010");
1245/// ```
1246#[must_use]
1247pub fn to_base(n: u64, base: u32) -> String {
1248    if !(2..=36).contains(&base) {
1249        return String::new();
1250    }
1251    if n == 0 {
1252        return "0".to_string();
1253    }
1254    let chars = "0123456789abcdefghijklmnopqrstuvwxyz";
1255    let mut digits = vec![];
1256    let mut n = n;
1257    while n > 0 {
1258        digits.push(chars.chars().nth((n % u64::from(base)) as usize).unwrap());
1259        n /= u64::from(base);
1260    }
1261    digits.iter().rev().collect()
1262}
1263
1264/// Parse a string in the given `base` (2-36) to `u64`.
1265///
1266/// # Examples
1267///
1268/// ```
1269/// use mathverse_core::integer::from_base;
1270///
1271/// assert_eq!(from_base("ff", 16), Some(255));
1272/// assert_eq!(from_base("1010", 2), Some(10));
1273/// ```
1274#[must_use]
1275pub fn from_base(s: &str, base: u32) -> Option<u64> {
1276    if !(2..=36).contains(&base) {
1277        return None;
1278    }
1279    let chars = "0123456789abcdefghijklmnopqrstuvwxyz";
1280    let s = s.to_lowercase();
1281    let mut result: u64 = 0;
1282    for c in s.chars() {
1283        let digit = chars.find(c)? as u64;
1284        if digit >= u64::from(base) {
1285            return None;
1286        }
1287        result = result * u64::from(base) + digit;
1288    }
1289    Some(result)
1290}
1291
1292/// Generate the first `n` rows of Pascal's triangle.
1293///
1294/// # Examples
1295///
1296/// ```
1297/// use mathverse_core::integer::pascal_triangle;
1298///
1299/// let pt = pascal_triangle(4);
1300/// assert_eq!(pt[3], vec![1, 3, 3, 1]);
1301/// ```
1302#[must_use]
1303pub fn pascal_triangle(n: usize) -> Vec<Vec<u128>> {
1304    let mut triangle: Vec<Vec<u128>> = vec![];
1305    for i in 0..n {
1306        let mut row = vec![1u128; i + 1];
1307        if i >= 2 {
1308            for j in 1..i {
1309                row[j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
1310            }
1311        }
1312        triangle.push(row);
1313    }
1314    triangle
1315}
1316
1317/// `n`-th Lucas number (`L_0 = 2, L_1 = 1, L_n = L_{n-1} + L_{n-2}`).
1318///
1319/// # Examples
1320///
1321/// ```
1322/// use mathverse_core::integer::lucas_number;
1323///
1324/// assert_eq!(lucas_number(0), 2);
1325/// assert_eq!(lucas_number(1), 1);
1326/// assert_eq!(lucas_number(4), 7);
1327/// ```
1328#[must_use]
1329pub fn lucas_number(n: u64) -> u128 {
1330    if n == 0 {
1331        return 2;
1332    }
1333    if n == 1 {
1334        return 1;
1335    }
1336    let (mut a, mut b) = (2u128, 1u128);
1337    for _ in 2..=n {
1338        let t = a + b;
1339        a = b;
1340        b = t;
1341    }
1342    b
1343}
1344
1345/// `n`-th Tribonacci number (`T_0 = 0, T_1 = 0, T_2 = 1, T_n = T_{n-1} + T_{n-2} + T_{n-3}`).
1346///
1347/// # Examples
1348///
1349/// ```
1350/// use mathverse_core::integer::tribonacci;
1351///
1352/// assert_eq!(tribonacci(0), 0);
1353/// assert_eq!(tribonacci(3), 1);
1354/// assert_eq!(tribonacci(4), 2);
1355/// ```
1356#[must_use]
1357pub fn tribonacci(n: u64) -> u128 {
1358    if n == 0 || n == 1 {
1359        return 0;
1360    }
1361    if n == 2 {
1362        return 1;
1363    }
1364    let (mut a, mut b, mut c) = (0u128, 0u128, 1u128);
1365    for _ in 3..=n {
1366        let t = a + b + c;
1367        a = b;
1368        b = c;
1369        c = t;
1370    }
1371    c
1372}
1373
1374/// `n`-th Catalan number: `C(n) = (1/(n+1)) * C(2n, n)`.
1375///
1376/// # Examples
1377///
1378/// ```
1379/// use mathverse_core::integer::catalan_number;
1380///
1381/// assert_eq!(catalan_number(0), 1);
1382/// assert_eq!(catalan_number(3), 5);
1383/// assert_eq!(catalan_number(5), 42);
1384/// ```
1385#[must_use]
1386pub fn catalan_number(n: u64) -> u128 {
1387    if n == 0 {
1388        return 1;
1389    }
1390    binomial(2 * n, n) / u128::from(n + 1)
1391}
1392
1393/// Number of integer partitions of `n` (partition function p(n)).
1394///
1395/// Uses Euler's pentagonal number theorem recurrence.
1396/// Time complexity: O(n^2). For large `n` (>200), consider memoization.
1397///
1398/// # Examples
1399///
1400/// ```
1401/// use mathverse_core::integer::partition_number;
1402///
1403/// assert_eq!(partition_number(0), 1);
1404/// assert_eq!(partition_number(4), 5);
1405/// assert_eq!(partition_number(5), 7);
1406/// ```
1407#[must_use]
1408pub fn partition_number(n: u64) -> u128 {
1409    if n == 0 {
1410        return 1;
1411    }
1412    let mut partitions = vec![0u128; n as usize + 1];
1413    partitions[0] = 1;
1414    for i in 1..=n as usize {
1415        let mut sum: i128 = 0;
1416        let mut k = 1u64;
1417        loop {
1418            let pent1 = (k * (3 * k - 1) / 2) as usize;
1419            if pent1 > i {
1420                break;
1421            }
1422            let sign: i128 = if k % 2 == 1 { 1 } else { -1 };
1423            sum += sign * partitions[i - pent1] as i128;
1424            let pent2 = (k * (3 * k + 1) / 2) as usize;
1425            if pent2 <= i {
1426                sum += sign * partitions[i - pent2] as i128;
1427            }
1428            k += 1;
1429        }
1430        partitions[i] = sum as u128;
1431    }
1432    partitions[n as usize]
1433}
1434
1435/// Unsigned Stirling numbers of the first kind: `s(n, k)`.
1436///
1437/// Counts permutations of `n` elements with `k` disjoint cycles.
1438/// Time complexity: O(n*k). Results grow fast — may overflow `u128` for `n > 34`.
1439///
1440/// # Examples
1441///
1442/// ```
1443/// use mathverse_core::integer::stirling_first;
1444///
1445/// assert_eq!(stirling_first(4, 2), 11);
1446/// ```
1447// ponytail: recursive implementation; memoize if profiling shows hot path.
1448#[must_use]
1449pub fn stirling_first(n: u64, k: u64) -> u128 {
1450    if k > n || k == 0 {
1451        return u128::from(n == 0 && k == 0);
1452    }
1453    if k == n {
1454        return 1;
1455    }
1456    stirling_first(n - 1, k - 1) + u128::from(n - 1) * stirling_first(n - 1, k)
1457}
1458
1459/// Stirling numbers of the second kind: `S(n, k)`.
1460///
1461/// Counts ways to partition `n` elements into `k` non-empty subsets.
1462/// Time complexity: O(n*k). Results grow fast — may overflow `u128` for `n > 34`.
1463///
1464/// # Examples
1465///
1466/// ```
1467/// use mathverse_core::integer::stirling_second;
1468///
1469/// assert_eq!(stirling_second(4, 2), 7);
1470/// ```
1471// ponytail: recursive implementation; memoize if profiling shows hot path.
1472#[must_use]
1473pub fn stirling_second(n: u64, k: u64) -> u128 {
1474    if k > n || k == 0 {
1475        return u128::from(n == 0 && k == 0);
1476    }
1477    if k == 1 || k == n {
1478        return 1;
1479    }
1480    stirling_second(n - 1, k - 1) + u128::from(k) * stirling_second(n - 1, k)
1481}
1482
1483/// `n`-th Bell number: total partitions of a set of n elements.
1484///
1485/// # Examples
1486///
1487/// ```
1488/// use mathverse_core::integer::bell_number;
1489///
1490/// assert_eq!(bell_number(0), 1);
1491/// assert_eq!(bell_number(3), 5);
1492/// assert_eq!(bell_number(4), 15);
1493/// ```
1494#[must_use]
1495pub fn bell_number(n: u64) -> u128 {
1496    let mut row = vec![1u128];
1497    for i in 1..=n {
1498        let mut next = vec![0u128; (i + 1) as usize];
1499        next[0] = *row.last().unwrap();
1500        for j in 1..=i as usize {
1501            next[j] = next[j - 1] + row[j - 1];
1502        }
1503        row = next;
1504    }
1505    row[0]
1506}
1507
1508/// Subfactorial (derangement number): `!n = n! * sum(k=0..n) (-1)^k / k!`.
1509///
1510/// # Examples
1511///
1512/// ```
1513/// use mathverse_core::integer::subfactorial;
1514///
1515/// assert_eq!(subfactorial(0), 1);
1516/// assert_eq!(subfactorial(1), 0);
1517/// assert_eq!(subfactorial(4), 9);
1518/// ```
1519#[must_use]
1520pub fn subfactorial(n: u64) -> u128 {
1521    if n == 0 {
1522        return 1;
1523    }
1524    if n == 1 {
1525        return 0;
1526    }
1527    let mut d = vec![0u128; n as usize + 1];
1528    d[0] = 1;
1529    d[1] = 0;
1530    for i in 2..=n as usize {
1531        d[i] = (i as u128 - 1) * (d[i - 1] + d[i - 2]);
1532    }
1533    d[n as usize]
1534}
1535
1536/// Number of permutations: `P(n, r) = n! / (n - r)!`.
1537///
1538/// # Examples
1539///
1540/// ```
1541/// use mathverse_core::integer::permutation_count;
1542///
1543/// assert_eq!(permutation_count(5, 3), 60);
1544/// assert_eq!(permutation_count(5, 0), 1);
1545/// assert_eq!(permutation_count(3, 5), 0);
1546/// ```
1547#[must_use]
1548pub fn permutation_count(n: u64, r: u64) -> u128 {
1549    if r > n {
1550        return 0;
1551    }
1552    let mut result: u128 = 1;
1553    for i in (n - r + 1)..=n {
1554        result *= u128::from(i);
1555    }
1556    result
1557}
1558
1559/// Number of divisors: `d(n)` or `tau(n)`.
1560///
1561/// # Examples
1562///
1563/// ```
1564/// use mathverse_core::integer::divisor_count;
1565///
1566/// assert_eq!(divisor_count(12), 6);
1567/// ```
1568#[must_use]
1569pub fn divisor_count(n: u64) -> u64 {
1570    let factors = prime_factorization(n);
1571    factors
1572        .iter()
1573        .map(|(_, e)| u64::from(e + 1))
1574        .product()
1575}
1576
1577/// Sum of divisors: `sigma(n)`.
1578///
1579/// # Examples
1580///
1581/// ```
1582/// use mathverse_core::integer::divisor_sum;
1583///
1584/// assert_eq!(divisor_sum(6), 12);
1585/// ```
1586#[must_use]
1587pub fn divisor_sum(n: u64) -> u64 {
1588    let factors = prime_factorization(n);
1589    factors
1590        .iter()
1591        .map(|(p, e)| {
1592            let mut sum = 1u64;
1593            let mut power = 1u64;
1594            for _ in 0..*e {
1595                power *= p;
1596                sum += power;
1597            }
1598            sum
1599        })
1600        .product()
1601}
1602
1603/// Radical (square-free kernel): product of distinct prime factors.
1604///
1605/// # Examples
1606///
1607/// ```
1608/// use mathverse_core::integer::radical;
1609///
1610/// assert_eq!(radical(18), 6);
1611/// ```
1612#[must_use]
1613pub fn radical(n: u64) -> u64 {
1614    prime_factors(n).iter().product()
1615}
1616
1617/// Check if `n` is a smooth number: all prime factors <= `bound`.
1618///
1619/// # Examples
1620///
1621/// ```
1622/// use mathverse_core::integer::is_smooth;
1623///
1624/// assert!(is_smooth(12, 3));
1625/// assert!(!is_smooth(12, 2));
1626/// ```
1627#[must_use]
1628pub fn is_smooth(n: u64, bound: u64) -> bool {
1629    prime_factors(n).iter().all(|&p| p <= bound)
1630}
1631
1632/// Primorial: product of primes <= `p`.
1633///
1634/// # Examples
1635///
1636/// ```
1637/// use mathverse_core::integer::primorial;
1638///
1639/// assert_eq!(primorial(5), 30);
1640/// ```
1641#[must_use]
1642pub fn primorial(p: u64) -> u64 {
1643    sieve_of_eratosthenes(p as usize)
1644        .iter()
1645        .copied()
1646        .product()
1647}
1648
1649/// Mobius function mu(n):
1650/// - 1 if n is squarefree with an even number of prime factors
1651/// - -1 if n is squarefree with an odd number of prime factors
1652/// - 0 if n has a repeated prime factor
1653///
1654/// # Examples
1655///
1656/// ```
1657/// use mathverse_core::integer::mobius;
1658///
1659/// assert_eq!(mobius(1), 1);
1660/// assert_eq!(mobius(2), -1);
1661/// assert_eq!(mobius(4), 0);
1662/// ```
1663#[must_use]
1664pub fn mobius(n: u64) -> i32 {
1665    if n == 0 {
1666        return 0;
1667    }
1668    let factors = prime_factorization(n);
1669    if factors.iter().any(|(_, e)| *e > 1) {
1670        return 0;
1671    }
1672    if factors.len().is_multiple_of(2) {
1673        1
1674    } else {
1675        -1
1676    }
1677}
1678
1679/// Liouville function lambda(n): `(-1)^Omega(n)` where Omega(n) = total number of prime factors with multiplicity.
1680///
1681/// # Examples
1682///
1683/// ```
1684/// use mathverse_core::integer::liouville;
1685///
1686/// assert_eq!(liouville(1), 1);
1687/// assert_eq!(liouville(6), 1);
1688/// assert_eq!(liouville(8), -1);
1689/// ```
1690#[must_use]
1691pub fn liouville(n: u64) -> i32 {
1692    if n == 0 {
1693        return 0;
1694    }
1695    let factors = prime_factorization(n);
1696    let total: u32 = factors.iter().map(|(_, e)| e).sum();
1697    if total.is_multiple_of(2) {
1698        1
1699    } else {
1700        -1
1701    }
1702}
1703
1704/// Double factorial: `n!! = n * (n-2) * (n-4) * ... * 1` (or 2).
1705///
1706/// # Examples
1707///
1708/// ```
1709/// use mathverse_core::integer::double_factorial;
1710///
1711/// assert_eq!(double_factorial(5), 15);
1712/// assert_eq!(double_factorial(6), 48);
1713/// ```
1714#[must_use]
1715pub fn double_factorial(n: u64) -> u128 {
1716    if n == 0 || n == 1 {
1717        return 1;
1718    }
1719    let mut result: u128 = 1;
1720    let mut k = n;
1721    while k >= 2 {
1722        result *= u128::from(k);
1723        k -= 2;
1724    }
1725    result
1726}
1727
1728/// Miller-Rabin probabilistic primality test.
1729///
1730/// Accuracy: `2^(-rounds)` probability of false positive.
1731/// Uses a simple PRNG seeded from `n` — not cryptographically secure.
1732///
1733/// # Examples
1734///
1735/// ```
1736/// use mathverse_core::integer::is_prime_miller_rabin;
1737///
1738/// assert!(is_prime_miller_rabin(97, 10));
1739/// assert!(!is_prime_miller_rabin(100, 10));
1740/// ```
1741#[must_use]
1742pub fn is_prime_miller_rabin(n: u64, rounds: u32) -> bool {
1743    if n < 2 {
1744        return false;
1745    }
1746    if n == 2 || n == 3 {
1747        return true;
1748    }
1749    if n.is_multiple_of(2) {
1750        return false;
1751    }
1752    let mut d = n - 1;
1753    let r = d.trailing_zeros();
1754    d >>= r;
1755    let mut rng_state = n.wrapping_mul(0x5DEECE66D);
1756    for _ in 0..rounds {
1757        let a = 2 + (rng_state % (n - 3));
1758        rng_state = rng_state
1759            .wrapping_mul(6364136223846793005)
1760            .wrapping_add(1442695040888963407);
1761        let mut x = mod_pow(a, d, n);
1762        if x == 1 || x == n - 1 {
1763            continue;
1764        }
1765        let mut composite = true;
1766        for _ in 1..r {
1767            x = (u128::from(x) * u128::from(x) % u128::from(n)) as u64;
1768            if x == n - 1 {
1769                composite = false;
1770                break;
1771            }
1772        }
1773        if composite {
1774            return false;
1775        }
1776    }
1777    true
1778}
1779
1780/// Check if `n` is a perfect power: `n = a^b` for some `a >= 2, b >= 2`.
1781///
1782/// # Examples
1783///
1784/// ```
1785/// use mathverse_core::integer::is_perfect_power;
1786///
1787/// assert!(is_perfect_power(8));
1788/// assert!(is_perfect_power(16));
1789/// assert!(!is_perfect_power(10));
1790/// ```
1791#[must_use]
1792pub fn is_perfect_power(n: u64) -> bool {
1793    if n < 4 {
1794        return false;
1795    }
1796    let mut b = 2u32;
1797    while u128::from(2u32).pow(b) <= u128::from(n) {
1798        let root = nth_root_u64(n, b);
1799        if root >= 2 && root.pow(b) == n {
1800            return true;
1801        }
1802        b += 1;
1803    }
1804    false
1805}
1806
1807/// Integer `n`-th root: `floor(n^(1/k))`.
1808fn nth_root_u64(n: u64, k: u32) -> u64 {
1809    if n == 0 {
1810        return 0;
1811    }
1812    if k == 0 {
1813        return 1;
1814    }
1815    if k == 1 {
1816        return n;
1817    }
1818    let mut lo: u64 = 1;
1819    let mut hi: u64 = n;
1820    while lo < hi {
1821        let mid = lo + (hi - lo).div_ceil(2);
1822        if mid.pow(k) <= n {
1823            lo = mid;
1824        } else {
1825            hi = mid - 1;
1826        }
1827    }
1828    lo
1829}
1830
1831/// Segmented sieve: all primes in `[lo, hi]`.
1832///
1833/// # Examples
1834///
1835/// ```
1836/// use mathverse_core::integer::segmented_sieve;
1837///
1838/// let primes = segmented_sieve(10, 30);
1839/// assert_eq!(primes, vec![11, 13, 17, 19, 23, 29]);
1840/// ```
1841#[must_use]
1842pub fn segmented_sieve(lo: u64, hi: u64) -> Vec<u64> {
1843    if hi < 2 || hi < lo {
1844        return vec![];
1845    }
1846    let limit = isqrt(hi) as usize;
1847    let small_primes = sieve_of_eratosthenes(limit);
1848    let mut is_prime = vec![true; (hi - lo + 1) as usize];
1849    for &p in &small_primes {
1850        let start = if lo <= p {
1851            p * p
1852        } else {
1853            lo.div_ceil(p) * p
1854        };
1855        let mut j = start;
1856        while j <= hi {
1857            if j >= lo {
1858                is_prime[(j - lo) as usize] = false;
1859            }
1860            j += p;
1861        }
1862    }
1863    (lo..=hi)
1864        .filter(|&i| i >= 2 && is_prime[(i - lo) as usize])
1865        .collect()
1866}
1867
1868#[cfg(test)]
1869mod tests {
1870    use super::*;
1871
1872    #[test]
1873    fn gcd_lcm_tests() {
1874        assert_eq!(gcd(48, 18), 6);
1875        assert_eq!(gcd(17, 5), 1);
1876        assert_eq!(gcd(0, 5), 5);
1877        assert_eq!(gcd_n(&[48, 18, 24]), 6);
1878        assert_eq!(lcm(4, 6), 12);
1879        assert_eq!(lcm(0, 5), 0);
1880        assert_eq!(lcm_n(&[4, 6, 8]), 24);
1881    }
1882
1883    #[test]
1884    fn extended_gcd_tests() {
1885        let (g, x, y) = extended_gcd(48, 18);
1886        assert_eq!(g, 6);
1887        assert_eq!(48 * x + 18 * y, 6);
1888    }
1889
1890    #[test]
1891    fn bezout_tests() {
1892        let (x, y) = bezout_coefficients(48, 18);
1893        assert_eq!(48 * x + 18 * y, 6);
1894    }
1895
1896    #[test]
1897    fn modular_inverse_tests() {
1898        assert_eq!(modular_inverse(3, 11), Some(4));
1899        assert_eq!(modular_inverse(2, 4), None);
1900    }
1901
1902    #[test]
1903    fn mod_pow_tests() {
1904        assert_eq!(mod_pow(2, 10, 1000), 24);
1905        assert_eq!(mod_pow(3, 0, 7), 1);
1906    }
1907
1908    #[test]
1909    fn isqrt_tests() {
1910        assert_eq!(isqrt(0), 0);
1911        assert_eq!(isqrt(1), 1);
1912        assert_eq!(isqrt(16), 4);
1913        assert_eq!(isqrt(17), 4);
1914        assert_eq!(isqrt_rem(17), (4, 1));
1915    }
1916
1917    #[test]
1918    fn is_square_tests() {
1919        assert!(is_square(0));
1920        assert!(is_square(1));
1921        assert!(is_square(16));
1922        assert!(!is_square(15));
1923    }
1924
1925    #[test]
1926    fn binomial_tests() {
1927        assert_eq!(binomial(10, 3), 120);
1928        assert_eq!(binomial(5, 0), 1);
1929        assert_eq!(binomial(3, 5), 0);
1930        assert_eq!(checked_binomial(10, 3), Some(120));
1931        assert_eq!(checked_binomial(5, 0), Some(1));
1932        assert_eq!(checked_binomial(3, 5), Some(0));
1933    }
1934
1935    #[test]
1936    fn factorial_tests() {
1937        assert_eq!(factorial(0), 1);
1938        assert_eq!(factorial(5), 120);
1939        assert_eq!(checked_factorial(0), Some(1));
1940        assert_eq!(checked_factorial(5), Some(120));
1941        assert_eq!(checked_factorial(34), Some(295232799039604140847618609643520000000));
1942        assert_eq!(checked_factorial(35), None);
1943    }
1944
1945    #[test]
1946    fn log2_ceil_tests() {
1947        assert_eq!(log2_ceil(0), 0);
1948        assert_eq!(log2_ceil(1), 0);
1949        assert_eq!(log2_ceil(2), 1);
1950        assert_eq!(log2_ceil(3), 2);
1951        assert_eq!(log2_ceil(8), 3);
1952        assert_eq!(log2_ceil(9), 4);
1953    }
1954
1955    #[test]
1956    fn is_even_is_odd_tests() {
1957        assert!(is_even(0));
1958        assert!(is_even(4));
1959        assert!(!is_even(7));
1960        assert!(!is_odd(0));
1961        assert!(is_odd(7));
1962        assert!(!is_odd(4));
1963    }
1964
1965    #[test]
1966    fn is_cube_tests() {
1967        assert!(is_cube(0));
1968        assert!(is_cube(1));
1969        assert!(is_cube(8));
1970        assert!(is_cube(27));
1971        assert!(is_cube(64));
1972        assert!(!is_cube(10));
1973        assert!(!is_cube(9));
1974    }
1975
1976    #[test]
1977    fn nearest_power_of_two_tests() {
1978        assert_eq!(nearest_power_of_two(0), 1);
1979        assert_eq!(nearest_power_of_two(1), 1);
1980        assert_eq!(nearest_power_of_two(2), 2);
1981        assert_eq!(nearest_power_of_two(3), 4);
1982        assert_eq!(nearest_power_of_two(4), 4);
1983        assert_eq!(nearest_power_of_two(5), 4);
1984        assert_eq!(nearest_power_of_two(6), 8);
1985        assert_eq!(nearest_power_of_two(7), 8);
1986        assert_eq!(nearest_power_of_two(8), 8);
1987    }
1988
1989    #[test]
1990    fn log2_floor_tests() {
1991        assert_eq!(log2_floor(0), 0);
1992        assert_eq!(log2_floor(1), 0);
1993        assert_eq!(log2_floor(2), 1);
1994        assert_eq!(log2_floor(3), 1);
1995        assert_eq!(log2_floor(7), 2);
1996        assert_eq!(log2_floor(8), 3);
1997        assert_eq!(log2_floor(15), 3);
1998        assert_eq!(log2_floor(16), 4);
1999    }
2000
2001    #[test]
2002    fn log_base_tests() {
2003        assert_eq!(log_base(0, 10), 0);
2004        assert_eq!(log_base(1, 10), 0);
2005        assert_eq!(log_base(9, 1), 0);
2006        assert_eq!(log_base(100, 10), 2);
2007        assert_eq!(log_base(26, 26), 1);
2008        assert_eq!(log_base(27, 3), 3);
2009        assert_eq!(log_base(63, 2), 5);
2010        assert_eq!(log_base(64, 2), 6);
2011    }
2012
2013    #[test]
2014    fn popcount_tests() {
2015        assert_eq!(popcount(0), 0);
2016        assert_eq!(popcount(1), 1);
2017        assert_eq!(popcount(7), 3);
2018        assert_eq!(popcount(8), 1);
2019        assert_eq!(popcount(u64::MAX), 64);
2020    }
2021
2022    #[test]
2023    fn digit_count_base_tests() {
2024        assert_eq!(digit_count_base(0, 10), 1);
2025        assert_eq!(digit_count_base(9, 10), 1);
2026        assert_eq!(digit_count_base(10, 10), 2);
2027        assert_eq!(digit_count_base(255, 16), 2);
2028        assert_eq!(digit_count_base(8, 2), 4);
2029        assert_eq!(digit_count_base(0, 2), 1);
2030    }
2031
2032    #[test]
2033    fn reverse_digits_base_tests() {
2034        assert_eq!(reverse_digits_base(123, 10), 321);
2035        assert_eq!(reverse_digits_base(0, 10), 0);
2036        assert_eq!(reverse_digits_base(0b1101, 2), 0b1011);
2037        assert_eq!(reverse_digits_base(0xff, 16), 0xff);
2038    }
2039
2040    #[test]
2041    fn is_palindrome_base_tests() {
2042        assert!(is_palindrome_base(121, 10));
2043        assert!(!is_palindrome_base(123, 10));
2044        assert!(is_palindrome_base(9, 2));
2045        assert!(is_palindrome_base(0, 10));
2046        assert!(is_palindrome_base(1, 10));
2047    }
2048
2049    #[test]
2050    fn sum_of_squares_tests() {
2051        assert_eq!(sum_of_squares(3, 4), 25);
2052        assert_eq!(sum_of_squares(0, 5), 25);
2053        assert_eq!(sum_of_squares(0, 0), 0);
2054    }
2055
2056    #[test]
2057    fn euler_phi_test() {
2058        assert_eq!(euler_phi(1), 1);
2059        assert_eq!(euler_phi(7), 6);
2060        assert_eq!(euler_phi(9), 6);
2061        assert_eq!(euler_phi(12), 4);
2062    }
2063
2064    #[test]
2065    fn coprime_test() {
2066        assert!(is_coprime(8, 9));
2067        assert!(!is_coprime(8, 12));
2068    }
2069
2070    #[test]
2071    fn crt_test() {
2072        let r = chinese_remainder(&[2, 3, 2], &[3, 5, 7]);
2073        assert_eq!(r, Some(23));
2074    }
2075
2076    #[test]
2077    fn fibonacci_test() {
2078        assert_eq!(fibonacci(0), 0);
2079        assert_eq!(fibonacci(1), 1);
2080        assert_eq!(fibonacci(10), 55);
2081    }
2082
2083    #[test]
2084    fn prime_utils() {
2085        assert!(is_prime(7));
2086        assert!(!is_prime(4));
2087        assert!(!is_prime(1));
2088        assert_eq!(next_prime(10), 11);
2089        assert_eq!(prev_prime(13), Some(11));
2090        assert_eq!(nth_prime(1), Some(2));
2091        assert_eq!(prime_count(20), 8);
2092    }
2093
2094    #[test]
2095    fn miller_rabin_test() {
2096        assert!(is_prime_miller_rabin(97, 10));
2097        assert!(!is_prime_miller_rabin(100, 10));
2098    }
2099
2100    #[test]
2101    fn prime_factorization_test() {
2102        assert_eq!(prime_factorization(60), vec![(2, 2), (3, 1), (5, 1)]);
2103        assert_eq!(prime_factors(60), vec![2, 3, 5]);
2104    }
2105
2106    #[test]
2107    fn triangular_test() {
2108        assert!(is_triangular(0));
2109        assert!(is_triangular(6));
2110        assert!(!is_triangular(5));
2111    }
2112
2113    #[test]
2114    fn harshad_test() {
2115        assert!(is_harshad(18));
2116        assert!(!is_harshad(16));
2117    }
2118
2119    #[test]
2120    fn armstrong_test() {
2121        assert!(is_armstrong(153));
2122        assert!(!is_armstrong(154));
2123    }
2124
2125    #[test]
2126    fn perfect_abundant_deficient() {
2127        assert!(is_perfect_number(6));
2128        assert!(is_abundant(12));
2129        assert!(is_deficient(8));
2130    }
2131
2132    #[test]
2133    fn semiprime_squarefree() {
2134        assert!(is_semiprime(6));
2135        assert!(is_squarefree(30));
2136        assert!(!is_squarefree(18));
2137    }
2138
2139    #[test]
2140    fn digit_ops() {
2141        assert_eq!(digit_sum(12345), 15);
2142        assert_eq!(digit_count(0), 1);
2143        assert_eq!(reverse_digits(12345), 54321);
2144        assert!(is_palindrome(12321));
2145        assert_eq!(to_digits(123), vec![1, 2, 3]);
2146        assert_eq!(from_digits(&[1, 2, 3]), 123);
2147        assert_eq!(to_base(255, 16), "ff");
2148        assert_eq!(from_base("ff", 16), Some(255));
2149    }
2150
2151    #[test]
2152    fn pascal_lucas_tribonacci_catalan() {
2153        let pt = pascal_triangle(5);
2154        assert_eq!(pt[3], vec![1, 3, 3, 1]);
2155        assert_eq!(lucas_number(0), 2);
2156        assert_eq!(tribonacci(0), 0);
2157        assert_eq!(catalan_number(5), 42);
2158    }
2159
2160    #[test]
2161    fn partition_stirling_bell() {
2162        assert_eq!(partition_number(0), 1);
2163        assert_eq!(stirling_second(4, 2), 7);
2164        assert_eq!(stirling_first(4, 2), 11);
2165        assert_eq!(bell_number(4), 15);
2166        assert_eq!(subfactorial(4), 9);
2167    }
2168
2169    #[test]
2170    fn divisor_functions() {
2171        assert_eq!(divisor_count(12), 6);
2172        assert_eq!(divisor_sum(6), 12);
2173        assert_eq!(radical(18), 6);
2174        assert!(is_smooth(12, 3));
2175    }
2176
2177    #[test]
2178    fn special_numbers() {
2179        assert_eq!(primorial(5), 30);
2180        assert_eq!(double_factorial(5), 15);
2181        assert_eq!(mobius(1), 1);
2182        assert_eq!(liouville(6), 1);
2183    }
2184
2185    #[test]
2186    fn segmented_sieve_test() {
2187        let primes = segmented_sieve(10, 30);
2188        assert_eq!(primes, vec![11, 13, 17, 19, 23, 29]);
2189    }
2190}