// Copyright 2020 ConsenSys Software Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
|
|
|
package ff
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"math/big"
|
|
"math/bits"
|
|
"testing"
|
|
|
|
"github.com/leanovate/gopter"
|
|
"github.com/leanovate/gopter/prop"
|
|
)
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// benchmarks
|
|
// most benchmarks are rudimentary and should sample a large number of random inputs
|
|
// or be run multiple times to ensure it didn't measure the fastest path of the function
|
|
|
|
var benchResElement Element
|
|
|
|
func BenchmarkElementSetBytes(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
bb := x.Bytes()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.SetBytes(bb[:])
|
|
}
|
|
|
|
}
|
|
|
|
func BenchmarkElementMulByConstants(b *testing.B) {
|
|
b.Run("mulBy3", func(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
MulBy3(&benchResElement)
|
|
}
|
|
})
|
|
b.Run("mulBy5", func(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
MulBy5(&benchResElement)
|
|
}
|
|
})
|
|
b.Run("mulBy13", func(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
MulBy13(&benchResElement)
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkElementInverse(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Inverse(&x)
|
|
}
|
|
|
|
}
|
|
|
|
func BenchmarkElementButterfly(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
Butterfly(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementExp(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b1, _ := rand.Int(rand.Reader, Modulus())
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Exp(x, b1)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementDouble(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Double(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementAdd(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Add(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementSub(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Sub(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementNeg(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Neg(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementDiv(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Div(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementFromMont(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.FromMont()
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementToMont(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.ToMont()
|
|
}
|
|
}
|
|
func BenchmarkElementSquare(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Square(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementSqrt(b *testing.B) {
|
|
var a Element
|
|
a.SetUint64(4)
|
|
a.Neg(&a)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Sqrt(&a)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementMul(b *testing.B) {
|
|
x := Element{
|
|
1997599621687373223,
|
|
6052339484930628067,
|
|
10108755138030829701,
|
|
150537098327114917,
|
|
}
|
|
benchResElement.SetOne()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Mul(&benchResElement, &x)
|
|
}
|
|
}
|
|
|
|
func BenchmarkElementCmp(b *testing.B) {
|
|
x := Element{
|
|
1997599621687373223,
|
|
6052339484930628067,
|
|
10108755138030829701,
|
|
150537098327114917,
|
|
}
|
|
benchResElement = x
|
|
benchResElement[0] = 0
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Cmp(&x)
|
|
}
|
|
}
|
|
|
|
func TestElementCmp(t *testing.T) {
|
|
var x, y Element
|
|
|
|
if x.Cmp(&y) != 0 {
|
|
t.Fatal("x == y")
|
|
}
|
|
|
|
one := One()
|
|
y.Sub(&y, &one)
|
|
|
|
if x.Cmp(&y) != -1 {
|
|
t.Fatal("x < y")
|
|
}
|
|
if y.Cmp(&x) != 1 {
|
|
t.Fatal("x < y")
|
|
}
|
|
|
|
x = y
|
|
if x.Cmp(&y) != 0 {
|
|
t.Fatal("x == y")
|
|
}
|
|
|
|
x.Sub(&x, &one)
|
|
if x.Cmp(&y) != -1 {
|
|
t.Fatal("x < y")
|
|
}
|
|
if y.Cmp(&x) != 1 {
|
|
t.Fatal("x < y")
|
|
}
|
|
}
|
|
|
|
func TestElementIsRandom(t *testing.T) {
|
|
for i := 0; i < 50; i++ {
|
|
var x, y Element
|
|
x.SetRandom()
|
|
y.SetRandom()
|
|
if x.Equal(&y) {
|
|
t.Fatal("2 random numbers are unlikely to be equal")
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Gopter tests
|
|
// most of them are generated with a template
|
|
|
|
const (
|
|
nbFuzzShort = 200
|
|
nbFuzz = 1000
|
|
)
|
|
|
|
// special values to be used in tests
|
|
var staticTestValues []Element
|
|
|
|
func init() {
|
|
staticTestValues = append(staticTestValues, Element{}) // zero
|
|
staticTestValues = append(staticTestValues, One()) // one
|
|
staticTestValues = append(staticTestValues, rSquare) // r^2
|
|
var e, one Element
|
|
one.SetOne()
|
|
e.Sub(&qElement, &one)
|
|
staticTestValues = append(staticTestValues, e) // q - 1
|
|
e.Double(&one)
|
|
staticTestValues = append(staticTestValues, e) // 2
|
|
|
|
{
|
|
a := qElement
|
|
a[3]--
|
|
staticTestValues = append(staticTestValues, a)
|
|
}
|
|
{
|
|
a := qElement
|
|
a[0]--
|
|
staticTestValues = append(staticTestValues, a)
|
|
}
|
|
|
|
for i := 0; i <= 3; i++ {
|
|
staticTestValues = append(staticTestValues, Element{uint64(i)})
|
|
staticTestValues = append(staticTestValues, Element{0, uint64(i)})
|
|
}
|
|
|
|
{
|
|
a := qElement
|
|
a[3]--
|
|
a[0]++
|
|
staticTestValues = append(staticTestValues, a)
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementNegZero(t *testing.T) {
|
|
var a, b Element
|
|
b.SetZero()
|
|
for a.IsZero() {
|
|
a.SetRandom()
|
|
}
|
|
a.Neg(&b)
|
|
if !a.IsZero() {
|
|
t.Fatal("neg(0) != 0")
|
|
}
|
|
}
|
|
|
|
func TestElementReduce(t *testing.T) {
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, s := range testValues {
|
|
expected := s
|
|
reduce(&s)
|
|
_reduceGeneric(&expected)
|
|
if !s.Equal(&expected) {
|
|
t.Fatal("reduce failed: asm and generic impl don't match")
|
|
}
|
|
}
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := genFull()
|
|
|
|
properties.Property("reduce should output a result smaller than modulus", prop.ForAll(
|
|
func(a Element) bool {
|
|
b := a
|
|
reduce(&a)
|
|
_reduceGeneric(&b)
|
|
return !a.biggerOrEqualModulus() && a.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementBytes(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("SetBytes(Bytes()) should stayt constant", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var b Element
|
|
bytes := a.element.Bytes()
|
|
b.SetBytes(bytes[:])
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
}
|
|
|
|
func TestElementInverseExp(t *testing.T) {
|
|
// inverse must be equal to exp^-2
|
|
exp := Modulus()
|
|
exp.Sub(exp, new(big.Int).SetUint64(2))
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("inv == exp^-2", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var b Element
|
|
b.Set(&a.element)
|
|
a.element.Inverse(&a.element)
|
|
b.Exp(b, exp)
|
|
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementMulByConstants(t *testing.T) {
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
implemented := []uint8{0, 1, 2, 3, 5, 13}
|
|
properties.Property("mulByConstant", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
for _, c := range implemented {
|
|
var constant Element
|
|
constant.SetUint64(uint64(c))
|
|
|
|
b := a.element
|
|
b.Mul(&b, &constant)
|
|
|
|
aa := a.element
|
|
mulByConstant(&aa, c)
|
|
|
|
if !aa.Equal(&b) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var constant Element
|
|
constant.SetUint64(3)
|
|
|
|
b := a.element
|
|
b.Mul(&b, &constant)
|
|
|
|
MulBy3(&a.element)
|
|
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var constant Element
|
|
constant.SetUint64(5)
|
|
|
|
b := a.element
|
|
b.Mul(&b, &constant)
|
|
|
|
MulBy5(&a.element)
|
|
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var constant Element
|
|
constant.SetUint64(13)
|
|
|
|
b := a.element
|
|
b.Mul(&b, &constant)
|
|
|
|
MulBy13(&a.element)
|
|
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementLegendre(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus())
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementButterflies(t *testing.T) {
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("butterfly0 == a -b; a +b", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
a0, b0 := a.element, b.element
|
|
|
|
_butterflyGeneric(&a.element, &b.element)
|
|
Butterfly(&a0, &b0)
|
|
|
|
return a.element.Equal(&a0) && b.element.Equal(&b0)
|
|
},
|
|
genA,
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementLexicographicallyLargest(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var negA Element
|
|
negA.Neg(&a.element)
|
|
|
|
cmpResult := a.element.Cmp(&negA)
|
|
lResult := a.element.LexicographicallyLargest()
|
|
|
|
if lResult && cmpResult == 1 {
|
|
return true
|
|
}
|
|
if !lResult && cmpResult != 1 {
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
supportAdx = true
|
|
}
|
|
|
|
}
|
|
|
|
func TestElementAdd(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
genB := gen()
|
|
|
|
properties.Property("Add: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
d.Set(&a.element)
|
|
|
|
c.Add(&a.element, &b.element)
|
|
a.element.Add(&a.element, &b.element)
|
|
b.element.Add(&d, &b.element)
|
|
|
|
return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Add: operation result must match big.Int result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
{
|
|
var c Element
|
|
|
|
c.Add(&a.element, &b.element)
|
|
|
|
var d, e big.Int
|
|
d.Add(&a.bigint, &b.bigint).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// fixed elements
|
|
// a is random
|
|
// r takes special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, r := range testValues {
|
|
var d, e, rb big.Int
|
|
r.ToBigIntRegular(&rb)
|
|
|
|
var c Element
|
|
c.Add(&a.element, &r)
|
|
d.Add(&a.bigint, &rb).Mod(&d, Modulus())
|
|
|
|
// checking generic impl against asm path
|
|
var cGeneric Element
|
|
_addGeneric(&cGeneric, &a.element, &r)
|
|
if !cGeneric.Equal(&c) {
|
|
// need to give context to failing error.
|
|
return false
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Add: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c Element
|
|
|
|
c.Add(&a.element, &b.element)
|
|
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Add: assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
c.Add(&a.element, &b.element)
|
|
_addGeneric(&d, &a.element, &b.element)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values against special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
for _, b := range testValues {
|
|
|
|
var bBig, d, e big.Int
|
|
b.ToBigIntRegular(&bBig)
|
|
|
|
var c Element
|
|
c.Add(&a, &b)
|
|
d.Add(&aBig, &bBig).Mod(&d, Modulus())
|
|
|
|
// checking asm against generic impl
|
|
var cGeneric Element
|
|
_addGeneric(&cGeneric, &a, &b)
|
|
if !cGeneric.Equal(&c) {
|
|
t.Fatal("Add failed special test values: asm and generic impl don't match")
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Add failed special test values")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementSub(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
genB := gen()
|
|
|
|
properties.Property("Sub: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
d.Set(&a.element)
|
|
|
|
c.Sub(&a.element, &b.element)
|
|
a.element.Sub(&a.element, &b.element)
|
|
b.element.Sub(&d, &b.element)
|
|
|
|
return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Sub: operation result must match big.Int result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
{
|
|
var c Element
|
|
|
|
c.Sub(&a.element, &b.element)
|
|
|
|
var d, e big.Int
|
|
d.Sub(&a.bigint, &b.bigint).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// fixed elements
|
|
// a is random
|
|
// r takes special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, r := range testValues {
|
|
var d, e, rb big.Int
|
|
r.ToBigIntRegular(&rb)
|
|
|
|
var c Element
|
|
c.Sub(&a.element, &r)
|
|
d.Sub(&a.bigint, &rb).Mod(&d, Modulus())
|
|
|
|
// checking generic impl against asm path
|
|
var cGeneric Element
|
|
_subGeneric(&cGeneric, &a.element, &r)
|
|
if !cGeneric.Equal(&c) {
|
|
// need to give context to failing error.
|
|
return false
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Sub: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c Element
|
|
|
|
c.Sub(&a.element, &b.element)
|
|
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Sub: assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
c.Sub(&a.element, &b.element)
|
|
_subGeneric(&d, &a.element, &b.element)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values against special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
for _, b := range testValues {
|
|
|
|
var bBig, d, e big.Int
|
|
b.ToBigIntRegular(&bBig)
|
|
|
|
var c Element
|
|
c.Sub(&a, &b)
|
|
d.Sub(&aBig, &bBig).Mod(&d, Modulus())
|
|
|
|
// checking asm against generic impl
|
|
var cGeneric Element
|
|
_subGeneric(&cGeneric, &a, &b)
|
|
if !cGeneric.Equal(&c) {
|
|
t.Fatal("Sub failed special test values: asm and generic impl don't match")
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Sub failed special test values")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementMul(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
genB := gen()
|
|
|
|
properties.Property("Mul: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
d.Set(&a.element)
|
|
|
|
c.Mul(&a.element, &b.element)
|
|
a.element.Mul(&a.element, &b.element)
|
|
b.element.Mul(&d, &b.element)
|
|
|
|
return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Mul: operation result must match big.Int result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
{
|
|
var c Element
|
|
|
|
c.Mul(&a.element, &b.element)
|
|
|
|
var d, e big.Int
|
|
d.Mul(&a.bigint, &b.bigint).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// fixed elements
|
|
// a is random
|
|
// r takes special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, r := range testValues {
|
|
var d, e, rb big.Int
|
|
r.ToBigIntRegular(&rb)
|
|
|
|
var c Element
|
|
c.Mul(&a.element, &r)
|
|
d.Mul(&a.bigint, &rb).Mod(&d, Modulus())
|
|
|
|
// checking generic impl against asm path
|
|
var cGeneric Element
|
|
_mulGeneric(&cGeneric, &a.element, &r)
|
|
if !cGeneric.Equal(&c) {
|
|
// need to give context to failing error.
|
|
return false
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Mul: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c Element
|
|
|
|
c.Mul(&a.element, &b.element)
|
|
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Mul: assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
c.Mul(&a.element, &b.element)
|
|
_mulGeneric(&d, &a.element, &b.element)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values against special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
for _, b := range testValues {
|
|
|
|
var bBig, d, e big.Int
|
|
b.ToBigIntRegular(&bBig)
|
|
|
|
var c Element
|
|
c.Mul(&a, &b)
|
|
d.Mul(&aBig, &bBig).Mod(&d, Modulus())
|
|
|
|
// checking asm against generic impl
|
|
var cGeneric Element
|
|
_mulGeneric(&cGeneric, &a, &b)
|
|
if !cGeneric.Equal(&c) {
|
|
t.Fatal("Mul failed special test values: asm and generic impl don't match")
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Mul failed special test values")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementDiv(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
genB := gen()
|
|
|
|
properties.Property("Div: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
d.Set(&a.element)
|
|
|
|
c.Div(&a.element, &b.element)
|
|
a.element.Div(&a.element, &b.element)
|
|
b.element.Div(&d, &b.element)
|
|
|
|
return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Div: operation result must match big.Int result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
{
|
|
var c Element
|
|
|
|
c.Div(&a.element, &b.element)
|
|
|
|
var d, e big.Int
|
|
d.ModInverse(&b.bigint, Modulus())
|
|
d.Mul(&d, &a.bigint).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// fixed elements
|
|
// a is random
|
|
// r takes special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, r := range testValues {
|
|
var d, e, rb big.Int
|
|
r.ToBigIntRegular(&rb)
|
|
|
|
var c Element
|
|
c.Div(&a.element, &r)
|
|
d.ModInverse(&rb, Modulus())
|
|
d.Mul(&d, &a.bigint).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Div: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c Element
|
|
|
|
c.Div(&a.element, &b.element)
|
|
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values against special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
for _, b := range testValues {
|
|
|
|
var bBig, d, e big.Int
|
|
b.ToBigIntRegular(&bBig)
|
|
|
|
var c Element
|
|
c.Div(&a, &b)
|
|
d.ModInverse(&bBig, Modulus())
|
|
d.Mul(&d, &aBig).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Div failed special test values")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementExp(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
genB := gen()
|
|
|
|
properties.Property("Exp: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c, d Element
|
|
d.Set(&a.element)
|
|
|
|
c.Exp(a.element, &b.bigint)
|
|
a.element.Exp(a.element, &b.bigint)
|
|
b.element.Exp(d, &b.bigint)
|
|
|
|
return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Exp: operation result must match big.Int result", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
{
|
|
var c Element
|
|
|
|
c.Exp(a.element, &b.bigint)
|
|
|
|
var d, e big.Int
|
|
d.Exp(&a.bigint, &b.bigint, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// fixed elements
|
|
// a is random
|
|
// r takes special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, r := range testValues {
|
|
var d, e, rb big.Int
|
|
r.ToBigIntRegular(&rb)
|
|
|
|
var c Element
|
|
c.Exp(a.element, &rb)
|
|
d.Exp(&a.bigint, &rb, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
properties.Property("Exp: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a, b testPairElement) bool {
|
|
var c Element
|
|
|
|
c.Exp(a.element, &b.bigint)
|
|
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
genB,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values against special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
for _, b := range testValues {
|
|
|
|
var bBig, d, e big.Int
|
|
b.ToBigIntRegular(&bBig)
|
|
|
|
var c Element
|
|
c.Exp(a, &bBig)
|
|
d.Exp(&aBig, &bBig, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Exp failed special test values")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
t.Log("disabling ADX")
|
|
supportAdx = false
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementSquare(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Square: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
|
|
var b Element
|
|
|
|
b.Square(&a.element)
|
|
a.element.Square(&a.element)
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Square: operation result must match big.Int result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Square(&a.element)
|
|
|
|
var d, e big.Int
|
|
d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus())
|
|
|
|
return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Square: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Square(&a.element)
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
var c Element
|
|
c.Square(&a)
|
|
|
|
var d, e big.Int
|
|
d.Mul(&aBig, &aBig).Mod(&d, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Square failed special test values")
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
supportAdx = false
|
|
t.Log("disabling ADX")
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementInverse(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Inverse: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
|
|
var b Element
|
|
|
|
b.Inverse(&a.element)
|
|
a.element.Inverse(&a.element)
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Inverse: operation result must match big.Int result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Inverse(&a.element)
|
|
|
|
var d, e big.Int
|
|
d.ModInverse(&a.bigint, Modulus())
|
|
|
|
return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Inverse: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Inverse(&a.element)
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
var c Element
|
|
c.Inverse(&a)
|
|
|
|
var d, e big.Int
|
|
d.ModInverse(&aBig, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Inverse failed special test values")
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
supportAdx = false
|
|
t.Log("disabling ADX")
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementSqrt(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Sqrt: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
|
|
b := a.element
|
|
|
|
b.Sqrt(&a.element)
|
|
a.element.Sqrt(&a.element)
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Sqrt: operation result must match big.Int result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Sqrt(&a.element)
|
|
|
|
var d, e big.Int
|
|
d.ModSqrt(&a.bigint, Modulus())
|
|
|
|
return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Sqrt: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Sqrt(&a.element)
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
var c Element
|
|
c.Sqrt(&a)
|
|
|
|
var d, e big.Int
|
|
d.ModSqrt(&aBig, Modulus())
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Sqrt failed special test values")
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
supportAdx = false
|
|
t.Log("disabling ADX")
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementDouble(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Double: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
|
|
var b Element
|
|
|
|
b.Double(&a.element)
|
|
a.element.Double(&a.element)
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Double: operation result must match big.Int result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Double(&a.element)
|
|
|
|
var d, e big.Int
|
|
d.Lsh(&a.bigint, 1).Mod(&d, Modulus())
|
|
|
|
return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Double: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Double(&a.element)
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Double: assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c, d Element
|
|
c.Double(&a.element)
|
|
_doubleGeneric(&d, &a.element)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
var c Element
|
|
c.Double(&a)
|
|
|
|
var d, e big.Int
|
|
d.Lsh(&aBig, 1).Mod(&d, Modulus())
|
|
|
|
// checking asm against generic impl
|
|
var cGeneric Element
|
|
_doubleGeneric(&cGeneric, &a)
|
|
if !cGeneric.Equal(&c) {
|
|
t.Fatal("Double failed special test values: asm and generic impl don't match")
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Double failed special test values")
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
supportAdx = false
|
|
t.Log("disabling ADX")
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementNeg(t *testing.T) {
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Neg: having the receiver as operand should output the same result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
|
|
var b Element
|
|
|
|
b.Neg(&a.element)
|
|
a.element.Neg(&a.element)
|
|
return a.element.Equal(&b)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Neg: operation result must match big.Int result", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Neg(&a.element)
|
|
|
|
var d, e big.Int
|
|
d.Neg(&a.bigint).Mod(&d, Modulus())
|
|
|
|
return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Neg: operation result must be smaller than modulus", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c Element
|
|
c.Neg(&a.element)
|
|
return !c.biggerOrEqualModulus()
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("Neg: assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
var c, d Element
|
|
c.Neg(&a.element)
|
|
_negGeneric(&d, &a.element)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
specialValueTest := func() {
|
|
// test special values
|
|
testValues := make([]Element, len(staticTestValues))
|
|
copy(testValues, staticTestValues)
|
|
|
|
for _, a := range testValues {
|
|
var aBig big.Int
|
|
a.ToBigIntRegular(&aBig)
|
|
var c Element
|
|
c.Neg(&a)
|
|
|
|
var d, e big.Int
|
|
d.Neg(&aBig).Mod(&d, Modulus())
|
|
|
|
// checking asm against generic impl
|
|
var cGeneric Element
|
|
_negGeneric(&cGeneric, &a)
|
|
if !cGeneric.Equal(&c) {
|
|
t.Fatal("Neg failed special test values: asm and generic impl don't match")
|
|
}
|
|
|
|
if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
|
|
t.Fatal("Neg failed special test values")
|
|
}
|
|
}
|
|
}
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
// if we have ADX instruction enabled, test both path in assembly
|
|
if supportAdx {
|
|
supportAdx = false
|
|
t.Log("disabling ADX")
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
specialValueTest()
|
|
supportAdx = true
|
|
}
|
|
}
|
|
|
|
func TestElementHalve(t *testing.T) {
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
var twoInv Element
|
|
twoInv.SetUint64(2)
|
|
twoInv.Inverse(&twoInv)
|
|
|
|
properties.Property("z.Halve must match z / 2", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
c := a.element
|
|
d := a.element
|
|
c.Halve()
|
|
d.Mul(&d, &twoInv)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
}
|
|
|
|
func TestElementFromMont(t *testing.T) {
|
|
|
|
parameters := gopter.DefaultTestParameters()
|
|
if testing.Short() {
|
|
parameters.MinSuccessfulTests = nbFuzzShort
|
|
} else {
|
|
parameters.MinSuccessfulTests = nbFuzz
|
|
}
|
|
|
|
properties := gopter.NewProperties(parameters)
|
|
|
|
genA := gen()
|
|
|
|
properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
c := a.element
|
|
d := a.element
|
|
c.FromMont()
|
|
_fromMontGeneric(&d)
|
|
return c.Equal(&d)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.Property("x.FromMont().ToMont() == x", prop.ForAll(
|
|
func(a testPairElement) bool {
|
|
c := a.element
|
|
c.FromMont().ToMont()
|
|
return c.Equal(&a.element)
|
|
},
|
|
genA,
|
|
))
|
|
|
|
properties.TestingRun(t, gopter.ConsoleReporter(false))
|
|
}
|
|
|
|
type testPairElement struct {
|
|
element Element
|
|
bigint big.Int
|
|
}
|
|
|
|
func (z *Element) biggerOrEqualModulus() bool {
|
|
if z[3] > qElement[3] {
|
|
return true
|
|
}
|
|
if z[3] < qElement[3] {
|
|
return false
|
|
}
|
|
|
|
if z[2] > qElement[2] {
|
|
return true
|
|
}
|
|
if z[2] < qElement[2] {
|
|
return false
|
|
}
|
|
|
|
if z[1] > qElement[1] {
|
|
return true
|
|
}
|
|
if z[1] < qElement[1] {
|
|
return false
|
|
}
|
|
|
|
return z[0] >= qElement[0]
|
|
}
|
|
|
|
func gen() gopter.Gen {
|
|
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
|
var g testPairElement
|
|
|
|
g.element = Element{
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
}
|
|
if qElement[3] != ^uint64(0) {
|
|
g.element[3] %= (qElement[3] + 1)
|
|
}
|
|
|
|
for g.element.biggerOrEqualModulus() {
|
|
g.element = Element{
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
}
|
|
if qElement[3] != ^uint64(0) {
|
|
g.element[3] %= (qElement[3] + 1)
|
|
}
|
|
}
|
|
|
|
g.element.ToBigIntRegular(&g.bigint)
|
|
genResult := gopter.NewGenResult(g, gopter.NoShrinker)
|
|
return genResult
|
|
}
|
|
}
|
|
|
|
func genFull() gopter.Gen {
|
|
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
|
|
|
genRandomFq := func() Element {
|
|
var g Element
|
|
|
|
g = Element{
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
}
|
|
|
|
if qElement[3] != ^uint64(0) {
|
|
g[3] %= (qElement[3] + 1)
|
|
}
|
|
|
|
for g.biggerOrEqualModulus() {
|
|
g = Element{
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
genParams.NextUint64(),
|
|
}
|
|
if qElement[3] != ^uint64(0) {
|
|
g[3] %= (qElement[3] + 1)
|
|
}
|
|
}
|
|
|
|
return g
|
|
}
|
|
a := genRandomFq()
|
|
|
|
var carry uint64
|
|
a[0], carry = bits.Add64(a[0], qElement[0], carry)
|
|
a[1], carry = bits.Add64(a[1], qElement[1], carry)
|
|
a[2], carry = bits.Add64(a[2], qElement[2], carry)
|
|
a[3], _ = bits.Add64(a[3], qElement[3], carry)
|
|
|
|
genResult := gopter.NewGenResult(a, gopter.NoShrinker)
|
|
return genResult
|
|
}
|
|
}
|