From: Robert Griesemer Date: Sat, 4 Apr 2015 00:50:37 +0000 (-0700) Subject: cmd/internal/gc: use approx. float formatting in error messages X-Git-Tag: go1.5beta1~1270 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=bb418a59f83f8dd19914522c58c1ba442dee522f;p=gostls13.git cmd/internal/gc: use approx. float formatting in error messages For very out-of-range floating-point constants (1e100000000), precise formatting of the offending value for error messages is not needed and potentially extremely slow. This change resurrects an adjusted variant of the original code which uses float64 formatting in the common case (in-range values), and a fast manual approximation for out-of-range values. Change-Id: I2f6e53040929b8bf924dac4bb27c4d811ede48e2 Reviewed-on: https://go-review.googlesource.com/8470 Reviewed-by: Alan Donovan --- diff --git a/src/cmd/internal/gc/mparith3.go b/src/cmd/internal/gc/mparith3.go index d1ae41dd74..88ab0e7413 100644 --- a/src/cmd/internal/gc/mparith3.go +++ b/src/cmd/internal/gc/mparith3.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/internal/gc/big" "cmd/internal/obj" "fmt" "math" @@ -184,8 +185,47 @@ func mpatoflt(a *Mpflt, as string) { } func Fconv(fvp *Mpflt, flag int) string { - if flag&obj.FmtSharp != 0 { - return fvp.Val.Format('g', 6) + if flag&obj.FmtSharp == 0 { + return fvp.Val.Format('b', 0) } - return fvp.Val.Format('b', 0) + + // use decimal format for error messages + + // determine sign + f := &fvp.Val + var sign string + if fvp.Val.Signbit() { + sign = "-" + f = new(big.Float).Abs(f) + } else if flag&obj.FmtSign != 0 { + sign = "+" + } + + // Use fmt formatting if in float64 range (common case). + if x, _ := f.Float64(); !math.IsInf(x, 0) { + return fmt.Sprintf("%s%.6g", sign, x) + } + + // Out of float64 range. Do approximate manual to decimal + // conversion to avoid precise but possibly slow Float + // formatting. The exponent is > 0 since a negative out- + // of-range exponent would have underflowed and led to 0. + // f = mant * 2**exp + var mant big.Float + exp := float64(f.MantExp(&mant)) // 0.5 <= mant < 1.0, exp > 0 + + // approximate float64 mantissa m and decimal exponent d + // f ~ m * 10**d + m, _ := mant.Float64() // 0.5 <= m < 1.0 + d := exp * (math.Ln2 / math.Ln10) // log_10(2) + + // adjust m for truncated (integer) decimal exponent e + e := int64(d) + m *= math.Pow(10, d-float64(e)) + for m >= 10 { + m /= 10 + e++ + } + + return fmt.Sprintf("%s%.5fe+%d", sign, m, e) }