diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
commit | 758ff64c69e34965f8af5b2d6ffd65e8d7ab2150 (patch) | |
tree | 6d6b34f8c678862fe9b56c945a7b63f68502c245 /src/pkg/math | |
parent | 3e45412327a2654a77944249962b3652e6142299 (diff) | |
download | golang-upstream/2011-02-01.1.tar.gz |
Imported Upstream version 2011-02-01.1upstream/2011-02-01.1
Diffstat (limited to 'src/pkg/math')
-rw-r--r-- | src/pkg/math/all_test.go | 118 | ||||
-rw-r--r-- | src/pkg/math/bits.go | 10 | ||||
-rw-r--r-- | src/pkg/math/frexp.go | 8 | ||||
-rw-r--r-- | src/pkg/math/gamma.go | 2 | ||||
-rw-r--r-- | src/pkg/math/jn.go | 4 | ||||
-rw-r--r-- | src/pkg/math/ldexp.go | 28 | ||||
-rw-r--r-- | src/pkg/math/lgamma.go | 2 | ||||
-rw-r--r-- | src/pkg/math/logb.go | 15 | ||||
-rw-r--r-- | src/pkg/math/pow.go | 2 |
9 files changed, 170 insertions, 19 deletions
diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go index 6033d37e3..d2a7d411e 100644 --- a/src/pkg/math/all_test.go +++ b/src/pkg/math/all_test.go @@ -1112,6 +1112,33 @@ var jM3SC = []float64{ NaN(), } +var vfldexpSC = []fi{ + {0, 0}, + {0, -1075}, + {0, 1024}, + {Copysign(0, -1), 0}, + {Copysign(0, -1), -1075}, + {Copysign(0, -1), 1024}, + {Inf(1), 0}, + {Inf(1), -1024}, + {Inf(-1), 0}, + {Inf(-1), -1024}, + {NaN(), -1024}, +} +var ldexpSC = []float64{ + 0, + 0, + 0, + Copysign(0, -1), + Copysign(0, -1), + Copysign(0, -1), + Inf(1), + Inf(1), + Inf(-1), + Inf(-1), + NaN(), +} + var vflgammaSC = []float64{ Inf(-1), -3, @@ -1440,6 +1467,65 @@ var yM3SC = []float64{ NaN(), } +// arguments and expected results for boundary cases +const ( + SmallestNormalFloat64 = 2.2250738585072014e-308 // 2**-1022 + LargestSubnormalFloat64 = SmallestNormalFloat64 - SmallestNonzeroFloat64 +) + +var vffrexpBC = []float64{ + SmallestNormalFloat64, + LargestSubnormalFloat64, + SmallestNonzeroFloat64, + MaxFloat64, + -SmallestNormalFloat64, + -LargestSubnormalFloat64, + -SmallestNonzeroFloat64, + -MaxFloat64, +} +var frexpBC = []fi{ + {0.5, -1021}, + {0.99999999999999978, -1022}, + {0.5, -1073}, + {0.99999999999999989, 1024}, + {-0.5, -1021}, + {-0.99999999999999978, -1022}, + {-0.5, -1073}, + {-0.99999999999999989, 1024}, +} + +var vfldexpBC = []fi{ + {SmallestNormalFloat64, -52}, + {LargestSubnormalFloat64, -51}, + {SmallestNonzeroFloat64, 1074}, + {MaxFloat64, -(1023 + 1074)}, + {1, -1075}, + {-1, -1075}, + {1, 1024}, + {-1, 1024}, +} +var ldexpBC = []float64{ + SmallestNonzeroFloat64, + 1e-323, // 2**-1073 + 1, + 1e-323, // 2**-1073 + 0, + Copysign(0, -1), + Inf(1), + Inf(-1), +} + +var logbBC = []float64{ + -1022, + -1023, + -1074, + 1023, + -1022, + -1023, + -1074, + 1023, +} + func tolerance(a, b, e float64) bool { d := a - b if d < 0 { @@ -1792,6 +1878,11 @@ func TestFrexp(t *testing.T) { t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i) } } + for i := 0; i < len(vffrexpBC); i++ { + if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j { + t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i) + } + } } func TestGamma(t *testing.T) { @@ -1833,6 +1924,11 @@ func TestIlogb(t *testing.T) { t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i]) } } + for i := 0; i < len(vffrexpBC); i++ { + if e := Ilogb(vffrexpBC[i]); int(logbBC[i]) != e { + t.Errorf("Ilogb(%g) = %d, want %d", vffrexpBC[i], e, int(logbBC[i])) + } + } } func TestJ0(t *testing.T) { @@ -1891,6 +1987,21 @@ func TestLdexp(t *testing.T) { t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i]) } } + for i := 0; i < len(vfldexpSC); i++ { + if f := Ldexp(vfldexpSC[i].f, vfldexpSC[i].i); !alike(ldexpSC[i], f) { + t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpSC[i].f, vfldexpSC[i].i, f, ldexpSC[i]) + } + } + for i := 0; i < len(vffrexpBC); i++ { + if f := Ldexp(frexpBC[i].f, frexpBC[i].i); !alike(vffrexpBC[i], f) { + t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpBC[i].f, frexpBC[i].i, f, vffrexpBC[i]) + } + } + for i := 0; i < len(vfldexpBC); i++ { + if f := Ldexp(vfldexpBC[i].f, vfldexpBC[i].i); !alike(ldexpBC[i], f) { + t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpBC[i].f, vfldexpBC[i].i, f, ldexpBC[i]) + } + } } func TestLgamma(t *testing.T) { @@ -1934,6 +2045,11 @@ func TestLogb(t *testing.T) { t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i]) } } + for i := 0; i < len(vffrexpBC); i++ { + if e := Logb(vffrexpBC[i]); !alike(logbBC[i], e) { + t.Errorf("Ilogb(%g) = %g, want %g", vffrexpBC[i], e, logbBC[i]) + } + } } func TestLog10(t *testing.T) { @@ -1960,7 +2076,7 @@ func TestLog1p(t *testing.T) { t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i]) } } - a := float64(9) + a := 9.0 if f := Log1p(a); f != Ln10 { t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10) } diff --git a/src/pkg/math/bits.go b/src/pkg/math/bits.go index 1a97e7679..a1dca3ed6 100644 --- a/src/pkg/math/bits.go +++ b/src/pkg/math/bits.go @@ -47,3 +47,13 @@ func IsInf(f float64, sign int) bool { // return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf; return sign >= 0 && f > MaxFloat64 || sign <= 0 && f < -MaxFloat64 } + +// normalize returns a normal number y and exponent exp +// satisfying x == y × 2**exp. It assumes x is finite and non-zero. +func normalize(x float64) (y float64, exp int) { + const SmallestNormal = 2.2250738585072014e-308 // 2**-1022 + if Fabs(x) < SmallestNormal { + return x * (1 << 52), -52 + } + return x, 0 +} diff --git a/src/pkg/math/frexp.go b/src/pkg/math/frexp.go index 203219c0d..867b78f36 100644 --- a/src/pkg/math/frexp.go +++ b/src/pkg/math/frexp.go @@ -8,6 +8,11 @@ package math // and an integral power of two. // It returns frac and exp satisfying f == frac × 2**exp, // with the absolute value of frac in the interval [½, 1). +// +// Special cases are: +// Frexp(±0) = ±0, 0 +// Frexp(±Inf) = ±Inf, 0 +// Frexp(NaN) = NaN, 0 func Frexp(f float64) (frac float64, exp int) { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us @@ -18,8 +23,9 @@ func Frexp(f float64) (frac float64, exp int) { case f < -MaxFloat64 || f > MaxFloat64 || f != f: // IsInf(f, 0) || IsNaN(f): return f, 0 } + f, exp = normalize(f) x := Float64bits(f) - exp = int((x>>shift)&mask) - bias + 1 + exp += int((x>>shift)&mask) - bias + 1 x &^= mask << shift x |= (-1 + bias) << shift frac = Float64frombits(x) diff --git a/src/pkg/math/gamma.go b/src/pkg/math/gamma.go index 4c5b17d05..73ca0e53a 100644 --- a/src/pkg/math/gamma.go +++ b/src/pkg/math/gamma.go @@ -151,7 +151,7 @@ func Gamma(x float64) float64 { } // Reduce argument - z := float64(1) + z := 1.0 for x >= 3 { x = x - 1 z = z * x diff --git a/src/pkg/math/jn.go b/src/pkg/math/jn.go index 7d3174310..9024af3c2 100644 --- a/src/pkg/math/jn.go +++ b/src/pkg/math/jn.go @@ -132,7 +132,7 @@ func Jn(n int, x float64) float64 { } else { temp := x * 0.5 b = temp - a := float64(1) + a := 1.0 for i := 2; i <= n; i++ { a *= float64(i) // a = n! b *= temp // b = (x/2)**n @@ -181,7 +181,7 @@ func Jn(n int, x float64) float64 { q0, q1 = q1, z*q1-q0 } m := n + n - t := float64(0) + t := 0.0 for i := 2 * (n + k); i >= m; i -= 2 { t = 1 / (float64(i)/x - t) } diff --git a/src/pkg/math/ldexp.go b/src/pkg/math/ldexp.go index d04bf1581..96c95cad4 100644 --- a/src/pkg/math/ldexp.go +++ b/src/pkg/math/ldexp.go @@ -6,6 +6,11 @@ package math // Ldexp is the inverse of Frexp. // It returns frac × 2**exp. +// +// Special cases are: +// Ldexp(±0, exp) = ±0 +// Ldexp(±Inf, exp) = ±Inf +// Ldexp(NaN, exp) = NaN func Ldexp(frac float64, exp int) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us @@ -13,21 +18,28 @@ func Ldexp(frac float64, exp int) float64 { switch { case frac == 0: return frac // correctly return -0 - case frac != frac: // IsNaN(frac): - return NaN() + case frac < -MaxFloat64 || frac > MaxFloat64 || frac != frac: // IsInf(frac, 0) || IsNaN(frac): + return frac } + frac, e := normalize(frac) + exp += e x := Float64bits(frac) - exp += int(x>>shift) & mask - if exp <= 0 { - return 0 // underflow + exp += int(x>>shift)&mask - bias + if exp < -1074 { + return Copysign(0, frac) // underflow } - if exp >= mask { // overflow + if exp > 1023 { // overflow if frac < 0 { return Inf(-1) } return Inf(1) } + var m float64 = 1 + if exp < -1022 { // denormal + exp += 52 + m = 1.0 / (1 << 52) // 2**-52 + } x &^= mask << shift - x |= uint64(exp) << shift - return Float64frombits(x) + x |= uint64(exp+bias) << shift + return m * Float64frombits(x) } diff --git a/src/pkg/math/lgamma.go b/src/pkg/math/lgamma.go index dc31be929..dc30f468f 100644 --- a/src/pkg/math/lgamma.go +++ b/src/pkg/math/lgamma.go @@ -272,7 +272,7 @@ func Lgamma(x float64) (lgamma float64, sign int) { p := y * (S0 + y*(S1+y*(S2+y*(S3+y*(S4+y*(S5+y*S6)))))) q := 1 + y*(R1+y*(R2+y*(R3+y*(R4+y*(R5+y*R6))))) lgamma = 0.5*y + p/q - z := float64(1) // Lgamma(1+s) = Log(s) + Lgamma(s) + z := 1.0 // Lgamma(1+s) = Log(s) + Lgamma(s) switch i { case 7: z *= (y + 6) diff --git a/src/pkg/math/logb.go b/src/pkg/math/logb.go index 9e4651517..072281ddf 100644 --- a/src/pkg/math/logb.go +++ b/src/pkg/math/logb.go @@ -4,7 +4,7 @@ package math -// Logb(x) returns the binary exponent of non-zero x. +// Logb(x) returns the binary exponent of x. // // Special cases are: // Logb(±Inf) = +Inf @@ -22,10 +22,10 @@ func Logb(x float64) float64 { case x != x: // IsNaN(x): return x } - return float64(int((Float64bits(x)>>shift)&mask) - bias) + return float64(ilogb(x)) } -// Ilogb(x) returns the binary exponent of non-zero x as an integer. +// Ilogb(x) returns the binary exponent of x as an integer. // // Special cases are: // Ilogb(±Inf) = MaxInt32 @@ -43,5 +43,12 @@ func Ilogb(x float64) int { case x < -MaxFloat64 || x > MaxFloat64: // IsInf(x, 0): return MaxInt32 } - return int((Float64bits(x)>>shift)&mask) - bias + return ilogb(x) +} + +// logb returns the binary exponent of x. It assumes x is finite and +// non-zero. +func ilogb(x float64) int { + x, exp := normalize(x) + return int((Float64bits(x)>>shift)&mask) - bias + exp } diff --git a/src/pkg/math/pow.go b/src/pkg/math/pow.go index f0ad84af6..06b107401 100644 --- a/src/pkg/math/pow.go +++ b/src/pkg/math/pow.go @@ -98,7 +98,7 @@ func Pow(x, y float64) float64 { } // ans = a1 * 2**ae (= 1 for now). - a1 := float64(1) + a1 := 1.0 ae := 0 // ans *= x**yf |