@@ -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
3367impl < 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