lambdaworks_math/field/fields/mersenne31/
extensions.rs

1use super::field::Mersenne31Field;
2use crate::field::{
3    element::FieldElement,
4    errors::FieldError,
5    traits::{IsFFTField, IsField, IsSubFieldOf},
6};
7#[cfg(feature = "alloc")]
8use alloc::vec::Vec;
9
10type FpE = FieldElement<Mersenne31Field>;
11type Fp2E = FieldElement<Degree2ExtensionField>;
12type Fp4E = FieldElement<Degree4ExtensionField>;
13
14#[derive(Clone, Debug)]
15pub struct Degree2ExtensionField;
16
17impl Degree2ExtensionField {
18    pub fn mul_fp2_by_nonresidue(a: &Fp2E) -> Fp2E {
19        Fp2E::new([
20            a.value()[0].double() - a.value()[1],
21            a.value()[1].double() + a.value()[0],
22        ])
23    }
24}
25
26impl IsField for Degree2ExtensionField {
27    //Element representation: a[0] = real part, a[1] = imaginary part
28    type BaseType = [FpE; 2];
29
30    /// Returns the component wise addition of `a` and `b`
31    fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
32        [a[0] + b[0], a[1] + b[1]]
33    }
34
35    /// Returns the multiplication of `a` and `b`.
36    fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
37        let a0b0 = a[0] * b[0];
38        let a1b1 = a[1] * b[1];
39        let z = (a[0] + a[1]) * (b[0] + b[1]);
40        [a0b0 - a1b1, z - a0b0 - a1b1]
41    }
42
43    fn square(a: &Self::BaseType) -> Self::BaseType {
44        let [a0, a1] = a;
45        let v0 = a0 * a1;
46        let c0 = (a0 + a1) * (a0 - a1);
47        let c1 = v0.double();
48        [c0, c1]
49    }
50    /// Returns the component wise subtraction of `a` and `b`
51    fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
52        [a[0] - b[0], a[1] - b[1]]
53    }
54
55    /// Returns the component wise negation of `a`
56    fn neg(a: &Self::BaseType) -> Self::BaseType {
57        [-a[0], -a[1]]
58    }
59
60    /// Returns the multiplicative inverse of `a`
61    fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
62        let inv_norm = (a[0].square() + a[1].square()).inv()?;
63        Ok([a[0] * inv_norm, -a[1] * inv_norm])
64    }
65
66    /// Returns the division of `a` and `b`
67    fn div(a: &Self::BaseType, b: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
68        let b_inv = &Self::inv(b).map_err(|_| FieldError::DivisionByZero)?;
69        Ok(<Self as IsField>::mul(a, b_inv))
70    }
71
72    /// Returns a boolean indicating whether `a` and `b` are equal component wise.
73    fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool {
74        a[0] == b[0] && a[1] == b[1]
75    }
76
77    /// Returns the multiplicative neutral element of the field extension.
78    fn one() -> Self::BaseType {
79        [FpE::one(), FpE::zero()]
80    }
81
82    /// Returns the element `x * 1` where 1 is the multiplicative neutral element.
83    fn from_u64(x: u64) -> Self::BaseType {
84        [FpE::from(x), FpE::zero()]
85    }
86
87    /// Takes as input an element of BaseType and returns the internal representation
88    /// of that element in the field.
89    /// Note: for this case this is simply the identity, because the components
90    /// already have correct representations.
91    fn from_base_type(x: Self::BaseType) -> Self::BaseType {
92        x
93    }
94}
95
96impl IsFFTField for Degree2ExtensionField {
97    // Values taken from stwo
98    // https://github.com/starkware-libs/stwo/blob/dev/crates/prover/src/core/circle.rs#L203-L209
99    const TWO_ADICITY: u64 = 31;
100    const TWO_ADIC_PRIMITVE_ROOT_OF_UNITY: Self::BaseType =
101        [FpE::const_from_raw(2), FpE::const_from_raw(1268011823)];
102}
103
104impl IsSubFieldOf<Degree2ExtensionField> for Mersenne31Field {
105    fn add(
106        a: &Self::BaseType,
107        b: &<Degree2ExtensionField as IsField>::BaseType,
108    ) -> <Degree2ExtensionField as IsField>::BaseType {
109        [FpE::from(a) + b[0], b[1]]
110    }
111
112    fn sub(
113        a: &Self::BaseType,
114        b: &<Degree2ExtensionField as IsField>::BaseType,
115    ) -> <Degree2ExtensionField as IsField>::BaseType {
116        [FpE::from(a) - b[0], -b[1]]
117    }
118
119    fn mul(
120        a: &Self::BaseType,
121        b: &<Degree2ExtensionField as IsField>::BaseType,
122    ) -> <Degree2ExtensionField as IsField>::BaseType {
123        [FpE::from(a) * b[0], FpE::from(a) * b[1]]
124    }
125
126    fn div(
127        a: &Self::BaseType,
128        b: &<Degree2ExtensionField as IsField>::BaseType,
129    ) -> Result<<Degree2ExtensionField as IsField>::BaseType, FieldError> {
130        let b_inv = Degree2ExtensionField::inv(b).map_err(|_| FieldError::DivisionByZero)?;
131        Ok(<Self as IsSubFieldOf<Degree2ExtensionField>>::mul(
132            a, &b_inv,
133        ))
134    }
135
136    fn embed(a: Self::BaseType) -> <Degree2ExtensionField as IsField>::BaseType {
137        [FieldElement::from_raw(a), FieldElement::zero()]
138    }
139
140    #[cfg(feature = "alloc")]
141    fn to_subfield_vec(
142        b: <Degree2ExtensionField as IsField>::BaseType,
143    ) -> alloc::vec::Vec<Self::BaseType> {
144        b.into_iter().map(|x| x.to_raw()).collect()
145    }
146}
147
148#[derive(Clone, Debug)]
149pub struct Degree4ExtensionField;
150
151impl Degree4ExtensionField {
152    pub const fn const_from_coefficients(a: u32, b: u32, c: u32, d: u32) -> Fp4E {
153        Fp4E::const_from_raw([
154            Fp2E::const_from_raw([FpE::const_from_raw(a), FpE::const_from_raw(b)]),
155            Fp2E::const_from_raw([FpE::const_from_raw(c), FpE::const_from_raw(d)]),
156        ])
157    }
158}
159
160impl IsField for Degree4ExtensionField {
161    type BaseType = [Fp2E; 2];
162
163    fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
164        [&a[0] + &b[0], &a[1] + &b[1]]
165    }
166
167    fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
168        [&a[0] - &b[0], &a[1] - &b[1]]
169    }
170
171    fn neg(a: &Self::BaseType) -> Self::BaseType {
172        [-&a[0], -&a[1]]
173    }
174
175    fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
176        // Algorithm from: https://github.com/ingonyama-zk/papers/blob/main/Mersenne31_polynomial_arithmetic.pdf (page 5):
177        let a0b0 = &a[0] * &b[0];
178        let a1b1 = &a[1] * &b[1];
179        [
180            &a0b0 + Degree2ExtensionField::mul_fp2_by_nonresidue(&a1b1),
181            (&a[0] + &a[1]) * (&b[0] + &b[1]) - a0b0 - a1b1,
182        ]
183    }
184
185    fn square(a: &Self::BaseType) -> Self::BaseType {
186        let a0_square = &a[0].square();
187        let a1_square = &a[1].square();
188        [
189            a0_square + Degree2ExtensionField::mul_fp2_by_nonresidue(a1_square),
190            (&a[0] + &a[1]).square() - a0_square - a1_square,
191        ]
192    }
193
194    fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
195        let inv_norm =
196            (a[0].square() - Degree2ExtensionField::mul_fp2_by_nonresidue(&a[1].square())).inv()?;
197        Ok([&a[0] * &inv_norm, -&a[1] * &inv_norm])
198    }
199
200    fn div(a: &Self::BaseType, b: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
201        let b_inv = &Self::inv(b).map_err(|_| FieldError::DivisionByZero)?;
202        Ok(<Self as IsField>::mul(a, b_inv))
203    }
204
205    fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool {
206        a[0] == b[0] && a[1] == b[1]
207    }
208
209    fn zero() -> Self::BaseType {
210        [Fp2E::zero(), Fp2E::zero()]
211    }
212
213    fn one() -> Self::BaseType {
214        [Fp2E::one(), Fp2E::zero()]
215    }
216
217    fn from_u64(x: u64) -> Self::BaseType {
218        [Fp2E::from(x), Fp2E::zero()]
219    }
220
221    fn from_base_type(x: Self::BaseType) -> Self::BaseType {
222        x
223    }
224}
225
226impl IsSubFieldOf<Degree4ExtensionField> for Mersenne31Field {
227    fn add(
228        a: &Self::BaseType,
229        b: &<Degree4ExtensionField as IsField>::BaseType,
230    ) -> <Degree4ExtensionField as IsField>::BaseType {
231        [FpE::from(a) + &b[0], b[1].clone()]
232    }
233
234    fn sub(
235        a: &Self::BaseType,
236        b: &<Degree4ExtensionField as IsField>::BaseType,
237    ) -> <Degree4ExtensionField as IsField>::BaseType {
238        [FpE::from(a) - &b[0], -&b[1]]
239    }
240
241    fn mul(
242        a: &Self::BaseType,
243        b: &<Degree4ExtensionField as IsField>::BaseType,
244    ) -> <Degree4ExtensionField as IsField>::BaseType {
245        let c0 = FpE::from(a) * &b[0];
246        let c1 = FpE::from(a) * &b[1];
247        [c0, c1]
248    }
249
250    fn div(
251        a: &Self::BaseType,
252        b: &<Degree4ExtensionField as IsField>::BaseType,
253    ) -> Result<<Degree4ExtensionField as IsField>::BaseType, FieldError> {
254        let b_inv = Degree4ExtensionField::inv(b).map_err(|_| FieldError::DivisionByZero)?;
255        Ok(<Self as IsSubFieldOf<Degree4ExtensionField>>::mul(
256            a, &b_inv,
257        ))
258    }
259
260    fn embed(a: Self::BaseType) -> <Degree4ExtensionField as IsField>::BaseType {
261        [
262            Fp2E::from_raw(<Self as IsSubFieldOf<Degree2ExtensionField>>::embed(a)),
263            Fp2E::zero(),
264        ]
265    }
266
267    #[cfg(feature = "alloc")]
268    fn to_subfield_vec(
269        b: <Degree4ExtensionField as IsField>::BaseType,
270    ) -> alloc::vec::Vec<Self::BaseType> {
271        // TODO: Repace this for with a map similarly to this:
272        // b.into_iter().map(|x| x.to_raw()).collect()
273        let mut result = Vec::new();
274        for fp2e in b {
275            result.push(fp2e.value()[0].to_raw());
276            result.push(fp2e.value()[1].to_raw());
277        }
278        result
279    }
280}
281
282#[cfg(test)]
283mod tests {
284    use core::ops::Neg;
285
286    use crate::field::fields::mersenne31::field::MERSENNE_31_PRIME_FIELD_ORDER;
287
288    use super::*;
289
290    type FpE = FieldElement<Mersenne31Field>;
291    type Fp2E = FieldElement<Degree2ExtensionField>;
292    type Fp4E = FieldElement<Degree4ExtensionField>;
293
294    #[test]
295    fn add_real_one_plus_one_is_two() {
296        assert_eq!(Fp2E::one() + Fp2E::one(), Fp2E::from(2))
297    }
298
299    #[test]
300    fn add_real_neg_one_plus_one_is_zero() {
301        assert_eq!(Fp2E::one() + Fp2E::one().neg(), Fp2E::zero())
302    }
303
304    #[test]
305    fn add_real_neg_one_plus_two_is_one() {
306        assert_eq!(Fp2E::one().neg() + Fp2E::from(2), Fp2E::one())
307    }
308
309    #[test]
310    fn add_real_neg_one_plus_neg_one_is_order_sub_two() {
311        assert_eq!(
312            Fp2E::one().neg() + Fp2E::one().neg(),
313            Fp2E::new([FpE::from(&(MERSENNE_31_PRIME_FIELD_ORDER - 2)), FpE::zero()])
314        )
315    }
316
317    #[test]
318    fn add_complex_one_plus_one_two() {
319        let one_i = Fp2E::new([FpE::zero(), FpE::one()]);
320        let two_i = Fp2E::new([FpE::zero(), FpE::from(2)]);
321        assert_eq!(&one_i + &one_i, two_i)
322    }
323
324    #[test]
325    fn add_complex_neg_one_plus_one_is_zero() {
326        //Manually declare the complex part to one
327        let neg_one_i = Fp2E::new([FpE::zero(), -FpE::one()]);
328        let one_i = Fp2E::new([FpE::zero(), FpE::one()]);
329        assert_eq!(neg_one_i + one_i, Fp2E::zero())
330    }
331
332    #[test]
333    fn add_complex_neg_one_plus_two_is_one() {
334        let neg_one_i = Fp2E::new([FpE::zero(), -FpE::one()]);
335        let two_i = Fp2E::new([FpE::zero(), FpE::from(2)]);
336        let one_i = Fp2E::new([FpE::zero(), FpE::one()]);
337        assert_eq!(&neg_one_i + &two_i, one_i)
338    }
339
340    #[test]
341    fn add_complex_neg_one_plus_neg_one_imag_is_order_sub_two() {
342        let neg_one_i = Fp2E::new([FpE::zero(), -FpE::one()]);
343        assert_eq!(
344            (&neg_one_i + &neg_one_i).value()[1],
345            FpE::from(&(MERSENNE_31_PRIME_FIELD_ORDER - 2))
346        )
347    }
348
349    #[test]
350    fn add_order() {
351        let a = Fp2E::new([-FpE::one(), FpE::one()]);
352        let b = Fp2E::new([
353            FpE::from(2),
354            FpE::from(&(MERSENNE_31_PRIME_FIELD_ORDER - 2)),
355        ]);
356        let c = Fp2E::new([FpE::one(), -FpE::one()]);
357        assert_eq!(&a + &b, c)
358    }
359
360    #[test]
361    fn add_equal_zero() {
362        let a = Fp2E::new([-FpE::one(), -FpE::one()]);
363        let b = Fp2E::new([FpE::one(), FpE::one()]);
364        assert_eq!(&a + &b, Fp2E::zero())
365    }
366
367    #[test]
368    fn add_plus_one() {
369        let a = Fp2E::new([FpE::one(), FpE::from(2)]);
370        let b = Fp2E::new([FpE::one(), FpE::one()]);
371        let c = Fp2E::new([FpE::from(2), FpE::from(3)]);
372        assert_eq!(&a + &b, c)
373    }
374
375    #[test]
376    fn sub_real_one_sub_one_is_zero() {
377        assert_eq!(&Fp2E::one() - &Fp2E::one(), Fp2E::zero())
378    }
379
380    #[test]
381    fn sub_real_two_sub_two_is_zero() {
382        assert_eq!(&Fp2E::from(2) - &Fp2E::from(2), Fp2E::zero())
383    }
384
385    #[test]
386    fn sub_real_neg_one_sub_neg_one_is_zero() {
387        assert_eq!(Fp2E::one().neg() - Fp2E::one().neg(), Fp2E::zero())
388    }
389
390    #[test]
391    fn sub_real_two_sub_one_is_one() {
392        assert_eq!(Fp2E::from(2) - Fp2E::one(), Fp2E::one())
393    }
394
395    #[test]
396    fn sub_real_neg_one_sub_zero_is_neg_one() {
397        assert_eq!(Fp2E::one().neg() - Fp2E::zero(), Fp2E::one().neg())
398    }
399
400    #[test]
401    fn sub_complex_one_sub_one_is_zero() {
402        let one = Fp2E::new([FpE::zero(), FpE::one()]);
403        assert_eq!(&one - &one, Fp2E::zero())
404    }
405
406    #[test]
407    fn sub_complex_two_sub_two_is_zero() {
408        let two = Fp2E::new([FpE::zero(), FpE::from(2)]);
409        assert_eq!(&two - &two, Fp2E::zero())
410    }
411
412    #[test]
413    fn sub_complex_neg_one_sub_neg_one_is_zero() {
414        let neg_one = Fp2E::new([FpE::zero(), -FpE::one()]);
415        assert_eq!(&neg_one - &neg_one, Fp2E::zero())
416    }
417
418    #[test]
419    fn sub_complex_two_sub_one_is_one() {
420        let two = Fp2E::new([FpE::zero(), FpE::from(2)]);
421        let one = Fp2E::new([FpE::zero(), FpE::one()]);
422        assert_eq!(&two - &one, one)
423    }
424
425    #[test]
426    fn sub_complex_neg_one_sub_zero_is_neg_one() {
427        let neg_one = Fp2E::new([FpE::zero(), -FpE::one()]);
428        assert_eq!(&neg_one - &Fp2E::zero(), neg_one)
429    }
430
431    #[test]
432    fn mul_fp2_is_correct() {
433        let a = Fp2E::new([FpE::from(2), FpE::from(2)]);
434        let b = Fp2E::new([FpE::from(4), FpE::from(5)]);
435        let c = Fp2E::new([-FpE::from(2), FpE::from(18)]);
436        assert_eq!(&a * &b, c)
437    }
438
439    #[test]
440    fn square_equals_mul_by_itself() {
441        let a = Fp2E::new([FpE::from(2), FpE::from(3)]);
442        assert_eq!(a.square(), &a * &a)
443    }
444
445    #[test]
446    fn test_fp2_add() {
447        let a = Fp2E::new([FpE::from(0), FpE::from(3)]);
448        let b = Fp2E::new([-FpE::from(2), FpE::from(8)]);
449        let expected_result = Fp2E::new([FpE::from(0) - FpE::from(2), FpE::from(3) + FpE::from(8)]);
450        assert_eq!(a + b, expected_result);
451    }
452
453    #[test]
454    fn test_fp2_add_2() {
455        let a = Fp2E::new([FpE::from(2), FpE::from(4)]);
456        let b = Fp2E::new([-FpE::from(2), -FpE::from(4)]);
457        let expected_result = Fp2E::new([FpE::from(2) - FpE::from(2), FpE::from(4) - FpE::from(4)]);
458        assert_eq!(a + b, expected_result);
459    }
460
461    #[test]
462    fn test_fp2_add_3() {
463        let a = Fp2E::new([FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER), FpE::from(1)]);
464        let b = Fp2E::new([FpE::from(1), FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER)]);
465        let expected_result = Fp2E::new([FpE::from(1), FpE::from(1)]);
466        assert_eq!(a + b, expected_result);
467    }
468
469    #[test]
470    fn test_fp2_sub() {
471        let a = Fp2E::new([FpE::from(0), FpE::from(3)]);
472        let b = Fp2E::new([-FpE::from(2), FpE::from(8)]);
473        let expected_result = Fp2E::new([FpE::from(0) + FpE::from(2), FpE::from(3) - FpE::from(8)]);
474        assert_eq!(a - b, expected_result);
475    }
476
477    #[test]
478    fn test_fp2_sub_2() {
479        let a = Fp2E::new([FpE::zero(), FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER)]);
480        let b = Fp2E::new([FpE::one(), -FpE::one()]);
481        let expected_result =
482            Fp2E::new([FpE::from(&(MERSENNE_31_PRIME_FIELD_ORDER - 1)), FpE::one()]);
483        assert_eq!(a - b, expected_result);
484    }
485
486    #[test]
487    fn test_fp2_sub_3() {
488        let a = Fp2E::new([FpE::from(5), FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER)]);
489        let b = Fp2E::new([FpE::from(5), FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER)]);
490        let expected_result = Fp2E::new([FpE::zero(), FpE::zero()]);
491        assert_eq!(a - b, expected_result);
492    }
493
494    #[test]
495    fn test_fp2_mul() {
496        let a = Fp2E::new([FpE::from(12), FpE::from(5)]);
497        let b = Fp2E::new([-FpE::from(4), FpE::from(2)]);
498        let expected_result = Fp2E::new([-FpE::from(58), FpE::new(4)]);
499        assert_eq!(a * b, expected_result);
500    }
501
502    #[test]
503    fn test_fp2_mul_2() {
504        let a = Fp2E::new([FpE::one(), FpE::zero()]);
505        let b = Fp2E::new([FpE::from(12), -FpE::from(8)]);
506        let expected_result = Fp2E::new([FpE::from(12), -FpE::new(8)]);
507        assert_eq!(a * b, expected_result);
508    }
509
510    #[test]
511    fn test_fp2_mul_3() {
512        let a = Fp2E::new([FpE::zero(), FpE::zero()]);
513        let b = Fp2E::new([FpE::from(2), FpE::from(7)]);
514        let expected_result = Fp2E::new([FpE::zero(), FpE::zero()]);
515        assert_eq!(a * b, expected_result);
516    }
517
518    #[test]
519    fn test_fp2_mul_4() {
520        let a = Fp2E::new([FpE::from(2), FpE::from(7)]);
521        let b = Fp2E::new([FpE::zero(), FpE::zero()]);
522        let expected_result = Fp2E::new([FpE::zero(), FpE::zero()]);
523        assert_eq!(a * b, expected_result);
524    }
525
526    #[test]
527    fn test_fp2_mul_5() {
528        let a = Fp2E::new([FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER), FpE::one()]);
529        let b = Fp2E::new([FpE::from(2), FpE::from(&MERSENNE_31_PRIME_FIELD_ORDER)]);
530        let expected_result = Fp2E::new([FpE::zero(), FpE::from(2)]);
531        assert_eq!(a * b, expected_result);
532    }
533
534    #[test]
535    fn test_fp2_inv() {
536        let a = Fp2E::new([FpE::one(), FpE::zero()]);
537        let expected_result = Fp2E::new([FpE::one(), FpE::zero()]);
538        assert_eq!(a.inv().unwrap(), expected_result);
539    }
540
541    #[test]
542    fn test_fp2_inv_2() {
543        let a = Fp2E::new([FpE::from(&(MERSENNE_31_PRIME_FIELD_ORDER - 1)), FpE::one()]);
544        let expected_result = Fp2E::new([FpE::from(1073741823), FpE::from(1073741823)]);
545        assert_eq!(a.inv().unwrap(), expected_result);
546    }
547
548    #[test]
549    fn test_fp2_inv_3() {
550        let a = Fp2E::new([FpE::from(2063384121), FpE::from(1232183486)]);
551        let expected_result = Fp2E::new([FpE::from(1244288232), FpE::from(1321511038)]);
552        assert_eq!(a.inv().unwrap(), expected_result);
553    }
554
555    #[test]
556    fn test_fp2_mul_inv() {
557        let a = Fp2E::new([FpE::from(12), FpE::from(5)]);
558        let b = a.inv().unwrap();
559        let expected_result = Fp2E::new([FpE::one(), FpE::zero()]);
560        assert_eq!(a * b, expected_result);
561    }
562
563    #[test]
564    fn test_fp2_div() {
565        let a = Fp2E::new([FpE::from(12), FpE::from(5)]);
566        let b = Fp2E::new([FpE::from(4), FpE::from(2)]);
567        let expected_result = Fp2E::new([FpE::from(644245097), FpE::from(1288490188)]);
568        assert_eq!((a / b).unwrap(), expected_result);
569    }
570
571    #[test]
572    fn test_fp2_div_2() {
573        let a = Fp2E::new([FpE::from(4), FpE::from(7)]);
574        let b = Fp2E::new([FpE::one(), FpE::zero()]);
575        let expected_result = Fp2E::new([FpE::from(4), FpE::from(7)]);
576        assert_eq!((a / b).unwrap(), expected_result);
577    }
578
579    #[test]
580    fn test_fp2_div_3() {
581        let a = Fp2E::new([FpE::zero(), FpE::zero()]);
582        let b = Fp2E::new([FpE::from(3), FpE::from(12)]);
583        let expected_result = Fp2E::new([FpE::zero(), FpE::zero()]);
584        assert_eq!((a / b).unwrap(), expected_result);
585    }
586
587    #[test]
588    fn mul_fp4_by_zero_is_zero() {
589        let a = Fp4E::new([
590            Fp2E::new([FpE::from(2), FpE::from(3)]),
591            Fp2E::new([FpE::from(4), FpE::from(5)]),
592        ]);
593        assert_eq!(Fp4E::zero(), a * Fp4E::zero())
594    }
595
596    #[test]
597    fn mul_fp4_by_one_is_identity() {
598        let a = Fp4E::new([
599            Fp2E::new([FpE::from(2), FpE::from(3)]),
600            Fp2E::new([FpE::from(4), FpE::from(5)]),
601        ]);
602        assert_eq!(a, a.clone() * Fp4E::one())
603    }
604
605    #[test]
606    fn square_fp4_equals_mul_two_times() {
607        let a = Fp4E::new([
608            Fp2E::new([FpE::from(3), FpE::from(4)]),
609            Fp2E::new([FpE::from(5), FpE::from(6)]),
610        ]);
611
612        assert_eq!(a.square(), &a * &a)
613    }
614
615    #[test]
616    fn fp4_mul_by_inv_is_one() {
617        let a = Fp4E::new([
618            Fp2E::new([FpE::from(2147483647), FpE::from(2147483648)]),
619            Fp2E::new([FpE::from(2147483649), FpE::from(2147483650)]),
620        ]);
621
622        assert_eq!(&a * a.inv().unwrap(), Fp4E::one())
623    }
624
625    #[test]
626    fn embed_fp_with_fp4() {
627        let a = FpE::from(3);
628        let a_extension = Fp4E::from(3);
629        assert_eq!(a.to_extension::<Degree4ExtensionField>(), a_extension);
630    }
631
632    #[test]
633    fn add_fp_and_fp4() {
634        let a = FpE::from(3);
635        let a_extension = Fp4E::from(3);
636        let b = Fp4E::from(2);
637        assert_eq!(a + &b, a_extension + b);
638    }
639
640    #[test]
641    fn mul_fp_by_fp4() {
642        let a = FpE::from(30000000000);
643        let a_extension = a.to_extension::<Degree4ExtensionField>();
644        let b = Fp4E::new([
645            Fp2E::new([FpE::from(1), FpE::from(2)]),
646            Fp2E::new([FpE::from(3), FpE::from(4)]),
647        ]);
648        assert_eq!(a * &b, a_extension * b);
649    }
650}