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