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
mpgetflt(Mpflt *a)
{
int s, i;
int s, i, e;
uvlong v, vm;
double f;
@ -200,12 +200,12 @@ mpgetflt(Mpflt *a)
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
// independently or in the 6g half of the compiler
// pick up the mantissa in a uvlong
s = 53;
// pick up the mantissa and a rounding bit in a uvlong
s = 53+1;
v = 0;
for(i=Mpnorm-1; s>=Mpscale; i--) {
v = (v<<Mpscale) | a->val.a[i];
@ -224,13 +224,26 @@ mpgetflt(Mpflt *a)
if(s > 0)
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);
// round toward even
if(v != (1ULL<<63) || (vm&1ULL) != 0)
vm += v>>63;
if(v != 0 || (vm&2ULL) != 0)
vm = (vm>>1) + (vm&1ULL);
else
vm >>= 1;
f = (double)(vm);
f = ldexp(f, Mpnorm*Mpscale + a->exp - 53);
f = ldexp(f, e);
if(a->val.neg)
f = -f;

View file

@ -121,9 +121,8 @@ var ftoatests = []ftoaTest{
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-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/
// {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
}
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")
}
}