pairing_plus/bls12_381/
fq12.rs1use super::fq::FROBENIUS_COEFF_FQ12_C1;
2use super::fq2::Fq2;
3use super::fq6::Fq6;
4use ff::Field;
5use rand_core::RngCore;
6
7#[derive(Copy, Clone, Debug, Eq, PartialEq)]
9pub struct Fq12 {
10 pub c0: Fq6,
11 pub c1: Fq6,
12}
13
14impl ::std::fmt::Display for Fq12 {
15 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
16 write!(f, "Fq12({} + {} * w)", self.c0, self.c1)
17 }
18}
19
20impl Fq12 {
21 pub fn conjugate(&mut self) {
22 self.c1.negate();
23 }
24
25 pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) {
26 let mut aa = self.c0;
27 aa.mul_by_01(c0, c1);
28 let mut bb = self.c1;
29 bb.mul_by_1(c4);
30 let mut o = *c1;
31 o.add_assign(c4);
32 self.c1.add_assign(&self.c0);
33 self.c1.mul_by_01(c0, &o);
34 self.c1.sub_assign(&aa);
35 self.c1.sub_assign(&bb);
36 self.c0 = bb;
37 self.c0.mul_by_nonresidue();
38 self.c0.add_assign(&aa);
39 }
40}
41
42impl Field for Fq12 {
43 fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
44 Fq12 {
45 c0: Fq6::random(rng),
46 c1: Fq6::random(rng),
47 }
48 }
49 fn zero() -> Self {
50 Fq12 {
51 c0: Fq6::zero(),
52 c1: Fq6::zero(),
53 }
54 }
55
56 fn one() -> Self {
57 Fq12 {
58 c0: Fq6::one(),
59 c1: Fq6::zero(),
60 }
61 }
62
63 fn is_zero(&self) -> bool {
64 self.c0.is_zero() && self.c1.is_zero()
65 }
66
67 fn double(&mut self) {
68 self.c0.double();
69 self.c1.double();
70 }
71
72 fn negate(&mut self) {
73 self.c0.negate();
74 self.c1.negate();
75 }
76
77 fn add_assign(&mut self, other: &Self) {
78 self.c0.add_assign(&other.c0);
79 self.c1.add_assign(&other.c1);
80 }
81
82 fn sub_assign(&mut self, other: &Self) {
83 self.c0.sub_assign(&other.c0);
84 self.c1.sub_assign(&other.c1);
85 }
86
87 fn frobenius_map(&mut self, power: usize) {
88 self.c0.frobenius_map(power);
89 self.c1.frobenius_map(power);
90
91 self.c1.c0.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
92 self.c1.c1.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
93 self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
94 }
95
96 fn square(&mut self) {
97 let mut ab = self.c0;
98 ab.mul_assign(&self.c1);
99 let mut c0c1 = self.c0;
100 c0c1.add_assign(&self.c1);
101 let mut c0 = self.c1;
102 c0.mul_by_nonresidue();
103 c0.add_assign(&self.c0);
104 c0.mul_assign(&c0c1);
105 c0.sub_assign(&ab);
106 self.c1 = ab;
107 self.c1.add_assign(&ab);
108 ab.mul_by_nonresidue();
109 c0.sub_assign(&ab);
110 self.c0 = c0;
111 }
112
113 fn mul_assign(&mut self, other: &Self) {
114 let mut aa = self.c0;
115 aa.mul_assign(&other.c0);
116 let mut bb = self.c1;
117 bb.mul_assign(&other.c1);
118 let mut o = other.c0;
119 o.add_assign(&other.c1);
120 self.c1.add_assign(&self.c0);
121 self.c1.mul_assign(&o);
122 self.c1.sub_assign(&aa);
123 self.c1.sub_assign(&bb);
124 self.c0 = bb;
125 self.c0.mul_by_nonresidue();
126 self.c0.add_assign(&aa);
127 }
128
129 fn inverse(&self) -> Option<Self> {
130 let mut c0s = self.c0;
131 c0s.square();
132 let mut c1s = self.c1;
133 c1s.square();
134 c1s.mul_by_nonresidue();
135 c0s.sub_assign(&c1s);
136
137 c0s.inverse().map(|t| {
138 let mut tmp = Fq12 { c0: t, c1: t };
139 tmp.c0.mul_assign(&self.c0);
140 tmp.c1.mul_assign(&self.c1);
141 tmp.c1.negate();
142
143 tmp
144 })
145 }
146}
147
148#[cfg(test)]
149use rand_core::SeedableRng;
150#[test]
153fn test_fq12_mul_by_014() {
154 let mut rng = rand_xorshift::XorShiftRng::from_seed([
155 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
156 0xe5,
157 ]);
158 for _ in 0..1000 {
159 let c0 = Fq2::random(&mut rng);
160 let c1 = Fq2::random(&mut rng);
161 let c5 = Fq2::random(&mut rng);
162 let mut a = Fq12::random(&mut rng);
163 let mut b = a;
164
165 a.mul_by_014(&c0, &c1, &c5);
166 b.mul_assign(&Fq12 {
167 c0: Fq6 {
168 c0,
169 c1,
170 c2: Fq2::zero(),
171 },
172 c1: Fq6 {
173 c0: Fq2::zero(),
174 c1: c5,
175 c2: Fq2::zero(),
176 },
177 });
178
179 assert_eq!(a, b);
180 }
181}
182
183#[test]
184fn fq12_field_tests() {
185 use ff::PrimeField;
186
187 ::tests::field::random_field_tests::<Fq12>();
188 ::tests::field::random_frobenius_tests::<Fq12, _>(super::fq::Fq::char(), 13);
189}