1pub fn primes_up_to(n: usize) -> Vec<u64> {
15 if n < 2 {
16 return Vec::new();
17 }
18 let mut is_prime = vec![true; n + 1];
19 is_prime[0] = false;
20 is_prime[1] = false;
21 let mut i = 2usize;
22 while i * i <= n {
23 if is_prime[i] {
24 let mut j = i * i;
25 while j <= n {
26 is_prime[j] = false;
27 j += i;
28 }
29 }
30 i += 1;
31 }
32 (2..=n)
33 .filter(|&i| is_prime[i])
34 .map(|i| i as u64)
35 .collect()
36}
37
38pub fn first_n_primes(n: usize) -> Vec<u64> {
43 if n == 0 {
44 return Vec::new();
45 }
46 if n < 6 {
47 return primes_up_to(15).into_iter().take(n).collect();
49 }
50 let nf = n as f64;
51 let mut limit = (nf * (nf.ln() + nf.ln().ln()) * 1.3).ceil() as usize;
52 loop {
53 let primes = primes_up_to(limit);
54 if primes.len() >= n {
55 return primes.into_iter().take(n).collect();
56 }
57 limit *= 2;
58 }
59}
60
61pub fn factorize(mut n: u64) -> Vec<(u64, u32)> {
64 let mut factors = Vec::new();
65 if n < 2 {
66 return factors;
67 }
68 let mut d = 2u64;
69 while d * d <= n {
70 if n % d == 0 {
71 let mut exp = 0u32;
72 while n % d == 0 {
73 n /= d;
74 exp += 1;
75 }
76 factors.push((d, exp));
77 }
78 d += if d == 2 { 1 } else { 2 };
79 }
80 if n > 1 {
81 factors.push((n, 1));
82 }
83 factors
84}
85
86pub fn radical(n: u64) -> u64 {
89 if n == 0 {
90 return 0;
91 }
92 factorize(n)
93 .into_iter()
94 .map(|(p, _)| p)
95 .product::<u64>()
96 .max(1)
97}
98
99pub fn distinct_primes(n: u64) -> Vec<u64> {
101 factorize(n).into_iter().map(|(p, _)| p).collect()
102}
103
104pub fn gcd(mut a: u64, mut b: u64) -> u64 {
106 while b != 0 {
107 let t = b;
108 b = a % b;
109 a = t;
110 }
111 a
112}
113
114pub fn lcm(a: u64, b: u64) -> u64 {
116 if a == 0 || b == 0 {
117 return 0;
118 }
119 a / gcd(a, b) * b
120}
121
122pub fn extended_gcd(a: i64, b: i64) -> (i64, i64, i64) {
126 if b == 0 {
127 return (a.abs(), if a < 0 { -1 } else { 1 }, 0);
129 }
130 let (g, x, y) = extended_gcd(b, a % b);
131 (g, y, x - (a / b) * y)
132}
133
134pub fn mod_inverse(a: u64, m: u64) -> Option<u64> {
136 if m == 0 {
137 return None;
138 }
139 if m == 1 {
140 return Some(0);
141 }
142 let (g, x, _) = extended_gcd((a % m) as i64, m as i64);
143 if g != 1 {
144 return None;
145 }
146 let m_i = m as i64;
147 Some((((x % m_i) + m_i) % m_i) as u64)
148}
149
150pub fn termination_period(n: u64, base: u64) -> Option<u64> {
160 if n == 0 || base < 2 {
161 return None;
162 }
163 let mut coprime_part = n;
165 loop {
166 let g = gcd(coprime_part, base);
167 if g == 1 {
168 break;
169 }
170 coprime_part /= g;
171 }
172 if coprime_part == 1 {
173 return Some(0); }
175 let b = base % coprime_part;
177 let mut order = 1u64;
178 let mut acc = b % coprime_part;
179 while acc != 1 {
180 acc = (acc * b) % coprime_part;
181 order += 1;
182 }
183 Some(order)
184}
185
186pub fn natural_base(denominators: &[u64]) -> u64 {
190 denominators
191 .iter()
192 .filter(|&&d| d != 0)
193 .map(|&d| radical(d))
194 .fold(1u64, lcm)
195 .max(1)
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn sieve_basic() {
204 assert_eq!(primes_up_to(11), vec![2, 3, 5, 7, 11]);
205 assert!(primes_up_to(1).is_empty());
206 }
207
208 #[test]
209 fn first_n() {
210 assert_eq!(first_n_primes(5), vec![2, 3, 5, 7, 11]);
211 let p = first_n_primes(32);
212 assert_eq!(p.len(), 32);
213 assert_eq!(*p.last().unwrap(), 131); }
215
216 #[test]
217 fn factor() {
218 assert_eq!(factorize(12), vec![(2, 2), (3, 1)]);
219 assert_eq!(factorize(13), vec![(13, 1)]);
220 assert!(factorize(1).is_empty());
221 }
222
223 #[test]
224 fn radicals() {
225 assert_eq!(radical(12), 6);
226 assert_eq!(radical(1), 1);
227 assert_eq!(radical(30), 30);
228 }
229
230 #[test]
231 fn gcd_lcm() {
232 assert_eq!(gcd(12, 18), 6);
233 assert_eq!(lcm(4, 6), 12);
234 }
235
236 #[test]
237 fn egcd_and_inverse() {
238 let (g, x, y) = extended_gcd(240, 46);
239 assert_eq!(g, 2);
240 assert_eq!(240 * x + 46 * y, 2);
241 assert_eq!(mod_inverse(3, 11), Some(4)); assert_eq!(mod_inverse(2, 4), None);
243 }
244
245 #[test]
246 fn termination() {
247 assert_eq!(termination_period(8, 10), Some(0)); assert_eq!(termination_period(3, 10), Some(1)); assert_eq!(termination_period(7, 10), Some(6)); assert_eq!(termination_period(6, 10), Some(1)); }
252
253 #[test]
254 fn nat_base() {
255 assert_eq!(natural_base(&[6, 10, 15]), 30);
256 assert_eq!(natural_base(&[12]), 6);
257 }
258}