Commit f44e5870 authored by Alberto Donizetti's avatar Alberto Donizetti Committed by Russ Cox

math: check overflow in amd64 Exp implementation

Unlike the pure go implementation used by every other architecture,
the amd64 asm implementation of Exp does not fail early if the
argument is known to overflow. Make it fail early.

Cost of the check is < 1ns (on an old Sandy Bridge machine):

name   old time/op  new time/op  delta
Exp-4  18.3ns ± 1%  18.7ns ± 1%  +2.08%  (p=0.000 n=18+20)

Fixes #14932
Fixes #18912

Change-Id: I04b3f9b4ee853822cbdc97feade726fbe2907289
Reviewed-on: https://go-review.googlesource.com/36271
Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 4fafc843
...@@ -947,6 +947,11 @@ var vfexpSC = []float64{ ...@@ -947,6 +947,11 @@ var vfexpSC = []float64{
2000, 2000,
Inf(1), Inf(1),
NaN(), NaN(),
// smallest float64 that overflows Exp(x)
7.097827128933841e+02,
// Issue 18912
1.48852223e+09,
1.4885222e+09,
} }
var expSC = []float64{ var expSC = []float64{
0, 0,
...@@ -954,6 +959,27 @@ var expSC = []float64{ ...@@ -954,6 +959,27 @@ var expSC = []float64{
Inf(1), Inf(1),
Inf(1), Inf(1),
NaN(), NaN(),
Inf(1),
Inf(1),
Inf(1),
}
var vfexp2SC = []float64{
Inf(-1),
-2000,
2000,
Inf(1),
NaN(),
// smallest float64 that overflows Exp2(x)
1024,
}
var exp2SC = []float64{
0,
0,
Inf(1),
Inf(1),
NaN(),
Inf(1),
} }
var vfexpm1SC = []float64{ var vfexpm1SC = []float64{
...@@ -2089,8 +2115,8 @@ func testExp2(t *testing.T, Exp2 func(float64) float64, name string) { ...@@ -2089,8 +2115,8 @@ func testExp2(t *testing.T, Exp2 func(float64) float64, name string) {
t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i]) t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i])
} }
} }
for i := 0; i < len(vfexpSC); i++ { for i := 0; i < len(vfexp2SC); i++ {
if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) { if f := Exp2(vfexp2SC[i]); !alike(exp2SC[i], f) {
t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i])
} }
} }
......
...@@ -31,10 +31,11 @@ ...@@ -31,10 +31,11 @@
#define T7 2.4801587301587301587e-5 #define T7 2.4801587301587301587e-5
#define PosInf 0x7FF0000000000000 #define PosInf 0x7FF0000000000000
#define NegInf 0xFFF0000000000000 #define NegInf 0xFFF0000000000000
#define Overflow 7.09782712893384e+02
// func Exp(x float64) float64 // func Exp(x float64) float64
TEXT ·Exp(SB),NOSPLIT,$0 TEXT ·Exp(SB),NOSPLIT,$0
// test bits for not-finite // test bits for not-finite
MOVQ x+0(FP), BX MOVQ x+0(FP), BX
MOVQ $~(1<<63), AX // sign bit mask MOVQ $~(1<<63), AX // sign bit mask
MOVQ BX, DX MOVQ BX, DX
...@@ -42,7 +43,11 @@ TEXT ·Exp(SB),NOSPLIT,$0 ...@@ -42,7 +43,11 @@ TEXT ·Exp(SB),NOSPLIT,$0
MOVQ $PosInf, AX MOVQ $PosInf, AX
CMPQ AX, DX CMPQ AX, DX
JLE notFinite JLE notFinite
// check if argument will overflow
MOVQ BX, X0 MOVQ BX, X0
MOVSD $Overflow, X1
COMISD X1, X0
JA overflow
MOVSD $LOG2E, X1 MOVSD $LOG2E, X1
MULSD X0, X1 MULSD X0, X1
CVTSD2SL X1, BX // BX = exponent CVTSD2SL X1, BX // BX = exponent
......
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