1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:07:59 -07:00

math: special cases for Ceil, Exp, Floor, Log, Log10

Added special case tests to all_test.go. Added tests to Floor,
in-lined tests in Exp and Log.

R=rsc
CC=golang-dev
https://golang.org/cl/184081
This commit is contained in:
Charles L. Dorian 2010-01-11 21:28:02 -08:00 committed by Russ Cox
parent e7cceb85e4
commit 46206c52e3
4 changed files with 108 additions and 10 deletions

View File

@ -118,6 +118,18 @@ var log = []float64{
6.0174879014578053e-01, 6.0174879014578053e-01,
2.1617038728473527e+00, 2.1617038728473527e+00,
} }
var log10 = []float64{
6.9714316642508291e-01,
8.8867769017393205e-01,
-5.5770832400658930e-01,
6.9989004768229943e-01,
9.8391002850684232e-01,
4.6633031029295153e-01,
7.1842557117242328e-01,
4.3583479968917772e-01,
2.6133617905227037e-01,
9.3881606348649405e-01,
}
var pow = []float64{ var pow = []float64{
9.5282232631648415e+04, 9.5282232631648415e+04,
5.4811599352999900e+07, 5.4811599352999900e+07,
@ -210,6 +222,28 @@ var atanSC = []float64{
NaN(), NaN(),
} }
var vfceilSC = []float64{
Inf(-1),
Inf(1),
NaN(),
}
var ceilSC = []float64{
Inf(-1),
Inf(1),
NaN(),
}
var vfexpSC = []float64{
Inf(-1),
Inf(1),
NaN(),
}
var expSC = []float64{
0,
Inf(1),
NaN(),
}
var vffmodSC = [][2]float64{ var vffmodSC = [][2]float64{
[2]float64{Inf(-1), Inf(-1)}, [2]float64{Inf(-1), Inf(-1)},
[2]float64{Inf(-1), -Pi}, [2]float64{Inf(-1), -Pi},
@ -275,6 +309,21 @@ var fmodSC = []float64{
NaN(), NaN(),
} }
var vflogSC = []float64{
Inf(-1),
-Pi,
0,
Inf(1),
NaN(),
}
var logSC = []float64{
NaN(),
NaN(),
Inf(-1),
Inf(1),
NaN(),
}
var vfpowSC = [][2]float64{ var vfpowSC = [][2]float64{
[2]float64{-Pi, Pi}, [2]float64{-Pi, Pi},
[2]float64{-Pi, -Pi}, [2]float64{-Pi, -Pi},
@ -440,6 +489,11 @@ func TestCeil(t *testing.T) {
t.Errorf("Ceil(%g) = %g, want %g\n", vf[i], f, ceil[i]) t.Errorf("Ceil(%g) = %g, want %g\n", vf[i], f, ceil[i])
} }
} }
for i := 0; i < len(vfceilSC); i++ {
if f := Ceil(vfceilSC[i]); !alike(ceilSC[i], f) {
t.Errorf("Ceil(%g) = %g, want %g\n", vfceilSC[i], f, ceilSC[i])
}
}
} }
func TestExp(t *testing.T) { func TestExp(t *testing.T) {
@ -448,6 +502,11 @@ func TestExp(t *testing.T) {
t.Errorf("Exp(%g) = %g, want %g\n", vf[i], f, exp[i]) t.Errorf("Exp(%g) = %g, want %g\n", vf[i], f, exp[i])
} }
} }
for i := 0; i < len(vfexpSC); i++ {
if f := Exp(vfexpSC[i]); !alike(expSC[i], f) {
t.Errorf("Exp(%g) = %g, want %g\n", vfexpSC[i], f, expSC[i])
}
}
} }
func TestFloor(t *testing.T) { func TestFloor(t *testing.T) {
@ -456,6 +515,11 @@ func TestFloor(t *testing.T) {
t.Errorf("Floor(%g) = %g, want %g\n", vf[i], f, floor[i]) t.Errorf("Floor(%g) = %g, want %g\n", vf[i], f, floor[i])
} }
} }
for i := 0; i < len(vfceilSC); i++ {
if f := Floor(vfceilSC[i]); !alike(ceilSC[i], f) {
t.Errorf("Floor(%g) = %g, want %g\n", vfceilSC[i], f, ceilSC[i])
}
}
} }
func TestFmod(t *testing.T) { func TestFmod(t *testing.T) {
@ -479,7 +543,29 @@ func TestLog(t *testing.T) {
} }
} }
if f := Log(10); f != Ln10 { if f := Log(10); f != Ln10 {
t.Errorf("Log(%g) = %g, want %g\n", 10, f, Ln10) t.Errorf("Log(%g) = %g, want %g\n", 10.0, f, Ln10)
}
for i := 0; i < len(vflogSC); i++ {
if f := Log(vflogSC[i]); !alike(logSC[i], f) {
t.Errorf("Log(%g) = %g, want %g\n", vflogSC[i], f, logSC[i])
}
}
}
func TestLog10(t *testing.T) {
for i := 0; i < len(vf); i++ {
a := Fabs(vf[i])
if f := Log10(a); !veryclose(log10[i], f) {
t.Errorf("Log10(%g) = %g, want %g\n", a, f, log10[i])
}
}
if f := Log10(E); f != Log10E {
t.Errorf("Log10(%g) = %g, want %g\n", E, f, Log10E)
}
for i := 0; i < len(vflogSC); i++ {
if f := Log10(vflogSC[i]); !alike(logSC[i], f) {
t.Errorf("Log10(%g) = %g, want %g\n", vflogSC[i], f, logSC[i])
}
} }
} }

View File

@ -104,11 +104,13 @@ func Exp(x float64) float64 {
NearZero = 1.0 / (1 << 28) // 2^-28 NearZero = 1.0 / (1 << 28) // 2^-28
) )
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases // special cases
switch { switch {
case IsNaN(x) || IsInf(x, 1): case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x return x
case IsInf(x, -1): case x < -MaxFloat64: // IsInf(x, -1):
return 0 return 0
case x > Overflow: case x > Overflow:
return Inf(1) return Inf(1)

View File

@ -6,7 +6,15 @@ package math
// Floor returns the greatest integer value less than or equal to x. // Floor returns the greatest integer value less than or equal to x.
//
// Special cases are:
// Floor(+Inf) = +Inf
// Floor(-Inf) = -Inf
// Floor(NaN) = NaN
func Floor(x float64) float64 { func Floor(x float64) float64 {
if x != x || x > MaxFloat64 || x < -MaxFloat64 { // IsNaN(x) || IsInf(x, 0)
return x
}
if x < 0 { if x < 0 {
d, fract := Modf(-x) d, fract := Modf(-x)
if fract != 0.0 { if fract != 0.0 {
@ -19,4 +27,9 @@ func Floor(x float64) float64 {
} }
// Ceil returns the least integer value greater than or equal to x. // Ceil returns the least integer value greater than or equal to x.
//
// Special cases are:
// Ceil(+Inf) = +Inf
// Ceil(-Inf) = -Inf
// Ceil(NaN) = NaN
func Ceil(x float64) float64 { return -Floor(-x) } func Ceil(x float64) float64 { return -Floor(-x) }

View File

@ -90,9 +90,11 @@ func Log(x float64) float64 {
L7 = 1.479819860511658591e-01 /* 3FC2F112 DF3E5244 */ L7 = 1.479819860511658591e-01 /* 3FC2F112 DF3E5244 */
) )
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases // special cases
switch { switch {
case IsNaN(x) || IsInf(x, 1): case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x return x
case x < 0: case x < 0:
return NaN() return NaN()
@ -122,9 +124,4 @@ func Log(x float64) float64 {
// Log10 returns the decimal logarithm of x. // Log10 returns the decimal logarithm of x.
// The special cases are the same as for Log. // The special cases are the same as for Log.
func Log10(x float64) float64 { func Log10(x float64) float64 { return Log(x) * (1 / Ln10) }
if x <= 0 {
return NaN()
}
return Log(x) * (1 / Ln10)
}