From 62a1dcfde1c8c51e0260a8816c89d958c074b79f Mon Sep 17 00:00:00 2001 From: Jordi Baylina Date: Wed, 15 Aug 2018 14:49:08 +0200 Subject: [PATCH] Superoptimized --- src/bigint.js | 350 +++++++++++++++++++++++++++++++++++++++---------- src/zqfield.js | 51 ++----- 2 files changed, 291 insertions(+), 110 deletions(-) diff --git a/src/bigint.js b/src/bigint.js index a6dbf97..f0f46fb 100644 --- a/src/bigint.js +++ b/src/bigint.js @@ -1,72 +1,133 @@ /* global BigInt */ const bigInt = require("big-integer"); +let wBigInt; + +console.log("XXX"); + if (typeof(BigInt) != "undefined") { - const wBigInt = BigInt; + wBigInt = BigInt; - wBigInt.prototype.affine = function (q) { - let aux = this; - if (aux < 0) { - if (aux <= -q) { - aux = aux % q; + // Affine + wBigInt.genAffine = (q) => { + const nq = -q; + return (a) => { + let aux = a; + if (aux < 0) { + if (aux <= nq) { + aux = aux % q; + } + if (aux.isNegative()) { + aux = aux.add(q); + } + } else { + if (aux >= q) { + aux = aux % q; + } } - if (aux.isNegative()) { - aux = aux.add(q); + return aux.valueOf(); + }; + }; + + + // Inverse + wBigInt.genInverse = (q) => { + return (a) => { + let t = wBigInt.zero; + let r = q; + let newt = wBigInt.one; + let newr = wBigInt.affine(a, q); + while (newr!=wBigInt.zero) { + let q = r/newr; + [t, newt] = [newt, t-q*newt]; + [r, newr] = [newr, r-q*newr]; } + if (t { + if (q) { + return (a,b) => (a+b) % q; } else { - if (aux >= q) { - aux = aux % q; - } + return (a,b) => a+b; } - return aux; }; - wBigInt.prototype.modInv = function (q) { - let t = wBigInt.zero; - let r = q; - let newt = wBigInt.one; - let newr = this.affine(q); - while (newr!=wBigInt.zero) { - let q = r/newr; - [t, newt] = [newt, t-q*newt]; - [r, newr] = [newr, r-q*newr]; + // Sub + wBigInt.genSub = (q) => { + if (q) { + return (a,b) => (a-b) % q; + } else { + return (a,b) => a-b; } - if (t { + if (q) { + return (a) => (-a) % q; + } else { + return (a) => -a; + } }; - wBigInt.prototype.minus = function(b) { - return this-b; + // Mul + wBigInt.genMul = (q) => { + if (q) { + return (a,b) => (a*b) % q; + } else { + return (a,b) => a*b; + } }; - wBigInt.prototype.times = function(b) { - return this*b; + // Equals + wBigInt.genEquals = (q) => { + if (q) { + return (a,b) => (a.affine(q) == b.affine(q)); + } else { + return (a,b) => a == b; + } }; - wBigInt.prototype.mod = function(q) { - return this%q; + // Square + wBigInt.genSquare = (q) => { + if (q) { + return (a) => (a*a) %q; + } else { + return (a) => a*a; + } }; - wBigInt.prototype.square = function() { - return this*this; + + // Double + wBigInt.genDouble = (q) => { + if (q) { + return (a) => (a+a) %q; + } else { + return (a) => a+a; + } }; - wBigInt.prototype.double = function() { - return this+this; + // IsZero + wBigInt.genIsZero = (q) => { + if (q) { + return (a) => (a.affine(q) == wBigInt.zero); + } else { + return (a) => a != 0; + } }; + + // Other minor functions wBigInt.prototype.isOdd = function() { return (this & wBigInt.one) == 1; }; - wBigInt.prototype.isZero = function() { - return (this == wBigInt.zero); - }; - wBigInt.prototype.isNegative = function() { return this < wBigInt.zero; }; @@ -83,46 +144,197 @@ if (typeof(BigInt) != "undefined") { return this <= b; }; - wBigInt.prototype.equals = function(b) { -/* console.log(".."); - console.log(this); - console.log(b); - console.log(this == b); - console.log(".."); */ - return this.valueOf() == b.valueOf(); + +} else { + + wBigInt = bigInt; + + // Affine + wBigInt.genAffine = (q) => { + const nq = wBigInt.zero.minus(q); + return (a) => { + let aux = a; + if (aux.isNegative()) { + if (aux.lesserOrEquals(nq)) { + aux = aux.mod(q); + } + if (aux.isNegative()) { + aux = aux.add(q); + } + } else { + if (aux.greaterOrEquals(q)) { + aux = aux.mod(q); + } + } + return aux; + }; + }; + + + // Inverse + wBigInt.genInverse = (q) => { + return (a) => a.affine(q).modInv(q); }; - wBigInt.prototype.mulMod = function(q, b) { - return this * b % q; + // Add + wBigInt.genAdd = (q) => { + if (q) { + return (a,b) => { + const r = a.add(b); + return r.greaterOrEquals(q) ? r.minus(q) : r; + }; + } else { + return (a,b) => a.add(b); + } }; - wBigInt.one = BigInt(1); - wBigInt.zero = BigInt(0); + // Sub + wBigInt.genSub = (q) => { + if (q) { + return (a,b) => a.greaterOrEquals(b) ? a.minus(b) : a.minus(b).add(q); + } else { + return (a,b) => a.minus(b); + } + }; - module.exports = wBigInt; -} else { + wBigInt.genNeg = (q) => { + if (q) { + return (a) => a.isZero() ? a : q.minus(a); + } else { + return (a) => wBigInt.zero.minus(a); + } + }; - bigInt.prototype.mulMod = function(q, b) { - return this.times(b).mod(q); + // Mul + wBigInt.genMul = (q) => { + if (q) { + return (a,b) => a.times(b).mod(q); + } else { + return (a,b) => a.times(b); + } }; - bigInt.prototype.affine = function (q) { - let aux = this; - if (aux.isNegative()) { - const nq = bigInt.zero.minus(q); - if (aux.lesserOrEquals(nq)) { - aux = aux.mod(q); - } - if (aux.isNegative()) { - aux = aux.add(q); - } + // Square + wBigInt.genSquare = (q) => { + if (q) { + return (a) => a.square().mod(q); } else { - if (aux.greaterOrEquals(q)) { - aux = aux.mod(q); - } + return (a) => a.square(); + } + }; + + // Double + wBigInt.genDouble = (q) => { + if (q) { + return (a) => a.add(a).mod(q); + } else { + return (a) => a.add(a); + } + }; + + // Equals + wBigInt.genEquals = (q) => { + if (q) { + return (a,b) => a.affine(q).equals(b.affine(q)); + } else { + return (a,b) => a.equals(b); } - return aux; }; - module.exports = bigInt; + // IsZero + wBigInt.genIsZero = (q) => { + if (q) { + return (a) => (a.affine(q).isZero()); + } else { + return (a) => a.isZero(); + } + }; } + + + +wBigInt.affine = function(a, q) { + return wBigInt.genAffine(q)(a); +}; + +wBigInt.prototype.affine = function (q) { + return wBigInt.affine(this, q); +}; + +wBigInt.inverse = function(a, q) { + return wBigInt.genInverse(q)(a); +}; + +wBigInt.prototype.inverse = function (q) { + return wBigInt.genInverse(this, q); +}; + +wBigInt.add = function(a, b, q) { + return wBigInt.genAdd(q)(a,b); +}; + +wBigInt.prototype.add = function (a, q) { + return wBigInt.genAdd(q)(this, a); +}; + +wBigInt.sub = function(a, b, q) { + return wBigInt.genSub(q)(a,b); +}; + +wBigInt.prototype.sub = function (a, q) { + return wBigInt.genSub(q)(this, a); +}; + +wBigInt.neg = function(a, q) { + return wBigInt.genNeg(q)(a); +}; + +wBigInt.prototype.neg = function (q) { + return wBigInt.genNeg(q)(this); +}; + +wBigInt.mul = function(a, b, q) { + return wBigInt.genMul(q)(a,b); +}; + +wBigInt.prototype.mul = function (a, q) { + return wBigInt.genMul(q)(this, a); +}; + +wBigInt.equals = function(a, b, q) { + return wBigInt.genEquals(q)(a,b); +}; + +wBigInt.prototype.equals = function (a, q) { + return wBigInt.genEquals(q)(this, a); +}; + +wBigInt.square = function(a, q) { + return wBigInt.genSquare(q)(a); +}; + +wBigInt.prototype.square = function (a, q) { + return wBigInt.genSquare(q)(a); +}; + +wBigInt.double = function(a, q) { + return wBigInt.genDouble(q)(a); +}; + +wBigInt.prototype.double = function (a, q) { + return wBigInt.genDouble(q)(a); +}; + +wBigInt.isZero = function(a, q) { + return wBigInt.genIsZero(q)(a); +}; + +wBigInt.prototype.isZero = function (a, q) { + return wBigInt.genIsZero(q)(a); +}; + +wBigInt.one = wBigInt(1); +wBigInt.zero = wBigInt(0); + +module.exports = wBigInt; + diff --git a/src/zqfield.js b/src/zqfield.js index 1c20e99..76d0c41 100644 --- a/src/zqfield.js +++ b/src/zqfield.js @@ -4,59 +4,28 @@ const fUtils = require("./futils.js"); class ZqField { constructor(q) { this.q = q; - this.nq = bigInt.zero.minus(q); this.zero = bigInt.zero; this.one = bigInt.one; + this.add = bigInt.genAdd(); + this.double = bigInt.genDouble(); + this.sub = bigInt.genSub(); + this.neg = bigInt.genNeg(); + this.mul = bigInt.genMul(q); + this.inverse = bigInt.genInverse(q); + this.square = bigInt.genSquare(q); + this.equals = bigInt.genEquals(q); + this.affine = bigInt.genAffine(q); + this.isZero = bigInt.genIsZero(q); } copy(a) { return bigInt(a); } - add(a, b) { - return a.add(b); - } - - double(a) { - return this.add(a,a); - } - - sub(a, b) { - return a.minus(b); - } - - neg(a) { - return bigInt.zero.minus(a); - } - - mul(a, b) { - return a.mulMod(this.q, b); - } - - inverse(a) { - return a.modInv(this.q); - } - div(a, b) { return this.mul(a, this.inverse(b)); } - square(a) { - return a.square().mod(this.q); - } - - isZero(a) { - return a.isZero(); - } - - equals(a, b) { - return this.affine(a).equals(this.affine(b)); - } - - affine(a) { - return a.affine(this.q); - } - mulEscalar(base, e) { return fUtils.mulEscalar(this, base, e); }