Commit bb418a59 authored by Robert Griesemer's avatar Robert Griesemer

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/8470Reviewed-by: 's avatarAlan Donovan <adonovan@google.com>
parent b643684f
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package gc package gc
import ( import (
"cmd/internal/gc/big"
"cmd/internal/obj" "cmd/internal/obj"
"fmt" "fmt"
"math" "math"
...@@ -184,8 +185,47 @@ func mpatoflt(a *Mpflt, as string) { ...@@ -184,8 +185,47 @@ func mpatoflt(a *Mpflt, as string) {
} }
func Fconv(fvp *Mpflt, flag int) string { func Fconv(fvp *Mpflt, flag int) string {
if flag&obj.FmtSharp != 0 { if flag&obj.FmtSharp == 0 {
return fvp.Val.Format('g', 6) 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)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment