Commit 3fd62ce9 authored by Brian Kessler's avatar Brian Kessler Committed by Robert Griesemer

math/big: optimize multiplication by 2 and 1/2 in float Sqrt

The Sqrt code previously used explicit constants for 2 and 1/2.  This change
replaces multiplication by these constants with increment and decrement of
the floating point exponent directly.  This improves performance by ~7-10%
for small inputs and minimal improvement for large inputs.

name                 old time/op    new time/op    delta
FloatSqrt/64-4         1.39µs ± 0%    1.29µs ± 3%   -7.01%  (p=0.016 n=4+5)
FloatSqrt/128-4        2.84µs ± 0%    2.60µs ± 1%   -8.33%  (p=0.008 n=5+5)
FloatSqrt/256-4        3.24µs ± 1%    2.91µs ± 2%  -10.00%  (p=0.008 n=5+5)
FloatSqrt/1000-4       7.42µs ± 1%    6.74µs ± 0%   -9.16%  (p=0.008 n=5+5)
FloatSqrt/10000-4      65.9µs ± 1%    65.3µs ± 4%     ~     (p=0.310 n=5+5)
FloatSqrt/100000-4     1.57ms ± 8%    1.52ms ± 1%     ~     (p=0.111 n=5+4)
FloatSqrt/1000000-4     127ms ± 1%     126ms ± 1%     ~     (p=0.690 n=5+5)

Change-Id: Id81ac842a9d64981e001c4ca3ff129eebd227593
Reviewed-on: https://go-review.googlesource.com/130835Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 28fbf5b8
...@@ -7,8 +7,6 @@ package big ...@@ -7,8 +7,6 @@ package big
import "math" import "math"
var ( var (
half = NewFloat(0.5)
two = NewFloat(2.0)
three = NewFloat(3.0) three = NewFloat(3.0)
) )
...@@ -57,9 +55,9 @@ func (z *Float) Sqrt(x *Float) *Float { ...@@ -57,9 +55,9 @@ func (z *Float) Sqrt(x *Float) *Float {
case 0: case 0:
// nothing to do // nothing to do
case 1: case 1:
z.Mul(two, z) z.exp++
case -1: case -1:
z.Mul(half, z) z.exp--
} }
// 0.25 <= z < 2.0 // 0.25 <= z < 2.0
...@@ -96,7 +94,7 @@ func (z *Float) sqrtDirect(x *Float) { ...@@ -96,7 +94,7 @@ func (z *Float) sqrtDirect(x *Float) {
u.prec = t.prec u.prec = t.prec
u.Mul(t, t) // u = t² u.Mul(t, t) // u = t²
u.Add(u, x) // = t² + x u.Add(u, x) // = t² + x
u.Mul(half, u) // = ½(t² + x) u.exp-- // = ½(t² + x)
return t.Quo(u, t) // = ½(t² + x)/t return t.Quo(u, t) // = ½(t² + x)/t
} }
...@@ -137,7 +135,9 @@ func (z *Float) sqrtInverse(x *Float) { ...@@ -137,7 +135,9 @@ func (z *Float) sqrtInverse(x *Float) {
u.Mul(x, u) // = xt² u.Mul(x, u) // = xt²
v.Sub(three, u) // v = 3 - xt² v.Sub(three, u) // v = 3 - xt²
u.Mul(t, v) // u = t(3 - xt²) u.Mul(t, v) // u = t(3 - xt²)
return t.Mul(half, u) // = ½t(3 - xt²) u.exp-- // = ½t(3 - xt²)
return t.Set(u)
} }
xf, _ := x.Float64() xf, _ := x.Float64()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment