halo2curves_axiom/bls12_381/hash_to_curve/chain.rs
1//! Addition chains for computing square roots.
2//! chain_pm3div4: input x, output x^((p-3)//4).
3//! chain_p2m9div16: input x, output x^((p**2 - 9) // 16).
4//!
5//! Source: <https://github.com/privacy-scaling-explorations/bls12_381>
6
7use core::ops::MulAssign;
8
9use crate::bls12_381::{fp::Fp, fp2::Fp2};
10
11macro_rules! square {
12 ($var:expr, $n:expr) => {
13 for _ in 0..$n {
14 $var = $var.square();
15 }
16 };
17}
18
19#[allow(clippy::cognitive_complexity)]
20/// addchain for 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946
21/// Bos-Coster (win=4) : 458 links, 16 variables */
22/// Addition chain implementing exponentiation by (p - 3) // 4.
23pub fn chain_pm3div4(var0: &Fp) -> Fp {
24 let mut var1 = var0.square();
25 //Self::sqr(var1, var0); /* 0 : 2 */
26 let var9 = var1 * var0;
27 //Self::mul(&mut var9, var1, var0); /* 1 : 3 */
28 let var5 = var1.square();
29 //Self::sqr(&mut var5, var1); /* 2 : 4 */
30 let var2 = var9 * var1;
31 //Self::mul(&mut var2, &var9, var1); /* 3 : 5 */
32 let var7 = var5 * var9;
33 //Self::mul(&mut var7, &var5, &var9); /* 4 : 7 */
34 let var10 = var2 * var5;
35 //Self::mul(&mut var10, &var2, &var5); /* 5 : 9 */
36 let var13 = var7 * var5;
37 //Self::mul(&mut var13, &var7, &var5); /* 6 : 11 */
38 let var4 = var10 * var5;
39 //Self::mul(&mut var4, &var10, &var5); /* 7 : 13 */
40 let var8 = var13 * var5;
41 //Self::mul(&mut var8, &var13, &var5); /* 8 : 15 */
42 let var15 = var4 * var5;
43 //Self::mul(&mut var15, &var4, &var5); /* 9 : 17 */
44 let var11 = var8 * var5;
45 //Self::mul(&mut var11, &var8, &var5); /* 10 : 19 */
46 let var3 = var15 * var5;
47 //Self::mul(&mut var3, &var15, &var5); /* 11 : 21 */
48 let var12 = var11 * var5;
49 //Self::mul(&mut var12, &var11, &var5); /* 12 : 23 */
50 var1 = var4.square();
51 //Self::sqr(var1, &var4); /* 13 : 26 */
52 let var14 = var12 * var5;
53 //Self::mul(&mut var14, &var12, &var5); /* 14 : 27 */
54 let var6 = var1 * var9;
55 //Self::mul(&mut var6, var1, &var9); /* 15 : 29 */
56 let var5 = var1 * var2;
57 //Self::mul(&mut var5, var1, &var2); /* 16 : 31 */
58 // 17 : 106496
59 square!(var1, 12);
60 // 29 : 106513
61 var1.mul_assign(&var15);
62 // 30 : 13633664
63 square!(var1, 7);
64 // 37 : 13633679
65 var1.mul_assign(&var8);
66 // 38 : 218138864
67 square!(var1, 4);
68 // 42 : 218138869
69 var1.mul_assign(&var2);
70 // 43 : 13960887616
71 square!(var1, 6);
72 // 49 : 13960887623
73 var1.mul_assign(&var7);
74 // 50 : 1786993615744
75 square!(var1, 7);
76 // 57 : 1786993615767
77 var1.mul_assign(&var12);
78 // 58 : 57183795704544
79 square!(var1, 5);
80 // 63 : 57183795704575
81 var1.mul_assign(&var5);
82 // 64 : 228735182818300
83 square!(var1, 2);
84 // 66 : 228735182818303
85 var1.mul_assign(&var9);
86 // 67 : 14639051700371392
87 square!(var1, 6);
88 // 73 : 14639051700371405
89 var1.mul_assign(&var4);
90 // 74 : 936899308823769920
91 square!(var1, 6);
92 // 80 : 936899308823769933
93 var1.mul_assign(&var4);
94 // 81 : 59961555764721275712
95 square!(var1, 6);
96 // 87 : 59961555764721275721
97 var1.mul_assign(&var10);
98 // 88 : 479692446117770205768
99 square!(var1, 3);
100 // 91 : 479692446117770205771
101 var1.mul_assign(&var9);
102 // 92 : 61400633103074586338688
103 square!(var1, 7);
104 // 99 : 61400633103074586338701
105 var1.mul_assign(&var4);
106 // 100 : 982410129649193381419216
107 square!(var1, 4);
108 // 104 : 982410129649193381419229
109 var1.mul_assign(&var4);
110 // 105 : 62874248297548376410830656
111 square!(var1, 6);
112 // 111 : 62874248297548376410830671
113 var1.mul_assign(&var8);
114 // 112 : 4023951891043096090293162944
115 square!(var1, 6);
116 // 118 : 4023951891043096090293162971
117 var1.mul_assign(&var14);
118 // 119 : 32191615128344768722345303768
119 square!(var1, 3);
120 // 122 : 32191615128344768722345303769
121 var1.mul_assign(var0);
122 // 123 : 8241053472856260792920397764864
123 square!(var1, 8);
124 // 131 : 8241053472856260792920397764877
125 var1.mul_assign(&var4);
126 // 132 : 1054854844525601381493810913904256
127 square!(var1, 7);
128 // 139 : 1054854844525601381493810913904279
129 var1.mul_assign(&var12);
130 // 140 : 33755355024819244207801949244936928
131 square!(var1, 5);
132 // 145 : 33755355024819244207801949244936939
133 var1.mul_assign(&var13);
134 // 146 : 2160342721588431629299324751675964096
135 square!(var1, 6);
136 // 152 : 2160342721588431629299324751675964109
137 var1.mul_assign(&var4);
138 // 153 : 138261934181659624275156784107261702976
139 square!(var1, 6);
140 // 159 : 138261934181659624275156784107261703005
141 var1.mul_assign(&var6);
142 // 160 : 2212190946906553988402508545716187248080
143 square!(var1, 4);
144 // 164 : 2212190946906553988402508545716187248089
145 var1.mul_assign(&var10);
146 // 165 : 566320882408077821031042187703343935510784
147 square!(var1, 8);
148 // 173 : 566320882408077821031042187703343935510813
149 var1.mul_assign(&var6);
150 // 174 : 9061134118529245136496675003253502968173008
151 square!(var1, 4);
152 // 178 : 9061134118529245136496675003253502968173021
153 var1.mul_assign(&var4);
154 // 179 : 1159825167171743377471574400416448379926146688
155 square!(var1, 7);
156 // 186 : 1159825167171743377471574400416448379926146711
157 var1.mul_assign(&var12);
158 // 187 : 593830485591932609265446093013221570522187116032
159 square!(var1, 9);
160 // 196 : 593830485591932609265446093013221570522187116051
161 var1.mul_assign(&var11);
162 // 197 : 2375321942367730437061784372052886282088748464204
163 square!(var1, 2);
164 // 199 : 2375321942367730437061784372052886282088748464207
165 var1.mul_assign(&var9);
166 // 200 : 76010302155767373985977099905692361026839950854624
167 square!(var1, 5);
168 // 205 : 76010302155767373985977099905692361026839950854631
169 var1.mul_assign(&var7);
170 // 206 : 9729318675938223870205068787928622211435513709392768
171 square!(var1, 7);
172 // 213 : 9729318675938223870205068787928622211435513709392773
173 var1.mul_assign(&var2);
174 // 214 : 1245352790520092655386248804854863643063745754802274944
175 square!(var1, 7);
176 // 221 : 1245352790520092655386248804854863643063745754802274953
177 var1.mul_assign(&var10);
178 // 222 : 79702578593285929944719923510711273156079728307345596992
179 square!(var1, 6);
180 // 228 : 79702578593285929944719923510711273156079728307345597015
181 var1.mul_assign(&var12);
182 // 229 : 2550482514985149758231037552342760740994551305835059104480
183 square!(var1, 5);
184 // 234 : 2550482514985149758231037552342760740994551305835059104509
185 var1.mul_assign(&var6);
186 // 235 : 81615440479524792263393201674968343711825641786721891344288
187 square!(var1, 5);
188 // 240 : 81615440479524792263393201674968343711825641786721891344307
189 var1.mul_assign(&var11);
190 // 241 : 2611694095344793352428582453598986998778420537175100523017824
191 square!(var1, 5);
192 // 246 : 2611694095344793352428582453598986998778420537175100523017843
193 var1.mul_assign(&var11);
194 // 247 : 668593688408267098221717108121340671687275657516825733892567808
195 square!(var1, 8);
196 // 255 : 668593688408267098221717108121340671687275657516825733892567821
197 var1.mul_assign(&var4);
198 // 256 : 85579992116258188572379789839531605975971284162153693938248681088
199 square!(var1, 7);
200 // 263 : 85579992116258188572379789839531605975971284162153693938248681109
201 var1.mul_assign(&var3);
202 // 264 : 43816955963524192549058452397840182259697297491022691296383324727808
203 square!(var1, 9);
204 // 273 : 43816955963524192549058452397840182259697297491022691296383324727823
205 var1.mul_assign(&var8);
206 // 274 : 1402142590832774161569870476730885832310313519712726121484266391290336
207 square!(var1, 5);
208 // 279 : 1402142590832774161569870476730885832310313519712726121484266391290349
209 var1.mul_assign(&var4);
210 // 280 : 11217140726662193292558963813847086658482508157701808971874131130322792
211 square!(var1, 3);
212 // 283 : 11217140726662193292558963813847086658482508157701808971874131130322795
213 var1.mul_assign(&var9);
214 // 284 : 2871588026025521482895094736344854184571522088371663096799777569362635520
215 square!(var1, 8);
216 // 292 : 2871588026025521482895094736344854184571522088371663096799777569362635535
217 var1.mul_assign(&var8);
218 // 293 : 22972704208204171863160757890758833476572176706973304774398220554901084280
219 square!(var1, 3);
220 // 296 : 22972704208204171863160757890758833476572176706973304774398220554901084283
221 var1.mul_assign(&var9);
222 // 297 : 2940506138650133998484577010017130685001238618492583011122972231027338788224
223 square!(var1, 7);
224 // 304 : 2940506138650133998484577010017130685001238618492583011122972231027338788233
225 var1.mul_assign(&var10);
226 // 305 : 1505539142988868607224103429128770910720634172668202501694961782285997459575296
227 square!(var1, 9);
228 // 314 : 1505539142988868607224103429128770910720634172668202501694961782285997459575311
229 var1.mul_assign(&var8);
230 // 315 : 96354505151287590862342619464241338286120587050764960108477554066303837412819904
231 square!(var1, 6);
232 // 321 : 96354505151287590862342619464241338286120587050764960108477554066303837412819925
233 var1.mul_assign(&var3);
234 // 322 : 6166688329682405815189927645711445650311717571248957446942563460243445594420475200
235 square!(var1, 6);
236 // 328 : 6166688329682405815189927645711445650311717571248957446942563460243445594420475231
237 var1.mul_assign(&var5);
238 // 329 : 197334026549836986086077684662766260809974962279966638302162030727790259021455207392
239 square!(var1, 5);
240 // 334 : 197334026549836986086077684662766260809974962279966638302162030727790259021455207423
241 var1.mul_assign(&var5);
242 // 335 : 6314688849594783554754485909208520345919198792958932425669184983289288288686566637536
243 square!(var1, 5);
244 // 340 : 6314688849594783554754485909208520345919198792958932425669184983289288288686566637567
245 var1.mul_assign(&var5);
246 // 341 : 101035021593516536876071774547336325534707180687342918810706959732628612618985066201072
247 square!(var1, 4);
248 // 345 : 101035021593516536876071774547336325534707180687342918810706959732628612618985066201085
249 var1.mul_assign(&var4);
250 // 346 : 808280172748132295008574196378690604277657445498743350485655677861028900951880529608680
251 square!(var1, 3);
252 // 349 : 808280172748132295008574196378690604277657445498743350485655677861028900951880529608683
253 var1.mul_assign(&var9);
254 // 350 : 206919724223521867522194994272944794695080306047678297724327853532423398643681415579822848
255 square!(var1, 8);
256 // 358 : 206919724223521867522194994272944794695080306047678297724327853532423398643681415579822869
257 var1.mul_assign(&var3);
258 // 359 : 26485724700610799042840959266936933720970279174102822108713965252150195026391221194217327232
259 square!(var1, 7);
260 // 366 : 26485724700610799042840959266936933720970279174102822108713965252150195026391221194217327263
261 var1.mul_assign(&var5);
262 // 367 : 847543190419545569370910696541981879071048933571290307478846888068806240844519078214954472416
263 square!(var1, 5);
264 // 372 : 847543190419545569370910696541981879071048933571290307478846888068806240844519078214954472447
265 var1.mul_assign(&var5);
266 // 373 : 27121382093425458219869142289343420130273565874281289839323100418201799707024610502878543118304
267 square!(var1, 5);
268 // 378 : 27121382093425458219869142289343420130273565874281289839323100418201799707024610502878543118335
269 var1.mul_assign(&var5);
270 // 379 : 433942113494807331517906276629494722084377053988500637429169606691228795312393768046056689893360
271 square!(var1, 4);
272 // 383 : 433942113494807331517906276629494722084377053988500637429169606691228795312393768046056689893375
273 var1.mul_assign(&var8);
274 // 384 : 6943073815916917304286500426071915553350032863816010198866713707059660724998300288736907038294000
275 square!(var1, 4);
276 // 388 : 6943073815916917304286500426071915553350032863816010198866713707059660724998300288736907038294007
277 var1.mul_assign(&var7);
278 // 389 : 888713448437365414948672054537205190828804206568449305454939354503636572799782436958324100901632896
279 square!(var1, 7);
280 // 396 : 888713448437365414948672054537205190828804206568449305454939354503636572799782436958324100901632927
281 var1.mul_assign(&var5);
282 // 397 : 28438830349995693278357505745190566106521734610190377774558059344116370329593037982666371228852253664
283 square!(var1, 5);
284 // 402 : 28438830349995693278357505745190566106521734610190377774558059344116370329593037982666371228852253693
285 var1.mul_assign(&var6);
286 // 403 : 910042571199862184907440183846098115408695507526092088785857899011723850546977215445323879323272118176
287 square!(var1, 5);
288 // 408 : 910042571199862184907440183846098115408695507526092088785857899011723850546977215445323879323272118207
289 var1.mul_assign(&var5);
290 // 409 : 29121362278395589917038085883075139693078256240834946841147452768375163217503270894250364138344707782624
291 square!(var1, 5);
292 // 414 : 29121362278395589917038085883075139693078256240834946841147452768375163217503270894250364138344707782655
293 var1.mul_assign(&var5);
294 // 415 : 931883592908658877345218748258404470178504199706718298916718488588005222960104668616011652427030649044960
295 square!(var1, 5);
296 // 420 : 931883592908658877345218748258404470178504199706718298916718488588005222960104668616011652427030649044991
297 var1.mul_assign(&var5);
298 // 421 : 29820274973077084075046999944268943045712134390614985565334991634816167134723349395712372877664980769439712
299 square!(var1, 5);
300 // 426 : 29820274973077084075046999944268943045712134390614985565334991634816167134723349395712372877664980769439743
301 var1.mul_assign(&var5);
302 // 427 : 954248799138466690401503998216606177462788300499679538090719732314117348311147180662795932085279384622071776
303 square!(var1, 5);
304 // 432 : 954248799138466690401503998216606177462788300499679538090719732314117348311147180662795932085279384622071807
305 var1.mul_assign(&var5);
306 // 433 : 30535961572430934092848127942931397678809225615989745218903031434051755145956709781209469826728940307906297824
307 square!(var1, 5);
308 // 438 : 30535961572430934092848127942931397678809225615989745218903031434051755145956709781209469826728940307906297855
309 var1.mul_assign(&var5);
310 // 439 : 488575385158894945485570047086902362860947609855835923502448502944828082335307356499351517227663044926500765680
311 square!(var1, 4);
312 // 443 : 488575385158894945485570047086902362860947609855835923502448502944828082335307356499351517227663044926500765693
313 var1.mul_assign(&var4);
314 // 444 : 31268824650169276511076483013561751223100647030773499104156704188468997269459670815958497102570434875296049004352
315 square!(var1, 6);
316 // 450 : 31268824650169276511076483013561751223100647030773499104156704188468997269459670815958497102570434875296049004373
317 var1.mul_assign(&var3);
318 // 451 : 500301194402708424177223728216988019569610352492375985666507267015503956311354733055335953641126958004736784069968
319 square!(var1, 4);
320 // 455 : 500301194402708424177223728216988019569610352492375985666507267015503956311354733055335953641126958004736784069973
321 var1.mul_assign(&var2);
322 // 456 : 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946
323 var1.square()
324}
325
326#[allow(clippy::cognitive_complexity)]
327/// addchain for 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835
328/// Bos-Coster (win=4) : 895 links, 17 variables
329/// Addition chain implementing exponentiation by (p**2 - 9) // 16.
330pub fn chain_p2m9div16(var0: &Fp2) -> Fp2 {
331 let mut var1 = var0.square();
332 //Self::sqr(var1, var0); /* 0 : 2 */
333 let var2 = var1 * var0;
334 //Self::mul(&mut var2, var1, var0); /* 1 : 3 */
335 let var15 = var2 * var1;
336 //Self::mul(&mut var15, &var2, var1); /* 2 : 5 */
337 let var3 = var15 * var1;
338 //Self::mul(&mut var3, &var15, var1); /* 3 : 7 */
339 let var14 = var3 * var1;
340 //Self::mul(&mut var14, &var3, var1); /* 4 : 9 */
341 let var13 = var14 * var1;
342 //Self::mul(&mut var13, &var14, var1); /* 5 : 11 */
343 let var5 = var13 * var1;
344 //Self::mul(&mut var5, &var13, var1); /* 6 : 13 */
345 let var10 = var5 * var1;
346 //Self::mul(&mut var10, &var5, var1); /* 7 : 15 */
347 let var9 = var10 * var1;
348 //Self::mul(&mut var9, &var10, var1); /* 8 : 17 */
349 let var16 = var9 * var1;
350 //Self::mul(&mut var16, &var9, var1); /* 9 : 19 */
351 let var4 = var16 * var1;
352 //Self::mul(&mut var4, &var16, var1); /* 10 : 21 */
353 let var7 = var4 * var1;
354 //Self::mul(&mut var7, &var4, var1); /* 11 : 23 */
355 let var6 = var7 * var1;
356 //Self::mul(&mut var6, &var7, var1); /* 12 : 25 */
357 let var12 = var6 * var1;
358 //Self::mul(&mut var12, &var6, var1); /* 13 : 27 */
359 let var8 = var12 * var1;
360 //Self::mul(&mut var8, &var12, var1); /* 14 : 29 */
361 let var11 = var8 * var1;
362 //Self::mul(&mut var11, &var8, var1); /* 15 : 31 */
363 var1 = var4.square();
364 //Self::sqr(var1, &var4); /* 16 : 42 */
365 // 17 : 168
366 square!(var1, 2);
367 // 19 : 169
368 var1.mul_assign(var0);
369 // 20 : 86528
370 square!(var1, 9);
371 // 29 : 86555
372 var1.mul_assign(&var12);
373 // 30 : 1384880
374 square!(var1, 4);
375 // 34 : 1384893
376 var1.mul_assign(&var5);
377 // 35 : 88633152
378 square!(var1, 6);
379 // 41 : 88633161
380 var1.mul_assign(&var14);
381 // 42 : 1418130576
382 square!(var1, 4);
383 // 46 : 1418130583
384 var1.mul_assign(&var3);
385 // 47 : 45380178656
386 square!(var1, 5);
387 // 52 : 45380178659
388 var1.mul_assign(&var2);
389 // 53 : 11617325736704
390 square!(var1, 8);
391 // 61 : 11617325736717
392 var1.mul_assign(&var5);
393 // 62 : 185877211787472
394 square!(var1, 4);
395 // 66 : 185877211787479
396 var1.mul_assign(&var3);
397 // 67 : 2974035388599664
398 square!(var1, 4);
399 // 71 : 2974035388599679
400 var1.mul_assign(&var10);
401 // 72 : 761353059481517824
402 square!(var1, 8);
403 // 80 : 761353059481517853
404 var1.mul_assign(&var8);
405 // 81 : 48726595806817142592
406 square!(var1, 6);
407 // 87 : 48726595806817142603
408 var1.mul_assign(&var13);
409 // 88 : 779625532909074281648
410 square!(var1, 4);
411 // 92 : 779625532909074281661
412 var1.mul_assign(&var5);
413 // 93 : 6237004263272594253288
414 square!(var1, 3);
415 // 96 : 6237004263272594253289
416 var1.mul_assign(var0);
417 // 97 : 399168272849446032210496
418 square!(var1, 6);
419 // 103 : 399168272849446032210511
420 var1.mul_assign(&var10);
421 // 104 : 102187077849458184245890816
422 square!(var1, 8);
423 // 112 : 102187077849458184245890845
424 var1.mul_assign(&var8);
425 // 113 : 6539972982365323791737014080
426 square!(var1, 6);
427 // 119 : 6539972982365323791737014101
428 var1.mul_assign(&var4);
429 // 120 : 1674233083485522890684675609856
430 square!(var1, 8);
431 // 128 : 1674233083485522890684675609873
432 var1.mul_assign(&var9);
433 // 129 : 53575458671536732501909619515936
434 square!(var1, 5);
435 // 134 : 53575458671536732501909619515951
436 var1.mul_assign(&var10);
437 // 135 : 3428829354978350880122215649020864
438 square!(var1, 6);
439 // 141 : 3428829354978350880122215649020873
440 var1.mul_assign(&var14);
441 // 142 : 109722539359307228163910900768667936
442 square!(var1, 5);
443 // 147 : 109722539359307228163910900768667951
444 var1.mul_assign(&var10);
445 // 148 : 438890157437228912655643603074671804
446 square!(var1, 2);
447 // 150 : 438890157437228912655643603074671805
448 var1.mul_assign(var0);
449 // 151 : 28088970075982650409961190596778995520
450 square!(var1, 6);
451 // 157 : 28088970075982650409961190596778995535
452 var1.mul_assign(&var10);
453 // 158 : 3595388169725779252475032396387711428480
454 square!(var1, 7);
455 // 165 : 3595388169725779252475032396387711428491
456 var1.mul_assign(&var13);
457 // 166 : 57526210715612468039600518342203382855856
458 square!(var1, 4);
459 // 170 : 57526210715612468039600518342203382855863
460 var1.mul_assign(&var3);
461 // 171 : 3681677485799197954534433173901016502775232
462 square!(var1, 6);
463 // 177 : 3681677485799197954534433173901016502775241
464 var1.mul_assign(&var14);
465 // 178 : 471254718182297338180407446259330112355230848
466 square!(var1, 7);
467 // 185 : 471254718182297338180407446259330112355230855
468 var1.mul_assign(&var3);
469 // 186 : 15080150981833514821773038280298563595367387360
470 square!(var1, 5);
471 // 191 : 15080150981833514821773038280298563595367387365
472 var1.mul_assign(&var15);
473 // 192 : 1930259325674689897186948899878216140207025582720
474 square!(var1, 7);
475 // 199 : 1930259325674689897186948899878216140207025582727
476 var1.mul_assign(&var3);
477 // 200 : 61768298421590076709982364796102916486624818647264
478 square!(var1, 5);
479 // 205 : 61768298421590076709982364796102916486624818647271
480 var1.mul_assign(&var3);
481 // 206 : 63250737583708238551021941551209386482303814294805504
482 square!(var1, 10);
483 // 216 : 63250737583708238551021941551209386482303814294805521
484 var1.mul_assign(&var9);
485 // 217 : 506005900669665908408175532409675091858430514358444168
486 square!(var1, 3);
487 // 220 : 506005900669665908408175532409675091858430514358444173
488 var1.mul_assign(&var15);
489 // 221 : 16192188821429309069061617037109602939469776459470213536
490 square!(var1, 5);
491 // 226 : 16192188821429309069061617037109602939469776459470213549
492 var1.mul_assign(&var5);
493 // 227 : 4145200338285903121679773961500058352504262773624374668544
494 square!(var1, 8);
495 // 235 : 4145200338285903121679773961500058352504262773624374668569
496 var1.mul_assign(&var6);
497 // 236 : 132646410825148899893752766768001867280136408755979989394208
498 square!(var1, 5);
499 // 241 : 132646410825148899893752766768001867280136408755979989394231
500 var1.mul_assign(&var7);
501 // 242 : 8489370292809529593200177073152119505928730160382719321230784
502 square!(var1, 6);
503 // 248 : 8489370292809529593200177073152119505928730160382719321230795
504 var1.mul_assign(&var13);
505 // 249 : 543319698739809893964811332681735648379438730264494036558770880
506 square!(var1, 6);
507 // 255 : 543319698739809893964811332681735648379438730264494036558770895
508 var1.mul_assign(&var10);
509 // 256 : 34772460719347833213747925291631081496284078736927618339761337280
510 square!(var1, 6);
511 // 262 : 34772460719347833213747925291631081496284078736927618339761337289
512 var1.mul_assign(&var14);
513 // 263 : 4450874972076522651359734437328778431524362078326735147489451172992
514 square!(var1, 7);
515 // 270 : 4450874972076522651359734437328778431524362078326735147489451173011
516 var1.mul_assign(&var16);
517 // 271 : 142427999106448724843511501994520909808779586506455524719662437536352
518 square!(var1, 5);
519 // 276 : 142427999106448724843511501994520909808779586506455524719662437536361
520 var1.mul_assign(&var14);
521 // 277 : 9115391942812718389984736127649338227761893536413153582058396002327104
522 square!(var1, 6);
523 // 283 : 9115391942812718389984736127649338227761893536413153582058396002327119
524 var1.mul_assign(&var10);
525 // 284 : 583385084340013976959023112169557646576761186330441829251737344148935616
526 square!(var1, 6);
527 // 290 : 583385084340013976959023112169557646576761186330441829251737344148935633
528 var1.mul_assign(&var9);
529 // 291 : 18668322698880447262688739589425844690456357962574138536055595012765940256
530 square!(var1, 5);
531 // 296 : 18668322698880447262688739589425844690456357962574138536055595012765940271
532 var1.mul_assign(&var10);
533 // 297 : 74673290795521789050754958357703378761825431850296554144222380051063761084
534 square!(var1, 2);
535 // 299 : 74673290795521789050754958357703378761825431850296554144222380051063761085
536 var1.mul_assign(var0);
537 // 300 : 19116362443653577996993269339572064963027310553675917860920929293072322837760
538 square!(var1, 8);
539 // 308 : 19116362443653577996993269339572064963027310553675917860920929293072322837765
540 var1.mul_assign(&var15);
541 // 309 : 2446894392787657983615138475465224315267495750870517486197878949513257323233920
542 square!(var1, 7);
543 // 316 : 2446894392787657983615138475465224315267495750870517486197878949513257323233925
544 var1.mul_assign(&var15);
545 // 317 : 39150310284602527737842215607443589044279932013928279779166063192212117171742800
546 square!(var1, 4);
547 // 321 : 39150310284602527737842215607443589044279932013928279779166063192212117171742803
548 var1.mul_assign(&var2);
549 // 322 : 5011239716429123550443803597752779397667831297782819811733256088603150997983078784
550 square!(var1, 7);
551 // 329 : 5011239716429123550443803597752779397667831297782819811733256088603150997983078795
552 var1.mul_assign(&var13);
553 // 330 : 320719341851463907228403430256177881450741203058100467950928389670601663870917042880
554 square!(var1, 6);
555 // 336 : 320719341851463907228403430256177881450741203058100467950928389670601663870917042895
556 var1.mul_assign(&var10);
557 // 337 : 5131509469623422515654454884098846103211859248929607487214854234729626621934672686320
558 square!(var1, 4);
559 // 341 : 5131509469623422515654454884098846103211859248929607487214854234729626621934672686333
560 var1.mul_assign(&var5);
561 // 342 : 656833212111798082003770225164652301211117983862989758363501342045392207607638103850624
562 square!(var1, 7);
563 // 349 : 656833212111798082003770225164652301211117983862989758363501342045392207607638103850635
564 var1.mul_assign(&var13);
565 // 350 : 42037325575155077248241294410537747277511550967231344535264085890905101286888838646440640
566 square!(var1, 6);
567 // 356 : 42037325575155077248241294410537747277511550967231344535264085890905101286888838646440667
568 var1.mul_assign(&var12);
569 // 357 : 1345194418404962471943721421137207912880369630951403025128450748508963241180442836686101344
570 square!(var1, 5);
571 // 362 : 1345194418404962471943721421137207912880369630951403025128450748508963241180442836686101367
572 var1.mul_assign(&var7);
573 // 363 : 43046221388958799102199085476390653212171828190444896804110423952286823717774170773955243744
574 square!(var1, 5);
575 // 368 : 43046221388958799102199085476390653212171828190444896804110423952286823717774170773955243749
576 var1.mul_assign(&var15);
577 // 369 : 5509916337786726285081482940978003611157994008376946790926134265892713435875093859066271199872
578 square!(var1, 7);
579 // 376 : 5509916337786726285081482940978003611157994008376946790926134265892713435875093859066271199899
580 var1.mul_assign(&var12);
581 // 377 : 176317322809175241122607454111296115557055808268062297309636296508566829948003003490120678396768
582 square!(var1, 5);
583 // 382 : 176317322809175241122607454111296115557055808268062297309636296508566829948003003490120678396791
584 var1.mul_assign(&var7);
585 // 383 : 5642154329893607715923438531561475697825785864577993513908361488274138558336096111683861708697312
586 square!(var1, 5);
587 // 388 : 5642154329893607715923438531561475697825785864577993513908361488274138558336096111683861708697333
588 var1.mul_assign(&var4);
589 // 389 : 90274469278297723454775016504983611165212573833247896222533783812386216933377537786941787339157328
590 square!(var1, 4);
591 // 393 : 90274469278297723454775016504983611165212573833247896222533783812386216933377537786941787339157331
592 var1.mul_assign(&var2);
593 // 394 : 5777566033811054301105601056318951114573604725327865358242162163992717883736162418364274389706069184
594 square!(var1, 6);
595 // 400 : 5777566033811054301105601056318951114573604725327865358242162163992717883736162418364274389706069189
596 var1.mul_assign(&var15);
597 // 401 : 369764226163907475270758467604412871332710702420983382927498378495533944559114394775313560941188428096
598 square!(var1, 6);
599 // 407 : 369764226163907475270758467604412871332710702420983382927498378495533944559114394775313560941188428105
600 var1.mul_assign(&var14);
601 // 408 : 5916227618622519604332135481670605941323371238735734126839974055928543112945830316405016975059014849680
602 square!(var1, 4);
603 // 412 : 5916227618622519604332135481670605941323371238735734126839974055928543112945830316405016975059014849683
604 var1.mul_assign(&var2);
605 // 413 : 94659641897960313669314167706729695061173939819771746029439584894856689807133285062480271600944237594928
606 square!(var1, 4);
607 // 417 : 94659641897960313669314167706729695061173939819771746029439584894856689807133285062480271600944237594931
608 var1.mul_assign(&var2);
609 // 418 : 24232868325877840299344426932922801935660528593861566983536533733083312590626120975994949529841724824302336
610 square!(var1, 8);
611 // 426 : 24232868325877840299344426932922801935660528593861566983536533733083312590626120975994949529841724824302345
612 var1.mul_assign(&var14);
613 // 427 : 775451786428090889579021661853529661941136915003570143473169079458666002900035871231838384954935194377675040
614 square!(var1, 5);
615 // 432 : 775451786428090889579021661853529661941136915003570143473169079458666002900035871231838384954935194377675055
616 var1.mul_assign(&var10);
617 // 433 : 49628914331397816933057386358625898364232762560228489182282821085354624185602295758837656637115852440171203520
618 square!(var1, 6);
619 // 439 : 49628914331397816933057386358625898364232762560228489182282821085354624185602295758837656637115852440171203527
620 var1.mul_assign(&var3);
621 // 440 : 1588125258604730141857836363476028747655448401927311653833050274731347973939273464282805012387707278085478512864
622 square!(var1, 5);
623 // 445 : 1588125258604730141857836363476028747655448401927311653833050274731347973939273464282805012387707278085478512879
624 var1.mul_assign(&var10);
625 // 446 : 6504961059244974661049697744797813750396716654294268534100173925299601301255264109702369330740049011038119988752384
626 square!(var1, 12);
627 // 458 : 6504961059244974661049697744797813750396716654294268534100173925299601301255264109702369330740049011038119988752401
628 var1.mul_assign(&var9);
629 // 459 : 104079376947919594576795163916765020006347466468708296545602782804793620820084225755237909291840784176609919820038416
630 square!(var1, 4);
631 // 463 : 104079376947919594576795163916765020006347466468708296545602782804793620820084225755237909291840784176609919820038429
632 var1.mul_assign(&var5);
633 // 464 : 3330540062333427026457445245336480640203118926998665489459289049753395866242695224167613097338905093651517434241229728
634 square!(var1, 5);
635 // 469 : 3330540062333427026457445245336480640203118926998665489459289049753395866242695224167613097338905093651517434241229741
636 var1.mul_assign(&var5);
637 // 470 : 213154563989339329693276495701534760972999611327914591325394499184217335439532494346727238229689925993697115791438703424
638 square!(var1, 6);
639 // 476 : 213154563989339329693276495701534760972999611327914591325394499184217335439532494346727238229689925993697115791438703427
640 var1.mul_assign(&var2);
641 // 477 : 109135136762541736802957565799185797618175800999892270758601983582319275745040637105524345973601242108772923285216616154624
642 square!(var1, 9);
643 // 486 : 109135136762541736802957565799185797618175800999892270758601983582319275745040637105524345973601242108772923285216616154649
644 var1.mul_assign(&var6);
645 // 487 : 3492324376401335577694642105573945523781625631996552664275263474634216823841300387376779071155239747480733545126931716948768
646 square!(var1, 5);
647 // 492 : 3492324376401335577694642105573945523781625631996552664275263474634216823841300387376779071155239747480733545126931716948793
648 var1.mul_assign(&var6);
649 // 493 : 223508760089685476972457094756732513522024040447779370513616862376589876725843224792113860553935343838766946888123629884722752
650 square!(var1, 6);
651 // 499 : 223508760089685476972457094756732513522024040447779370513616862376589876725843224792113860553935343838766946888123629884722755
652 var1.mul_assign(&var2);
653 // 500 : 14304560645739870526237254064430880865409538588657879712871479192101752110453966386695287075451862005681084600839912312622256320
654 square!(var1, 6);
655 // 506 : 14304560645739870526237254064430880865409538588657879712871479192101752110453966386695287075451862005681084600839912312622256323
656 var1.mul_assign(&var2);
657 // 507 : 7323935050618813709433474080988611003089683757392834412990197346356097080552430789987986982631353346908715315630035104062595237376
658 square!(var1, 9);
659 // 516 : 7323935050618813709433474080988611003089683757392834412990197346356097080552430789987986982631353346908715315630035104062595237399
660 var1.mul_assign(&var7);
661 // 517 : 937463686479208154807484682366542208395479520946282804862745260333580426310711141118462333776813228404315560400644493320012190387072
662 square!(var1, 7);
663 // 524 : 937463686479208154807484682366542208395479520946282804862745260333580426310711141118462333776813228404315560400644493320012190387087
664 var1.mul_assign(&var10);
665 // 525 : 59997675934669321907679019671458701337310689340562099511215696661349147283885513031581589361716046617876195865641247572480780184773568
666 square!(var1, 6);
667 // 531 : 59997675934669321907679019671458701337310689340562099511215696661349147283885513031581589361716046617876195865641247572480780184773593
668 var1.mul_assign(&var6);
669 // 532 : 1919925629909418301045728629486678442793942058897987184358902293163172713084336417010610859574913491772038267700519922319384965912754976
670 square!(var1, 5);
671 // 537 : 1919925629909418301045728629486678442793942058897987184358902293163172713084336417010610859574913491772038267700519922319384965912754985
672 var1.mul_assign(&var14);
673 // 538 : 245750480628405542533853264574294840677624583538942359597939493524886107274795061377358190025588926946820898265666550056881275636832638080
674 square!(var1, 7);
675 // 545 : 245750480628405542533853264574294840677624583538942359597939493524886107274795061377358190025588926946820898265666550056881275636832638103
676 var1.mul_assign(&var7);
677 // 546 : 983001922513622170135413058297179362710498334155769438391757974099544429099180245509432760102355707787283593062666200227525102547330552412
678 square!(var1, 2);
679 // 548 : 983001922513622170135413058297179362710498334155769438391757974099544429099180245509432760102355707787283593062666200227525102547330552413
680 var1.mul_assign(var0);
681 // 549 : 251648492163487275554665742924077916853887573543876976228290041369483373849390142850414786586203061193544599824042547258246426252116621417728
682 square!(var1, 8);
683 // 557 : 251648492163487275554665742924077916853887573543876976228290041369483373849390142850414786586203061193544599824042547258246426252116621417739
684 var1.mul_assign(&var13);
685 // 558 : 4026375874615796408874651886785246669662201176702031619652640661911733981590242285606636585379248979096713597184680756131942820033865942683824
686 square!(var1, 4);
687 // 562 : 4026375874615796408874651886785246669662201176702031619652640661911733981590242285606636585379248979096713597184680756131942820033865942683829
688 var1.mul_assign(&var15);
689 // 563 : 515376111950821940335955441508511573716761750617860047315538004724701949643551012557649482928543869324379340439639136784888680964334840663530112
690 square!(var1, 7);
691 // 570 : 515376111950821940335955441508511573716761750617860047315538004724701949643551012557649482928543869324379340439639136784888680964334840663530119
692 var1.mul_assign(&var3);
693 // 571 : 131936284659410416726004593026178962871491008158172172112777729209523699108749059214758267629707230547041111152547619016931502326869719209863710464
694 square!(var1, 8);
695 // 579 : 131936284659410416726004593026178962871491008158172172112777729209523699108749059214758267629707230547041111152547619016931502326869719209863710473
696 var1.mul_assign(&var14);
697 // 580 : 16887844436404533340928587907350907247550849044246038030435549338819033485919879579489058256602525510021262227526095234167232297839324058862554940544
698 square!(var1, 7);
699 // 587 : 16887844436404533340928587907350907247550849044246038030435549338819033485919879579489058256602525510021262227526095234167232297839324058862554940557
700 var1.mul_assign(&var5);
701 // 588 : 17293152702878242141110874017127329021492069421307942943166002522950690289581956689396795654760986122261772520986721519787245872987467836275256259130368
702 square!(var1, 10);
703 // 598 : 17293152702878242141110874017127329021492069421307942943166002522950690289581956689396795654760986122261772520986721519787245872987467836275256259130377
704 var1.mul_assign(&var14);
705 // 599 : 1106761772984207497031095937096149057375492442963708348362624161468844178533245228121394921904703111824753441343150177266383735871197941521616400584344128
706 square!(var1, 6);
707 // 605 : 1106761772984207497031095937096149057375492442963708348362624161468844178533245228121394921904703111824753441343150177266383735871197941521616400584344139
708 var1.mul_assign(&var13);
709 // 606 : 70832753470989279809990139974153539672031516349677334295207946334006027426127694599769275001900999156784220245961611345048559095756668257383449637398024896
710 square!(var1, 6);
711 // 612 : 70832753470989279809990139974153539672031516349677334295207946334006027426127694599769275001900999156784220245961611345048559095756668257383449637398024909
712 var1.mul_assign(&var5);
713 // 613 : 4533296222143313907839368958345826539010017046379349394893308565376385755272172454385233600121663946034190095741543126083107782128426768472540776793473594176
714 square!(var1, 6);
715 // 619 : 4533296222143313907839368958345826539010017046379349394893308565376385755272172454385233600121663946034190095741543126083107782128426768472540776793473594207
716 var1.mul_assign(&var11);
717 // 620 : 145065479108586045050859806667066449248320545484139180636585874092044344168709518540327475203893246273094083063729380034659449028109656591121304857391155014624
718 square!(var1, 5);
719 // 625 : 145065479108586045050859806667066449248320545484139180636585874092044344168709518540327475203893246273094083063729380034659449028109656591121304857391155014649
720 var1.mul_assign(&var6);
721 // 626 : 18568381325899013766510055253384505503785029821969815121482991883781676053594818373161916826098335522956042632157360644436409475598036043663527021746067841875072
722 square!(var1, 7);
723 // 633 : 18568381325899013766510055253384505503785029821969815121482991883781676053594818373161916826098335522956042632157360644436409475598036043663527021746067841875087
724 var1.mul_assign(&var10);
725 // 634 : 594188202428768440528321768108304176121120954303034083887455740281013633715034187941181338435146736734593364229035540621965103219137153397232864695874170940002784
726 square!(var1, 5);
727 // 639 : 594188202428768440528321768108304176121120954303034083887455740281013633715034187941181338435146736734593364229035540621965103219137153397232864695874170940002797
728 var1.mul_assign(&var5);
729 // 640 : 76056089910882360387625186317862934543503482150788362737594334755969745115524376056471211319698782302027950621316549199611533212049555634845806681071893880320358016
730 square!(var1, 7);
731 // 647 : 76056089910882360387625186317862934543503482150788362737594334755969745115524376056471211319698782302027950621316549199611533212049555634845806681071893880320358047
732 var1.mul_assign(&var11);
733 // 648 : 2433794877148235532404005962171613905392111428825227607603018712191031843696780033807078762230361033664894419882129574387569062785585780315065813794300604170251457504
734 square!(var1, 5);
735 // 653 : 2433794877148235532404005962171613905392111428825227607603018712191031843696780033807078762230361033664894419882129574387569062785585780315065813794300604170251457511
736 var1.mul_assign(&var3);
737 // 654 : 623051488549948296295425526315933159780380525779258267546372790320904151986375688654612163130972424618212971489825171043217680073109959760656848331340954667584373122816
738 square!(var1, 8);
739 // 662 : 623051488549948296295425526315933159780380525779258267546372790320904151986375688654612163130972424618212971489825171043217680073109959760656848331340954667584373122843
740 var1.mul_assign(&var12);
741 // 663 : 39875295267196690962907233684219722225944353649872529122967858580537865727128044073895178440382235175565630175348810946765931524679037424682038293205821098725399879861952
742 square!(var1, 6);
743 // 669 : 39875295267196690962907233684219722225944353649872529122967858580537865727128044073895178440382235175565630175348810946765931524679037424682038293205821098725399879861981
744 var1.mul_assign(&var8);
745 // 670 : 2552018897100588221626062955790062222460438633591841863869942949154423406536194820729291420184463051236200331222323900593019617579458395179650450765172550318425592311166784
746 square!(var1, 6);
747 // 676 : 2552018897100588221626062955790062222460438633591841863869942949154423406536194820729291420184463051236200331222323900593019617579458395179650450765172550318425592311166787
748 var1.mul_assign(&var2);
749 // 677 : 326658418828875292368136058341127964474936145099755758575352697491766196036632937053349301783611270558233642396457459275906511050170674582995257697942086440758475815829348736
750 square!(var1, 7);
751 // 684 : 326658418828875292368136058341127964474936145099755758575352697491766196036632937053349301783611270558233642396457459275906511050170674582995257697942086440758475815829348747
752 var1.mul_assign(&var13);
753 // 685 : 41812277610096037423121415467664379452791826572768737097645145278946073092689015942828710628302242631453906226746554787316033414421846346623392985336587064417084904426156639616
754 square!(var1, 7);
755 // 692 : 41812277610096037423121415467664379452791826572768737097645145278946073092689015942828710628302242631453906226746554787316033414421846346623392985336587064417084904426156639627
756 var1.mul_assign(&var13);
757 // 693 : 2675985767046146395079770589930520284978676900657199174249289297852548677932097020341037480211343528413049998511779506388226138522998166183897151061541572122693433883274024936128
758 square!(var1, 6);
759 // 699 : 2675985767046146395079770589930520284978676900657199174249289297852548677932097020341037480211343528413049998511779506388226138522998166183897151061541572122693433883274024936131
760 var1.mul_assign(&var2);
761 // 700 : 85631544545476684642552658877776649119317660821030373575977257531281557693827104650913199366762992909217599952376944204423236432735941317884708833969330307926189884264768797956192
762 square!(var1, 5);
763 // 705 : 85631544545476684642552658877776649119317660821030373575977257531281557693827104650913199366762992909217599952376944204423236432735941317884708833969330307926189884264768797956199
764 var1.mul_assign(&var3);
765 // 706 : 87686701614568125073973922690843288698181284680735102541800711712032315078478955162535116151565304739038822351233990865329394107121603909513941845984594235316418441487123249107147776
766 square!(var1, 10);
767 // 716 : 87686701614568125073973922690843288698181284680735102541800711712032315078478955162535116151565304739038822351233990865329394107121603909513941845984594235316418441487123249107147803
768 var1.mul_assign(&var12);
769 // 717 : 1402987225833090001183582763053492619170900554891761640668811387392517041255663282600561858425044875824621157619743853845270305713945662552223069535753507765062695063793971985714364848
770 square!(var1, 4);
771 // 721 : 1402987225833090001183582763053492619170900554891761640668811387392517041255663282600561858425044875824621157619743853845270305713945662552223069535753507765062695063793971985714364849
772 var1.mul_assign(var0);
773 // 722 : 718329459626542080605994374683388221015501084104581960022431430344968725122899600691487671513622976422206032701308853168778396525540179226738211602305795975712099872662513656685754802688
774 square!(var1, 9);
775 // 731 : 718329459626542080605994374683388221015501084104581960022431430344968725122899600691487671513622976422206032701308853168778396525540179226738211602305795975712099872662513656685754802705
776 var1.mul_assign(&var9);
777 // 732 : 45973085416098693158783639979736846144992069382693245441435611542077998407865574444255210976871870491021186092883766602801817377634571470511245542547570942445574391850400874027888307373120
778 square!(var1, 6);
779 // 738 : 45973085416098693158783639979736846144992069382693245441435611542077998407865574444255210976871870491021186092883766602801817377634571470511245542547570942445574391850400874027888307373135
780 var1.mul_assign(&var10);
781 // 739 : 5884554933260632724324305917406316306558984880984735416503758277385983796206793528864667005039599422850711819889122125158632624337225148225439429446089080633033522156851311875569703343761280
782 square!(var1, 7);
783 // 746 : 5884554933260632724324305917406316306558984880984735416503758277385983796206793528864667005039599422850711819889122125158632624337225148225439429446089080633033522156851311875569703343761311
784 var1.mul_assign(&var11);
785 // 747 : 188305757864340247178377789357002121809887516191511533328120264876351481478617392923669344161267181531222778236451908005076243978791204743214061742274850580257072709019241980018230507000361952
786 square!(var1, 5);
787 // 752 : 188305757864340247178377789357002121809887516191511533328120264876351481478617392923669344161267181531222778236451908005076243978791204743214061742274850580257072709019241980018230507000361973
788 var1.mul_assign(&var4);
789 // 753 : 3012892125829443954854044629712033948958200259064184533249924238021623703657878286778709506580274904499564451783230528081219903660659275891424987876397609284113163344307871680291688112005791568
790 square!(var1, 4);
791 // 757 : 3012892125829443954854044629712033948958200259064184533249924238021623703657878286778709506580274904499564451783230528081219903660659275891424987876397609284113163344307871680291688112005791583
792 var1.mul_assign(&var10);
793 // 758 : 385650192106168826221317712603140345466649633160215620255990302466767834068208420707674816842275187775944249828253507594396147668564387314102398448178893988366484908071407575077336078336741322624
794 square!(var1, 7);
795 // 765 : 385650192106168826221317712603140345466649633160215620255990302466767834068208420707674816842275187775944249828253507594396147668564387314102398448178893988366484908071407575077336078336741322653
796 var1.mul_assign(&var8);
797 // 766 : 12340806147397402439082166803300491054932788261126899848191689678936570690182669462645594138952806008830215994504112243020676725394060394051276750341724607627727517058285042402474754506775722324896
798 square!(var1, 5);
799 // 771 : 12340806147397402439082166803300491054932788261126899848191689678936570690182669462645594138952806008830215994504112243020676725394060394051276750341724607627727517058285042402474754506775722324917
800 var1.mul_assign(&var4);
801 // 772 : 394905796716716878050629337705615713757849224356060795142134069725970262085845422804659012446489792282566911824131591776661655212609932609640856010935187444087280545865121356879192144216823114397344
802 square!(var1, 5);
803 // 777 : 394905796716716878050629337705615713757849224356060795142134069725970262085845422804659012446489792282566911824131591776661655212609932609640856010935187444087280545865121356879192144216823114397365
804 var1.mul_assign(&var4);
805 // 778 : 12636985494934940097620138806579702840251175179393945444548290231231048386747053529749088398287673353042141178372210936853172966803517843508507392349925998210792977467683883420134148614938339660715680
806 square!(var1, 5);
807 // 783 : 12636985494934940097620138806579702840251175179393945444548290231231048386747053529749088398287673353042141178372210936853172966803517843508507392349925998210792977467683883420134148614938339660715697
808 var1.mul_assign(&var9);
809 // 784 : 202191767918959041561922220905275245444018802870303127112772643699696774187952856475985414372602773648674258853955374989650767468856285496136118277598815971372687639482942134722146377839013434571451152
810 square!(var1, 4);
811 // 788 : 202191767918959041561922220905275245444018802870303127112772643699696774187952856475985414372602773648674258853955374989650767468856285496136118277598815971372687639482942134722146377839013434571451165
812 var1.mul_assign(&var5);
813 // 789 : 12940273146813378659963022137937615708417203383699400135217449196780593548028982814463066519846577513515152566653143999337649118006802271752711569766324222167852008926908296622217368181696859812572874560
814 square!(var1, 6);
815 // 795 : 12940273146813378659963022137937615708417203383699400135217449196780593548028982814463066519846577513515152566653143999337649118006802271752711569766324222167852008926908296622217368181696859812572874589
816 var1.mul_assign(&var8);
817 // 796 : 25880546293626757319926044275875231416834406767398800270434898393561187096057965628926133039693155027030305133306287998675298236013604543505423139532648444335704017853816593244434736363393719625145749178
818 var1 = var1.square();
819 // 797 : 25880546293626757319926044275875231416834406767398800270434898393561187096057965628926133039693155027030305133306287998675298236013604543505423139532648444335704017853816593244434736363393719625145749179
820 var1.mul_assign(var0);
821 // 798 : 1656354962792112468475266833656014810677402033113523217307833497187915974147709800251272514540361921729939528531602431915219087104870690784347080930089500437485057142644261967643823127257198056009327947456
822 square!(var1, 6);
823 // 804 : 1656354962792112468475266833656014810677402033113523217307833497187915974147709800251272514540361921729939528531602431915219087104870690784347080930089500437485057142644261967643823127257198056009327947463
824 var1.mul_assign(&var3);
825 // 805 : 1696107481899123167718673237663759166133659681908247774523221501120425957527254835457303054889330607851458077216360890281184345195387587363171410872411648447984698514067724254867274882311370809353551818202112
826 square!(var1, 10);
827 // 815 : 1696107481899123167718673237663759166133659681908247774523221501120425957527254835457303054889330607851458077216360890281184345195387587363171410872411648447984698514067724254867274882311370809353551818202135
828 var1.mul_assign(&var7);
829 // 816 : 108550878841543882733995087210480586632554219642127857569486176071707261281744309469267395512917158902493316941847096977995798092504805591242970295834345500671020704900334352311505592467927731798627316364936640
830 square!(var1, 6);
831 // 822 : 108550878841543882733995087210480586632554219642127857569486176071707261281744309469267395512917158902493316941847096977995798092504805591242970295834345500671020704900334352311505592467927731798627316364936661
832 var1.mul_assign(&var4);
833 // 823 : 6947256245858808494975685581470757544483470057096182884447115268589264722031635806033113312826698169759572284278214206591731077920307557839550098933398112042945325113621398547936357917947374835112148247355946304
834 square!(var1, 6);
835 // 829 : 6947256245858808494975685581470757544483470057096182884447115268589264722031635806033113312826698169759572284278214206591731077920307557839550098933398112042945325113621398547936357917947374835112148247355946329
836 var1.mul_assign(&var6);
837 // 830 : 444624399734963743678443877214128482846942083654155704604615377189712942210024691586119252020908682864612626193805709221870788986899683701731206331737479170748500807271769507067926906748631989447177487830780565056
838 square!(var1, 6);
839 // 836 : 444624399734963743678443877214128482846942083654155704604615377189712942210024691586119252020908682864612626193805709221870788986899683701731206331737479170748500807271769507067926906748631989447177487830780565069
840 var1.mul_assign(&var5);
841 // 837 : 28455961583037679595420408141704222902204293353865965094695384140141628301441580261511632129338155703335208076403565390199730495161579756910797205231198666927904051665393248452347322031912447324619359221169956164416
842 square!(var1, 6);
843 // 843 : 28455961583037679595420408141704222902204293353865965094695384140141628301441580261511632129338155703335208076403565390199730495161579756910797205231198666927904051665393248452347322031912447324619359221169956164437
844 var1.mul_assign(&var4);
845 // 844 : 238705906983162543355580399100765177871214152862586865721082456961065184302499251714358569373223087638243353151383559860752580829556389241459968722180074986980751351032731127113348364375477010926880553717580063640645533696
846 square!(var1, 23);
847 // 867 : 238705906983162543355580399100765177871214152862586865721082456961065184302499251714358569373223087638243353151383559860752580829556389241459968722180074986980751351032731127113348364375477010926880553717580063640645533703
848 var1.mul_assign(&var3);
849 // 868 : 15277178046922402774757145542448971383757705783205559406149277245508171795359952109718948439886277608847574601688547831088165173091608911453437998219524799166768086466094792135254295320030528699320355437925124073001314156992
850 square!(var1, 6);
851 // 874 : 15277178046922402774757145542448971383757705783205559406149277245508171795359952109718948439886277608847574601688547831088165173091608911453437998219524799166768086466094792135254295320030528699320355437925124073001314156999
852 var1.mul_assign(&var3);
853 // 875 : 488869697501516888792228657358367084280246585062577900996776871856261497451518467511006350076360883483122387254033530594821285538931485166510015943024793573336578766915033348328137450240976918378251374013603970336042053023968
854 square!(var1, 5);
855 // 880 : 488869697501516888792228657358367084280246585062577900996776871856261497451518467511006350076360883483122387254033530594821285538931485166510015943024793573336578766915033348328137450240976918378251374013603970336042053023971
856 var1.mul_assign(&var2);
857 // 881 : 31287660640097080882702634070935493393935781444004985663793719798800735836897181920704406404887096542919832784258145958068562274491615050656641020353586788693541041082562134293000796815422522776208087936870654101506691393534144
858 square!(var1, 6);
859 // 887 : 31287660640097080882702634070935493393935781444004985663793719798800735836897181920704406404887096542919832784258145958068562274491615050656641020353586788693541041082562134293000796815422522776208087936870654101506691393534151
860 var1.mul_assign(&var3);
861 // 888 : 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092832
862 square!(var1, 5);
863 // 893 : 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835
864 var1 * var2
865}
866
867/// Tests for addition chains
868#[cfg(test)]
869mod tests {
870 use super::*;
871 use rand_core::SeedableRng;
872
873 const SEED: [u8; 16] = [
874 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
875 0xe5,
876 ];
877
878 #[test]
879 fn test_fp_chain() {
880 let mut rng = rand_xorshift::XorShiftRng::from_seed(SEED);
881 let p_m3_over4 = [
882 0xee7f_bfff_ffff_eaaa,
883 0x07aa_ffff_ac54_ffff,
884 0xd9cc_34a8_3dac_3d89,
885 0xd91d_d2e1_3ce1_44af,
886 0x92c6_e9ed_90d2_eb35,
887 0x0680_447a_8e5f_f9a6,
888 ];
889
890 for _ in 0..32 {
891 let input = Fp::random(&mut rng);
892 assert_eq!(chain_pm3div4(&input), input.pow_vartime(&p_m3_over4));
893 }
894 }
895
896 #[test]
897 fn test_fp2_chain() {
898 let mut rng = rand_xorshift::XorShiftRng::from_seed(SEED);
899 let p_sq_m9_over16 = [
900 0xb26a_a000_01c7_18e3,
901 0xd7ce_d6b1_d763_82ea,
902 0x3162_c338_3621_13cf,
903 0x966b_f91e_d3e7_1b74,
904 0xb292_e85a_8709_1a04,
905 0x11d6_8619_c861_85c7,
906 0xef53_1493_3097_8ef0,
907 0x050a_62cf_d16d_dca6,
908 0x466e_59e4_9349_e8bd,
909 0x9e2d_c90e_50e7_046b,
910 0x74bd_278e_aa22_f25e,
911 0x002a_437a_4b8c_35fc,
912 ];
913
914 for _ in 0..32 {
915 let input = Fp2::random(&mut rng);
916 assert_eq!(
917 chain_p2m9div16(&input),
918 input.pow_vartime_extended(&p_sq_m9_over16[..]),
919 );
920 }
921 }
922}