From 7832c82bf5ebd32e24e3f324f5284194e505f3e4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 29 Oct 2015 19:16:20 -0700 Subject: [PATCH] math: fix bad shift in Expm1 Noticed by cmd/vet. Expected values array produced by Python instead of Keisan because: 1) Keisan's website calculator is painfully difficult to copy/paste values into and out of, and 2) after tediously computing e^(vf[i] * 10) - 1 via Keisan I discovered that Keisan computing vf[i]*10 in a higher precision was giving substantially different output values. Also, testing uses "close" instead of "veryclose" because 386's assembly implementation produces values for some of the test cases that fail "veryclose". Curiously, Expm1(vf[i]*10) is identical to Exp(vf[i]*10)-1 on 386, whereas with the portable implementation they're only "veryclose". Investigating these questions is left to someone else. I just wanted to fix the cmd/vet warning. Fixes #13101. Change-Id: Ica8f6c267d01aa4cc31f53593e95812746942fbc Reviewed-on: https://go-review.googlesource.com/16505 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Klaus Post Reviewed-by: Robert Griesemer --- src/math/all_test.go | 18 ++++++++++++++++++ src/math/expm1.go | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/math/all_test.go b/src/math/all_test.go index 4838ffc5e1..968a7b1837 100644 --- a/src/math/all_test.go +++ b/src/math/all_test.go @@ -234,6 +234,18 @@ var expm1 = []float64{ 1.842068661871398836913874273e-02, -8.3193870863553801814961137573e-02, } +var expm1Large = []float64{ + 4.2031418113550844e+21, + 4.0690789717473863e+33, + -0.9372627915981363e+00, + -1.0, + 7.077694784145933e+41, + 5.117936223839153e+12, + 5.124137759001189e+22, + 7.03546003972584e+11, + 8.456921800389698e+07, + -1.0, +} var exp2 = []float64{ 3.1537839463286288034313104e+01, 2.1361549283756232296144849e+02, @@ -1987,6 +1999,12 @@ func TestExpm1(t *testing.T) { t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i]) } } + for i := 0; i < len(vf); i++ { + a := vf[i] * 10 + if f := Expm1(a); !close(expm1Large[i], f) { + t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i]) + } + } for i := 0; i < len(vfexpm1SC); i++ { if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) { t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i]) diff --git a/src/math/expm1.go b/src/math/expm1.go index 064e131161..670b96de5e 100644 --- a/src/math/expm1.go +++ b/src/math/expm1.go @@ -227,7 +227,7 @@ func expm1(x float64) float64 { y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent return y } - t := Float64frombits(uint64((0x3ff - k) << 52)) // 2**-k + t := Float64frombits(uint64(0x3ff-k) << 52) // 2**-k y := x - (e + t) y += 1 y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent -- 2.48.1