diff --git a/ecc/bls12-377/fr/fft/domain.go b/ecc/bls12-377/fr/fft/domain.go index 3ad436c4f7..ad939c6177 100644 --- a/ecc/bls12-377/fr/fft/domain.go +++ b/ecc/bls12-377/fr/fft/domain.go @@ -188,7 +188,7 @@ func (d *Domain) preComputeTwiddles() { cosetGensInv[0].Set(&d.FinerGeneratorInv) for i := 1; i < nbCosets; i++ { cosetGens[i].Mul(&cosetGens[i-1], &d.FinerGenerator) - cosetGensInv[i].Mul(&cosetGensInv[1], &d.FinerGeneratorInv) + cosetGensInv[i].Mul(&cosetGensInv[i-1], &d.FinerGeneratorInv) } wg.Add(2 + 2*nbCosets) go twiddles(d.Twiddles, d.Generator) @@ -246,9 +246,13 @@ func precomputeExpTable(w fr.Element, table []fr.Element) { } func precomputeExpTableChunk(w fr.Element, power uint64, table []fr.Element) { - table[0].Exp(w, new(big.Int).SetUint64(power)) - for i := 1; i < len(table); i++ { - table[i].Mul(&table[i-1], &w) + + // this condition ensures that creating a domain of size 1 with cosets don't fail + if len(table) > 0 { + table[0].Exp(w, new(big.Int).SetUint64(power)) + for i := 1; i < len(table); i++ { + table[i].Mul(&table[i-1], &w) + } } } diff --git a/ecc/bls12-377/fr/fft/fft_test.go b/ecc/bls12-377/fr/fft/fft_test.go index 9471742b0c..ebd66639b7 100644 --- a/ecc/bls12-377/fr/fft/fft_test.go +++ b/ecc/bls12-377/fr/fft/fft_test.go @@ -31,8 +31,9 @@ import ( func TestFFT(t *testing.T) { const maxSize = 1 << 10 - domainWithPrecompute := NewDomain(maxSize, 1, true) - domainWOPrecompute := NewDomain(maxSize, 1, false) + nbCosets := 3 + domainWithPrecompute := NewDomain(maxSize, 2, true) + domainWOPrecompute := NewDomain(maxSize, 2, false) parameters := gopter.DefaultTestParameters() parameters.MinSuccessfulTests = 5 @@ -186,15 +187,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWithPrecompute.FFT(pol, DIT, 1) - domainWithPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWithPrecompute.FFT(pol, DIT, uint64(i)) + domainWithPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) @@ -211,15 +217,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWOPrecompute.FFT(pol, DIT, 1) - domainWOPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWOPrecompute.FFT(pol, DIT, uint64(i)) + domainWOPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) diff --git a/ecc/bls12-381/fr/fft/domain.go b/ecc/bls12-381/fr/fft/domain.go index 654648a9e6..af43749ec3 100644 --- a/ecc/bls12-381/fr/fft/domain.go +++ b/ecc/bls12-381/fr/fft/domain.go @@ -188,7 +188,7 @@ func (d *Domain) preComputeTwiddles() { cosetGensInv[0].Set(&d.FinerGeneratorInv) for i := 1; i < nbCosets; i++ { cosetGens[i].Mul(&cosetGens[i-1], &d.FinerGenerator) - cosetGensInv[i].Mul(&cosetGensInv[1], &d.FinerGeneratorInv) + cosetGensInv[i].Mul(&cosetGensInv[i-1], &d.FinerGeneratorInv) } wg.Add(2 + 2*nbCosets) go twiddles(d.Twiddles, d.Generator) @@ -246,9 +246,13 @@ func precomputeExpTable(w fr.Element, table []fr.Element) { } func precomputeExpTableChunk(w fr.Element, power uint64, table []fr.Element) { - table[0].Exp(w, new(big.Int).SetUint64(power)) - for i := 1; i < len(table); i++ { - table[i].Mul(&table[i-1], &w) + + // this condition ensures that creating a domain of size 1 with cosets don't fail + if len(table) > 0 { + table[0].Exp(w, new(big.Int).SetUint64(power)) + for i := 1; i < len(table); i++ { + table[i].Mul(&table[i-1], &w) + } } } diff --git a/ecc/bls12-381/fr/fft/fft_test.go b/ecc/bls12-381/fr/fft/fft_test.go index d610e5829b..0ed6c74041 100644 --- a/ecc/bls12-381/fr/fft/fft_test.go +++ b/ecc/bls12-381/fr/fft/fft_test.go @@ -31,8 +31,9 @@ import ( func TestFFT(t *testing.T) { const maxSize = 1 << 10 - domainWithPrecompute := NewDomain(maxSize, 1, true) - domainWOPrecompute := NewDomain(maxSize, 1, false) + nbCosets := 3 + domainWithPrecompute := NewDomain(maxSize, 2, true) + domainWOPrecompute := NewDomain(maxSize, 2, false) parameters := gopter.DefaultTestParameters() parameters.MinSuccessfulTests = 5 @@ -186,15 +187,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWithPrecompute.FFT(pol, DIT, 1) - domainWithPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWithPrecompute.FFT(pol, DIT, uint64(i)) + domainWithPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) @@ -211,15 +217,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWOPrecompute.FFT(pol, DIT, 1) - domainWOPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWOPrecompute.FFT(pol, DIT, uint64(i)) + domainWOPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) diff --git a/ecc/bn254/fr/fft/domain.go b/ecc/bn254/fr/fft/domain.go index 18e8351d1f..a842c30bbc 100644 --- a/ecc/bn254/fr/fft/domain.go +++ b/ecc/bn254/fr/fft/domain.go @@ -188,7 +188,7 @@ func (d *Domain) preComputeTwiddles() { cosetGensInv[0].Set(&d.FinerGeneratorInv) for i := 1; i < nbCosets; i++ { cosetGens[i].Mul(&cosetGens[i-1], &d.FinerGenerator) - cosetGensInv[i].Mul(&cosetGensInv[1], &d.FinerGeneratorInv) + cosetGensInv[i].Mul(&cosetGensInv[i-1], &d.FinerGeneratorInv) } wg.Add(2 + 2*nbCosets) go twiddles(d.Twiddles, d.Generator) @@ -246,9 +246,13 @@ func precomputeExpTable(w fr.Element, table []fr.Element) { } func precomputeExpTableChunk(w fr.Element, power uint64, table []fr.Element) { - table[0].Exp(w, new(big.Int).SetUint64(power)) - for i := 1; i < len(table); i++ { - table[i].Mul(&table[i-1], &w) + + // this condition ensures that creating a domain of size 1 with cosets don't fail + if len(table) > 0 { + table[0].Exp(w, new(big.Int).SetUint64(power)) + for i := 1; i < len(table); i++ { + table[i].Mul(&table[i-1], &w) + } } } diff --git a/ecc/bn254/fr/fft/fft_test.go b/ecc/bn254/fr/fft/fft_test.go index e934fc202d..57ffb6081f 100644 --- a/ecc/bn254/fr/fft/fft_test.go +++ b/ecc/bn254/fr/fft/fft_test.go @@ -31,8 +31,9 @@ import ( func TestFFT(t *testing.T) { const maxSize = 1 << 10 - domainWithPrecompute := NewDomain(maxSize, 1, true) - domainWOPrecompute := NewDomain(maxSize, 1, false) + nbCosets := 3 + domainWithPrecompute := NewDomain(maxSize, 2, true) + domainWOPrecompute := NewDomain(maxSize, 2, false) parameters := gopter.DefaultTestParameters() parameters.MinSuccessfulTests = 5 @@ -186,15 +187,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWithPrecompute.FFT(pol, DIT, 1) - domainWithPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWithPrecompute.FFT(pol, DIT, uint64(i)) + domainWithPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) @@ -211,15 +217,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWOPrecompute.FFT(pol, DIT, 1) - domainWOPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWOPrecompute.FFT(pol, DIT, uint64(i)) + domainWOPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) diff --git a/ecc/bw6-761/fr/fft/domain.go b/ecc/bw6-761/fr/fft/domain.go index 3d025b1703..42f3ebead7 100644 --- a/ecc/bw6-761/fr/fft/domain.go +++ b/ecc/bw6-761/fr/fft/domain.go @@ -188,7 +188,7 @@ func (d *Domain) preComputeTwiddles() { cosetGensInv[0].Set(&d.FinerGeneratorInv) for i := 1; i < nbCosets; i++ { cosetGens[i].Mul(&cosetGens[i-1], &d.FinerGenerator) - cosetGensInv[i].Mul(&cosetGensInv[1], &d.FinerGeneratorInv) + cosetGensInv[i].Mul(&cosetGensInv[i-1], &d.FinerGeneratorInv) } wg.Add(2 + 2*nbCosets) go twiddles(d.Twiddles, d.Generator) @@ -246,9 +246,13 @@ func precomputeExpTable(w fr.Element, table []fr.Element) { } func precomputeExpTableChunk(w fr.Element, power uint64, table []fr.Element) { - table[0].Exp(w, new(big.Int).SetUint64(power)) - for i := 1; i < len(table); i++ { - table[i].Mul(&table[i-1], &w) + + // this condition ensures that creating a domain of size 1 with cosets don't fail + if len(table) > 0 { + table[0].Exp(w, new(big.Int).SetUint64(power)) + for i := 1; i < len(table); i++ { + table[i].Mul(&table[i-1], &w) + } } } diff --git a/ecc/bw6-761/fr/fft/fft_test.go b/ecc/bw6-761/fr/fft/fft_test.go index aa44030b2f..40d5e52620 100644 --- a/ecc/bw6-761/fr/fft/fft_test.go +++ b/ecc/bw6-761/fr/fft/fft_test.go @@ -31,8 +31,9 @@ import ( func TestFFT(t *testing.T) { const maxSize = 1 << 10 - domainWithPrecompute := NewDomain(maxSize, 1, true) - domainWOPrecompute := NewDomain(maxSize, 1, false) + nbCosets := 3 + domainWithPrecompute := NewDomain(maxSize, 2, true) + domainWOPrecompute := NewDomain(maxSize, 2, false) parameters := gopter.DefaultTestParameters() parameters.MinSuccessfulTests = 5 @@ -186,15 +187,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWithPrecompute.FFT(pol, DIT, 1) - domainWithPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWithPrecompute.FFT(pol, DIT, uint64(i)) + domainWithPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) @@ -211,15 +217,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWOPrecompute.FFT(pol, DIT, 1) - domainWOPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWOPrecompute.FFT(pol, DIT, uint64(i)) + domainWOPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) diff --git a/internal/generator/fft/template/domain.go.tmpl b/internal/generator/fft/template/domain.go.tmpl index f8b79d4c03..bfbf58d5b6 100644 --- a/internal/generator/fft/template/domain.go.tmpl +++ b/internal/generator/fft/template/domain.go.tmpl @@ -179,7 +179,7 @@ func (d *Domain) preComputeTwiddles() { cosetGensInv[0].Set(&d.FinerGeneratorInv) for i := 1; i < nbCosets; i++ { cosetGens[i].Mul(&cosetGens[i-1], &d.FinerGenerator) - cosetGensInv[i].Mul(&cosetGensInv[1], &d.FinerGeneratorInv) + cosetGensInv[i].Mul(&cosetGensInv[i-1], &d.FinerGeneratorInv) } wg.Add(2 + 2*nbCosets) go twiddles(d.Twiddles, d.Generator) @@ -237,9 +237,13 @@ func precomputeExpTable(w fr.Element, table []fr.Element) { } func precomputeExpTableChunk(w fr.Element, power uint64, table []fr.Element) { - table[0].Exp(w, new(big.Int).SetUint64(power)) - for i := 1; i < len(table); i++ { - table[i].Mul(&table[i-1], &w) + + // this condition ensures that creating a domain of size 1 with cosets don't fail + if len(table) > 0 { + table[0].Exp(w, new(big.Int).SetUint64(power)) + for i := 1; i < len(table); i++ { + table[i].Mul(&table[i-1], &w) + } } } diff --git a/internal/generator/fft/template/tests/fft.go.tmpl b/internal/generator/fft/template/tests/fft.go.tmpl index 754b133dd1..26e5666308 100644 --- a/internal/generator/fft/template/tests/fft.go.tmpl +++ b/internal/generator/fft/template/tests/fft.go.tmpl @@ -14,8 +14,9 @@ import ( func TestFFT(t *testing.T) { const maxSize = 1 << 10 - domainWithPrecompute := NewDomain(maxSize, 1, true) - domainWOPrecompute := NewDomain(maxSize, 1, false) + nbCosets := 3 + domainWithPrecompute := NewDomain(maxSize, 2, true) + domainWOPrecompute := NewDomain(maxSize, 2, false) parameters := gopter.DefaultTestParameters() parameters.MinSuccessfulTests = 5 @@ -169,15 +170,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWithPrecompute.FFT(pol, DIT, 1) - domainWithPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWithPrecompute.FFT(pol, DIT, uint64(i)) + domainWithPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, )) @@ -194,15 +200,20 @@ func TestFFT(t *testing.T) { } copy(backupPol, pol) - BitReverse(pol) - domainWOPrecompute.FFT(pol, DIT, 1) - domainWOPrecompute.FFTInverse(pol, DIF, 1) - BitReverse(pol) - check := true - for i := 0; i < len(pol); i++ { - check = check && pol[i].Equal(&backupPol[i]) + + for i := 1; i <= nbCosets; i++ { + + BitReverse(pol) + domainWOPrecompute.FFT(pol, DIT, uint64(i)) + domainWOPrecompute.FFTInverse(pol, DIF, uint64(i)) + BitReverse(pol) + + for i := 0; i < len(pol); i++ { + check = check && pol[i].Equal(&backupPol[i]) + } } + return check }, ))