diff options
Diffstat (limited to 'src/cmd/gc/mparith3.c')
-rw-r--r-- | src/cmd/gc/mparith3.c | 27 |
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; |