github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/fp2_test.go (about) 1 package ff 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/cloudflare/circl/internal/test" 8 ) 9 10 func randomFp2(t testing.TB) *Fp2 { return &Fp2{*randomFp(t), *randomFp(t)} } 11 12 func TestFp2(t *testing.T) { 13 const testTimes = 1 << 9 14 t.Run("no_alias", func(t *testing.T) { 15 var want, got Fp2 16 x := randomFp2(t) 17 got = *x 18 got.Sqr(&got) 19 want = *x 20 want.Mul(&want, &want) 21 if got.IsEqual(&want) == 0 { 22 test.ReportError(t, got, want, x) 23 } 24 }) 25 t.Run("mul_inv", func(t *testing.T) { 26 var z Fp2 27 for i := 0; i < testTimes; i++ { 28 x := randomFp2(t) 29 y := randomFp2(t) 30 31 // x*y*x^1 - y = 0 32 z.Inv(x) 33 z.Mul(&z, y) 34 z.Mul(&z, x) 35 z.Sub(&z, y) 36 got := z.IsZero() 37 want := 1 38 if got != want { 39 test.ReportError(t, got, want, x, y, z) 40 } 41 } 42 }) 43 t.Run("mul_sqr", func(t *testing.T) { 44 var l0, l1, r0, r1 Fp2 45 for i := 0; i < testTimes; i++ { 46 x := randomFp2(t) 47 y := randomFp2(t) 48 49 // (x+y)(x-y) = (x^2-y^2) 50 l0.Add(x, y) 51 l1.Sub(x, y) 52 l0.Mul(&l0, &l1) 53 r0.Sqr(x) 54 r1.Sqr(y) 55 r0.Sub(&r0, &r1) 56 got := &l0 57 want := &r0 58 if got.IsEqual(want) == 0 { 59 test.ReportError(t, got, want, x, y) 60 } 61 } 62 }) 63 t.Run("sqrt", func(t *testing.T) { 64 var r, notRoot, got Fp2 65 // Check when x has square-root. 66 for i := 0; i < testTimes; i++ { 67 x := randomFp2(t) 68 x.Sqr(x) 69 70 // let x is QR and r = sqrt(x); check (+r)^2 = (-r)^2 = x. 71 isQR := r.Sqrt(x) 72 test.CheckOk(isQR == 1, fmt.Sprintf("should be a QR: %v", x), t) 73 rNeg := r 74 rNeg.Neg() 75 76 want := x 77 for _, root := range []*Fp2{&r, &rNeg} { 78 got.Sqr(root) 79 if got.IsEqual(want) == 0 { 80 test.ReportError(t, got, want, x, root) 81 } 82 } 83 } 84 // Check when x has not square-root. 85 var uPlus1 Fp2 86 uPlus1[0].SetUint64(1) 87 uPlus1[1].SetUint64(1) 88 for i := 0; i < testTimes; i++ { 89 want := randomFp2(t) 90 x := randomFp2(t) 91 x.Sqr(x) 92 x.Mul(x, &uPlus1) // x = (u+1)*(x^2), since u+1 is not QR in Fp2. 93 94 // let x is not QR and r = sqrt(x); check that r was not modified. 95 got := want 96 isQR := got.Sqrt(x) 97 test.CheckOk(isQR == 0, fmt.Sprintf("shouldn't be a QR: %v", x), t) 98 99 if got.IsEqual(want) != 1 { 100 test.ReportError(t, got, want, x, notRoot) 101 } 102 } 103 }) 104 t.Run("marshal", func(t *testing.T) { 105 var b Fp2 106 for i := 0; i < testTimes; i++ { 107 a := randomFp2(t) 108 s, err := a.MarshalBinary() 109 test.CheckNoErr(t, err, "MarshalBinary failed") 110 err = b.UnmarshalBinary(s) 111 test.CheckNoErr(t, err, "UnmarshalBinary failed") 112 if b.IsEqual(a) == 0 { 113 test.ReportError(t, a, b) 114 } 115 } 116 }) 117 } 118 119 func BenchmarkFp2(b *testing.B) { 120 x := randomFp2(b) 121 y := randomFp2(b) 122 z := randomFp2(b) 123 b.Run("Add", func(b *testing.B) { 124 for i := 0; i < b.N; i++ { 125 z.Add(x, y) 126 } 127 }) 128 b.Run("Mul", func(b *testing.B) { 129 for i := 0; i < b.N; i++ { 130 z.Mul(x, y) 131 } 132 }) 133 b.Run("Sqr", func(b *testing.B) { 134 for i := 0; i < b.N; i++ { 135 z.Sqr(x) 136 } 137 }) 138 b.Run("Inv", func(b *testing.B) { 139 for i := 0; i < b.N; i++ { 140 z.Inv(x) 141 } 142 }) 143 }