From 0a939b14f2825053699530f8a82f879126e3e350 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Sat, 28 Sep 2024 14:00:58 +0000 Subject: [PATCH] test: add more tests for vector ops --- ecc/bls12-377/fp/vector_test.go | 96 ++++--- ecc/bls12-377/fr/element_ops_amd64.go | 6 +- ecc/bls12-377/fr/element_ops_amd64.s | 2 +- ecc/bls12-377/fr/vector_test.go | 96 ++++--- ecc/bls12-381/fp/vector_test.go | 96 ++++--- ecc/bls12-381/fr/element_ops_amd64.go | 6 +- ecc/bls12-381/fr/element_ops_amd64.s | 2 +- ecc/bls12-381/fr/vector_test.go | 96 ++++--- ecc/bls24-315/fp/vector_test.go | 96 ++++--- ecc/bls24-315/fr/element_ops_amd64.go | 6 +- ecc/bls24-315/fr/element_ops_amd64.s | 2 +- ecc/bls24-315/fr/vector_test.go | 96 ++++--- ecc/bls24-317/fp/vector_test.go | 96 ++++--- ecc/bls24-317/fr/element_ops_amd64.go | 6 +- ecc/bls24-317/fr/element_ops_amd64.s | 2 +- ecc/bls24-317/fr/vector_test.go | 96 ++++--- ecc/bn254/fp/element_ops_amd64.go | 6 +- ecc/bn254/fp/element_ops_amd64.s | 2 +- ecc/bn254/fp/vector_test.go | 96 ++++--- ecc/bn254/fr/element_ops_amd64.go | 6 +- ecc/bn254/fr/element_ops_amd64.s | 2 +- ecc/bn254/fr/vector_test.go | 96 ++++--- ecc/bw6-633/fp/vector_test.go | 96 ++++--- ecc/bw6-633/fr/vector_test.go | 96 ++++--- ecc/bw6-761/fp/vector_test.go | 96 ++++--- ecc/bw6-761/fr/vector_test.go | 96 ++++--- ecc/secp256k1/fp/vector_test.go | 96 ++++--- ecc/secp256k1/fr/vector_test.go | 96 ++++--- ecc/stark-curve/fp/element_ops_amd64.go | 6 +- ecc/stark-curve/fp/element_ops_amd64.s | 2 +- ecc/stark-curve/fp/vector_test.go | 96 ++++--- ecc/stark-curve/fr/element_ops_amd64.go | 6 +- ecc/stark-curve/fr/element_ops_amd64.s | 2 +- ecc/stark-curve/fr/vector_test.go | 96 ++++--- field/asm/vector_4w_amd64.s | 20 +- field/generator/asm/amd64/element_vec.go | 240 ++++++++++++------ .../internal/templates/element/ops_asm.go | 6 +- .../templates/element/tests_vector.go | 99 +++++--- field/goldilocks/vector_test.go | 96 ++++--- 39 files changed, 1508 insertions(+), 745 deletions(-) diff --git a/ecc/bls12-377/fp/vector_test.go b/ecc/bls12-377/fp/vector_test.go index a7586a378..5c4e3a6c3 100644 --- a/ecc/bls12-377/fp/vector_test.go +++ b/ecc/bls12-377/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls12-377/fr/element_ops_amd64.go b/ecc/bls12-377/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/bls12-377/fr/element_ops_amd64.go +++ b/ecc/bls12-377/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bls12-377/fr/element_ops_amd64.s b/ecc/bls12-377/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bls12-377/fr/element_ops_amd64.s +++ b/ecc/bls12-377/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bls12-377/fr/vector_test.go b/ecc/bls12-377/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/bls12-377/fr/vector_test.go +++ b/ecc/bls12-377/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls12-381/fp/vector_test.go b/ecc/bls12-381/fp/vector_test.go index a7586a378..5c4e3a6c3 100644 --- a/ecc/bls12-381/fp/vector_test.go +++ b/ecc/bls12-381/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls12-381/fr/element_ops_amd64.go b/ecc/bls12-381/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/bls12-381/fr/element_ops_amd64.go +++ b/ecc/bls12-381/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bls12-381/fr/element_ops_amd64.s b/ecc/bls12-381/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bls12-381/fr/element_ops_amd64.s +++ b/ecc/bls12-381/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bls12-381/fr/vector_test.go b/ecc/bls12-381/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/bls12-381/fr/vector_test.go +++ b/ecc/bls12-381/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls24-315/fp/vector_test.go b/ecc/bls24-315/fp/vector_test.go index 217f02f2b..6236eafee 100644 --- a/ecc/bls24-315/fp/vector_test.go +++ b/ecc/bls24-315/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls24-315/fr/element_ops_amd64.go b/ecc/bls24-315/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/bls24-315/fr/element_ops_amd64.go +++ b/ecc/bls24-315/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bls24-315/fr/element_ops_amd64.s b/ecc/bls24-315/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bls24-315/fr/element_ops_amd64.s +++ b/ecc/bls24-315/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bls24-315/fr/vector_test.go b/ecc/bls24-315/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/bls24-315/fr/vector_test.go +++ b/ecc/bls24-315/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls24-317/fp/vector_test.go b/ecc/bls24-317/fp/vector_test.go index 217f02f2b..6236eafee 100644 --- a/ecc/bls24-317/fp/vector_test.go +++ b/ecc/bls24-317/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bls24-317/fr/element_ops_amd64.go b/ecc/bls24-317/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/bls24-317/fr/element_ops_amd64.go +++ b/ecc/bls24-317/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bls24-317/fr/element_ops_amd64.s b/ecc/bls24-317/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bls24-317/fr/element_ops_amd64.s +++ b/ecc/bls24-317/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bls24-317/fr/vector_test.go b/ecc/bls24-317/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/bls24-317/fr/vector_test.go +++ b/ecc/bls24-317/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bn254/fp/element_ops_amd64.go b/ecc/bn254/fp/element_ops_amd64.go index 42f1f461e..8f909cd0f 100644 --- a/ecc/bn254/fp/element_ops_amd64.go +++ b/ecc/bn254/fp/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bn254/fp/element_ops_amd64.s b/ecc/bn254/fp/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bn254/fp/element_ops_amd64.s +++ b/ecc/bn254/fp/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bn254/fp/vector_test.go b/ecc/bn254/fp/vector_test.go index 987fb25da..655f88692 100644 --- a/ecc/bn254/fp/vector_test.go +++ b/ecc/bn254/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bn254/fr/element_ops_amd64.go b/ecc/bn254/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/bn254/fr/element_ops_amd64.go +++ b/ecc/bn254/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/bn254/fr/element_ops_amd64.s b/ecc/bn254/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/bn254/fr/element_ops_amd64.s +++ b/ecc/bn254/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/bn254/fr/vector_test.go b/ecc/bn254/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/bn254/fr/vector_test.go +++ b/ecc/bn254/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bw6-633/fp/vector_test.go b/ecc/bw6-633/fp/vector_test.go index ec408df28..c6dd6cfd1 100644 --- a/ecc/bw6-633/fp/vector_test.go +++ b/ecc/bw6-633/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bw6-633/fr/vector_test.go b/ecc/bw6-633/fr/vector_test.go index 18d1af1f3..415a8b490 100644 --- a/ecc/bw6-633/fr/vector_test.go +++ b/ecc/bw6-633/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bw6-761/fp/vector_test.go b/ecc/bw6-761/fp/vector_test.go index e104e22a4..1daa1dca4 100644 --- a/ecc/bw6-761/fp/vector_test.go +++ b/ecc/bw6-761/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/bw6-761/fr/vector_test.go b/ecc/bw6-761/fr/vector_test.go index f9d9077ef..0cf7bb0b9 100644 --- a/ecc/bw6-761/fr/vector_test.go +++ b/ecc/bw6-761/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/secp256k1/fp/vector_test.go b/ecc/secp256k1/fp/vector_test.go index 987fb25da..655f88692 100644 --- a/ecc/secp256k1/fp/vector_test.go +++ b/ecc/secp256k1/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/secp256k1/fr/vector_test.go b/ecc/secp256k1/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/secp256k1/fr/vector_test.go +++ b/ecc/secp256k1/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/stark-curve/fp/element_ops_amd64.go b/ecc/stark-curve/fp/element_ops_amd64.go index 42f1f461e..8f909cd0f 100644 --- a/ecc/stark-curve/fp/element_ops_amd64.go +++ b/ecc/stark-curve/fp/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/stark-curve/fp/element_ops_amd64.s b/ecc/stark-curve/fp/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/stark-curve/fp/element_ops_amd64.s +++ b/ecc/stark-curve/fp/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/stark-curve/fp/vector_test.go b/ecc/stark-curve/fp/vector_test.go index 987fb25da..655f88692 100644 --- a/ecc/stark-curve/fp/vector_test.go +++ b/ecc/stark-curve/fp/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/ecc/stark-curve/fr/element_ops_amd64.go b/ecc/stark-curve/fr/element_ops_amd64.go index 77573a1ea..e79066cd4 100644 --- a/ecc/stark-curve/fr/element_ops_amd64.go +++ b/ecc/stark-curve/fr/element_ops_amd64.go @@ -102,7 +102,7 @@ func (vector *Vector) Sum() (res Element) { func sumVec(res *Element, a *Element, n uint64) //go:noescape -func innerProdVec(res *Element, a, b *Element, n uint64) +func innerProdVec(res *uint64, a, b *Element, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -114,14 +114,14 @@ func (vector *Vector) InnerProduct(other Vector) (res Element) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16 * 7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/ecc/stark-curve/fr/element_ops_amd64.s b/ecc/stark-curve/fr/element_ops_amd64.s index 01814b7bc..3ef8676bb 100644 --- a/ecc/stark-curve/fr/element_ops_amd64.s +++ b/ecc/stark-curve/fr/element_ops_amd64.s @@ -5,6 +5,6 @@ #include "../../../field/asm/element_4w_amd64.s" // Code generated by gnark-crypto/generator. DO NOT EDIT. -// We include the hash to force the Go compiler to recompile: 16788540410342696950 +// We include the hash to force the Go compiler to recompile: 7023651991118674373 #include "../../../field/asm/vector_4w_amd64.s" diff --git a/ecc/stark-curve/fr/vector_test.go b/ecc/stark-curve/fr/vector_test.go index 396187eac..f230cab99 100644 --- a/ecc/stark-curve/fr/vector_test.go +++ b/ecc/stark-curve/fr/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/field/asm/vector_4w_amd64.s b/field/asm/vector_4w_amd64.s index 87a2eee69..b97a1cf55 100644 --- a/field/asm/vector_4w_amd64.s +++ b/field/asm/vector_4w_amd64.s @@ -632,10 +632,12 @@ TEXT ·innerProdVec(SB), NOSPLIT, $0-32 JEQ done_14 // n == 0, we are done loop_13: - TESTQ CX, CX - JEQ accumulate_15 // n == 0 we can accumulate - VPMOVZXDQ (R15), Z4 - ADDQ $32, R15 + TESTQ CX, CX + JEQ accumulate_15 // n == 0 we can accumulate + VPMOVZXDQ (R15), Z4 + ADDQ $32, R15 + + // we multiply and accumulate partial products of 4 bytes * 32 bytes VPMULUDQ.BCST 0*4(R14), Z4, Z2 VPSRLQ $32, Z2, Z3 VPANDQ Z5, Z2, Z2 @@ -681,10 +683,12 @@ loop_13: JMP loop_13 accumulate_15: - MOVQ $0x0000000000001555, AX - KMOVD AX, K1 - MOVQ $1, AX - KMOVD AX, K2 + MOVQ $0x0000000000001555, AX + KMOVD AX, K1 + MOVQ $1, AX + KMOVD AX, K2 + + // store the least significant 32 bits of ACC (starts with A0L) in Z0 VALIGND.Z $16, Z16, Z16, K2, Z0 KSHIFTLW $1, K2, K2 VPSRLQ $32, Z16, Z2 diff --git a/field/generator/asm/amd64/element_vec.go b/field/generator/asm/amd64/element_vec.go index f25d86a66..415208b8b 100644 --- a/field/generator/asm/amd64/element_vec.go +++ b/field/generator/asm/amd64/element_vec.go @@ -621,6 +621,8 @@ func (f *FFAmd64) generateInnerProduct() { f.ADDQ("$32", PY) + f.Comment("we multiply and accumulate partial products of 4 bytes * 32 bytes") + f.VPMULUDQ_BCST("0*4("+PX+")", Y, PPL) f.VPSRLQ("$32", PPL, PPH) f.VPANDQ(LSW, PPL, PPL) @@ -678,24 +680,6 @@ func (f *FFAmd64) generateInnerProduct() { f.LABEL(AddPP) - // we have - // r0 = A0L + lo32(A0H)<<32 - // r1 = hi32(A0H)>>32 + A1L + lo32(A1H)<<32 - // r2 = hi32(A1H)>>32 + A2L + lo32(A2H)<<32 - // r3 = hi32(A2H)>>32 + A3L + lo32(A3H)<<32 - // r4 = hi32(A3H)>>32 + A4L + lo32(A4H)<<32 - // r5 = hi32(A4H)>>32 + A5L + lo32(A5H)<<32 - // r6 = hi32(A5H)>>32 + A6L + lo32(A6H)<<32 - // r7 = hi32(A6H)>>32 + A7L + lo32(A7H)<<32 - // r8 = hi32(A7H)>>32 - - var r [8]amd64.Register - for i := 0; i < 8; i++ { - r[i] = f.Pop(®isters) - } - - // Load mask register values - f.MOVQ(uint64(0x1555), amd64.AX) f.KMOVD(amd64.AX, "K1") @@ -704,23 +688,10 @@ func (f *FFAmd64) generateInnerProduct() { // ACC starts with the value of A0L - f.VALIGND_Z("$16", ACC, ACC, "K2", "Z0") // Store least significant 32 bits of ACC + f.Comment("store the least significant 32 bits of ACC (starts with A0L) in Z0") + f.VALIGND_Z("$16", ACC, ACC, "K2", "Z0") f.KSHIFTLW("$1", "K2", "K2") - // vpsrlq $32, ACC, PPL - // valignd $2, ACC, ACC, ACC{%k1}{z} - // vpaddq PPL, ACC, ACC - - // vpandq LSW, A0H, PPL - // vpaddq PPL, ACC, ACC - - // vpandq LSW, A1L, PPL - // vpaddq PPL, ACC, ACC - - // Word 1 of z is ready - // valignd $15, ACC, ACC, %zmm0{%k2} - // kshiftlw $1, %k2, %k2 - f.VPSRLQ("$32", ACC, PPL) f.VALIGND_Z("$2", ACC, ACC, "K1", ACC) f.VPADDQ(PPL, ACC, ACC) @@ -758,15 +729,6 @@ func (f *FFAmd64) generateInnerProduct() { ADDPP(A4H, A5L, A5H, A6L, "6") ADDPP(A5H, A6L, A6H, A7L, "7") - // vpsrlq $32, ACC, PPL; - // valignd $2, ACC, ACC, ACC{%k1}{z}; - // vpaddq PPL, ACC, ACC; - // vpsrlq $32, A6H, A6H; vpaddq A6H, ACC, ACC; - // vpsrlq $32, A7L, A7L; vpaddq A7L, ACC, ACC; - // vpandq LSW, A7H, PPL; vpaddq PPL, ACC, ACC; - // valignd $16-8, ACC, ACC, %zmm0{%k2} - // kshiftlw $1, %k2, %k2 - f.VPSRLQ("$32", ACC, PPL) f.VALIGND_Z("$2", ACC, ACC, "K1", ACC) f.VPADDQ(PPL, ACC, ACC) @@ -779,13 +741,6 @@ func (f *FFAmd64) generateInnerProduct() { f.VALIGND("$16-8", ACC, ACC, "K2", "Z0") f.KSHIFTLW("$1", "K2", "K2") - // vpsrlq $32, ACC, PPL; - // valignd $2, ACC, ACC, ACC{%k1}{z}; - // vpaddq PPL, ACC, ACC; - // vpsrlq $32, A7H, A7H; vpaddq A7H, ACC, ACC; - // valignd $16-9, ACC, ACC, %zmm0{%k2} - // kshiftlw $1, %k2, %k2 - f.VPSRLQ("$32", ACC, PPL) f.VALIGND_Z("$2", ACC, ACC, "K1", ACC) f.VPADDQ(PPL, ACC, ACC) @@ -794,12 +749,6 @@ func (f *FFAmd64) generateInnerProduct() { f.VALIGND("$16-9", ACC, ACC, "K2", "Z0") f.KSHIFTLW("$1", "K2", "K2") - // #define ADDPP(I) \ - // vpsrlq $32, ACC, PPL; \ - // valignd $2, ACC, ACC, ACC{%k1}{z}; \ - // vpaddq PPL, ACC, ACC; \ - // valignd $16-I, ACC, ACC, %zmm0{%k2}; \ - // kshiftlw $1, %k2, %k2 ADDPP_2 := func(I int) { f.VPSRLQ("$32", ACC, PPL) f.VALIGND_Z("$2", ACC, ACC, "K1", ACC) @@ -815,19 +764,11 @@ func (f *FFAmd64) generateInnerProduct() { ADDPP_2(14) ADDPP_2(15) - // vpsrlq $32, ACC, PPL; - // valignd $2, ACC, ACC, ACC{%k1}{z}; - // vpaddq PPL, ACC, ACC; - // vmovdqa64 ACC, %zmm1{%k1}{z} - f.VPSRLQ("$32", ACC, PPL) f.VALIGND_Z("$2", ACC, ACC, "K1", ACC) f.VPADDQ(PPL, ACC, ACC) f.VMOVDQA64_Z(ACC, "K1", "Z1") - // We have 544-bit (72-byte) result in Z1:Z0. - // Only the modular reduction remains to be computed. - T0 := f.Pop(®isters) T1 := f.Pop(®isters) T2 := f.Pop(®isters) @@ -879,14 +820,14 @@ func (f *FFAmd64) generateInnerProduct() { f.ADCQ(PH, T0) f.ADCQ("$0", T1) - // movq INV, %rdx + // // movq INV, %rdx - // mulx T2, %rdx, PH + // // mulx T2, %rdx, PH - // mulx 0*8(PM), PL, PH; add PL, T2; adc PH, T3 - // mulx 2*8(PM), PL, PH; adc PL, T4; adc PH, T0; adc $0, T1 - // mulx 1*8(PM), PL, PH; add PL, T3; adc PH, T4 - // mulx 3*8(PM), PL, PH; adc PL, T0; adc PH, T1; adc $0, T2 + // // mulx 0*8(PM), PL, PH; add PL, T2; adc PH, T3 + // // mulx 2*8(PM), PL, PH; adc PL, T4; adc PH, T0; adc $0, T1 + // // mulx 1*8(PM), PL, PH; add PL, T3; adc PH, T4 + // // mulx 3*8(PM), PL, PH; adc PL, T0; adc PH, T1; adc $0, T2 f.MOVQ(f.qInv0(), amd64.DX) f.MULXQ(T2, amd64.DX, PH) @@ -906,14 +847,14 @@ func (f *FFAmd64) generateInnerProduct() { f.ADCQ(PH, T1) f.ADCQ("$0", T2) - // movq INV, %rdx + // // movq INV, %rdx - // mulx T3, %rdx, PH + // // mulx T3, %rdx, PH - // mulx 0*8(PM), PL, PH; add PL, T3; adc PH, T4 - // mulx 2*8(PM), PL, PH; adc PL, T0; adc PH, T1; adc $0, T2 - // mulx 1*8(PM), PL, PH; add PL, T4; adc PH, T0 - // mulx 3*8(PM), PL, PH; adc PL, T1; adc PH, T2; adc $0, T3 + // // mulx 0*8(PM), PL, PH; add PL, T3; adc PH, T4 + // // mulx 2*8(PM), PL, PH; adc PL, T0; adc PH, T1; adc $0, T2 + // // mulx 1*8(PM), PL, PH; add PL, T4; adc PH, T0 + // // mulx 3*8(PM), PL, PH; adc PL, T1; adc PH, T2; adc $0, T3 f.MOVQ(f.qInv0(), amd64.DX) @@ -934,14 +875,14 @@ func (f *FFAmd64) generateInnerProduct() { f.ADCQ(PH, T2) f.ADCQ("$0", T3) - // movq INV, %rdx + // // movq INV, %rdx - // mulx T4, %rdx, PH + // // mulx T4, %rdx, PH - // mulx 0*8(PM), PL, PH; add PL, T4; adc PH, T0 - // mulx 2*8(PM), PL, PH; adc PL, T1; adc PH, T2; adc $0, T3 - // mulx 1*8(PM), PL, PH; add PL, T0; adc PH, T1 - // mulx 3*8(PM), PL, PH; adc PL, T2; adc PH, T3; adc $0, T4 + // // mulx 0*8(PM), PL, PH; add PL, T4; adc PH, T0 + // // mulx 2*8(PM), PL, PH; adc PL, T1; adc PH, T2; adc $0, T3 + // // mulx 1*8(PM), PL, PH; add PL, T0; adc PH, T1 + // // mulx 3*8(PM), PL, PH; adc PL, T2; adc PH, T3; adc $0, T4 f.MOVQ(f.qInv0(), amd64.DX) @@ -1054,4 +995,141 @@ func (f *FFAmd64) generateInnerProduct() { f.LABEL(done) f.RET() + + // f.Push(®isters, lo, hi) + + // // We have 544-bit (72-byte) result in Z1:Z0. + // // Only the modular reduction remains to be computed. + + // // for i=0 to s-1 + // // C := 0 + // // m := t[i]*n'[0] mod W + // // for j=0 to s-1 + // // (C,S) := t[i+j] + m*n[j] + C + // // t[i+j] := S + // // ADD (t[i+s],C) + + // f.XORQ(amd64.AX, amd64.AX) + // m := amd64.DX + // tr := f.Pop(®isters) + // zero := f.Pop(®isters) + + // f.MOVQ(f.qInv0(), m) + // for i := 0; i < 4; i++ { + // f.XORQ(zero, zero) + // f.IMULQ(r[i], m) + + // f.MULXQ(f.qAt(i), amd64.AX, tr) + + // // shift in the loop. + + // for j := 0; j < 4; j++ { + // f.MULXQ(f.qAt(j), amd64.AX, tr) + // f.ADCXQ(amd64.AX, r[i+j]) + // f.ADOXQ(tr, r[i+j+1]) + // } + + // for j := i + 1; j < 8; j++ { + // f.ADCXQ(zero, r[j]) + // f.ADOXQ(zero, r[j+1]) + // } + + // f.ADCXQ(zero, r[8]) + // } + + // // // j == 0 + // // // C,_ := r[i] + m*q[0] + // // f.MULXQ(f.qAt(0), amd64.AX, tr) + // // f.ADCXQ(amd64.AX, r[i]) + // // f.ADOXQ(tr, r[i+1]) + + // // for j := 1; j < 4; j++ { + // // f.MULXQ(f.qAt(j), amd64.AX, tr) // m * n[j] + // // f.ADCXQ(amd64.AX, r[i+j]) + // // f.ADOXQ(tr, r[i+j+1]) + // // } + + // // for k := i + 4; k < 9; k++ { + // // f.ADCXQ(zero, r[k]) + // // f.ADOXQ(zero, r[k]) + // // } + + // f.Push(®isters, zero, tr, m) + + // // now our result should be in r[4] to r[8] + // T0 := r[4] + // T1 := r[5] + // T2 := r[6] + // T3 := r[7] + // T4 := r[8] + + // PL := f.Pop(®isters) + // PH := f.Pop(®isters) + + // // ////////////////////////////////////////////////// + // // // Barrett reduction + // // ////////////////////////////////////////////////// + + // // // // For explanation of mu, q1, q2, q3, r1, r2, see Handbook of + // // // // Applied Cryptography, Algorithm 14.42. + + // // // // q1 is low 32 bits of T4 and high 32 bits of T3 + + // // // movq T3, %rax + // // // shrd $32, T4, %rax // q1 + // // // mulq MU // Multiply by mu. q2 in rdx:rax, q3 in rdx + + // f.MOVQ(T3, amd64.AX) + // f.SHRQw("$32", T4, amd64.AX) + // f.MOVQ(f.mu(), amd64.DX) + // f.MULQ(amd64.DX) + + // // // // Subtract r2 from r1 + + // // // mulx 0*8(PM), PL, PH; sub PL, T0; sbb PH, T1; + // // // mulx 2*8(PM), PL, PH; sbb PL, T2; sbb PH, T3; sbb $0, T4 + // // // mulx 1*8(PM), PL, PH; sub PL, T1; sbb PH, T2; + // // // mulx 3*8(PM), PL, PH; sbb PL, T3; sbb PH, T4 + + // f.MULXQ(f.qAt(0), PL, PH) + // f.SUBQ(PL, T0) + // f.SBBQ(PH, T1) + // f.MULXQ(f.qAt(2), PL, PH) + // f.SBBQ(PL, T2) + // f.SBBQ(PH, T3) + // f.SBBQ("$0", T4) + // f.MULXQ(f.qAt(1), PL, PH) + // f.SUBQ(PL, T1) + // f.SBBQ(PH, T2) + // f.MULXQ(f.qAt(3), PL, PH) + // f.SBBQ(PL, T3) + // f.SBBQ(PH, T4) + + // PZ := f.Pop(®isters) + // f.MOVQ("res+0(FP)", PZ) + // t := []amd64.Register{T0, T1, T2, T3} + // f.Mov(t, PZ) + + // // sub q + // f.SUBQ(f.qAt(0), T0) + // f.SBBQ(f.qAt(1), T1) + // f.SBBQ(f.qAt(2), T2) + // f.SBBQ(f.qAt(3), T3) + // f.SBBQ("$0", T4) + + // // if borrow, we go to done + // f.JCS(done) + + // f.Mov(t, PZ) + + // f.SUBQ(f.qAt(0), T0) + // f.SBBQ(f.qAt(1), T1) + // f.SBBQ(f.qAt(2), T2) + // f.SBBQ(f.qAt(3), T3) + // f.SBBQ("$0", T4) + + // f.JCS(done) + + // f.Mov(t, PZ) + } diff --git a/field/generator/internal/templates/element/ops_asm.go b/field/generator/internal/templates/element/ops_asm.go index 4a5a13182..042337d20 100644 --- a/field/generator/internal/templates/element/ops_asm.go +++ b/field/generator/internal/templates/element/ops_asm.go @@ -87,7 +87,7 @@ func (vector *Vector) Sum() (res {{.ElementName}}) { func sumVec(res *{{.ElementName}}, a *{{.ElementName}}, n uint64) //go:noescape -func innerProdVec(res *{{.ElementName}}, a,b *{{.ElementName}}, n uint64) +func innerProdVec(res *uint64, a,b *{{.ElementName}}, n uint64) // InnerProduct computes the inner product of two vectors. // It panics if the vectors don't have the same length. @@ -99,14 +99,14 @@ func (vector *Vector) InnerProduct(other Vector) (res {{.ElementName}}) { if n != uint64(len(other)) { panic("vector.InnerProduct: vectors don't have the same length") } - const minN = 16*7 // AVX512 slower than generic for small n + const minN = 0 // AVX512 slower than generic for small n const maxN = (1 << 32) - 1 if !supportAvx512 || n <= minN || n >= maxN { // call innerProductVecGeneric innerProductVecGeneric(&res, *vector, other) return } - innerProdVec(&res, &(*vector)[0], &other[0], uint64(len(*vector))) + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) return } diff --git a/field/generator/internal/templates/element/tests_vector.go b/field/generator/internal/templates/element/tests_vector.go index 1472e38d5..2eb753c99 100644 --- a/field/generator/internal/templates/element/tests_vector.go +++ b/field/generator/internal/templates/element/tests_vector.go @@ -9,6 +9,7 @@ import ( "sort" "reflect" "bytes" + "os" "fmt" "github.com/leanovate/gopter" @@ -155,43 +156,54 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} - + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } + for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - gen{{.ElementName}}(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + gen{{.ElementName}}(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } + func BenchmarkVectorOps(b *testing.B) { // note; to benchmark against "no asm" version, use the following // build tag: -tags purego @@ -248,6 +260,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size) diff --git a/field/goldilocks/vector_test.go b/field/goldilocks/vector_test.go index e18752c69..3f6711ccb 100644 --- a/field/goldilocks/vector_test.go +++ b/field/goldilocks/vector_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "github.com/stretchr/testify/require" + "os" "reflect" "sort" "testing" @@ -166,41 +167,51 @@ func TestVectorOps(t *testing.T) { return innerProduct.Equal(&computed) } - sizes := []int{1, 2, 3, 4, 7, 9, 64, 65, 117, 127, 128, 129, 130, 131, 1024} + sizes := []int{1, 2, 3, 4, 509, 510, 511, 512, 513, 514} + type genPair struct { + g1, g2 gopter.Gen + } for _, size := range sizes { - properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( - addVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( - subVector, - genVector(size), - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( - scalarMulVector, - genVector(size), - genElement(), - )) - - properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( - sumVector, - genVector(size), - )) - - properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( - innerProductVector, - genVector(size), - genVector(size), - )) - + generators := []genPair{ + {genZeroVector(size), genZeroVector(size)}, + {genMaxVector(size), genMaxVector(size)}, + {genVector(size), genVector(size)}, + {genVector(size), genZeroVector(size)}, + } + for _, gp := range generators { + properties.Property(fmt.Sprintf("vector addition %d", size), prop.ForAll( + addVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector subtraction %d", size), prop.ForAll( + subVector, + gp.g1, + gp.g2, + )) + + properties.Property(fmt.Sprintf("vector scalar multiplication %d", size), prop.ForAll( + scalarMulVector, + gp.g1, + genElement(), + )) + + properties.Property(fmt.Sprintf("vector sum %d", size), prop.ForAll( + sumVector, + gp.g1, + )) + + properties.Property(fmt.Sprintf("vector inner product %d", size), prop.ForAll( + innerProductVector, + gp.g1, + gp.g2, + )) + } } - properties.TestingRun(t, gopter.ConsoleReporter(false)) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 260, os.Stdout)) } func BenchmarkVectorOps(b *testing.B) { @@ -259,6 +270,29 @@ func BenchmarkVectorOps(b *testing.B) { }) } +func genZeroVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + +func genMaxVector(size int) gopter.Gen { + return func(genParams *gopter.GenParameters) *gopter.GenResult { + g := make(Vector, size) + + qMinusOne := qElement + qMinusOne[0]-- + + for i := 0; i < size; i++ { + g[i] = qMinusOne + } + genResult := gopter.NewGenResult(g, gopter.NoShrinker) + return genResult + } +} + func genVector(size int) gopter.Gen { return func(genParams *gopter.GenParameters) *gopter.GenResult { g := make(Vector, size)