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

     1  {{ $G1TAffine := print (toUpper .G1.PointName) "Affine" }}
     2  {{ $G1TJacobian := print (toUpper .G1.PointName) "Jac" }}
     3  {{ $G1TJacobianExtended := print (toLower .G1.PointName) "JacExtended" }}
     4  
     5  {{ $G2TAffine := print (toUpper .G2.PointName) "Affine" }}
     6  {{ $G2TJacobian := print (toUpper .G2.PointName) "Jac" }}
     7  {{ $G2TJacobianExtended := print (toLower .G2.PointName) "JacExtended" }}
     8  
     9  
    10  
    11  {{ template "multiexp" dict "PointName" .G1.PointName "UPointName" (toUpper .G1.PointName) "TAffine" $G1TAffine "TJacobian" $G1TJacobian "TJacobianExtended" $G1TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G1.CRange }}
    12  {{- if ne .Name "secp256k1"}}
    13  {{ template "multiexp" dict "PointName" .G2.PointName "UPointName" (toUpper .G2.PointName) "TAffine" $G2TAffine "TJacobian" $G2TJacobian "TJacobianExtended" $G2TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G2.CRange }}
    14  {{- end}}
    15  
    16  
    17  
    18  {{define "multiexp" }}
    19  
    20  func processChunk{{ $.UPointName }}Jacobian[B ib{{ $.TJacobianExtended }}](chunk uint64,
    21  	chRes chan<- {{ $.TJacobianExtended }},
    22  	c uint64,
    23  	points []{{ $.TAffine }},
    24  	digits []uint16,
    25  	sem chan struct{}) {
    26  
    27  	if sem != nil {
    28  		// if we are limited, wait for a token in the semaphore
    29  		<-sem
    30  	}
    31  
    32     var buckets B
    33     for i := 0 ; i < len(buckets); i++ {
    34  	   buckets[i].setInfinity()
    35     }
    36  
    37     // for each scalars, get the digit corresponding to the chunk we're processing.
    38     for i, digit := range digits {
    39  	   if digit == 0 {
    40  		   continue
    41  	   }
    42  
    43  	   // if msbWindow bit is set, we need to subtract
    44  	   if digit & 1 == 0 {
    45  		   // add
    46  		   buckets[(digit>>1)-1].addMixed(&points[i])
    47  	   } else {
    48  		   // sub
    49  		   buckets[(digit>>1)].subMixed(&points[i])
    50  	   }
    51     }
    52  
    53  
    54     // reduce buckets into total
    55     // total =  bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1]
    56  
    57     var runningSum, total {{ $.TJacobianExtended }}
    58     runningSum.setInfinity()
    59     total.setInfinity()
    60     for k := len(buckets) - 1; k >= 0; k-- {
    61  	   if !buckets[k].IsInfinity() {
    62  		   runningSum.add(&buckets[k])
    63  	   }
    64  	   total.add(&runningSum)
    65     }
    66  
    67     if sem != nil {
    68  	// release a token to the semaphore
    69  	// before sending to chRes
    70  	sem <- struct{}{}
    71  }
    72  
    73     chRes <- total
    74  }
    75  
    76  // we declare the buckets as fixed-size array types
    77  // this allow us to allocate the buckets on the stack
    78  {{- range $c :=  $.CRange}}
    79  type bucket{{ $.TJacobianExtended }}C{{$c}} [{{nbBuckets $c}}]{{ $.TJacobianExtended }}
    80  {{- end}}
    81  
    82  type ib{{ $.TJacobianExtended }} interface {
    83  	{{- range $i, $c :=  $.CRange}}
    84  	bucket{{ $.TJacobianExtended }}C{{$c}} {{- if not (last $i $.CRange)}} | {{- end}}
    85  	{{- end}}
    86  }
    87  
    88  {{end }}