modular_arithmetic/
arithmetic.rs1use std::u64;
2use std::i64;
3
4
5pub fn mod_add(a:u64, b:u64, q:u64) -> u64 {
6 let a0 = a % q;
7 let b0 = b % q;
8 let sum = a0.checked_add(b0);
9 match sum {
10 Some(x) => x % q,
11 None => slow_add(a0,b0,q)
12 }
13}
14
15pub fn mod_abs(a: i64, q: u64) -> u64 {
16 let mut abs_a = a;
17 while abs_a < 0 {
18 abs_a += q as i64;
19 }
20 abs_a as u64
21}
22
23pub fn mod_sub(a: i64, b: i64, modulus: u64) -> u64 {
24 mod_add(mod_abs(a,modulus), mod_abs(b, modulus), modulus)
25}
26
27
28fn slow_add(a:u64, b:u64, q:u64) -> u64 {
30 if a > b {
31 let neg_b = q -b;
32 a - neg_b
33 } else {
34 let neg_a = q - a;
35 b - neg_a
36 }
37}
38
39
40pub fn mod_mul(a:u64, b:u64, q:u64) -> u64 {
41 let a0 = a % q;
42 let b0 = b % q;
43 let prod = a0.checked_mul(b0);
44 match prod {
45 Some(x) => x % q,
46 None => slow_mul(a0, b0, q)
47 }
48}
49
50fn slow_mul(a:u64, b:u64, q:u64) -> u64 {
51 let mut total = 0;
52 for _ii in 0..b {
53 total = mod_add(total, a, q);
54 }
55 total
56}
57
58pub fn mod_exp(base :u64, exponent :u64, q:u64) -> u64 {
59 if exponent == 0{
60 return 1
61 }
62
63 let reduced_base = base % q;
64 let mut current_state = reduced_base;
65
66 for _i in 0..exponent-1 {
67 current_state = mod_mul(current_state, reduced_base, q);
68 }
69 current_state
70}