diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-12 01:31:45 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-12 01:31:45 +0000 |
commit | 26ae0101ebafafea33beadccea3056f4b5e135e8 (patch) | |
tree | 86a3b8019380d5fad53258c4baba3dd9e1e7c736 /libgo/go/math | |
parent | c8142b20a95ae9c6bd0bac8c5a545b27402836fe (diff) | |
download | gcc-26ae0101ebafafea33beadccea3056f4b5e135e8.tar.gz |
libgo: Update to weekly.2011-12-14.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183118 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/math')
42 files changed, 643 insertions, 502 deletions
diff --git a/libgo/go/math/abs.go b/libgo/go/math/abs.go index 4c6297c6f33..6818998ee91 100644 --- a/libgo/go/math/abs.go +++ b/libgo/go/math/abs.go @@ -9,7 +9,12 @@ package math // Special cases are: // Abs(±Inf) = +Inf // Abs(NaN) = NaN +func libc_fabs(float64) float64 __asm__("fabs") func Abs(x float64) float64 { + return libc_fabs(x) +} + +func abs(x float64) float64 { switch { case x < 0: return -x diff --git a/libgo/go/math/abs_decl.go b/libgo/go/math/abs_decl.go deleted file mode 100644 index 6be9305ac50..00000000000 --- a/libgo/go/math/abs_decl.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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 - -func Abs(x float64) float64 diff --git a/libgo/go/math/acosh.go b/libgo/go/math/acosh.go index 7e8740b89bd..8d556377f59 100644 --- a/libgo/go/math/acosh.go +++ b/libgo/go/math/acosh.go @@ -36,6 +36,7 @@ package math // Acosh(x) calculates the inverse hyperbolic cosine of x. // // Special cases are: +// Acosh(+Inf) = +Inf // Acosh(x) = NaN if x < 1 // Acosh(NaN) = NaN func Acosh(x float64) float64 { diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go index 7e63023a1c4..0a3cb0315d2 100644 --- a/libgo/go/math/all_test.go +++ b/libgo/go/math/all_test.go @@ -958,6 +958,75 @@ var fabsSC = []float64{ NaN(), } +var vffdimSC = [][2]float64{ + {Inf(-1), Inf(-1)}, + {Inf(-1), Inf(1)}, + {Inf(-1), NaN()}, + {Copysign(0, -1), Copysign(0, -1)}, + {Copysign(0, -1), 0}, + {0, Copysign(0, -1)}, + {0, 0}, + {Inf(1), Inf(-1)}, + {Inf(1), Inf(1)}, + {Inf(1), NaN()}, + {NaN(), Inf(-1)}, + {NaN(), Copysign(0, -1)}, + {NaN(), 0}, + {NaN(), Inf(1)}, + {NaN(), NaN()}, +} +var fdimSC = []float64{ + NaN(), + 0, + NaN(), + 0, + 0, + 0, + 0, + Inf(1), + NaN(), + NaN(), + NaN(), + NaN(), + NaN(), + NaN(), + NaN(), +} +var fmaxSC = []float64{ + Inf(-1), + Inf(1), + NaN(), + Copysign(0, -1), + 0, + 0, + 0, + Inf(1), + Inf(1), + Inf(1), + NaN(), + NaN(), + NaN(), + Inf(1), + NaN(), +} +var fminSC = []float64{ + Inf(-1), + Inf(-1), + Inf(-1), + Copysign(0, -1), + Copysign(0, -1), + Copysign(0, -1), + 0, + Inf(-1), + Inf(1), + NaN(), + Inf(-1), + NaN(), + NaN(), + NaN(), + NaN(), +} + var vffmodSC = [][2]float64{ {Inf(-1), Inf(-1)}, {Inf(-1), -Pi}, @@ -1259,12 +1328,26 @@ var modfSC = [][2]float64{ } var vfnextafterSC = [][2]float64{ + {0, 0}, + {0, Copysign(0, -1)}, + {0, -1}, {0, NaN()}, + {Copysign(0, -1), 1}, + {Copysign(0, -1), 0}, + {Copysign(0, -1), Copysign(0, -1)}, + {Copysign(0, -1), -1}, {NaN(), 0}, {NaN(), NaN()}, } var nextafterSC = []float64{ + 0, + 0, + -4.9406564584124654418e-324, // Float64frombits(0x8000000000000001) NaN(), + 4.9406564584124654418e-324, // Float64frombits(0x0000000000000001) + Copysign(0, -1), + Copysign(0, -1), + -4.9406564584124654418e-324, // Float64frombits(0x8000000000000001) NaN(), NaN(), } @@ -1875,6 +1958,11 @@ func TestDim(t *testing.T) { t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i]) } } + for i := 0; i < len(vffdimSC); i++ { + if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) { + t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i]) + } + } } func TestFloor(t *testing.T) { @@ -1896,6 +1984,11 @@ func TestMax(t *testing.T) { t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i]) } } + for i := 0; i < len(vffdimSC); i++ { + if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) { + t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i]) + } + } } func TestMin(t *testing.T) { @@ -1904,6 +1997,11 @@ func TestMin(t *testing.T) { t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i]) } } + for i := 0; i < len(vffdimSC); i++ { + if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) { + t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i]) + } + } } func TestMod(t *testing.T) { @@ -1964,6 +2062,20 @@ func TestHypot(t *testing.T) { } } +func TestHypotGo(t *testing.T) { + for i := 0; i < len(vf); i++ { + a := Abs(1e200 * tanh[i] * Sqrt(2)) + if f := HypotGo(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) { + t.Errorf("HypotGo(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a) + } + } + for i := 0; i < len(vfhypotSC); i++ { + if f := HypotGo(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) { + t.Errorf("HypotGo(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i]) + } + } +} + func TestIlogb(t *testing.T) { for i := 0; i < len(vf); i++ { a := frexp[i].i - 1 // adjust because fr in the interval [½, 1) @@ -2175,7 +2287,7 @@ func TestNextafter(t *testing.T) { t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i]) } } - for i := 0; i < len(vfmodfSC); i++ { + for i := 0; i < len(vfnextafterSC); i++ { if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) { t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i]) } diff --git a/libgo/go/math/asin.go b/libgo/go/math/asin.go index 0a0b0a11cb4..d67f32a5097 100644 --- a/libgo/go/math/asin.go +++ b/libgo/go/math/asin.go @@ -16,7 +16,12 @@ package math // Special cases are: // Asin(±0) = ±0 // Asin(x) = NaN if x < -1 or x > 1 +func libc_asin(float64) float64 __asm__("asin") func Asin(x float64) float64 { + return libc_asin(x) +} + +func asin(x float64) float64 { if x == 0 { return x // special case } @@ -46,4 +51,11 @@ func Asin(x float64) float64 { // // Special case is: // Acos(x) = NaN if x < -1 or x > 1 -func Acos(x float64) float64 { return Pi/2 - Asin(x) } +func libc_acos(float64) float64 __asm__("acos") +func Acos(x float64) float64 { + return libc_acos(x) +} + +func acos(x float64) float64 { + return Pi/2 - Asin(x) +} diff --git a/libgo/go/math/asinh.go b/libgo/go/math/asinh.go index d6979463d65..f786dd9f8f0 100644 --- a/libgo/go/math/asinh.go +++ b/libgo/go/math/asinh.go @@ -33,6 +33,7 @@ package math // Asinh(x) calculates the inverse hyperbolic sine of x. // // Special cases are: +// Asinh(±0) = ±0 // Asinh(±Inf) = ±Inf // Asinh(NaN) = NaN func Asinh(x float64) float64 { diff --git a/libgo/go/math/atan.go b/libgo/go/math/atan.go index 9d4ec2f72db..ff52cf3d367 100644 --- a/libgo/go/math/atan.go +++ b/libgo/go/math/atan.go @@ -51,7 +51,12 @@ func satan(arg float64) float64 { // Special cases are: // Atan(±0) = ±0 // Atan(±Inf) = ±Pi/2 +func libc_atan(float64) float64 __asm__("atan") func Atan(x float64) float64 { + return libc_atan(x) +} + +func atan(x float64) float64 { if x == 0 { return x } diff --git a/libgo/go/math/atan2.go b/libgo/go/math/atan2.go index 49d4bdd7191..7260f986fad 100644 --- a/libgo/go/math/atan2.go +++ b/libgo/go/math/atan2.go @@ -26,7 +26,12 @@ package math // Atan2(y<0, -Inf) = -Pi // Atan2(+Inf, x) = +Pi/2 // Atan2(-Inf, x) = -Pi/2 +func libc_atan2(float64, float64) float64 __asm__("atan2") func Atan2(y, x float64) float64 { + return libc_atan2(y, x) +} + +func atan2(y, x float64) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us // special cases diff --git a/libgo/go/math/atanh.go b/libgo/go/math/atanh.go index ed38fcac665..e150673c700 100644 --- a/libgo/go/math/atanh.go +++ b/libgo/go/math/atanh.go @@ -39,9 +39,10 @@ package math // Atanh(x) calculates the inverse hyperbolic tangent of x. // // Special cases are: -// Atanh(x) = NaN if x < -1 or x > 1 // Atanh(1) = +Inf +// Atanh(±0) = ±0 // Atanh(-1) = -Inf +// Atanh(x) = NaN if x < -1 or x > 1 // Atanh(NaN) = NaN func Atanh(x float64) float64 { const NearZero = 1.0 / (1 << 28) // 2**-28 diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go index 680445dc9a7..ead1a881a6a 100644 --- a/libgo/go/math/big/nat.go +++ b/libgo/go/math/big/nat.go @@ -592,7 +592,7 @@ func (x nat) bitLen() int { const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1 func hexValue(ch rune) Word { - d := MaxBase + 1 // illegal base + d := int(MaxBase + 1) // illegal base switch { case '0' <= ch && ch <= '9': d = int(ch - '0') diff --git a/libgo/go/math/const.go b/libgo/go/math/const.go index a108d3e294d..282561f98bb 100644 --- a/libgo/go/math/const.go +++ b/libgo/go/math/const.go @@ -49,5 +49,3 @@ const ( MaxUint32 = 1<<32 - 1 MaxUint64 = 1<<64 - 1 ) - -// BUG(rsc): The manual should define the special cases for all of these functions. diff --git a/libgo/go/math/dim.go b/libgo/go/math/dim.go index d2eb52f3bf1..24a84e6d03b 100644 --- a/libgo/go/math/dim.go +++ b/libgo/go/math/dim.go @@ -5,15 +5,45 @@ package math // Dim returns the maximum of x-y or 0. +// +// Special cases are: +// Dim(+Inf, +Inf) = NaN +// Dim(-Inf, -Inf) = NaN +// Dim(x, NaN) = Dim(NaN, x) = NaN func Dim(x, y float64) float64 { - if x > y { - return x - y - } - return 0 + return dim(x, y) +} + +func dim(x, y float64) float64 { + return max(x-y, 0) } // Max returns the larger of x or y. +// +// Special cases are: +// Max(x, +Inf) = Max(+Inf, x) = +Inf +// Max(x, NaN) = Max(NaN, x) = NaN +// Max(+0, ±0) = Max(±0, +0) = +0 +// Max(-0, -0) = -0 func Max(x, y float64) float64 { + return max(x, y) +} + +func max(x, y float64) float64 { + // TODO(rsc): Remove manual inlining of IsNaN, IsInf + // when compiler does it for us + // special cases + switch { + case x > MaxFloat64 || y > MaxFloat64: // IsInf(x, 1) || IsInf(y, 1): + return Inf(1) + case x != x || y != y: // IsNaN(x) || IsNaN(y): + return NaN() + case x == 0 && x == y: + if Signbit(x) { + return y + } + return x + } if x > y { return x } @@ -21,7 +51,30 @@ func Max(x, y float64) float64 { } // Min returns the smaller of x or y. +// +// Special cases are: +// Min(x, -Inf) = Min(-Inf, x) = -Inf +// Min(x, NaN) = Min(NaN, x) = NaN +// Min(-0, ±0) = Min(±0, -0) = -0 func Min(x, y float64) float64 { + return min(x, y) +} + +func min(x, y float64) float64 { + // TODO(rsc): Remove manual inlining of IsNaN, IsInf + // when compiler does it for us + // special cases + switch { + case x < -MaxFloat64 || y < -MaxFloat64: // IsInf(x, -1) || IsInf(y, -1): + return Inf(-1) + case x != x || y != y: // IsNaN(x) || IsNaN(y): + return NaN() + case x == 0 && x == y: + if Signbit(x) { + return x + } + return y + } if x < y { return x } diff --git a/libgo/go/math/dim_decl.go b/libgo/go/math/dim_decl.go deleted file mode 100644 index 196f84fd793..00000000000 --- a/libgo/go/math/dim_decl.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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 - -func Dim(x, y float64) float64 -func Max(x, y float64) float64 -func Min(x, y float64) float64 diff --git a/libgo/go/math/exp.go b/libgo/go/math/exp.go index c519c2cb6b6..2db691f38f1 100644 --- a/libgo/go/math/exp.go +++ b/libgo/go/math/exp.go @@ -11,4 +11,190 @@ package math // Exp(NaN) = NaN // Very large values overflow to 0 or +Inf. // Very small values underflow to 1. -func Exp(x float64) float64 { return expGo(x) } +func libc_exp(float64) float64 __asm__("exp") +func Exp(x float64) float64 { + return libc_exp(x) +} + +// 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. + +func exp(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 expmulti(hi, lo, k) +} + +// Exp2 returns 2**x, the base-2 exponential of x. +// +// Special cases are the same as Exp. +func Exp2(x float64) float64 { + return exp2(x) +} + +func exp2(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 expmulti(hi, lo, k) +} + +// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. +func expmulti(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/exp2.go b/libgo/go/math/exp2.go deleted file mode 100644 index 1cface9d360..00000000000 --- a/libgo/go/math/exp2.go +++ /dev/null @@ -1,10 +0,0 @@ -// 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 - -// Exp2 returns 2**x, the base-2 exponential of x. -// -// Special cases are the same as Exp. -func Exp2(x float64) float64 { return exp2Go(x) } diff --git a/libgo/go/math/exp_port.go b/libgo/go/math/exp_port.go deleted file mode 100644 index 618c31a5d11..00000000000 --- a/libgo/go/math/exp_port.go +++ /dev/null @@ -1,191 +0,0 @@ -// 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 deleted file mode 100644 index 7381fd5ad34..00000000000 --- a/libgo/go/math/exp_test.go +++ /dev/null @@ -1,10 +0,0 @@ -// 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/expm1.go b/libgo/go/math/expm1.go index e9f833140b5..5bffdb323a4 100644 --- a/libgo/go/math/expm1.go +++ b/libgo/go/math/expm1.go @@ -121,7 +121,12 @@ package math // Expm1(-Inf) = -1 // Expm1(NaN) = NaN // Very large values overflow to -1 or +Inf. +func libc_expm1(float64) float64 __asm__("expm1") func Expm1(x float64) float64 { + return libc_expm1(x) +} + +func expm1(x float64) float64 { const ( Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF Ln2X56 = 3.88162421113569373274e+01 // 0x4043687a9f1af2b1 diff --git a/libgo/go/math/export_test.go b/libgo/go/math/export_test.go new file mode 100644 index 00000000000..02992d70e84 --- /dev/null +++ b/libgo/go/math/export_test.go @@ -0,0 +1,11 @@ +// Copyright 2011 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 + +// Export internal functions for testing. +var ExpGo = exp +var Exp2Go = exp2 +var HypotGo = hypot +var SqrtGo = sqrt diff --git a/libgo/go/math/floor.go b/libgo/go/math/floor.go index 8de4d7e2ce6..4d5f4a42707 100644 --- a/libgo/go/math/floor.go +++ b/libgo/go/math/floor.go @@ -7,9 +7,15 @@ package math // Floor returns the greatest integer value less than or equal to x. // // Special cases are: +// Floor(±0) = ±0 // Floor(±Inf) = ±Inf // Floor(NaN) = NaN +func libc_floor(float64) float64 __asm__("floor") func Floor(x float64) float64 { + return libc_floor(x) +} + +func floor(x float64) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0) @@ -29,16 +35,30 @@ func Floor(x float64) float64 { // Ceil returns the least integer value greater than or equal to x. // // Special cases are: +// Ceil(±0) = ±0 // Ceil(±Inf) = ±Inf // Ceil(NaN) = NaN -func Ceil(x float64) float64 { return -Floor(-x) } +func libc_ceil(float64) float64 __asm__("ceil") +func Ceil(x float64) float64 { + return libc_ceil(x) +} + +func ceil(x float64) float64 { + return -Floor(-x) +} // Trunc returns the integer value of x. // // Special cases are: +// Trunc(±0) = ±0 // Trunc(±Inf) = ±Inf // Trunc(NaN) = NaN +func libc_trunc(float64) float64 __asm__("trunc") func Trunc(x float64) float64 { + return libc_trunc(x) +} + +func trunc(x float64) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0) diff --git a/libgo/go/math/frexp.go b/libgo/go/math/frexp.go index 867b78f3648..6b928e714c5 100644 --- a/libgo/go/math/frexp.go +++ b/libgo/go/math/frexp.go @@ -14,6 +14,10 @@ package math // Frexp(±Inf) = ±Inf, 0 // Frexp(NaN) = NaN, 0 func Frexp(f float64) (frac float64, exp int) { + return frexp(f) +} + +func frexp(f float64) (frac float64, exp int) { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us // special cases diff --git a/libgo/go/math/hypot.go b/libgo/go/math/hypot.go index ecd115d9ef8..5c7c3a832b3 100644 --- a/libgo/go/math/hypot.go +++ b/libgo/go/math/hypot.go @@ -15,6 +15,10 @@ package math // Hypot(p, q) = +Inf if p or q is infinite // Hypot(p, q) = NaN if p or q is NaN func Hypot(p, q float64) float64 { + return hypot(p, q) +} + +func hypot(p, q float64) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us // special cases diff --git a/libgo/go/math/hypot_port.go b/libgo/go/math/hypot_port.go deleted file mode 100644 index 27f335ba2de..00000000000 --- a/libgo/go/math/hypot_port.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2009-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 - -/* - Hypot -- sqrt(p*p + q*q), but overflows only if the result does. - See: - Cleve Moler and Donald Morrison, - Replacing Square Roots by Pythagorean Sums - IBM Journal of Research and Development, - Vol. 27, Number 6, pp. 577-581, Nov. 1983 -*/ - -// Hypot computes Sqrt(p*p + q*q), taking care to avoid -// unnecessary overflow and underflow. -// -// Special cases are: -// Hypot(p, q) = +Inf if p or q is infinite -// Hypot(p, q) = NaN if p or q is NaN -func hypotGo(p, q float64) float64 { - // TODO(rsc): Remove manual inlining of IsNaN, IsInf - // when compiler does it for us - // special cases - switch { - case p < -MaxFloat64 || p > MaxFloat64 || q < -MaxFloat64 || q > MaxFloat64: // IsInf(p, 0) || IsInf(q, 0): - return Inf(1) - case p != p || q != q: // IsNaN(p) || IsNaN(q): - return NaN() - } - if p < 0 { - p = -p - } - if q < 0 { - q = -q - } - - if p < q { - p, q = q, p - } - - if p == 0 { - return 0 - } - - pfac := p - q = q / p - r := q - p = 1 - for { - r = r * r - s := r + 4 - if s == 4 { - return p * pfac - } - r = r / s - p = p + 2*r*p - q = q * r - r = q / p - } - panic("unreachable") -} diff --git a/libgo/go/math/hypot_test.go b/libgo/go/math/hypot_test.go deleted file mode 100644 index 85ce1d404d6..00000000000 --- a/libgo/go/math/hypot_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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 hypotGo available for testing. - -func HypotGo(x, y float64) float64 { return hypotGo(x, y) } diff --git a/libgo/go/math/ldexp.go b/libgo/go/math/ldexp.go index 96c95cad4ae..4601cd58cbb 100644 --- a/libgo/go/math/ldexp.go +++ b/libgo/go/math/ldexp.go @@ -11,7 +11,12 @@ package math // Ldexp(±0, exp) = ±0 // Ldexp(±Inf, exp) = ±Inf // Ldexp(NaN, exp) = NaN +func libc_ldexp(float64, int) float64 __asm__("ldexp") func Ldexp(frac float64, exp int) float64 { + return libc_ldexp(frac, exp) +} + +func ldexp(frac float64, exp int) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us // special cases diff --git a/libgo/go/math/log.go b/libgo/go/math/log.go index a786c8ce3ab..f06611dfdd2 100644 --- a/libgo/go/math/log.go +++ b/libgo/go/math/log.go @@ -77,7 +77,12 @@ package math // Log(0) = -Inf // Log(x < 0) = NaN // Log(NaN) = NaN +func libc_log(float64) float64 __asm__("log") func Log(x float64) float64 { + return libc_log(x) +} + +func log(x float64) float64 { const ( Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */ Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */ diff --git a/libgo/go/math/log10.go b/libgo/go/math/log10.go index 6d18baae2a9..5204492b3c4 100644 --- a/libgo/go/math/log10.go +++ b/libgo/go/math/log10.go @@ -6,8 +6,22 @@ package math // Log10 returns the decimal logarithm of x. // The special cases are the same as for Log. -func Log10(x float64) float64 { return Log(x) * (1 / Ln10) } +func libc_log10(float64) float64 __asm__("log10") +func Log10(x float64) float64 { + return libc_log10(x) +} + +func log10(x float64) float64 { + return Log(x) * (1 / Ln10) +} // Log2 returns the binary logarithm of x. // The special cases are the same as for Log. -func Log2(x float64) float64 { return Log(x) * (1 / Ln2) } +func libc_log2(float64) float64 __asm__("log2") +func Log2(x float64) float64 { + return libc_log2(x) +} + +func log2(x float64) float64 { + return Log(x) * (1 / Ln2) +} diff --git a/libgo/go/math/log10_decl.go b/libgo/go/math/log10_decl.go deleted file mode 100644 index 5aec94e1c4f..00000000000 --- a/libgo/go/math/log10_decl.go +++ /dev/null @@ -1,8 +0,0 @@ -// 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 - -func Log10(x float64) float64 -func Log2(x float64) float64 diff --git a/libgo/go/math/log1p.go b/libgo/go/math/log1p.go index e8914a1d053..39c1b40e802 100644 --- a/libgo/go/math/log1p.go +++ b/libgo/go/math/log1p.go @@ -92,7 +92,12 @@ package math // Log1p(-1) = -Inf // Log1p(x < -1) = NaN // Log1p(NaN) = NaN +func libc_log1p(float64) float64 __asm__("log1p") func Log1p(x float64) float64 { + return libc_log1p(x) +} + +func log1p(x float64) float64 { const ( Sqrt2M1 = 4.142135623730950488017e-01 // Sqrt(2)-1 = 0x3fda827999fcef34 Sqrt2HalfM1 = -2.928932188134524755992e-01 // Sqrt(2)/2-1 = 0xbfd2bec333018866 diff --git a/libgo/go/math/mod.go b/libgo/go/math/mod.go index 6b16abe5d13..347da70f832 100644 --- a/libgo/go/math/mod.go +++ b/libgo/go/math/mod.go @@ -13,9 +13,17 @@ package math // sign agrees with that of x. // // Special cases are: -// if x is not finite, Mod returns NaN -// if y is 0 or NaN, Mod returns NaN +// Mod(±Inf, y) = NaN +// Mod(NaN, y) = NaN +// Mod(x, 0) = NaN +// Mod(x, ±Inf) = x +// Mod(x, NaN) = NaN +func libc_fmod(float64, float64) float64 __asm__("fmod") func Mod(x, y float64) float64 { + return libc_fmod(x, y) +} + +func mod(x, y float64) float64 { // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us. if y == 0 || x > MaxFloat64 || x < -MaxFloat64 || x != x || y != y { // y == 0 || IsInf(x, 0) || IsNaN(x) || IsNan(y) diff --git a/libgo/go/math/mod_decl.go b/libgo/go/math/mod_decl.go deleted file mode 100644 index d5047a754a8..00000000000 --- a/libgo/go/math/mod_decl.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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 - -func Mod(x, y float64) float64 diff --git a/libgo/go/math/modf.go b/libgo/go/math/modf.go index 34889e0c0af..ecec4b756c7 100644 --- a/libgo/go/math/modf.go +++ b/libgo/go/math/modf.go @@ -11,6 +11,10 @@ package math // Modf(±Inf) = ±Inf, NaN // Modf(NaN) = NaN, NaN func Modf(f float64) (int float64, frac float64) { + return modf(f) +} + +func modf(f float64) (int float64, frac float64) { if f < 1 { if f < 0 { int, frac = Modf(-f) diff --git a/libgo/go/math/nextafter.go b/libgo/go/math/nextafter.go index 86114340c1e..e7723baacfb 100644 --- a/libgo/go/math/nextafter.go +++ b/libgo/go/math/nextafter.go @@ -8,8 +8,8 @@ package math // If x == y, then x is returned. // // Special cases are: -// Nextafter(NaN, y) = NaN -// Nextafter(x, NaN) = NaN +// Nextafter(NaN, y) = NaN +// Nextafter(x, NaN) = NaN func Nextafter(x, y float64) (r float64) { // TODO(rsc): Remove manual inlining of IsNaN // when compiler does it for us @@ -25,5 +25,5 @@ func Nextafter(x, y float64) (r float64) { default: r = Float64frombits(Float64bits(x) - 1) } - return r + return } diff --git a/libgo/go/math/pow10.go b/libgo/go/math/pow10.go index 20f91bcb70c..f5ad28bb4b0 100644 --- a/libgo/go/math/pow10.go +++ b/libgo/go/math/pow10.go @@ -9,6 +9,10 @@ package math var pow10tab [70]float64 // Pow10 returns 10**e, the base-10 exponential of e. +// +// Special cases are: +// Pow10(e) = +Inf for e > 309 +// Pow10(e) = 0 for e < -324 func Pow10(e int) float64 { if e <= -325 { return 0 diff --git a/libgo/go/math/remainder.go b/libgo/go/math/remainder.go index 7fb8a12f9e6..77811b183f5 100644 --- a/libgo/go/math/remainder.go +++ b/libgo/go/math/remainder.go @@ -29,12 +29,16 @@ package math // Remainder returns the IEEE 754 floating-point remainder of x/y. // // Special cases are: -// Remainder(x, NaN) = NaN +// Remainder(±Inf, y) = NaN // Remainder(NaN, y) = NaN -// Remainder(Inf, y) = NaN // Remainder(x, 0) = NaN -// Remainder(x, Inf) = x +// Remainder(x, ±Inf) = x +// Remainder(x, NaN) = NaN func Remainder(x, y float64) float64 { + return remainder(x, y) +} + +func remainder(x, y float64) float64 { const ( Tiny = 4.45014771701440276618e-308 // 0x0020000000000000 HalfMax = MaxFloat64 / 2 diff --git a/libgo/go/math/sin.go b/libgo/go/math/sin.go index b2a3f8a4e0e..2fbe3e7ec5b 100644 --- a/libgo/go/math/sin.go +++ b/libgo/go/math/sin.go @@ -113,7 +113,12 @@ var _cos = [...]float64{ // Special cases are: // Cos(±Inf) = NaN // Cos(NaN) = NaN +func libc_cos(float64) float64 __asm__("cos") func Cos(x float64) float64 { + return libc_cos(x) +} + +func cos(x float64) float64 { const ( PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000, @@ -166,11 +171,16 @@ func Cos(x float64) float64 { // Sin returns the sine of x. // -// Special conditions are: +// Special cases are: // Sin(±0) = ±0 // Sin(±Inf) = NaN // Sin(NaN) = NaN +func libc_sin(float64) float64 __asm__("sin") func Sin(x float64) float64 { + return libc_sin(x) +} + +func sin(x float64) float64 { const ( PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000, diff --git a/libgo/go/math/sincos.go b/libgo/go/math/sincos.go index 74294256beb..f0de0893e19 100644 --- a/libgo/go/math/sincos.go +++ b/libgo/go/math/sincos.go @@ -13,6 +13,10 @@ package math // Sincos(±Inf) = NaN, NaN // Sincos(NaN) = NaN, NaN func Sincos(x float64) (sin, cos float64) { + return sincos(x) +} + +func sincos(x float64) (sin, cos float64) { const ( PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000, diff --git a/libgo/go/math/sqrt.go b/libgo/go/math/sqrt.go index bf6ef64a0b4..fb3aff8e4fc 100644 --- a/libgo/go/math/sqrt.go +++ b/libgo/go/math/sqrt.go @@ -4,7 +4,95 @@ package math +// Sqrt returns the square root of x. +// +// Special cases are: +// Sqrt(+Inf) = +Inf +// Sqrt(±0) = ±0 +// Sqrt(x < 0) = NaN +// Sqrt(NaN) = NaN func libc_sqrt(float64) float64 __asm__("sqrt") +func Sqrt(x float64) float64 { + return libc_sqrt(x) +} + +// The original C code and the long comment below are +// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and +// came with this notice. The go code is a simplified +// version of the original C. +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// __ieee754_sqrt(x) +// Return correctly rounded sqrt. +// ----------------------------------------- +// | Use the hardware sqrt if you have one | +// ----------------------------------------- +// Method: +// Bit by bit method using integer arithmetic. (Slow, but portable) +// 1. Normalization +// Scale x to y in [1,4) with even powers of 2: +// find an integer k such that 1 <= (y=x*2**(2k)) < 4, then +// sqrt(x) = 2**k * sqrt(y) +// 2. Bit by bit computation +// Let q = sqrt(y) truncated to i bit after binary point (q = 1), +// i 0 +// i+1 2 +// s = 2*q , and y = 2 * ( y - q ). (1) +// i i i i +// +// To compute q from q , one checks whether +// i+1 i +// +// -(i+1) 2 +// (q + 2 ) <= y. (2) +// i +// -(i+1) +// If (2) is false, then q = q ; otherwise q = q + 2 . +// i+1 i i+1 i +// +// With some algebraic manipulation, it is not difficult to see +// that (2) is equivalent to +// -(i+1) +// s + 2 <= y (3) +// i i +// +// The advantage of (3) is that s and y can be computed by +// i i +// the following recurrence formula: +// if (3) is false +// +// s = s , y = y ; (4) +// i+1 i i+1 i +// +// otherwise, +// -i -(i+1) +// s = s + 2 , y = y - s - 2 (5) +// i+1 i i+1 i i +// +// One may easily use induction to prove (4) and (5). +// Note. Since the left hand side of (3) contain only i+2 bits, +// it does not necessary to do a full (53-bit) comparison +// in (3). +// 3. Final rounding +// After generating the 53 bits result, we compute one more bit. +// Together with the remainder, we can decide whether the +// result is exact, bigger than 1/2ulp, or less than 1/2ulp +// (it will never equal to 1/2ulp). +// The rounding mode can be detected by checking whether +// huge + tiny is equal to huge, and whether huge - tiny is +// equal to huge for some floating point number "huge" and "tiny". +// +// +// Notes: Rounding mode detection omitted. The constants "mask", "shift", +// and "bias" are found in src/pkg/math/bits.go // Sqrt returns the square root of x. // @@ -13,7 +101,7 @@ func libc_sqrt(float64) float64 __asm__("sqrt") // Sqrt(±0) = ±0 // Sqrt(x < 0) = NaN // Sqrt(NaN) = NaN -func Sqrt(x float64) float64 { +func sqrt(x float64) float64 { // special cases // TODO(rsc): Remove manual inlining of IsNaN, IsInf // when compiler does it for us @@ -23,6 +111,45 @@ func Sqrt(x float64) float64 { case x < 0: return NaN() } + ix := Float64bits(x) + // normalize x + exp := int((ix >> shift) & mask) + if exp == 0 { // subnormal x + for ix&1<<shift == 0 { + ix <<= 1 + exp-- + } + exp++ + } + exp -= bias // unbias exponent + ix &^= mask << shift + ix |= 1 << shift + if exp&1 == 1 { // odd exp, double x to make it even + ix <<= 1 + } + exp >>= 1 // exp = exp/2, exponent of square root + // generate sqrt(x) bit by bit + ix <<= 1 + var q, s uint64 // q = sqrt(x) + r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB + for r != 0 { + t := s + r + if t <= ix { + s = t + r + ix -= t + q += r + } + ix <<= 1 + r >>= 1 + } + // final rounding + if ix != 0 { // remainder, result not exact + q += q & 1 // round according to extra bit + } + ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent + return Float64frombits(ix) +} - return libc_sqrt(x) +func sqrtC(f float64, r *float64) { + *r = sqrt(f) } diff --git a/libgo/go/math/sqrt_decl.go b/libgo/go/math/sqrt_decl.go deleted file mode 100644 index e507746458b..00000000000 --- a/libgo/go/math/sqrt_decl.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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 - -func Sqrt(x float64) float64 diff --git a/libgo/go/math/sqrt_port.go b/libgo/go/math/sqrt_port.go deleted file mode 100644 index 148239bcff6..00000000000 --- a/libgo/go/math/sqrt_port.go +++ /dev/null @@ -1,147 +0,0 @@ -// 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 - -/* - Floating-point square root. -*/ - -// The original C code and the long comment below are -// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and -// came with this notice. The go code is a simplified -// version of the original C. -// -// ==================================================== -// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -// -// Developed at SunPro, a Sun Microsystems, Inc. business. -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// __ieee754_sqrt(x) -// Return correctly rounded sqrt. -// ----------------------------------------- -// | Use the hardware sqrt if you have one | -// ----------------------------------------- -// Method: -// Bit by bit method using integer arithmetic. (Slow, but portable) -// 1. Normalization -// Scale x to y in [1,4) with even powers of 2: -// find an integer k such that 1 <= (y=x*2**(2k)) < 4, then -// sqrt(x) = 2**k * sqrt(y) -// 2. Bit by bit computation -// Let q = sqrt(y) truncated to i bit after binary point (q = 1), -// i 0 -// i+1 2 -// s = 2*q , and y = 2 * ( y - q ). (1) -// i i i i -// -// To compute q from q , one checks whether -// i+1 i -// -// -(i+1) 2 -// (q + 2 ) <= y. (2) -// i -// -(i+1) -// If (2) is false, then q = q ; otherwise q = q + 2 . -// i+1 i i+1 i -// -// With some algebraic manipulation, it is not difficult to see -// that (2) is equivalent to -// -(i+1) -// s + 2 <= y (3) -// i i -// -// The advantage of (3) is that s and y can be computed by -// i i -// the following recurrence formula: -// if (3) is false -// -// s = s , y = y ; (4) -// i+1 i i+1 i -// -// otherwise, -// -i -(i+1) -// s = s + 2 , y = y - s - 2 (5) -// i+1 i i+1 i i -// -// One may easily use induction to prove (4) and (5). -// Note. Since the left hand side of (3) contain only i+2 bits, -// it does not necessary to do a full (53-bit) comparison -// in (3). -// 3. Final rounding -// After generating the 53 bits result, we compute one more bit. -// Together with the remainder, we can decide whether the -// result is exact, bigger than 1/2ulp, or less than 1/2ulp -// (it will never equal to 1/2ulp). -// The rounding mode can be detected by checking whether -// huge + tiny is equal to huge, and whether huge - tiny is -// equal to huge for some floating point number "huge" and "tiny". -// -// -// Notes: Rounding mode detection omitted. The constants "mask", "shift", -// and "bias" are found in src/pkg/math/bits.go - -// Sqrt returns the square root of x. -// -// Special cases are: -// Sqrt(+Inf) = +Inf -// Sqrt(±0) = ±0 -// Sqrt(x < 0) = NaN -// Sqrt(NaN) = NaN -func sqrtGo(x float64) float64 { - // special cases - // TODO(rsc): Remove manual inlining of IsNaN, IsInf - // when compiler does it for us - switch { - case x == 0 || x != x || x > MaxFloat64: // x == 0 || IsNaN(x) || IsInf(x, 1): - return x - case x < 0: - return NaN() - } - ix := Float64bits(x) - // normalize x - exp := int((ix >> shift) & mask) - if exp == 0 { // subnormal x - for ix&1<<shift == 0 { - ix <<= 1 - exp-- - } - exp++ - } - exp -= bias // unbias exponent - ix &^= mask << shift - ix |= 1 << shift - if exp&1 == 1 { // odd exp, double x to make it even - ix <<= 1 - } - exp >>= 1 // exp = exp/2, exponent of square root - // generate sqrt(x) bit by bit - ix <<= 1 - var q, s uint64 // q = sqrt(x) - r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB - for r != 0 { - t := s + r - if t <= ix { - s = t + r - ix -= t - q += r - } - ix <<= 1 - r >>= 1 - } - // final rounding - if ix != 0 { // remainder, result not exact - q += q & 1 // round according to extra bit - } - ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent - return Float64frombits(ix) -} - -func sqrtGoC(f float64, r *float64) { - *r = sqrtGo(f) -} diff --git a/libgo/go/math/sqrt_test.go b/libgo/go/math/sqrt_test.go deleted file mode 100644 index 84cbc169e81..00000000000 --- a/libgo/go/math/sqrt_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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 sqrtGo available for testing. - -func SqrtGo(x float64) float64 { return sqrtGo(x) } diff --git a/libgo/go/math/tan.go b/libgo/go/math/tan.go index 76131fcd935..926bb4b227e 100644 --- a/libgo/go/math/tan.go +++ b/libgo/go/math/tan.go @@ -79,7 +79,12 @@ var _tanQ = [...]float64{ // Tan(±0) = ±0 // Tan(±Inf) = NaN // Tan(NaN) = NaN +func libc_tan(float64) float64 __asm__("tan") func Tan(x float64) float64 { + return libc_tan(x) +} + +func tan(x float64) float64 { const ( PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000, |