1
0
mirror of https://github.com/golang/go synced 2024-11-22 01:14:40 -07:00

gc: correct rounding of denormal constants

Fixes #1463.

R=rsc
CC=golang-dev
https://golang.org/cl/4079060
This commit is contained in:
Eoghan Sherry 2011-02-02 22:36:54 -05:00 committed by Russ Cox
parent fb9fc886ff
commit cf63e34b1d
3 changed files with 51 additions and 9 deletions

View File

@ -179,7 +179,7 @@ mpdivfltflt(Mpflt *a, Mpflt *b)
double double
mpgetflt(Mpflt *a) mpgetflt(Mpflt *a)
{ {
int s, i; int s, i, e;
uvlong v, vm; uvlong v, vm;
double f; double f;
@ -200,12 +200,12 @@ mpgetflt(Mpflt *a)
a->exp -= 1; a->exp -= 1;
} }
// the magic numbers (64, 63, 53, 10) are // the magic numbers (64, 63, 53, 10, -1074) are
// IEEE specific. this should be done machine // IEEE specific. this should be done machine
// independently or in the 6g half of the compiler // independently or in the 6g half of the compiler
// pick up the mantissa in a uvlong // pick up the mantissa and a rounding bit in a uvlong
s = 53; s = 53+1;
v = 0; v = 0;
for(i=Mpnorm-1; s>=Mpscale; i--) { for(i=Mpnorm-1; s>=Mpscale; i--) {
v = (v<<Mpscale) | a->val.a[i]; v = (v<<Mpscale) | a->val.a[i];
@ -224,13 +224,26 @@ mpgetflt(Mpflt *a)
if(s > 0) if(s > 0)
v = (v<<s) | (a->val.a[i]>>(Mpscale-s)); v = (v<<s) | (a->val.a[i]>>(Mpscale-s));
// gradual underflow
e = Mpnorm*Mpscale + a->exp - 53;
if(e < -1074) {
s = -e - 1074;
if(s > 54)
s = 54;
v |= vm & ((1ULL<<s) - 1);
vm >>= s;
e = -1074;
}
//print("vm=%.16llux v=%.16llux\n", vm, v); //print("vm=%.16llux v=%.16llux\n", vm, v);
// round toward even // round toward even
if(v != (1ULL<<63) || (vm&1ULL) != 0) if(v != 0 || (vm&2ULL) != 0)
vm += v>>63; vm = (vm>>1) + (vm&1ULL);
else
vm >>= 1;
f = (double)(vm); f = (double)(vm);
f = ldexp(f, Mpnorm*Mpscale + a->exp - 53); f = ldexp(f, e);
if(a->val.neg) if(a->val.neg)
f = -f; f = -f;

View File

@ -121,9 +121,8 @@ var ftoatests = []ftoaTest{
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
// TODO: uncomment after fixing issue 1463.
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
// {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
} }
func TestFtoa(t *testing.T) { func TestFtoa(t *testing.T) {

30
test/fixedbugs/bug321.go Normal file
View File

@ -0,0 +1,30 @@
// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug321
// 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.
// Troublesome floating point constants. Issue 1463.
package main
import "fmt"
func check(test string, got, want float64) bool {
if got != want {
fmt.Println(test, "got", got, "want", want)
return false
}
return true
}
func main() {
good := true
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
good = good && check("2.2250738585072012e-308", 2.2250738585072012e-308, 2.2250738585072014e-308)
// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
good = good && check("2.2250738585072011e-308", 2.2250738585072011e-308, 2.225073858507201e-308)
if !good {
panic("fail")
}
}