// Code generated by goff DO NOT EDIT
|
|
package ff
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"math/big"
|
|
mrand "math/rand"
|
|
"testing"
|
|
)
|
|
|
|
func TestELEMENTCorrectnessAgainstBigInt(t *testing.T) {
|
|
modulus, _ := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
|
cmpEandB := func(e *Element, b *big.Int, name string) {
|
|
var _e big.Int
|
|
if e.FromMont().ToBigInt(&_e).Cmp(b) != 0 {
|
|
t.Fatal(name, "failed")
|
|
}
|
|
}
|
|
var modulusMinusOne, one big.Int
|
|
one.SetUint64(1)
|
|
|
|
modulusMinusOne.Sub(modulus, &one)
|
|
|
|
for i := 0; i < 1000; i++ {
|
|
|
|
// sample 2 random big int
|
|
b1, _ := rand.Int(rand.Reader, modulus)
|
|
b2, _ := rand.Int(rand.Reader, modulus)
|
|
rExp := mrand.Uint64()
|
|
|
|
// adding edge cases
|
|
// TODO need more edge cases
|
|
switch i {
|
|
case 0:
|
|
rExp = 0
|
|
b1.SetUint64(0)
|
|
case 1:
|
|
b2.SetUint64(0)
|
|
case 2:
|
|
b1.SetUint64(0)
|
|
b2.SetUint64(0)
|
|
case 3:
|
|
rExp = 0
|
|
case 4:
|
|
rExp = 1
|
|
case 5:
|
|
rExp = ^uint64(0) // max uint
|
|
case 6:
|
|
rExp = 2
|
|
b1.Set(&modulusMinusOne)
|
|
case 7:
|
|
b2.Set(&modulusMinusOne)
|
|
case 8:
|
|
b1.Set(&modulusMinusOne)
|
|
b2.Set(&modulusMinusOne)
|
|
}
|
|
|
|
rbExp := new(big.Int).SetUint64(rExp)
|
|
|
|
var bMul, bAdd, bSub, bDiv, bNeg, bLsh, bInv, bExp, bSquare big.Int
|
|
|
|
// e1 = mont(b1), e2 = mont(b2)
|
|
var e1, e2, eMul, eAdd, eSub, eDiv, eNeg, eLsh, eInv, eExp, eSquare, eMulAssign, eSubAssign, eAddAssign Element
|
|
e1.SetBigInt(b1)
|
|
e2.SetBigInt(b2)
|
|
|
|
// (e1*e2).FromMont() === b1*b2 mod q ... etc
|
|
eSquare.Square(&e1)
|
|
eMul.Mul(&e1, &e2)
|
|
eMulAssign.Set(&e1)
|
|
eMulAssign.MulAssign(&e2)
|
|
eAdd.Add(&e1, &e2)
|
|
eAddAssign.Set(&e1)
|
|
eAddAssign.AddAssign(&e2)
|
|
eSub.Sub(&e1, &e2)
|
|
eSubAssign.Set(&e1)
|
|
eSubAssign.SubAssign(&e2)
|
|
eDiv.Div(&e1, &e2)
|
|
eNeg.Neg(&e1)
|
|
eInv.Inverse(&e1)
|
|
eExp.Exp(e1, rExp)
|
|
eLsh.Double(&e1)
|
|
|
|
// same operations with big int
|
|
bAdd.Add(b1, b2).Mod(&bAdd, modulus)
|
|
bMul.Mul(b1, b2).Mod(&bMul, modulus)
|
|
bSquare.Mul(b1, b1).Mod(&bSquare, modulus)
|
|
bSub.Sub(b1, b2).Mod(&bSub, modulus)
|
|
bDiv.ModInverse(b2, modulus)
|
|
bDiv.Mul(&bDiv, b1).
|
|
Mod(&bDiv, modulus)
|
|
bNeg.Neg(b1).Mod(&bNeg, modulus)
|
|
|
|
bInv.ModInverse(b1, modulus)
|
|
bExp.Exp(b1, rbExp, modulus)
|
|
bLsh.Lsh(b1, 1).Mod(&bLsh, modulus)
|
|
|
|
cmpEandB(&eSquare, &bSquare, "Square")
|
|
cmpEandB(&eMul, &bMul, "Mul")
|
|
cmpEandB(&eMulAssign, &bMul, "MulAssign")
|
|
cmpEandB(&eAdd, &bAdd, "Add")
|
|
cmpEandB(&eAddAssign, &bAdd, "AddAssign")
|
|
cmpEandB(&eSub, &bSub, "Sub")
|
|
cmpEandB(&eSubAssign, &bSub, "SubAssign")
|
|
cmpEandB(&eDiv, &bDiv, "Div")
|
|
cmpEandB(&eNeg, &bNeg, "Neg")
|
|
cmpEandB(&eInv, &bInv, "Inv")
|
|
cmpEandB(&eExp, &bExp, "Exp")
|
|
cmpEandB(&eLsh, &bLsh, "Lsh")
|
|
}
|
|
}
|
|
|
|
func TestELEMENTIsRandom(t *testing.T) {
|
|
for i := 0; i < 1000; i++ {
|
|
var x, y Element
|
|
x.SetRandom()
|
|
y.SetRandom()
|
|
if x.Equal(&y) {
|
|
t.Fatal("2 random numbers are unlikely to be equal")
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// 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
|
|
// TODO: clean up and push benchmarking branch
|
|
|
|
var benchResElement Element
|
|
|
|
func BenchmarkInverseELEMENT(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Inverse(&x)
|
|
}
|
|
|
|
}
|
|
func BenchmarkExpELEMENT(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Exp(x, mrand.Uint64())
|
|
}
|
|
}
|
|
|
|
func BenchmarkDoubleELEMENT(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Double(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkAddELEMENT(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Add(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkSubELEMENT(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Sub(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkNegELEMENT(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Neg(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkDivELEMENT(b *testing.B) {
|
|
var x Element
|
|
x.SetRandom()
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Div(&x, &benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkFromMontELEMENT(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.FromMont()
|
|
}
|
|
}
|
|
|
|
func BenchmarkToMontELEMENT(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.ToMont()
|
|
}
|
|
}
|
|
func BenchmarkSquareELEMENT(b *testing.B) {
|
|
benchResElement.SetRandom()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.Square(&benchResElement)
|
|
}
|
|
}
|
|
|
|
func BenchmarkMulAssignELEMENT(b *testing.B) {
|
|
x := Element{
|
|
1997599621687373223,
|
|
6052339484930628067,
|
|
10108755138030829701,
|
|
150537098327114917,
|
|
}
|
|
benchResElement.SetOne()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
benchResElement.MulAssign(&x)
|
|
}
|
|
}
|