double
mpgetflt(Mpflt *a)
{
- int s, i;
+ int s, i, e;
uvlong v, vm;
double f;
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];
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;
// 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) {
--- /dev/null
+// $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")
+ }
+}