halo2curves/bls12381/
fq2.rs
1use core::convert::TryInto;
2use std::cmp::Ordering;
3
4use subtle::{Choice, CtOption};
5
6use super::fq::Fq;
7use crate::{
8 ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup},
9 ff_ext::{
10 quadratic::{QuadExtField, QuadExtFieldArith, SQRT},
11 ExtField, Legendre,
12 },
13};
14
15crate::impl_binops_additive!(Fq2, Fq2);
16crate::impl_binops_multiplicative!(Fq2, Fq2);
17crate::impl_binops_calls!(Fq2);
18crate::impl_sum_prod!(Fq2);
19crate::impl_tower2!(Fq, Fq2);
20crate::impl_tower2_from_uniform_bytes!(Fq, Fq2, 128);
21
22pub type Fq2 = QuadExtField<Fq>;
23impl QuadExtFieldArith for Fq2 {
24 type Base = Fq;
25 const SQRT: SQRT<Fq> = SQRT::Algorithm9 {
26 q_minus_3_over_4: &[
27 0xee7fbfffffffeaaa,
28 0x07aaffffac54ffff,
29 0xd9cc34a83dac3d89,
30 0xd91dd2e13ce144af,
31 0x92c6e9ed90d2eb35,
32 0x0680447a8e5ff9a6,
33 ],
34 q_minus_1_over_2: &[
35 0xdcff7fffffffd555,
36 0x0f55ffff58a9ffff,
37 0xb39869507b587b12,
38 0xb23ba5c279c2895f,
39 0x258dd3db21a5d66b,
40 0x0d0088f51cbff34d,
41 ],
42 };
43
44 fn square_assign(el: &mut QuadExtField<Self::Base>) {
45 let a = el.c0 + el.c1;
46 let b = el.c0 - el.c1;
47 let c = el.c0.double();
48 el.c0 = a * b;
49 el.c1 = c * el.c1;
50 }
51}
52
53impl ExtField for Fq2 {
54 const NON_RESIDUE: Self = Fq2::new(Fq::ONE, Fq::ONE);
55
56 fn mul_by_nonresidue(&self) -> Self {
57 Self {
58 c0: self.c0 - self.c1,
59 c1: self.c0 + self.c1,
60 }
61 }
62
63 fn frobenius_map(&mut self, power: usize) {
64 if power % 2 != 0 {
65 self.conjugate();
66 }
67 }
68}
69
70#[cfg(test)]
71mod test {
72
73 use rand_core::RngCore;
74
75 use super::*;
76 use crate::{
77 arith_test, constants_test, f2_test, frobenius_test, legendre_test, serde_test, test,
78 };
79
80 constants_test!(Fq2);
81
82 arith_test!(Fq2);
83 legendre_test!(Fq2);
84 test!(arith, Fq2, sqrt_test, 1000);
85
86 serde_test!(Fq2);
87
88 f2_test!(Fq2, Fq);
89 frobenius_test!(Fq2, Fq, 20);
90
91 #[test]
92 fn test_fq2_mul_nonresidue() {
93 let e = Fq2::random(rand_core::OsRng);
94 let a0 = e.mul_by_nonresidue();
95 let a1 = e * Fq2::NON_RESIDUE;
96 assert_eq!(a0, a1);
97 }
98}