1mod fp;
2mod fq2;
3mod fq6;
4mod fq12;
5
6use crate::arith::U256;
7use rand::Rng;
8use core::ops::{Add, Mul, Neg, Sub};
9use alloc::fmt::Debug;
10
11pub use self::fp::{const_fq, Fq, Fr};
12pub use self::fq2::{Fq2, fq2_nonresidue};
13pub use self::fq6::Fq6;
14pub use self::fq12::Fq12;
15
16pub trait FieldElement
17 : Sized
18 + Copy
19 + Clone
20 + Add<Output = Self>
21 + Sub<Output = Self>
22 + Mul<Output = Self>
23 + Neg<Output = Self>
24 + PartialEq
25 + Eq
26 + Debug {
27 fn zero() -> Self;
28 fn one() -> Self;
29 fn random<R: Rng>(_: &mut R) -> Self;
30 fn is_zero(&self) -> bool;
31 fn squared(&self) -> Self {
32 (*self) * (*self)
33 }
34 fn inverse(self) -> Option<Self>;
35 fn pow<I: Into<U256>>(&self, by: I) -> Self {
36 let mut res = Self::one();
37
38 for i in by.into().bits() {
39 res = res.squared();
40 if i {
41 res = *self * res;
42 }
43 }
44
45 res
46 }
47}
48
49#[cfg(test)]
50mod tests;
51
52#[test]
53fn test_fr() {
54 tests::field_trials::<Fr>();
55}
56
57#[test]
58fn test_fq() {
59 tests::field_trials::<Fq>();
60}
61
62#[test]
63fn test_fq2() {
64 tests::field_trials::<Fq2>();
65}
66
67#[test]
68fn test_str() {
69 assert_eq!(
70 -Fr::one(),
71 Fr::from_str(
72 "21888242871839275222246405745257275088548364400416034343698204186575808495616"
73 ).unwrap()
74 );
75 assert_eq!(
76 -Fq::one(),
77 Fq::from_str(
78 "21888242871839275222246405745257275088696311157297823662689037894645226208582"
79 ).unwrap()
80 );
81}
82
83#[test]
84fn test_fq6() {
85 tests::field_trials::<Fq6>();
86}
87
88#[test]
89fn test_fq12() {
90 tests::field_trials::<Fq12>();
91}
92
93#[test]
94fn fq12_test_vector() {
95 let start = Fq12::new(
96 Fq6::new(
97 Fq2::new(
98 Fq::from_str(
99 "19797905000333868150253315089095386158892526856493194078073564469188852136946",
100 ).unwrap(),
101 Fq::from_str(
102 "10509658143212501778222314067134547632307419253211327938344904628569123178733",
103 ).unwrap(),
104 ),
105 Fq2::new(
106 Fq::from_str(
107 "208316612133170645758860571704540129781090973693601051684061348604461399206",
108 ).unwrap(),
109 Fq::from_str(
110 "12617661120538088237397060591907161689901553895660355849494983891299803248390",
111 ).unwrap(),
112 ),
113 Fq2::new(
114 Fq::from_str(
115 "2897490589776053688661991433341220818937967872052418196321943489809183508515",
116 ).unwrap(),
117 Fq::from_str(
118 "2730506433347642574983433139433778984782882168213690554721050571242082865799",
119 ).unwrap(),
120 ),
121 ),
122 Fq6::new(
123 Fq2::new(
124 Fq::from_str(
125 "17870056122431653936196746815433147921488990391314067765563891966783088591110",
126 ).unwrap(),
127 Fq::from_str(
128 "14314041658607615069703576372547568077123863812415914883625850585470406221594",
129 ).unwrap(),
130 ),
131 Fq2::new(
132 Fq::from_str(
133 "10123533891707846623287020000407963680629966110211808794181173248765209982878",
134 ).unwrap(),
135 Fq::from_str(
136 "5062091880848845693514855272640141851746424235009114332841857306926659567101",
137 ).unwrap(),
138 ),
139 Fq2::new(
140 Fq::from_str(
141 "9839781502639936537333620974973645053542086898304697594692219798017709586567",
142 ).unwrap(),
143 Fq::from_str(
144 "1583892292110602864638265389721494775152090720173641072176370350017825640703",
145 ).unwrap(),
146 ),
147 ),
148 );
149
150 let mut next = start.clone();
153 for _ in 0..100 {
154 next = next * start;
155 }
156
157 let cpy = next.clone();
158
159 for _ in 0..10 {
160 next = next.squared();
161 }
162
163 for _ in 0..10 {
164 next = next + start;
165 next = next - cpy;
166 next = -next;
167 }
168
169 next = next.squared();
170
171 let finally = Fq12::new(
172 Fq6::new(
173 Fq2::new(
174 Fq::from_str(
175 "18388750939593263065521177085001223024106699964957029146547831509155008229833",
176 ).unwrap(),
177 Fq::from_str(
178 "18370529854582635460997127698388761779167953912610241447912705473964014492243",
179 ).unwrap(),
180 ),
181 Fq2::new(
182 Fq::from_str(
183 "3691824277096717481466579496401243638295254271265821828017111951446539785268",
184 ).unwrap(),
185 Fq::from_str(
186 "20513494218085713799072115076991457239411567892860153903443302793553884247235",
187 ).unwrap(),
188 ),
189 Fq2::new(
190 Fq::from_str(
191 "12214155472433286415803224222551966441740960297013786627326456052558698216399",
192 ).unwrap(),
193 Fq::from_str(
194 "10987494248070743195602580056085773610850106455323751205990078881956262496575",
195 ).unwrap(),
196 ),
197 ),
198 Fq6::new(
199 Fq2::new(
200 Fq::from_str(
201 "5134522153456102954632718911439874984161223687865160221119284322136466794876",
202 ).unwrap(),
203 Fq::from_str(
204 "20119236909927036376726859192821071338930785378711977469360149362002019539920",
205 ).unwrap(),
206 ),
207 Fq2::new(
208 Fq::from_str(
209 "8839766648621210419302228913265679710586991805716981851373026244791934012854",
210 ).unwrap(),
211 Fq::from_str(
212 "9103032146464138788288547957401673544458789595252696070370942789051858719203",
213 ).unwrap(),
214 ),
215 Fq2::new(
216 Fq::from_str(
217 "10378379548636866240502412547812481928323945124508039853766409196375806029865",
218 ).unwrap(),
219 Fq::from_str(
220 "9021627154807648093720460686924074684389554332435186899318369174351765754041",
221 ).unwrap(),
222 ),
223 ),
224 );
225
226 assert_eq!(finally, next);
227}
228
229#[test]
230fn test_cyclotomic_exp() {
231 let orig = Fq12::new(
232 Fq6::new(
233 Fq2::new(
234 Fq::from_str(
235 "2259924035228092997691937637688451143058635253053054071159756458902878894295",
236 ).unwrap(),
237 Fq::from_str(
238 "13145690032701362144460254305183927872683620413225364127064863863535255135244",
239 ).unwrap(),
240 ),
241 Fq2::new(
242 Fq::from_str(
243 "9910063591662383599552477067956819406417086889312288278252482503717089428441",
244 ).unwrap(),
245 Fq::from_str(
246 "537414042055419261990282459138081732565514913399498746664966841152381183961",
247 ).unwrap(),
248 ),
249 Fq2::new(
250 Fq::from_str(
251 "15311812409497308894370893420777496684951030254049554818293571309705780605004",
252 ).unwrap(),
253 Fq::from_str(
254 "13657107176064455789881282546557276003626320193974643644160350907227082365810",
255 ).unwrap(),
256 ),
257 ),
258 Fq6::new(
259 Fq2::new(
260 Fq::from_str(
261 "4913017949003742946864670837361832856526234260447029873580022776602534856819",
262 ).unwrap(),
263 Fq::from_str(
264 "7834351480852267338070670220119081676575418514182895774094743209915633114041",
265 ).unwrap(),
266 ),
267 Fq2::new(
268 Fq::from_str(
269 "12837298223308203788092748646758194441270207338661891973231184407371206766993",
270 ).unwrap(),
271 Fq::from_str(
272 "12756474445699147370503225379431475413909971718057034061593007812727141391799",
273 ).unwrap(),
274 ),
275 Fq2::new(
276 Fq::from_str(
277 "9473802207170192255373153510655867502408045964296373712891954747252332944018",
278 ).unwrap(),
279 Fq::from_str(
280 "4583089109360519374075173304035813179013579459429335467869926761027310749713",
281 ).unwrap(),
282 ),
283 ),
284 );
285
286 let expected = Fq12::new(
287 Fq6::new(
288 Fq2::new(
289 Fq::from_str(
290 "14722956046055152398903846391223329501345567382234608299399030576415080188350",
291 ).unwrap(),
292 Fq::from_str(
293 "14280703280777926697010730619606819467080027543707671882210769811674790473417",
294 ).unwrap(),
295 ),
296 Fq2::new(
297 Fq::from_str(
298 "19969875076083990244184003223190771301761436396530543002586073549972410735411",
299 ).unwrap(),
300 Fq::from_str(
301 "10717335566913889643303549252432531178405520196706173198634734518494041323243",
302 ).unwrap(),
303 ),
304 Fq2::new(
305 Fq::from_str(
306 "6063612626166484870786832843320782567259894784043383626084549455432890717937",
307 ).unwrap(),
308 Fq::from_str(
309 "17089783040131779205038789608891431427943860868115199598200376195935079808729",
310 ).unwrap(),
311 ),
312 ),
313 Fq6::new(
314 Fq2::new(
315 Fq::from_str(
316 "10029863438921507421569931792104023129735006154272482043027653425575205672906",
317 ).unwrap(),
318 Fq::from_str(
319 "6406252222753462799887280578845937185621081001436094637606245493619821542775",
320 ).unwrap(),
321 ),
322 Fq2::new(
323 Fq::from_str(
324 "1048245462913506652602966692378792381004227332967846949234978073448561848050",
325 ).unwrap(),
326 Fq::from_str(
327 "1444281375189053827455518242624554285012408033699861764136810522738182087554",
328 ).unwrap(),
329 ),
330 Fq2::new(
331 Fq::from_str(
332 "8839610992666735109106629514135300820412539620261852250193684883379364789120",
333 ).unwrap(),
334 Fq::from_str(
335 "11347360242067273846784836674906058940820632082713814508736182487171407730718",
336 ).unwrap(),
337 ),
338 ),
339 );
340
341 let e = orig.exp_by_neg_z();
342
343 assert_eq!(e, expected);
344}