From: Russ Cox Date: Wed, 21 May 2014 21:11:52 +0000 (-0400) Subject: cmd/gc: fix floating point rounding again X-Git-Tag: go1.3rc1~59 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1be479df926fae2291e78f59be7474e6edb1cf97;p=gostls13.git 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 --- 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; }