halo2curves_axiom/bls12_381/hash_to_curve/
chain.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
//! Addition chains for computing square roots.
//! chain_pm3div4: input x, output x^((p-3)//4).
//! chain_p2m9div16: input x, output x^((p**2 - 9) // 16).
//!
//! Source: <https://github.com/privacy-scaling-explorations/bls12_381>

use core::ops::MulAssign;

use crate::bls12_381::{fp::Fp, fp2::Fp2};

macro_rules! square {
    ($var:expr, $n:expr) => {
        for _ in 0..$n {
            $var = $var.square();
        }
    };
}

#[allow(clippy::cognitive_complexity)]
/// addchain for 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946
/// Bos-Coster (win=4) : 458 links, 16 variables */
/// Addition chain implementing exponentiation by (p - 3) // 4.
pub fn chain_pm3div4(var0: &Fp) -> Fp {
    let mut var1 = var0.square();
    //Self::sqr(var1, var0);                              /*    0 : 2 */
    let var9 = var1 * var0;
    //Self::mul(&mut var9, var1, var0);                /*    1 : 3 */
    let var5 = var1.square();
    //Self::sqr(&mut var5, var1);                         /*    2 : 4 */
    let var2 = var9 * var1;
    //Self::mul(&mut var2, &var9, var1);               /*    3 : 5 */
    let var7 = var5 * var9;
    //Self::mul(&mut var7, &var5, &var9);              /*    4 : 7 */
    let var10 = var2 * var5;
    //Self::mul(&mut var10, &var2, &var5);             /*    5 : 9 */
    let var13 = var7 * var5;
    //Self::mul(&mut var13, &var7, &var5);             /*    6 : 11 */
    let var4 = var10 * var5;
    //Self::mul(&mut var4, &var10, &var5);             /*    7 : 13 */
    let var8 = var13 * var5;
    //Self::mul(&mut var8, &var13, &var5);             /*    8 : 15 */
    let var15 = var4 * var5;
    //Self::mul(&mut var15, &var4, &var5);             /*    9 : 17 */
    let var11 = var8 * var5;
    //Self::mul(&mut var11, &var8, &var5);             /*   10 : 19 */
    let var3 = var15 * var5;
    //Self::mul(&mut var3, &var15, &var5);             /*   11 : 21 */
    let var12 = var11 * var5;
    //Self::mul(&mut var12, &var11, &var5);            /*   12 : 23 */
    var1 = var4.square();
    //Self::sqr(var1, &var4);                             /*   13 : 26 */
    let var14 = var12 * var5;
    //Self::mul(&mut var14, &var12, &var5);            /*   14 : 27 */
    let var6 = var1 * var9;
    //Self::mul(&mut var6, var1, &var9);               /*   15 : 29 */
    let var5 = var1 * var2;
    //Self::mul(&mut var5, var1, &var2);               /*   16 : 31 */
    //   17 : 106496
    square!(var1, 12);
    //   29 : 106513
    var1.mul_assign(&var15);
    //   30 : 13633664
    square!(var1, 7);
    //   37 : 13633679
    var1.mul_assign(&var8);
    //   38 : 218138864
    square!(var1, 4);
    //   42 : 218138869
    var1.mul_assign(&var2);
    //   43 : 13960887616
    square!(var1, 6);
    //   49 : 13960887623
    var1.mul_assign(&var7);
    //   50 : 1786993615744
    square!(var1, 7);
    //   57 : 1786993615767
    var1.mul_assign(&var12);
    //   58 : 57183795704544
    square!(var1, 5);
    //   63 : 57183795704575
    var1.mul_assign(&var5);
    //   64 : 228735182818300
    square!(var1, 2);
    //   66 : 228735182818303
    var1.mul_assign(&var9);
    //   67 : 14639051700371392
    square!(var1, 6);
    //   73 : 14639051700371405
    var1.mul_assign(&var4);
    //   74 : 936899308823769920
    square!(var1, 6);
    //   80 : 936899308823769933
    var1.mul_assign(&var4);
    //   81 : 59961555764721275712
    square!(var1, 6);
    //   87 : 59961555764721275721
    var1.mul_assign(&var10);
    //   88 : 479692446117770205768
    square!(var1, 3);
    //   91 : 479692446117770205771
    var1.mul_assign(&var9);
    //   92 : 61400633103074586338688
    square!(var1, 7);
    //   99 : 61400633103074586338701
    var1.mul_assign(&var4);
    //  100 : 982410129649193381419216
    square!(var1, 4);
    //  104 : 982410129649193381419229
    var1.mul_assign(&var4);
    //  105 : 62874248297548376410830656
    square!(var1, 6);
    //  111 : 62874248297548376410830671
    var1.mul_assign(&var8);
    //  112 : 4023951891043096090293162944
    square!(var1, 6);
    //  118 : 4023951891043096090293162971
    var1.mul_assign(&var14);
    //  119 : 32191615128344768722345303768
    square!(var1, 3);
    //  122 : 32191615128344768722345303769
    var1.mul_assign(var0);
    //  123 : 8241053472856260792920397764864
    square!(var1, 8);
    //  131 : 8241053472856260792920397764877
    var1.mul_assign(&var4);
    //  132 : 1054854844525601381493810913904256
    square!(var1, 7);
    //  139 : 1054854844525601381493810913904279
    var1.mul_assign(&var12);
    //  140 : 33755355024819244207801949244936928
    square!(var1, 5);
    //  145 : 33755355024819244207801949244936939
    var1.mul_assign(&var13);
    //  146 : 2160342721588431629299324751675964096
    square!(var1, 6);
    //  152 : 2160342721588431629299324751675964109
    var1.mul_assign(&var4);
    //  153 : 138261934181659624275156784107261702976
    square!(var1, 6);
    //  159 : 138261934181659624275156784107261703005
    var1.mul_assign(&var6);
    //  160 : 2212190946906553988402508545716187248080
    square!(var1, 4);
    //  164 : 2212190946906553988402508545716187248089
    var1.mul_assign(&var10);
    //  165 : 566320882408077821031042187703343935510784
    square!(var1, 8);
    //  173 : 566320882408077821031042187703343935510813
    var1.mul_assign(&var6);
    //  174 : 9061134118529245136496675003253502968173008
    square!(var1, 4);
    //  178 : 9061134118529245136496675003253502968173021
    var1.mul_assign(&var4);
    //  179 : 1159825167171743377471574400416448379926146688
    square!(var1, 7);
    //  186 : 1159825167171743377471574400416448379926146711
    var1.mul_assign(&var12);
    //  187 : 593830485591932609265446093013221570522187116032
    square!(var1, 9);
    //  196 : 593830485591932609265446093013221570522187116051
    var1.mul_assign(&var11);
    //  197 : 2375321942367730437061784372052886282088748464204
    square!(var1, 2);
    //  199 : 2375321942367730437061784372052886282088748464207
    var1.mul_assign(&var9);
    //  200 : 76010302155767373985977099905692361026839950854624
    square!(var1, 5);
    //  205 : 76010302155767373985977099905692361026839950854631
    var1.mul_assign(&var7);
    //  206 : 9729318675938223870205068787928622211435513709392768
    square!(var1, 7);
    //  213 : 9729318675938223870205068787928622211435513709392773
    var1.mul_assign(&var2);
    //  214 : 1245352790520092655386248804854863643063745754802274944
    square!(var1, 7);
    //  221 : 1245352790520092655386248804854863643063745754802274953
    var1.mul_assign(&var10);
    //  222 : 79702578593285929944719923510711273156079728307345596992
    square!(var1, 6);
    //  228 : 79702578593285929944719923510711273156079728307345597015
    var1.mul_assign(&var12);
    //  229 : 2550482514985149758231037552342760740994551305835059104480
    square!(var1, 5);
    //  234 : 2550482514985149758231037552342760740994551305835059104509
    var1.mul_assign(&var6);
    //  235 : 81615440479524792263393201674968343711825641786721891344288
    square!(var1, 5);
    //  240 : 81615440479524792263393201674968343711825641786721891344307
    var1.mul_assign(&var11);
    //  241 : 2611694095344793352428582453598986998778420537175100523017824
    square!(var1, 5);
    //  246 : 2611694095344793352428582453598986998778420537175100523017843
    var1.mul_assign(&var11);
    //  247 : 668593688408267098221717108121340671687275657516825733892567808
    square!(var1, 8);
    //  255 : 668593688408267098221717108121340671687275657516825733892567821
    var1.mul_assign(&var4);
    //  256 : 85579992116258188572379789839531605975971284162153693938248681088
    square!(var1, 7);
    //  263 : 85579992116258188572379789839531605975971284162153693938248681109
    var1.mul_assign(&var3);
    //  264 : 43816955963524192549058452397840182259697297491022691296383324727808
    square!(var1, 9);
    //  273 : 43816955963524192549058452397840182259697297491022691296383324727823
    var1.mul_assign(&var8);
    //  274 : 1402142590832774161569870476730885832310313519712726121484266391290336
    square!(var1, 5);
    //  279 : 1402142590832774161569870476730885832310313519712726121484266391290349
    var1.mul_assign(&var4);
    //  280 : 11217140726662193292558963813847086658482508157701808971874131130322792
    square!(var1, 3);
    //  283 : 11217140726662193292558963813847086658482508157701808971874131130322795
    var1.mul_assign(&var9);
    //  284 : 2871588026025521482895094736344854184571522088371663096799777569362635520
    square!(var1, 8);
    //  292 : 2871588026025521482895094736344854184571522088371663096799777569362635535
    var1.mul_assign(&var8);
    //  293 : 22972704208204171863160757890758833476572176706973304774398220554901084280
    square!(var1, 3);
    //  296 : 22972704208204171863160757890758833476572176706973304774398220554901084283
    var1.mul_assign(&var9);
    //  297 : 2940506138650133998484577010017130685001238618492583011122972231027338788224
    square!(var1, 7);
    //  304 : 2940506138650133998484577010017130685001238618492583011122972231027338788233
    var1.mul_assign(&var10);
    //  305 : 1505539142988868607224103429128770910720634172668202501694961782285997459575296
    square!(var1, 9);
    //  314 : 1505539142988868607224103429128770910720634172668202501694961782285997459575311
    var1.mul_assign(&var8);
    //  315 : 96354505151287590862342619464241338286120587050764960108477554066303837412819904
    square!(var1, 6);
    //  321 : 96354505151287590862342619464241338286120587050764960108477554066303837412819925
    var1.mul_assign(&var3);
    //  322 : 6166688329682405815189927645711445650311717571248957446942563460243445594420475200
    square!(var1, 6);
    //  328 : 6166688329682405815189927645711445650311717571248957446942563460243445594420475231
    var1.mul_assign(&var5);
    //  329 : 197334026549836986086077684662766260809974962279966638302162030727790259021455207392
    square!(var1, 5);
    //  334 : 197334026549836986086077684662766260809974962279966638302162030727790259021455207423
    var1.mul_assign(&var5);
    //  335 : 6314688849594783554754485909208520345919198792958932425669184983289288288686566637536
    square!(var1, 5);
    //  340 : 6314688849594783554754485909208520345919198792958932425669184983289288288686566637567
    var1.mul_assign(&var5);
    //  341 : 101035021593516536876071774547336325534707180687342918810706959732628612618985066201072
    square!(var1, 4);
    //  345 : 101035021593516536876071774547336325534707180687342918810706959732628612618985066201085
    var1.mul_assign(&var4);
    //  346 : 808280172748132295008574196378690604277657445498743350485655677861028900951880529608680
    square!(var1, 3);
    //  349 : 808280172748132295008574196378690604277657445498743350485655677861028900951880529608683
    var1.mul_assign(&var9);
    //  350 : 206919724223521867522194994272944794695080306047678297724327853532423398643681415579822848
    square!(var1, 8);
    //  358 : 206919724223521867522194994272944794695080306047678297724327853532423398643681415579822869
    var1.mul_assign(&var3);
    //  359 : 26485724700610799042840959266936933720970279174102822108713965252150195026391221194217327232
    square!(var1, 7);
    //  366 : 26485724700610799042840959266936933720970279174102822108713965252150195026391221194217327263
    var1.mul_assign(&var5);
    //  367 : 847543190419545569370910696541981879071048933571290307478846888068806240844519078214954472416
    square!(var1, 5);
    //  372 : 847543190419545569370910696541981879071048933571290307478846888068806240844519078214954472447
    var1.mul_assign(&var5);
    //  373 : 27121382093425458219869142289343420130273565874281289839323100418201799707024610502878543118304
    square!(var1, 5);
    //  378 : 27121382093425458219869142289343420130273565874281289839323100418201799707024610502878543118335
    var1.mul_assign(&var5);
    //  379 : 433942113494807331517906276629494722084377053988500637429169606691228795312393768046056689893360
    square!(var1, 4);
    //  383 : 433942113494807331517906276629494722084377053988500637429169606691228795312393768046056689893375
    var1.mul_assign(&var8);
    //  384 : 6943073815916917304286500426071915553350032863816010198866713707059660724998300288736907038294000
    square!(var1, 4);
    //  388 : 6943073815916917304286500426071915553350032863816010198866713707059660724998300288736907038294007
    var1.mul_assign(&var7);
    //  389 : 888713448437365414948672054537205190828804206568449305454939354503636572799782436958324100901632896
    square!(var1, 7);
    //  396 : 888713448437365414948672054537205190828804206568449305454939354503636572799782436958324100901632927
    var1.mul_assign(&var5);
    //  397 : 28438830349995693278357505745190566106521734610190377774558059344116370329593037982666371228852253664
    square!(var1, 5);
    //  402 : 28438830349995693278357505745190566106521734610190377774558059344116370329593037982666371228852253693
    var1.mul_assign(&var6);
    //  403 : 910042571199862184907440183846098115408695507526092088785857899011723850546977215445323879323272118176
    square!(var1, 5);
    //  408 : 910042571199862184907440183846098115408695507526092088785857899011723850546977215445323879323272118207
    var1.mul_assign(&var5);
    //  409 : 29121362278395589917038085883075139693078256240834946841147452768375163217503270894250364138344707782624
    square!(var1, 5);
    //  414 : 29121362278395589917038085883075139693078256240834946841147452768375163217503270894250364138344707782655
    var1.mul_assign(&var5);
    //  415 : 931883592908658877345218748258404470178504199706718298916718488588005222960104668616011652427030649044960
    square!(var1, 5);
    //  420 : 931883592908658877345218748258404470178504199706718298916718488588005222960104668616011652427030649044991
    var1.mul_assign(&var5);
    //  421 : 29820274973077084075046999944268943045712134390614985565334991634816167134723349395712372877664980769439712
    square!(var1, 5);
    //  426 : 29820274973077084075046999944268943045712134390614985565334991634816167134723349395712372877664980769439743
    var1.mul_assign(&var5);
    //  427 : 954248799138466690401503998216606177462788300499679538090719732314117348311147180662795932085279384622071776
    square!(var1, 5);
    //  432 : 954248799138466690401503998216606177462788300499679538090719732314117348311147180662795932085279384622071807
    var1.mul_assign(&var5);
    //  433 : 30535961572430934092848127942931397678809225615989745218903031434051755145956709781209469826728940307906297824
    square!(var1, 5);
    //  438 : 30535961572430934092848127942931397678809225615989745218903031434051755145956709781209469826728940307906297855
    var1.mul_assign(&var5);
    //  439 : 488575385158894945485570047086902362860947609855835923502448502944828082335307356499351517227663044926500765680
    square!(var1, 4);
    //  443 : 488575385158894945485570047086902362860947609855835923502448502944828082335307356499351517227663044926500765693
    var1.mul_assign(&var4);
    //  444 : 31268824650169276511076483013561751223100647030773499104156704188468997269459670815958497102570434875296049004352
    square!(var1, 6);
    //  450 : 31268824650169276511076483013561751223100647030773499104156704188468997269459670815958497102570434875296049004373
    var1.mul_assign(&var3);
    //  451 : 500301194402708424177223728216988019569610352492375985666507267015503956311354733055335953641126958004736784069968
    square!(var1, 4);
    //  455 : 500301194402708424177223728216988019569610352492375985666507267015503956311354733055335953641126958004736784069973
    var1.mul_assign(&var2);
    //  456 : 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946
    var1.square()
}

#[allow(clippy::cognitive_complexity)]
/// addchain for 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835
/// Bos-Coster (win=4) : 895 links, 17 variables
/// Addition chain implementing exponentiation by (p**2 - 9) // 16.
pub fn chain_p2m9div16(var0: &Fp2) -> Fp2 {
    let mut var1 = var0.square();
    //Self::sqr(var1, var0);                              /*    0 : 2 */
    let var2 = var1 * var0;
    //Self::mul(&mut var2, var1, var0);                /*    1 : 3 */
    let var15 = var2 * var1;
    //Self::mul(&mut var15, &var2, var1);              /*    2 : 5 */
    let var3 = var15 * var1;
    //Self::mul(&mut var3, &var15, var1);              /*    3 : 7 */
    let var14 = var3 * var1;
    //Self::mul(&mut var14, &var3, var1);              /*    4 : 9 */
    let var13 = var14 * var1;
    //Self::mul(&mut var13, &var14, var1);             /*    5 : 11 */
    let var5 = var13 * var1;
    //Self::mul(&mut var5, &var13, var1);              /*    6 : 13 */
    let var10 = var5 * var1;
    //Self::mul(&mut var10, &var5, var1);              /*    7 : 15 */
    let var9 = var10 * var1;
    //Self::mul(&mut var9, &var10, var1);              /*    8 : 17 */
    let var16 = var9 * var1;
    //Self::mul(&mut var16, &var9, var1);              /*    9 : 19 */
    let var4 = var16 * var1;
    //Self::mul(&mut var4, &var16, var1);              /*   10 : 21 */
    let var7 = var4 * var1;
    //Self::mul(&mut var7, &var4, var1);               /*   11 : 23 */
    let var6 = var7 * var1;
    //Self::mul(&mut var6, &var7, var1);               /*   12 : 25 */
    let var12 = var6 * var1;
    //Self::mul(&mut var12, &var6, var1);              /*   13 : 27 */
    let var8 = var12 * var1;
    //Self::mul(&mut var8, &var12, var1);              /*   14 : 29 */
    let var11 = var8 * var1;
    //Self::mul(&mut var11, &var8, var1);              /*   15 : 31 */
    var1 = var4.square();
    //Self::sqr(var1, &var4);                             /*   16 : 42 */
    //   17 : 168
    square!(var1, 2);
    //   19 : 169
    var1.mul_assign(var0);
    //   20 : 86528
    square!(var1, 9);
    //   29 : 86555
    var1.mul_assign(&var12);
    //   30 : 1384880
    square!(var1, 4);
    //   34 : 1384893
    var1.mul_assign(&var5);
    //   35 : 88633152
    square!(var1, 6);
    //   41 : 88633161
    var1.mul_assign(&var14);
    //   42 : 1418130576
    square!(var1, 4);
    //   46 : 1418130583
    var1.mul_assign(&var3);
    //   47 : 45380178656
    square!(var1, 5);
    //   52 : 45380178659
    var1.mul_assign(&var2);
    //   53 : 11617325736704
    square!(var1, 8);
    //   61 : 11617325736717
    var1.mul_assign(&var5);
    //   62 : 185877211787472
    square!(var1, 4);
    //   66 : 185877211787479
    var1.mul_assign(&var3);
    //   67 : 2974035388599664
    square!(var1, 4);
    //   71 : 2974035388599679
    var1.mul_assign(&var10);
    //   72 : 761353059481517824
    square!(var1, 8);
    //   80 : 761353059481517853
    var1.mul_assign(&var8);
    //   81 : 48726595806817142592
    square!(var1, 6);
    //   87 : 48726595806817142603
    var1.mul_assign(&var13);
    //   88 : 779625532909074281648
    square!(var1, 4);
    //   92 : 779625532909074281661
    var1.mul_assign(&var5);
    //   93 : 6237004263272594253288
    square!(var1, 3);
    //   96 : 6237004263272594253289
    var1.mul_assign(var0);
    //   97 : 399168272849446032210496
    square!(var1, 6);
    //  103 : 399168272849446032210511
    var1.mul_assign(&var10);
    //  104 : 102187077849458184245890816
    square!(var1, 8);
    //  112 : 102187077849458184245890845
    var1.mul_assign(&var8);
    //  113 : 6539972982365323791737014080
    square!(var1, 6);
    //  119 : 6539972982365323791737014101
    var1.mul_assign(&var4);
    //  120 : 1674233083485522890684675609856
    square!(var1, 8);
    //  128 : 1674233083485522890684675609873
    var1.mul_assign(&var9);
    //  129 : 53575458671536732501909619515936
    square!(var1, 5);
    //  134 : 53575458671536732501909619515951
    var1.mul_assign(&var10);
    //  135 : 3428829354978350880122215649020864
    square!(var1, 6);
    //  141 : 3428829354978350880122215649020873
    var1.mul_assign(&var14);
    //  142 : 109722539359307228163910900768667936
    square!(var1, 5);
    //  147 : 109722539359307228163910900768667951
    var1.mul_assign(&var10);
    //  148 : 438890157437228912655643603074671804
    square!(var1, 2);
    //  150 : 438890157437228912655643603074671805
    var1.mul_assign(var0);
    //  151 : 28088970075982650409961190596778995520
    square!(var1, 6);
    //  157 : 28088970075982650409961190596778995535
    var1.mul_assign(&var10);
    //  158 : 3595388169725779252475032396387711428480
    square!(var1, 7);
    //  165 : 3595388169725779252475032396387711428491
    var1.mul_assign(&var13);
    //  166 : 57526210715612468039600518342203382855856
    square!(var1, 4);
    //  170 : 57526210715612468039600518342203382855863
    var1.mul_assign(&var3);
    //  171 : 3681677485799197954534433173901016502775232
    square!(var1, 6);
    //  177 : 3681677485799197954534433173901016502775241
    var1.mul_assign(&var14);
    //  178 : 471254718182297338180407446259330112355230848
    square!(var1, 7);
    //  185 : 471254718182297338180407446259330112355230855
    var1.mul_assign(&var3);
    //  186 : 15080150981833514821773038280298563595367387360
    square!(var1, 5);
    //  191 : 15080150981833514821773038280298563595367387365
    var1.mul_assign(&var15);
    //  192 : 1930259325674689897186948899878216140207025582720
    square!(var1, 7);
    //  199 : 1930259325674689897186948899878216140207025582727
    var1.mul_assign(&var3);
    //  200 : 61768298421590076709982364796102916486624818647264
    square!(var1, 5);
    //  205 : 61768298421590076709982364796102916486624818647271
    var1.mul_assign(&var3);
    //  206 : 63250737583708238551021941551209386482303814294805504
    square!(var1, 10);
    //  216 : 63250737583708238551021941551209386482303814294805521
    var1.mul_assign(&var9);
    //  217 : 506005900669665908408175532409675091858430514358444168
    square!(var1, 3);
    //  220 : 506005900669665908408175532409675091858430514358444173
    var1.mul_assign(&var15);
    //  221 : 16192188821429309069061617037109602939469776459470213536
    square!(var1, 5);
    //  226 : 16192188821429309069061617037109602939469776459470213549
    var1.mul_assign(&var5);
    //  227 : 4145200338285903121679773961500058352504262773624374668544
    square!(var1, 8);
    //  235 : 4145200338285903121679773961500058352504262773624374668569
    var1.mul_assign(&var6);
    //  236 : 132646410825148899893752766768001867280136408755979989394208
    square!(var1, 5);
    //  241 : 132646410825148899893752766768001867280136408755979989394231
    var1.mul_assign(&var7);
    //  242 : 8489370292809529593200177073152119505928730160382719321230784
    square!(var1, 6);
    //  248 : 8489370292809529593200177073152119505928730160382719321230795
    var1.mul_assign(&var13);
    //  249 : 543319698739809893964811332681735648379438730264494036558770880
    square!(var1, 6);
    //  255 : 543319698739809893964811332681735648379438730264494036558770895
    var1.mul_assign(&var10);
    //  256 : 34772460719347833213747925291631081496284078736927618339761337280
    square!(var1, 6);
    //  262 : 34772460719347833213747925291631081496284078736927618339761337289
    var1.mul_assign(&var14);
    //  263 : 4450874972076522651359734437328778431524362078326735147489451172992
    square!(var1, 7);
    //  270 : 4450874972076522651359734437328778431524362078326735147489451173011
    var1.mul_assign(&var16);
    //  271 : 142427999106448724843511501994520909808779586506455524719662437536352
    square!(var1, 5);
    //  276 : 142427999106448724843511501994520909808779586506455524719662437536361
    var1.mul_assign(&var14);
    //  277 : 9115391942812718389984736127649338227761893536413153582058396002327104
    square!(var1, 6);
    //  283 : 9115391942812718389984736127649338227761893536413153582058396002327119
    var1.mul_assign(&var10);
    //  284 : 583385084340013976959023112169557646576761186330441829251737344148935616
    square!(var1, 6);
    //  290 : 583385084340013976959023112169557646576761186330441829251737344148935633
    var1.mul_assign(&var9);
    //  291 : 18668322698880447262688739589425844690456357962574138536055595012765940256
    square!(var1, 5);
    //  296 : 18668322698880447262688739589425844690456357962574138536055595012765940271
    var1.mul_assign(&var10);
    //  297 : 74673290795521789050754958357703378761825431850296554144222380051063761084
    square!(var1, 2);
    //  299 : 74673290795521789050754958357703378761825431850296554144222380051063761085
    var1.mul_assign(var0);
    //  300 : 19116362443653577996993269339572064963027310553675917860920929293072322837760
    square!(var1, 8);
    //  308 : 19116362443653577996993269339572064963027310553675917860920929293072322837765
    var1.mul_assign(&var15);
    //  309 : 2446894392787657983615138475465224315267495750870517486197878949513257323233920
    square!(var1, 7);
    //  316 : 2446894392787657983615138475465224315267495750870517486197878949513257323233925
    var1.mul_assign(&var15);
    //  317 : 39150310284602527737842215607443589044279932013928279779166063192212117171742800
    square!(var1, 4);
    //  321 : 39150310284602527737842215607443589044279932013928279779166063192212117171742803
    var1.mul_assign(&var2);
    //  322 : 5011239716429123550443803597752779397667831297782819811733256088603150997983078784
    square!(var1, 7);
    //  329 : 5011239716429123550443803597752779397667831297782819811733256088603150997983078795
    var1.mul_assign(&var13);
    //  330 : 320719341851463907228403430256177881450741203058100467950928389670601663870917042880
    square!(var1, 6);
    //  336 : 320719341851463907228403430256177881450741203058100467950928389670601663870917042895
    var1.mul_assign(&var10);
    //  337 : 5131509469623422515654454884098846103211859248929607487214854234729626621934672686320
    square!(var1, 4);
    //  341 : 5131509469623422515654454884098846103211859248929607487214854234729626621934672686333
    var1.mul_assign(&var5);
    //  342 : 656833212111798082003770225164652301211117983862989758363501342045392207607638103850624
    square!(var1, 7);
    //  349 : 656833212111798082003770225164652301211117983862989758363501342045392207607638103850635
    var1.mul_assign(&var13);
    //  350 : 42037325575155077248241294410537747277511550967231344535264085890905101286888838646440640
    square!(var1, 6);
    //  356 : 42037325575155077248241294410537747277511550967231344535264085890905101286888838646440667
    var1.mul_assign(&var12);
    //  357 : 1345194418404962471943721421137207912880369630951403025128450748508963241180442836686101344
    square!(var1, 5);
    //  362 : 1345194418404962471943721421137207912880369630951403025128450748508963241180442836686101367
    var1.mul_assign(&var7);
    //  363 : 43046221388958799102199085476390653212171828190444896804110423952286823717774170773955243744
    square!(var1, 5);
    //  368 : 43046221388958799102199085476390653212171828190444896804110423952286823717774170773955243749
    var1.mul_assign(&var15);
    //  369 : 5509916337786726285081482940978003611157994008376946790926134265892713435875093859066271199872
    square!(var1, 7);
    //  376 : 5509916337786726285081482940978003611157994008376946790926134265892713435875093859066271199899
    var1.mul_assign(&var12);
    //  377 : 176317322809175241122607454111296115557055808268062297309636296508566829948003003490120678396768
    square!(var1, 5);
    //  382 : 176317322809175241122607454111296115557055808268062297309636296508566829948003003490120678396791
    var1.mul_assign(&var7);
    //  383 : 5642154329893607715923438531561475697825785864577993513908361488274138558336096111683861708697312
    square!(var1, 5);
    //  388 : 5642154329893607715923438531561475697825785864577993513908361488274138558336096111683861708697333
    var1.mul_assign(&var4);
    //  389 : 90274469278297723454775016504983611165212573833247896222533783812386216933377537786941787339157328
    square!(var1, 4);
    //  393 : 90274469278297723454775016504983611165212573833247896222533783812386216933377537786941787339157331
    var1.mul_assign(&var2);
    //  394 : 5777566033811054301105601056318951114573604725327865358242162163992717883736162418364274389706069184
    square!(var1, 6);
    //  400 : 5777566033811054301105601056318951114573604725327865358242162163992717883736162418364274389706069189
    var1.mul_assign(&var15);
    //  401 : 369764226163907475270758467604412871332710702420983382927498378495533944559114394775313560941188428096
    square!(var1, 6);
    //  407 : 369764226163907475270758467604412871332710702420983382927498378495533944559114394775313560941188428105
    var1.mul_assign(&var14);
    //  408 : 5916227618622519604332135481670605941323371238735734126839974055928543112945830316405016975059014849680
    square!(var1, 4);
    //  412 : 5916227618622519604332135481670605941323371238735734126839974055928543112945830316405016975059014849683
    var1.mul_assign(&var2);
    //  413 : 94659641897960313669314167706729695061173939819771746029439584894856689807133285062480271600944237594928
    square!(var1, 4);
    //  417 : 94659641897960313669314167706729695061173939819771746029439584894856689807133285062480271600944237594931
    var1.mul_assign(&var2);
    //  418 : 24232868325877840299344426932922801935660528593861566983536533733083312590626120975994949529841724824302336
    square!(var1, 8);
    //  426 : 24232868325877840299344426932922801935660528593861566983536533733083312590626120975994949529841724824302345
    var1.mul_assign(&var14);
    //  427 : 775451786428090889579021661853529661941136915003570143473169079458666002900035871231838384954935194377675040
    square!(var1, 5);
    //  432 : 775451786428090889579021661853529661941136915003570143473169079458666002900035871231838384954935194377675055
    var1.mul_assign(&var10);
    //  433 : 49628914331397816933057386358625898364232762560228489182282821085354624185602295758837656637115852440171203520
    square!(var1, 6);
    //  439 : 49628914331397816933057386358625898364232762560228489182282821085354624185602295758837656637115852440171203527
    var1.mul_assign(&var3);
    //  440 : 1588125258604730141857836363476028747655448401927311653833050274731347973939273464282805012387707278085478512864
    square!(var1, 5);
    //  445 : 1588125258604730141857836363476028747655448401927311653833050274731347973939273464282805012387707278085478512879
    var1.mul_assign(&var10);
    //  446 : 6504961059244974661049697744797813750396716654294268534100173925299601301255264109702369330740049011038119988752384
    square!(var1, 12);
    //  458 : 6504961059244974661049697744797813750396716654294268534100173925299601301255264109702369330740049011038119988752401
    var1.mul_assign(&var9);
    //  459 : 104079376947919594576795163916765020006347466468708296545602782804793620820084225755237909291840784176609919820038416
    square!(var1, 4);
    //  463 : 104079376947919594576795163916765020006347466468708296545602782804793620820084225755237909291840784176609919820038429
    var1.mul_assign(&var5);
    //  464 : 3330540062333427026457445245336480640203118926998665489459289049753395866242695224167613097338905093651517434241229728
    square!(var1, 5);
    //  469 : 3330540062333427026457445245336480640203118926998665489459289049753395866242695224167613097338905093651517434241229741
    var1.mul_assign(&var5);
    //  470 : 213154563989339329693276495701534760972999611327914591325394499184217335439532494346727238229689925993697115791438703424
    square!(var1, 6);
    //  476 : 213154563989339329693276495701534760972999611327914591325394499184217335439532494346727238229689925993697115791438703427
    var1.mul_assign(&var2);
    //  477 : 109135136762541736802957565799185797618175800999892270758601983582319275745040637105524345973601242108772923285216616154624
    square!(var1, 9);
    //  486 : 109135136762541736802957565799185797618175800999892270758601983582319275745040637105524345973601242108772923285216616154649
    var1.mul_assign(&var6);
    //  487 : 3492324376401335577694642105573945523781625631996552664275263474634216823841300387376779071155239747480733545126931716948768
    square!(var1, 5);
    //  492 : 3492324376401335577694642105573945523781625631996552664275263474634216823841300387376779071155239747480733545126931716948793
    var1.mul_assign(&var6);
    //  493 : 223508760089685476972457094756732513522024040447779370513616862376589876725843224792113860553935343838766946888123629884722752
    square!(var1, 6);
    //  499 : 223508760089685476972457094756732513522024040447779370513616862376589876725843224792113860553935343838766946888123629884722755
    var1.mul_assign(&var2);
    //  500 : 14304560645739870526237254064430880865409538588657879712871479192101752110453966386695287075451862005681084600839912312622256320
    square!(var1, 6);
    //  506 : 14304560645739870526237254064430880865409538588657879712871479192101752110453966386695287075451862005681084600839912312622256323
    var1.mul_assign(&var2);
    //  507 : 7323935050618813709433474080988611003089683757392834412990197346356097080552430789987986982631353346908715315630035104062595237376
    square!(var1, 9);
    //  516 : 7323935050618813709433474080988611003089683757392834412990197346356097080552430789987986982631353346908715315630035104062595237399
    var1.mul_assign(&var7);
    //  517 : 937463686479208154807484682366542208395479520946282804862745260333580426310711141118462333776813228404315560400644493320012190387072
    square!(var1, 7);
    //  524 : 937463686479208154807484682366542208395479520946282804862745260333580426310711141118462333776813228404315560400644493320012190387087
    var1.mul_assign(&var10);
    //  525 : 59997675934669321907679019671458701337310689340562099511215696661349147283885513031581589361716046617876195865641247572480780184773568
    square!(var1, 6);
    //  531 : 59997675934669321907679019671458701337310689340562099511215696661349147283885513031581589361716046617876195865641247572480780184773593
    var1.mul_assign(&var6);
    //  532 : 1919925629909418301045728629486678442793942058897987184358902293163172713084336417010610859574913491772038267700519922319384965912754976
    square!(var1, 5);
    //  537 : 1919925629909418301045728629486678442793942058897987184358902293163172713084336417010610859574913491772038267700519922319384965912754985
    var1.mul_assign(&var14);
    //  538 : 245750480628405542533853264574294840677624583538942359597939493524886107274795061377358190025588926946820898265666550056881275636832638080
    square!(var1, 7);
    //  545 : 245750480628405542533853264574294840677624583538942359597939493524886107274795061377358190025588926946820898265666550056881275636832638103
    var1.mul_assign(&var7);
    //  546 : 983001922513622170135413058297179362710498334155769438391757974099544429099180245509432760102355707787283593062666200227525102547330552412
    square!(var1, 2);
    //  548 : 983001922513622170135413058297179362710498334155769438391757974099544429099180245509432760102355707787283593062666200227525102547330552413
    var1.mul_assign(var0);
    //  549 : 251648492163487275554665742924077916853887573543876976228290041369483373849390142850414786586203061193544599824042547258246426252116621417728
    square!(var1, 8);
    //  557 : 251648492163487275554665742924077916853887573543876976228290041369483373849390142850414786586203061193544599824042547258246426252116621417739
    var1.mul_assign(&var13);
    //  558 : 4026375874615796408874651886785246669662201176702031619652640661911733981590242285606636585379248979096713597184680756131942820033865942683824
    square!(var1, 4);
    //  562 : 4026375874615796408874651886785246669662201176702031619652640661911733981590242285606636585379248979096713597184680756131942820033865942683829
    var1.mul_assign(&var15);
    //  563 : 515376111950821940335955441508511573716761750617860047315538004724701949643551012557649482928543869324379340439639136784888680964334840663530112
    square!(var1, 7);
    //  570 : 515376111950821940335955441508511573716761750617860047315538004724701949643551012557649482928543869324379340439639136784888680964334840663530119
    var1.mul_assign(&var3);
    //  571 : 131936284659410416726004593026178962871491008158172172112777729209523699108749059214758267629707230547041111152547619016931502326869719209863710464
    square!(var1, 8);
    //  579 : 131936284659410416726004593026178962871491008158172172112777729209523699108749059214758267629707230547041111152547619016931502326869719209863710473
    var1.mul_assign(&var14);
    //  580 : 16887844436404533340928587907350907247550849044246038030435549338819033485919879579489058256602525510021262227526095234167232297839324058862554940544
    square!(var1, 7);
    //  587 : 16887844436404533340928587907350907247550849044246038030435549338819033485919879579489058256602525510021262227526095234167232297839324058862554940557
    var1.mul_assign(&var5);
    //  588 : 17293152702878242141110874017127329021492069421307942943166002522950690289581956689396795654760986122261772520986721519787245872987467836275256259130368
    square!(var1, 10);
    //  598 : 17293152702878242141110874017127329021492069421307942943166002522950690289581956689396795654760986122261772520986721519787245872987467836275256259130377
    var1.mul_assign(&var14);
    //  599 : 1106761772984207497031095937096149057375492442963708348362624161468844178533245228121394921904703111824753441343150177266383735871197941521616400584344128
    square!(var1, 6);
    //  605 : 1106761772984207497031095937096149057375492442963708348362624161468844178533245228121394921904703111824753441343150177266383735871197941521616400584344139
    var1.mul_assign(&var13);
    //  606 : 70832753470989279809990139974153539672031516349677334295207946334006027426127694599769275001900999156784220245961611345048559095756668257383449637398024896
    square!(var1, 6);
    //  612 : 70832753470989279809990139974153539672031516349677334295207946334006027426127694599769275001900999156784220245961611345048559095756668257383449637398024909
    var1.mul_assign(&var5);
    //  613 : 4533296222143313907839368958345826539010017046379349394893308565376385755272172454385233600121663946034190095741543126083107782128426768472540776793473594176
    square!(var1, 6);
    //  619 : 4533296222143313907839368958345826539010017046379349394893308565376385755272172454385233600121663946034190095741543126083107782128426768472540776793473594207
    var1.mul_assign(&var11);
    //  620 : 145065479108586045050859806667066449248320545484139180636585874092044344168709518540327475203893246273094083063729380034659449028109656591121304857391155014624
    square!(var1, 5);
    //  625 : 145065479108586045050859806667066449248320545484139180636585874092044344168709518540327475203893246273094083063729380034659449028109656591121304857391155014649
    var1.mul_assign(&var6);
    //  626 : 18568381325899013766510055253384505503785029821969815121482991883781676053594818373161916826098335522956042632157360644436409475598036043663527021746067841875072
    square!(var1, 7);
    //  633 : 18568381325899013766510055253384505503785029821969815121482991883781676053594818373161916826098335522956042632157360644436409475598036043663527021746067841875087
    var1.mul_assign(&var10);
    //  634 : 594188202428768440528321768108304176121120954303034083887455740281013633715034187941181338435146736734593364229035540621965103219137153397232864695874170940002784
    square!(var1, 5);
    //  639 : 594188202428768440528321768108304176121120954303034083887455740281013633715034187941181338435146736734593364229035540621965103219137153397232864695874170940002797
    var1.mul_assign(&var5);
    //  640 : 76056089910882360387625186317862934543503482150788362737594334755969745115524376056471211319698782302027950621316549199611533212049555634845806681071893880320358016
    square!(var1, 7);
    //  647 : 76056089910882360387625186317862934543503482150788362737594334755969745115524376056471211319698782302027950621316549199611533212049555634845806681071893880320358047
    var1.mul_assign(&var11);
    //  648 : 2433794877148235532404005962171613905392111428825227607603018712191031843696780033807078762230361033664894419882129574387569062785585780315065813794300604170251457504
    square!(var1, 5);
    //  653 : 2433794877148235532404005962171613905392111428825227607603018712191031843696780033807078762230361033664894419882129574387569062785585780315065813794300604170251457511
    var1.mul_assign(&var3);
    //  654 : 623051488549948296295425526315933159780380525779258267546372790320904151986375688654612163130972424618212971489825171043217680073109959760656848331340954667584373122816
    square!(var1, 8);
    //  662 : 623051488549948296295425526315933159780380525779258267546372790320904151986375688654612163130972424618212971489825171043217680073109959760656848331340954667584373122843
    var1.mul_assign(&var12);
    //  663 : 39875295267196690962907233684219722225944353649872529122967858580537865727128044073895178440382235175565630175348810946765931524679037424682038293205821098725399879861952
    square!(var1, 6);
    //  669 : 39875295267196690962907233684219722225944353649872529122967858580537865727128044073895178440382235175565630175348810946765931524679037424682038293205821098725399879861981
    var1.mul_assign(&var8);
    //  670 : 2552018897100588221626062955790062222460438633591841863869942949154423406536194820729291420184463051236200331222323900593019617579458395179650450765172550318425592311166784
    square!(var1, 6);
    //  676 : 2552018897100588221626062955790062222460438633591841863869942949154423406536194820729291420184463051236200331222323900593019617579458395179650450765172550318425592311166787
    var1.mul_assign(&var2);
    //  677 : 326658418828875292368136058341127964474936145099755758575352697491766196036632937053349301783611270558233642396457459275906511050170674582995257697942086440758475815829348736
    square!(var1, 7);
    //  684 : 326658418828875292368136058341127964474936145099755758575352697491766196036632937053349301783611270558233642396457459275906511050170674582995257697942086440758475815829348747
    var1.mul_assign(&var13);
    //  685 : 41812277610096037423121415467664379452791826572768737097645145278946073092689015942828710628302242631453906226746554787316033414421846346623392985336587064417084904426156639616
    square!(var1, 7);
    //  692 : 41812277610096037423121415467664379452791826572768737097645145278946073092689015942828710628302242631453906226746554787316033414421846346623392985336587064417084904426156639627
    var1.mul_assign(&var13);
    //  693 : 2675985767046146395079770589930520284978676900657199174249289297852548677932097020341037480211343528413049998511779506388226138522998166183897151061541572122693433883274024936128
    square!(var1, 6);
    //  699 : 2675985767046146395079770589930520284978676900657199174249289297852548677932097020341037480211343528413049998511779506388226138522998166183897151061541572122693433883274024936131
    var1.mul_assign(&var2);
    //  700 : 85631544545476684642552658877776649119317660821030373575977257531281557693827104650913199366762992909217599952376944204423236432735941317884708833969330307926189884264768797956192
    square!(var1, 5);
    //  705 : 85631544545476684642552658877776649119317660821030373575977257531281557693827104650913199366762992909217599952376944204423236432735941317884708833969330307926189884264768797956199
    var1.mul_assign(&var3);
    //  706 : 87686701614568125073973922690843288698181284680735102541800711712032315078478955162535116151565304739038822351233990865329394107121603909513941845984594235316418441487123249107147776
    square!(var1, 10);
    //  716 : 87686701614568125073973922690843288698181284680735102541800711712032315078478955162535116151565304739038822351233990865329394107121603909513941845984594235316418441487123249107147803
    var1.mul_assign(&var12);
    //  717 : 1402987225833090001183582763053492619170900554891761640668811387392517041255663282600561858425044875824621157619743853845270305713945662552223069535753507765062695063793971985714364848
    square!(var1, 4);
    //  721 : 1402987225833090001183582763053492619170900554891761640668811387392517041255663282600561858425044875824621157619743853845270305713945662552223069535753507765062695063793971985714364849
    var1.mul_assign(var0);
    //  722 : 718329459626542080605994374683388221015501084104581960022431430344968725122899600691487671513622976422206032701308853168778396525540179226738211602305795975712099872662513656685754802688
    square!(var1, 9);
    //  731 : 718329459626542080605994374683388221015501084104581960022431430344968725122899600691487671513622976422206032701308853168778396525540179226738211602305795975712099872662513656685754802705
    var1.mul_assign(&var9);
    //  732 : 45973085416098693158783639979736846144992069382693245441435611542077998407865574444255210976871870491021186092883766602801817377634571470511245542547570942445574391850400874027888307373120
    square!(var1, 6);
    //  738 : 45973085416098693158783639979736846144992069382693245441435611542077998407865574444255210976871870491021186092883766602801817377634571470511245542547570942445574391850400874027888307373135
    var1.mul_assign(&var10);
    //  739 : 5884554933260632724324305917406316306558984880984735416503758277385983796206793528864667005039599422850711819889122125158632624337225148225439429446089080633033522156851311875569703343761280
    square!(var1, 7);
    //  746 : 5884554933260632724324305917406316306558984880984735416503758277385983796206793528864667005039599422850711819889122125158632624337225148225439429446089080633033522156851311875569703343761311
    var1.mul_assign(&var11);
    //  747 : 188305757864340247178377789357002121809887516191511533328120264876351481478617392923669344161267181531222778236451908005076243978791204743214061742274850580257072709019241980018230507000361952
    square!(var1, 5);
    //  752 : 188305757864340247178377789357002121809887516191511533328120264876351481478617392923669344161267181531222778236451908005076243978791204743214061742274850580257072709019241980018230507000361973
    var1.mul_assign(&var4);
    //  753 : 3012892125829443954854044629712033948958200259064184533249924238021623703657878286778709506580274904499564451783230528081219903660659275891424987876397609284113163344307871680291688112005791568
    square!(var1, 4);
    //  757 : 3012892125829443954854044629712033948958200259064184533249924238021623703657878286778709506580274904499564451783230528081219903660659275891424987876397609284113163344307871680291688112005791583
    var1.mul_assign(&var10);
    //  758 : 385650192106168826221317712603140345466649633160215620255990302466767834068208420707674816842275187775944249828253507594396147668564387314102398448178893988366484908071407575077336078336741322624
    square!(var1, 7);
    //  765 : 385650192106168826221317712603140345466649633160215620255990302466767834068208420707674816842275187775944249828253507594396147668564387314102398448178893988366484908071407575077336078336741322653
    var1.mul_assign(&var8);
    //  766 : 12340806147397402439082166803300491054932788261126899848191689678936570690182669462645594138952806008830215994504112243020676725394060394051276750341724607627727517058285042402474754506775722324896
    square!(var1, 5);
    //  771 : 12340806147397402439082166803300491054932788261126899848191689678936570690182669462645594138952806008830215994504112243020676725394060394051276750341724607627727517058285042402474754506775722324917
    var1.mul_assign(&var4);
    //  772 : 394905796716716878050629337705615713757849224356060795142134069725970262085845422804659012446489792282566911824131591776661655212609932609640856010935187444087280545865121356879192144216823114397344
    square!(var1, 5);
    //  777 : 394905796716716878050629337705615713757849224356060795142134069725970262085845422804659012446489792282566911824131591776661655212609932609640856010935187444087280545865121356879192144216823114397365
    var1.mul_assign(&var4);
    //  778 : 12636985494934940097620138806579702840251175179393945444548290231231048386747053529749088398287673353042141178372210936853172966803517843508507392349925998210792977467683883420134148614938339660715680
    square!(var1, 5);
    //  783 : 12636985494934940097620138806579702840251175179393945444548290231231048386747053529749088398287673353042141178372210936853172966803517843508507392349925998210792977467683883420134148614938339660715697
    var1.mul_assign(&var9);
    //  784 : 202191767918959041561922220905275245444018802870303127112772643699696774187952856475985414372602773648674258853955374989650767468856285496136118277598815971372687639482942134722146377839013434571451152
    square!(var1, 4);
    //  788 : 202191767918959041561922220905275245444018802870303127112772643699696774187952856475985414372602773648674258853955374989650767468856285496136118277598815971372687639482942134722146377839013434571451165
    var1.mul_assign(&var5);
    //  789 : 12940273146813378659963022137937615708417203383699400135217449196780593548028982814463066519846577513515152566653143999337649118006802271752711569766324222167852008926908296622217368181696859812572874560
    square!(var1, 6);
    //  795 : 12940273146813378659963022137937615708417203383699400135217449196780593548028982814463066519846577513515152566653143999337649118006802271752711569766324222167852008926908296622217368181696859812572874589
    var1.mul_assign(&var8);
    //  796 : 25880546293626757319926044275875231416834406767398800270434898393561187096057965628926133039693155027030305133306287998675298236013604543505423139532648444335704017853816593244434736363393719625145749178
    var1 = var1.square();
    //  797 : 25880546293626757319926044275875231416834406767398800270434898393561187096057965628926133039693155027030305133306287998675298236013604543505423139532648444335704017853816593244434736363393719625145749179
    var1.mul_assign(var0);
    //  798 : 1656354962792112468475266833656014810677402033113523217307833497187915974147709800251272514540361921729939528531602431915219087104870690784347080930089500437485057142644261967643823127257198056009327947456
    square!(var1, 6);
    //  804 : 1656354962792112468475266833656014810677402033113523217307833497187915974147709800251272514540361921729939528531602431915219087104870690784347080930089500437485057142644261967643823127257198056009327947463
    var1.mul_assign(&var3);
    //  805 : 1696107481899123167718673237663759166133659681908247774523221501120425957527254835457303054889330607851458077216360890281184345195387587363171410872411648447984698514067724254867274882311370809353551818202112
    square!(var1, 10);
    //  815 : 1696107481899123167718673237663759166133659681908247774523221501120425957527254835457303054889330607851458077216360890281184345195387587363171410872411648447984698514067724254867274882311370809353551818202135
    var1.mul_assign(&var7);
    //  816 : 108550878841543882733995087210480586632554219642127857569486176071707261281744309469267395512917158902493316941847096977995798092504805591242970295834345500671020704900334352311505592467927731798627316364936640
    square!(var1, 6);
    //  822 : 108550878841543882733995087210480586632554219642127857569486176071707261281744309469267395512917158902493316941847096977995798092504805591242970295834345500671020704900334352311505592467927731798627316364936661
    var1.mul_assign(&var4);
    //  823 : 6947256245858808494975685581470757544483470057096182884447115268589264722031635806033113312826698169759572284278214206591731077920307557839550098933398112042945325113621398547936357917947374835112148247355946304
    square!(var1, 6);
    //  829 : 6947256245858808494975685581470757544483470057096182884447115268589264722031635806033113312826698169759572284278214206591731077920307557839550098933398112042945325113621398547936357917947374835112148247355946329
    var1.mul_assign(&var6);
    //  830 : 444624399734963743678443877214128482846942083654155704604615377189712942210024691586119252020908682864612626193805709221870788986899683701731206331737479170748500807271769507067926906748631989447177487830780565056
    square!(var1, 6);
    //  836 : 444624399734963743678443877214128482846942083654155704604615377189712942210024691586119252020908682864612626193805709221870788986899683701731206331737479170748500807271769507067926906748631989447177487830780565069
    var1.mul_assign(&var5);
    //  837 : 28455961583037679595420408141704222902204293353865965094695384140141628301441580261511632129338155703335208076403565390199730495161579756910797205231198666927904051665393248452347322031912447324619359221169956164416
    square!(var1, 6);
    //  843 : 28455961583037679595420408141704222902204293353865965094695384140141628301441580261511632129338155703335208076403565390199730495161579756910797205231198666927904051665393248452347322031912447324619359221169956164437
    var1.mul_assign(&var4);
    //  844 : 238705906983162543355580399100765177871214152862586865721082456961065184302499251714358569373223087638243353151383559860752580829556389241459968722180074986980751351032731127113348364375477010926880553717580063640645533696
    square!(var1, 23);
    //  867 : 238705906983162543355580399100765177871214152862586865721082456961065184302499251714358569373223087638243353151383559860752580829556389241459968722180074986980751351032731127113348364375477010926880553717580063640645533703
    var1.mul_assign(&var3);
    //  868 : 15277178046922402774757145542448971383757705783205559406149277245508171795359952109718948439886277608847574601688547831088165173091608911453437998219524799166768086466094792135254295320030528699320355437925124073001314156992
    square!(var1, 6);
    //  874 : 15277178046922402774757145542448971383757705783205559406149277245508171795359952109718948439886277608847574601688547831088165173091608911453437998219524799166768086466094792135254295320030528699320355437925124073001314156999
    var1.mul_assign(&var3);
    //  875 : 488869697501516888792228657358367084280246585062577900996776871856261497451518467511006350076360883483122387254033530594821285538931485166510015943024793573336578766915033348328137450240976918378251374013603970336042053023968
    square!(var1, 5);
    //  880 : 488869697501516888792228657358367084280246585062577900996776871856261497451518467511006350076360883483122387254033530594821285538931485166510015943024793573336578766915033348328137450240976918378251374013603970336042053023971
    var1.mul_assign(&var2);
    //  881 : 31287660640097080882702634070935493393935781444004985663793719798800735836897181920704406404887096542919832784258145958068562274491615050656641020353586788693541041082562134293000796815422522776208087936870654101506691393534144
    square!(var1, 6);
    //  887 : 31287660640097080882702634070935493393935781444004985663793719798800735836897181920704406404887096542919832784258145958068562274491615050656641020353586788693541041082562134293000796815422522776208087936870654101506691393534151
    var1.mul_assign(&var3);
    //  888 : 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092832
    square!(var1, 5);
    //  893 : 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835
    var1 * var2
}

/// Tests for addition chains
#[cfg(test)]
mod tests {
    use super::*;
    use rand_core::SeedableRng;

    const SEED: [u8; 16] = [
        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
        0xe5,
    ];

    #[test]
    fn test_fp_chain() {
        let mut rng = rand_xorshift::XorShiftRng::from_seed(SEED);
        let p_m3_over4 = [
            0xee7f_bfff_ffff_eaaa,
            0x07aa_ffff_ac54_ffff,
            0xd9cc_34a8_3dac_3d89,
            0xd91d_d2e1_3ce1_44af,
            0x92c6_e9ed_90d2_eb35,
            0x0680_447a_8e5f_f9a6,
        ];

        for _ in 0..32 {
            let input = Fp::random(&mut rng);
            assert_eq!(chain_pm3div4(&input), input.pow_vartime(&p_m3_over4));
        }
    }

    #[test]
    fn test_fp2_chain() {
        let mut rng = rand_xorshift::XorShiftRng::from_seed(SEED);
        let p_sq_m9_over16 = [
            0xb26a_a000_01c7_18e3,
            0xd7ce_d6b1_d763_82ea,
            0x3162_c338_3621_13cf,
            0x966b_f91e_d3e7_1b74,
            0xb292_e85a_8709_1a04,
            0x11d6_8619_c861_85c7,
            0xef53_1493_3097_8ef0,
            0x050a_62cf_d16d_dca6,
            0x466e_59e4_9349_e8bd,
            0x9e2d_c90e_50e7_046b,
            0x74bd_278e_aa22_f25e,
            0x002a_437a_4b8c_35fc,
        ];

        for _ in 0..32 {
            let input = Fp2::random(&mut rng);
            assert_eq!(
                chain_p2m9div16(&input),
                input.pow_vartime_extended(&p_sq_m9_over16[..]),
            );
        }
    }
}