halo2curves/bn256/
fq12.rs

1use super::{fq::Fq, fq2::Fq2, fq6::Fq6};
2use crate::ff_ext::{
3    quadratic::{QuadExtField, QuadExtFieldArith, QuadSparseMul},
4    ExtField,
5};
6
7// -GAMMA is a quadratic non-residue in Fp6. Fp12 = Fp6[X] / (X^2 + GAMMA)
8// We introduce the variable w such that w^2 = -GAMMA
9// GAMMA = -v
10/// An element of Fq12, represented by c0 + c1 * w.
11pub type Fq12 = QuadExtField<Fq6>;
12
13impl QuadExtFieldArith for Fq12 {
14    type Base = Fq6;
15}
16
17impl QuadSparseMul for Fq12 {
18    type Base = Fq2;
19}
20
21impl ExtField for Fq12 {
22    const NON_RESIDUE: Self = Fq12::zero(); // no needs
23
24    fn frobenius_map(&mut self, power: usize) {
25        self.c0.frobenius_map(power);
26        self.c1.frobenius_map(power);
27        self.c1.c0.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
28        self.c1.c1.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
29        self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
30    }
31}
32
33crate::impl_binops_additive!(Fq12, Fq12);
34crate::impl_binops_multiplicative!(Fq12, Fq12);
35crate::impl_binops_calls!(Fq12);
36crate::impl_sum_prod!(Fq12);
37crate::impl_cyclotomic_square!(Fq2, Fq12);
38
39// non_residue^((modulus^i-1)/6) for i=0,...,11
40pub const FROBENIUS_COEFF_FQ12_C1: [Fq2; 12] = [
41    // Fq2(u + 9)**(((q^0) - 1) / 6)
42    // Fq points are represented in Montgomery form with R = 2^256
43    Fq2 {
44        c0: Fq([
45            0xd35d438dc58f0d9d,
46            0x0a78eb28f5c70b3d,
47            0x666ea36f7879462c,
48            0x0e0a77c19a07df2f,
49        ]),
50        c1: Fq([0x0, 0x0, 0x0, 0x0]),
51    },
52    // Fq2(u + 9)**(((q^1) - 1) / 6)
53    Fq2 {
54        c0: Fq([
55            0xaf9ba69633144907,
56            0xca6b1d7387afb78a,
57            0x11bded5ef08a2087,
58            0x02f34d751a1f3a7c,
59        ]),
60        c1: Fq([
61            0xa222ae234c492d72,
62            0xd00f02a4565de15b,
63            0xdc2ff3a253dfc926,
64            0x10a75716b3899551,
65        ]),
66    },
67    // Fq2(u + 9)**(((q^2) - 1) / 6)
68    Fq2 {
69        c0: Fq([
70            0xca8d800500fa1bf2,
71            0xf0c5d61468b39769,
72            0x0e201271ad0d4418,
73            0x04290f65bad856e6,
74        ]),
75        c1: Fq([0x0, 0x0, 0x0, 0x0]),
76    },
77    // Fq2(u + 9)**(((q^3) - 1) / 6)
78    Fq2 {
79        c0: Fq([
80            0x365316184e46d97d,
81            0x0af7129ed4c96d9f,
82            0x659da72fca1009b5,
83            0x08116d8983a20d23,
84        ]),
85        c1: Fq([
86            0xb1df4af7c39c1939,
87            0x3d9f02878a73bf7f,
88            0x9b2220928caf0ae0,
89            0x26684515eff054a6,
90        ]),
91    },
92    // Fq2(u + 9)**(((q^4) - 1) / 6)
93    Fq2 {
94        c0: Fq([
95            0x3350c88e13e80b9c,
96            0x7dce557cdb5e56b9,
97            0x6001b4b8b615564a,
98            0x2682e617020217e0,
99        ]),
100        c1: Fq([0x0, 0x0, 0x0, 0x0]),
101    },
102    // Fq2(u + 9)**(((q^5) - 1) / 6)
103    Fq2 {
104        c0: Fq([
105            0x86b76f821b329076,
106            0x408bf52b4d19b614,
107            0x53dfb9d0d985e92d,
108            0x051e20146982d2a7,
109        ]),
110        c1: Fq([
111            0x0fbc9cd47752ebc7,
112            0x6d8fffe33415de24,
113            0xbef22cf038cf41b9,
114            0x15c0edff3c66bf54,
115        ]),
116    },
117    // Fq2(u + 9)**(((q^6) - 1) / 6)
118    Fq2 {
119        c0: Fq([
120            0x68c3488912edefaa,
121            0x8d087f6872aabf4f,
122            0x51e1a24709081231,
123            0x2259d6b14729c0fa,
124        ]),
125        c1: Fq([0x0, 0x0, 0x0, 0x0]),
126    },
127    // Fq2(u + 9)**(((q^7) - 1) / 6)
128    Fq2 {
129        c0: Fq([
130            0x8c84e580a568b440,
131            0xcd164d1de0c21302,
132            0xa692585790f737d5,
133            0x2d7100fdc71265ad,
134        ]),
135        c1: Fq([
136            0x99fdddf38c33cfd5,
137            0xc77267ed1213e931,
138            0xdc2052142da18f36,
139            0x1fbcf75c2da80ad7,
140        ]),
141    },
142    // Fq2(u + 9)**(((q^8) - 1) / 6)
143    Fq2 {
144        c0: Fq([
145            0x71930c11d782e155,
146            0xa6bb947cffbe3323,
147            0xaa303344d4741444,
148            0x2c3b3f0d26594943,
149        ]),
150        c1: Fq([0x0, 0x0, 0x0, 0x0]),
151    },
152    // Fq2(u + 9)**(((q^9) - 1) / 6)
153    Fq2 {
154        c0: Fq([
155            0x05cd75fe8a3623ca,
156            0x8c8a57f293a85cee,
157            0x52b29e86b7714ea8,
158            0x2852e0e95d8f9306,
159        ]),
160        c1: Fq([
161            0x8a41411f14e0e40e,
162            0x59e26809ddfe0b0d,
163            0x1d2e2523f4d24d7d,
164            0x09fc095cf1414b83,
165        ]),
166    },
167    // Fq2(u + 9)**(((q^10) - 1) / 6)
168    Fq2 {
169        c0: Fq([
170            0x08cfc388c494f1ab,
171            0x19b315148d1373d4,
172            0x584e90fdcb6c0213,
173            0x09e1685bdf2f8849,
174        ]),
175        c1: Fq([0x0, 0x0, 0x0, 0x0]),
176    },
177    // Fq2(u + 9)**(((q^11) - 1) / 6)
178    Fq2 {
179        c0: Fq([
180            0xb5691c94bd4a6cd1,
181            0x56f575661b581478,
182            0x64708be5a7fb6f30,
183            0x2b462e5e77aecd82,
184        ]),
185        c1: Fq([
186            0x2c63ef42612a1180,
187            0x29f16aae345bec69,
188            0xf95e18c648b216a4,
189            0x1aa36073a4cae0d4,
190        ]),
191    },
192];
193
194#[cfg(test)]
195mod test {
196
197    macro_rules! test_fq12 {
198        ($test:ident, $size: expr) => {
199            paste::paste! {
200            #[test]
201            fn [< $test test >]() {
202                use rand::SeedableRng;
203                use rand_xorshift::XorShiftRng;
204                let mut rng = XorShiftRng::from_seed(crate::tests::SEED);
205                crate::bn256::fq12::test::$test(&mut rng, $size);
206            }
207            }
208        };
209    }
210    use ff::Field;
211    use rand::RngCore;
212
213    use super::*;
214    use crate::{arith_test, frobenius_test, setup_f12_test_funcs, test};
215
216    arith_test!(Fq12);
217
218    // F12 specific
219    setup_f12_test_funcs!(Fq12, Fq6, Fq2);
220    test_fq12!(f12_mul_by_014_, 500);
221    test_fq12!(f12_mul_by_034_, 500);
222    frobenius_test!(Fq12, Fq, 8);
223}