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

     1  import (
     2  	"math/big"
     3  	"math/bits"
     4  
     5  	"github.com/consensys/gnark-crypto/internal/parallel"
     6  
     7  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr"
     8  	"github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr/fft"
     9  )
    10  
    11  // DivideByXMinusOne
    12  // The input must be in LagrangeCoset.
    13  // The result is in Canonical Regular.
    14  func DivideByXMinusOne(a *Polynomial, domains [2]*fft.Domain) (*Polynomial, error) {
    15  
    16  	// check that the basis is LagrangeCoset
    17  	if a.Basis != LagrangeCoset {
    18  		return nil, ErrMustBeLagrangeCoset
    19  	}
    20  
    21  	// prepare the evaluations of x^n-1 on the big domain's coset
    22  	xnMinusOneInverseLagrangeCoset := evaluateXnMinusOneDomainBigCoset(domains)
    23  
    24  	rho := a.coefficients.Len() / a.size
    25  
    26  	nbElmts := a.coefficients.Len()
    27  
    28  	coeffs := make([]fr.Element, a.coefficients.Len())
    29  	res := NewPolynomial(&coeffs, Form{Layout: BitReverse, Basis: LagrangeCoset})
    30  	res.size = a.size
    31  	res.blindedSize = a.blindedSize
    32  
    33  	nn := uint64(64 - bits.TrailingZeros(uint(nbElmts)))
    34  	parallel.Execute(a.coefficients.Len(), func(start, end int){
    35  		for i := start; i < end; i++ {
    36  			iRev := bits.Reverse64(uint64(i)) >> nn
    37  			c := a.GetCoeff(i)
    38  			(*res.coefficients)[iRev].
    39  				Mul(&c, &xnMinusOneInverseLagrangeCoset[i%rho])
    40  		}
    41  	})
    42  	
    43  
    44  	res.ToCanonical(domains[1])
    45  
    46  	return res, nil
    47  
    48  }
    49  
    50  // evaluateXnMinusOneDomainBigCoset evaluates Xᵐ-1 on DomainBig coset
    51  func evaluateXnMinusOneDomainBigCoset(domains [2]*fft.Domain) []fr.Element {
    52  
    53  	ratio := domains[1].Cardinality / domains[0].Cardinality
    54  
    55  	res := make([]fr.Element, ratio)
    56  
    57  	expo := big.NewInt(int64(domains[0].Cardinality))
    58  	res[0].Exp(domains[1].FrMultiplicativeGen, expo)
    59  
    60  	var t fr.Element
    61  	t.Exp(domains[1].Generator, big.NewInt(int64(domains[0].Cardinality)))
    62  
    63  	one := fr.One()
    64  
    65  	for i := 1; i < int(ratio); i++ {
    66  		res[i].Mul(&res[i-1], &t)
    67  		res[i-1].Sub(&res[i-1], &one)
    68  	}
    69  	res[len(res)-1].Sub(&res[len(res)-1], &one)
    70  
    71  	res = fr.BatchInvert(res)
    72  
    73  	return res
    74  }