Skip to content

Commit

Permalink
Merge pull request #1077 from shramee/faster-fq6-01
Browse files Browse the repository at this point in the history
Faster cubic 012 mul 01
  • Loading branch information
yelhousni committed Mar 11, 2024
2 parents 2e80e8a + a485ada commit 732620b
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 39 deletions.
Binary file modified internal/stats/latest.stats
Binary file not shown.
7 changes: 4 additions & 3 deletions std/algebra/emulated/fields_bls12381/e6.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,10 @@ func (e Ext6) MulBy01(z *E6, c0, c1 *E2) *E6 {
t0 = e.Ext2.Sub(t0, b)
t0 = e.Ext2.MulByNonResidue(t0)
t0 = e.Ext2.Add(t0, a)
tmp = e.Ext2.Add(&z.B0, &z.B2)
t2 := e.Ext2.Mul(c0, tmp)
t2 = e.Ext2.Sub(t2, a)
// for t2, schoolbook is faster than karatsuba
// c2 = a0b2 + a1b1 + a2b0,
// c2 = a2b0 + b ∵ b2 = 0, b = a1b1
t2 := e.Ext2.Mul(&z.B2, c0)
t2 = e.Ext2.Add(t2, b)
t1 := e.Ext2.Add(c0, c1)
tmp = e.Ext2.Add(&z.B0, &z.B1)
Expand Down
7 changes: 4 additions & 3 deletions std/algebra/emulated/fields_bn254/e6.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ func (e Ext6) MulBy01(z *E6, c0, c1 *E2) *E6 {
t0 = e.Ext2.Sub(t0, b)
t0 = e.Ext2.MulByNonResidue(t0)
t0 = e.Ext2.Add(t0, a)
tmp = e.Ext2.Add(&z.B0, &z.B2)
t2 := e.Ext2.Mul(c0, tmp)
t2 = e.Ext2.Sub(t2, a)
// for t2, schoolbook is faster than karatsuba
// c2 = a0b2 + a1b1 + a2b0,
// c2 = a2b0 + b ∵ b2 = 0, b = a1b1
t2 := e.Ext2.Mul(&z.B2, c0)
t2 = e.Ext2.Add(t2, b)
t1 := e.Ext2.Add(c0, c1)
tmp = e.Ext2.Add(&z.B0, &z.B1)
Expand Down
7 changes: 4 additions & 3 deletions std/algebra/emulated/fields_bw6761/e3.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ func (e Ext3) MulBy01(z *E3, c0, c1 *baseEl) *E3 {
t0 = e.fp.MulConst(t0, big.NewInt(4))
t0 = e.fp.Add(t0, a)

tmp = e.fp.Add(&z.A0, &z.A2)
t2 := e.fp.Mul(c0, tmp)
t2 = e.fp.Sub(t2, a)
// for t2, schoolbook is faster than karatsuba
// c2 = a0b2 + a1b1 + a2b0,
// c2 = a2b0 + b ∵ b2 = 0, b = a1b1
t2 := e.fp.Mul(&z.A2, c0)
t2 = e.fp.Add(t2, b)

t1 := e.fp.Add(c0, c1)
Expand Down
7 changes: 4 additions & 3 deletions std/algebra/native/fields_bls12377/e6.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,10 @@ func (e *E6) MulBy01(api frontend.API, c0, c1 E2) *E6 {
t0.MulByNonResidue(api, t0)
t0.Add(api, t0, a)

tmp.Add(api, e.B0, e.B2)
t2.Mul(api, c0, tmp)
t2.Sub(api, t2, a)
// for t2, schoolbook is faster than karatsuba
// c2 = a0b2 + a1b1 + a2b0,
// c2 = a2b0 + b ∵ b2 = 0, b = a1b1
t2.Mul(api, e.B2, c0)
t2.Add(api, t2, b)

t1.Add(api, c0, c1)
Expand Down
40 changes: 16 additions & 24 deletions std/algebra/native/fields_bls12377/e6_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,43 +122,35 @@ func TestMulFp6(t *testing.T) {
assert.CheckCircuit(&circuit, test.WithValidAssignment(&witness), test.WithCurves(ecc.BW6_761))
}

type e6Mul01By01 struct {
A0, A1 E2
B0, B1 E2
type fp6MulBy01 struct {
A E6
C0, C1 E2
C E6 `gnark:",public"`
}

func (circuit *e6Mul01By01) Define(api frontend.API) error {
expected := *Mul01By01(api, circuit.A0, circuit.A1, circuit.B0, circuit.B1)
func (circuit *fp6MulBy01) Define(api frontend.API) error {
expected := circuit.A
expected.MulBy01(api, circuit.C0, circuit.C1)
expected.AssertIsEqual(api, circuit.C)

return nil
}

func TestMul01By01(t *testing.T) {
func TestMulFp6By01(t *testing.T) {

// we test our new E3.Mul01By01 against E3.MulBy01
var circuit, witness e6Mul01By01
var circuit, witness fp6MulBy01
// witness values
var a, c bls12377.E6
var A0, A1, B0, B1 bls12377.E2
_, _ = A0.SetRandom()
_, _ = A1.SetRandom()
_, _ = B0.SetRandom()
_, _ = B1.SetRandom()
// build a 01 sparse E3 with,
// first two elements as A1 and A2,
// and the third as 0
a.B0 = A0
a.B1 = A1
a.B2.SetZero()
var C0, C1 bls12377.E2
_, _ = a.SetRandom()
_, _ = C0.SetRandom()
_, _ = C1.SetRandom()
c.Set(&a)
c.MulBy01(&B0, &B1)
c.MulBy01(&C0, &C1)

witness.A0.Assign(&A0)
witness.A1.Assign(&A1)
witness.B0.Assign(&B0)
witness.B1.Assign(&B1)
witness.A.Assign(&a)
witness.C0.Assign(&C0)
witness.C1.Assign(&C1)
witness.C.Assign(&c)

assert := test.NewAssert(t)
Expand Down
7 changes: 4 additions & 3 deletions std/algebra/native/fields_bls24315/e12.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,10 @@ func (e *E12) MulBy01(api frontend.API, c0, c1 E4) *E12 {
t0.MulByNonResidue(api, t0)
t0.Add(api, t0, a)

tmp.Add(api, e.C0, e.C2)
t2.Mul(api, c0, tmp)
t2.Sub(api, t2, a)
// for t2, schoolbook is faster than karatsuba
// c2 = a0b2 + a1b1 + a2b0,
// c2 = a2b0 + b ∵ b2 = 0, b = a1b1
t2.Mul(api, e.C2, c0)
t2.Add(api, t2, b)

t1.Add(api, c0, c1)
Expand Down
36 changes: 36 additions & 0 deletions std/algebra/native/fields_bls24315/e12_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,42 @@ func TestMulFp12(t *testing.T) {
assert.CheckCircuit(&circuit, test.WithValidAssignment(&witness), test.WithCurves(ecc.BW6_633))
}

type fp12MulBy01 struct {
A E12
C0, C1 E4
C E12 `gnark:",public"`
}

func (circuit *fp12MulBy01) Define(api frontend.API) error {
expected := circuit.A
expected.MulBy01(api, circuit.C0, circuit.C1)
expected.AssertIsEqual(api, circuit.C)

return nil
}

func TestMulFp12By01(t *testing.T) {

var circuit, witness fp12MulBy01
// witness values
var a, c bls24315.E12
var C0, C1 bls24315.E4
_, _ = a.SetRandom()
_, _ = C0.SetRandom()
_, _ = C1.SetRandom()
c.Set(&a)
c.MulBy01(&C0, &C1)

witness.A.Assign(&a)
witness.C0.Assign(&C0)
witness.C1.Assign(&C1)
witness.C.Assign(&c)

assert := test.NewAssert(t)
assert.CheckCircuit(&circuit, test.WithValidAssignment(&witness), test.WithCurves(ecc.BW6_633))

}

type fp12MulByNonResidue struct {
A E12
C E12 `gnark:",public"`
Expand Down

0 comments on commit 732620b

Please sign in to comment.