Polynomial division done
This commit is contained in:
parent
8bc1bb610b
commit
0270ceada6
66
aux/calculate2roots.js
Normal file
66
aux/calculate2roots.js
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
const bigInt = require("../src/bigint.js");
|
||||
const ZqField = require("../src/zqfield.js");
|
||||
|
||||
|
||||
const r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const s = 28;
|
||||
const nqr_to_t = bigInt("19103219067921713944291392827692070036145651957329286315305642004821462161904");
|
||||
const t_minus_1_over_2 = bigInt("40770029410420498293352137776570907027550720424234931066070132305055");
|
||||
const root_unity = bigInt("19103219067921713944291392827692070036145651957329286315305642004821462161904");
|
||||
const t = bigInt("81540058820840996586704275553141814055101440848469862132140264610111");
|
||||
|
||||
const F = new ZqField(r);
|
||||
|
||||
function sqrt(a) {
|
||||
|
||||
let v = s;
|
||||
let z = nqr_to_t;
|
||||
let w = F.exp(a, t_minus_1_over_2);
|
||||
let x = F.mul(a, w);
|
||||
let b = F.mul(x, w);
|
||||
|
||||
|
||||
// compute square root with Tonelli--Shanks
|
||||
// (does not terminate if not a square!)
|
||||
|
||||
while (!F.equals(b, F.one))
|
||||
{
|
||||
let m = 0;
|
||||
let b2m = b;
|
||||
while (!F.equals(b2m, F.one))
|
||||
{
|
||||
/* invariant: b2m = b^(2^m) after entering this loop */
|
||||
b2m = F.square(b2m);
|
||||
m += 1;
|
||||
}
|
||||
|
||||
let j = v-m-1;
|
||||
w = z;
|
||||
while (j > 0)
|
||||
{
|
||||
w = F.square(w);
|
||||
--j;
|
||||
} // w = z^2^(v-m-1)
|
||||
|
||||
z = F.square(w);
|
||||
b = F.mul(b, z);
|
||||
x = F.mul(x, w);
|
||||
v = m;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
const p_minus1= F.sub(r,bigInt(1));
|
||||
const gen = bigInt(bigInt(5));
|
||||
const twoto28= F.exp(bigInt(2), bigInt(28));
|
||||
const rem = F.div(p_minus1, twoto28);
|
||||
const w28 = F.exp(gen, rem);
|
||||
|
||||
const one = F.exp(w28, twoto28);
|
||||
|
||||
|
||||
console.log(F.toString(w28));
|
||||
console.log(w28.toString(10));
|
||||
console.log(F.toString(one));
|
260
file%3a/Users/jbaylina/git/personal/zksnark/src/polfield.js
Normal file
260
file%3a/Users/jbaylina/git/personal/zksnark/src/polfield.js
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
This library do operations on polinomials where their coefficients are in field F
|
||||
|
||||
The polynomial P(x) = p0 + p1 * x + p2 * x^2 + p3 * x^3, ...
|
||||
is represented by the array [ p0, p1, p2, p3, ... ]
|
||||
*/
|
||||
|
||||
const bigInt = require("./bigInt");
|
||||
const ZqField = require("./zqfield");
|
||||
|
||||
class PolFieldZq {
|
||||
constructor (q) {
|
||||
this.F = new ZqField(q);
|
||||
|
||||
let rem = q.sub(bigInt(1));
|
||||
let s = 0;
|
||||
while (!rem.isOdd()) {
|
||||
s ++;
|
||||
rem = rem.shiftRight(1);
|
||||
}
|
||||
|
||||
this.w = new Array(s+1);
|
||||
this.wi = new Array(s+1);
|
||||
this.w[s] = this.F.exp(bigInt(5), rem);
|
||||
this.wi[s] = this.F.inverse(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--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
add(a, b) {
|
||||
const m = Math.max(a.length, b.length);
|
||||
const res = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
res[i] = this.F.add(a[i] || this.F.zero, b[i] || this.F.zero);
|
||||
}
|
||||
return this.reduce(res);
|
||||
}
|
||||
|
||||
double(a) {
|
||||
return this.add(a,a);
|
||||
}
|
||||
|
||||
sub(a, b) {
|
||||
const m = Math.max(a.length, b.length);
|
||||
const res = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
res[i] = this.F.sub(a[i] || this.F.zero, b[i] || this.F.zero);
|
||||
}
|
||||
return this.reduce(res);
|
||||
}
|
||||
|
||||
mulEscalar(a, b) {
|
||||
if (this.F.isZero(b)) return [];
|
||||
const res = new Array(a.length);
|
||||
for (let i=0; i<a.length; i++) {
|
||||
res[i] = this.F.mul(a[i], b);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
mul(a, b) {
|
||||
if (a.length == 0) return [];
|
||||
if (b.length == 0) return [];
|
||||
if (a.length == 1) return this.mulEscalar(b, a[0]);
|
||||
if (b.length == 1) return this.mulEscalar(a, b[0]);
|
||||
|
||||
const longestN = Math.max(a.length, b.length);
|
||||
const bitsResult = log2(longestN-1)+2;
|
||||
const m = 1 << bitsResult;
|
||||
const ea = this.extend(a,m);
|
||||
const eb = this.extend(b,m);
|
||||
|
||||
const ta = this._fft(ea, bitsResult, 0, 1, false);
|
||||
const tb = this._fft(eb, bitsResult, 0, 1, false);
|
||||
|
||||
const tres = new Array(m);
|
||||
|
||||
for (let i=0; i<m; i++) {
|
||||
tres[i] = this.F.mul(ta[i], tb[i]);
|
||||
}
|
||||
|
||||
const res = this._fft(tres, bitsResult, 0, 1, true);
|
||||
|
||||
const twoinvm = this.F.inverse(bigInt(m));
|
||||
const resn = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
||||
}
|
||||
|
||||
return this.reduce(this.affine(resn));
|
||||
}
|
||||
|
||||
square(a) {
|
||||
return this.mul(a,a);
|
||||
}
|
||||
|
||||
scaleX(p, n) {
|
||||
if (n==0) {
|
||||
return p;
|
||||
} else if (n>0) {
|
||||
const z = new Array(n).fill(this.F.zero);
|
||||
return z.concat(p);
|
||||
} else {
|
||||
return p.slice(-n);
|
||||
}
|
||||
}
|
||||
|
||||
div(a, b) {
|
||||
throw new Error("Not Implementted");
|
||||
}
|
||||
|
||||
eval(p, x) {
|
||||
let v = this.F.zero;
|
||||
let ix = this.F.one;
|
||||
for (let i=0; i<p.length; i++) {
|
||||
v = this.F.add(v, this.F.mul(p[i], ix));
|
||||
ix = this.F.mul(ix, x);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
lagrange(points) {
|
||||
throw new Error("Not Implementted");
|
||||
}
|
||||
|
||||
_fft(pall, bits, offset, step) {
|
||||
|
||||
const n = 1 << bits;
|
||||
if (n==1) {
|
||||
return [ pall[offset] ];
|
||||
}
|
||||
|
||||
const ndiv2 = n >> 1;
|
||||
const p1 = this._fft(pall, bits-1, offset, step*2);
|
||||
const p2 = this._fft(pall, bits-1, offset+step, step*2);
|
||||
|
||||
const out = new Array(n);
|
||||
|
||||
let m= bigInt(1);
|
||||
for (let i=0; i<ndiv2; i++) {
|
||||
out[i] = this.F.add(p1[i], this.F.mul(m, p2[i]));
|
||||
out[i+ndiv2] = this.F.sub(p1[i], this.F.mul(m, p2[i]));
|
||||
m = this.F.mul(m, this.w[bits]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
extend(p, e) {
|
||||
if (e == p.length) return p;
|
||||
const z = new Array(e-p.length).fill(this.F.zero);
|
||||
|
||||
return p.concat(z);
|
||||
}
|
||||
|
||||
reduce(p) {
|
||||
if (p.length == 0) return p;
|
||||
if (! this.F.isZero(p[p.length-1]) ) return p;
|
||||
let i=p.length-1;
|
||||
while( i>0 && this.F.isZero(p[i]) ) i--;
|
||||
return p.slice(0, i+1);
|
||||
}
|
||||
|
||||
affine(p) {
|
||||
for (let i=0; i<p.length; i++) {
|
||||
p[i] = this.F.affine(p[i]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
equals(a, b) {
|
||||
const pa = this.reduce(this.affine(a));
|
||||
const pb = this.reduce(this.affine(b));
|
||||
|
||||
if (pa.length != pb.length) return false;
|
||||
for (let i=0; i<pb.length; i++) {
|
||||
if (!this.F.equals(pa[i], pb[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_next2Power(v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
toString(p) {
|
||||
const ap = this.affine(p);
|
||||
let S = "";
|
||||
for (let i=ap.length-1; i>=0; i--) {
|
||||
if (!this.F.isZero(p[i])) {
|
||||
if (S!="") S += " + ";
|
||||
S = S + p[i].toString(10);
|
||||
if (i>0) {
|
||||
S = S + "x";
|
||||
if (i>1) {
|
||||
S = S + "^" +i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
_reciprocal(p, bits) {
|
||||
const k = 1 << bits;
|
||||
if (k==1) {
|
||||
return [ this.F.inverse(p[0]) ];
|
||||
}
|
||||
const np = this.scaleX(p, -k/2);
|
||||
const q = this._reciprocal(np, bits-1);
|
||||
const a = this.scaleX(this.double(q), 3*k/2-2);
|
||||
const b = this.mul( this.square(q), p);
|
||||
|
||||
return this.scaleX(this.sub(a,b), -(k-2));
|
||||
}
|
||||
|
||||
// divides x^m / v
|
||||
_div2(m, v) {
|
||||
const kbits = log2(v.length-1)+1;
|
||||
const k = 1 << kbits;
|
||||
|
||||
const scaleV = k - v.length;
|
||||
|
||||
// rec = x^(k - 2) / v* x^scaleV =>
|
||||
// rec = x^(k-2-scaleV)/ v
|
||||
//
|
||||
// res = x^m/v = x^(m +(2k-2-scaleV) -(2k-2-scaleV)) /v =>
|
||||
// res = rec * x^(m - (2k-2-scaleV)) =>
|
||||
// res = rec * x^(m - 2k +2 + scaleV)
|
||||
|
||||
const rec = this._reciprocal(this.scaleX(v, scaleV), kbits);
|
||||
const res = this.scaleX(rec, m - k*2 +2+scaleV);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
module.exports = PolFieldZq;
|
@ -3,8 +3,6 @@ const bigInt = require("big-integer");
|
||||
|
||||
let wBigInt;
|
||||
|
||||
console.log("XXX");
|
||||
|
||||
if (typeof(BigInt) != "undefined") {
|
||||
wBigInt = BigInt;
|
||||
wBigInt.one = wBigInt(1);
|
||||
|
281
src/polfield.js
281
src/polfield.js
@ -5,46 +5,291 @@
|
||||
is represented by the array [ p0, p1, p2, p3, ... ]
|
||||
*/
|
||||
|
||||
class PolField {
|
||||
constructor (F) {
|
||||
this.F = F;
|
||||
const bigInt = require("./bigInt");
|
||||
const ZqField = require("./zqfield");
|
||||
|
||||
class PolFieldZq {
|
||||
constructor (q) {
|
||||
this.F = new ZqField(q);
|
||||
|
||||
let rem = q.sub(bigInt(1));
|
||||
let s = 0;
|
||||
while (!rem.isOdd()) {
|
||||
s ++;
|
||||
rem = rem.shiftRight(1);
|
||||
}
|
||||
|
||||
this.w = new Array(s+1);
|
||||
this.wi = new Array(s+1);
|
||||
this.w[s] = this.F.exp(bigInt(5), rem);
|
||||
this.wi[s] = this.F.inverse(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--;
|
||||
}
|
||||
|
||||
_reduce(a) {
|
||||
let i = a.length-1;
|
||||
while ((i>=0) && (this.F.isZero(a[i])) ) i--;
|
||||
return (i < a.length-1) ? a.slice(0, i+1) : a;
|
||||
}
|
||||
|
||||
add(a, b) {
|
||||
const maxGrade = Math.max(a.length, b.length);
|
||||
const res = new Array(maxGrade);
|
||||
for (let i=0; i<maxGrade; i++) {
|
||||
res[i] = this.F.add(a[i], b[i]);
|
||||
const m = Math.max(a.length, b.length);
|
||||
const res = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
res[i] = this.F.add(a[i] || this.F.zero, b[i] || this.F.zero);
|
||||
}
|
||||
return this._reduce(res);
|
||||
return this.reduce(res);
|
||||
}
|
||||
|
||||
double(a) {
|
||||
return this.add(a,a);
|
||||
}
|
||||
|
||||
sub(a, b) {
|
||||
throw new Error("Not Implementted");
|
||||
const m = Math.max(a.length, b.length);
|
||||
const res = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
res[i] = this.F.sub(a[i] || this.F.zero, b[i] || this.F.zero);
|
||||
}
|
||||
return this.reduce(res);
|
||||
}
|
||||
|
||||
mulEscalar(a, b) {
|
||||
if (this.F.isZero(b)) return [];
|
||||
const res = new Array(a.length);
|
||||
for (let i=0; i<a.length; i++) {
|
||||
res[i] = this.F.mul(a[i], b);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
mul(a, b) {
|
||||
throw new Error("Not Implementted");
|
||||
if (a.length == 0) return [];
|
||||
if (b.length == 0) return [];
|
||||
if (a.length == 1) return this.mulEscalar(b, a[0]);
|
||||
if (b.length == 1) return this.mulEscalar(a, b[0]);
|
||||
|
||||
const longestN = Math.max(a.length, b.length);
|
||||
const bitsResult = log2(longestN-1)+2;
|
||||
const m = 1 << bitsResult;
|
||||
const ea = this.extend(a,m);
|
||||
const eb = this.extend(b,m);
|
||||
|
||||
const ta = this._fft(ea, bitsResult, 0, 1, false);
|
||||
const tb = this._fft(eb, bitsResult, 0, 1, false);
|
||||
|
||||
const tres = new Array(m);
|
||||
|
||||
for (let i=0; i<m; i++) {
|
||||
tres[i] = this.F.mul(ta[i], tb[i]);
|
||||
}
|
||||
|
||||
div(a, b) {
|
||||
throw new Error("Not Implementted");
|
||||
const res = this._fft(tres, bitsResult, 0, 1, true);
|
||||
|
||||
const twoinvm = this.F.inverse(bigInt(m));
|
||||
const resn = new Array(m);
|
||||
for (let i=0; i<m; i++) {
|
||||
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
||||
}
|
||||
|
||||
return this.reduce(this.affine(resn));
|
||||
}
|
||||
|
||||
|
||||
|
||||
square(a) {
|
||||
return this.mul(a,a);
|
||||
}
|
||||
|
||||
scaleX(p, n) {
|
||||
if (n==0) {
|
||||
return p;
|
||||
} else if (n>0) {
|
||||
const z = new Array(n).fill(this.F.zero);
|
||||
return z.concat(p);
|
||||
} else {
|
||||
if (-n >= p.length) return [];
|
||||
return p.slice(-n);
|
||||
}
|
||||
}
|
||||
|
||||
eval(p, x) {
|
||||
throw new Error("Not Implementted");
|
||||
let v = this.F.zero;
|
||||
let ix = this.F.one;
|
||||
for (let i=0; i<p.length; i++) {
|
||||
v = this.F.add(v, this.F.mul(p[i], ix));
|
||||
ix = this.F.mul(ix, x);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
lagrange(points) {
|
||||
throw new Error("Not Implementted");
|
||||
}
|
||||
|
||||
_fft(pall, bits, offset, step) {
|
||||
|
||||
const n = 1 << bits;
|
||||
if (n==1) {
|
||||
return [ pall[offset] ];
|
||||
}
|
||||
|
||||
const ndiv2 = n >> 1;
|
||||
const p1 = this._fft(pall, bits-1, offset, step*2);
|
||||
const p2 = this._fft(pall, bits-1, offset+step, step*2);
|
||||
|
||||
const out = new Array(n);
|
||||
|
||||
let m= bigInt(1);
|
||||
for (let i=0; i<ndiv2; i++) {
|
||||
out[i] = this.F.add(p1[i], this.F.mul(m, p2[i]));
|
||||
out[i+ndiv2] = this.F.sub(p1[i], this.F.mul(m, p2[i]));
|
||||
m = this.F.mul(m, this.w[bits]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
extend(p, e) {
|
||||
if (e == p.length) return p;
|
||||
const z = new Array(e-p.length).fill(this.F.zero);
|
||||
|
||||
return p.concat(z);
|
||||
}
|
||||
|
||||
reduce(p) {
|
||||
if (p.length == 0) return p;
|
||||
if (! this.F.isZero(p[p.length-1]) ) return p;
|
||||
let i=p.length-1;
|
||||
while( i>0 && this.F.isZero(p[i]) ) i--;
|
||||
return p.slice(0, i+1);
|
||||
}
|
||||
|
||||
affine(p) {
|
||||
for (let i=0; i<p.length; i++) {
|
||||
p[i] = this.F.affine(p[i]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
equals(a, b) {
|
||||
const pa = this.reduce(this.affine(a));
|
||||
const pb = this.reduce(this.affine(b));
|
||||
|
||||
if (pa.length != pb.length) return false;
|
||||
for (let i=0; i<pb.length; i++) {
|
||||
if (!this.F.equals(pa[i], pb[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_next2Power(v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
toString(p) {
|
||||
const ap = this.affine(p);
|
||||
let S = "";
|
||||
for (let i=ap.length-1; i>=0; i--) {
|
||||
if (!this.F.isZero(p[i])) {
|
||||
if (S!="") S += " + ";
|
||||
S = S + p[i].toString(10);
|
||||
if (i>0) {
|
||||
S = S + "x";
|
||||
if (i>1) {
|
||||
S = S + "^" +i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
_reciprocal(p, bits) {
|
||||
const k = 1 << bits;
|
||||
if (k==1) {
|
||||
return [ this.F.inverse(p[0]) ];
|
||||
}
|
||||
const np = this.scaleX(p, -k/2);
|
||||
const q = this._reciprocal(np, bits-1);
|
||||
const a = this.scaleX(this.double(q), 3*k/2-2);
|
||||
const b = this.mul( this.square(q), p);
|
||||
|
||||
return this.scaleX(this.sub(a,b), -(k-2));
|
||||
}
|
||||
|
||||
// divides x^m / v
|
||||
_div2(m, v) {
|
||||
const kbits = log2(v.length-1)+1;
|
||||
const k = 1 << kbits;
|
||||
|
||||
const scaleV = k - v.length;
|
||||
|
||||
// rec = x^(k - 2) / v* x^scaleV =>
|
||||
// rec = x^(k-2-scaleV)/ v
|
||||
//
|
||||
// res = x^m/v = x^(m + (2*k-2 - scaleV) - (2*k-2 - scaleV)) /v =>
|
||||
// res = rec * x^(m - (2*k-2 - scaleV)) =>
|
||||
// res = rec * x^(m - 2*k + 2 + scaleV)
|
||||
|
||||
const rec = this._reciprocal(this.scaleX(v, scaleV), kbits);
|
||||
const res = this.scaleX(rec, m - 2*k + 2 + scaleV);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
div(_u, _v) {
|
||||
if (_u.length < _v.length) return [];
|
||||
const kbits = log2(_v.length-1)+1;
|
||||
const k = 1 << kbits;
|
||||
|
||||
const u = this.scaleX(_u, k-_v.length);
|
||||
const v = this.scaleX(_v, k-_v.length);
|
||||
|
||||
const n = v.length-1;
|
||||
let m = u.length-1;
|
||||
|
||||
const s = this._reciprocal(v, kbits);
|
||||
let t;
|
||||
if (m>2*n) {
|
||||
t = this.sub(this.scaleX([bigInt(1)], 2*n), this.mul(s, v));
|
||||
}
|
||||
|
||||
let q = [];
|
||||
let rem = u;
|
||||
let us, ut;
|
||||
let finish = false;
|
||||
|
||||
while (!finish) {
|
||||
us = this.mul(rem, s);
|
||||
q = this.add(q, this.scaleX(us, -2*n));
|
||||
|
||||
if ( m > 2*n ) {
|
||||
ut = this.mul(rem, t);
|
||||
rem = this.scaleX(ut, -2*n);
|
||||
m = rem.length-1;
|
||||
} else {
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
module.exports = PolField;
|
||||
module.exports = PolFieldZq;
|
||||
|
@ -16,6 +16,8 @@ class ZqField {
|
||||
this.equals = bigInt.genEquals(q);
|
||||
this.affine = bigInt.genAffine(q);
|
||||
this.isZero = bigInt.genIsZero(q);
|
||||
this.two = this.add(this.one, this.one);
|
||||
this.twoinv = this.inverse(this.two);
|
||||
}
|
||||
|
||||
copy(a) {
|
||||
|
@ -154,7 +154,6 @@ describe("Pairing", () => {
|
||||
const g1b = bn128.G1.mulEscalar(bn128.G1.g, 30);
|
||||
const g2b = bn128.G2.mulEscalar(bn128.G2.g, 25);
|
||||
|
||||
|
||||
const pre1a = bn128.precomputeG1(g1a);
|
||||
const pre2a = bn128.precomputeG2(g2a);
|
||||
const pre1b = bn128.precomputeG1(g1b);
|
||||
|
107
test/pols.js
Normal file
107
test/pols.js
Normal file
@ -0,0 +1,107 @@
|
||||
const chai = require("chai");
|
||||
|
||||
const bigInt = require("../src/bigint.js");
|
||||
const PolField = require("../src/polfield.js");
|
||||
|
||||
const assert = chai.assert;
|
||||
|
||||
const r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
|
||||
describe("Polinomial field", () => {
|
||||
it("Should compute a multiplication", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(1), bigInt(2), bigInt(3)];
|
||||
const b = [bigInt(1), bigInt(2), bigInt(3)];
|
||||
const res = PF.mul(a,b);
|
||||
|
||||
assert(PF.equals(res, [bigInt(1), bigInt(4), bigInt(10), bigInt(12), bigInt(9)]));
|
||||
});
|
||||
it("Should compute a multiplication 2", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(5), bigInt(1)];
|
||||
const b = [bigInt(-5), bigInt(1)];
|
||||
const res = PF.mul(a,b);
|
||||
|
||||
assert(PF.equals(res, [bigInt(-25), bigInt(0), bigInt(1)]));
|
||||
});
|
||||
it("Should compute an addition", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(5), bigInt(1)];
|
||||
const b = [bigInt(-5), bigInt(1)];
|
||||
const res = PF.add(a,b);
|
||||
|
||||
assert(PF.equals(res, [bigInt(0), bigInt(2)]));
|
||||
});
|
||||
it("Should compute a substraction", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(5), bigInt(3), bigInt(4)];
|
||||
const b = [bigInt(5), bigInt(1)];
|
||||
const res = PF.sub(a,b);
|
||||
|
||||
assert(PF.equals(res, [bigInt(0), bigInt(2), bigInt(4)]));
|
||||
});
|
||||
it("Should compute reciprocal", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(4), bigInt(1), bigInt(-3), bigInt(-1), bigInt(2),bigInt(1), bigInt(-1), bigInt(1)];
|
||||
const res = PF._reciprocal(a, 3, 0);
|
||||
|
||||
assert(PF.equals(res, [bigInt(12), bigInt(15), bigInt(3), bigInt(-4), bigInt(-3), bigInt(0), bigInt(1), bigInt(1)]));
|
||||
});
|
||||
it("Should div2", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
// x^6
|
||||
const a = [bigInt(0), bigInt(0), bigInt(0), bigInt(0), bigInt(0),bigInt(0), bigInt(1)];
|
||||
// x^5
|
||||
const b = [bigInt(0), bigInt(0), bigInt(0), bigInt(0), bigInt(0), bigInt(1)];
|
||||
|
||||
const res = PF._div2(6, b);
|
||||
assert(PF.equals(res, [bigInt(0), bigInt(1)]));
|
||||
|
||||
const res2 = PF.div(a,b);
|
||||
assert(PF.equals(res2, [bigInt(0), bigInt(1)]));
|
||||
});
|
||||
it("Should div", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(1), bigInt(2), bigInt(3), bigInt(4), bigInt(5),bigInt(6), bigInt(7)];
|
||||
const b = [bigInt(8), bigInt(9), bigInt(10), bigInt(11), bigInt(12), bigInt(13)];
|
||||
|
||||
const c = PF.mul(a,b);
|
||||
const d = PF.div(c,b);
|
||||
|
||||
assert(PF.equals(a, d));
|
||||
});
|
||||
|
||||
it("Should div big/small", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [bigInt(1), bigInt(2), bigInt(3), bigInt(4), bigInt(5),bigInt(6), bigInt(7)];
|
||||
const b = [bigInt(8), bigInt(9)];
|
||||
|
||||
const c = PF.mul(a,b);
|
||||
const d = PF.div(c,b);
|
||||
|
||||
assert(PF.equals(a, d));
|
||||
});
|
||||
it("Should div random big", () => {
|
||||
const PF = new PolField(r);
|
||||
|
||||
const a = [];
|
||||
const b = [];
|
||||
for (let i=0; i<1000; i++) a.push(bigInt(Math.floor(Math.random()*100000) -500000));
|
||||
for (let i=0; i<300; i++) b.push(bigInt(Math.floor(Math.random()*100000) -500000));
|
||||
|
||||
const c = PF.mul(a,b);
|
||||
|
||||
const d = PF.div(c,b);
|
||||
|
||||
assert(PF.equals(a, d));
|
||||
}).timeout(10000000);
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user