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}