// 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) } }