github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/cyclo6_test.go (about) 1 package ff 2 3 import ( 4 "math/big" 5 "testing" 6 7 "github.com/cloudflare/circl/internal/test" 8 ) 9 10 func randomCyclo6(t testing.TB) *Cyclo6 { 11 c := &Cyclo6{} 12 EasyExponentiation(c, randomFp12(t)) 13 return c 14 } 15 16 // phi6primeSq evaluates the 6-th cyclotomic polynomial, \phi_6(x) = x^2-x+1, at p^2. 17 func phi6primeSq() []byte { 18 one := big.NewInt(1) 19 p := new(big.Int).SetBytes(fpOrder[:]) // p 20 p2 := new(big.Int).Mul(p, p) // p^2 21 p4 := new(big.Int).Sub(p2, one) // p^2 - 1 22 p4.Mul(p4, p2) // p^4 - p^2 23 p4.Add(p4, one) // p^4 - p^2 + 1 24 return p4.Bytes() 25 } 26 27 func TestCyclo6(t *testing.T) { 28 const testTimes = 1 << 10 29 t.Run("no_alias", func(t *testing.T) { 30 var want, got Cyclo6 31 x := randomCyclo6(t) 32 got = *x 33 got.Sqr(&got) 34 want = *x 35 want.Mul(&want, &want) 36 if got.IsEqual(&want) == 0 { 37 test.ReportError(t, got, want, x) 38 } 39 }) 40 t.Run("order", func(t *testing.T) { 41 cyclo6Order := phi6primeSq() 42 var z Cyclo6 43 for i := 0; i < 16; i++ { 44 x := randomCyclo6(t) 45 z.exp(x, cyclo6Order) 46 47 // x^phi6primeSq = 1 48 got := z.IsIdentity() 49 want := 1 50 if got != want { 51 test.ReportError(t, got, want, x, z) 52 } 53 } 54 }) 55 t.Run("mul_inv", func(t *testing.T) { 56 var z Cyclo6 57 for i := 0; i < testTimes; i++ { 58 x := randomCyclo6(t) 59 y := randomCyclo6(t) 60 61 // x*y*x^1 = y 62 z.Inv(x) 63 z.Mul(&z, y) 64 z.Mul(&z, x) 65 got := z 66 want := y 67 if got.IsEqual(want) == 0 { 68 test.ReportError(t, got, want, x, y) 69 } 70 } 71 }) 72 t.Run("mul_sqr", func(t *testing.T) { 73 var want, got Cyclo6 74 for i := 0; i < testTimes; i++ { 75 x := randomCyclo6(t) 76 77 // x*x = x^2 78 got.Mul(x, x) 79 want.Sqr(x) 80 if got.IsEqual(&want) == 0 { 81 test.ReportError(t, got, want, x) 82 } 83 } 84 }) 85 t.Run("sqr_sqrfasr", func(t *testing.T) { 86 var want, got Cyclo6 87 for i := 0; i < testTimes; i++ { 88 x := randomCyclo6(t) 89 90 // Specialized square in cyclotomic vs Generic Square in Fp12 91 got.Sqr(x) 92 (*Fp12)(&want).Sqr((*Fp12)(x)) 93 if got.IsEqual(&want) == 0 { 94 test.ReportError(t, got, want, x) 95 } 96 } 97 }) 98 99 t.Run("invFp12_vs_invCyclo6", func(t *testing.T) { 100 var want, got Fp12 101 var y Cyclo6 102 for i := 0; i < testTimes; i++ { 103 x := randomCyclo6(t) 104 105 y.Inv(x) 106 got = (Fp12)(y) 107 want.Inv((*Fp12)(x)) 108 109 if got.IsEqual(&want) == 0 { 110 test.ReportError(t, got, want, x) 111 } 112 } 113 }) 114 } 115 116 func BenchmarkCyclo6(b *testing.B) { 117 x := randomCyclo6(b) 118 y := randomCyclo6(b) 119 z := randomCyclo6(b) 120 b.Run("Mul", func(b *testing.B) { 121 for i := 0; i < b.N; i++ { 122 z.Mul(x, y) 123 } 124 }) 125 b.Run("Sqr", func(b *testing.B) { 126 for i := 0; i < b.N; i++ { 127 z.Sqr(x) 128 } 129 }) 130 b.Run("Inv", func(b *testing.B) { 131 for i := 0; i < b.N; i++ { 132 z.Inv(x) 133 } 134 }) 135 b.Run("PowToX", func(b *testing.B) { 136 for i := 0; i < b.N; i++ { 137 z.PowToX(x) 138 } 139 }) 140 }