arnaucube
arnaucube/websnarkPublic Self-hosted repository
websnark/src/build_int.js
src/build_int.jsRaw
  1/*
  2    Copyright 2019 0KIMS association.
  3
  4    This file is part of websnark (Web Assembly zkSnark Prover).
  5
  6    websnark is a free software: you can redistribute it and/or modify it
  7    under the terms of the GNU General Public License as published by
  8    the Free Software Foundation, either version 3 of the License, or
  9    (at your option) any later version.
 10
 11    websnark is distributed in the hope that it will be useful, but WITHOUT
 12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 13    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 14    License for more details.
 15
 16    You should have received a copy of the GNU General Public License
 17    along with websnark. If not, see <https://www.gnu.org/licenses/>.
 18*/
 19
 20const utils = require("./utils.js");
 21
 22module.exports = function buildInt(module, n64, _prefix) {
 23
 24    const prefix = _prefix || "int";
 25    if (module.modules[prefix]) return prefix;  // already builded
 26    module.modules[prefix] = {};
 27
 28    const n32 = n64*2;
 29    const n8 = n64*8;
 30
 31    const one = module.alloc(n8, utils.bigInt2BytesLE(1, n8));
 32
 33    function buildCopy() {
 34        const f = module.addFunction(prefix+"_copy");
 35        f.addParam("px", "i32");
 36        f.addParam("pr", "i32");
 37
 38        const c = f.getCodeBuilder();
 39
 40        for (let i=0; i<n64; i++) {
 41            f.addCode(
 42                c.i64_store(
 43                    c.getLocal("pr"),
 44                    i*8,
 45                    c.i64_load(
 46                        c.getLocal("px"),
 47                        i*8
 48                    )
 49                )
 50            );
 51        }
 52    }
 53
 54    function buildZero() {
 55        const f = module.addFunction(prefix+"_zero");
 56        f.addParam("pr", "i32");
 57
 58        const c = f.getCodeBuilder();
 59
 60        for (let i=0; i<n64; i++) {
 61            f.addCode(
 62                c.i64_store(
 63                    c.getLocal("pr"),
 64                    i*8,
 65                    c.i64_const(0)
 66                )
 67            );
 68        }
 69    }
 70
 71    function buildOne() {
 72        const f = module.addFunction(prefix+"_one");
 73        f.addParam("pr", "i32");
 74
 75        const c = f.getCodeBuilder();
 76
 77        f.addCode(
 78            c.i64_store(
 79                c.getLocal("pr"),
 80                0,
 81                c.i64_const(1)
 82            )
 83        );
 84        for (let i=1; i<n64; i++) {
 85            f.addCode(
 86                c.i64_store(
 87                    c.getLocal("pr"),
 88                    i*8,
 89                    c.i64_const(0)
 90                )
 91            );
 92        }
 93    }
 94
 95    function buildIsZero() {
 96        const f = module.addFunction(prefix+"_isZero");
 97        f.addParam("px", "i32");
 98        f.setReturnType("i32");
 99
100        const c = f.getCodeBuilder();
101
102        function getCompCode(n) {
103            if (n==0) {
104                return  c.ret(c.i64_eqz(
105                    c.i64_load(c.getLocal("px"))
106                ));
107            }
108            return c.if(
109                c.i64_eqz(
110                    c.i64_load(c.getLocal("px"), n*8 )
111                ),
112                getCompCode(n-1),
113                c.ret(c.i32_const(0))
114            );
115        }
116
117        f.addCode(getCompCode(n64-1));
118        f.addCode(c.ret(c.i32_const(0)));
119    }
120
121    function buildEq() {
122        const f = module.addFunction(prefix+"_eq");
123        f.addParam("px", "i32");
124        f.addParam("py", "i32");
125        f.setReturnType("i32");
126
127        const c = f.getCodeBuilder();
128
129        function getCompCode(n) {
130            if (n==0) {
131                return  c.ret(c.i64_eq(
132                    c.i64_load(c.getLocal("px")),
133                    c.i64_load(c.getLocal("py"))
134                ));
135            }
136            return c.if(
137                c.i64_eq(
138                    c.i64_load(c.getLocal("px"), n*8 ),
139                    c.i64_load(c.getLocal("py"), n*8 )
140                ),
141                getCompCode(n-1),
142                c.ret(c.i32_const(0))
143            );
144        }
145
146        f.addCode(getCompCode(n64-1));
147        f.addCode(c.ret(c.i32_const(0)));
148    }
149
150
151
152    function buildGte() {
153        const f = module.addFunction(prefix+"_gte");
154        f.addParam("px", "i32");
155        f.addParam("py", "i32");
156        f.setReturnType("i32");
157
158        const c = f.getCodeBuilder();
159
160        function getCompCode(n) {
161            if (n==0) {
162                return  c.ret(c.i64_ge_u(
163                    c.i64_load(c.getLocal("px")),
164                    c.i64_load(c.getLocal("py"))
165                ));
166            }
167            return c.if(
168                c.i64_lt_u(
169                    c.i64_load(c.getLocal("px"), n*8 ),
170                    c.i64_load(c.getLocal("py"), n*8 )
171                ),
172                c.ret(c.i32_const(0)),
173                c.if(
174                    c.i64_gt_u(
175                        c.i64_load(c.getLocal("px"), n*8 ),
176                        c.i64_load(c.getLocal("py"), n*8 )
177                    ),
178                    c.ret(c.i32_const(1)),
179                    getCompCode(n-1)
180                )
181            );
182        }
183
184        f.addCode(getCompCode(n64-1));
185        f.addCode(c.ret(c.i32_const(0)));
186    }
187
188
189
190    function buildAdd() {
191
192        const f = module.addFunction(prefix+"_add");
193        f.addParam("x", "i32");
194        f.addParam("y", "i32");
195        f.addParam("r", "i32");
196        f.setReturnType("i32");
197        f.addLocal("c", "i64");
198
199        const c = f.getCodeBuilder();
200
201        f.addCode(c.setLocal(
202            "c",
203            c.i64_add(
204                c.i64_load32_u(c.getLocal("x")),
205                c.i64_load32_u(c.getLocal("y"))
206            )
207        ));
208
209        f.addCode(c.i64_store32(
210            c.getLocal("r"),
211            c.getLocal("c"),
212        ));
213
214        for (let i=1; i<n32; i++) {
215            f.addCode(c.setLocal( "c",
216                c.i64_add(
217                    c.i64_add(
218                        c.i64_load32_u(c.getLocal("x"), 4*i),
219                        c.i64_load32_u(c.getLocal("y"), 4*i)
220                    ),
221                    c.i64_shr_u (c.getLocal("c"), c.i64_const(32))
222                )
223            ));
224
225            f.addCode(c.i64_store32(
226                c.getLocal("r"),
227                i*4,
228                c.getLocal("c")
229            ));
230        }
231
232        f.addCode(c.i32_wrap_i64(c.i64_shr_u (c.getLocal("c"), c.i64_const(32))));
233    }
234
235
236    function buildSub() {
237
238        const f = module.addFunction(prefix+"_sub");
239        f.addParam("x", "i32");
240        f.addParam("y", "i32");
241        f.addParam("r", "i32");
242        f.setReturnType("i32");
243        f.addLocal("c", "i64");
244
245        const c = f.getCodeBuilder();
246
247        f.addCode(c.setLocal(
248            "c",
249            c.i64_sub(
250                c.i64_load32_u(c.getLocal("x")),
251                c.i64_load32_u(c.getLocal("y"))
252            )
253        ));
254
255        f.addCode(c.i64_store32(
256            c.getLocal("r"),
257            c.i64_and(
258                c.getLocal("c"),
259                c.i64_const("0xFFFFFFFF")
260            )
261        ));
262
263        for (let i=1; i<n32; i++) {
264            f.addCode(c.setLocal( "c",
265                c.i64_add(
266                    c.i64_sub(
267                        c.i64_load32_u(c.getLocal("x"), 4*i),
268                        c.i64_load32_u(c.getLocal("y"), 4*i)
269                    ),
270                    c.i64_shr_s (c.getLocal("c"), c.i64_const(32))
271                )
272            ));
273
274            f.addCode(c.i64_store32(
275                c.getLocal("r"),
276                i*4,
277                c.i64_and( c.getLocal("c"), c.i64_const("0xFFFFFFFF"))
278            ));
279        }
280
281        f.addCode(c.i32_wrap_i64 ( c.i64_shr_s (c.getLocal("c"), c.i64_const(32))));
282    }
283
284
285    function buildMul() {
286
287        const mulBuff = module.alloc(n32*n32*8);
288
289        const f = module.addFunction(prefix+"_mul");
290        f.addParam("x", "i32");
291        f.addParam("y", "i32");
292        f.addParam("r", "i32");
293        f.addLocal("c", "i64");
294
295        const c = f.getCodeBuilder();
296
297        for (let i=0; i<n32; i++) {
298            for (let j=0; j<n32; j++) {
299                f.addCode(c.i64_store(
300                    c.i32_const(mulBuff),
301                    (i*n32+j)*8,
302                    c.i64_mul(
303                        c.i64_load32_u( c.getLocal("x"), i*4),
304                        c.i64_load32_u( c.getLocal("y"), j*4)
305                    )
306                ));
307            }
308        }
309
310        for (let i=0; i<n32; i++) {
311            f.addCode(c.i64_shr_u(c.getLocal("c"), c.i64_const(32)));
312            for (let j=0; j<i; j++) {
313                f.addCode(c.i64_add(
314                    [],
315                    c.i64_load32_u(
316                        c.i32_const(mulBuff),
317                        j*(n32*8) + i*8-4 - j*8
318                    )
319                ));
320            }
321            for (let j=0; j<i+1; j++) {
322                f.addCode(c.i64_add(
323                    [],
324                    c.i64_load32_u(
325                        c.i32_const(mulBuff),
326                        j*(n32*8) + i*8 - j*8
327                    )
328                ));
329            }
330            f.addCode(c.setLocal("c", []));
331            f.addCode(
332                c.i64_store32(
333                    c.getLocal("r"),
334                    i*4,
335                    c.getLocal("c")
336                )
337            );
338        }
339
340        for (let i=0; i<n32; i++) {
341            f.addCode(c.i64_shr_u(c.getLocal("c"), c.i64_const(32)));
342            for (let j=i; j<n32; j++) {
343                f.addCode(c.i64_add(
344                    [],
345                    c.i64_load32_u(
346                        c.i32_const(mulBuff),
347                        j*(n32*8) + n32*8-4 + i*8- j*8
348                    )
349                ));
350            }
351            for (let j=i+1; j<n32; j++) {
352                f.addCode(c.i64_add(
353                    [],
354                    c.i64_load32_u(
355                        c.i32_const(mulBuff),
356                        j*(n32*8) + n32*8 + i*8 - j*8
357                    )
358                ));
359            }
360            f.addCode(c.setLocal("c", []));
361            f.addCode(
362                c.i64_store32(
363                    c.getLocal("r"),
364                    i*4 + n32*4,
365                    c.getLocal("c")
366                )
367            );
368        }
369    }
370
371    function _buildMul1() {
372        const f = module.addFunction(prefix+"__mul1");
373        f.addParam("px", "i32");
374        f.addParam("y", "i64");
375        f.addParam("pr", "i32");
376        f.addLocal("c", "i64");
377
378        const c = f.getCodeBuilder();
379
380        f.addCode(c.setLocal(
381            "c",
382            c.i64_mul(
383                c.i64_load32_u(c.getLocal("px"), 0, 0),
384                c.getLocal("y")
385            )
386        ));
387
388        f.addCode(c.i64_store32(
389            c.getLocal("pr"),
390            0,
391            0,
392            c.getLocal("c"),
393        ));
394
395        for (let i=1; i<n32; i++) {
396            f.addCode(c.setLocal( "c",
397                c.i64_add(
398                    c.i64_mul(
399                        c.i64_load32_u(c.getLocal("px"), 4*i, 0),
400                        c.getLocal("y")
401                    ),
402                    c.i64_shr_u (c.getLocal("c"), c.i64_const(32))
403                )
404            ));
405
406            f.addCode(c.i64_store32(
407                c.getLocal("pr"),
408                i*4,
409                0,
410                c.getLocal("c")
411            ));
412        }
413    }
414
415    function _buildAdd1() {
416        const f = module.addFunction(prefix+"__add1");
417        f.addParam("x", "i32");
418        f.addParam("y", "i64");
419        f.addLocal("c", "i64");
420        f.addLocal("px", "i32");
421
422        const c = f.getCodeBuilder();
423
424        f.addCode(c.setLocal("px", c.getLocal("x")));
425
426        f.addCode(c.setLocal(
427            "c",
428            c.i64_add(
429                c.i64_load32_u(c.getLocal("px"), 0, 0),
430                c.getLocal("y")
431            )
432        ));
433
434        f.addCode(c.i64_store32(
435            c.getLocal("px"),
436            0,
437            0,
438            c.getLocal("c"),
439        ));
440
441        f.addCode(c.setLocal(
442            "c",
443            c.i64_shr_u(
444                c.getLocal("c"),
445                c.i64_const(32)
446            )
447        ));
448
449        f.addCode(c.block(c.loop(
450            c.br_if(
451                1,
452                c.i64_eqz(c.getLocal("c"))
453            ),
454            c.setLocal(
455                "px",
456                c.i32_add(
457                    c.getLocal("px"),
458                    c.i32_const(4)
459                )
460            ),
461
462            c.setLocal(
463                "c",
464                c.i64_add(
465                    c.i64_load32_u(c.getLocal("px"), 0, 0),
466                    c.getLocal("c")
467                )
468            ),
469
470            c.i64_store32(
471                c.getLocal("px"),
472                0,
473                0,
474                c.getLocal("c"),
475            ),
476
477            c.setLocal(
478                "c",
479                c.i64_shr_u(
480                    c.getLocal("c"),
481                    c.i64_const(32)
482                )
483            ),
484
485            c.br(0)
486        )));
487    }
488
489
490    function buildDiv() {
491        _buildMul1();
492        _buildAdd1();
493
494        const f = module.addFunction(prefix+"_div");
495        f.addParam("x", "i32");
496        f.addParam("y", "i32");
497        f.addParam("c", "i32");
498        f.addParam("r", "i32");
499        f.addLocal("rr", "i32");
500        f.addLocal("cc", "i32");
501        f.addLocal("eX", "i32");
502        f.addLocal("eY", "i32");
503        f.addLocal("sy", "i64");
504        f.addLocal("sx", "i64");
505        f.addLocal("ec", "i32");
506
507        const c = f.getCodeBuilder();
508
509        const Y = c.i32_const(module.alloc(n8));
510        const Caux = c.i32_const(module.alloc(n8));
511        const Raux = c.i32_const(module.alloc(n8));
512        const C = c.getLocal("cc");
513        const R = c.getLocal("rr");
514        const pr1 = module.alloc(n8*2);
515        const R1 = c.i32_const(pr1);
516        const R2 = c.i32_const(pr1+n8);
517
518        // Ic c is 0 then store it in an auxiliary buffer
519        f.addCode(c.if(
520            c.getLocal("c"),
521            c.setLocal("cc", c.getLocal("c")),
522            c.setLocal("cc", Caux)
523        ));
524
525        // Ic r is 0 then store it in an auxiliary buffer
526        f.addCode(c.if(
527            c.getLocal("r"),
528            c.setLocal("rr", c.getLocal("r")),
529            c.setLocal("rr", Raux)
530        ));
531
532        // Copy
533        f.addCode(c.call(prefix + "_copy", c.getLocal("x"), R));
534        f.addCode(c.call(prefix + "_copy", c.getLocal("y"), Y));
535        f.addCode(c.call(prefix + "_zero", C));
536        f.addCode(c.call(prefix + "_zero", R1));
537
538
539        f.addCode(c.setLocal("eX", c.i32_const(n8-1)));
540        f.addCode(c.setLocal("eY", c.i32_const(n8-1)));
541
542        // while (eY>3)&&(Y[eY]==0) ey--;
543        f.addCode(c.block(c.loop(
544            c.br_if(
545                1,
546                c.i32_or(
547                    c.i32_load8_u(
548                        c.i32_add(Y , c.getLocal("eY")),
549                        0,
550                        0
551                    ),
552                    c.i32_eq(
553                        c.getLocal("eY"),
554                        c.i32_const(3)
555                    )
556                )
557            ),
558            c.setLocal("eY", c.i32_sub(c.getLocal("eY"), c.i32_const(1))),
559            c.br(0)
560        )));
561
562        f.addCode(
563            c.setLocal(
564                "sy",
565                c.i64_add(
566                    c.i64_load32_u(
567                        c.i32_sub(
568                            c.i32_add( Y, c.getLocal("eY")),
569                            c.i32_const(3)
570                        ),
571                        0,
572                        0
573                    ),
574                    c.i64_const(1)
575                )
576            )
577        );
578
579        // Force a divide by 0 if quotien is 0
580        f.addCode(
581            c.if(
582                c.i64_eq(
583                    c.getLocal("sy"),
584                    c.i64_const(1)
585                ),
586                c.drop(c.i64_div_u(c.i64_const(0), c.i64_const(0)))
587            )
588        );
589
590        f.addCode(c.block(c.loop(
591
592            // while (eX>7)&&(Y[eX]==0) ex--;
593            c.block(c.loop(
594                c.br_if(
595                    1,
596                    c.i32_or(
597                        c.i32_load8_u(
598                            c.i32_add(R , c.getLocal("eX")),
599                            0,
600                            0
601                        ),
602                        c.i32_eq(
603                            c.getLocal("eX"),
604                            c.i32_const(7)
605                        )
606                    )
607                ),
608                c.setLocal("eX", c.i32_sub(c.getLocal("eX"), c.i32_const(1))),
609                c.br(0)
610            )),
611
612            c.setLocal(
613                "sx",
614                c.i64_load(
615                    c.i32_sub(
616                        c.i32_add( R, c.getLocal("eX")),
617                        c.i32_const(7)
618                    ),
619                    0,
620                    0
621                )
622            ),
623
624            c.setLocal(
625                "sx",
626                c.i64_div_u(
627                    c.getLocal("sx"),
628                    c.getLocal("sy")
629                )
630            ),
631            c.setLocal(
632                "ec",
633                c.i32_sub(
634                    c.i32_sub(
635                        c.getLocal("eX"),
636                        c.getLocal("eY")
637                    ),
638                    c.i32_const(4)
639                )
640            ),
641
642            // While greater than 32 bits or ec is neg, shr and inc exp
643            c.block(c.loop(
644                c.br_if(
645                    1,
646                    c.i32_and(
647                        c.i64_eqz(
648                            c.i64_and(
649                                c.getLocal("sx"),
650                                c.i64_const("0xFFFFFFFF00000000")
651                            )
652                        ),
653                        c.i32_ge_s(
654                            c.getLocal("ec"),
655                            c.i32_const(0)
656                        )
657                    )
658                ),
659
660                c.setLocal(
661                    "sx",
662                    c.i64_shr_u(
663                        c.getLocal("sx"),
664                        c.i64_const(8)
665                    )
666                ),
667
668                c.setLocal(
669                    "ec",
670                    c.i32_add(
671                        c.getLocal("ec"),
672                        c.i32_const(1)
673                    )
674                ),
675                c.br(0)
676            )),
677
678            c.if(
679                c.i64_eqz(c.getLocal("sx")),
680                [
681                    ...c.br_if(
682                        2,
683                        c.i32_eqz(c.call(prefix + "_gte", R, Y))
684                    ),
685                    ...c.setLocal("sx", c.i64_const(1)),
686                    ...c.setLocal("ec", c.i32_const(0))
687                ]
688            ),
689
690            c.call(prefix + "__mul1", Y, c.getLocal("sx"), R2),
691            c.drop(c.call(
692                prefix + "_sub",
693                R,
694                c.i32_sub(R2, c.getLocal("ec")),
695                R
696            )),
697            c.call(
698                prefix + "__add1",
699                c.i32_add(C, c.getLocal("ec")),
700                c.getLocal("sx")
701            ),
702            c.br(0)
703        )));
704    }
705
706    function buildInverseMod() {
707
708        const f = module.addFunction(prefix+"_inverseMod");
709        f.addParam("px", "i32");
710        f.addParam("pm", "i32");
711        f.addParam("pr", "i32");
712        f.addLocal("t", "i32");
713        f.addLocal("newt", "i32");
714        f.addLocal("r", "i32");
715        f.addLocal("qq", "i32");
716        f.addLocal("qr", "i32");
717        f.addLocal("newr", "i32");
718        f.addLocal("swp", "i32");
719        f.addLocal("x", "i32");
720        f.addLocal("signt", "i32");
721        f.addLocal("signnewt", "i32");
722        f.addLocal("signx", "i32");
723
724        const c = f.getCodeBuilder();
725
726        const aux1 = c.i32_const(module.alloc(n8));
727        const aux2 = c.i32_const(module.alloc(n8));
728        const aux3 = c.i32_const(module.alloc(n8));
729        const aux4 = c.i32_const(module.alloc(n8));
730        const aux5 = c.i32_const(module.alloc(n8));
731        const aux6 = c.i32_const(module.alloc(n8));
732        const mulBuff = c.i32_const(module.alloc(n8*2));
733        const aux7 = c.i32_const(module.alloc(n8));
734
735        f.addCode(
736            c.setLocal("t", aux1),
737            c.call(prefix + "_zero", aux1),
738            c.setLocal("signt", c.i32_const(0)),
739        );
740
741        f.addCode(
742            c.setLocal("r", aux2),
743            c.call(prefix + "_copy", c.getLocal("pm"), aux2)
744        );
745
746        f.addCode(
747            c.setLocal("newt", aux3),
748            c.call(prefix + "_one", aux3),
749            c.setLocal("signnewt", c.i32_const(0)),
750        );
751
752        f.addCode(
753            c.setLocal("newr", aux4),
754            c.call(prefix + "_copy", c.getLocal("px"), aux4)
755        );
756
757
758
759
760        f.addCode(c.setLocal("qq", aux5));
761        f.addCode(c.setLocal("qr", aux6));
762        f.addCode(c.setLocal("x", aux7));
763
764        f.addCode(c.block(c.loop(
765            c.br_if(
766                1,
767                c.call(prefix + "_isZero", c.getLocal("newr") )
768            ),
769            c.call(prefix + "_div", c.getLocal("r"), c.getLocal("newr"), c.getLocal("qq"), c.getLocal("qr")),
770
771            c.call(prefix + "_mul", c.getLocal("qq"), c.getLocal("newt"), mulBuff),
772
773            c.if(
774                c.getLocal("signt"),
775                c.if(
776                    c.getLocal("signnewt"),
777                    c.if (
778                        c.call(prefix + "_gte", mulBuff, c.getLocal("t")),
779                        [
780                            ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))),
781                            ...c.setLocal("signx", c.i32_const(0))
782                        ],
783                        [
784                            ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))),
785                            ...c.setLocal("signx", c.i32_const(1))
786                        ],
787                    ),
788                    [
789                        ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))),
790                        ...c.setLocal("signx", c.i32_const(1))
791                    ]
792                ),
793                c.if(
794                    c.getLocal("signnewt"),
795                    [
796                        ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))),
797                        ...c.setLocal("signx", c.i32_const(0))
798                    ],
799                    c.if (
800                        c.call(prefix + "_gte", c.getLocal("t"), mulBuff),
801                        [
802                            ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))),
803                            ...c.setLocal("signx", c.i32_const(0))
804                        ],
805                        [
806                            ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))),
807                            ...c.setLocal("signx", c.i32_const(1))
808                        ]
809                    )
810                )
811            ),
812
813            c.setLocal("swp", c.getLocal("t")),
814            c.setLocal("t", c.getLocal("newt")),
815            c.setLocal("newt", c.getLocal("x")),
816            c.setLocal("x", c.getLocal("swp")),
817
818            c.setLocal("signt", c.getLocal("signnewt")),
819            c.setLocal("signnewt", c.getLocal("signx")),
820
821            c.setLocal("swp", c.getLocal("r")),
822            c.setLocal("r", c.getLocal("newr")),
823            c.setLocal("newr", c.getLocal("qr")),
824            c.setLocal("qr", c.getLocal("swp")),
825
826            c.br(0)
827        )));
828
829        f.addCode(c.if(
830            c.getLocal("signt"),
831            c.drop(c.call(prefix + "_sub", c.getLocal("pm"), c.getLocal("t"), c.getLocal("pr"))),
832            c.call(prefix + "_copy", c.getLocal("t"), c.getLocal("pr"))
833        ));
834    }
835
836
837    buildCopy();
838    buildZero();
839    buildIsZero();
840    buildOne();
841    buildEq();
842    buildGte();
843    buildAdd();
844    buildSub();
845    buildMul();
846    buildDiv();
847    buildInverseMod();
848    module.exportFunction(prefix+"_copy");
849    module.exportFunction(prefix+"_zero");
850    module.exportFunction(prefix+"_one");
851    module.exportFunction(prefix+"_isZero");
852    module.exportFunction(prefix+"_eq");
853    module.exportFunction(prefix+"_gte");
854    module.exportFunction(prefix+"_add");
855    module.exportFunction(prefix+"_sub");
856    module.exportFunction(prefix+"_mul");
857    module.exportFunction(prefix+"_div");
858    module.exportFunction(prefix+"_inverseMod");
859
860    return prefix;
861};