github.com/consensys/gnark-crypto@v0.14.0/internal/generator/iop/template/polynomial.test.go.tmpl (about)

     1  import (
     2  	"testing"
     3  
     4  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr"
     5  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr/fft"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"bytes"
    10  	"reflect"
    11  )
    12  
    13  func TestEvaluation(t *testing.T) {
    14  
    15  	size := 8
    16  	shift := 2
    17  	d := fft.NewDomain(uint64(size))
    18  	c := randomVector(size)
    19  	wp := NewPolynomial(c, Form{Basis: Canonical, Layout: Regular})
    20  	wps := wp.ShallowClone().Shift(shift)
    21  	ref := wp.Clone()
    22  	ref.ToLagrange(d).ToRegular()
    23  
    24  	// regular layout
    25  	a := wp.Evaluate(d.Generator)
    26  	b := wps.Evaluate(d.Generator)
    27  	if !a.Equal(&ref.Coefficients()[1]) {
    28  		t.Fatal("error evaluation")
    29  	}
    30  	if !b.Equal(&ref.Coefficients()[1+shift]) {
    31  		t.Fatal("error evaluation shifted")
    32  	}
    33  
    34  	// bit reversed layout
    35  	wp.ToBitReverse()
    36  	wps.ToBitReverse()
    37  	a = wp.Evaluate(d.Generator)
    38  	b = wps.Evaluate(d.Generator)
    39  	if !a.Equal(&ref.Coefficients()[1]) {
    40  		t.Fatal("error evaluation")
    41  	}
    42  	if !b.Equal(&ref.Coefficients()[1+shift]) {
    43  		t.Fatal("error evaluation shifted")
    44  	}
    45  
    46  }
    47  
    48  func randomVector(size int) *[]fr.Element {
    49  
    50  	r := make([]fr.Element, size)
    51  	for i := 0; i < size; i++ {
    52  		r[i].SetRandom()
    53  	}
    54  	return &r
    55  }
    56  
    57  func TestGetCoeff(t *testing.T) {
    58  
    59  	size := 8
    60  	v := make([]fr.Element, size)
    61  	for i := 0; i < size; i++ {
    62  		v[i].SetUint64(uint64(i))
    63  	}
    64  	wp := NewPolynomial(&v, Form{Layout: Regular, Basis: Canonical})
    65  	wsp := wp.ShallowClone().Shift(1)
    66  
    67  	var aa, bb fr.Element
    68  
    69  	// regular layout
    70  	for i := 0; i < size; i++ {
    71  
    72  		a := wp.GetCoeff(i)
    73  		b := wsp.GetCoeff(i)
    74  		aa.SetUint64(uint64(i))
    75  		bb.SetUint64(uint64((i + 1) % size))
    76  		if !a.Equal(&aa) {
    77  			t.Fatal("error GetCoeff")
    78  		}
    79  		if !b.Equal(&bb) {
    80  			t.Fatal("error GetCoeff")
    81  		}
    82  	}
    83  
    84  	// bit reverse + bitReverse and shifted
    85  	wp.ToBitReverse()
    86  	wsp.ToBitReverse()
    87  	for i := 0; i < size; i++ {
    88  
    89  		a := wp.GetCoeff(i)
    90  		b := wsp.GetCoeff(i)
    91  		aa.SetUint64(uint64(i))
    92  		bb.SetUint64(uint64((i + 1) % size))
    93  		if !a.Equal(&aa) {
    94  			t.Fatal("error GetCoeff")
    95  		}
    96  		if !b.Equal(&bb) {
    97  			t.Fatal("error GetCoeff")
    98  		}
    99  	}
   100  
   101  }
   102  
   103  
   104  func TestRoundTrip(t *testing.T) {
   105  	assert := require.New(t)
   106  	var buf bytes.Buffer
   107  
   108  	size := 8
   109  	d := fft.NewDomain(uint64(8))
   110  	blindingOrder := 2
   111  
   112  	p := NewPolynomial(randomVector(size), Form{Basis:Lagrange, Layout: Regular}).ToCanonical(d).ToRegular()
   113  	p.Blind(blindingOrder)
   114  
   115  	// serialize
   116  	written, err := p.WriteTo(&buf)
   117  	assert.NoError(err)
   118  
   119  	// deserialize
   120  	var reconstructed Polynomial
   121  	read, err := reconstructed.ReadFrom(&buf)
   122  	assert.NoError(err)
   123  
   124  	assert.Equal(read, written, "number of bytes written != number of bytes read")
   125  
   126  	// compare 
   127  	assert.Equal(p.Basis, reconstructed.Basis)
   128  	assert.Equal(p.Layout, reconstructed.Layout)
   129  	assert.Equal(p.shift, reconstructed.shift)
   130  	assert.Equal(p.size, reconstructed.size)
   131  	assert.Equal(p.blindedSize, reconstructed.blindedSize)
   132  	c1, c2 := p.Coefficients(), reconstructed.Coefficients()
   133  	assert.True(reflect.DeepEqual(c1, c2))
   134  }
   135  
   136  func TestBlinding(t *testing.T) {
   137  
   138  	size := 8
   139  	d := fft.NewDomain(uint64(8))
   140  	blindingOrder := 2
   141  
   142  	// generate a random polynomial in Lagrange form for the moment
   143  	// to check that an error is raised when the polynomial is not
   144  	// in canonical form.
   145  	wp := NewPolynomial(randomVector(size), Form{Basis:Lagrange, Layout: Regular})
   146  
   147  	// checks the blinding is correct: the evaluation of the blinded polynomial
   148  	// should be the same as the original on d's domain
   149  	wp.Basis = Canonical
   150  	wt := wp.Clone()
   151  	wt.Blind(blindingOrder)
   152  	if wt.coefficients.Len() != blindingOrder+size+1 {
   153  		t.Fatal("size of blinded polynomial is incorrect")
   154  	}
   155  	if wt.blindedSize != size+blindingOrder+1 {
   156  		t.Fatal("Size field of blinded polynomial is incorrect")
   157  	}
   158  	if wt.size != size {
   159  		t.Fatal("the size should not have been modified")
   160  	}
   161  	x := make([]fr.Element, size)
   162  	x[0].SetOne()
   163  	for i := 1; i < size; i++ {
   164  		x[i].Mul(&x[i-1], &d.Generator)
   165  	}
   166  	var a, b fr.Element
   167  	for i := 0; i < size; i++ {
   168  		a = wt.Evaluate(x[i])
   169  		b = wp.Evaluate(x[i])
   170  		if a != b {
   171  			t.Fatal("polynomial and its blinded version should be equal on V(X^{n}-1)")
   172  		}
   173  	}
   174  
   175  }
   176  
   177  // list of functions to turn a polynomial in Lagrange-regular form
   178  // to all different forms in ordered using this encoding:
   179  // int(p.Basis)*4 + int(p.Layout)*2 + int(p.Status)
   180  // p is in Lagrange/Regular here. This function is for testing purpose
   181  // only.
   182  type TransfoTest func(p polynomial, d *fft.Domain) polynomial
   183  
   184  // CANONICAL REGULAR
   185  func fromLagrange0(p *Polynomial, d *fft.Domain) *Polynomial {
   186  	r := p.Clone()
   187  	r.Basis = Canonical
   188  	r.Layout = Regular
   189  	d.FFTInverse(r.Coefficients(), fft.DIF)
   190  	fft.BitReverse(r.Coefficients())
   191  	return r
   192  }
   193  
   194  // CANONICAL BITREVERSE
   195  func fromLagrange1(p *Polynomial, d *fft.Domain) *Polynomial {
   196  	r := p.Clone()
   197  	r.Basis = Canonical
   198  	r.Layout = BitReverse
   199  	d.FFTInverse(r.Coefficients(), fft.DIF)
   200  	return r
   201  }
   202  
   203  // LAGRANGE REGULAR
   204  func fromLagrange2(p *Polynomial, d *fft.Domain) *Polynomial {
   205  	r := p.Clone()
   206  	r.Basis = Lagrange
   207  	r.Layout = Regular
   208  	return r
   209  }
   210  
   211  // LAGRANGE BITREVERSE
   212  func fromLagrange3(p *Polynomial, d *fft.Domain) *Polynomial {
   213  	r := p.Clone()
   214  	r.Basis = Lagrange
   215  	r.Layout = BitReverse
   216  	fft.BitReverse(r.Coefficients())
   217  	return r
   218  }
   219  
   220  // LAGRANGE_COSET REGULAR
   221  func fromLagrange4(p *Polynomial, d *fft.Domain) *Polynomial {
   222  	r := p.Clone()
   223  	r.Basis = LagrangeCoset
   224  	r.Layout = Regular
   225  	d.FFTInverse(r.Coefficients(), fft.DIF)
   226  	d.FFT(r.Coefficients(), fft.DIT, fft.OnCoset())
   227  	return r
   228  }
   229  
   230  // LAGRANGE_COSET BITREVERSE
   231  func fromLagrange5(p *Polynomial, d *fft.Domain) *Polynomial {
   232  	r := p.Clone()
   233  	r.Basis = LagrangeCoset
   234  	r.Layout = BitReverse
   235  	d.FFTInverse(r.Coefficients(), fft.DIF)
   236  	d.FFT(r.Coefficients(), fft.DIT, fft.OnCoset())
   237  	fft.BitReverse(r.Coefficients())
   238  	return r
   239  }
   240  
   241  func fromLagrange(p *Polynomial, d *fft.Domain) *Polynomial {
   242  	id := p.Form
   243  	switch id {
   244  	case canonicalRegular:
   245  		return fromLagrange0(p, d)
   246  	case canonicalBitReverse:
   247  		return fromLagrange1(p, d)
   248  	case lagrangeRegular:
   249  		return fromLagrange2(p, d)
   250  	case lagrangeBitReverse:
   251  		return fromLagrange3(p, d)
   252  	case lagrangeCosetRegular:
   253  		return fromLagrange4(p, d)
   254  	case lagrangeCosetBitReverse:
   255  		return fromLagrange5(p, d)
   256  	default:
   257  		panic("unknown id")
   258  	}
   259  }
   260  
   261  func cmpCoefficents(p, q *fr.Vector) bool {
   262  	if p.Len() != q.Len() {
   263  		return false
   264  	}
   265  	for i := 0; i < p.Len(); i++ {
   266  		if !((*p)[i].Equal(&(*q)[i])){
   267  			return false 
   268  		}
   269  	}
   270  	return true
   271  }
   272  
   273  func TestPutInLagrangeForm(t *testing.T) {
   274  
   275  	size := 64
   276  	domain := fft.NewDomain(uint64(size))
   277  
   278  	// reference vector in Lagrange-regular form
   279  	c := randomVector(size)
   280  	p := NewPolynomial(c, Form{Basis: Canonical, Layout: Regular})
   281  
   282  	// CANONICAL REGULAR
   283  	{
   284  		_p := fromLagrange(p, domain)
   285  		q := _p.Clone()
   286  		q.ToLagrange(domain)
   287  		if q.Basis != Lagrange {
   288  			t.Fatal("expected basis is Lagrange")
   289  		}
   290  		if q.Layout != BitReverse {
   291  			t.Fatal("expected layout is BitReverse")
   292  		}
   293  		fft.BitReverse(q.Coefficients())
   294  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   295  			t.Fatal("wrong coefficients")
   296  		}
   297  	}
   298  
   299  	// CANONICAL BITREVERSE
   300  	{
   301  		_p := fromLagrange1(p, domain)
   302  		q := _p.Clone()
   303  		q.ToLagrange(domain)
   304  		if q.Basis != Lagrange {
   305  			t.Fatal("expected basis is Lagrange")
   306  		}
   307  		if q.Layout != Regular {
   308  			t.Fatal("expected layout is Regular")
   309  		}
   310  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   311  			t.Fatal("wrong coefficients")
   312  		}
   313  	}
   314  
   315  	// LAGRANGE REGULAR
   316  	{
   317  		_p := fromLagrange2(p, domain)
   318  		q := _p.Clone()
   319  		q.ToLagrange(domain)
   320  
   321  		if q.Basis != Lagrange {
   322  			t.Fatal("expected basis is Lagrange")
   323  		}
   324  		if q.Layout != Regular {
   325  			t.Fatal("expected layout is Regular")
   326  		}
   327  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   328  			t.Fatal("wrong coefficients")
   329  		}
   330  	}
   331  
   332  	// LAGRANGE BITREVERSE
   333  	{
   334  		_p := fromLagrange3(p, domain)
   335  		q := _p.Clone()
   336  		q.ToLagrange(domain)
   337  		if q.Basis != Lagrange {
   338  			t.Fatal("expected basis is Lagrange")
   339  		}
   340  		if q.Layout != BitReverse {
   341  			t.Fatal("expected layout is BitReverse")
   342  		}
   343  		fft.BitReverse(q.Coefficients())
   344  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   345  			t.Fatal("wrong coefficients")
   346  		}
   347  	}
   348  
   349  	// LAGRANGE_COSET REGULAR
   350  	{
   351  		_p := fromLagrange4(p, domain)
   352  		q := _p.Clone()
   353  		q.ToLagrange(domain)
   354  		if q.Basis != Lagrange {
   355  			t.Fatal("expected basis is Lagrange")
   356  		}
   357  		if q.Layout != Regular {
   358  			t.Fatal("expected layout is Regular")
   359  		}
   360  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   361  			t.Fatal("wrong coefficients")
   362  		}
   363  	}
   364  
   365  	// LAGRANGE_COSET BITREVERSE
   366  	{
   367  		_p := fromLagrange5(p, domain)
   368  		q := _p.Clone()
   369  		q.ToLagrange(domain)
   370  		if q.Basis != Lagrange {
   371  			t.Fatal("expected basis is Lagrange")
   372  		}
   373  		if q.Layout != BitReverse {
   374  			t.Fatal("expected layout is BitReverse")
   375  		}
   376  		fft.BitReverse(q.Coefficients())
   377  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   378  			t.Fatal("wrong coefficients")
   379  		}
   380  	}
   381  
   382  }
   383  
   384  // CANONICAL REGULAR
   385  func fromCanonical0(p *Polynomial, d *fft.Domain) *Polynomial {
   386  	_p := p.Clone()
   387  	_p.Basis = Canonical
   388  	_p.Layout = Regular
   389  	return _p
   390  }
   391  
   392  // CANONICAL BITREVERSE
   393  func fromCanonical1(p *Polynomial, d *fft.Domain) *Polynomial {
   394  	_p := p.Clone()
   395  	_p.Basis = Canonical
   396  	_p.Layout = BitReverse
   397  	return _p
   398  }
   399  
   400  // LAGRANGE REGULAR
   401  func fromCanonical2(p *Polynomial, d *fft.Domain) *Polynomial {
   402  	_p := p.Clone()
   403  	_p.Basis = Lagrange
   404  	_p.Layout = Regular
   405  	d.FFT(_p.Coefficients(), fft.DIF)
   406  	fft.BitReverse(_p.Coefficients())
   407  	return _p
   408  }
   409  
   410  // LAGRANGE BITREVERSE
   411  func fromCanonical3(p *Polynomial, d *fft.Domain) *Polynomial {
   412  	_p := p.Clone()
   413  	_p.Basis = Lagrange
   414  	_p.Layout = BitReverse
   415  	d.FFT(_p.Coefficients(), fft.DIF)
   416  	return _p
   417  }
   418  
   419  // LAGRANGE_COSET REGULAR
   420  func fromCanonical4(p *Polynomial, d *fft.Domain) *Polynomial {
   421  	_p := p.Clone()
   422  	_p.Basis = LagrangeCoset
   423  	_p.Layout = Regular
   424  	d.FFT(_p.Coefficients(), fft.DIF, fft.OnCoset())
   425  	fft.BitReverse(_p.Coefficients())
   426  	return _p
   427  }
   428  
   429  // LAGRANGE_COSET BITREVERSE
   430  func fromCanonical5(p *Polynomial, d *fft.Domain) *Polynomial {
   431  	_p := p.Clone()
   432  	_p.Basis = LagrangeCoset
   433  	_p.Layout = BitReverse
   434  	d.FFT(_p.Coefficients(), fft.DIF, fft.OnCoset())
   435  	return _p
   436  }
   437  
   438  func TestPutInCanonicalForm(t *testing.T) {
   439  
   440  	size := 64
   441  	domain := fft.NewDomain(uint64(size))
   442  
   443  	// reference vector in canonical-regular form
   444  	c := randomVector(size)
   445  	p := NewPolynomial(c, Form{Basis: Canonical, Layout: Regular})
   446  
   447  	// CANONICAL REGULAR
   448  	{
   449  		_p := fromCanonical0(p, domain)
   450  		q := _p.Clone()
   451  		q.ToCanonical(domain)
   452  		if q.Basis != Canonical {
   453  			t.Fatal("expected basis is canonical")
   454  		}
   455  		if q.Layout != Regular {
   456  			t.Fatal("expected layout is regular")
   457  		}
   458  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   459  			t.Fatal("wrong coefficients")
   460  		}
   461  	}
   462  
   463  	// CANONICAL BITREVERSE
   464  	{
   465  		_p := fromCanonical1(p, domain)
   466  		q := _p.Clone()
   467  		q.ToCanonical(domain)
   468  		if q.Basis != Canonical {
   469  			t.Fatal("expected basis is canonical")
   470  		}
   471  		if q.Layout != BitReverse {
   472  			t.Fatal("expected layout is bitReverse")
   473  		}
   474  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   475  			t.Fatal("wrong coefficients")
   476  		}
   477  	}
   478  
   479  	// LAGRANGE REGULAR
   480  	{
   481  		_p := fromCanonical2(p, domain)
   482  		q := _p.Clone()
   483  		q.ToCanonical(domain)
   484  		if q.Basis != Canonical {
   485  			t.Fatal("expected basis is canonical")
   486  		}
   487  		if q.Layout != BitReverse {
   488  			t.Fatal("expected layout is bitReverse")
   489  		}
   490  		fft.BitReverse(q.Coefficients())
   491  		if !cmpCoefficents(p.coefficients, q.coefficients) {
   492  			t.Fatal("wrong coefficients")
   493  		}
   494  	}
   495  
   496  	// LAGRANGE BITREVERSE
   497  	{
   498  		_p := fromCanonical3(p, domain)
   499  		q := _p.Clone()
   500  		q.ToCanonical(domain)
   501  		if q.Basis != Canonical {
   502  			t.Fatal("expected basis is canonical")
   503  		}
   504  		if q.Layout != Regular {
   505  			t.Fatal("expected layout is regular")
   506  		}
   507  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   508  			t.Fatal("wrong coefficients")
   509  		}
   510  	}
   511  
   512  	// LAGRANGE_COSET REGULAR
   513  	{
   514  		_p := fromCanonical4(p, domain)
   515  		q := _p.Clone()
   516  		q.ToCanonical(domain)
   517  		if q.Basis != Canonical {
   518  			t.Fatal("expected basis is canonical")
   519  		}
   520  		if q.Layout != BitReverse {
   521  			t.Fatal("expected layout is BitReverse")
   522  		}
   523  		fft.BitReverse(q.Coefficients())
   524  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   525  			t.Fatal("wrong coefficients")
   526  		}
   527  	}
   528  
   529  	// LAGRANGE_COSET BITREVERSE
   530  	{
   531  		_p := fromCanonical5(p, domain)
   532  		q := _p.Clone()
   533  		q.ToCanonical(domain)
   534  		if q.Basis != Canonical {
   535  			t.Fatal("expected basis is canonical")
   536  		}
   537  		if q.Layout != Regular {
   538  			t.Fatal("expected layout is regular")
   539  		}
   540  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   541  			t.Fatal("wrong coefficients")
   542  		}
   543  	}
   544  
   545  }
   546  
   547  // CANONICAL REGULAR
   548  func fromLagrangeCoset0(p *Polynomial, d *fft.Domain) *Polynomial {
   549  	_p := p.Clone()
   550  	_p.Basis = Canonical
   551  	_p.Layout = Regular
   552  	d.FFTInverse(_p.Coefficients(), fft.DIF, fft.OnCoset())
   553  	fft.BitReverse(_p.Coefficients())
   554  	return _p
   555  }
   556  
   557  // CANONICAL BITREVERSE
   558  func fromLagrangeCoset1(p *Polynomial, d *fft.Domain) *Polynomial {
   559  	_p := p.Clone()
   560  	_p.Basis = Canonical
   561  	_p.Layout = BitReverse
   562  	d.FFTInverse(_p.Coefficients(), fft.DIF, fft.OnCoset())
   563  	return _p
   564  }
   565  
   566  // LAGRANGE REGULAR
   567  func fromLagrangeCoset2(p *Polynomial, d *fft.Domain) *Polynomial {
   568  	_p := p.Clone()
   569  	_p.Basis = Lagrange
   570  	_p.Layout = Regular
   571  	d.FFTInverse(_p.Coefficients(), fft.DIF, fft.OnCoset())
   572  	d.FFT(_p.Coefficients(), fft.DIT)
   573  	return _p
   574  }
   575  
   576  // LAGRANGE BITREVERSE
   577  func fromLagrangeCoset3(p *Polynomial, d *fft.Domain) *Polynomial {
   578  	_p := p.Clone()
   579  	_p.Basis = Lagrange
   580  	_p.Layout = BitReverse
   581  	d.FFTInverse(_p.Coefficients(), fft.DIF, fft.OnCoset())
   582  	d.FFT(_p.Coefficients(), fft.DIT)
   583  	fft.BitReverse(_p.Coefficients())
   584  	return _p
   585  }
   586  
   587  // LAGRANGE_COSET REGULAR
   588  func fromLagrangeCoset4(p *Polynomial, d *fft.Domain) *Polynomial {
   589  	_p := p.Clone()
   590  	_p.Basis = LagrangeCoset
   591  	_p.Layout = Regular
   592  	return _p
   593  }
   594  
   595  // LAGRANGE_COSET BITREVERSE
   596  func fromLagrangeCoset5(p *Polynomial, d *fft.Domain) *Polynomial {
   597  	_p := p.Clone()
   598  	_p.Basis = LagrangeCoset
   599  	_p.Layout = BitReverse
   600  	fft.BitReverse(p.Coefficients())
   601  	return _p
   602  }
   603  
   604  func TestPutInLagrangeCosetForm(t *testing.T) {
   605  
   606  	size := 64
   607  	domain := fft.NewDomain(uint64(size))
   608  
   609  	// reference vector in canonical-regular form
   610  	c := randomVector(size)
   611  	p := NewPolynomial(c, Form{Basis: LagrangeCoset, Layout: Regular})
   612  
   613  	// CANONICAL REGULAR
   614  	{
   615  		_p := fromLagrangeCoset0(p, domain)
   616  		q := _p.Clone()
   617  		q.ToLagrangeCoset(domain)
   618  		if q.Basis != LagrangeCoset {
   619  			t.Fatal("expected basis is lagrange coset")
   620  		}
   621  		if q.Layout != BitReverse {
   622  			t.Fatal("expected layout is bit reverse")
   623  		}
   624  		fft.BitReverse(q.Coefficients())
   625  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   626  			t.Fatal("wrong coefficients")
   627  		}
   628  	}
   629  
   630  	// CANONICAL BITREVERSE
   631  	{
   632  		_p := fromLagrangeCoset1(p, domain)
   633  		q := _p.Clone()
   634  		q.ToLagrangeCoset(domain)
   635  		if q.Basis != LagrangeCoset {
   636  			t.Fatal("expected basis is lagrange coset")
   637  		}
   638  		if q.Layout != Regular {
   639  			t.Fatal("expected layout is regular")
   640  		}
   641  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   642  			t.Fatal("wrong coefficients")
   643  		}
   644  	}
   645  
   646  	// LAGRANGE REGULAR
   647  	{
   648  		_p := fromLagrangeCoset2(p, domain)
   649  		q := _p.Clone()
   650  		q.ToLagrangeCoset(domain)
   651  		if q.Basis != LagrangeCoset {
   652  			t.Fatal("expected basis is lagrange coset")
   653  		}
   654  		if q.Layout != Regular {
   655  			t.Fatal("expected layout is regular")
   656  		}
   657  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   658  			t.Fatal("wrong coefficients")
   659  		}
   660  	}
   661  
   662  	// LAGRANGE BITREVERSE
   663  	{
   664  		_p := fromLagrangeCoset3(p, domain)
   665  		q := _p.Clone()
   666  		q.ToLagrangeCoset(domain)
   667  		if q.Basis != LagrangeCoset {
   668  			t.Fatal("expected basis is lagrange coset")
   669  		}
   670  		if q.Layout != BitReverse {
   671  			t.Fatal("expected layout is bit reverse")
   672  		}
   673  		fft.BitReverse(q.Coefficients())
   674  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   675  			t.Fatal("wrong coefficients")
   676  		}
   677  	}
   678  
   679  	// LAGRANGE_COSET REGULAR
   680  	{
   681  		_p := fromLagrangeCoset4(p, domain)
   682  		q := _p.Clone()
   683  		q.ToLagrangeCoset(domain)
   684  		if q.Basis != LagrangeCoset {
   685  			t.Fatal("expected basis is lagrange coset")
   686  		}
   687  		if q.Layout != Regular {
   688  			t.Fatal("expected layout is regular")
   689  		}
   690  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   691  			t.Fatal("wrong coefficients")
   692  		}
   693  	}
   694  
   695  	// LAGRANGE_COSET BITREVERSE
   696  	{
   697  		_p := fromLagrangeCoset5(p, domain)
   698  		q := _p.Clone()
   699  		q.ToLagrangeCoset(domain)
   700  		if q.Basis != LagrangeCoset {
   701  			t.Fatal("expected basis is lagrange coset")
   702  		}
   703  		if q.Layout != BitReverse {
   704  			t.Fatal("expected layout is bit reverse")
   705  		}
   706  		fft.BitReverse(q.Coefficients())
   707  		if !cmpCoefficents(q.coefficients, p.coefficients) {
   708  			t.Fatal("wrong coefficients")
   709  		}
   710  	}
   711  
   712  }