summaryrefslogtreecommitdiff
path: root/src/cmd/gc/mparith3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/mparith3.c')
-rw-r--r--src/cmd/gc/mparith3.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
index 7b7e66668..b11a4f5f1 100644
--- a/src/cmd/gc/mparith3.c
+++ b/src/cmd/gc/mparith3.c
@@ -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;