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};