diff --git a/build/lib.cjs/main.js b/build/lib.cjs/main.js
new file mode 100644
index 0000000..9823eb8
--- /dev/null
+++ b/build/lib.cjs/main.js
@@ -0,0 +1,10 @@
+'use strict';
+
+var scalar = require('./src/scalar.js');
+var f1field = require('./src/f1field.js');
+
+const Scalar = scalar;
+
+exports.F1Field = f1field;
+exports.ZqField = f1field;
+exports.Scalar = Scalar;
diff --git a/build/lib.cjs/src/f1field.js b/build/lib.cjs/src/f1field.js
new file mode 100644
index 0000000..4dad3d8
--- /dev/null
+++ b/build/lib.cjs/src/f1field.js
@@ -0,0 +1,367 @@
+'use strict';
+
+var scalar = require('./scalar.js');
+var futils = require('./futils.js');
+var fsqrt = require('./fsqrt.js');
+var random = require('./random.js');
+var fft = require('./fft.js');
+
+/* global BigInt */
+
+class ZqField {
+ constructor(p) {
+ this.type = "F1";
+ this.one = BigInt(1);
+ this.zero = BigInt(0);
+ this.p = BigInt(p);
+ this.m = 1;
+ this.negone = this.p - this.one;
+ this.two = BigInt(2);
+ this.half = this.p >> this.one;
+ this.bitLength = scalar.bitLength(this.p);
+ this.mask = (this.one << BigInt(this.bitLength)) - this.one;
+
+ this.n64 = Math.floor((this.bitLength - 1) / 64) + 1;
+ this.n32 = this.n64 * 2;
+ this.n8 = this.n64 * 8;
+ this.R = this.e(this.one << BigInt(this.n64 * 64));
+ this.Ri = this.inv(this.R);
+
+ const e = this.negone >> this.one;
+ this.nqr = this.two;
+ let r = this.pow(this.nqr, e);
+ while (!this.eq(r, this.negone)) {
+ this.nqr = this.nqr + this.one;
+ r = this.pow(this.nqr, e);
+ }
+
+ this.s = 0;
+ this.t = this.negone;
+
+ while ((this.t & this.one) == this.zero) {
+ this.s = this.s + 1;
+ this.t = this.t >> this.one;
+ }
+
+ this.nqr_to_t = this.pow(this.nqr, this.t);
+
+ fsqrt(this);
+
+ this.FFT = new fft(this, this, this.mul.bind(this));
+
+ this.fft = this.FFT.fft.bind(this.FFT);
+ this.ifft = this.FFT.ifft.bind(this.FFT);
+ this.w = this.FFT.w;
+ this.wi = this.FFT.wi;
+
+ this.shift = this.square(this.nqr);
+ this.k = this.exp(this.nqr, 2 ** this.s);
+ }
+
+ e(a, b) {
+ let res;
+ if (!b) {
+ res = BigInt(a);
+ } else if (b == 16) {
+ res = BigInt("0x" + a);
+ }
+ if (res < 0) {
+ let nres = -res;
+ if (nres >= this.p) nres = nres % this.p;
+ return this.p - nres;
+ } else {
+ return res >= this.p ? res % this.p : res;
+ }
+ }
+
+ add(a, b) {
+ const res = a + b;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ sub(a, b) {
+ return a >= b ? a - b : this.p - b + a;
+ }
+
+ neg(a) {
+ return a ? this.p - a : a;
+ }
+
+ mul(a, b) {
+ return (a * b) % this.p;
+ }
+
+ mulScalar(base, s) {
+ return (base * this.e(s)) % this.p;
+ }
+
+ square(a) {
+ return (a * a) % this.p;
+ }
+
+ eq(a, b) {
+ return a == b;
+ }
+
+ neq(a, b) {
+ return a != b;
+ }
+
+ lt(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa < bb;
+ }
+
+ gt(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa > bb;
+ }
+
+ leq(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa <= bb;
+ }
+
+ geq(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa >= bb;
+ }
+
+ div(a, b) {
+ return this.mul(a, this.inv(b));
+ }
+
+ idiv(a, b) {
+ if (!b) throw new Error("Division by zero");
+ return a / b;
+ }
+
+ inv(a) {
+ if (!a) throw new Error("Division by zero");
+
+ let t = this.zero;
+ let r = this.p;
+ let newt = this.one;
+ let newr = a % this.p;
+ while (newr) {
+ let q = r / newr;
+ [t, newt] = [newt, t - q * newt];
+ [r, newr] = [newr, r - q * newr];
+ }
+ if (t < this.zero) t += this.p;
+ return t;
+ }
+
+ mod(a, b) {
+ return a % b;
+ }
+
+ pow(b, e) {
+ return futils.exp(this, b, e);
+ }
+
+ exp(b, e) {
+ return futils.exp(this, b, e);
+ }
+
+ band(a, b) {
+ const res = a & b & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bor(a, b) {
+ const res = (a | b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bxor(a, b) {
+ const res = (a ^ b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bnot(a) {
+ const res = a ^ this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ shl(a, b) {
+ if (Number(b) < this.bitLength) {
+ const res = (a << b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ return a >> nb;
+ } else {
+ return this.zero;
+ }
+ }
+ }
+
+ shr(a, b) {
+ if (Number(b) < this.bitLength) {
+ return a >> b;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ const res = (a << nb) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ land(a, b) {
+ return a && b ? this.one : this.zero;
+ }
+
+ lor(a, b) {
+ return a || b ? this.one : this.zero;
+ }
+
+ lnot(a) {
+ return a ? this.zero : this.one;
+ }
+
+ sqrt_old(n) {
+ if (n == this.zero) return this.zero;
+
+ // Test that have solution
+ const res = this.pow(n, this.negone >> this.one);
+ if (res != this.one) return null;
+
+ let m = this.s;
+ let c = this.nqr_to_t;
+ let t = this.pow(n, this.t);
+ let r = this.pow(n, this.add(this.t, this.one) >> this.one);
+
+ while (t != this.one) {
+ let sq = this.square(t);
+ let i = 1;
+ while (sq != this.one) {
+ i++;
+ sq = this.square(sq);
+ }
+
+ // b = c ^ m-i-1
+ let b = c;
+ for (let j = 0; j < m - i - 1; j++) b = this.square(b);
+
+ m = i;
+ c = this.square(b);
+ t = this.mul(t, c);
+ r = this.mul(r, b);
+ }
+
+ if (r > this.p >> this.one) {
+ r = this.neg(r);
+ }
+
+ return r;
+ }
+
+ normalize(a, b) {
+ a = BigInt(a, b);
+ if (a < 0) {
+ let na = -a;
+ if (na >= this.p) na = na % this.p;
+ return this.p - na;
+ } else {
+ return a >= this.p ? a % this.p : a;
+ }
+ }
+
+ random() {
+ const nBytes = (this.bitLength * 2) / 8;
+ let res = this.zero;
+ for (let i = 0; i < nBytes; i++) {
+ res = (res << BigInt(8)) + BigInt(random.getRandomBytes(1)[0]);
+ }
+ return res % this.p;
+ }
+
+ toString(a, base) {
+ base = base || 10;
+ let vs;
+ if (a > this.half && base == 10) {
+ const v = this.p - a;
+ vs = "-" + v.toString(base);
+ } else {
+ vs = a.toString(base);
+ }
+ return vs;
+ }
+
+ isZero(a) {
+ return a == this.zero;
+ }
+
+ fromRng(rng) {
+ let v;
+ do {
+ v = this.zero;
+ for (let i = 0; i < this.n64; i++) {
+ v += rng.nextU64() << BigInt(64 * i);
+ }
+ v &= this.mask;
+ } while (v >= this.p);
+ v = (v * this.Ri) % this.p; // Convert from montgomery
+ return v;
+ }
+
+ fft(a) {
+ return this.FFT.fft(a);
+ }
+
+ ifft(a) {
+ return this.FFT.ifft(a);
+ }
+
+ // Returns a buffer with Little Endian Representation
+ toRprLE(buff, o, e) {
+ scalar.toRprLE(buff, o, e, this.n64 * 8);
+ }
+
+ // Returns a buffer with Big Endian Representation
+ toRprBE(buff, o, e) {
+ scalar.toRprBE(buff, o, e, this.n64 * 8);
+ }
+
+ // Returns a buffer with Big Endian Montgomery Representation
+ toRprBEM(buff, o, e) {
+ return this.toRprBE(buff, o, this.mul(this.R, e));
+ }
+
+ toRprLEM(buff, o, e) {
+ return this.toRprLE(buff, o, this.mul(this.R, e));
+ }
+
+ // Pases a buffer with Little Endian Representation
+ fromRprLE(buff, o) {
+ return scalar.fromRprLE(buff, o, this.n8);
+ }
+
+ // Pases a buffer with Big Endian Representation
+ fromRprBE(buff, o) {
+ return scalar.fromRprBE(buff, o, this.n8);
+ }
+
+ fromRprLEM(buff, o) {
+ return this.mul(this.fromRprLE(buff, o), this.Ri);
+ }
+
+ fromRprBEM(buff, o) {
+ return this.mul(this.fromRprBE(buff, o), this.Ri);
+ }
+
+ toObject(a) {
+ return a;
+ }
+}
+
+module.exports = ZqField;
diff --git a/build/lib.cjs/src/fft.js b/build/lib.cjs/src/fft.js
new file mode 100644
index 0000000..5256ff1
--- /dev/null
+++ b/build/lib.cjs/src/fft.js
@@ -0,0 +1,148 @@
+'use strict';
+
+/*
+ Copyright 2018 0kims association.
+
+ This file is part of snarkjs.
+
+ snarkjs is a free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ snarkjs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ snarkjs. If not, see .
+*/
+
+/*
+ This library does operations on polynomials with coefficients in a field F.
+
+ A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
+ by the array [ p0, p1, p2, ... , pn ].
+ */
+
+class FFT {
+ constructor(G, F, opMulGF) {
+ this.F = F;
+ this.G = G;
+ this.opMulGF = opMulGF;
+
+ let rem = F.sqrt_t || F.t;
+ let s = F.sqrt_s || F.s;
+
+ let nqr = F.one;
+ while (F.eq(F.pow(nqr, F.half), F.one)) nqr = F.add(nqr, F.one);
+
+ this.w = new Array(s + 1);
+ this.wi = new Array(s + 1);
+ this.w[s] = this.F.pow(nqr, rem);
+ this.wi[s] = this.F.inv(this.w[s]);
+
+ let n = s - 1;
+ while (n >= 0) {
+ this.w[n] = this.F.square(this.w[n + 1]);
+ this.wi[n] = this.F.square(this.wi[n + 1]);
+ n--;
+ }
+
+ this.roots = [];
+ /*
+ for (let i=0; i<16; i++) {
+ let r = this.F.one;
+ n = 1 << i;
+ const rootsi = new Array(n);
+ for (let j=0; j= 0 && !this.roots[i]; i--) {
+ let r = this.F.one;
+ const nroots = 1 << i;
+ const rootsi = new Array(nroots);
+ for (let j = 0; j < nroots; j++) {
+ rootsi[j] = r;
+ r = this.F.mul(r, this.w[i]);
+ }
+
+ this.roots[i] = rootsi;
+ }
+ }
+
+ fft(p) {
+ if (p.length <= 1) return p;
+ const bits = log2(p.length - 1) + 1;
+ this._setRoots(bits);
+
+ const m = 1 << bits;
+ if (p.length != m) {
+ throw new Error("Size must be multiple of 2");
+ }
+ const res = __fft(this, p, bits, 0, 1);
+ return res;
+ }
+
+ ifft(p) {
+ if (p.length <= 1) return p;
+ const bits = log2(p.length - 1) + 1;
+ this._setRoots(bits);
+ const m = 1 << bits;
+ if (p.length != m) {
+ throw new Error("Size must be multiple of 2");
+ }
+ const res = __fft(this, p, bits, 0, 1);
+ const twoinvm = this.F.inv(this.F.mulScalar(this.F.one, m));
+ const resn = new Array(m);
+ for (let i = 0; i < m; i++) {
+ resn[i] = this.opMulGF(res[(m - i) % m], twoinvm);
+ }
+
+ return resn;
+ }
+}
+
+function log2(V) {
+ return (
+ ((V & 0xffff0000) !== 0 ? ((V &= 0xffff0000), 16) : 0) |
+ ((V & 0xff00ff00) !== 0 ? ((V &= 0xff00ff00), 8) : 0) |
+ ((V & 0xf0f0f0f0) !== 0 ? ((V &= 0xf0f0f0f0), 4) : 0) |
+ ((V & 0xcccccccc) !== 0 ? ((V &= 0xcccccccc), 2) : 0) |
+ ((V & 0xaaaaaaaa) !== 0)
+ );
+}
+
+function __fft(PF, pall, bits, offset, step) {
+ const n = 1 << bits;
+ if (n == 1) {
+ return [pall[offset]];
+ } else if (n == 2) {
+ return [PF.G.add(pall[offset], pall[offset + step]), PF.G.sub(pall[offset], pall[offset + step])];
+ }
+
+ const ndiv2 = n >> 1;
+ const p1 = __fft(PF, pall, bits - 1, offset, step * 2);
+ const p2 = __fft(PF, pall, bits - 1, offset + step, step * 2);
+
+ const out = new Array(n);
+
+ for (let i = 0; i < ndiv2; i++) {
+ out[i] = PF.G.add(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i]));
+ out[i + ndiv2] = PF.G.sub(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i]));
+ }
+
+ return out;
+}
+
+module.exports = FFT;
diff --git a/build/lib.cjs/src/fsqrt.js b/build/lib.cjs/src/fsqrt.js
new file mode 100644
index 0000000..2468612
--- /dev/null
+++ b/build/lib.cjs/src/fsqrt.js
@@ -0,0 +1,167 @@
+'use strict';
+
+var scalar = require('./scalar.js');
+
+// Check here: https://eprint.iacr.org/2012/685.pdf
+
+function buildSqrt(F) {
+ if (F.m % 2 == 1) {
+ if (scalar.eq(scalar.mod(F.p, 4), 1)) {
+ if (scalar.eq(scalar.mod(F.p, 8), 1)) {
+ if (scalar.eq(scalar.mod(F.p, 16), 1)) {
+ // alg7_muller(F);
+ alg5_tonelliShanks(F);
+ } else if (scalar.eq(scalar.mod(F.p, 16), 9)) {
+ alg4_kong(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (scalar.eq(scalar.mod(F.p, 8), 5)) {
+ alg3_atkin(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (scalar.eq(scalar.mod(F.p, 4), 3)) {
+ alg2_shanks(F);
+ }
+ } else {
+ const pm2mod4 = scalar.mod(scalar.pow(F.p, F.m / 2), 4);
+ if (pm2mod4 == 1) {
+ alg10_adj(F);
+ } else if (pm2mod4 == 3) {
+ alg9_adj(F);
+ } else {
+ alg8_complex(F);
+ }
+ }
+}
+
+function alg5_tonelliShanks(F) {
+ F.sqrt_q = scalar.pow(F.p, F.m);
+
+ F.sqrt_s = 0;
+ F.sqrt_t = scalar.sub(F.sqrt_q, 1);
+
+ while (!scalar.isOdd(F.sqrt_t)) {
+ F.sqrt_s = F.sqrt_s + 1;
+ F.sqrt_t = scalar.div(F.sqrt_t, 2);
+ }
+
+ let c0 = F.one;
+
+ while (F.eq(c0, F.one)) {
+ const c = F.random();
+ F.sqrt_z = F.pow(c, F.sqrt_t);
+ c0 = F.pow(F.sqrt_z, 2 ** (F.sqrt_s - 1));
+ }
+
+ F.sqrt_tm1d2 = scalar.div(scalar.sub(F.sqrt_t, 1), 2);
+
+ F.sqrt = function (a) {
+ const F = this;
+ if (F.isZero(a)) return F.zero;
+ let w = F.pow(a, F.sqrt_tm1d2);
+ const a0 = F.pow(F.mul(F.square(w), a), 2 ** (F.sqrt_s - 1));
+ if (F.eq(a0, F.negone)) return null;
+
+ let v = F.sqrt_s;
+ let x = F.mul(a, w);
+ let b = F.mul(x, w);
+ let z = F.sqrt_z;
+ while (!F.eq(b, F.one)) {
+ let b2k = F.square(b);
+ let k = 1;
+ while (!F.eq(b2k, F.one)) {
+ b2k = F.square(b2k);
+ k++;
+ }
+
+ w = z;
+ for (let i = 0; i < v - k - 1; i++) {
+ w = F.square(w);
+ }
+ z = F.square(w);
+ b = F.mul(b, z);
+ x = F.mul(x, w);
+ v = k;
+ }
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg4_kong(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 4 not implemented");
+ };
+}
+
+function alg3_atkin(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 3 not implemented");
+ };
+}
+
+function alg2_shanks(F) {
+ F.sqrt_q = scalar.pow(F.p, F.m);
+ F.sqrt_e1 = scalar.div(scalar.sub(F.sqrt_q, 3), 4);
+
+ F.sqrt = function (a) {
+ if (this.isZero(a)) return this.zero;
+
+ // Test that have solution
+ const a1 = this.pow(a, this.sqrt_e1);
+
+ const a0 = this.mul(this.square(a1), a);
+
+ if (this.eq(a0, this.negone)) return null;
+
+ const x = this.mul(a1, a);
+
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg10_adj(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 10 not implemented");
+ };
+}
+
+function alg9_adj(F) {
+ F.sqrt_q = scalar.pow(F.p, F.m / 2);
+ F.sqrt_e34 = scalar.div(scalar.sub(F.sqrt_q, 3), 4);
+ F.sqrt_e12 = scalar.div(scalar.sub(F.sqrt_q, 1), 2);
+
+ F.frobenius = function (n, x) {
+ if (n % 2 == 1) {
+ return F.conjugate(x);
+ } else {
+ return x;
+ }
+ };
+
+ F.sqrt = function (a) {
+ const F = this;
+ const a1 = F.pow(a, F.sqrt_e34);
+ const alfa = F.mul(F.square(a1), a);
+ const a0 = F.mul(F.frobenius(1, alfa), alfa);
+ if (F.eq(a0, F.negone)) return null;
+ const x0 = F.mul(a1, a);
+ let x;
+ if (F.eq(alfa, F.negone)) {
+ x = F.mul(x0, [F.F.zero, F.F.one]);
+ } else {
+ const b = F.pow(F.add(F.one, alfa), F.sqrt_e12);
+ x = F.mul(b, x0);
+ }
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg8_complex(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 8 not implemented");
+ };
+}
+
+module.exports = buildSqrt;
diff --git a/build/lib.cjs/src/futils.js b/build/lib.cjs/src/futils.js
new file mode 100644
index 0000000..c9b9402
--- /dev/null
+++ b/build/lib.cjs/src/futils.js
@@ -0,0 +1,63 @@
+'use strict';
+
+var scalar = require('./scalar.js');
+
+/*
+ Copyright 2018 0kims association.
+
+ This file is part of snarkjs.
+
+ snarkjs is a free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ snarkjs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ snarkjs. If not, see .
+*/
+
+
+/*
+exports.mulScalar = (F, base, e) =>{
+ let res = F.zero;
+ let rem = bigInt(e);
+ let exp = base;
+
+ while (! rem.eq(bigInt.zero)) {
+ if (rem.and(bigInt.one).eq(bigInt.one)) {
+ res = F.add(res, exp);
+ }
+ exp = F.double(exp);
+ rem = rem.shiftRight(1);
+ }
+
+ return res;
+};
+*/
+
+function exp(F, base, e) {
+ if (scalar.isZero(e)) return F.one;
+
+ const n = scalar.bits(e);
+
+ if (n.length == 0) return F.one;
+
+ let res = base;
+
+ for (let i = n.length - 2; i >= 0; i--) {
+ res = F.square(res);
+
+ if (n[i]) {
+ res = F.mul(res, base);
+ }
+ }
+
+ return res;
+}
+
+exports.exp = exp;
diff --git a/build/lib.cjs/src/random.js b/build/lib.cjs/src/random.js
new file mode 100644
index 0000000..a14767b
--- /dev/null
+++ b/build/lib.cjs/src/random.js
@@ -0,0 +1,18 @@
+'use strict';
+
+function getRandomBytes(n) {
+ let array = new Uint8Array(n);
+ // Browser & Node
+ if (typeof globalThis.crypto !== "undefined") {
+ // Supported
+ globalThis.crypto.getRandomValues(array);
+ } else {
+ // fallback
+ for (let i = 0; i < n; i++) {
+ array[i] = (Math.random() * 4294967296) >>> 0;
+ }
+ }
+ return array;
+}
+
+exports.getRandomBytes = getRandomBytes;
diff --git a/build/lib.cjs/src/scalar.js b/build/lib.cjs/src/scalar.js
new file mode 100644
index 0000000..0f7479d
--- /dev/null
+++ b/build/lib.cjs/src/scalar.js
@@ -0,0 +1,294 @@
+'use strict';
+
+/* global BigInt */
+const hexLen = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4];
+
+function fromString(s, radix) {
+ if (!radix || radix == 10) {
+ return BigInt(s);
+ } else if (radix == 16) {
+ if (s.slice(0, 2) == "0x") {
+ return BigInt(s);
+ } else {
+ return BigInt("0x" + s);
+ }
+ }
+}
+
+const e = fromString;
+
+function fromArray(a, radix) {
+ let acc = BigInt(0);
+ radix = BigInt(radix);
+ for (let i = 0; i < a.length; i++) {
+ acc = acc * radix + BigInt(a[i]);
+ }
+ return acc;
+}
+
+function bitLength(a) {
+ const aS = a.toString(16);
+ return (aS.length - 1) * 4 + hexLen[parseInt(aS[0], 16)];
+}
+
+function isNegative(a) {
+ return BigInt(a) < BigInt(0);
+}
+
+function isZero(a) {
+ return !a;
+}
+
+function shiftLeft(a, n) {
+ return BigInt(a) << BigInt(n);
+}
+
+function shiftRight(a, n) {
+ return BigInt(a) >> BigInt(n);
+}
+
+const shl = shiftLeft;
+const shr = shiftRight;
+
+function isOdd(a) {
+ return (BigInt(a) & BigInt(1)) == BigInt(1);
+}
+
+function naf(n) {
+ let E = BigInt(n);
+ const res = [];
+ while (E) {
+ if (E & BigInt(1)) {
+ const z = 2 - Number(E % BigInt(4));
+ res.push(z);
+ E = E - BigInt(z);
+ } else {
+ res.push(0);
+ }
+ E = E >> BigInt(1);
+ }
+ return res;
+}
+
+function bits(n) {
+ let E = BigInt(n);
+ const res = [];
+ while (E) {
+ if (E & BigInt(1)) {
+ res.push(1);
+ } else {
+ res.push(0);
+ }
+ E = E >> BigInt(1);
+ }
+ return res;
+}
+
+function toNumber(s) {
+ if (s > BigInt(Number.MAX_SAFE_INTEGER)) {
+ throw new Error("Number too big");
+ }
+ return Number(s);
+}
+
+function toArray(s, radix) {
+ const res = [];
+ let rem = BigInt(s);
+ radix = BigInt(radix);
+ while (rem) {
+ res.unshift(Number(rem % radix));
+ rem = rem / radix;
+ }
+ return res;
+}
+
+function add(a, b) {
+ return BigInt(a) + BigInt(b);
+}
+
+function sub(a, b) {
+ return BigInt(a) - BigInt(b);
+}
+
+function neg(a) {
+ return -BigInt(a);
+}
+
+function mul(a, b) {
+ return BigInt(a) * BigInt(b);
+}
+
+function square(a) {
+ return BigInt(a) * BigInt(a);
+}
+
+function pow(a, b) {
+ return BigInt(a) ** BigInt(b);
+}
+
+function exp(a, b) {
+ return BigInt(a) ** BigInt(b);
+}
+
+function abs(a) {
+ return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a);
+}
+
+function div(a, b) {
+ return BigInt(a) / BigInt(b);
+}
+
+function mod(a, b) {
+ return BigInt(a) % BigInt(b);
+}
+
+function eq(a, b) {
+ return BigInt(a) == BigInt(b);
+}
+
+function neq(a, b) {
+ return BigInt(a) != BigInt(b);
+}
+
+function lt(a, b) {
+ return BigInt(a) < BigInt(b);
+}
+
+function gt(a, b) {
+ return BigInt(a) > BigInt(b);
+}
+
+function leq(a, b) {
+ return BigInt(a) <= BigInt(b);
+}
+
+function geq(a, b) {
+ return BigInt(a) >= BigInt(b);
+}
+
+function band(a, b) {
+ return BigInt(a) & BigInt(b);
+}
+
+function bor(a, b) {
+ return BigInt(a) | BigInt(b);
+}
+
+function bxor(a, b) {
+ return BigInt(a) ^ BigInt(b);
+}
+
+function land(a, b) {
+ return BigInt(a) && BigInt(b);
+}
+
+function lor(a, b) {
+ return BigInt(a) || BigInt(b);
+}
+
+function lnot(a) {
+ return !BigInt(a);
+}
+
+// Returns a buffer with Little Endian Representation
+function toRprLE(buff, o, e, n8) {
+ const s = "0000000" + e.toString(16);
+ const v = new Uint32Array(buff.buffer, o, n8 / 4);
+ const l = (((s.length - 7) * 4 - 1) >> 5) + 1; // Number of 32bit words;
+ for (let i = 0; i < l; i++) v[i] = parseInt(s.substring(s.length - 8 * i - 8, s.length - 8 * i), 16);
+ for (let i = l; i < v.length; i++) v[i] = 0;
+ for (let i = v.length * 4; i < n8; i++) buff[i] = toNumber(band(shiftRight(e, i * 8), 0xff));
+}
+
+// Returns a buffer with Big Endian Representation
+function toRprBE(buff, o, e, n8) {
+ const s = "0000000" + e.toString(16);
+ const v = new DataView(buff.buffer, buff.byteOffset + o, n8);
+ const l = (((s.length - 7) * 4 - 1) >> 5) + 1; // Number of 32bit words;
+ for (let i = 0; i < l; i++) v.setUint32(n8 - i * 4 - 4, parseInt(s.substring(s.length - 8 * i - 8, s.length - 8 * i), 16), false);
+ for (let i = 0; i < n8 / 4 - l; i++) v[i] = 0;
+}
+
+// Pases a buffer with Little Endian Representation
+function fromRprLE(buff, o, n8) {
+ n8 = n8 || buff.byteLength;
+ o = o || 0;
+ const v = new Uint32Array(buff.buffer, o, n8 / 4);
+ const a = new Array(n8 / 4);
+ v.forEach((ch, i) => (a[a.length - i - 1] = ch.toString(16).padStart(8, "0")));
+ return fromString(a.join(""), 16);
+}
+
+// Pases a buffer with Big Endian Representation
+function fromRprBE(buff, o, n8) {
+ n8 = n8 || buff.byteLength;
+ o = o || 0;
+ const v = new DataView(buff.buffer, buff.byteOffset + o, n8);
+ const a = new Array(n8 / 4);
+ for (let i = 0; i < n8 / 4; i++) {
+ a[i] = v
+ .getUint32(i * 4, false)
+ .toString(16)
+ .padStart(8, "0");
+ }
+ return fromString(a.join(""), 16);
+}
+
+function toString(a, radix) {
+ return a.toString(radix);
+}
+
+function toLEBuff(a) {
+ const buff = new Uint8Array(Math.floor((bitLength(a) - 1) / 8) + 1);
+ toRprLE(buff, 0, a, buff.byteLength);
+ return buff;
+}
+
+const zero = e(0);
+const one = e(1);
+
+exports.abs = abs;
+exports.add = add;
+exports.band = band;
+exports.bitLength = bitLength;
+exports.bits = bits;
+exports.bor = bor;
+exports.bxor = bxor;
+exports.div = div;
+exports.e = e;
+exports.eq = eq;
+exports.exp = exp;
+exports.fromArray = fromArray;
+exports.fromRprBE = fromRprBE;
+exports.fromRprLE = fromRprLE;
+exports.fromString = fromString;
+exports.geq = geq;
+exports.gt = gt;
+exports.isNegative = isNegative;
+exports.isOdd = isOdd;
+exports.isZero = isZero;
+exports.land = land;
+exports.leq = leq;
+exports.lnot = lnot;
+exports.lor = lor;
+exports.lt = lt;
+exports.mod = mod;
+exports.mul = mul;
+exports.naf = naf;
+exports.neg = neg;
+exports.neq = neq;
+exports.one = one;
+exports.pow = pow;
+exports.shiftLeft = shiftLeft;
+exports.shiftRight = shiftRight;
+exports.shl = shl;
+exports.shr = shr;
+exports.square = square;
+exports.sub = sub;
+exports.toArray = toArray;
+exports.toLEBuff = toLEBuff;
+exports.toNumber = toNumber;
+exports.toRprBE = toRprBE;
+exports.toRprLE = toRprLE;
+exports.toString = toString;
+exports.zero = zero;
diff --git a/build/lib.esm/main.js b/build/lib.esm/main.js
new file mode 100644
index 0000000..5c2792a
--- /dev/null
+++ b/build/lib.esm/main.js
@@ -0,0 +1,6 @@
+import * as scalar from './src/scalar.js';
+export { default as F1Field, default as ZqField } from './src/f1field.js';
+
+const Scalar = scalar;
+
+export { Scalar };
diff --git a/build/lib.esm/src/f1field.js b/build/lib.esm/src/f1field.js
new file mode 100644
index 0000000..7aa0f3e
--- /dev/null
+++ b/build/lib.esm/src/f1field.js
@@ -0,0 +1,365 @@
+import { bitLength, toRprLE, toRprBE, fromRprLE, fromRprBE } from './scalar.js';
+import { exp } from './futils.js';
+import buildSqrt from './fsqrt.js';
+import { getRandomBytes } from './random.js';
+import FFT from './fft.js';
+
+/* global BigInt */
+
+class ZqField {
+ constructor(p) {
+ this.type = "F1";
+ this.one = BigInt(1);
+ this.zero = BigInt(0);
+ this.p = BigInt(p);
+ this.m = 1;
+ this.negone = this.p - this.one;
+ this.two = BigInt(2);
+ this.half = this.p >> this.one;
+ this.bitLength = bitLength(this.p);
+ this.mask = (this.one << BigInt(this.bitLength)) - this.one;
+
+ this.n64 = Math.floor((this.bitLength - 1) / 64) + 1;
+ this.n32 = this.n64 * 2;
+ this.n8 = this.n64 * 8;
+ this.R = this.e(this.one << BigInt(this.n64 * 64));
+ this.Ri = this.inv(this.R);
+
+ const e = this.negone >> this.one;
+ this.nqr = this.two;
+ let r = this.pow(this.nqr, e);
+ while (!this.eq(r, this.negone)) {
+ this.nqr = this.nqr + this.one;
+ r = this.pow(this.nqr, e);
+ }
+
+ this.s = 0;
+ this.t = this.negone;
+
+ while ((this.t & this.one) == this.zero) {
+ this.s = this.s + 1;
+ this.t = this.t >> this.one;
+ }
+
+ this.nqr_to_t = this.pow(this.nqr, this.t);
+
+ buildSqrt(this);
+
+ this.FFT = new FFT(this, this, this.mul.bind(this));
+
+ this.fft = this.FFT.fft.bind(this.FFT);
+ this.ifft = this.FFT.ifft.bind(this.FFT);
+ this.w = this.FFT.w;
+ this.wi = this.FFT.wi;
+
+ this.shift = this.square(this.nqr);
+ this.k = this.exp(this.nqr, 2 ** this.s);
+ }
+
+ e(a, b) {
+ let res;
+ if (!b) {
+ res = BigInt(a);
+ } else if (b == 16) {
+ res = BigInt("0x" + a);
+ }
+ if (res < 0) {
+ let nres = -res;
+ if (nres >= this.p) nres = nres % this.p;
+ return this.p - nres;
+ } else {
+ return res >= this.p ? res % this.p : res;
+ }
+ }
+
+ add(a, b) {
+ const res = a + b;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ sub(a, b) {
+ return a >= b ? a - b : this.p - b + a;
+ }
+
+ neg(a) {
+ return a ? this.p - a : a;
+ }
+
+ mul(a, b) {
+ return (a * b) % this.p;
+ }
+
+ mulScalar(base, s) {
+ return (base * this.e(s)) % this.p;
+ }
+
+ square(a) {
+ return (a * a) % this.p;
+ }
+
+ eq(a, b) {
+ return a == b;
+ }
+
+ neq(a, b) {
+ return a != b;
+ }
+
+ lt(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa < bb;
+ }
+
+ gt(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa > bb;
+ }
+
+ leq(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa <= bb;
+ }
+
+ geq(a, b) {
+ const aa = a > this.half ? a - this.p : a;
+ const bb = b > this.half ? b - this.p : b;
+ return aa >= bb;
+ }
+
+ div(a, b) {
+ return this.mul(a, this.inv(b));
+ }
+
+ idiv(a, b) {
+ if (!b) throw new Error("Division by zero");
+ return a / b;
+ }
+
+ inv(a) {
+ if (!a) throw new Error("Division by zero");
+
+ let t = this.zero;
+ let r = this.p;
+ let newt = this.one;
+ let newr = a % this.p;
+ while (newr) {
+ let q = r / newr;
+ [t, newt] = [newt, t - q * newt];
+ [r, newr] = [newr, r - q * newr];
+ }
+ if (t < this.zero) t += this.p;
+ return t;
+ }
+
+ mod(a, b) {
+ return a % b;
+ }
+
+ pow(b, e) {
+ return exp(this, b, e);
+ }
+
+ exp(b, e) {
+ return exp(this, b, e);
+ }
+
+ band(a, b) {
+ const res = a & b & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bor(a, b) {
+ const res = (a | b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bxor(a, b) {
+ const res = (a ^ b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ bnot(a) {
+ const res = a ^ this.mask;
+ return res >= this.p ? res - this.p : res;
+ }
+
+ shl(a, b) {
+ if (Number(b) < this.bitLength) {
+ const res = (a << b) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ return a >> nb;
+ } else {
+ return this.zero;
+ }
+ }
+ }
+
+ shr(a, b) {
+ if (Number(b) < this.bitLength) {
+ return a >> b;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ const res = (a << nb) & this.mask;
+ return res >= this.p ? res - this.p : res;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ land(a, b) {
+ return a && b ? this.one : this.zero;
+ }
+
+ lor(a, b) {
+ return a || b ? this.one : this.zero;
+ }
+
+ lnot(a) {
+ return a ? this.zero : this.one;
+ }
+
+ sqrt_old(n) {
+ if (n == this.zero) return this.zero;
+
+ // Test that have solution
+ const res = this.pow(n, this.negone >> this.one);
+ if (res != this.one) return null;
+
+ let m = this.s;
+ let c = this.nqr_to_t;
+ let t = this.pow(n, this.t);
+ let r = this.pow(n, this.add(this.t, this.one) >> this.one);
+
+ while (t != this.one) {
+ let sq = this.square(t);
+ let i = 1;
+ while (sq != this.one) {
+ i++;
+ sq = this.square(sq);
+ }
+
+ // b = c ^ m-i-1
+ let b = c;
+ for (let j = 0; j < m - i - 1; j++) b = this.square(b);
+
+ m = i;
+ c = this.square(b);
+ t = this.mul(t, c);
+ r = this.mul(r, b);
+ }
+
+ if (r > this.p >> this.one) {
+ r = this.neg(r);
+ }
+
+ return r;
+ }
+
+ normalize(a, b) {
+ a = BigInt(a, b);
+ if (a < 0) {
+ let na = -a;
+ if (na >= this.p) na = na % this.p;
+ return this.p - na;
+ } else {
+ return a >= this.p ? a % this.p : a;
+ }
+ }
+
+ random() {
+ const nBytes = (this.bitLength * 2) / 8;
+ let res = this.zero;
+ for (let i = 0; i < nBytes; i++) {
+ res = (res << BigInt(8)) + BigInt(getRandomBytes(1)[0]);
+ }
+ return res % this.p;
+ }
+
+ toString(a, base) {
+ base = base || 10;
+ let vs;
+ if (a > this.half && base == 10) {
+ const v = this.p - a;
+ vs = "-" + v.toString(base);
+ } else {
+ vs = a.toString(base);
+ }
+ return vs;
+ }
+
+ isZero(a) {
+ return a == this.zero;
+ }
+
+ fromRng(rng) {
+ let v;
+ do {
+ v = this.zero;
+ for (let i = 0; i < this.n64; i++) {
+ v += rng.nextU64() << BigInt(64 * i);
+ }
+ v &= this.mask;
+ } while (v >= this.p);
+ v = (v * this.Ri) % this.p; // Convert from montgomery
+ return v;
+ }
+
+ fft(a) {
+ return this.FFT.fft(a);
+ }
+
+ ifft(a) {
+ return this.FFT.ifft(a);
+ }
+
+ // Returns a buffer with Little Endian Representation
+ toRprLE(buff, o, e) {
+ toRprLE(buff, o, e, this.n64 * 8);
+ }
+
+ // Returns a buffer with Big Endian Representation
+ toRprBE(buff, o, e) {
+ toRprBE(buff, o, e, this.n64 * 8);
+ }
+
+ // Returns a buffer with Big Endian Montgomery Representation
+ toRprBEM(buff, o, e) {
+ return this.toRprBE(buff, o, this.mul(this.R, e));
+ }
+
+ toRprLEM(buff, o, e) {
+ return this.toRprLE(buff, o, this.mul(this.R, e));
+ }
+
+ // Pases a buffer with Little Endian Representation
+ fromRprLE(buff, o) {
+ return fromRprLE(buff, o, this.n8);
+ }
+
+ // Pases a buffer with Big Endian Representation
+ fromRprBE(buff, o) {
+ return fromRprBE(buff, o, this.n8);
+ }
+
+ fromRprLEM(buff, o) {
+ return this.mul(this.fromRprLE(buff, o), this.Ri);
+ }
+
+ fromRprBEM(buff, o) {
+ return this.mul(this.fromRprBE(buff, o), this.Ri);
+ }
+
+ toObject(a) {
+ return a;
+ }
+}
+
+export { ZqField as default };
diff --git a/build/lib.esm/src/fft.js b/build/lib.esm/src/fft.js
new file mode 100644
index 0000000..c1db886
--- /dev/null
+++ b/build/lib.esm/src/fft.js
@@ -0,0 +1,146 @@
+/*
+ Copyright 2018 0kims association.
+
+ This file is part of snarkjs.
+
+ snarkjs is a free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ snarkjs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ snarkjs. If not, see .
+*/
+
+/*
+ This library does operations on polynomials with coefficients in a field F.
+
+ A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
+ by the array [ p0, p1, p2, ... , pn ].
+ */
+
+class FFT {
+ constructor(G, F, opMulGF) {
+ this.F = F;
+ this.G = G;
+ this.opMulGF = opMulGF;
+
+ let rem = F.sqrt_t || F.t;
+ let s = F.sqrt_s || F.s;
+
+ let nqr = F.one;
+ while (F.eq(F.pow(nqr, F.half), F.one)) nqr = F.add(nqr, F.one);
+
+ this.w = new Array(s + 1);
+ this.wi = new Array(s + 1);
+ this.w[s] = this.F.pow(nqr, rem);
+ this.wi[s] = this.F.inv(this.w[s]);
+
+ let n = s - 1;
+ while (n >= 0) {
+ this.w[n] = this.F.square(this.w[n + 1]);
+ this.wi[n] = this.F.square(this.wi[n + 1]);
+ n--;
+ }
+
+ this.roots = [];
+ /*
+ for (let i=0; i<16; i++) {
+ let r = this.F.one;
+ n = 1 << i;
+ const rootsi = new Array(n);
+ for (let j=0; j= 0 && !this.roots[i]; i--) {
+ let r = this.F.one;
+ const nroots = 1 << i;
+ const rootsi = new Array(nroots);
+ for (let j = 0; j < nroots; j++) {
+ rootsi[j] = r;
+ r = this.F.mul(r, this.w[i]);
+ }
+
+ this.roots[i] = rootsi;
+ }
+ }
+
+ fft(p) {
+ if (p.length <= 1) return p;
+ const bits = log2(p.length - 1) + 1;
+ this._setRoots(bits);
+
+ const m = 1 << bits;
+ if (p.length != m) {
+ throw new Error("Size must be multiple of 2");
+ }
+ const res = __fft(this, p, bits, 0, 1);
+ return res;
+ }
+
+ ifft(p) {
+ if (p.length <= 1) return p;
+ const bits = log2(p.length - 1) + 1;
+ this._setRoots(bits);
+ const m = 1 << bits;
+ if (p.length != m) {
+ throw new Error("Size must be multiple of 2");
+ }
+ const res = __fft(this, p, bits, 0, 1);
+ const twoinvm = this.F.inv(this.F.mulScalar(this.F.one, m));
+ const resn = new Array(m);
+ for (let i = 0; i < m; i++) {
+ resn[i] = this.opMulGF(res[(m - i) % m], twoinvm);
+ }
+
+ return resn;
+ }
+}
+
+function log2(V) {
+ return (
+ ((V & 0xffff0000) !== 0 ? ((V &= 0xffff0000), 16) : 0) |
+ ((V & 0xff00ff00) !== 0 ? ((V &= 0xff00ff00), 8) : 0) |
+ ((V & 0xf0f0f0f0) !== 0 ? ((V &= 0xf0f0f0f0), 4) : 0) |
+ ((V & 0xcccccccc) !== 0 ? ((V &= 0xcccccccc), 2) : 0) |
+ ((V & 0xaaaaaaaa) !== 0)
+ );
+}
+
+function __fft(PF, pall, bits, offset, step) {
+ const n = 1 << bits;
+ if (n == 1) {
+ return [pall[offset]];
+ } else if (n == 2) {
+ return [PF.G.add(pall[offset], pall[offset + step]), PF.G.sub(pall[offset], pall[offset + step])];
+ }
+
+ const ndiv2 = n >> 1;
+ const p1 = __fft(PF, pall, bits - 1, offset, step * 2);
+ const p2 = __fft(PF, pall, bits - 1, offset + step, step * 2);
+
+ const out = new Array(n);
+
+ for (let i = 0; i < ndiv2; i++) {
+ out[i] = PF.G.add(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i]));
+ out[i + ndiv2] = PF.G.sub(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i]));
+ }
+
+ return out;
+}
+
+export { FFT as default };
diff --git a/build/lib.esm/src/fsqrt.js b/build/lib.esm/src/fsqrt.js
new file mode 100644
index 0000000..080e94e
--- /dev/null
+++ b/build/lib.esm/src/fsqrt.js
@@ -0,0 +1,165 @@
+import { eq, mod, pow, sub, isOdd, div } from './scalar.js';
+
+// Check here: https://eprint.iacr.org/2012/685.pdf
+
+function buildSqrt(F) {
+ if (F.m % 2 == 1) {
+ if (eq(mod(F.p, 4), 1)) {
+ if (eq(mod(F.p, 8), 1)) {
+ if (eq(mod(F.p, 16), 1)) {
+ // alg7_muller(F);
+ alg5_tonelliShanks(F);
+ } else if (eq(mod(F.p, 16), 9)) {
+ alg4_kong(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (eq(mod(F.p, 8), 5)) {
+ alg3_atkin(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (eq(mod(F.p, 4), 3)) {
+ alg2_shanks(F);
+ }
+ } else {
+ const pm2mod4 = mod(pow(F.p, F.m / 2), 4);
+ if (pm2mod4 == 1) {
+ alg10_adj(F);
+ } else if (pm2mod4 == 3) {
+ alg9_adj(F);
+ } else {
+ alg8_complex(F);
+ }
+ }
+}
+
+function alg5_tonelliShanks(F) {
+ F.sqrt_q = pow(F.p, F.m);
+
+ F.sqrt_s = 0;
+ F.sqrt_t = sub(F.sqrt_q, 1);
+
+ while (!isOdd(F.sqrt_t)) {
+ F.sqrt_s = F.sqrt_s + 1;
+ F.sqrt_t = div(F.sqrt_t, 2);
+ }
+
+ let c0 = F.one;
+
+ while (F.eq(c0, F.one)) {
+ const c = F.random();
+ F.sqrt_z = F.pow(c, F.sqrt_t);
+ c0 = F.pow(F.sqrt_z, 2 ** (F.sqrt_s - 1));
+ }
+
+ F.sqrt_tm1d2 = div(sub(F.sqrt_t, 1), 2);
+
+ F.sqrt = function (a) {
+ const F = this;
+ if (F.isZero(a)) return F.zero;
+ let w = F.pow(a, F.sqrt_tm1d2);
+ const a0 = F.pow(F.mul(F.square(w), a), 2 ** (F.sqrt_s - 1));
+ if (F.eq(a0, F.negone)) return null;
+
+ let v = F.sqrt_s;
+ let x = F.mul(a, w);
+ let b = F.mul(x, w);
+ let z = F.sqrt_z;
+ while (!F.eq(b, F.one)) {
+ let b2k = F.square(b);
+ let k = 1;
+ while (!F.eq(b2k, F.one)) {
+ b2k = F.square(b2k);
+ k++;
+ }
+
+ w = z;
+ for (let i = 0; i < v - k - 1; i++) {
+ w = F.square(w);
+ }
+ z = F.square(w);
+ b = F.mul(b, z);
+ x = F.mul(x, w);
+ v = k;
+ }
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg4_kong(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 4 not implemented");
+ };
+}
+
+function alg3_atkin(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 3 not implemented");
+ };
+}
+
+function alg2_shanks(F) {
+ F.sqrt_q = pow(F.p, F.m);
+ F.sqrt_e1 = div(sub(F.sqrt_q, 3), 4);
+
+ F.sqrt = function (a) {
+ if (this.isZero(a)) return this.zero;
+
+ // Test that have solution
+ const a1 = this.pow(a, this.sqrt_e1);
+
+ const a0 = this.mul(this.square(a1), a);
+
+ if (this.eq(a0, this.negone)) return null;
+
+ const x = this.mul(a1, a);
+
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg10_adj(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 10 not implemented");
+ };
+}
+
+function alg9_adj(F) {
+ F.sqrt_q = pow(F.p, F.m / 2);
+ F.sqrt_e34 = div(sub(F.sqrt_q, 3), 4);
+ F.sqrt_e12 = div(sub(F.sqrt_q, 1), 2);
+
+ F.frobenius = function (n, x) {
+ if (n % 2 == 1) {
+ return F.conjugate(x);
+ } else {
+ return x;
+ }
+ };
+
+ F.sqrt = function (a) {
+ const F = this;
+ const a1 = F.pow(a, F.sqrt_e34);
+ const alfa = F.mul(F.square(a1), a);
+ const a0 = F.mul(F.frobenius(1, alfa), alfa);
+ if (F.eq(a0, F.negone)) return null;
+ const x0 = F.mul(a1, a);
+ let x;
+ if (F.eq(alfa, F.negone)) {
+ x = F.mul(x0, [F.F.zero, F.F.one]);
+ } else {
+ const b = F.pow(F.add(F.one, alfa), F.sqrt_e12);
+ x = F.mul(b, x0);
+ }
+ return F.geq(x, F.zero) ? x : F.neg(x);
+ };
+}
+
+function alg8_complex(F) {
+ F.sqrt = function () {
+ throw new Error("Sqrt alg 8 not implemented");
+ };
+}
+
+export { buildSqrt as default };
diff --git a/build/lib.esm/src/futils.js b/build/lib.esm/src/futils.js
new file mode 100644
index 0000000..7119a60
--- /dev/null
+++ b/build/lib.esm/src/futils.js
@@ -0,0 +1,61 @@
+import { isZero, bits } from './scalar.js';
+
+/*
+ Copyright 2018 0kims association.
+
+ This file is part of snarkjs.
+
+ snarkjs is a free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ snarkjs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ snarkjs. If not, see .
+*/
+
+
+/*
+exports.mulScalar = (F, base, e) =>{
+ let res = F.zero;
+ let rem = bigInt(e);
+ let exp = base;
+
+ while (! rem.eq(bigInt.zero)) {
+ if (rem.and(bigInt.one).eq(bigInt.one)) {
+ res = F.add(res, exp);
+ }
+ exp = F.double(exp);
+ rem = rem.shiftRight(1);
+ }
+
+ return res;
+};
+*/
+
+function exp(F, base, e) {
+ if (isZero(e)) return F.one;
+
+ const n = bits(e);
+
+ if (n.length == 0) return F.one;
+
+ let res = base;
+
+ for (let i = n.length - 2; i >= 0; i--) {
+ res = F.square(res);
+
+ if (n[i]) {
+ res = F.mul(res, base);
+ }
+ }
+
+ return res;
+}
+
+export { exp };
diff --git a/build/lib.esm/src/random.js b/build/lib.esm/src/random.js
new file mode 100644
index 0000000..1215d08
--- /dev/null
+++ b/build/lib.esm/src/random.js
@@ -0,0 +1,16 @@
+function getRandomBytes(n) {
+ let array = new Uint8Array(n);
+ // Browser & Node
+ if (typeof globalThis.crypto !== "undefined") {
+ // Supported
+ globalThis.crypto.getRandomValues(array);
+ } else {
+ // fallback
+ for (let i = 0; i < n; i++) {
+ array[i] = (Math.random() * 4294967296) >>> 0;
+ }
+ }
+ return array;
+}
+
+export { getRandomBytes };
diff --git a/build/lib.esm/src/scalar.js b/build/lib.esm/src/scalar.js
new file mode 100644
index 0000000..81e9b74
--- /dev/null
+++ b/build/lib.esm/src/scalar.js
@@ -0,0 +1,248 @@
+/* global BigInt */
+const hexLen = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4];
+
+function fromString(s, radix) {
+ if (!radix || radix == 10) {
+ return BigInt(s);
+ } else if (radix == 16) {
+ if (s.slice(0, 2) == "0x") {
+ return BigInt(s);
+ } else {
+ return BigInt("0x" + s);
+ }
+ }
+}
+
+const e = fromString;
+
+function fromArray(a, radix) {
+ let acc = BigInt(0);
+ radix = BigInt(radix);
+ for (let i = 0; i < a.length; i++) {
+ acc = acc * radix + BigInt(a[i]);
+ }
+ return acc;
+}
+
+function bitLength(a) {
+ const aS = a.toString(16);
+ return (aS.length - 1) * 4 + hexLen[parseInt(aS[0], 16)];
+}
+
+function isNegative(a) {
+ return BigInt(a) < BigInt(0);
+}
+
+function isZero(a) {
+ return !a;
+}
+
+function shiftLeft(a, n) {
+ return BigInt(a) << BigInt(n);
+}
+
+function shiftRight(a, n) {
+ return BigInt(a) >> BigInt(n);
+}
+
+const shl = shiftLeft;
+const shr = shiftRight;
+
+function isOdd(a) {
+ return (BigInt(a) & BigInt(1)) == BigInt(1);
+}
+
+function naf(n) {
+ let E = BigInt(n);
+ const res = [];
+ while (E) {
+ if (E & BigInt(1)) {
+ const z = 2 - Number(E % BigInt(4));
+ res.push(z);
+ E = E - BigInt(z);
+ } else {
+ res.push(0);
+ }
+ E = E >> BigInt(1);
+ }
+ return res;
+}
+
+function bits(n) {
+ let E = BigInt(n);
+ const res = [];
+ while (E) {
+ if (E & BigInt(1)) {
+ res.push(1);
+ } else {
+ res.push(0);
+ }
+ E = E >> BigInt(1);
+ }
+ return res;
+}
+
+function toNumber(s) {
+ if (s > BigInt(Number.MAX_SAFE_INTEGER)) {
+ throw new Error("Number too big");
+ }
+ return Number(s);
+}
+
+function toArray(s, radix) {
+ const res = [];
+ let rem = BigInt(s);
+ radix = BigInt(radix);
+ while (rem) {
+ res.unshift(Number(rem % radix));
+ rem = rem / radix;
+ }
+ return res;
+}
+
+function add(a, b) {
+ return BigInt(a) + BigInt(b);
+}
+
+function sub(a, b) {
+ return BigInt(a) - BigInt(b);
+}
+
+function neg(a) {
+ return -BigInt(a);
+}
+
+function mul(a, b) {
+ return BigInt(a) * BigInt(b);
+}
+
+function square(a) {
+ return BigInt(a) * BigInt(a);
+}
+
+function pow(a, b) {
+ return BigInt(a) ** BigInt(b);
+}
+
+function exp(a, b) {
+ return BigInt(a) ** BigInt(b);
+}
+
+function abs(a) {
+ return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a);
+}
+
+function div(a, b) {
+ return BigInt(a) / BigInt(b);
+}
+
+function mod(a, b) {
+ return BigInt(a) % BigInt(b);
+}
+
+function eq(a, b) {
+ return BigInt(a) == BigInt(b);
+}
+
+function neq(a, b) {
+ return BigInt(a) != BigInt(b);
+}
+
+function lt(a, b) {
+ return BigInt(a) < BigInt(b);
+}
+
+function gt(a, b) {
+ return BigInt(a) > BigInt(b);
+}
+
+function leq(a, b) {
+ return BigInt(a) <= BigInt(b);
+}
+
+function geq(a, b) {
+ return BigInt(a) >= BigInt(b);
+}
+
+function band(a, b) {
+ return BigInt(a) & BigInt(b);
+}
+
+function bor(a, b) {
+ return BigInt(a) | BigInt(b);
+}
+
+function bxor(a, b) {
+ return BigInt(a) ^ BigInt(b);
+}
+
+function land(a, b) {
+ return BigInt(a) && BigInt(b);
+}
+
+function lor(a, b) {
+ return BigInt(a) || BigInt(b);
+}
+
+function lnot(a) {
+ return !BigInt(a);
+}
+
+// Returns a buffer with Little Endian Representation
+function toRprLE(buff, o, e, n8) {
+ const s = "0000000" + e.toString(16);
+ const v = new Uint32Array(buff.buffer, o, n8 / 4);
+ const l = (((s.length - 7) * 4 - 1) >> 5) + 1; // Number of 32bit words;
+ for (let i = 0; i < l; i++) v[i] = parseInt(s.substring(s.length - 8 * i - 8, s.length - 8 * i), 16);
+ for (let i = l; i < v.length; i++) v[i] = 0;
+ for (let i = v.length * 4; i < n8; i++) buff[i] = toNumber(band(shiftRight(e, i * 8), 0xff));
+}
+
+// Returns a buffer with Big Endian Representation
+function toRprBE(buff, o, e, n8) {
+ const s = "0000000" + e.toString(16);
+ const v = new DataView(buff.buffer, buff.byteOffset + o, n8);
+ const l = (((s.length - 7) * 4 - 1) >> 5) + 1; // Number of 32bit words;
+ for (let i = 0; i < l; i++) v.setUint32(n8 - i * 4 - 4, parseInt(s.substring(s.length - 8 * i - 8, s.length - 8 * i), 16), false);
+ for (let i = 0; i < n8 / 4 - l; i++) v[i] = 0;
+}
+
+// Pases a buffer with Little Endian Representation
+function fromRprLE(buff, o, n8) {
+ n8 = n8 || buff.byteLength;
+ o = o || 0;
+ const v = new Uint32Array(buff.buffer, o, n8 / 4);
+ const a = new Array(n8 / 4);
+ v.forEach((ch, i) => (a[a.length - i - 1] = ch.toString(16).padStart(8, "0")));
+ return fromString(a.join(""), 16);
+}
+
+// Pases a buffer with Big Endian Representation
+function fromRprBE(buff, o, n8) {
+ n8 = n8 || buff.byteLength;
+ o = o || 0;
+ const v = new DataView(buff.buffer, buff.byteOffset + o, n8);
+ const a = new Array(n8 / 4);
+ for (let i = 0; i < n8 / 4; i++) {
+ a[i] = v
+ .getUint32(i * 4, false)
+ .toString(16)
+ .padStart(8, "0");
+ }
+ return fromString(a.join(""), 16);
+}
+
+function toString(a, radix) {
+ return a.toString(radix);
+}
+
+function toLEBuff(a) {
+ const buff = new Uint8Array(Math.floor((bitLength(a) - 1) / 8) + 1);
+ toRprLE(buff, 0, a, buff.byteLength);
+ return buff;
+}
+
+const zero = e(0);
+const one = e(1);
+
+export { abs, add, band, bitLength, bits, bor, bxor, div, e, eq, exp, fromArray, fromRprBE, fromRprLE, fromString, geq, gt, isNegative, isOdd, isZero, land, leq, lnot, lor, lt, mod, mul, naf, neg, neq, one, pow, shiftLeft, shiftRight, shl, shr, square, sub, toArray, toLEBuff, toNumber, toRprBE, toRprLE, toString, zero };
diff --git a/build/main.cjs b/build/main.cjs
index 7ba9ac3..c0a0c92 100644
--- a/build/main.cjs
+++ b/build/main.cjs
@@ -1,7 +1,5 @@
'use strict';
-var crypto = require('crypto');
-
/* global BigInt */
const hexLen = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4];
@@ -520,20 +518,15 @@ function alg8_complex(F) {
function getRandomBytes(n) {
let array = new Uint8Array(n);
- if (process.browser) {
- // Browser
- if (typeof globalThis.crypto !== "undefined") {
- // Supported
- globalThis.crypto.getRandomValues(array);
- } else {
- // fallback
- for (let i = 0; i < n; i++) {
- array[i] = (Math.random() * 4294967296) >>> 0;
- }
- }
+ // Browser & Node
+ if (typeof globalThis.crypto !== "undefined") {
+ // Supported
+ globalThis.crypto.getRandomValues(array);
} else {
- // NodeJS
- crypto.randomFillSync(array);
+ // fallback
+ for (let i = 0; i < n; i++) {
+ array[i] = (Math.random() * 4294967296) >>> 0;
+ }
}
return array;
}
diff --git a/build/main.esm.js b/build/main.esm.js
index 182e480..4fb647f 100644
--- a/build/main.esm.js
+++ b/build/main.esm.js
@@ -1,5 +1,3 @@
-import crypto from 'crypto';
-
/* global BigInt */
const hexLen = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4];
@@ -518,20 +516,15 @@ function alg8_complex(F) {
function getRandomBytes(n) {
let array = new Uint8Array(n);
- if (process.browser) {
- // Browser
- if (typeof globalThis.crypto !== "undefined") {
- // Supported
- globalThis.crypto.getRandomValues(array);
- } else {
- // fallback
- for (let i = 0; i < n; i++) {
- array[i] = (Math.random() * 4294967296) >>> 0;
- }
- }
+ // Browser & Node
+ if (typeof globalThis.crypto !== "undefined") {
+ // Supported
+ globalThis.crypto.getRandomValues(array);
} else {
- // NodeJS
- crypto.randomFillSync(array);
+ // fallback
+ for (let i = 0; i < n; i++) {
+ array[i] = (Math.random() * 4294967296) >>> 0;
+ }
}
return array;
}
diff --git a/build/main.umd.min.js b/build/main.umd.min.js
index 02835ed..ad0c5ff 100644
--- a/build/main.umd.min.js
+++ b/build/main.umd.min.js
@@ -1 +1 @@
-!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("crypto")):"function"==typeof define&&define.amd?define(["exports","crypto"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Ffjavascript={},t.crypto)}(this,(function(t,n){"use strict";const i=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];function r(t,n){return n&&10!=n?16==n?"0x"==t.slice(0,2)?BigInt(t):BigInt("0x"+t):void 0:BigInt(t)}const s=r;function e(t){const n=t.toString(16);return 4*(n.length-1)+i[parseInt(n[0],16)]}function o(t){return!t}function h(t,n){return BigInt(t)<>BigInt(n)}const f=h,l=u;function g(t){return(BigInt(t)&BigInt(1))==BigInt(1)}function p(t){let n=BigInt(t);const i=[];for(;n;)n&BigInt(1)?i.push(1):i.push(0),n>>=BigInt(1);return i}function c(t){if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Number too big");return Number(t)}function a(t,n){return BigInt(t)-BigInt(n)}function q(t,n){return BigInt(t)**BigInt(n)}function B(t,n){return BigInt(t)/BigInt(n)}function m(t,n){return BigInt(t)%BigInt(n)}function I(t,n){return BigInt(t)==BigInt(n)}function w(t,n){return BigInt(t)&BigInt(n)}function b(t,n,i,r){const s="0000000"+i.toString(16),e=new Uint32Array(t.buffer,n,r/4),o=1+(4*(s.length-7)-1>>5);for(let t=0;t>5);for(let t=0;te[e.length-n-1]=t.toString(16).padStart(8,"0"))),r(e.join(""),16)}function F(t,n,i){i=i||t.byteLength,n=n||0;const s=new DataView(t.buffer,t.byteOffset+n,i),e=new Array(i/4);for(let t=0;t=0?BigInt(t):-BigInt(t)},add:function(t,n){return BigInt(t)+BigInt(n)},band:w,bitLength:e,bits:p,bor:function(t,n){return BigInt(t)|BigInt(n)},bxor:function(t,n){return BigInt(t)^BigInt(n)},div:B,e:s,eq:I,exp:function(t,n){return BigInt(t)**BigInt(n)},fromArray:function(t,n){let i=BigInt(0);n=BigInt(n);for(let r=0;r=BigInt(n)},gt:function(t,n){return BigInt(t)>BigInt(n)},isNegative:function(t){return BigInt(t)>=BigInt(1)}return i},neg:function(t){return-BigInt(t)},neq:function(t,n){return BigInt(t)!=BigInt(n)},one:R,pow:q,shiftLeft:h,shiftRight:u,shl:f,shr:l,square:function(t){return BigInt(t)*BigInt(t)},sub:a,toArray:function(t,n){const i=[];let r=BigInt(t);for(n=BigInt(n);r;)i.unshift(Number(r%n)),r/=n;return i},toLEBuff:function(t){const n=new Uint8Array(Math.floor((e(t)-1)/8)+1);return b(n,0,t,n.byteLength),n},toNumber:c,toRprBE:d,toRprLE:b,toString:function(t,n){return t.toString(n)},zero:E});function z(t,n,i){if(o(i))return t.one;const r=p(i);if(0==r.length)return t.one;let s=n;for(let i=r.length-2;i>=0;i--)s=t.square(s),r[i]&&(s=t.mul(s,n));return s}function S(t){if(t.m%2==1)if(I(m(t.p,4),1))if(I(m(t.p,8),1))if(I(m(t.p,16),1))!function(t){t.sqrt_q=q(t.p,t.m),t.sqrt_s=0,t.sqrt_t=a(t.sqrt_q,1);for(;!g(t.sqrt_t);)t.sqrt_s=t.sqrt_s+1,t.sqrt_t=B(t.sqrt_t,2);let n=t.one;for(;t.eq(n,t.one);){const i=t.random();t.sqrt_z=t.pow(i,t.sqrt_t),n=t.pow(t.sqrt_z,2**(t.sqrt_s-1))}t.sqrt_tm1d2=B(a(t.sqrt_t,1),2),t.sqrt=function(t){const n=this;if(n.isZero(t))return n.zero;let i=n.pow(t,n.sqrt_tm1d2);const r=n.pow(n.mul(n.square(i),t),2**(n.sqrt_s-1));if(n.eq(r,n.negone))return null;let s=n.sqrt_s,e=n.mul(t,i),o=n.mul(e,i),h=n.sqrt_z;for(;!n.eq(o,n.one);){let t=n.square(o),r=1;for(;!n.eq(t,n.one);)t=n.square(t),r++;i=h;for(let t=0;t>>0;else n.randomFillSync(i);return i}class v{constructor(t,n,i){this.F=n,this.G=t,this.opMulGF=i;let r=n.sqrt_t||n.t,s=n.sqrt_s||n.s,e=n.one;for(;n.eq(n.pow(e,n.half),n.one);)e=n.add(e,n.one);this.w=new Array(s+1),this.wi=new Array(s+1),this.w[s]=this.F.pow(e,r),this.wi[s]=this.F.inv(this.w[s]);let o=s-1;for(;o>=0;)this.w[o]=this.F.square(this.w[o+1]),this.wi[o]=this.F.square(this.wi[o+1]),o--;this.roots=[],this._setRoots(Math.min(s,15))}_setRoots(t){for(let n=t;n>=0&&!this.roots[n];n--){let t=this.F.one;const i=1<>1,h=T(t,n,i-1,r,2*s),u=T(t,n,i-1,r+s,2*s),f=new Array(e);for(let n=0;n>this.one,this.bitLength=e(this.p),this.mask=(this.one<>this.one;this.nqr=this.two;let i=this.pow(this.nqr,n);for(;!this.eq(i,this.negone);)this.nqr=this.nqr+this.one,i=this.pow(this.nqr,n);for(this.s=0,this.t=this.negone;(this.t&this.one)==this.zero;)this.s=this.s+1,this.t=this.t>>this.one;this.nqr_to_t=this.pow(this.nqr,this.t),S(this),this.FFT=new v(this,this,this.mul.bind(this)),this.fft=this.FFT.fft.bind(this.FFT),this.ifft=this.FFT.ifft.bind(this.FFT),this.w=this.FFT.w,this.wi=this.FFT.wi,this.shift=this.square(this.nqr),this.k=this.exp(this.nqr,2**this.s)}e(t,n){let i;if(n?16==n&&(i=BigInt("0x"+t)):i=BigInt(t),i<0){let t=-i;return t>=this.p&&(t%=this.p),this.p-t}return i>=this.p?i%this.p:i}add(t,n){const i=t+n;return i>=this.p?i-this.p:i}sub(t,n){return t>=n?t-n:this.p-n+t}neg(t){return t?this.p-t:t}mul(t,n){return t*n%this.p}mulScalar(t,n){return t*this.e(n)%this.p}square(t){return t*t%this.p}eq(t,n){return t==n}neq(t,n){return t!=n}lt(t,n){return(t>this.half?t-this.p:t)<(n>this.half?n-this.p:n)}gt(t,n){return(t>this.half?t-this.p:t)>(n>this.half?n-this.p:n)}leq(t,n){return(t>this.half?t-this.p:t)<=(n>this.half?n-this.p:n)}geq(t,n){return(t>this.half?t-this.p:t)>=(n>this.half?n-this.p:n)}div(t,n){return this.mul(t,this.inv(n))}idiv(t,n){if(!n)throw new Error("Division by zero");return t/n}inv(t){if(!t)throw new Error("Division by zero");let n=this.zero,i=this.p,r=this.one,s=t%this.p;for(;s;){let t=i/s;[n,r]=[r,n-t*r],[i,s]=[s,i-t*s]}return n=this.p?i-this.p:i}bor(t,n){const i=(t|n)&this.mask;return i>=this.p?i-this.p:i}bxor(t,n){const i=(t^n)&this.mask;return i>=this.p?i-this.p:i}bnot(t){const n=t^this.mask;return n>=this.p?n-this.p:n}shl(t,n){if(Number(n)=this.p?i-this.p:i}{const i=this.p-n;return Number(i)>i:this.zero}}shr(t,n){if(Number(n)>n;{const i=this.p-n;if(Number(i)=this.p?n-this.p:n}return 0}}land(t,n){return t&&n?this.one:this.zero}lor(t,n){return t||n?this.one:this.zero}lnot(t){return t?this.zero:this.one}sqrt_old(t){if(t==this.zero)return this.zero;if(this.pow(t,this.negone>>this.one)!=this.one)return null;let n=this.s,i=this.nqr_to_t,r=this.pow(t,this.t),s=this.pow(t,this.add(this.t,this.one)>>this.one);for(;r!=this.one;){let t=this.square(r),e=1;for(;t!=this.one;)e++,t=this.square(t);let o=i;for(let t=0;tthis.p>>this.one&&(s=this.neg(s)),s}normalize(t,n){if((t=BigInt(t,n))<0){let n=-t;return n>=this.p&&(n%=this.p),this.p-n}return t>=this.p?t%this.p:t}random(){const t=2*this.bitLength/8;let n=this.zero;for(let i=0;ithis.half&&10==n){i="-"+(this.p-t).toString(n)}else i=t.toString(n);return i}isZero(t){return t==this.zero}fromRng(t){let n;do{n=this.zero;for(let i=0;i=this.p);return n=n*this.Ri%this.p,n}fft(t){return this.FFT.fft(t)}ifft(t){return this.FFT.ifft(t)}toRprLE(t,n,i){b(t,n,i,8*this.n64)}toRprBE(t,n,i){d(t,n,i,8*this.n64)}toRprBEM(t,n,i){return this.toRprBE(t,n,this.mul(this.R,i))}toRprLEM(t,n,i){return this.toRprLE(t,n,this.mul(this.R,i))}fromRprLE(t,n){return _(t,n,this.n8)}fromRprBE(t,n){return F(t,n,this.n8)}fromRprLEM(t,n){return this.mul(this.fromRprLE(t,n),this.Ri)}fromRprBEM(t,n){return this.mul(this.fromRprBE(t,n),this.Ri)}toObject(t){return t}}const x=y;t.F1Field=M,t.Scalar=x,t.ZqField=M}));
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Ffjavascript={})}(this,(function(t){"use strict";const n=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];function i(t,n){return n&&10!=n?16==n?"0x"==t.slice(0,2)?BigInt(t):BigInt("0x"+t):void 0:BigInt(t)}const r=i;function s(t){const i=t.toString(16);return 4*(i.length-1)+n[parseInt(i[0],16)]}function e(t){return!t}function o(t,n){return BigInt(t)<>BigInt(n)}const u=o,f=h;function l(t){return(BigInt(t)&BigInt(1))==BigInt(1)}function g(t){let n=BigInt(t);const i=[];for(;n;)n&BigInt(1)?i.push(1):i.push(0),n>>=BigInt(1);return i}function p(t){if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Number too big");return Number(t)}function c(t,n){return BigInt(t)-BigInt(n)}function a(t,n){return BigInt(t)**BigInt(n)}function q(t,n){return BigInt(t)/BigInt(n)}function B(t,n){return BigInt(t)%BigInt(n)}function m(t,n){return BigInt(t)==BigInt(n)}function I(t,n){return BigInt(t)&BigInt(n)}function w(t,n,i,r){const s="0000000"+i.toString(16),e=new Uint32Array(t.buffer,n,r/4),o=1+(4*(s.length-7)-1>>5);for(let t=0;t>5);for(let t=0;te[e.length-n-1]=t.toString(16).padStart(8,"0"))),i(e.join(""),16)}function _(t,n,r){r=r||t.byteLength,n=n||0;const s=new DataView(t.buffer,t.byteOffset+n,r),e=new Array(r/4);for(let t=0;t=0?BigInt(t):-BigInt(t)},add:function(t,n){return BigInt(t)+BigInt(n)},band:I,bitLength:s,bits:g,bor:function(t,n){return BigInt(t)|BigInt(n)},bxor:function(t,n){return BigInt(t)^BigInt(n)},div:q,e:r,eq:m,exp:function(t,n){return BigInt(t)**BigInt(n)},fromArray:function(t,n){let i=BigInt(0);n=BigInt(n);for(let r=0;r=BigInt(n)},gt:function(t,n){return BigInt(t)>BigInt(n)},isNegative:function(t){return BigInt(t)>=BigInt(1)}return i},neg:function(t){return-BigInt(t)},neq:function(t,n){return BigInt(t)!=BigInt(n)},one:E,pow:a,shiftLeft:o,shiftRight:h,shl:u,shr:f,square:function(t){return BigInt(t)*BigInt(t)},sub:c,toArray:function(t,n){const i=[];let r=BigInt(t);for(n=BigInt(n);r;)i.unshift(Number(r%n)),r/=n;return i},toLEBuff:function(t){const n=new Uint8Array(Math.floor((s(t)-1)/8)+1);return w(n,0,t,n.byteLength),n},toNumber:p,toRprBE:b,toRprLE:w,toString:function(t,n){return t.toString(n)},zero:F});function z(t,n,i){if(e(i))return t.one;const r=g(i);if(0==r.length)return t.one;let s=n;for(let i=r.length-2;i>=0;i--)s=t.square(s),r[i]&&(s=t.mul(s,n));return s}function y(t){if(t.m%2==1)if(m(B(t.p,4),1))if(m(B(t.p,8),1))if(m(B(t.p,16),1))!function(t){t.sqrt_q=a(t.p,t.m),t.sqrt_s=0,t.sqrt_t=c(t.sqrt_q,1);for(;!l(t.sqrt_t);)t.sqrt_s=t.sqrt_s+1,t.sqrt_t=q(t.sqrt_t,2);let n=t.one;for(;t.eq(n,t.one);){const i=t.random();t.sqrt_z=t.pow(i,t.sqrt_t),n=t.pow(t.sqrt_z,2**(t.sqrt_s-1))}t.sqrt_tm1d2=q(c(t.sqrt_t,1),2),t.sqrt=function(t){const n=this;if(n.isZero(t))return n.zero;let i=n.pow(t,n.sqrt_tm1d2);const r=n.pow(n.mul(n.square(i),t),2**(n.sqrt_s-1));if(n.eq(r,n.negone))return null;let s=n.sqrt_s,e=n.mul(t,i),o=n.mul(e,i),h=n.sqrt_z;for(;!n.eq(o,n.one);){let t=n.square(o),r=1;for(;!n.eq(t,n.one);)t=n.square(t),r++;i=h;for(let t=0;t>>0;return n}class L{constructor(t,n,i){this.F=n,this.G=t,this.opMulGF=i;let r=n.sqrt_t||n.t,s=n.sqrt_s||n.s,e=n.one;for(;n.eq(n.pow(e,n.half),n.one);)e=n.add(e,n.one);this.w=new Array(s+1),this.wi=new Array(s+1),this.w[s]=this.F.pow(e,r),this.wi[s]=this.F.inv(this.w[s]);let o=s-1;for(;o>=0;)this.w[o]=this.F.square(this.w[o+1]),this.wi[o]=this.F.square(this.wi[o+1]),o--;this.roots=[],this._setRoots(Math.min(s,15))}_setRoots(t){for(let n=t;n>=0&&!this.roots[n];n--){let t=this.F.one;const i=1<>1,h=A(t,n,i-1,r,2*s),u=A(t,n,i-1,r+s,2*s),f=new Array(e);for(let n=0;n>this.one,this.bitLength=s(this.p),this.mask=(this.one<>this.one;this.nqr=this.two;let i=this.pow(this.nqr,n);for(;!this.eq(i,this.negone);)this.nqr=this.nqr+this.one,i=this.pow(this.nqr,n);for(this.s=0,this.t=this.negone;(this.t&this.one)==this.zero;)this.s=this.s+1,this.t=this.t>>this.one;this.nqr_to_t=this.pow(this.nqr,this.t),y(this),this.FFT=new L(this,this,this.mul.bind(this)),this.fft=this.FFT.fft.bind(this.FFT),this.ifft=this.FFT.ifft.bind(this.FFT),this.w=this.FFT.w,this.wi=this.FFT.wi,this.shift=this.square(this.nqr),this.k=this.exp(this.nqr,2**this.s)}e(t,n){let i;if(n?16==n&&(i=BigInt("0x"+t)):i=BigInt(t),i<0){let t=-i;return t>=this.p&&(t%=this.p),this.p-t}return i>=this.p?i%this.p:i}add(t,n){const i=t+n;return i>=this.p?i-this.p:i}sub(t,n){return t>=n?t-n:this.p-n+t}neg(t){return t?this.p-t:t}mul(t,n){return t*n%this.p}mulScalar(t,n){return t*this.e(n)%this.p}square(t){return t*t%this.p}eq(t,n){return t==n}neq(t,n){return t!=n}lt(t,n){return(t>this.half?t-this.p:t)<(n>this.half?n-this.p:n)}gt(t,n){return(t>this.half?t-this.p:t)>(n>this.half?n-this.p:n)}leq(t,n){return(t>this.half?t-this.p:t)<=(n>this.half?n-this.p:n)}geq(t,n){return(t>this.half?t-this.p:t)>=(n>this.half?n-this.p:n)}div(t,n){return this.mul(t,this.inv(n))}idiv(t,n){if(!n)throw new Error("Division by zero");return t/n}inv(t){if(!t)throw new Error("Division by zero");let n=this.zero,i=this.p,r=this.one,s=t%this.p;for(;s;){let t=i/s;[n,r]=[r,n-t*r],[i,s]=[s,i-t*s]}return n=this.p?i-this.p:i}bor(t,n){const i=(t|n)&this.mask;return i>=this.p?i-this.p:i}bxor(t,n){const i=(t^n)&this.mask;return i>=this.p?i-this.p:i}bnot(t){const n=t^this.mask;return n>=this.p?n-this.p:n}shl(t,n){if(Number(n)=this.p?i-this.p:i}{const i=this.p-n;return Number(i)>i:this.zero}}shr(t,n){if(Number(n)>n;{const i=this.p-n;if(Number(i)=this.p?n-this.p:n}return 0}}land(t,n){return t&&n?this.one:this.zero}lor(t,n){return t||n?this.one:this.zero}lnot(t){return t?this.zero:this.one}sqrt_old(t){if(t==this.zero)return this.zero;if(this.pow(t,this.negone>>this.one)!=this.one)return null;let n=this.s,i=this.nqr_to_t,r=this.pow(t,this.t),s=this.pow(t,this.add(this.t,this.one)>>this.one);for(;r!=this.one;){let t=this.square(r),e=1;for(;t!=this.one;)e++,t=this.square(t);let o=i;for(let t=0;tthis.p>>this.one&&(s=this.neg(s)),s}normalize(t,n){if((t=BigInt(t,n))<0){let n=-t;return n>=this.p&&(n%=this.p),this.p-n}return t>=this.p?t%this.p:t}random(){const t=2*this.bitLength/8;let n=this.zero;for(let i=0;ithis.half&&10==n){i="-"+(this.p-t).toString(n)}else i=t.toString(n);return i}isZero(t){return t==this.zero}fromRng(t){let n;do{n=this.zero;for(let i=0;i=this.p);return n=n*this.Ri%this.p,n}fft(t){return this.FFT.fft(t)}ifft(t){return this.FFT.ifft(t)}toRprLE(t,n,i){w(t,n,i,8*this.n64)}toRprBE(t,n,i){b(t,n,i,8*this.n64)}toRprBEM(t,n,i){return this.toRprBE(t,n,this.mul(this.R,i))}toRprLEM(t,n,i){return this.toRprLE(t,n,this.mul(this.R,i))}fromRprLE(t,n){return d(t,n,this.n8)}fromRprBE(t,n){return _(t,n,this.n8)}fromRprLEM(t,n){return this.mul(this.fromRprLE(t,n),this.Ri)}fromRprBEM(t,n){return this.mul(this.fromRprBE(t,n),this.Ri)}toObject(t){return t}}const M=R;t.F1Field=T,t.Scalar=M,t.ZqField=T}));
diff --git a/package.json b/package.json
index 2d63d72..e67911a 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,8 @@
"type": "module",
"version": "1.0.0",
"description": "Finite Field Library in Javascript",
- "main": "./build/main.cjs",
- "module": "./build/main.esm.js",
+ "main": "./build/lib.cjs/main.js",
+ "module": "./build/lib.esm/main.js",
"unpkg": "./build/main.umd.min.js",
"jsdelivr": "./build/main.umd.min.js",
"files": [
diff --git a/rollup.config.js b/rollup.config.js
index e258b6e..144c0f1 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -19,6 +19,16 @@ export default [
file: "build/main.esm.js",
format: "esm",
},
+ {
+ dir: "build/lib.cjs",
+ format: "cjs",
+ preserveModules: true,
+ },
+ {
+ dir: "build/lib.esm",
+ format: "esm",
+ preserveModules: true,
+ },
],
external: [...Object.keys(pkg.dependencies || {})],
},
diff --git a/src/random.js b/src/random.js
index 9d0e213..a411329 100644
--- a/src/random.js
+++ b/src/random.js
@@ -1,21 +1,14 @@
-import crypto from "crypto";
-
export function getRandomBytes(n) {
let array = new Uint8Array(n);
- if (process.browser) {
- // Browser
- if (typeof globalThis.crypto !== "undefined") {
- // Supported
- globalThis.crypto.getRandomValues(array);
- } else {
- // fallback
- for (let i = 0; i < n; i++) {
- array[i] = (Math.random() * 4294967296) >>> 0;
- }
- }
+ // Browser & Node
+ if (typeof globalThis.crypto !== "undefined") {
+ // Supported
+ globalThis.crypto.getRandomValues(array);
} else {
- // NodeJS
- crypto.randomFillSync(array);
+ // fallback
+ for (let i = 0; i < n; i++) {
+ array[i] = (Math.random() * 4294967296) >>> 0;
+ }
}
return array;
}