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 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 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 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 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 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 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
159pub const FROBENIUS_COEFF_FQ6_C2: [Fq2; 6] = [
161 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 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 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 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 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 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}