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  }