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);
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 {
49 c0: Fq([
50 0xd35d438dc58f0d9d,
51 0x0a78eb28f5c70b3d,
52 0x666ea36f7879462c,
53 0x0e0a77c19a07df2f,
54 ]),
55 c1: Fq([0x0, 0x0, 0x0, 0x0]),
56 },
57 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 {
76 c0: Fq([
77 0x3350c88e13e80b9c,
78 0x7dce557cdb5e56b9,
79 0x6001b4b8b615564a,
80 0x2682e617020217e0,
81 ]),
82 c1: Fq([0x0, 0x0, 0x0, 0x0]),
83 },
84 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 {
101 c0: Fq([
102 0x71930c11d782e155,
103 0xa6bb947cffbe3323,
104 0xaa303344d4741444,
105 0x2c3b3f0d26594943,
106 ]),
107 c1: Fq([0x0, 0x0, 0x0, 0x0]),
108 },
109 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 {
129 c0: Fq([
130 0xd35d438dc58f0d9d,
131 0x0a78eb28f5c70b3d,
132 0x666ea36f7879462c,
133 0x0e0a77c19a07df2f,
134 ]),
135 c1: Fq([0x0, 0x0, 0x0, 0x0]),
136 },
137 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 {
154 c0: Fq([
155 0x71930c11d782e155,
156 0xa6bb947cffbe3323,
157 0xaa303344d4741444,
158 0x2c3b3f0d26594943,
159 ]),
160 c1: Fq([0x0, 0x0, 0x0, 0x0]),
161 },
162 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 {
179 c0: Fq([
180 0x3350c88e13e80b9c,
181 0x7dce557cdb5e56b9,
182 0x6001b4b8b615564a,
183 0x2682e617020217e0,
184 ]),
185 c1: Fq([0x0, 0x0, 0x0, 0x0]),
186 },
187 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}