From 1be479df926fae2291e78f59be7474e6edb1cf97 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 21 May 2014 17:11:52 -0400 Subject: [PATCH] cmd/gc: fix floating point rounding again Passes the expanded test in CL 100660044, which gives me some confidence that it might be right. (The old code failed by not considering all the low bits.) LGTM=r R=golang-codereviews, r, bradfitz CC=golang-codereviews, iant, khr https://golang.org/cl/99410051 --- src/cmd/gc/mparith3.c | 46 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c index a109a0c420..95618f1c61 100644 --- a/src/cmd/gc/mparith3.c +++ b/src/cmd/gc/mparith3.c @@ -203,7 +203,7 @@ static double mpgetfltN(Mpflt *a, int prec, int bias) { int s, i, e, minexp; - uvlong v, vm; + uvlong v; double f; if(a->val.ovf && nsavederrors+nerrors == 0) @@ -226,25 +226,23 @@ mpgetfltN(Mpflt *a, int prec, int bias) return 0; } - // pick up the mantissa and a rounding bit in a uvlong - s = prec+1; + // pick up the mantissa, a rounding bit, and a tie-breaking bit in a uvlong + s = prec+2; v = 0; for(i=Mpnorm-1; s>=Mpscale; i--) { v = (v<val.a[i]; s -= Mpscale; } - vm = v; - if(s > 0) - vm = (vm<val.a[i]>>(Mpscale-s)); - - // continue with 64 more bits - s += 64; - for(; s>=Mpscale; i--) { - v = (v<val.a[i]; - s -= Mpscale; - } - if(s > 0) + if(s > 0) { v = (v<val.a[i]>>(Mpscale-s)); + if((a->val.a[i]&((1<<(Mpscale-s))-1)) != 0) + v |= 1; + i--; + } + for(; i >= 0; i--) { + if(a->val.a[i] != 0) + v |= 1; + } // gradual underflow e = Mpnorm*Mpscale + a->exp - prec; @@ -253,23 +251,23 @@ mpgetfltN(Mpflt *a, int prec, int bias) s = minexp - e; if(s > prec+1) s = prec+1; - v |= vm & ((1ULL<>= s; + if((v & ((1<>= s; e = minexp; } + + // round to even + v |= (v&4)>>2; + v += v&1; + v >>= 2; -//print("vm=%.16llux v=%.16llux\n", vm, v); - // round toward even - if(v != 0 || (vm&2ULL) != 0) - vm = (vm>>1) + (vm&1ULL); - else - vm >>= 1; - - f = (double)(vm); + f = (double)(v); f = ldexp(f, e); if(a->val.neg) f = -f; + return f; } -- 2.50.0