1#[macro_use]
2extern crate log;
3
4use traceidr::TraceId;
5use std::fmt;
6
7fn u64_sqrt(n: u64) -> u64 {
8 if n == 0 || n == 1 {
9 return n;
10 }
11
12 let mut i = 0;
13 let mut result = 0;
14
15 while result <= n {
16 i += 1;
17 result = i * i;
18 }
19
20 return i - 1;
21}
22
23#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Debug)]
24struct U128 {
25 hi: u64,
26 lo: u64,
27}
28
29fn modulo(mut a: U128, m: u64) -> u64 {
30 if a.hi >= m {
31 a.hi -= (a.hi / m) * m;
32 }
33 let mut x = a.hi;
34 let mut y = a.lo;
35 for _ in 0..64 {
36 let t = (x as i64 >> 63) as u64;
37 x = (x << 1) | (y >> 63);
38 y <<= 1;
39 if (x | t) >= m {
40 x = x.wrapping_sub(m);
41 y += 1;
42 }
43 }
44 x
45}
46fn mul128(u: u64, v: u64) -> U128 {
47 let u1 = u >> 32;
48 let u0 = u & (!0 >> 32);
49 let v1 = v >> 32;
50 let v0 = v & (!0 >> 32);
51
52 let t = u0 * v0;
53 let w0 = t & (!0 >> 32);
54 let k = t >> 32;
55
56 let t = u1 * v0 + k;
57 let w1 = t & (!0 >> 32);
58 let w2 = t >> 32;
59
60 let t = u0 * v1 + w1;
61 let k = t >> 32;
62 U128 {
63 lo: (t << 32) + w0,
64 hi: u1 * v1 + w2 + k,
65 }
66}
67fn mod_mul_(a: u64, b: u64, m: u64) -> u64 {
68 modulo(mul128(a, b), m)
69}
70
71fn mod_mul(a: u64, b: u64, m: u64) -> u64 {
72 match a.checked_mul(b) {
73 Some(r) => {
74 if r >= m {
75 r % m
76 } else {
77 r
78 }
79 }
80 None => mod_mul_(a, b, m),
81 }
82}
83
84fn mod_sqr(a: u64, m: u64) -> u64 {
85 if a < (1 << 32) {
86 let r = a * a;
87 if r >= m {
88 r % m
89 } else {
90 r
91 }
92 } else {
93 mod_mul_(a, a, m)
94 }
95}
96
97fn mod_exp(mut x: u64, mut d: u64, n: u64) -> u64 {
98 let mut ret: u64 = 1;
99 while d != 0 {
100 if d % 2 == 1 {
101 ret = mod_mul(ret, x, n)
102 }
103 d /= 2;
104 x = mod_sqr(x, n);
105 }
106 ret
107}
108
109fn miller_rabin(n: u64) -> bool {
110 const HINT: &'static [u64] = &[2];
111
112 const WITNESSES: &'static [(u64, &'static [u64])] = &[
117 (2_046, HINT),
118 (1_373_652, &[2, 3]),
119 (9_080_190, &[31, 73]),
120 (25_326_000, &[2, 3, 5]),
121 (4_759_123_140, &[2, 7, 61]),
122 (1_112_004_669_632, &[2, 13, 23, 1662803]),
123 (2_152_302_898_746, &[2, 3, 5, 7, 11]),
124 (3_474_749_660_382, &[2, 3, 5, 7, 11, 13]),
125 (341_550_071_728_320, &[2, 3, 5, 7, 11, 13, 17]),
126 (0xFFFF_FFFF_FFFF_FFFF, &[2, 3, 5, 7, 11, 13, 17, 19, 23]),
127 ];
128
129 let trace = TraceId::new();
130 debug!(
131 "Running Miller-Rabin test for the number {} with TraceId {}. This is an expensive task.",
132 n, trace
133 );
134
135 if n % 2 == 0 {
136 return n == 2;
137 }
138 if n == 1 {
139 return false;
140 }
141
142 let mut d = n - 1;
143 let mut s = 0;
144 while d % 2 == 0 {
145 d /= 2;
146 s += 1
147 }
148
149 let witnesses = WITNESSES
150 .iter()
151 .find(|&&(hi, _)| hi >= n)
152 .map(|&(_, wtnss)| wtnss)
153 .unwrap();
154 'next_witness: for &a in witnesses.iter() {
155 let mut power = mod_exp(a, d, n);
156 assert!(power < n);
157 if power == 1 || power == n - 1 {
158 continue 'next_witness;
159 }
160
161 for _r in 0..s {
162 power = mod_sqr(power, n);
163 assert!(power < n);
164 if power == 1 {
165 return false;
166 }
167 if power == n - 1 {
168 continue 'next_witness;
169 }
170 }
171 debug!(
172 "Miller-Rabin test completed for number {} with TraceId {} with a result of false.",
173 n, trace
174 );
175 return false;
176 }
177
178 debug!(
179 "Miller-Rabin test completed for number {} with TraceId {} with a result of true.",
180 n, trace
181 );
182 true
183}
184
185fn is_prime(num: u64) -> bool {
186 let trace = TraceId::new();
187 debug!(
188 "Running primality tests for {} with TraceId {}.",
189 num, trace
190 );
191 let is_prime = miller_rabin(num);
192 debug!(
193 "Primality test for number {} with TraceId {} produced result {}.",
194 num, trace, is_prime
195 );
196 is_prime
197}
198
199pub struct Factors {
200 inner: Vec<u64>,
201}
202
203impl Factors {
204 fn new() -> Self {
205 Self {
206 inner: Vec::new(),
207 }
208 }
209
210 fn add(&mut self, f: u64) {
211 self.inner.push(f);
212 }
213}
214
215impl fmt::Display for Factors {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 let mut flag = false;
218 for (i, factor) in self.inner.iter().enumerate() {
219 if flag {
220 write!(f, "* {}", factor)?;
221 } else {
222 flag = true;
223 write!(f, "{}", factor)?;
224 }
225 if i != self.inner.len() - 1 {
226 write!(f, " ")?;
227 }
228 }
229 Ok(())
230 }
231}
232
233pub fn factorize_to_primes(mut num: u64) -> Factors {
234 let trace = TraceId::new();
235 debug!("Factorizing number {} with TraceId {}.", num, trace);
236 let mut factors = Factors::new();
237
238 if is_prime(num) {
239 debug!(
240 "Number passed primality test. Returning as is. TraceId {}.",
241 trace
242 );
243 factors.add(num);
244 return factors;
245 } else {
246 debug!(
247 "Number did not pass primality test. Continuing. TraceId {}.",
248 trace
249 );
250 }
251
252 while num % 2 == 0 {
253 factors.add(2);
254 num /= 2;
255 }
256
257 let mut i = 3;
258 let e = u64_sqrt(num);
259 while i <= e {
260 while num % i == 0 {
261 factors.add(i);
262 num /= i;
263 }
264
265 i += 2;
266 }
267
268 if num > 2 {
269 factors.add(num);
270 }
271
272 debug!(
273 "Finished factorization of number {} with TraceId {}.",
274 num, trace
275 );
276
277 factors
278}