halo2curves/bls12381/
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
9crate::impl_binops_additive!(Fq6, Fq6);
10crate::impl_binops_multiplicative!(Fq6, Fq6);
11crate::impl_binops_calls!(Fq6);
12crate::impl_sum_prod!(Fq6);
13pub type Fq6 = CubicExtField<Fq2>;
14
15impl CubicExtFieldArith for Fq6 {
16    type Base = Fq2;
17}
18
19impl CubicSparseMul for Fq6 {
20    type Base = Fq2;
21}
22
23impl ExtField for Fq6 {
24    const NON_RESIDUE: Self = Fq6::new(Fq2::ZERO, Fq2::ONE, Fq2::ZERO);
25
26    fn frobenius_map(&mut self, power: usize) {
27        self.c0.frobenius_map(power);
28        self.c1.frobenius_map(power);
29        self.c2.frobenius_map(power);
30        self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
31        self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
32    }
33
34    fn mul_by_nonresidue(self: &Fq6) -> Fq6 {
35        let c0 = self.c2.mul_by_nonresidue();
36        let c1 = self.c0;
37        let c2 = self.c1;
38        Self { c0, c1, c2 }
39    }
40}
41
42pub const FROBENIUS_COEFF_FQ6_C1: [Fq2; 6] = [
43    // z ^ (( p ^ 0 - 1) / 3)
44    Fq2 {
45        c0: Fq([
46            0x760900000002fffd,
47            0xebf4000bc40c0002,
48            0x5f48985753c758ba,
49            0x77ce585370525745,
50            0x5c071a97a256ec6d,
51            0x15f65ec3fa80e493,
52        ]),
53        c1: Fq([
54            0x0000000000000000,
55            0x0000000000000000,
56            0x0000000000000000,
57            0x0000000000000000,
58            0x0000000000000000,
59            0x0000000000000000,
60        ]),
61    },
62    // z ^ (( p ^ 1 - 1) / 3)
63    Fq2 {
64        c0: Fq([
65            0x0000000000000000,
66            0x0000000000000000,
67            0x0000000000000000,
68            0x0000000000000000,
69            0x0000000000000000,
70            0x0000000000000000,
71        ]),
72        c1: Fq([
73            0xcd03c9e48671f071,
74            0x5dab22461fcda5d2,
75            0x587042afd3851b95,
76            0x8eb60ebe01bacb9e,
77            0x03f97d6e83d050d2,
78            0x18f0206554638741,
79        ]),
80    },
81    // z ^ (( p ^ 2 - 1) / 3)
82    Fq2 {
83        c0: Fq([
84            0x30f1361b798a64e8,
85            0xf3b8ddab7ece5a2a,
86            0x16a8ca3ac61577f7,
87            0xc26a2ff874fd029b,
88            0x3636b76660701c6e,
89            0x051ba4ab241b6160,
90        ]),
91        c1: Fq([
92            0x0000000000000000,
93            0x0000000000000000,
94            0x0000000000000000,
95            0x0000000000000000,
96            0x0000000000000000,
97            0x0000000000000000,
98        ]),
99    },
100    // z ^ (( p ^ 3 - 1) / 3)
101    Fq2 {
102        c0: Fq([
103            0x0000000000000000,
104            0x0000000000000000,
105            0x0000000000000000,
106            0x0000000000000000,
107            0x0000000000000000,
108            0x0000000000000000,
109        ]),
110        c1: Fq([
111            0x760900000002fffd,
112            0xebf4000bc40c0002,
113            0x5f48985753c758ba,
114            0x77ce585370525745,
115            0x5c071a97a256ec6d,
116            0x15f65ec3fa80e493,
117        ]),
118    },
119    // z ^ (( p ^ 4 - 1) / 3)
120    Fq2 {
121        c0: Fq([
122            0xcd03c9e48671f071,
123            0x5dab22461fcda5d2,
124            0x587042afd3851b95,
125            0x8eb60ebe01bacb9e,
126            0x03f97d6e83d050d2,
127            0x18f0206554638741,
128        ]),
129        c1: Fq([
130            0x0000000000000000,
131            0x0000000000000000,
132            0x0000000000000000,
133            0x0000000000000000,
134            0x0000000000000000,
135            0x0000000000000000,
136        ]),
137    },
138    // z ^ (( p ^ 5 - 1) / 3)
139    Fq2 {
140        c0: Fq([
141            0x0000000000000000,
142            0x0000000000000000,
143            0x0000000000000000,
144            0x0000000000000000,
145            0x0000000000000000,
146            0x0000000000000000,
147        ]),
148        c1: Fq([
149            0x30f1361b798a64e8,
150            0xf3b8ddab7ece5a2a,
151            0x16a8ca3ac61577f7,
152            0xc26a2ff874fd029b,
153            0x3636b76660701c6e,
154            0x051ba4ab241b6160,
155        ]),
156    },
157];
158
159// z = u + 1
160pub const FROBENIUS_COEFF_FQ6_C2: [Fq2; 6] = [
161    // z ^ (( 2 * p ^ 0 - 2) / 3)
162    Fq2 {
163        c0: Fq([
164            0x760900000002fffd,
165            0xebf4000bc40c0002,
166            0x5f48985753c758ba,
167            0x77ce585370525745,
168            0x5c071a97a256ec6d,
169            0x15f65ec3fa80e493,
170        ]),
171        c1: Fq([
172            0x0000000000000000,
173            0x0000000000000000,
174            0x0000000000000000,
175            0x0000000000000000,
176            0x0000000000000000,
177            0x0000000000000000,
178        ]),
179    },
180    // z ^ (( 2 * p ^ 1 - 2) / 3)
181    Fq2 {
182        c0: Fq([
183            0x890dc9e4867545c3,
184            0x2af322533285a5d5,
185            0x50880866309b7e2c,
186            0xa20d1b8c7e881024,
187            0x14e4f04fe2db9068,
188            0x14e56d3f1564853a,
189        ]),
190        c1: Fq([
191            0x0000000000000000,
192            0x0000000000000000,
193            0x0000000000000000,
194            0x0000000000000000,
195            0x0000000000000000,
196            0x0000000000000000,
197        ]),
198    },
199    // z ^ (( 2 * p ^ 2 - 2) / 3)
200    Fq2 {
201        c0: Fq([
202            0xcd03c9e48671f071,
203            0x5dab22461fcda5d2,
204            0x587042afd3851b95,
205            0x8eb60ebe01bacb9e,
206            0x03f97d6e83d050d2,
207            0x18f0206554638741,
208        ]),
209        c1: Fq([
210            0x0000000000000000,
211            0x0000000000000000,
212            0x0000000000000000,
213            0x0000000000000000,
214            0x0000000000000000,
215            0x0000000000000000,
216        ]),
217    },
218    // z ^ (( 2 * p ^ 3 - 2) / 3)
219    Fq2 {
220        c0: Fq([
221            0x43f5fffffffcaaae,
222            0x32b7fff2ed47fffd,
223            0x07e83a49a2e99d69,
224            0xeca8f3318332bb7a,
225            0xef148d1ea0f4c069,
226            0x040ab3263eff0206,
227        ]),
228        c1: Fq([
229            0x0000000000000000,
230            0x0000000000000000,
231            0x0000000000000000,
232            0x0000000000000000,
233            0x0000000000000000,
234            0x0000000000000000,
235        ]),
236    },
237    // z ^ (( 2 * p ^ 4 - 2) / 3)
238    Fq2 {
239        c0: Fq([
240            0x30f1361b798a64e8,
241            0xf3b8ddab7ece5a2a,
242            0x16a8ca3ac61577f7,
243            0xc26a2ff874fd029b,
244            0x3636b76660701c6e,
245            0x051ba4ab241b6160,
246        ]),
247        c1: Fq([
248            0x0000000000000000,
249            0x0000000000000000,
250            0x0000000000000000,
251            0x0000000000000000,
252            0x0000000000000000,
253            0x0000000000000000,
254        ]),
255    },
256    // z ^ (( 2 * p ^ 5 - 2) / 3)
257    Fq2 {
258        c0: Fq([
259            0xecfb361b798dba3a,
260            0xc100ddb891865a2c,
261            0x0ec08ff1232bda8e,
262            0xd5c13cc6f1ca4721,
263            0x47222a47bf7b5c04,
264            0x0110f184e51c5f59,
265        ]),
266        c1: Fq([
267            0x0000000000000000,
268            0x0000000000000000,
269            0x0000000000000000,
270            0x0000000000000000,
271            0x0000000000000000,
272            0x0000000000000000,
273        ]),
274    },
275];
276
277#[cfg(test)]
278mod test {
279    use rand_core::RngCore;
280
281    use super::*;
282    use crate::{arith_test, frobenius_test, setup_f6_test_funcs, test};
283
284    macro_rules! test_fq6 {
285        ($test:ident, $size: expr) => {
286            paste::paste! {
287            #[test]
288            fn [< $test test >]() {
289                use rand::SeedableRng;
290                use rand_xorshift::XorShiftRng;
291                let mut rng = XorShiftRng::from_seed(crate::tests::SEED);
292                crate::bls12381::fq6::test::$test(&mut rng, $size);
293            }
294            }
295        };
296    }
297
298    arith_test!(Fq6);
299    setup_f6_test_funcs!(Fq6, Fq2);
300    test_fq6!(f6_mul_nonresidue_, 1000);
301    test_fq6!(f6_mul_by_1_, 1000);
302    test_fq6!(f6_mul_by_01_, 1000);
303    frobenius_test!(Fq6, Fq, 10);
304
305    #[test]
306    fn test_fq6_mul_nonresidue() {
307        let e = Fq6::random(rand_core::OsRng);
308        let a0 = e.mul_by_nonresidue();
309        let a1 = e * Fq6::NON_RESIDUE;
310        assert_eq!(a0, a1);
311    }
312}