From: Brian Kessler Date: Fri, 21 Jul 2017 06:31:51 +0000 (-0700) Subject: math/big: speed up GCD x, y calculation X-Git-Tag: go1.10beta1~1523 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=53836a74f8b0137ebd52f0279edc16fc7d5cf2ca;p=gostls13.git math/big: speed up GCD x, y calculation The current implementation of the extended Euclidean GCD algorithm calculates both cosequences x and y inside the division loop. This is unneccessary since the second Bezout coefficient can be obtained at the end of calculation via a multiplication, subtraction and a division. In case only one coefficient is needed, e.g. ModInverse this calculation can be skipped entirely. This is a standard optimization, see e.g. "Handbook of Elliptic and Hyperelliptic Curve Cryptography" Cohen et al pp 191 Available at: http://cs.ucsb.edu/~koc/ccs130h/2013/EllipticHyperelliptic-CohenFrey.pdf Updates #15833 Change-Id: I1e0d2e63567cfed97fd955048fe6373d36f22757 Reviewed-on: https://go-review.googlesource.com/50530 Reviewed-by: Robert Griesemer --- diff --git a/src/math/big/int.go b/src/math/big/int.go index 62f7fc5320..52b6423dfe 100644 --- a/src/math/big/int.go +++ b/src/math/big/int.go @@ -447,7 +447,7 @@ func (z *Int) Exp(x, y, m *Int) *Int { // GCD sets z to the greatest common divisor of a and b, which both must // be > 0, and returns z. -// If x and y are not nil, GCD sets x and y such that z = a*x + b*y. +// If x or y are not nil, GCD sets their value such that z = a*x + b*y. // If either a or b is <= 0, GCD sets z = x = y = 0. func (z *Int) GCD(x, y, a, b *Int) *Int { if a.Sign() <= 0 || b.Sign() <= 0 { @@ -468,10 +468,7 @@ func (z *Int) GCD(x, y, a, b *Int) *Int { B := new(Int).Set(b) X := new(Int) - Y := new(Int).SetInt64(1) - lastX := new(Int).SetInt64(1) - lastY := new(Int) q := new(Int) temp := new(Int) @@ -484,15 +481,8 @@ func (z *Int) GCD(x, y, a, b *Int) *Int { temp.Set(X) X.Mul(X, q) - X.neg = !X.neg - X.Add(X, lastX) + X.Sub(lastX, X) lastX.Set(temp) - - temp.Set(Y) - Y.Mul(Y, q) - Y.neg = !Y.neg - Y.Add(Y, lastY) - lastY.Set(temp) } if x != nil { @@ -500,7 +490,10 @@ func (z *Int) GCD(x, y, a, b *Int) *Int { } if y != nil { - *y = *lastY + // y = (z - a*x)/b + y.Mul(a, lastX) + y.Sub(A, y) + y.Div(y, b) } *z = *A