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 `