@@ -27,7 +27,7 @@ impl<F: FiniteField> QuadraticExtensionField<F> {
27
27
const D : usize = 2 ;
28
28
29
29
/// irreducible polynomial used to reduce field polynomials to second degree:
30
- /// F[X]/(X^2-K )
30
+ /// F[X]/(X^2-2 )
31
31
fn irreducible ( ) -> F { F :: from_canonical_u32 ( 2 ) }
32
32
}
33
33
@@ -56,8 +56,22 @@ impl<F: FiniteField> FiniteField for QuadraticExtensionField<F> {
56
56
57
57
fn neg_one ( ) -> Self { Self { value : [ F :: neg_one ( ) , F :: zero ( ) ] } }
58
58
59
- fn generator ( ) -> Self { Self { value : [ F :: from_canonical_u32 ( 15 ) , F :: from_canonical_u32 ( 20 ) ] } }
59
+ // field generator: can be verified using sage script
60
+ // ```sage
61
+ // F = GF(101)
62
+ // Ft.<t> = F[]
63
+ // P = Ft(t ^ 2 - 2)
64
+ // F_2 = GF(101 ^ 2, name="t", modulus=P)
65
+ // f_2_primitive_element = F_2.primitive_element()
66
+ // ```
67
+ fn generator ( ) -> Self {
68
+ // TODO: unsure if this is correct or not, research more
69
+ Self { value : [ F :: from_canonical_u32 ( 15 ) , F :: from_canonical_u32 ( 20 ) ] }
70
+ }
60
71
72
+ /// Computes the multiplicative inverse of `a`, i.e. 1 / (a0 + a1 * t).
73
+ /// Multiply by `a0 - a1 * t` in numerator and denominator.
74
+ /// Denominator equals `(a0 + a1 * t) * (a0 - a1 * t) = a0.pow(2) - a1.pow(2) * Q::residue()`
61
75
fn inverse ( & self ) -> Option < Self > {
62
76
if * self == Self :: zero ( ) {
63
77
return None ;
@@ -109,6 +123,20 @@ impl<F: FiniteField> AddAssign for QuadraticExtensionField<F> {
109
123
fn add_assign ( & mut self , rhs : Self ) { * self = self . clone ( ) + rhs; }
110
124
}
111
125
126
+ impl < F : FiniteField > Add < F > for QuadraticExtensionField < F > {
127
+ type Output = Self ;
128
+
129
+ fn add ( self , rhs : F ) -> Self :: Output {
130
+ let mut res = self ;
131
+ res. value [ 0 ] += rhs;
132
+ res
133
+ }
134
+ }
135
+
136
+ impl < F : FiniteField > AddAssign < F > for QuadraticExtensionField < F > {
137
+ fn add_assign ( & mut self , rhs : F ) { * self = * self + rhs; }
138
+ }
139
+
112
140
impl < F : FiniteField > Sub for QuadraticExtensionField < F > {
113
141
type Output = Self ;
114
142
@@ -126,6 +154,20 @@ impl<F: FiniteField> SubAssign for QuadraticExtensionField<F> {
126
154
fn sub_assign ( & mut self , rhs : Self ) { * self = self . clone ( ) - rhs; }
127
155
}
128
156
157
+ impl < F : FiniteField > Sub < F > for QuadraticExtensionField < F > {
158
+ type Output = Self ;
159
+
160
+ fn sub ( self , rhs : F ) -> Self :: Output {
161
+ let mut res = self ;
162
+ res. value [ 0 ] -= rhs;
163
+ res
164
+ }
165
+ }
166
+
167
+ impl < F : FiniteField > SubAssign < F > for QuadraticExtensionField < F > {
168
+ fn sub_assign ( & mut self , rhs : F ) { * self = * self - rhs; }
169
+ }
170
+
129
171
impl < F : FiniteField > Sum for QuadraticExtensionField < F > {
130
172
fn sum < I : Iterator < Item = Self > > ( iter : I ) -> Self {
131
173
iter. reduce ( |x, y| x + y) . unwrap_or ( Self :: zero ( ) )
@@ -141,6 +183,8 @@ impl<F: FiniteField> Product for QuadraticExtensionField<F> {
141
183
impl < F : FiniteField > Mul for QuadraticExtensionField < F > {
142
184
type Output = Self ;
143
185
186
+ /// Returns the multiplication of `a` and `b` using the following equation:
187
+ /// (a0 + a1 * t) * (b0 + b1 * t) = a0 * b0 + a1 * b1 * irreducible() + (a0 * b1 + a1 * b0) * t
144
188
fn mul ( self , rhs : Self ) -> Self :: Output {
145
189
let a = self . value ;
146
190
let b = rhs. value ;
@@ -155,6 +199,21 @@ impl<F: FiniteField> MulAssign for QuadraticExtensionField<F> {
155
199
fn mul_assign ( & mut self , rhs : Self ) { * self = * self * rhs; }
156
200
}
157
201
202
+ impl < F : FiniteField > Mul < F > for QuadraticExtensionField < F > {
203
+ type Output = Self ;
204
+
205
+ fn mul ( self , rhs : F ) -> Self :: Output {
206
+ let mut res = self ;
207
+ res. value [ 0 ] *= rhs;
208
+ res. value [ 1 ] *= rhs;
209
+ res
210
+ }
211
+ }
212
+
213
+ impl < F : FiniteField > MulAssign < F > for QuadraticExtensionField < F > {
214
+ fn mul_assign ( & mut self , rhs : F ) { * self = * self * rhs; }
215
+ }
216
+
158
217
impl < F : FiniteField > Div for QuadraticExtensionField < F > {
159
218
type Output = Self ;
160
219
@@ -224,6 +283,17 @@ mod tests {
224
283
assert_eq ! ( x + y + z + x + y + z, [ x, x, y, y, z, z] . iter( ) . cloned( ) . sum( ) ) ;
225
284
}
226
285
286
+ #[ test]
287
+ fn test_pow ( ) {
288
+ let mut rng = rand:: thread_rng ( ) ;
289
+ let x = F2 :: from_base ( rng. gen :: < F > ( ) ) ;
290
+
291
+ assert_eq ! ( x, x. pow( <F2 as FiniteField >:: Storage :: from( 1_u32 ) ) ) ;
292
+
293
+ let res = x. pow ( <F2 as FiniteField >:: Storage :: from ( 4_u32 ) ) ;
294
+ assert_eq ! ( res, x. square( ) . square( ) ) ;
295
+ }
296
+
227
297
#[ test]
228
298
fn test_inv_div ( ) {
229
299
let mut rng = rand:: thread_rng ( ) ;
@@ -240,4 +310,26 @@ mod tests {
240
310
assert_eq ! ( x / ( y * z) , ( x / y) / z) ;
241
311
assert_eq ! ( ( x * y) / z, x * ( y / z) ) ;
242
312
}
313
+
314
+ #[ test]
315
+ fn test_generator ( ) {
316
+ assert_eq ! ( F2 :: generator( ) * F :: from_canonical_u32( F :: ORDER ) , F2 :: zero( ) ) ;
317
+ }
318
+
319
+ #[ test]
320
+ fn test_add_sub_mul_subfield ( ) {
321
+ let mut rng = rand:: thread_rng ( ) ;
322
+ let x = F2 :: from_base ( rng. gen :: < F > ( ) ) ;
323
+ let y = rng. gen :: < F > ( ) ;
324
+
325
+ let add1 = x + y;
326
+ let sub1 = x - y;
327
+ let res = x * F :: two ( ) ;
328
+ assert_eq ! ( add1 + sub1, res) ;
329
+
330
+ let mul1 = x * y;
331
+ let inv_mul = x * y. inverse ( ) . unwrap ( ) ;
332
+ let res = x. square ( ) ;
333
+ assert_eq ! ( mul1 * inv_mul, res) ;
334
+ }
243
335
}
0 commit comments