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}