Skip to content

Commit f58a573

Browse files
committed
Simplify funkcia a little bit
1 parent e1f098d commit f58a573

File tree

1 file changed

+18
-31
lines changed

1 file changed

+18
-31
lines changed

src/funkcia.rs

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,52 +36,38 @@ pub fn funkcia(a: i64, b: i64) -> u64 {
3636
let g = gcd_nodiv(a, b);
3737
debug_assert!(g % 2 == 1);
3838

39-
if g > 1 {
40-
debug_assert!(a % g == 0);
41-
debug_assert!(b % g == 0);
42-
// remove common factors with exponent 1
43-
a = a / g;
44-
b = b / g;
45-
debug_assert!(a % 2 == 1 && b % 2 == 1);
46-
47-
// if factor in a has higher exponent than in b, we need to divide a again by that factor
48-
// so we find the remaining common prime factors in a, and divide them out
49-
loop {
50-
let a_rem = gcd_nodiv(a, g); // get remaining prime factors of a
51-
if a_rem == 1 {
52-
break;
53-
}
54-
debug_assert!(a % a_rem == 0);
55-
a /= a_rem;
56-
}
57-
// and the same for b
58-
loop {
59-
let b_rem = gcd_nodiv(b, g); // get remaining prime factors of b
60-
if b_rem == 1 {
61-
break;
62-
}
63-
debug_assert!(b % b_rem == 0);
64-
b /= b_rem;
65-
}
39+
// g contains all common factors multiplied together (with some exponent)
40+
// we need to repeatedly divide `a` by the remaining factors from `g`
41+
// the remaining factors are found by `gcd(a / g, g)`
42+
let mut a_rem = g;
43+
while a_rem > 1 {
44+
a = a / a_rem;
45+
a_rem = gcd_nodiv(a, a_rem); // get remaining prime factors of a
46+
}
47+
// and the same for b
48+
let mut b_rem = g;
49+
while b_rem > 1 {
50+
b /= b_rem;
51+
b_rem = gcd_nodiv(b, b_rem); // get remaining prime factors of b
6652
}
6753

6854
debug_assert!(gcd(a, b) == 1);
69-
if a == b && prime_2_exp == 0 {
55+
if a == b && prime_2_exp == 0 { // a == b means that both are 1, because they cannot have common divisors
7056
return 0; // Pokiaľ je množina prvočísel prázdna, výsledkom je nula
7157
}
7258

7359
// Result is simply (a * b * 2^prime_2_exp) % MOD
7460
// We just need to be careful about i64 overflow (and minimizing number of modulos)
7561
if let Some(result) = a.checked_mul(b) {
76-
if result < MOD >> prime_2_exp {
62+
if result < (MOD >> prime_2_exp) {
7763
// no overflow
7864
debug_assert!(result.checked_mul(1 << prime_2_exp).unwrap() < MOD);
7965
result << prime_2_exp
80-
} else if prime_2_exp < 30 {
66+
} else if prime_2_exp < MOD.leading_zeros() {
8167
debug_assert!((result % MOD).checked_mul(1 << prime_2_exp).is_some());
8268
((result % MOD) << prime_2_exp) % MOD
8369
} else {
84-
(result % MOD).checked_mul((1 << prime_2_exp) % MOD).unwrap() % MOD
70+
((result % MOD) * ((1 << prime_2_exp) % MOD)) % MOD
8571
}
8672
} else {
8773
let a2 = a % MOD;
@@ -123,6 +109,7 @@ fn gcd_nodiv(mut a: u64, mut b: u64) -> u64 {
123109
}
124110

125111
debug_assert_eq!(a, gcd(a_orig, b_orig), "a_orig = {a_orig}, b_orig = {b_orig}");
112+
debug_assert!(a_orig % a == 0);
126113

127114
a
128115
}

0 commit comments

Comments
 (0)