1use alloc::string::{String, ToString};
9use alloc::vec;
10use alloc::vec::Vec;
11
12#[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#[must_use]
43#[inline]
44pub fn gcd_n(xs: &[u64]) -> u64 {
45 xs.iter().copied().fold(0, gcd)
46}
47
48#[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#[must_use]
77#[inline]
78pub fn lcm_n(xs: &[u64]) -> u64 {
79 xs.iter().copied().fold(1, lcm)
80}
81
82#[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#[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#[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#[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#[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#[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#[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#[must_use]
263#[inline]
264pub fn binomial(n: u64, k: u64) -> u128 {
265 checked_binomial(n, k).unwrap_or(u128::MAX)
266}
267
268#[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#[must_use]
307#[inline]
308pub fn factorial(n: u64) -> u128 {
309 checked_factorial(n).unwrap_or(u128::MAX)
310}
311
312#[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#[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#[must_use]
367#[inline]
368pub const fn is_even(n: u64) -> bool {
369 n.is_multiple_of(2)
370}
371
372#[must_use]
384#[inline]
385pub const fn is_odd(n: u64) -> bool {
386 !n.is_multiple_of(2)
387}
388
389#[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#[must_use]
435#[inline]
436pub const fn next_power_of_two(n: u64) -> u64 {
437 n.next_power_of_two()
438}
439
440#[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#[must_use]
484pub const fn log2_floor(n: u64) -> u32 {
485 if n == 0 {
486 return 0;
487 }
488 n.ilog2()
489}
490
491#[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#[must_use]
530#[inline]
531pub const fn popcount(n: u64) -> u32 {
532 n.count_ones()
533}
534
535#[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#[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#[must_use]
599#[inline]
600pub fn is_palindrome_base(n: u64, base: u32) -> bool {
601 n == reverse_digits_base(n, base)
602}
603
604#[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#[must_use]
632#[inline]
633pub const fn is_power_of_two(n: u64) -> bool {
634 n.is_power_of_two()
635}
636
637#[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#[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#[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#[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#[must_use]
751#[inline]
752pub fn is_coprime(a: u64, b: u64) -> bool {
753 gcd(a, b) == 1
754}
755
756#[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#[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#[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#[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#[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#[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#[must_use]
937#[inline]
938pub fn prime_count(n: u64) -> usize {
939 sieve_of_eratosthenes(n as usize).len()
940}
941
942#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[must_use]
1162#[inline]
1163pub fn is_squarefree(n: u64) -> bool {
1164 prime_factorization(n).iter().all(|(_, e)| *e == 1)
1165}
1166
1167#[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#[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#[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#[must_use]
1232#[inline]
1233pub fn is_palindrome(n: u64) -> bool {
1234 n == reverse_digits(n)
1235}
1236
1237#[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#[must_use]
1271#[inline]
1272pub fn from_digits(digits: &[u64]) -> u64 {
1273 digits.iter().fold(0u64, |acc, &d| acc * 10 + d)
1274}
1275
1276#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[must_use]
1653#[inline]
1654pub fn radical(n: u64) -> u64 {
1655 prime_factors(n).iter().product()
1656}
1657
1658#[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#[must_use]
1684pub fn primorial(p: u64) -> u64 {
1685 sieve_of_eratosthenes(p as usize)
1686 .iter()
1687 .copied()
1688 .product()
1689}
1690
1691#[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#[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#[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#[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#[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
1849fn 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#[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}