Skip to content

Commit 993ab31

Browse files
committed
add Zq.inv
1 parent e3371f2 commit 993ab31

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

src/zq.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,40 @@ impl<const Q: u64> Zq<Q> {
2828
pub fn one() -> Self {
2929
Zq { value: 1 }
3030
}
31+
32+
/// Multiplicative inverse of v, i.e. s = v^{-1} s.t. v*s = 1 mod q
33+
pub fn inv(self) -> Self {
34+
assert!(self.value != 0, "cannout invert zero");
35+
// find s, t. s.t. sq + tv = 1
36+
let mut a = Q as i128;
37+
let mut b = self.value as i128;
38+
// q's multiplier
39+
let mut s = [1, 0] as [i128; 2];
40+
// v's multiplier
41+
let mut t = [0, 1] as [i128; 2];
42+
43+
// gcd: (a, b) = (b, r) until b = 1
44+
let mut i = 0;
45+
while b > 1 {
46+
println!("round {i}: a={a}, b={b}, s={s:?}, t={t:?}");
47+
// a > b, b times a factor k and a minus bk
48+
let q = a / b;
49+
let r = a - q * b;
50+
let r_mplr = [s[0] - q * t[0], s[1] - q * t[1]];
51+
// (a, b) = (b, r)
52+
(a, b) = (b, r);
53+
(s, t) = (t, r_mplr);
54+
i += 1;
55+
}
56+
57+
// when b = 1, t[1] is v's multiplier, i.e. v^{-1}
58+
// Add Q to t[1] to ensure it's positive, then cast it back to u64
59+
// should be safe since we originally operate in u64.
60+
// mod Q again to enusre it's in range [0, Q)
61+
Zq {
62+
value: ((t[1] + (Q as i128)) as u64) % Q,
63+
}
64+
}
3165
}
3266

3367
impl<const Q: u64> Add for Zq<Q> {
@@ -134,4 +168,18 @@ mod tests {
134168
assert_eq!(F::zero().value(), 0);
135169
assert_eq!(F::one().value(), 1);
136170
}
171+
172+
#[test]
173+
fn test_inv() {
174+
for i in 1..Q {
175+
let e = F::new(i);
176+
assert_eq!((e * e.inv()).value(), 1);
177+
}
178+
}
179+
180+
#[test]
181+
#[should_panic]
182+
fn test_inv_zero() {
183+
F::new(0).inv();
184+
}
137185
}

0 commit comments

Comments
 (0)