github.com/consensys/gnark-crypto@v0.14.0/field/generator/internal/templates/element/tests.go (about)

     1  package element
     2  
     3  const Test = `
     4  
     5  
     6  import (
     7  	"crypto/rand"
     8  	"encoding/json"
     9  	"math/big"
    10  	"math/bits"
    11  	"fmt"
    12  	{{if .UsingP20Inverse}} 
    13  	mrand "math/rand" 
    14  	{{end}}
    15  	"testing"
    16  	
    17  	"github.com/leanovate/gopter"
    18  	"github.com/leanovate/gopter/prop"
    19  	ggen "github.com/leanovate/gopter/gen"
    20  
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  
    25  // -------------------------------------------------------------------------------------------------
    26  // benchmarks
    27  // most benchmarks are rudimentary and should sample a large number of random inputs
    28  // or be run multiple times to ensure it didn't measure the fastest path of the function
    29  
    30  var benchRes{{.ElementName}} {{.ElementName}}
    31  
    32  func Benchmark{{toTitle .ElementName}}Select(b *testing.B) {
    33  	var x, y {{.ElementName}}
    34  	x.SetRandom()
    35  	y.SetRandom()
    36  
    37  	b.ResetTimer()
    38  	for i := 0; i < b.N; i++ {
    39  		benchRes{{.ElementName}}.Select(i%3, &x, &y)
    40  	}
    41  }
    42  
    43  func Benchmark{{toTitle .ElementName}}SetRandom(b *testing.B) {
    44  	var x {{.ElementName}}
    45  	x.SetRandom()
    46  
    47  	b.ResetTimer()
    48  	for i := 0; i < b.N; i++ {
    49  		_, _ = x.SetRandom()
    50  	}
    51  }
    52  
    53  func Benchmark{{toTitle .ElementName}}SetBytes(b *testing.B) {
    54  	var x {{.ElementName}}
    55  	x.SetRandom()
    56  	bb := x.Bytes()
    57  	b.ResetTimer()
    58  
    59  	for i := 0; i < b.N; i++ {
    60  		benchRes{{.ElementName}}.SetBytes(bb[:])
    61  	}
    62  
    63  }
    64  
    65  func Benchmark{{toTitle .ElementName}}MulByConstants(b *testing.B) {
    66  	b.Run("mulBy3", func(b *testing.B){
    67  		benchRes{{.ElementName}}.SetRandom()
    68  		b.ResetTimer()
    69  		for i := 0; i < b.N; i++ {
    70  			MulBy3(&benchRes{{.ElementName}})
    71  		}
    72  	})
    73  	b.Run("mulBy5", func(b *testing.B){
    74  		benchRes{{.ElementName}}.SetRandom()
    75  		b.ResetTimer()
    76  		for i := 0; i < b.N; i++ {
    77  			MulBy5(&benchRes{{.ElementName}})
    78  		}
    79  	})
    80  	b.Run("mulBy13", func(b *testing.B){
    81  		benchRes{{.ElementName}}.SetRandom()
    82  		b.ResetTimer()
    83  		for i := 0; i < b.N; i++ {
    84  			MulBy13(&benchRes{{.ElementName}})
    85  		}
    86  	})
    87  }
    88  
    89  func Benchmark{{toTitle .ElementName}}Inverse(b *testing.B) {
    90  	var x {{.ElementName}}
    91  	x.SetRandom()
    92  	benchRes{{.ElementName}}.SetRandom()
    93  	b.ResetTimer()
    94  
    95  	for i := 0; i < b.N; i++ {
    96  		benchRes{{.ElementName}}.Inverse(&x)
    97  	}
    98  
    99  }
   100  
   101  func Benchmark{{toTitle .ElementName}}Butterfly(b *testing.B) {
   102  	var x {{.ElementName}}
   103  	x.SetRandom()
   104  	benchRes{{.ElementName}}.SetRandom()
   105  	b.ResetTimer()
   106  	for i := 0; i < b.N; i++ {
   107  		Butterfly(&x, &benchRes{{.ElementName}})
   108  	}
   109  }
   110  
   111  
   112  func Benchmark{{toTitle .ElementName}}Exp(b *testing.B) {
   113  	var x {{.ElementName}}
   114  	x.SetRandom()
   115  	benchRes{{.ElementName}}.SetRandom()
   116  	b1, _ := rand.Int(rand.Reader, Modulus())
   117  	b.ResetTimer()
   118  	for i := 0; i < b.N; i++ {
   119  		benchRes{{.ElementName}}.Exp(x, b1)
   120  	}
   121  }
   122  
   123  
   124  func Benchmark{{toTitle .ElementName}}Double(b *testing.B) {
   125  	benchRes{{.ElementName}}.SetRandom()
   126  	b.ResetTimer()
   127  	for i := 0; i < b.N; i++ {
   128  		benchRes{{.ElementName}}.Double(&benchRes{{.ElementName}})
   129  	}
   130  }
   131  
   132  
   133  func Benchmark{{toTitle .ElementName}}Add(b *testing.B) {
   134  	var x {{.ElementName}}
   135  	x.SetRandom()
   136  	benchRes{{.ElementName}}.SetRandom()
   137  	b.ResetTimer()
   138  	for i := 0; i < b.N; i++ {
   139  		benchRes{{.ElementName}}.Add(&x, &benchRes{{.ElementName}})
   140  	}
   141  }
   142  
   143  func Benchmark{{toTitle .ElementName}}Sub(b *testing.B) {
   144  	var x {{.ElementName}}
   145  	x.SetRandom()
   146  	benchRes{{.ElementName}}.SetRandom()
   147  	b.ResetTimer()
   148  	for i := 0; i < b.N; i++ {
   149  		benchRes{{.ElementName}}.Sub(&x, &benchRes{{.ElementName}})
   150  	}
   151  }
   152  
   153  func Benchmark{{toTitle .ElementName}}Neg(b *testing.B) {
   154  	benchRes{{.ElementName}}.SetRandom()
   155  	b.ResetTimer()
   156  	for i := 0; i < b.N; i++ {
   157  		benchRes{{.ElementName}}.Neg(&benchRes{{.ElementName}})
   158  	}
   159  }
   160  
   161  func Benchmark{{toTitle .ElementName}}Div(b *testing.B) {
   162  	var x {{.ElementName}}
   163  	x.SetRandom()
   164  	benchRes{{.ElementName}}.SetRandom()
   165  	b.ResetTimer()
   166  	for i := 0; i < b.N; i++ {
   167  		benchRes{{.ElementName}}.Div(&x, &benchRes{{.ElementName}})
   168  	}
   169  }
   170  
   171  
   172  func Benchmark{{toTitle .ElementName}}FromMont(b *testing.B) {
   173  	benchRes{{.ElementName}}.SetRandom()
   174  	b.ResetTimer()
   175  	for i := 0; i < b.N; i++ {
   176  		benchRes{{.ElementName}}.fromMont()
   177  	}
   178  }
   179  
   180  func Benchmark{{toTitle .ElementName}}Square(b *testing.B) {
   181  	benchRes{{.ElementName}}.SetRandom()
   182  	b.ResetTimer()
   183  	for i := 0; i < b.N; i++ {
   184  		benchRes{{.ElementName}}.Square(&benchRes{{.ElementName}})
   185  	}
   186  }
   187  
   188  func Benchmark{{toTitle .ElementName}}Sqrt(b *testing.B) {
   189  	var a {{.ElementName}}
   190  	a.SetUint64(4)
   191  	a.Neg(&a)
   192  	b.ResetTimer()
   193  	for i := 0; i < b.N; i++ {
   194  		benchRes{{.ElementName}}.Sqrt(&a)
   195  	}
   196  }
   197  
   198  func Benchmark{{toTitle .ElementName}}Mul(b *testing.B) {
   199  	x := {{.ElementName}}{
   200  		{{- range $i := .RSquare}}
   201  		{{$i}},{{end}}
   202  	}
   203  	benchRes{{.ElementName}}.SetOne()
   204  	b.ResetTimer()
   205  	for i := 0; i < b.N; i++ {
   206  		benchRes{{.ElementName}}.Mul(&benchRes{{.ElementName}}, &x)
   207  	}
   208  }
   209  
   210  func Benchmark{{toTitle .ElementName}}Cmp(b *testing.B) {
   211  	x := {{.ElementName}}{
   212  		{{- range $i := .RSquare}}
   213  		{{$i}},{{end}}
   214  	}
   215  	benchRes{{.ElementName}} = x 
   216  	benchRes{{.ElementName}}[0] = 0
   217  	b.ResetTimer()
   218  	for i := 0; i < b.N; i++ {
   219  		benchRes{{.ElementName}}.Cmp(&x)
   220  	}
   221  }
   222  
   223  func Test{{toTitle .ElementName}}Cmp(t *testing.T) {
   224  	var x, y {{.ElementName}}
   225  	
   226  	if x.Cmp(&y) != 0 {
   227  		t.Fatal("x == y")
   228  	}
   229  
   230  	one := One()
   231  	y.Sub(&y, &one)
   232  
   233  	if x.Cmp(&y) != -1 {
   234  		t.Fatal("x < y")
   235  	}
   236  	if y.Cmp(&x) != 1 {
   237  		t.Fatal("x < y")
   238  	}
   239  
   240  	x = y 
   241  	if x.Cmp(&y) != 0 {
   242  		t.Fatal("x == y")
   243  	}
   244  
   245  	x.Sub(&x, &one)
   246  	if x.Cmp(&y) != -1 {
   247  		t.Fatal("x < y")
   248  	}
   249  	if y.Cmp(&x) != 1 {
   250  		t.Fatal("x < y")
   251  	}
   252  }
   253  
   254  {{- if gt .NbWords 1}}
   255  func Test{{toTitle .ElementName}}IsRandom(t *testing.T) {
   256  	for i := 0; i < 50; i++ {
   257  		var x, y {{.ElementName}}
   258  		x.SetRandom()
   259  		y.SetRandom()
   260  		if x.Equal(&y) {
   261  			t.Fatal("2 random numbers are unlikely to be equal")
   262  		}
   263  	}
   264  }
   265  
   266  func Test{{toTitle .ElementName}}IsUint64(t *testing.T) {
   267  	t.Parallel()
   268  	parameters := gopter.DefaultTestParameters()
   269  	if testing.Short() {
   270  		parameters.MinSuccessfulTests = nbFuzzShort
   271  	} else {
   272  		parameters.MinSuccessfulTests = nbFuzz
   273  	}
   274  
   275  	properties := gopter.NewProperties(parameters)
   276  
   277  
   278  	properties.Property("reduce should output a result smaller than modulus", prop.ForAll(
   279  		func(v uint64) bool {
   280  			var e {{.ElementName}}
   281  			e.SetUint64(v)
   282  
   283  			if !e.IsUint64() {
   284  				return false
   285  			}
   286  
   287  			return e.Uint64() == v
   288  		},
   289  		ggen.UInt64(),
   290  	))
   291  
   292  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   293  }
   294  
   295  {{- end}}
   296  
   297  func Test{{toTitle .ElementName}}NegZero(t *testing.T) {
   298  	var a, b {{.ElementName}}
   299  	b.SetZero()
   300  	for a.IsZero() {
   301  		a.SetRandom()
   302  	}
   303  	a.Neg(&b)
   304  	if !a.IsZero() {
   305  		t.Fatal("neg(0) != 0")
   306  	}
   307  }
   308  
   309  // -------------------------------------------------------------------------------------------------
   310  // Gopter tests
   311  // most of them are generated with a template
   312  
   313  {{ if gt .NbWords 6}}
   314  const (
   315  	nbFuzzShort = 20
   316  	nbFuzz = 100
   317  )
   318  {{else}}
   319  const (
   320  	nbFuzzShort = 200
   321  	nbFuzz = 1000
   322  )
   323  {{end}}
   324  
   325  // special values to be used in tests
   326  var staticTestValues []{{.ElementName}}
   327  
   328  func init() {
   329  	staticTestValues = append(staticTestValues, {{.ElementName}}{}) // zero
   330  	staticTestValues = append(staticTestValues, One()) 				// one
   331  	staticTestValues = append(staticTestValues, rSquare) 			// r²
   332  	var e, one {{.ElementName}}
   333  	one.SetOne()
   334  	e.Sub(&q{{.ElementName}}, &one)
   335  	staticTestValues = append(staticTestValues, e) 	// q - 1
   336  	e.Double(&one)
   337  	staticTestValues = append(staticTestValues, e) 	// 2 
   338  
   339  
   340  	{
   341  		a := q{{.ElementName}}
   342  		a[0]--
   343  		staticTestValues = append(staticTestValues, a)
   344  	}
   345  
   346  	{{- $qi := index $.Q $.NbWordsLastIndex}}
   347  	{{- range $i := iterate 0 3}}
   348  		staticTestValues = append(staticTestValues, {{$.ElementName}}{ {{$i}} })
   349  		{{- if gt $.NbWords 1}}
   350  			{{- if le $i $qi}}
   351  			staticTestValues = append(staticTestValues, {{$.ElementName}}{0, {{$i}} })
   352  			{{- end}}
   353  		{{- end}}
   354  	{{- end}}
   355  
   356  	{
   357  		a := q{{.ElementName}}
   358  		a[{{.NbWordsLastIndex}}]--
   359  		staticTestValues = append(staticTestValues, a)
   360  	}
   361  
   362  	{{- if ne .NbWords 1}}
   363  	{
   364  		a := q{{.ElementName}}
   365  		a[{{.NbWordsLastIndex}}]--
   366  		a[0]++
   367  		staticTestValues = append(staticTestValues, a)
   368  	}
   369  	{{- end}}
   370  
   371  	{
   372  		a := q{{.ElementName}}
   373  		a[{{.NbWordsLastIndex}}] = 0
   374  		staticTestValues = append(staticTestValues, a)
   375  	}
   376  
   377  }
   378  
   379  func Test{{toTitle .ElementName}}Reduce(t *testing.T) {
   380  	testValues := make([]{{.ElementName}}, len(staticTestValues))
   381  	copy(testValues, staticTestValues)
   382  
   383  	for i := range testValues {
   384  		s := testValues[i]
   385  		expected := s
   386  		reduce(&s)
   387  		_reduceGeneric(&expected)
   388  		if !s.Equal(&expected) {
   389  			t.Fatal("reduce failed: asm and generic impl don't match")
   390  		}
   391  	}
   392  
   393  
   394  	t.Parallel()
   395  	parameters := gopter.DefaultTestParameters()
   396  	if testing.Short() {
   397  		parameters.MinSuccessfulTests = nbFuzzShort
   398  	} else {
   399  		parameters.MinSuccessfulTests = nbFuzz
   400  	}
   401  
   402  	properties := gopter.NewProperties(parameters)
   403  
   404  	genA := genFull()
   405  
   406  	properties.Property("reduce should output a result smaller than modulus", prop.ForAll(
   407  		func(a {{.ElementName}}) bool {
   408  			b := a
   409  			reduce(&a)
   410  			_reduceGeneric(&b)
   411  			return a.smallerThanModulus()  && a.Equal(&b)
   412  		},
   413  		genA,
   414  	))
   415  
   416  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   417  
   418  	
   419  }
   420  
   421  func Test{{toTitle .ElementName}}Equal(t *testing.T) {
   422  	t.Parallel()
   423  	parameters := gopter.DefaultTestParameters()
   424  	if testing.Short() {
   425  		parameters.MinSuccessfulTests = nbFuzzShort
   426  	} else {
   427  		parameters.MinSuccessfulTests = nbFuzz
   428  	}
   429  
   430  	properties := gopter.NewProperties(parameters)
   431  
   432  	genA := gen()
   433  	genB := gen()
   434  
   435  	properties.Property("x.Equal(&y) iff x == y; likely false for random pairs", prop.ForAll(
   436  		func(a testPair{{.ElementName}}, b testPair{{.ElementName}}) bool {
   437  			return a.element.Equal(&b.element) == (a.element == b.element)
   438  		},
   439  		genA,
   440  		genB,
   441  	))
   442  
   443  	properties.Property("x.Equal(&y) if x == y", prop.ForAll(
   444  		func(a testPair{{.ElementName}}) bool {
   445  			b := a.element
   446  			return a.element.Equal(&b)
   447  		},
   448  		genA,
   449  	))
   450  
   451  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   452  }
   453  
   454  func Test{{toTitle .ElementName}}Bytes(t *testing.T) {
   455  	t.Parallel()
   456  	parameters := gopter.DefaultTestParameters()
   457  	if testing.Short() {
   458  		parameters.MinSuccessfulTests = nbFuzzShort
   459  	} else {
   460  		parameters.MinSuccessfulTests = nbFuzz
   461  	}
   462  
   463  	properties := gopter.NewProperties(parameters)
   464  
   465  	genA := gen()
   466  
   467  	properties.Property("SetBytes(Bytes()) should stay constant", prop.ForAll(
   468  		func(a testPair{{.ElementName}}) bool {
   469  			var b {{.ElementName}}
   470  			bytes := a.element.Bytes()
   471  			b.SetBytes(bytes[:])
   472  			return a.element.Equal(&b)
   473  		},
   474  		genA,
   475  	))
   476  
   477  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   478  }
   479  
   480  func Test{{toTitle .ElementName}}InverseExp(t *testing.T) {
   481  	// inverse must be equal to exp^-2
   482  	exp := Modulus()
   483  	exp.Sub(exp, new(big.Int).SetUint64(2))
   484  
   485  	invMatchExp := func(a testPair{{.ElementName}}) bool {
   486  		var b {{.ElementName}}
   487  		b.Set(&a.element)
   488  		a.element.Inverse(&a.element)
   489  		b.Exp(b, exp)
   490  
   491  		return a.element.Equal(&b)
   492  	}
   493  
   494  	t.Parallel()
   495  	parameters := gopter.DefaultTestParameters()
   496  	if testing.Short() {
   497  		parameters.MinSuccessfulTests = nbFuzzShort
   498  	} else {
   499  		parameters.MinSuccessfulTests = nbFuzz
   500  	}
   501  	properties := gopter.NewProperties(parameters)
   502  	genA := gen()
   503  	properties.Property("inv == exp^-2", prop.ForAll(invMatchExp, genA))
   504  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   505  
   506  	parameters.MinSuccessfulTests = 1
   507  	properties = gopter.NewProperties(parameters)
   508  	properties.Property("inv(0) == 0", prop.ForAll(invMatchExp, ggen.OneConstOf(testPair{{.ElementName}}{})))
   509  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   510  
   511  
   512  }
   513  
   514  
   515  func mulByConstant(z *{{.ElementName}}, c uint8) {
   516  	var y {{.ElementName}}
   517  	y.SetUint64(uint64(c))
   518  	z.Mul(z, &y)
   519  }
   520  
   521  
   522  func Test{{toTitle .ElementName}}MulByConstants(t *testing.T) {
   523  
   524  	t.Parallel()
   525  	parameters := gopter.DefaultTestParameters()
   526  	if testing.Short() {
   527  		parameters.MinSuccessfulTests = nbFuzzShort
   528  	} else {
   529  		parameters.MinSuccessfulTests = nbFuzz
   530  	}
   531  
   532  	properties := gopter.NewProperties(parameters)
   533  
   534  	genA := gen()
   535  
   536  	implemented := []uint8{0,1,2,3,5,13}
   537  	properties.Property("mulByConstant", prop.ForAll(
   538  		func(a testPair{{.ElementName}}) bool {
   539  			for _, c := range implemented {
   540  				var constant {{.ElementName}}
   541  				constant.SetUint64(uint64(c))
   542  	
   543  				b := a.element 
   544  				b.Mul(&b, &constant)
   545  
   546  				aa := a.element
   547  				mulByConstant(&aa, c)
   548  
   549  				if !aa.Equal(&b) {
   550  					return false
   551  				}
   552  			}
   553  			
   554  			return true
   555  		},
   556  		genA,
   557  	))
   558  	
   559  
   560  	properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll(
   561  		func(a testPair{{.ElementName}}) bool {
   562  			var constant {{.ElementName}}
   563  			constant.SetUint64(3)
   564  
   565  			b := a.element 
   566  			b.Mul(&b, &constant)
   567  
   568  			MulBy3(&a.element)
   569  
   570  			return a.element.Equal(&b)
   571  		},
   572  		genA,
   573  	))
   574  
   575  	properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll(
   576  		func(a testPair{{.ElementName}}) bool {
   577  			var constant {{.ElementName}}
   578  			constant.SetUint64(5)
   579  
   580  			b := a.element 
   581  			b.Mul(&b, &constant)
   582  
   583  			MulBy5(&a.element)
   584  
   585  			return a.element.Equal(&b)
   586  		},
   587  		genA,
   588  	))
   589  
   590  	properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll(
   591  		func(a testPair{{.ElementName}}) bool {
   592  			var constant {{.ElementName}}
   593  			constant.SetUint64(13)
   594  
   595  			b := a.element 
   596  			b.Mul(&b, &constant)
   597  
   598  			MulBy13(&a.element)
   599  
   600  			return a.element.Equal(&b)
   601  		},
   602  		genA,
   603  	))
   604  
   605  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   606  
   607  	
   608  }
   609  
   610  func Test{{toTitle .ElementName}}Legendre(t *testing.T) {
   611  	t.Parallel()
   612  	parameters := gopter.DefaultTestParameters()
   613  	if testing.Short() {
   614  		parameters.MinSuccessfulTests = nbFuzzShort
   615  	} else {
   616  		parameters.MinSuccessfulTests = nbFuzz
   617  	}
   618  
   619  	properties := gopter.NewProperties(parameters)
   620  
   621  	genA := gen()
   622  
   623  	properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll(
   624  		func(a testPair{{.ElementName}}) bool {
   625  			return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus()) 
   626  		},
   627  		genA,
   628  	))
   629  
   630  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   631  
   632  	
   633  }
   634  
   635  func Test{{toTitle .ElementName}}BitLen(t *testing.T) {
   636  	t.Parallel()
   637  	parameters := gopter.DefaultTestParameters()
   638  	if testing.Short() {
   639  		parameters.MinSuccessfulTests = nbFuzzShort
   640  	} else {
   641  		parameters.MinSuccessfulTests = nbFuzz
   642  	}
   643  
   644  	properties := gopter.NewProperties(parameters)
   645  
   646  	genA := gen()
   647  
   648  	properties.Property("BitLen should output same result than big.Int.BitLen", prop.ForAll(
   649  		func(a testPair{{.ElementName}}) bool {
   650  			return a.element.fromMont().BitLen() ==  a.bigint.BitLen()
   651  		},
   652  		genA,
   653  	))
   654  
   655  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   656  
   657  	
   658  }
   659  
   660  
   661  
   662  func Test{{toTitle .ElementName}}Butterflies(t *testing.T) {
   663  
   664  	t.Parallel()
   665  	parameters := gopter.DefaultTestParameters()
   666  	if testing.Short() {
   667  		parameters.MinSuccessfulTests = nbFuzzShort
   668  	} else {
   669  		parameters.MinSuccessfulTests = nbFuzz
   670  	}
   671  
   672  	properties := gopter.NewProperties(parameters)
   673  
   674  	genA := gen()
   675  
   676  	properties.Property("butterfly0 == a -b; a +b", prop.ForAll(
   677  		func(a,b testPair{{.ElementName}}) bool {
   678  			a0, b0 := a.element, b.element 
   679  			
   680  			_butterflyGeneric(&a.element, &b.element)
   681  			Butterfly(&a0, &b0)
   682  
   683  			return a.element.Equal(&a0) && b.element.Equal(&b0)
   684  		},
   685  		genA,
   686  		genA,
   687  	))
   688  
   689  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   690  
   691  
   692  }
   693  
   694  func Test{{toTitle .ElementName}}LexicographicallyLargest(t *testing.T) {
   695  	t.Parallel()
   696  	parameters := gopter.DefaultTestParameters()
   697  	if testing.Short() {
   698  		parameters.MinSuccessfulTests = nbFuzzShort
   699  	} else {
   700  		parameters.MinSuccessfulTests = nbFuzz
   701  	}
   702  
   703  	properties := gopter.NewProperties(parameters)
   704  
   705  	genA := gen()
   706  
   707  	properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll(
   708  		func(a testPair{{.ElementName}}) bool {
   709  			var negA {{.ElementName}}
   710  			negA.Neg(&a.element)
   711  
   712  			cmpResult := a.element.Cmp(&negA)
   713  			lResult := a.element.LexicographicallyLargest()
   714  
   715  			if lResult && cmpResult == 1 {
   716  				return true 
   717  			}
   718  			if !lResult && cmpResult !=1 {
   719  				return true
   720  			}
   721  			return false
   722  		},
   723  		genA,
   724  	))
   725  
   726  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   727  
   728  	
   729  }
   730  
   731  
   732  {{template "testBinaryOp" dict "all" . "Op" "Add"}}
   733  {{template "testBinaryOp" dict "all" . "Op" "Sub"}}
   734  {{template "testBinaryOp" dict "all" . "Op" "Mul" "GenericOp" "_mulGeneric"}}
   735  {{template "testBinaryOp" dict "all" . "Op" "Div"}}
   736  {{template "testBinaryOp" dict "all" . "Op" "Exp"}}
   737  
   738  {{template "testUnaryOp" dict "all" . "Op" "Square" }}
   739  {{template "testUnaryOp" dict "all" . "Op" "Inverse"}}
   740  {{template "testUnaryOp" dict "all" . "Op" "Sqrt"}}
   741  {{template "testUnaryOp" dict "all" . "Op" "Double"}}
   742  {{template "testUnaryOp" dict "all" . "Op" "Neg" }}
   743  
   744  {{ define "testBinaryOp" }}
   745  
   746  func Test{{toTitle .all.ElementName}}{{.Op}}(t *testing.T) {
   747  	t.Parallel()
   748  	parameters := gopter.DefaultTestParameters()
   749  	if testing.Short() {
   750  		parameters.MinSuccessfulTests = nbFuzzShort
   751  	} else {
   752  		parameters.MinSuccessfulTests = nbFuzz
   753  	}
   754  	
   755  
   756  	properties := gopter.NewProperties(parameters)
   757  
   758  	genA := gen()
   759  	genB := gen()
   760  
   761  	properties.Property("{{.Op}}: having the receiver as operand should output the same result", prop.ForAll(
   762  		func(a, b testPair{{.all.ElementName}}) bool {
   763  			var c, d {{.all.ElementName}}
   764  			d.Set(&a.element)
   765  			{{if eq .Op "Exp"}}
   766  				c.{{.Op}}(a.element, &b.bigint)
   767  				a.element.{{.Op}}(a.element, &b.bigint)
   768  				b.element.{{.Op}}(d, &b.bigint)
   769  			{{else}}
   770  				c.{{.Op}}(&a.element, &b.element)
   771  				a.element.{{.Op}}(&a.element, &b.element)
   772  				b.element.{{.Op}}(&d, &b.element)
   773  			{{end}}
   774  			return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
   775  		},
   776  		genA,
   777  		genB,
   778  	))
   779  
   780  	properties.Property("{{.Op}}: operation result must match big.Int result", prop.ForAll(
   781  		func(a, b testPair{{.all.ElementName}}) bool {
   782  			{
   783  				var c {{.all.ElementName}}
   784  				{{if eq .Op "Exp"}}
   785  					c.{{.Op}}(a.element, &b.bigint)
   786  				{{else}}
   787  					c.{{.Op}}(&a.element, &b.element)
   788  				{{end}}
   789  				var d, e big.Int 
   790  				{{- if eq .Op "Div"}}
   791  					d.ModInverse(&b.bigint, Modulus())
   792  					d.Mul(&d, &a.bigint).Mod(&d, Modulus())
   793  				{{- else if eq .Op "Exp"}}
   794  					d.Exp(&a.bigint, &b.bigint, Modulus())
   795  				{{- else}}
   796  					d.{{.Op}}(&a.bigint, &b.bigint).Mod(&d, Modulus())
   797  				{{- end }}
   798  
   799  
   800  				if c.BigInt(&e).Cmp(&d) != 0 {
   801  					return false
   802  				} 
   803  			}
   804  
   805  			// fixed elements
   806  			// a is random
   807  			// r takes special values
   808  			testValues := make([]{{.all.ElementName}}, len(staticTestValues))
   809  			copy(testValues, staticTestValues)
   810  
   811  			for i := range testValues {
   812  				r := testValues[i]
   813  				var d, e, rb big.Int 
   814  				r.BigInt(&rb) 
   815  
   816  				var c {{.all.ElementName}}
   817  				{{- if eq .Op "Div"}}
   818  					c.{{.Op}}(&a.element, &r)
   819  					d.ModInverse(&rb, Modulus())
   820  					d.Mul(&d, &a.bigint).Mod(&d, Modulus())
   821  				{{- else if eq .Op "Exp"}}
   822  					c.{{.Op}}(a.element, &rb)
   823  					d.Exp(&a.bigint, &rb, Modulus())
   824  				{{- else}}
   825  					c.{{.Op}}(&a.element, &r)
   826  					d.{{.Op}}(&a.bigint, &rb).Mod(&d, Modulus())
   827  				{{- end }}
   828  
   829  				{{if .GenericOp}}
   830  					// checking generic impl against asm path
   831  					var cGeneric {{.all.ElementName}}
   832  					{{.GenericOp}}(&cGeneric, &a.element, &r)
   833  					if !cGeneric.Equal(&c) {
   834  						// need to give context to failing error.
   835  						return false
   836  					}
   837  				{{end}}
   838  
   839  				if c.BigInt(&e).Cmp(&d) != 0 {
   840  					return false
   841  				} 
   842  			}
   843  			return true 
   844  		},
   845  		genA,
   846  		genB,
   847  	))
   848  
   849  	properties.Property("{{.Op}}: operation result must be smaller than modulus", prop.ForAll(
   850  		func(a, b testPair{{.all.ElementName}}) bool {
   851  			var c {{.all.ElementName}}
   852  			{{if eq .Op "Exp"}}
   853  				c.{{.Op}}(a.element, &b.bigint)
   854  			{{else}}
   855  				c.{{.Op}}(&a.element, &b.element)
   856  			{{end}}
   857  			return c.smallerThanModulus()
   858  		},
   859  		genA,
   860  		genB,
   861  	))
   862  
   863  	{{if .GenericOp}}
   864  	properties.Property("{{.Op}}: assembly implementation must be consistent with generic one", prop.ForAll(
   865  		func(a, b testPair{{.all.ElementName}}) bool {
   866  			var c,d {{.all.ElementName}}
   867  			c.{{.Op}}(&a.element, &b.element)
   868  			{{.GenericOp}}(&d, &a.element, &b.element)
   869  			return c.Equal(&d)
   870  		},
   871  		genA,
   872  		genB,
   873  	))
   874  
   875  	{{end}}
   876  
   877  
   878  	specialValueTest := func() {
   879  		// test special values against special values
   880  		testValues := make([]{{.all.ElementName}}, len(staticTestValues))
   881  		copy(testValues, staticTestValues)
   882  	
   883  		for i := range testValues {
   884  			a := testValues[i]
   885  			var aBig big.Int
   886  			a.BigInt(&aBig)
   887  			for j := range testValues {
   888  				b := testValues[j]
   889  				var bBig, d, e big.Int 
   890  				b.BigInt(&bBig)
   891  
   892  				var c {{.all.ElementName}}
   893  				
   894  
   895  
   896  				{{- if eq .Op "Div"}}
   897  					c.{{.Op}}(&a, &b)
   898  					d.ModInverse(&bBig, Modulus())
   899  					d.Mul(&d, &aBig).Mod(&d, Modulus())
   900  				{{- else if eq .Op "Exp"}}
   901  					c.{{.Op}}(a, &bBig)
   902  					d.Exp(&aBig, &bBig, Modulus())
   903  				{{- else}}
   904  					c.{{.Op}}(&a, &b)
   905  					d.{{.Op}}(&aBig, &bBig).Mod(&d, Modulus())
   906  				{{- end }}
   907  	
   908  				{{if .GenericOp}}
   909  					// checking asm against generic impl
   910  					var cGeneric {{.all.ElementName}}
   911  					{{.GenericOp}}(&cGeneric, &a, &b)
   912  					if !cGeneric.Equal(&c) {
   913  						t.Fatal("{{.Op}} failed special test values: asm and generic impl don't match")
   914  					}
   915  				{{end}}
   916  				
   917  
   918  				if c.BigInt(&e).Cmp(&d) != 0 {
   919  					t.Fatal("{{.Op}} failed special test values")
   920  				} 
   921  			}
   922  		}
   923  	}
   924  
   925  
   926  	properties.TestingRun(t, gopter.ConsoleReporter(false))
   927  	specialValueTest()
   928  
   929  }
   930  
   931  {{ end }}
   932  
   933  
   934  {{ define "testUnaryOp" }}
   935  
   936  func Test{{toTitle .all.ElementName}}{{.Op}}(t *testing.T) {
   937  	t.Parallel()
   938  	parameters := gopter.DefaultTestParameters()
   939  	if testing.Short() {
   940  		parameters.MinSuccessfulTests = nbFuzzShort
   941  	} else {
   942  		parameters.MinSuccessfulTests = nbFuzz
   943  	}
   944  
   945  	properties := gopter.NewProperties(parameters)
   946  
   947  	genA := gen()
   948  
   949  	properties.Property("{{.Op}}: having the receiver as operand should output the same result", prop.ForAll(
   950  		func(a testPair{{.all.ElementName}}) bool {
   951  			{{if eq .Op "Sqrt"}}
   952  			b := a.element
   953  			{{else}}
   954  			var b {{.all.ElementName}}
   955  			{{end}}
   956  			b.{{.Op}}(&a.element)
   957  			a.element.{{.Op}}(&a.element)
   958  			return a.element.Equal(&b)
   959  		},
   960  		genA,
   961  	))
   962  
   963  	properties.Property("{{.Op}}: operation result must match big.Int result", prop.ForAll(
   964  		func(a testPair{{.all.ElementName}}) bool {
   965  			var c {{.all.ElementName}}
   966  			c.{{.Op}}(&a.element)
   967  
   968  			var d, e big.Int 
   969  			{{- if eq .Op "Square"}}
   970  				d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus())
   971  			{{- else if eq .Op "Inverse"}}
   972  				d.ModInverse(&a.bigint, Modulus())
   973  			{{- else if eq .Op "Sqrt"}}
   974  				d.ModSqrt(&a.bigint, Modulus())
   975  			{{- else if eq .Op "Double"}}
   976  				d.Lsh(&a.bigint, 1).Mod(&d, Modulus())
   977  			{{- else if eq .Op "Neg"}}
   978  				d.Neg(&a.bigint).Mod(&d, Modulus())
   979  			{{- end }}
   980  
   981  
   982  			return c.BigInt(&e).Cmp(&d) == 0
   983  		},
   984  		genA,
   985  	))
   986  
   987  	properties.Property("{{.Op}}: operation result must be smaller than modulus", prop.ForAll(
   988  		func(a testPair{{.all.ElementName}}) bool {
   989  			var c {{.all.ElementName}}
   990  			c.{{.Op}}(&a.element)
   991  			return c.smallerThanModulus()
   992  		},
   993  		genA,
   994  	))
   995  
   996  	{{if .GenericOp}}
   997  	properties.Property("{{.Op}}: assembly implementation must be consistent with generic one", prop.ForAll(
   998  		func(a testPair{{.all.ElementName}}) bool {
   999  			var c,d {{.all.ElementName}}
  1000  			c.{{.Op}}(&a.element)
  1001  			{{.GenericOp}}(&d, &a.element)
  1002  			return c.Equal(&d)
  1003  		},
  1004  		genA,
  1005  	))
  1006  
  1007  	{{end}}
  1008  
  1009  
  1010  	specialValueTest := func() {
  1011  		// test special values
  1012  		testValues := make([]{{.all.ElementName}}, len(staticTestValues))
  1013  		copy(testValues, staticTestValues)
  1014  	
  1015  		for i := range testValues {
  1016  			a := testValues[i]
  1017  			var aBig big.Int
  1018  			a.BigInt(&aBig)
  1019  			var c {{.all.ElementName}}
  1020  			c.{{.Op}}(&a)
  1021  
  1022  			var  d, e big.Int 
  1023  			{{- if eq .Op "Square"}}
  1024  				d.Mul(&aBig, &aBig).Mod(&d, Modulus())
  1025  			{{- else if eq .Op "Inverse"}}
  1026  				d.ModInverse(&aBig, Modulus())
  1027  			{{- else if eq .Op "Sqrt"}}
  1028  				d.ModSqrt(&aBig, Modulus())
  1029  			{{- else if eq .Op "Double"}}
  1030  				d.Lsh(&aBig, 1).Mod(&d, Modulus())
  1031  			{{- else if eq .Op "Neg"}}
  1032  				d.Neg(&aBig).Mod(&d, Modulus())
  1033  			{{- end }}
  1034  
  1035  			{{if .GenericOp}}
  1036  				// checking asm against generic impl
  1037  				var cGeneric {{.all.ElementName}}
  1038  				{{.GenericOp}}(&cGeneric, &a)
  1039  				if !cGeneric.Equal(&c) {
  1040  					t.Fatal("{{.Op}} failed special test values: asm and generic impl don't match")
  1041  				}
  1042  			{{end}}
  1043  			
  1044  
  1045  			if c.BigInt(&e).Cmp(&d) != 0 {
  1046  				t.Fatal("{{.Op}} failed special test values")
  1047  			} 
  1048  		}
  1049  	}
  1050  
  1051  
  1052  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1053  	specialValueTest()
  1054  
  1055  }
  1056  
  1057  {{ end }}
  1058  
  1059  {{ if .UseAddChain}}
  1060  func Test{{toTitle .ElementName}}FixedExp(t *testing.T) {
  1061  
  1062  	t.Parallel()
  1063  	parameters := gopter.DefaultTestParameters()
  1064  	if testing.Short() {
  1065  		parameters.MinSuccessfulTests = nbFuzzShort
  1066  	} else {
  1067  		parameters.MinSuccessfulTests = nbFuzz
  1068  	}
  1069  
  1070  	properties := gopter.NewProperties(parameters)
  1071  
  1072  	var (
  1073  		_bLegendreExponent{{.ElementName}} *big.Int
  1074  		_bSqrtExponent{{.ElementName}} *big.Int
  1075  	)
  1076  
  1077  	_bLegendreExponent{{.ElementName}}, _ = new(big.Int).SetString("{{.LegendreExponent}}", 16)
  1078  	{{- if .SqrtQ3Mod4}}
  1079  		const sqrtExponent{{.ElementName}} = "{{.SqrtQ3Mod4Exponent}}"
  1080  	{{- else if .SqrtAtkin}}
  1081  		const sqrtExponent{{.ElementName}} = "{{.SqrtAtkinExponent}}"
  1082  	{{- else if .SqrtTonelliShanks}}
  1083  		const sqrtExponent{{.ElementName}} = "{{.SqrtSMinusOneOver2}}"
  1084  	{{- end }}
  1085  	_bSqrtExponent{{.ElementName}}, _ = new(big.Int).SetString(sqrtExponent{{.ElementName}}, 16)
  1086  
  1087  	genA := gen()
  1088  
  1089  	properties.Property(fmt.Sprintf("expBySqrtExp must match Exp(%s)", sqrtExponent{{.ElementName}}), prop.ForAll(
  1090  		func(a testPair{{.ElementName}}) bool {
  1091  			c := a.element
  1092  			d := a.element
  1093  			c.expBySqrtExp(c)
  1094  			d.Exp(d, _bSqrtExponent{{.ElementName}})
  1095  			return c.Equal(&d)
  1096  		},
  1097  		genA,
  1098  	))
  1099  
  1100  	properties.Property("expByLegendreExp must match Exp({{.LegendreExponent}})", prop.ForAll(
  1101  		func(a testPair{{.ElementName}}) bool {
  1102  			c := a.element
  1103  			d := a.element
  1104  			c.expByLegendreExp(c)
  1105  			d.Exp(d, _bLegendreExponent{{.ElementName}})
  1106  			return c.Equal(&d)
  1107  		},
  1108  		genA,
  1109  	))
  1110  
  1111  
  1112  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1113  }
  1114  
  1115  {{ end }}
  1116  
  1117  
  1118  
  1119  
  1120  
  1121  func Test{{toTitle .ElementName}}Halve(t *testing.T) {
  1122  
  1123  	t.Parallel()
  1124  	parameters := gopter.DefaultTestParameters()
  1125  	if testing.Short() {
  1126  		parameters.MinSuccessfulTests = nbFuzzShort
  1127  	} else {
  1128  		parameters.MinSuccessfulTests = nbFuzz
  1129  	}
  1130  
  1131  	properties := gopter.NewProperties(parameters)
  1132  
  1133  	genA := gen()
  1134  	var twoInv {{.ElementName}}
  1135  	twoInv.SetUint64(2)
  1136  	twoInv.Inverse(&twoInv)
  1137  
  1138  	properties.Property("z.Halve must match z / 2", prop.ForAll(
  1139  		func(a testPair{{.ElementName}}) bool {
  1140  			c := a.element
  1141  			d := a.element
  1142  			c.Halve()
  1143  			d.Mul(&d, &twoInv)
  1144  			return c.Equal(&d)
  1145  		},
  1146  		genA,
  1147  	))
  1148  
  1149  
  1150  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1151  }
  1152  
  1153  func combineSelectionArguments(c int64, z int8) int {
  1154  	if z%3 == 0 {
  1155  		return 0
  1156  	}
  1157  	return int(c)
  1158  }
  1159  
  1160  func Test{{toTitle .ElementName}}Select(t *testing.T) {
  1161  	t.Parallel()
  1162  	parameters := gopter.DefaultTestParameters()
  1163  	if testing.Short() {
  1164  		parameters.MinSuccessfulTests = nbFuzzShort
  1165  	} else {
  1166  		parameters.MinSuccessfulTests = nbFuzz
  1167  	}
  1168  
  1169  	properties := gopter.NewProperties(parameters)
  1170  
  1171  	genA := genFull()
  1172  	genB := genFull()
  1173  	genC := ggen.Int64()	//the condition
  1174  	genZ := ggen.Int8()	//to make zeros artificially more likely
  1175  
  1176  	properties.Property("Select: must select correctly", prop.ForAll(
  1177  		func(a, b {{.ElementName}}, cond int64, z int8) bool {
  1178  			condC := combineSelectionArguments(cond, z)
  1179  
  1180  			var c {{.ElementName}}
  1181  			c.Select(condC, &a, &b)
  1182  			
  1183  			if condC == 0 {
  1184  				return c.Equal(&a)
  1185  			}
  1186  			return c.Equal(&b)
  1187  		},
  1188  		genA,
  1189  		genB,
  1190  		genC,
  1191  		genZ,
  1192  	))
  1193  
  1194  	properties.Property("Select: having the receiver as operand should output the same result", prop.ForAll(
  1195  		func(a, b {{.ElementName}}, cond int64, z int8) bool {
  1196  			condC := combineSelectionArguments(cond, z)
  1197  			
  1198  			var c, d {{.ElementName}}
  1199  			d.Set(&a)
  1200  			c.Select(condC, &a, &b)
  1201  			a.Select(condC, &a, &b)
  1202  			b.Select(condC, &d, &b)
  1203  			return a.Equal(&b) && a.Equal(&c) && b.Equal(&c)
  1204  		},
  1205  		genA,
  1206  		genB,
  1207  		genC,
  1208  		genZ,
  1209  	))
  1210  
  1211  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1212  }
  1213  
  1214  func Test{{toTitle .ElementName}}SetInt64(t *testing.T) {
  1215  
  1216  	t.Parallel()
  1217  	parameters := gopter.DefaultTestParameters()
  1218  	if testing.Short() {
  1219  		parameters.MinSuccessfulTests = nbFuzzShort
  1220  	} else {
  1221  		parameters.MinSuccessfulTests = nbFuzz
  1222  	}
  1223  
  1224  	properties := gopter.NewProperties(parameters)
  1225  
  1226  	genA := gen()
  1227  
  1228  	properties.Property("z.SetInt64 must match z.SetString", prop.ForAll(
  1229  		func(a testPair{{.ElementName}}, v int64) bool {
  1230  			c := a.element
  1231  			d := a.element
  1232  
  1233  			c.SetInt64(v)
  1234  			d.SetString(fmt.Sprintf("%v",v))
  1235  
  1236  			return c.Equal(&d)
  1237  		},
  1238  		genA, ggen.Int64(),
  1239  	))
  1240  
  1241  
  1242  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1243  }
  1244  
  1245  
  1246  func Test{{toTitle .ElementName}}SetInterface(t *testing.T) {
  1247  
  1248  	t.Parallel()
  1249  	parameters := gopter.DefaultTestParameters()
  1250  	if testing.Short() {
  1251  		parameters.MinSuccessfulTests = nbFuzzShort
  1252  	} else {
  1253  		parameters.MinSuccessfulTests = nbFuzz
  1254  	}
  1255  
  1256  	properties := gopter.NewProperties(parameters)
  1257  
  1258  	genA := gen()
  1259  	genInt := ggen.Int
  1260  	genInt8 := ggen.Int8
  1261  	genInt16 := ggen.Int16
  1262  	genInt32 := ggen.Int32
  1263  	genInt64 := ggen.Int64
  1264  
  1265  	genUint := ggen.UInt
  1266  	genUint8 := ggen.UInt8
  1267  	genUint16 := ggen.UInt16
  1268  	genUint32 := ggen.UInt32
  1269  	genUint64 := ggen.UInt64
  1270  
  1271  	{{setInterface .ElementName "int8"}}
  1272  	{{setInterface .ElementName "int16"}}
  1273  	{{setInterface .ElementName "int32"}}
  1274  	{{setInterface .ElementName "int64"}}
  1275  	{{setInterface .ElementName "int"}}
  1276  
  1277  	{{setInterface .ElementName "uint8"}}
  1278  	{{setInterface .ElementName "uint16"}}
  1279  	{{setInterface .ElementName "uint32"}}
  1280  	{{setInterface .ElementName "uint64"}}
  1281  	{{setInterface .ElementName "uint"}}
  1282  
  1283  
  1284  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1285  
  1286  	{
  1287  		assert := require.New(t)
  1288  		var e {{.ElementName}}
  1289  		r, err := e.SetInterface(nil)
  1290  		assert.Nil(r)
  1291  		assert.Error(err)
  1292  
  1293  		var ptE *{{.ElementName}}
  1294  		var ptB *big.Int
  1295  
  1296  		r, err = e.SetInterface(ptE)
  1297  		assert.Nil(r)
  1298  		assert.Error(err)
  1299  		ptE = new({{.ElementName}}).SetOne()
  1300  		r, err = e.SetInterface(ptE)
  1301  		assert.NoError(err)
  1302  		assert.True(r.IsOne())
  1303  
  1304  		r, err = e.SetInterface(ptB)
  1305  		assert.Nil(r)
  1306  		assert.Error(err)
  1307  
  1308  	}
  1309  }
  1310  
  1311  
  1312  {{define "setInterface eName tName"}}
  1313  
  1314  properties.Property("z.SetInterface must match z.SetString with {{.tName}}", prop.ForAll(
  1315  	func(a testPair{{.eName}}, v {{.tName}}) bool {
  1316  		c := a.element
  1317  		d := a.element
  1318  
  1319  		c.SetInterface(v)
  1320  		d.SetString(fmt.Sprintf("%v",v))
  1321  
  1322  		return c.Equal(&d)
  1323  	},
  1324  	genA, gen{{toTitle .tName}}(),
  1325  ))
  1326  
  1327  {{end}}
  1328  
  1329  func Test{{toTitle .ElementName}}NegativeExp(t *testing.T) {
  1330  	t.Parallel()
  1331  
  1332  	parameters := gopter.DefaultTestParameters()
  1333  	if testing.Short() {
  1334  		parameters.MinSuccessfulTests = nbFuzzShort
  1335  	} else {
  1336  		parameters.MinSuccessfulTests = nbFuzz
  1337  	}
  1338  
  1339  	properties := gopter.NewProperties(parameters)
  1340  
  1341  	genA := gen()
  1342  	
  1343  	properties.Property("x⁻ᵏ == 1/xᵏ", prop.ForAll(
  1344  		func(a,b testPair{{.ElementName}}) bool {
  1345  
  1346  			var nb, d, e big.Int 
  1347  			nb.Neg(&b.bigint)
  1348  
  1349  			var c {{.ElementName}}
  1350  			c.Exp(a.element, &nb)
  1351  
  1352  			d.Exp(&a.bigint, &nb, Modulus())
  1353  
  1354  			return c.BigInt(&e).Cmp(&d) == 0
  1355  		},
  1356  		genA, genA,
  1357  	))
  1358  
  1359  
  1360  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1361  }
  1362  
  1363  func Test{{toTitle .ElementName}}New{{.ElementName}}(t *testing.T) {
  1364  	assert := require.New(t)
  1365  
  1366  	t.Parallel()
  1367  
  1368  	e := New{{.ElementName}}(1)
  1369  	assert.True(e.IsOne())
  1370  
  1371  	e = New{{.ElementName}}(0)
  1372  	assert.True(e.IsZero())
  1373  }
  1374  
  1375  
  1376  func Test{{toTitle .ElementName}}BatchInvert(t *testing.T) {
  1377  	assert := require.New(t)
  1378  
  1379  	t.Parallel()
  1380  
  1381  	// ensure batchInvert([x]) == invert(x)
  1382  	for i:=int64(-1); i <=2; i++ {
  1383  		var e, eInv {{.ElementName}}
  1384  		e.SetInt64(i)
  1385  		eInv.Inverse(&e)
  1386  
  1387  		a := []{{.ElementName}}{e}
  1388  		aInv := BatchInvert(a)
  1389  
  1390  		assert.True(aInv[0].Equal(&eInv), "batchInvert != invert")
  1391  
  1392  	}
  1393  
  1394  	// test x * x⁻¹ == 1
  1395  	tData := [][]int64 {
  1396  		[]int64{-1,1,2,3},
  1397  		[]int64{0, -1,1,2,3, 0},
  1398  		[]int64{0, -1,1,0, 2,3, 0},
  1399  		[]int64{-1,1,0, 2,3},
  1400  		[]int64{0,0,1},
  1401  		[]int64{1,0,0},
  1402  		[]int64{0,0,0},
  1403  	}
  1404  
  1405  	for _, t := range tData {
  1406  		a := make([]{{.ElementName}}, len(t))
  1407  		for i:=0; i <len(a);i++ {
  1408  			a[i].SetInt64(t[i])
  1409  		}
  1410  
  1411  		aInv := BatchInvert(a)
  1412  
  1413  		assert.True(len(aInv) == len(a))
  1414  
  1415  		for i:=0; i <len(a);i++ {
  1416  			if a[i].IsZero() {
  1417  				assert.True(aInv[i].IsZero(), "0⁻¹ != 0")
  1418  			} else {
  1419  				assert.True(a[i].Mul(&a[i], &aInv[i]).IsOne(), "x * x⁻¹ != 1")
  1420  			}
  1421  		}
  1422  	}
  1423  
  1424  
  1425  	parameters := gopter.DefaultTestParameters()
  1426  	if testing.Short() {
  1427  		parameters.MinSuccessfulTests = nbFuzzShort
  1428  	} else {
  1429  		parameters.MinSuccessfulTests = nbFuzz
  1430  	}
  1431  
  1432  	properties := gopter.NewProperties(parameters)
  1433  
  1434  	genA := gen()
  1435  
  1436  	properties.Property("batchInvert --> x * x⁻¹ == 1", prop.ForAll(
  1437  		func(tp testPair{{.ElementName}}, r uint8) bool {
  1438  
  1439  			a := make([]{{.ElementName}}, r)
  1440  			if r != 0 {
  1441  				a[0] = tp.element
  1442  
  1443  			}
  1444  			one := One()
  1445  			for i:=1; i <len(a);i++ {
  1446  				a[i].Add(&a[i-1], &one)
  1447  			}
  1448  	
  1449  			aInv := BatchInvert(a)
  1450  	
  1451  			assert.True(len(aInv) == len(a))
  1452  	
  1453  			for i:=0; i <len(a);i++ {
  1454  				if a[i].IsZero() {
  1455  					if !aInv[i].IsZero() {
  1456  						return false 
  1457  					}
  1458  				} else {
  1459  					if !a[i].Mul(&a[i], &aInv[i]).IsOne() {
  1460  						return false
  1461  					}
  1462  				}
  1463  			}
  1464  			return true
  1465  		},
  1466  		genA,ggen.UInt8(),
  1467  	))
  1468  
  1469  
  1470  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1471  }
  1472  
  1473  func Test{{toTitle .ElementName}}FromMont(t *testing.T) {
  1474  
  1475  	t.Parallel()
  1476  	parameters := gopter.DefaultTestParameters()
  1477  	if testing.Short() {
  1478  		parameters.MinSuccessfulTests = nbFuzzShort
  1479  	} else {
  1480  		parameters.MinSuccessfulTests = nbFuzz
  1481  	}
  1482  
  1483  	properties := gopter.NewProperties(parameters)
  1484  
  1485  	genA := gen()
  1486  
  1487  	properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll(
  1488  		func(a testPair{{.ElementName}}) bool {
  1489  			c := a.element
  1490  			d := a.element
  1491  			c.fromMont()
  1492  			_fromMontGeneric(&d)
  1493  			return c.Equal(&d)
  1494  		},
  1495  		genA,
  1496  	))
  1497  
  1498  	properties.Property("x.fromMont().toMont() == x", prop.ForAll(
  1499  		func(a testPair{{.ElementName}}) bool {
  1500  			c := a.element
  1501  			c.fromMont().toMont()
  1502  			return c.Equal(&a.element)
  1503  		},
  1504  		genA,
  1505  	))
  1506  
  1507  
  1508  	properties.TestingRun(t, gopter.ConsoleReporter(false))
  1509  }
  1510  
  1511  
  1512  
  1513  func Test{{toTitle .ElementName}}JSON(t *testing.T) {
  1514  	assert := require.New(t)
  1515  
  1516  	type S struct {
  1517  		A {{.ElementName}}
  1518  		B [3]{{.ElementName}}
  1519  		C *{{.ElementName}}
  1520  		D *{{.ElementName}}
  1521  	}
  1522  
  1523  	// encode to JSON
  1524  	var s S
  1525  	s.A.SetString("-1")
  1526  	s.B[2].SetUint64(42)
  1527  	s.D = new({{.ElementName}}).SetUint64(8000)
  1528  
  1529  	encoded, err := json.Marshal(&s)
  1530  	assert.NoError(err)
  1531  	{{- $noNeg := and (eq $.NbWords 1) (ltu64 (index $.Q 0) 1000000)}}
  1532  	// we may need to adjust "42" and "8000" values for some moduli; see Text() method for more details.
  1533  	formatValue := func(v int64) string {
  1534  		var a big.Int 
  1535  		a.SetInt64(v)
  1536  		a.Mod(&a, Modulus())
  1537  		{{- if not $noNeg}}
  1538  		const maxUint16 = 65535
  1539  		var aNeg big.Int 
  1540  		aNeg.Neg(&a).Mod(&aNeg, Modulus())
  1541  		if aNeg.Uint64() != 0 && aNeg.Uint64() <= maxUint16 {
  1542  			return "-"+aNeg.Text(10)
  1543  		}
  1544  		{{- end}}
  1545  		return a.Text(10)
  1546  	}
  1547  	expected := fmt.Sprintf("{\"A\":%s,\"B\":[0,0,%s],\"C\":null,\"D\":%s}", formatValue(-1), formatValue(42), formatValue(8000))
  1548  	assert.Equal(expected, string(encoded))
  1549  
  1550  	// decode valid
  1551  	var decoded S
  1552  	err = json.Unmarshal([]byte(expected), &decoded)
  1553  	assert.NoError(err)
  1554  
  1555  	assert.Equal(s, decoded, "element -> json -> element round trip failed")
  1556  
  1557  	// decode hex and string values
  1558  	withHexValues := "{\"A\":\"-1\",\"B\":[0,\"0x00000\",\"0x2A\"],\"C\":null,\"D\":\"8000\"}"
  1559  
  1560  	var decodedS S
  1561  	err = json.Unmarshal([]byte(withHexValues), &decodedS)
  1562  	assert.NoError(err)
  1563  
  1564  	assert.Equal(s, decodedS, " json with strings  -> element  failed")
  1565  
  1566  }
  1567  
  1568  type testPair{{.ElementName}} struct {
  1569  	element {{.ElementName}}
  1570  	bigint       big.Int
  1571  }
  1572  
  1573  
  1574  func gen() gopter.Gen {
  1575  	return func(genParams *gopter.GenParameters) *gopter.GenResult {
  1576  		var g testPair{{.ElementName}}
  1577  
  1578  		g.element = {{.ElementName}}{
  1579  			{{- range $i := .NbWordsIndexesFull}}
  1580  			genParams.NextUint64(),{{end}}
  1581  		}
  1582  		if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) {
  1583  			g.element[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 )
  1584  		}
  1585  		
  1586  
  1587  		for !g.element.smallerThanModulus() {
  1588  			g.element = {{.ElementName}}{
  1589  				{{- range $i := .NbWordsIndexesFull}}
  1590  				genParams.NextUint64(),{{end}}
  1591  			}
  1592  			if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) {
  1593  				g.element[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 )
  1594  			}
  1595  		}
  1596  
  1597  		g.element.BigInt(&g.bigint)
  1598  		genResult := gopter.NewGenResult(g, gopter.NoShrinker)
  1599  		return genResult
  1600  	}
  1601  }
  1602  
  1603  
  1604  func genFull() gopter.Gen {
  1605  	return func(genParams *gopter.GenParameters) *gopter.GenResult {
  1606  
  1607  		genRandomFq := func() {{.ElementName}} {
  1608  			var g {{.ElementName}}
  1609  
  1610  			g = {{.ElementName}}{
  1611  				{{- range $i := .NbWordsIndexesFull}}
  1612  				genParams.NextUint64(),{{end}}
  1613  			}
  1614  
  1615  			if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) {
  1616  				g[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 )
  1617  			}
  1618  
  1619  			for !g.smallerThanModulus() {
  1620  				g = {{.ElementName}}{
  1621  					{{- range $i := .NbWordsIndexesFull}}
  1622  					genParams.NextUint64(),{{end}}
  1623  				}
  1624  				if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) {
  1625  					g[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 )
  1626  				}
  1627  			}
  1628  
  1629  			return g 
  1630  		}
  1631  		a := genRandomFq()
  1632  
  1633  		var carry uint64
  1634  		{{- range $i := .NbWordsIndexesFull}}
  1635  			{{- if eq $i $.NbWordsLastIndex}}
  1636  			a[{{$i}}], _ = bits.Add64(a[{{$i}}], q{{$.ElementName}}[{{$i}}], carry)
  1637  			{{- else}}
  1638  			a[{{$i}}], carry = bits.Add64(a[{{$i}}], q{{$.ElementName}}[{{$i}}], carry)
  1639  			{{- end}}
  1640  		{{- end}}
  1641  		
  1642  		genResult := gopter.NewGenResult(a, gopter.NoShrinker)
  1643  		return genResult
  1644  	}
  1645  }
  1646  {{if $.UsingP20Inverse}}
  1647  func (z *{{.ElementName}}) matchVeryBigInt(aHi uint64, aInt *big.Int) error {
  1648  	var modulus big.Int
  1649  	var aIntMod big.Int
  1650  	modulus.SetInt64(1)
  1651  	modulus.Lsh(&modulus, (Limbs+1)*64)
  1652  	aIntMod.Mod(aInt, &modulus)
  1653  
  1654  	slice := append(z[:], aHi)
  1655  
  1656  	return bigIntMatchUint64Slice(&aIntMod, slice)
  1657  }
  1658  
  1659  //TODO: Phase out in favor of property based testing
  1660  func (z *{{.ElementName}}) assertMatchVeryBigInt(t *testing.T, aHi uint64, aInt *big.Int) {
  1661  
  1662  	if err := z.matchVeryBigInt(aHi, aInt); err != nil {
  1663  		t.Error(err)
  1664  	}
  1665  }
  1666  
  1667  
  1668  // bigIntMatchUint64Slice is a test helper to match big.Int words against a uint64 slice
  1669  func bigIntMatchUint64Slice(aInt *big.Int, a []uint64) error {
  1670  
  1671  	words := aInt.Bits()
  1672  
  1673  	const steps = 64 / bits.UintSize
  1674  	const filter uint64 = 0xFFFFFFFFFFFFFFFF >> (64 - bits.UintSize)
  1675  	for i := 0; i < len(a)*steps; i++ {
  1676  
  1677  		var wI big.Word
  1678  
  1679  		if i < len(words) {
  1680  			wI = words[i]
  1681  		}
  1682  
  1683  		aI := a[i/steps] >> ((i * bits.UintSize) % 64)
  1684  		aI &= filter
  1685  
  1686  		if uint64(wI) != aI {
  1687  			return fmt.Errorf("bignum mismatch: disagreement on word %d: %x ≠ %x; %d ≠ %d", i, uint64(wI), aI, uint64(wI), aI)
  1688  		}
  1689  	}
  1690  
  1691  	return nil
  1692  }
  1693  {{- end}}
  1694  
  1695  
  1696  
  1697  `