-
Notifications
You must be signed in to change notification settings - Fork 0
/
prime-factors.rs
68 lines (59 loc) · 1.37 KB
/
prime-factors.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
macro_rules! repeat {
($body:block until $condition:expr) => (
loop {
$body
if $condition { break }
}
);
}
fn gcd(a: u32, b: u32) -> u32 {
if b == 0 { return a; }
gcd(b, a % b)
}
struct SmallCoprime {
number: u32,
coprime: u32
}
impl SmallCoprime {
fn init(number: u32) -> SmallCoprime {
SmallCoprime{ number, coprime: 1 }
}
fn even_period(&self) -> u32 {
let mut period = 2;
repeat!({
period += 2
} until self.coprime.pow(period) % self.number == 1);
period
}
fn factors(&self, period: u32) -> (u32, u32) {
let w = self.coprime.pow(period / 2);
let p = gcd(self.number, w + 1);
let q = gcd(self.number, w - 1);
(p, q)
}
}
impl Iterator for SmallCoprime {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.coprime >= self.number-1 { return None }
repeat!({
self.coprime += 1
} until gcd(self.number, self.coprime) == 1);
Some(self.coprime)
}
}
fn solve(number: u32) -> (u32, u32) {
let mut coprime = SmallCoprime::init(number);
let mut factors: (u32, u32);
repeat!({
coprime.next();
let period = coprime.even_period();
factors = coprime.factors(period);
} until factors.0 < number && factors.1 < number);
factors
}
fn main() {
for number in vec![15, 35, 65, 91] {
println!("The factors of {} are {:?}", number, solve(number));
}
}