@@ -29,6 +29,22 @@ impl<const Q: u64> Zq<Q> {
2929 Zq { value : 1 }
3030 }
3131
32+ /// Modular exponentiation: self^exp mod Q (square-and-multiply).
33+ pub fn pow ( self , exp : u64 ) -> Self {
34+ if exp == 0 {
35+ Self :: one ( )
36+ } else {
37+ // f(x) = g^x
38+ // = g*f(x/2)**2 if x \in odd else f(x/2)**2
39+ let half = self . pow ( exp / 2 ) ;
40+ if exp. is_multiple_of ( 2 ) {
41+ half * half
42+ } else {
43+ self * ( half * half)
44+ }
45+ }
46+ }
47+
3248 /// Multiplicative inverse of v, i.e. s = v^{-1} s.t. v*s = 1 mod q
3349 pub fn inv ( self ) -> Self {
3450 assert ! ( self . value != 0 , "cannout invert zero" ) ;
@@ -41,17 +57,14 @@ impl<const Q: u64> Zq<Q> {
4157 let mut t = [ 0 , 1 ] as [ i128 ; 2 ] ;
4258
4359 // gcd: (a, b) = (b, r) until b = 1
44- let mut i = 0 ;
4560 while b > 1 {
46- println ! ( "round {i}: a={a}, b={b}, s={s:?}, t={t:?}" ) ;
4761 // a > b, b times a factor k and a minus bk
4862 let q = a / b;
4963 let r = a - q * b;
5064 let r_mplr = [ s[ 0 ] - q * t[ 0 ] , s[ 1 ] - q * t[ 1 ] ] ;
5165 // (a, b) = (b, r)
5266 ( a, b) = ( b, r) ;
5367 ( s, t) = ( t, r_mplr) ;
54- i += 1 ;
5568 }
5669
5770 // when b = 1, t[1] is v's multiplier, i.e. v^{-1}
@@ -169,6 +182,24 @@ mod tests {
169182 assert_eq ! ( F :: one( ) . value( ) , 1 ) ;
170183 }
171184
185+ #[ test]
186+ fn test_pow ( ) {
187+ // 3^0 = 1
188+ assert_eq ! ( F :: new( 3 ) . pow( 0 ) , F :: one( ) ) ;
189+ // 3^1 = 3
190+ assert_eq ! ( F :: new( 3 ) . pow( 1 ) , F :: new( 3 ) ) ;
191+ // 3^2 = 9
192+ assert_eq ! ( F :: new( 3 ) . pow( 2 ) , F :: new( 9 ) ) ;
193+ // 3^3 = 27 mod 17 = 10
194+ assert_eq ! ( F :: new( 3 ) . pow( 3 ) , F :: new( 10 ) ) ;
195+ // Fermat's little theorem: a^(q-1) = 1 for a != 0
196+ for i in 1 ..Q {
197+ assert_eq ! ( F :: new( i) . pow( Q - 1 ) , F :: one( ) ) ;
198+ }
199+ // 0^n = 0 for n > 0
200+ assert_eq ! ( F :: new( 0 ) . pow( 5 ) , F :: zero( ) ) ;
201+ }
202+
172203 #[ test]
173204 fn test_inv ( ) {
174205 for i in 1 ..Q {
0 commit comments