diff options
author | Ian Lance Taylor <iant@google.com> | 2011-01-21 18:19:03 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-01-21 18:19:03 +0000 |
commit | ff5f50c52c421d75940ef9392211e3ab24d71332 (patch) | |
tree | 27d8768fb1d25696d3c40b42535eb5e073c278da /libgo/go/math | |
parent | d6ed1c8903e728f4233122554bab5910853338bd (diff) | |
download | gcc-ff5f50c52c421d75940ef9392211e3ab24d71332.zip gcc-ff5f50c52c421d75940ef9392211e3ab24d71332.tar.gz gcc-ff5f50c52c421d75940ef9392211e3ab24d71332.tar.bz2 |
Remove the types float and complex.
Update to current version of Go library.
Update testsuite for removed types.
* go-lang.c (go_langhook_init): Omit float_type_size when calling
go_create_gogo.
* go-c.h: Update declaration of go_create_gogo.
From-SVN: r169098
Diffstat (limited to 'libgo/go/math')
-rw-r--r-- | libgo/go/math/all_test.go | 159 | ||||
-rw-r--r-- | libgo/go/math/bits.go | 12 | ||||
-rw-r--r-- | libgo/go/math/const.go | 10 | ||||
-rw-r--r-- | libgo/go/math/exp.go | 129 | ||||
-rw-r--r-- | libgo/go/math/exp2.go | 2 | ||||
-rw-r--r-- | libgo/go/math/exp_port.go | 192 | ||||
-rw-r--r-- | libgo/go/math/exp_test.go | 10 | ||||
-rw-r--r-- | libgo/go/math/frexp.go | 10 | ||||
-rw-r--r-- | libgo/go/math/gamma.go | 2 | ||||
-rw-r--r-- | libgo/go/math/jn.go | 4 | ||||
-rw-r--r-- | libgo/go/math/ldexp.go | 28 | ||||
-rw-r--r-- | libgo/go/math/lgamma.go | 2 | ||||
-rw-r--r-- | libgo/go/math/logb.go | 15 | ||||
-rw-r--r-- | libgo/go/math/modf.go | 6 | ||||
-rw-r--r-- | libgo/go/math/pow.go | 2 | ||||
-rw-r--r-- | libgo/go/math/sqrt_port.go | 4 |
16 files changed, 421 insertions, 166 deletions
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go index 7a61280..d2a7d41 100644 --- a/libgo/go/math/all_test.go +++ b/libgo/go/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 { @@ -1662,14 +1748,19 @@ func TestErfc(t *testing.T) { } func TestExp(t *testing.T) { + testExp(t, Exp, "Exp") + testExp(t, ExpGo, "ExpGo") +} + +func testExp(t *testing.T, Exp func(float64) float64, name string) { for i := 0; i < len(vf); i++ { if f := Exp(vf[i]); !close(exp[i], f) { - t.Errorf("Exp(%g) = %g, want %g", vf[i], f, exp[i]) + t.Errorf("%s(%g) = %g, want %g", name, 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", vfexpSC[i], f, expSC[i]) + t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) } } } @@ -1689,14 +1780,26 @@ func TestExpm1(t *testing.T) { } func TestExp2(t *testing.T) { + testExp2(t, Exp2, "Exp2") + testExp2(t, Exp2Go, "Exp2Go") +} + +func testExp2(t *testing.T, Exp2 func(float64) float64, name string) { for i := 0; i < len(vf); i++ { if f := Exp2(vf[i]); !close(exp2[i], f) { - t.Errorf("Exp2(%g) = %g, want %g", 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++ { if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) { - t.Errorf("Exp2(%g) = %g, want %g", vfexpSC[i], f, expSC[i]) + t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) + } + } + for n := -1074; n < 1024; n++ { + f := Exp2(float64(n)) + vf := Ldexp(1, n) + if f != vf { + t.Errorf("%s(%d) = %g, want %g", name, n, f, vf) } } } @@ -1775,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) { @@ -1816,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) { @@ -1874,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) { @@ -1917,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) { @@ -1943,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) } @@ -2246,9 +2379,9 @@ type floatTest struct { var floatTests = []floatTest{ {float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"}, - {float64(MinFloat64), "MinFloat64", "5e-324"}, + {float64(SmallestNonzeroFloat64), "SmallestNonzeroFloat64", "5e-324"}, {float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"}, - {float32(MinFloat32), "MinFloat32", "1e-45"}, + {float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"}, } func TestFloatMinMax(t *testing.T) { @@ -2352,6 +2485,12 @@ func BenchmarkExp(b *testing.B) { } } +func BenchmarkExpGo(b *testing.B) { + for i := 0; i < b.N; i++ { + ExpGo(.5) + } +} + func BenchmarkExpm1(b *testing.B) { for i := 0; i < b.N; i++ { Expm1(.5) @@ -2364,6 +2503,12 @@ func BenchmarkExp2(b *testing.B) { } } +func BenchmarkExp2Go(b *testing.B) { + for i := 0; i < b.N; i++ { + Exp2Go(.5) + } +} + func BenchmarkFabs(b *testing.B) { for i := 0; i < b.N; i++ { Fabs(.5) diff --git a/libgo/go/math/bits.go b/libgo/go/math/bits.go index d36cd18..a1dca3e 100644 --- a/libgo/go/math/bits.go +++ b/libgo/go/math/bits.go @@ -10,7 +10,7 @@ const ( uvneginf = 0xFFF0000000000000 mask = 0x7FF shift = 64 - 11 - 1 - bias = 1022 + bias = 1023 ) // Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. @@ -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/libgo/go/math/const.go b/libgo/go/math/const.go index 6a78d00..b53527a 100644 --- a/libgo/go/math/const.go +++ b/libgo/go/math/const.go @@ -25,13 +25,13 @@ const ( // Floating-point limit values. // Max is the largest finite value representable by the type. -// Min is the smallest nonzero value representable by the type. +// SmallestNonzero is the smallest positive, non-zero value representable by the type. const ( - MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */ - MinFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */ + MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */ + SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */ - MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */ - MinFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */ + MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */ + SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */ ) // Integer limit values. diff --git a/libgo/go/math/exp.go b/libgo/go/math/exp.go index 90409c3..c519c2c 100644 --- a/libgo/go/math/exp.go +++ b/libgo/go/math/exp.go @@ -4,83 +4,6 @@ package math - -// The original C code, the long comment, and the constants -// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c -// and came with this notice. The go code is a simplified -// version of the original C. -// -// ==================================================== -// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. -// -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// -// exp(x) -// Returns the exponential of x. -// -// Method -// 1. Argument reduction: -// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. -// Given x, find r and integer k such that -// -// x = k*ln2 + r, |r| <= 0.5*ln2. -// -// Here r will be represented as r = hi-lo for better -// accuracy. -// -// 2. Approximation of exp(r) by a special rational function on -// the interval [0,0.34658]: -// Write -// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... -// We use a special Remes algorithm on [0,0.34658] to generate -// a polynomial of degree 5 to approximate R. The maximum error -// of this polynomial approximation is bounded by 2**-59. In -// other words, -// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 -// (where z=r*r, and the values of P1 to P5 are listed below) -// and -// | 5 | -59 -// | 2.0+P1*z+...+P5*z - R(z) | <= 2 -// | | -// The computation of exp(r) thus becomes -// 2*r -// exp(r) = 1 + ------- -// R - r -// r*R1(r) -// = 1 + r + ----------- (for better accuracy) -// 2 - R1(r) -// where -// 2 4 10 -// R1(r) = r - (P1*r + P2*r + ... + P5*r ). -// -// 3. Scale back to obtain exp(x): -// From step 1, we have -// exp(x) = 2**k * exp(r) -// -// Special cases: -// exp(INF) is INF, exp(NaN) is NaN; -// exp(-INF) is 0, and -// for finite argument, only exp(0)=1 is exact. -// -// Accuracy: -// according to an error analysis, the error is always less than -// 1 ulp (unit in the last place). -// -// Misc. info. -// For IEEE double -// if x > 7.09782712893383973096e+02 then exp(x) overflow -// if x < -7.45133219101941108420e+02 then exp(x) underflow -// -// Constants: -// The hexadecimal values are the intended ones for the following -// constants. The decimal values may be used, provided that the -// compiler will convert from decimal to binary accurately enough -// to produce the hexadecimal values shown. - // Exp returns e**x, the base-e exponential of x. // // Special cases are: @@ -88,54 +11,4 @@ package math // Exp(NaN) = NaN // Very large values overflow to 0 or +Inf. // Very small values underflow to 1. -func Exp(x float64) float64 { - const ( - Ln2Hi = 6.93147180369123816490e-01 - Ln2Lo = 1.90821492927058770002e-10 - Log2e = 1.44269504088896338700e+00 - P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */ - P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */ - P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */ - P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */ - P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */ - - Overflow = 7.09782712893383973096e+02 - Underflow = -7.45133219101941108420e+02 - NearZero = 1.0 / (1 << 28) // 2**-28 - ) - - // TODO(rsc): Remove manual inlining of IsNaN, IsInf - // when compiler does it for us - // special cases - switch { - case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): - return x - case x < -MaxFloat64: // IsInf(x, -1): - return 0 - case x > Overflow: - return Inf(1) - case x < Underflow: - return 0 - case -NearZero < x && x < NearZero: - return 1 - } - - // reduce; computed as r = hi - lo for extra precision. - var k int - switch { - case x < 0: - k = int(Log2e*x - 0.5) - case x > 0: - k = int(Log2e*x + 0.5) - } - hi := x - float64(k)*Ln2Hi - lo := float64(k) * Ln2Lo - r := hi - lo - - // compute - t := r * r - c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) - y := 1 - ((lo - (r*c)/(2-c)) - hi) - // TODO(rsc): make sure Ldexp can handle boundary k - return Ldexp(y, k) -} +func Exp(x float64) float64 { return expGo(x) } diff --git a/libgo/go/math/exp2.go b/libgo/go/math/exp2.go index 1e67f29..1cface9 100644 --- a/libgo/go/math/exp2.go +++ b/libgo/go/math/exp2.go @@ -7,4 +7,4 @@ package math // Exp2 returns 2**x, the base-2 exponential of x. // // Special cases are the same as Exp. -func Exp2(x float64) float64 { return Exp(x * Ln2) } +func Exp2(x float64) float64 { return exp2Go(x) } diff --git a/libgo/go/math/exp_port.go b/libgo/go/math/exp_port.go new file mode 100644 index 0000000..071420c --- /dev/null +++ b/libgo/go/math/exp_port.go @@ -0,0 +1,192 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math + + +// The original C code, the long comment, and the constants +// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c +// and came with this notice. The go code is a simplified +// version of the original C. +// +// ==================================================== +// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. +// +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// +// exp(x) +// Returns the exponential of x. +// +// Method +// 1. Argument reduction: +// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. +// Given x, find r and integer k such that +// +// x = k*ln2 + r, |r| <= 0.5*ln2. +// +// Here r will be represented as r = hi-lo for better +// accuracy. +// +// 2. Approximation of exp(r) by a special rational function on +// the interval [0,0.34658]: +// Write +// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... +// We use a special Remes algorithm on [0,0.34658] to generate +// a polynomial of degree 5 to approximate R. The maximum error +// of this polynomial approximation is bounded by 2**-59. In +// other words, +// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 +// (where z=r*r, and the values of P1 to P5 are listed below) +// and +// | 5 | -59 +// | 2.0+P1*z+...+P5*z - R(z) | <= 2 +// | | +// The computation of exp(r) thus becomes +// 2*r +// exp(r) = 1 + ------- +// R - r +// r*R1(r) +// = 1 + r + ----------- (for better accuracy) +// 2 - R1(r) +// where +// 2 4 10 +// R1(r) = r - (P1*r + P2*r + ... + P5*r ). +// +// 3. Scale back to obtain exp(x): +// From step 1, we have +// exp(x) = 2**k * exp(r) +// +// Special cases: +// exp(INF) is INF, exp(NaN) is NaN; +// exp(-INF) is 0, and +// for finite argument, only exp(0)=1 is exact. +// +// Accuracy: +// according to an error analysis, the error is always less than +// 1 ulp (unit in the last place). +// +// Misc. info. +// For IEEE double +// if x > 7.09782712893383973096e+02 then exp(x) overflow +// if x < -7.45133219101941108420e+02 then exp(x) underflow +// +// Constants: +// The hexadecimal values are the intended ones for the following +// constants. The decimal values may be used, provided that the +// compiler will convert from decimal to binary accurately enough +// to produce the hexadecimal values shown. + +// Exp returns e**x, the base-e exponential of x. +// +// Special cases are: +// Exp(+Inf) = +Inf +// Exp(NaN) = NaN +// Very large values overflow to 0 or +Inf. +// Very small values underflow to 1. +func expGo(x float64) float64 { + const ( + Ln2Hi = 6.93147180369123816490e-01 + Ln2Lo = 1.90821492927058770002e-10 + Log2e = 1.44269504088896338700e+00 + + Overflow = 7.09782712893383973096e+02 + Underflow = -7.45133219101941108420e+02 + NearZero = 1.0 / (1 << 28) // 2**-28 + ) + + // TODO(rsc): Remove manual inlining of IsNaN, IsInf + // when compiler does it for us + // special cases + switch { + case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): + return x + case x < -MaxFloat64: // IsInf(x, -1): + return 0 + case x > Overflow: + return Inf(1) + case x < Underflow: + return 0 + case -NearZero < x && x < NearZero: + return 1 + x + } + + // reduce; computed as r = hi - lo for extra precision. + var k int + switch { + case x < 0: + k = int(Log2e*x - 0.5) + case x > 0: + k = int(Log2e*x + 0.5) + } + hi := x - float64(k)*Ln2Hi + lo := float64(k) * Ln2Lo + + // compute + return exp(hi, lo, k) +} + +// Exp2 returns 2**x, the base-2 exponential of x. +// +// Special cases are the same as Exp. +func exp2Go(x float64) float64 { + const ( + Ln2Hi = 6.93147180369123816490e-01 + Ln2Lo = 1.90821492927058770002e-10 + + Overflow = 1.0239999999999999e+03 + Underflow = -1.0740e+03 + ) + + // TODO: remove manual inlining of IsNaN and IsInf + // when compiler does it for us + // special cases + switch { + case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): + return x + case x < -MaxFloat64: // IsInf(x, -1): + return 0 + case x > Overflow: + return Inf(1) + case x < Underflow: + return 0 + } + + // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2. + // computed as r = hi - lo for extra precision. + var k int + switch { + case x > 0: + k = int(x + 0.5) + case x < 0: + k = int(x - 0.5) + } + t := x - float64(k) + hi := t * Ln2Hi + lo := -t * Ln2Lo + + // compute + return exp(hi, lo, k) +} + +// exp returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. +func exp(hi, lo float64, k int) float64 { + const ( + P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */ + P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */ + P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */ + P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */ + P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */ + ) + + r := hi - lo + t := r * r + c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) + y := 1 - ((lo - (r*c)/(2-c)) - hi) + // TODO(rsc): make sure Ldexp can handle boundary k + return Ldexp(y, k) +} diff --git a/libgo/go/math/exp_test.go b/libgo/go/math/exp_test.go new file mode 100644 index 0000000..7381fd5 --- /dev/null +++ b/libgo/go/math/exp_test.go @@ -0,0 +1,10 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math + +// Make expGo and exp2Go available for testing. + +func ExpGo(x float64) float64 { return expGo(x) } +func Exp2Go(x float64) float64 { return exp2Go(x) } diff --git a/libgo/go/math/frexp.go b/libgo/go/math/frexp.go index b63b508..867b78f 100644 --- a/libgo/go/math/frexp.go +++ b/libgo/go/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,10 +23,11 @@ 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 + exp += int((x>>shift)&mask) - bias + 1 x &^= mask << shift - x |= bias << shift + x |= (-1 + bias) << shift frac = Float64frombits(x) return } diff --git a/libgo/go/math/gamma.go b/libgo/go/math/gamma.go index 4c5b17d..73ca0e5 100644 --- a/libgo/go/math/gamma.go +++ b/libgo/go/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/libgo/go/math/jn.go b/libgo/go/math/jn.go index 7d31743..9024af3 100644 --- a/libgo/go/math/jn.go +++ b/libgo/go/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/libgo/go/math/ldexp.go b/libgo/go/math/ldexp.go index d04bf15..96c95ca 100644 --- a/libgo/go/math/ldexp.go +++ b/libgo/go/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/libgo/go/math/lgamma.go b/libgo/go/math/lgamma.go index dc31be9..dc30f46 100644 --- a/libgo/go/math/lgamma.go +++ b/libgo/go/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/libgo/go/math/logb.go b/libgo/go/math/logb.go index 22ec063..072281d 100644 --- a/libgo/go/math/logb.go +++ b/libgo/go/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 + 1)) + 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 + 1) + 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/libgo/go/math/modf.go b/libgo/go/math/modf.go index ae0c7c8..315174b 100644 --- a/libgo/go/math/modf.go +++ b/libgo/go/math/modf.go @@ -23,9 +23,9 @@ func Modf(f float64) (int float64, frac float64) { x := Float64bits(f) e := uint(x>>shift)&mask - bias - // Keep the top 11+e bits, the integer part; clear the rest. - if e < 64-11 { - x &^= 1<<(64-11-e) - 1 + // Keep the top 12+e bits, the integer part; clear the rest. + if e < 64-12 { + x &^= 1<<(64-12-e) - 1 } int = Float64frombits(x) frac = f - int diff --git a/libgo/go/math/pow.go b/libgo/go/math/pow.go index f0ad84a..06b1074 100644 --- a/libgo/go/math/pow.go +++ b/libgo/go/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 diff --git a/libgo/go/math/sqrt_port.go b/libgo/go/math/sqrt_port.go index 8d821b5..6f35a38 100644 --- a/libgo/go/math/sqrt_port.go +++ b/libgo/go/math/sqrt_port.go @@ -113,7 +113,7 @@ func sqrtGo(x float64) float64 { } exp++ } - exp -= bias + 1 // unbias exponent + exp -= bias // unbias exponent ix &^= mask << shift ix |= 1 << shift if exp&1 == 1 { // odd exp, double x to make it even @@ -138,6 +138,6 @@ func sqrtGo(x float64) float64 { if ix != 0 { // remainder, result not exact q += q & 1 // round according to extra bit } - ix = q>>1 + uint64(exp+bias)<<shift // significand + biased exponent + ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent return Float64frombits(ix) } |