From 6880305f2204b0c7c4fcfaba6bb146ffabd30952 Mon Sep 17 00:00:00 2001 From: Ivo Kubjas Date: Tue, 29 Oct 2024 21:01:28 +0000 Subject: [PATCH] xxx: simplify --- std/algebra/emulated/fields_bw6761/e6.go | 36 ++++---- .../emulated/fields_bw6761/e6_mul_sz.go | 6 +- .../emulated/fields_bw6761/e6_pairing.go | 28 +++---- std/math/emulated/element_test.go | 77 +++++++++-------- std/math/emulated/field_mul.go | 84 ++++++++----------- 5 files changed, 109 insertions(+), 122 deletions(-) diff --git a/std/algebra/emulated/fields_bw6761/e6.go b/std/algebra/emulated/fields_bw6761/e6.go index 8fd736b331..bc17f4611d 100644 --- a/std/algebra/emulated/fields_bw6761/e6.go +++ b/std/algebra/emulated/fields_bw6761/e6.go @@ -434,22 +434,22 @@ func (e Ext6) mulMontgomery6(x, y *E6) *E6 { func (e Ext6) mulDirect(x, y *E6) *E6 { nonResidue := e.fp.NewElement(-4) // c0 = a0b0 + β(a1b5 + a2b4 + a3b3 + a4b2 + a5b1) - c0 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A0}, {nonResidue, &x.A1, &y.A5}, {nonResidue, &x.A2, &y.A4}, {nonResidue, &x.A3, &y.A3}, {nonResidue, &x.A4, &y.A2}, {nonResidue, &x.A5, &y.A1}}, + c0 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A0}, {nonResidue, &x.A1, &y.A5}, {nonResidue, &x.A2, &y.A4}, {nonResidue, &x.A3, &y.A3}, {nonResidue, &x.A4, &y.A2}, {nonResidue, &x.A5, &y.A1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c1 = a0b1 + a1b0 + β(a2b5 + a3b4 + a4b3 + a5b2) - c1 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A1}, {&x.A1, &y.A0}, {nonResidue, &x.A2, &y.A5}, {nonResidue, &x.A3, &y.A4}, {nonResidue, &x.A4, &y.A3}, {nonResidue, &x.A5, &y.A2}}, + c1 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A1}, {&x.A1, &y.A0}, {nonResidue, &x.A2, &y.A5}, {nonResidue, &x.A3, &y.A4}, {nonResidue, &x.A4, &y.A3}, {nonResidue, &x.A5, &y.A2}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c2 = a0b2 + a1b1 + a2b0 + β(a3b5 + a4b4 + a5b3) - c2 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A2}, {&x.A1, &y.A1}, {&x.A2, &y.A0}, {nonResidue, &x.A3, &y.A5}, {nonResidue, &x.A4, &y.A4}, {nonResidue, &x.A5, &y.A3}}, + c2 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A2}, {&x.A1, &y.A1}, {&x.A2, &y.A0}, {nonResidue, &x.A3, &y.A5}, {nonResidue, &x.A4, &y.A4}, {nonResidue, &x.A5, &y.A3}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c3 = a0b3 + a1b2 + a2b1 + a3b0 + β(a4b5 + a5b4) - c3 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A3}, {&x.A1, &y.A2}, {&x.A2, &y.A1}, {&x.A3, &y.A0}, {nonResidue, &x.A4, &y.A5}, {nonResidue, &x.A5, &y.A4}}, + c3 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A3}, {&x.A1, &y.A2}, {&x.A2, &y.A1}, {&x.A3, &y.A0}, {nonResidue, &x.A4, &y.A5}, {nonResidue, &x.A5, &y.A4}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c4 = a0b4 + a1b3 + a2b2 + a3b1 + a4b0 + βa5b5 - c4 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A4}, {&x.A1, &y.A3}, {&x.A2, &y.A2}, {&x.A3, &y.A1}, {&x.A4, &y.A0}, {nonResidue, &x.A5, &y.A5}}, + c4 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A4}, {&x.A1, &y.A3}, {&x.A2, &y.A2}, {&x.A3, &y.A1}, {&x.A4, &y.A0}, {nonResidue, &x.A5, &y.A5}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c5 = a0b5 + a1b4 + a2b3 + a3b2 + a4b1 + a5b0, - c5 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &y.A5}, {&x.A1, &y.A4}, {&x.A2, &y.A3}, {&x.A3, &y.A2}, {&x.A4, &y.A1}, {&x.A5, &y.A0}}, + c5 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &y.A5}, {&x.A1, &y.A4}, {&x.A2, &y.A3}, {&x.A3, &y.A2}, {&x.A4, &y.A1}, {&x.A5, &y.A0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) return &E6{ @@ -742,22 +742,22 @@ func (e Ext6) mulToomCook6(x, y *E6) *E6 { func (e Ext6) squareDirect(x *E6) *E6 { nonResidue := e.fp.NewElement(-4) // c0 = a0b0 + β(a1b5 + a2b4 + a3b3 + a4b2 + a5b1) - c0 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A0}, {nonResidue, &x.A1, &x.A5}, {nonResidue, &x.A2, &x.A4}, {nonResidue, &x.A3, &x.A3}, {nonResidue, &x.A4, &x.A2}, {nonResidue, &x.A5, &x.A1}}, + c0 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A0}, {nonResidue, &x.A1, &x.A5}, {nonResidue, &x.A2, &x.A4}, {nonResidue, &x.A3, &x.A3}, {nonResidue, &x.A4, &x.A2}, {nonResidue, &x.A5, &x.A1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c1 = a0b1 + a1b0 + β(a2b5 + a3b4 + a4b3 + a5b2) - c1 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A1}, {&x.A1, &x.A0}, {nonResidue, &x.A2, &x.A5}, {nonResidue, &x.A3, &x.A4}, {nonResidue, &x.A4, &x.A3}, {nonResidue, &x.A5, &x.A2}}, + c1 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A1}, {&x.A1, &x.A0}, {nonResidue, &x.A2, &x.A5}, {nonResidue, &x.A3, &x.A4}, {nonResidue, &x.A4, &x.A3}, {nonResidue, &x.A5, &x.A2}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c2 = a0b2 + a1b1 + a2b0 + β(a3b5 + a4b4 + a5b3) - c2 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A2}, {&x.A1, &x.A1}, {&x.A2, &x.A0}, {nonResidue, &x.A3, &x.A5}, {nonResidue, &x.A4, &x.A4}, {nonResidue, &x.A5, &x.A3}}, + c2 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A2}, {&x.A1, &x.A1}, {&x.A2, &x.A0}, {nonResidue, &x.A3, &x.A5}, {nonResidue, &x.A4, &x.A4}, {nonResidue, &x.A5, &x.A3}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c3 = a0b3 + a1b2 + a2b1 + a3b0 + β(a4b5 + a5b4) - c3 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A3}, {&x.A1, &x.A2}, {&x.A2, &x.A1}, {&x.A3, &x.A0}, {nonResidue, &x.A4, &x.A5}, {nonResidue, &x.A5, &x.A4}}, + c3 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A3}, {&x.A1, &x.A2}, {&x.A2, &x.A1}, {&x.A3, &x.A0}, {nonResidue, &x.A4, &x.A5}, {nonResidue, &x.A5, &x.A4}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c4 = a0b4 + a1b3 + a2b2 + a3b1 + a4b0 + βa5b5 - c4 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A4}, {&x.A1, &x.A3}, {&x.A2, &x.A2}, {&x.A3, &x.A1}, {&x.A4, &x.A0}, {nonResidue, &x.A5, &x.A5}}, + c4 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A4}, {&x.A1, &x.A3}, {&x.A2, &x.A2}, {&x.A3, &x.A1}, {&x.A4, &x.A0}, {nonResidue, &x.A5, &x.A5}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c5 = a0b5 + a1b4 + a2b3 + a3b2 + a4b1 + a5b0, - c5 := e.fp.EvalMultivariate2([][]*baseEl{{&x.A0, &x.A5}, {&x.A1, &x.A4}, {&x.A2, &x.A3}, {&x.A3, &x.A2}, {&x.A4, &x.A1}, {&x.A5, &x.A0}}, + c5 := e.fp.EvalMultivariate([][]*baseEl{{&x.A0, &x.A5}, {&x.A1, &x.A4}, {&x.A2, &x.A3}, {&x.A3, &x.A2}, {&x.A4, &x.A1}, {&x.A5, &x.A0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) return &E6{ @@ -866,15 +866,15 @@ func (e Ext6) CyclotomicSquareKarabina12345Direct(x *E6) *E6 { g4 := x.A3 g5 := x.A5 // h1 = 3*c*g2^2 + 3*g3^2 - 2*g1 - h1 := e.fp.EvalMultivariate2([][]*baseEl{{c, &g2, &g2}, {&g3, &g3}, {mone, &g1}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(2)}) + h1 := e.fp.EvalMultivariate([][]*baseEl{{c, &g2, &g2}, {&g3, &g3}, {mone, &g1}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(2)}) // h2 = 3*c*g5^2 + 3*g1^2 - 2*g2 - h2 := e.fp.EvalMultivariate2([][]*baseEl{{c, &g5, &g5}, {&g1, &g1}, {mone, &g2}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(2)}) + h2 := e.fp.EvalMultivariate([][]*baseEl{{c, &g5, &g5}, {&g1, &g1}, {mone, &g2}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(2)}) // h3 = 6*c*g1*g5 + 2*g3 - h3 := e.fp.EvalMultivariate2([][]*baseEl{{c, &g1, &g5}, {&g3}}, []*big.Int{big.NewInt(6), big.NewInt(2)}) + h3 := e.fp.EvalMultivariate([][]*baseEl{{c, &g1, &g5}, {&g3}}, []*big.Int{big.NewInt(6), big.NewInt(2)}) // h4 = 3*c*g2*g5 + 3*g1*g3 - g4 - h4 := e.fp.EvalMultivariate2([][]*baseEl{{c, &g2, &g5}, {&g1, &g3}, {mone, &g4}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(1)}) + h4 := e.fp.EvalMultivariate([][]*baseEl{{c, &g2, &g5}, {&g1, &g3}, {mone, &g4}}, []*big.Int{big.NewInt(3), big.NewInt(3), big.NewInt(1)}) // h5 = 6*g2*g3 + 2*g5 - h5 := e.fp.EvalMultivariate2([][]*baseEl{{&g2, &g3}, {&g5}}, []*big.Int{big.NewInt(6), big.NewInt(2)}) + h5 := e.fp.EvalMultivariate([][]*baseEl{{&g2, &g3}, {&g5}}, []*big.Int{big.NewInt(6), big.NewInt(2)}) return &E6{ A0: x.A0, @@ -958,7 +958,7 @@ func (e Ext6) DecompressKarabina12345Direct(x *E6) *E6 { g4 := x.A3 g5 := x.A5 // h0 = -3*c*g1*g2 + 2*c*g4^2 + c*g3*g5 + 1 - h0 := e.fp.EvalMultivariate2([][]*baseEl{{mone, c, &g1, &g2}, {c, &g4, &g4}, {c, &g3, &g5}, {e.fp.One()}}, []*big.Int{big.NewInt(3), big.NewInt(2), big.NewInt(1), big.NewInt(1)}) + h0 := e.fp.EvalMultivariate([][]*baseEl{{mone, c, &g1, &g2}, {c, &g4, &g4}, {c, &g3, &g5}, {e.fp.One()}}, []*big.Int{big.NewInt(3), big.NewInt(2), big.NewInt(1), big.NewInt(1)}) return &E6{ A0: *h0, A1: g3, diff --git a/std/algebra/emulated/fields_bw6761/e6_mul_sz.go b/std/algebra/emulated/fields_bw6761/e6_mul_sz.go index 2cf4a05b81..f9ad1f5284 100644 --- a/std/algebra/emulated/fields_bw6761/e6_mul_sz.go +++ b/std/algebra/emulated/fields_bw6761/e6_mul_sz.go @@ -17,17 +17,17 @@ type e6mulCheck struct { func (mc *e6mulCheck) check(sapi *emulated.Field[emulated.BW6761Fp], rpowers []*baseEl, modEval *baseEl) { mone := sapi.NewElement(-1) // a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5 - ax := sapi.EvalMultivariate2([][]*baseEl{{&mc.A.A0}, {&mc.A.A1, rpowers[0]}, {&mc.A.A2, rpowers[1]}, {&mc.A.A3, rpowers[2]}, {&mc.A.A4, rpowers[3]}, {&mc.A.A5, rpowers[4]}}, + ax := sapi.EvalMultivariate([][]*baseEl{{&mc.A.A0}, {&mc.A.A1, rpowers[0]}, {&mc.A.A2, rpowers[1]}, {&mc.A.A3, rpowers[2]}, {&mc.A.A4, rpowers[3]}, {&mc.A.A5, rpowers[4]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) var bx *emulated.Element[emulated.BW6761Fp] if mc.A != mc.B { - bx = sapi.EvalMultivariate2([][]*baseEl{{&mc.B.A0}, {&mc.B.A1, rpowers[0]}, {&mc.B.A2, rpowers[1]}, {&mc.B.A3, rpowers[2]}, {&mc.B.A4, rpowers[3]}, {&mc.B.A5, rpowers[4]}}, + bx = sapi.EvalMultivariate([][]*baseEl{{&mc.B.A0}, {&mc.B.A1, rpowers[0]}, {&mc.B.A2, rpowers[1]}, {&mc.B.A3, rpowers[2]}, {&mc.B.A4, rpowers[3]}, {&mc.B.A5, rpowers[4]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) } else { bx = ax } // r0 + r1 x + r2 x^2 + r3 x^3 + r4 x^4 + r5 x^5 + q0 np + q1 x np + q2 x^2 np + q3 x^3 np + q4 x^4 np - ax0 bx0 - ax1 bx1 - ax2 bx2 - ax3 bx3 - ax4 bx4 - ax5 bx5 - rqnx := sapi.EvalMultivariate2([][]*baseEl{ + rqnx := sapi.EvalMultivariate([][]*baseEl{ {&mc.R.A0}, {&mc.R.A1, rpowers[0]}, {&mc.R.A2, rpowers[1]}, {&mc.R.A3, rpowers[2]}, {&mc.R.A4, rpowers[3]}, {&mc.R.A5, rpowers[4]}, {&mc.Q.A0, modEval}, {&mc.Q.A1, rpowers[0], modEval}, {&mc.Q.A2, rpowers[1], modEval}, {&mc.Q.A3, rpowers[2], modEval}, {&mc.Q.A4, rpowers[3], modEval}, {ax, bx, mone}, diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index 90670229c8..81c3e8e9fb 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -136,17 +136,17 @@ func (e Ext6) mulBy023Direct(z *E6, c0, c1 *baseEl) *E6 { // E6{A0: c0, A1: 0, A2: c1, A3: 1, A4: 0, A5: 0} // z0 = a0c0 + β(a3 + a4c1) - z0 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, c0}, {nonResidue, &z.A3}, {nonResidue, &z.A4, c1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z0 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, c0}, {nonResidue, &z.A3}, {nonResidue, &z.A4, c1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // z1 = a1c0 + β(a4 + a5c1) - z1 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A1, c0}, {nonResidue, &z.A4}, {nonResidue, &z.A5, c1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z1 := e.fp.EvalMultivariate([][]*baseEl{{&z.A1, c0}, {nonResidue, &z.A4}, {nonResidue, &z.A5, c1}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // z2 = a0c1 + a2c0 + β(a5) - z2 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, c1}, {&z.A2, c0}, {nonResidue, &z.A5}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z2 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, c1}, {&z.A2, c0}, {nonResidue, &z.A5}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c3 = a0 + a1c1 + a3c0 - z3 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0}, {&z.A1, c1}, {&z.A3, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z3 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0}, {&z.A1, c1}, {&z.A3, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c4 = a1 + a2c1 + a4c0 - z4 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A1}, {&z.A2, c1}, {&z.A4, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z4 := e.fp.EvalMultivariate([][]*baseEl{{&z.A1}, {&z.A2, c1}, {&z.A4, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c5 = a2 + a3c1 + a5c0, - z5 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A2}, {&z.A3, c1}, {&z.A5, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) + z5 := e.fp.EvalMultivariate([][]*baseEl{{&z.A2}, {&z.A3, c1}, {&z.A5, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)}) return &E6{ A0: *z0, @@ -232,9 +232,9 @@ func (e *Ext6) MulBy023(z *E6, c0, c1 *baseEl) *E6 { func (e Ext6) mul023by023Direct(d0, d1, c0, c1 *baseEl) [5]*baseEl { nonResidue := e.fp.NewElement(-4) // c0 = d0c0 + β - z0 := e.fp.EvalMultivariate2([][]*baseEl{{d0, c0}, {nonResidue}}, []*big.Int{big.NewInt(1), big.NewInt(1)}) + z0 := e.fp.EvalMultivariate([][]*baseEl{{d0, c0}, {nonResidue}}, []*big.Int{big.NewInt(1), big.NewInt(1)}) // c2 = d0c1 + d1c0 - z2 := e.fp.EvalMultivariate2([][]*baseEl{{d0, c1}, {d1, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1)}) + z2 := e.fp.EvalMultivariate([][]*baseEl{{d0, c1}, {d1, c0}}, []*big.Int{big.NewInt(1), big.NewInt(1)}) // c3 = d0 + c0 z3 := e.fp.Add(d0, c0) // c4 = d1c1 @@ -278,22 +278,22 @@ func (e Ext6) mulBy02345Direct(z *E6, x [5]*baseEl) *E6 { nonResidue := e.fp.NewElement(-4) // c0 = a0y0 + β(a1y4 + a2y3 + a3y2 + a4y1) - c0 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, x[0]}, {nonResidue, &z.A1, x[4]}, {nonResidue, &z.A2, x[3]}, {nonResidue, &z.A3, x[2]}, {nonResidue, &z.A4, x[1]}}, + c0 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, x[0]}, {nonResidue, &z.A1, x[4]}, {nonResidue, &z.A2, x[3]}, {nonResidue, &z.A3, x[2]}, {nonResidue, &z.A4, x[1]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c1 = a1y0 + β(a2y4 + a3y3 + a4y2 + a5y1) - c1 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A1, x[0]}, {nonResidue, &z.A2, x[4]}, {nonResidue, &z.A3, x[3]}, {nonResidue, &z.A4, x[2]}, {nonResidue, &z.A5, x[1]}}, + c1 := e.fp.EvalMultivariate([][]*baseEl{{&z.A1, x[0]}, {nonResidue, &z.A2, x[4]}, {nonResidue, &z.A3, x[3]}, {nonResidue, &z.A4, x[2]}, {nonResidue, &z.A5, x[1]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c2 = a0y1 + a2y0 + β(a3y4 + a4y3 + a5y2) - c2 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, x[1]}, {&z.A2, x[0]}, {nonResidue, &z.A3, x[4]}, {nonResidue, &z.A4, x[3]}, {nonResidue, &z.A5, x[2]}}, + c2 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, x[1]}, {&z.A2, x[0]}, {nonResidue, &z.A3, x[4]}, {nonResidue, &z.A4, x[3]}, {nonResidue, &z.A5, x[2]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c3 = a0y2 + a1y1 + a3y0 + β(a4y4 + a5y3) - c3 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, x[2]}, {&z.A1, x[1]}, {&z.A3, x[0]}, {nonResidue, &z.A4, x[4]}, {nonResidue, &z.A5, x[3]}}, + c3 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, x[2]}, {&z.A1, x[1]}, {&z.A3, x[0]}, {nonResidue, &z.A4, x[4]}, {nonResidue, &z.A5, x[3]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c4 = a0y3 + a1y2 + a2y1 + a4y0 + βa5y4 - c4 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, x[3]}, {&z.A1, x[2]}, {&z.A2, x[1]}, {&z.A4, x[0]}, {nonResidue, &z.A5, x[4]}}, + c4 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, x[3]}, {&z.A1, x[2]}, {&z.A2, x[1]}, {&z.A4, x[0]}, {nonResidue, &z.A5, x[4]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) // c5 = a0y4 + a1y3 + a2y2 + a3y1 + a5y0, - c5 := e.fp.EvalMultivariate2([][]*baseEl{{&z.A0, x[4]}, {&z.A1, x[3]}, {&z.A2, x[2]}, {&z.A3, x[1]}, {&z.A5, x[0]}}, + c5 := e.fp.EvalMultivariate([][]*baseEl{{&z.A0, x[4]}, {&z.A1, x[3]}, {&z.A2, x[2]}, {&z.A3, x[1]}, {&z.A5, x[0]}}, []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1), big.NewInt(1)}) return &E6{ diff --git a/std/math/emulated/element_test.go b/std/math/emulated/element_test.go index 083415c330..9e9f879358 100644 --- a/std/math/emulated/element_test.go +++ b/std/math/emulated/element_test.go @@ -1279,9 +1279,10 @@ func TestIsZeroEdgeCases(t *testing.T) { } type PolyEvalCircuit[T FieldParams] struct { - Inputs []Element[T] - Polynomial Multivariate[T] - Expected Element[T] + Inputs []Element[T] + Terms [][]int + Coeffs []*big.Int + Expected Element[T] } func (c *PolyEvalCircuit[T]) Define(api frontend.API) error { @@ -1289,19 +1290,23 @@ func (c *PolyEvalCircuit[T]) Define(api frontend.API) error { if err != nil { return err } - input := make([]*Element[T], len(c.Inputs)) - for i := range input { - input[i] = &c.Inputs[i] + terms := make([][]*Element[T], len(c.Terms)) + for i := range terms { + terms[i] = make([]*Element[T], len(c.Terms[i])) + for j := range terms[i] { + terms[i][j] = &c.Inputs[c.Terms[i][j]] + } } - res := f.evalMultivariate(&c.Polynomial, input) + res := f.EvalMultivariate(terms, c.Coeffs) f.AssertIsEqual(res, &c.Expected) return nil } type PolyEval2Circuit[T FieldParams] struct { - Inputs []Element[T] - Polynomial Multivariate[T] - Expected Element[T] + Inputs []Element[T] + Terms [][]int + Coeffs []*big.Int + Expected Element[T] } func (c *PolyEval2Circuit[T]) Define(api frontend.API) error { @@ -1309,15 +1314,13 @@ func (c *PolyEval2Circuit[T]) Define(api frontend.API) error { if err != nil { return err } - addTerms := make([]*Element[T], len(c.Polynomial.Terms)) - for i, term := range c.Polynomial.Terms { + addTerms := make([]*Element[T], len(c.Terms)) + for i, term := range c.Terms { termVal := f.One() - for j, exp := range term { - for k := 0; k < int(exp); k++ { - termVal = f.Mul(termVal, &c.Inputs[j]) - } + for j := range term { + termVal = f.Mul(termVal, &c.Inputs[term[j]]) } - addTerms[i] = f.MulConst(termVal, c.Polynomial.Coefficients[i]) + addTerms[i] = f.MulConst(termVal, c.Coeffs[i]) } res := f.Sum(addTerms...) @@ -1327,7 +1330,8 @@ func (c *PolyEval2Circuit[T]) Define(api frontend.API) error { type PolyEval3Circuit[T FieldParams] struct { Inputs []Element[T] - Polynomial Multivariate[T] + Terms [][]int + Coeffs []*big.Int Expected Element[T] withReduce bool } @@ -1337,15 +1341,13 @@ func (c *PolyEval3Circuit[T]) Define(api frontend.API) error { if err != nil { return err } - addTerms := make([]*Element[T], len(c.Polynomial.Terms)) - for i, term := range c.Polynomial.Terms { + addTerms := make([]*Element[T], len(c.Terms)) + for i, term := range c.Terms { termVal := f.One() - for j, exp := range term { - for k := 0; k < int(exp); k++ { - termVal = f.MulNoReduce(termVal, &c.Inputs[j]) - } + for j := range term { + termVal = f.MulNoReduce(termVal, &c.Inputs[term[j]]) } - addTerms[i] = f.MulConst(termVal, c.Polynomial.Coefficients[i]) + addTerms[i] = f.MulConst(termVal, c.Coeffs[i]) } res := f.Sum(addTerms...) @@ -1369,7 +1371,7 @@ func testPolyEval[T FieldParams](t *testing.T) { var fp T var err error // 2*x^3 + 3*x^2 y + 4*x y^2 + 5*y^3 - terms := [][]int{{3, 0}, {2, 1}, {1, 2}, {0, 3}} + terms := [][]int{{0, 0, 0}, {0, 0, 1}, {0, 1, 1}, {1, 1, 1}} coefficients := []*big.Int{big.NewInt(2), big.NewInt(3), big.NewInt(4), big.NewInt(5)} inputs := make([]*big.Int, nbInputs) assignmentInput := make([]Element[T], nbInputs) @@ -1381,33 +1383,30 @@ func testPolyEval[T FieldParams](t *testing.T) { assignmentInput[i] = ValueOf[T](inputs[i]) } expected := new(big.Int) - tmp := new(big.Int) for i, term := range terms { termVal := new(big.Int).Set(coefficients[i]) - for i, in := range inputs { - tmp.Exp(in, big.NewInt(int64(term[i])), fp.Modulus()) - termVal.Mul(termVal, tmp) + for j := range term { + termVal.Mul(termVal, inputs[term[j]]) } expected.Add(expected, termVal) } expected.Mod(expected, fp.Modulus()) - mv := ValueOfMultivariate[T](terms, coefficients) assignment := &PolyEvalCircuit[T]{ Inputs: assignmentInput, Expected: ValueOf[T](expected), } - err = test.IsSolved(&PolyEvalCircuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}, assignment, testCurve.ScalarField()) + err = test.IsSolved(&PolyEvalCircuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}, assignment, testCurve.ScalarField()) assert.NoError(err) - err = test.IsSolved(&PolyEval2Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}, assignment, testCurve.ScalarField()) + err = test.IsSolved(&PolyEval2Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}, assignment, testCurve.ScalarField()) assert.NoError(err) - err = test.IsSolved(&PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}, assignment, testCurve.ScalarField()) + err = test.IsSolved(&PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}, assignment, testCurve.ScalarField()) assert.NoError(err) - err = test.IsSolved(&PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv, withReduce: true}, assignment, testCurve.ScalarField()) + err = test.IsSolved(&PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients, withReduce: true}, assignment, testCurve.ScalarField()) assert.NoError(err) - frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEvalCircuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}) - frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval2Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}) - frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv}) - frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Polynomial: mv, withReduce: true}) + frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEvalCircuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}) + frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval2Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}) + frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients}) + frontend.Compile(testCurve.ScalarField(), scs.NewBuilder, &PolyEval3Circuit[T]{Inputs: make([]Element[T], nbInputs), Terms: terms, Coeffs: coefficients, withReduce: true}) } diff --git a/std/math/emulated/field_mul.go b/std/math/emulated/field_mul.go index 00664884a9..df8d09f408 100644 --- a/std/math/emulated/field_mul.go +++ b/std/math/emulated/field_mul.go @@ -517,59 +517,21 @@ func (f *Field[T]) Exp(base, exp *Element[T]) *Element[T] { return res } -// Multivariate represents a multivariate polynomial. It is a list of terms +// multivariate represents a multivariate polynomial. It is a list of terms // where each term is a list of exponents for each variable. The coefficients // are stored in the same order as the terms. -// -// TODO: better to move this to package. But this needs refactoring to allow for -// initializing the elements. -type Multivariate[T FieldParams] struct { +type multivariate[T FieldParams] struct { Terms [][]int Coefficients []*big.Int } -func ValueOfMultivariate[T FieldParams](terms [][]int, coeffs []*big.Int) Multivariate[T] { - if len(terms) != len(coeffs) { - panic("terms and coefficients mismatch") - } - return Multivariate[T]{Terms: terms, Coefficients: coeffs} -} - -func (f *Field[T]) evalMultivariate(mv *Multivariate[T], at []*Element[T]) *Element[T] { - if len(mv.Terms) != len(mv.Coefficients) { +func (f *Field[T]) EvalMultivariate(at [][]*Element[T], coefs []*big.Int) *Element[T] { + if len(at) != len(coefs) { panic("terms and coefficients mismatch") } - if len(mv.Terms) == 0 { + if len(at) == 0 { return f.Zero() } - nbVars := len(at) - for i := range mv.Terms { - if len(mv.Terms[i]) != nbVars { - panic("term and variable mismatch") - } - } - for i := range at { - f.enforceWidthConditional(at[i]) - } - k, r, c, err := f.callPolyHint(mv, at) - if err != nil { - panic(err) - } - - mvc := mvCheck[T]{ - f: f, - mv: mv, - vals: at, - r: r, - k: k, - c: c, - } - - f.deferredChecks = append(f.deferredChecks, &mvc) - return r -} - -func (f *Field[T]) EvalMultivariate2(at [][]*Element[T], coefs []*big.Int) *Element[T] { // initialize the multivariate struct from the inputs // it would be easier to use a map to store the elements and then use the @@ -595,11 +557,37 @@ func (f *Field[T]) EvalMultivariate2(at [][]*Element[T], coefs []*big.Int) *Elem } terms = append(terms, term) } - mv := ValueOfMultivariate[T](terms, coefs) - return f.evalMultivariate(&mv, allElems) + + // ensure that all the elements have the range checks enforced on limbs. + // Necessary in case the input is a witness. + for i := range allElems { + f.enforceWidthConditional(allElems[i]) + } + + mv := &multivariate[T]{ + Terms: terms, + Coefficients: coefs, + } + + k, r, c, err := f.callPolyHint(mv, allElems) + if err != nil { + panic(err) + } + + mvc := mvCheck[T]{ + f: f, + mv: mv, + vals: allElems, + r: r, + k: k, + c: c, + } + + f.deferredChecks = append(f.deferredChecks, &mvc) + return r } -func (f *Field[T]) callPolyHint(mv *Multivariate[T], at []*Element[T]) (quo, rem, carries *Element[T], err error) { +func (f *Field[T]) callPolyHint(mv *multivariate[T], at []*Element[T]) (quo, rem, carries *Element[T], err error) { // first compute the length of the result so that we know how many bits we need for the quotient. nbLimbs, nbBits := f.fParams.NbLimbs(), f.fParams.BitsPerLimb() modBits := uint(f.fParams.Modulus().BitLen()) @@ -643,7 +631,7 @@ func (f *Field[T]) callPolyHint(mv *Multivariate[T], at []*Element[T]) (quo, rem type mvCheck[T FieldParams] struct { f *Field[T] - mv *Multivariate[T] + mv *multivariate[T] vals []*Element[T] r *Element[T] // reduced result k *Element[T] // quotient @@ -707,7 +695,7 @@ func (mc *mvCheck[T]) cleanEvaluations() { mc.c.isEvaluated = false } -func (f *Field[T]) polyEvalQuoSize(mv *Multivariate[T], at []*Element[T]) (quoSize uint) { +func (f *Field[T]) polyEvalQuoSize(mv *multivariate[T], at []*Element[T]) (quoSize uint) { modBits := f.fParams.Modulus().BitLen() quoSizes := make([]uint, len(mv.Terms)) for i, term := range mv.Terms {