halo2curves/bn256/
fq6.rs

1use ff::Field;
2
3use super::{fq::Fq, fq2::Fq2};
4use crate::ff_ext::{
5    cubic::{CubicExtField, CubicExtFieldArith, CubicSparseMul},
6    ExtField,
7};
8
9// -BETA is a cubic non-residue in Fp2. Fp6 = Fp2[X]/(X^3 + BETA)
10// We introduce the variable v such that v^3 = -BETA
11// BETA = - (u + 9)
12// An element of Fq6, represented by c0 + c1 * v + c2 * v^2.Â
13crate::impl_binops_additive!(Fq6, Fq6);
14crate::impl_binops_multiplicative!(Fq6, Fq6);
15crate::impl_binops_calls!(Fq6);
16crate::impl_sum_prod!(Fq6);
17pub type Fq6 = CubicExtField<Fq2>;
18
19impl CubicExtFieldArith for Fq6 {
20    type Base = Fq2;
21}
22
23impl CubicSparseMul for Fq6 {
24    type Base = Fq2;
25}
26
27impl ExtField for Fq6 {
28    const NON_RESIDUE: Self = Fq6::new(Fq2::ZERO, Fq2::ONE, Fq2::ZERO);
29
30    fn frobenius_map(&mut self, power: usize) {
31        self.c0.frobenius_map(power);
32        self.c1.frobenius_map(power);
33        self.c2.frobenius_map(power);
34        self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
35        self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
36    }
37
38    fn mul_by_nonresidue(self: &Fq6) -> Fq6 {
39        let c0 = self.c2.mul_by_nonresidue();
40        let c1 = self.c0;
41        let c2 = self.c1;
42        Self { c0, c1, c2 }
43    }
44}
45
46pub const FROBENIUS_COEFF_FQ6_C1: [Fq2; 6] = [
47    // Fq2(u + 9)**(((q^0) - 1) / 3)
48    Fq2 {
49        c0: Fq([
50            0xd35d438dc58f0d9d,
51            0x0a78eb28f5c70b3d,
52            0x666ea36f7879462c,
53            0x0e0a77c19a07df2f,
54        ]),
55        c1: Fq([0x0, 0x0, 0x0, 0x0]),
56    },
57    // Fq2(u + 9)**(((q^1) - 1) / 3)
58    // taken from go-ethereum and also re-calculated manually
59    Fq2 {
60        c0: Fq([
61            0xb5773b104563ab30,
62            0x347f91c8a9aa6454,
63            0x7a007127242e0991,
64            0x1956bcd8118214ec,
65        ]),
66        c1: Fq([
67            0x6e849f1ea0aa4757,
68            0xaa1c7b6d89f89141,
69            0xb6e713cdfae0ca3a,
70            0x26694fbb4e82ebc3,
71        ]),
72    },
73    // Fq2(u + 9)**(((q^2) - 1) / 3)
74    // this one and other below are recalculated manually
75    Fq2 {
76        c0: Fq([
77            0x3350c88e13e80b9c,
78            0x7dce557cdb5e56b9,
79            0x6001b4b8b615564a,
80            0x2682e617020217e0,
81        ]),
82        c1: Fq([0x0, 0x0, 0x0, 0x0]),
83    },
84    // Fq2(u + 9)**(((q^3) - 1) / 3)
85    Fq2 {
86        c0: Fq([
87            0xc9af22f716ad6bad,
88            0xb311782a4aa662b2,
89            0x19eeaf64e248c7f4,
90            0x20273e77e3439f82,
91        ]),
92        c1: Fq([
93            0xacc02860f7ce93ac,
94            0x3933d5817ba76b4c,
95            0x69e6188b446c8467,
96            0x0a46036d4417cc55,
97        ]),
98    },
99    // Fq2(u + 9)**(((q^4) - 1) / 3)
100    Fq2 {
101        c0: Fq([
102            0x71930c11d782e155,
103            0xa6bb947cffbe3323,
104            0xaa303344d4741444,
105            0x2c3b3f0d26594943,
106        ]),
107        c1: Fq([0x0, 0x0, 0x0, 0x0]),
108    },
109    // Fq2(u + 9)**(((q^5) - 1) / 3)
110    Fq2 {
111        c0: Fq([
112            0xf91aba2654e8e3b1,
113            0x4771cb2fdc92ce12,
114            0xdcb16ae0fc8bdf35,
115            0x274aa195cd9d8be4,
116        ]),
117        c1: Fq([
118            0x5cfc50ae18811f8b,
119            0x4bb28433cb43988c,
120            0x4fd35f13c3b56219,
121            0x301949bd2fc8883a,
122        ]),
123    },
124];
125
126pub const FROBENIUS_COEFF_FQ6_C2: [Fq2; 6] = [
127    // Fq2(u + 9)**(((2q^0) - 2) / 3)
128    Fq2 {
129        c0: Fq([
130            0xd35d438dc58f0d9d,
131            0x0a78eb28f5c70b3d,
132            0x666ea36f7879462c,
133            0x0e0a77c19a07df2f,
134        ]),
135        c1: Fq([0x0, 0x0, 0x0, 0x0]),
136    },
137    // Fq2(u + 9)**(((2q^1) - 2) / 3)
138    Fq2 {
139        c0: Fq([
140            0x7361d77f843abe92,
141            0xa5bb2bd3273411fb,
142            0x9c941f314b3e2399,
143            0x15df9cddbb9fd3ec,
144        ]),
145        c1: Fq([
146            0x5dddfd154bd8c949,
147            0x62cb29a5a4445b60,
148            0x37bc870a0c7dd2b9,
149            0x24830a9d3171f0fd,
150        ]),
151    },
152    // Fq2(u + 9)**(((2q^2) - 2) / 3)
153    Fq2 {
154        c0: Fq([
155            0x71930c11d782e155,
156            0xa6bb947cffbe3323,
157            0xaa303344d4741444,
158            0x2c3b3f0d26594943,
159        ]),
160        c1: Fq([0x0, 0x0, 0x0, 0x0]),
161    },
162    // Fq2(u + 9)**(((2q^3) - 2) / 3)
163    Fq2 {
164        c0: Fq([
165            0x448a93a57b6762df,
166            0xbfd62df528fdeadf,
167            0xd858f5d00e9bd47a,
168            0x06b03d4d3476ec58,
169        ]),
170        c1: Fq([
171            0x2b19daf4bcc936d1,
172            0xa1a54e7a56f4299f,
173            0xb533eee05adeaef1,
174            0x170c812b84dda0b2,
175        ]),
176    },
177    // Fq2(u + 9)**(((2q^4) - 2) / 3)
178    Fq2 {
179        c0: Fq([
180            0x3350c88e13e80b9c,
181            0x7dce557cdb5e56b9,
182            0x6001b4b8b615564a,
183            0x2682e617020217e0,
184        ]),
185        c1: Fq([0x0, 0x0, 0x0, 0x0]),
186    },
187    // Fq2(u + 9)**(((2q^5) - 2) / 3)
188    Fq2 {
189        c0: Fq([
190            0x843420f1d8dadbd6,
191            0x31f010c9183fcdb2,
192            0x436330b527a76049,
193            0x13d47447f11adfe4,
194        ]),
195        c1: Fq([
196            0xef494023a857fa74,
197            0x2a925d02d5ab101a,
198            0x83b015829ba62f10,
199            0x2539111d0c13aea3,
200        ]),
201    },
202];
203
204#[cfg(test)]
205mod test {
206    use rand_core::RngCore;
207
208    use super::*;
209    use crate::{arith_test, frobenius_test, setup_f6_test_funcs, test};
210
211    macro_rules! test_fq6 {
212        ($test:ident, $size: expr) => {
213            paste::paste! {
214            #[test]
215            fn [< $test test >]() {
216                use rand::SeedableRng;
217                use rand_xorshift::XorShiftRng;
218                let mut rng = XorShiftRng::from_seed(crate::tests::SEED);
219                crate::bn256::fq6::test::$test(&mut rng, $size);
220            }
221            }
222        };
223    }
224
225    arith_test!(Fq6);
226    setup_f6_test_funcs!(Fq6, Fq2);
227    test_fq6!(f6_mul_nonresidue_, 1000);
228    test_fq6!(f6_mul_by_1_, 1000);
229    test_fq6!(f6_mul_by_01_, 1000);
230    frobenius_test!(Fq6, Fq, 10);
231}