arnaucube
arnaucube/snarkjsPublic Self-hosted repository
snarkjs/src/f2field.js
src/f2field.jsRaw
  1const fUtils = require("./futils.js");
  2
  3class F2Field {
  4    constructor(F, nonResidue) {
  5        this.F = F;
  6        this.zero = [this.F.zero, this.F.zero];
  7        this.one = [this.F.one, this.F.zero];
  8        this.nonResidue = nonResidue;
  9    }
 10
 11    _mulByNonResidue(a) {
 12        return this.F.mul(this.nonResidue, a);
 13    }
 14
 15    copy(a) {
 16        return [this.F.copy(a[0]), this.F.copy(a[1])];
 17    }
 18
 19    add(a, b) {
 20        return [
 21            this.F.add(a[0], b[0]),
 22            this.F.add(a[1], b[1])
 23        ];
 24    }
 25
 26    double(a) {
 27        return this.add(a,a);
 28    }
 29
 30    sub(a, b) {
 31        return [
 32            this.F.sub(a[0], b[0]),
 33            this.F.sub(a[1], b[1])
 34        ];
 35    }
 36
 37    neg(a) {
 38        return this.sub(this.zero, a);
 39    }
 40
 41    mul(a, b) {
 42        const aA = this.F.mul(a[0] , b[0]);
 43        const bB = this.F.mul(a[1] , b[1]);
 44
 45        return [
 46            this.F.add( aA , this._mulByNonResidue(bB)),
 47            this.F.sub(
 48                this.F.mul(
 49                    this.F.add(a[0], a[1]),
 50                    this.F.add(b[0], b[1])),
 51                this.F.add(aA, bB))];
 52    }
 53
 54    inverse(a) {
 55        const t0 = this.F.square(a[0]);
 56        const t1 = this.F.square(a[1]);
 57        const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
 58        const t3 = this.F.inverse(t2);
 59        return [
 60            this.F.mul(a[0], t3),
 61            this.F.neg(this.F.mul( a[1], t3)) ];
 62    }
 63
 64    div(a, b) {
 65        return this.mul(a, this.inverse(b));
 66    }
 67
 68    square(a) {
 69        const ab = this.F.mul(a[0] , a[1]);
 70
 71        /*
 72        [
 73            (a + b) * (a + non_residue * b) - ab - non_residue * ab,
 74            ab + ab
 75        ];
 76        */
 77
 78        return [
 79            this.F.sub(
 80                this.F.mul(
 81                    this.F.add(a[0], a[1]) ,
 82                    this.F.add(
 83                        a[0] ,
 84                        this._mulByNonResidue(a[1]))),
 85                this.F.add(
 86                    ab,
 87                    this._mulByNonResidue(ab))),
 88            this.F.add(ab, ab)
 89        ];
 90    }
 91
 92    isZero(a) {
 93        return this.F.isZero(a[0]) && this.F.isZero(a[1]);
 94    }
 95
 96    equals(a, b) {
 97        return this.F.equals(a[0], b[0]) && this.F.equals(a[1], b[1]);
 98    }
 99
100    affine(a) {
101        return [this.F.affine(a[0]), this.F.affine(a[1])];
102    }
103
104    mulEscalar(base, e) {
105        return fUtils.mulEscalar(this, base, e);
106    }
107
108    exp(base, e) {
109        return fUtils.exp(this, base, e);
110    }
111
112    toString(a) {
113        const cp = this.affine(a);
114        return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
115    }
116}
117
118module.exports = F2Field;