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

     1  package element
     2  
     3  const BigNum = `
     4  
     5  {{/* Only used for the Pornin Extended GCD Inverse Algorithm*/}}
     6  {{if $.UsingP20Inverse}}
     7  
     8  // negL negates in place [x | xHi] and return the new most significant word xHi
     9  func negL(x *{{.ElementName}}, xHi uint64) uint64 {
    10  	var b uint64
    11  
    12  	x[0], b = bits.Sub64(0, x[0], 0)
    13  	{{- range $i := .NbWordsIndexesNoZero}}
    14  	x[{{$i}}], b = bits.Sub64(0, x[{{$i}}], b)
    15  	{{- end}}
    16  	xHi, _ = bits.Sub64(0, xHi, b)
    17  
    18  	return xHi
    19  }
    20  
    21  // mulWNonModular multiplies by one word in non-montgomery, without reducing
    22  func (z *{{.ElementName}}) mulWNonModular(x *{{.ElementName}}, y int64) uint64 {
    23  
    24  	// w := abs(y)
    25  	m := y >> 63
    26  	w := uint64((y^m)-m)
    27  
    28  	var c uint64
    29  	c, z[0] = bits.Mul64(x[0], w)
    30  	{{- range $i := .NbWordsIndexesNoZero }}
    31  	c, z[{{$i}}] = madd1(x[{{$i}}], w, c)
    32  	{{- end}}
    33  
    34  	if y < 0 {
    35  		c = negL(z, c)
    36  	}
    37  
    38  	return c
    39  }
    40  
    41  // linearCombNonModular computes a linear combination without modular reduction
    42  func (z *{{.ElementName}}) linearCombNonModular(x *{{.ElementName}}, xC int64, y *{{.ElementName}}, yC int64) uint64 {
    43  	var yTimes {{.ElementName}}
    44  
    45  	yHi := yTimes.mulWNonModular(y, yC)
    46  	xHi := z.mulWNonModular(x, xC)
    47  
    48  	var carry uint64
    49  
    50  	{{- range $i := .NbWordsIndexesFull}}
    51  		z[{{$i}}], carry = bits.Add64(z[{{$i}}], yTimes[{{$i}}], {{- if eq $i 0}}0{{- else}}carry{{- end}})
    52  	{{- end}}
    53  
    54  	yHi, _ = bits.Add64(xHi, yHi, carry)
    55  
    56  	return yHi
    57  }
    58  
    59  {{- end}}
    60  `