go.tools/go/types: fix float32 conversions

Pending CL 93550043.
For submission after the 1.3 release.

Fixes golang/go#8066.

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/95580045
This commit is contained in:
Robert Griesemer 2014-06-11 09:12:52 -07:00
parent 95e5e90454
commit 459aaad458
4 changed files with 28 additions and 13 deletions

View File

@ -245,6 +245,22 @@ func Uint64Val(x Value) (uint64, bool) {
panic(fmt.Sprintf("%v not an Int", x))
}
// Float32Val is like Float64Val but for float32 instead of float64.
func Float32Val(x Value) (float32, bool) {
switch x := x.(type) {
case int64Val:
f := float32(x)
return f, int64Val(f) == x
case intVal:
return new(big.Rat).SetFrac(x.val, int1).Float32()
case floatVal:
return x.val.Float32()
case unknownVal:
return 0, false
}
panic(fmt.Sprintf("%v not a Float", x))
}
// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
// to represent as float64, Float64Val silently underflows to 0. The result sign always

View File

@ -149,21 +149,14 @@ func isComparison(op token.Token) bool {
}
func fitsFloat32(x exact.Value) bool {
f, _ := exact.Float64Val(x)
// spec: "In all non-constant conversions involving floating-point
// or complex values, if the result type cannot represent the value
// the conversion succeeds but the result value is implementation-
// dependent."
//
// We assume that float32(f) returns an Inf if f is too large for
// a float32, or if f is an Inf; and that it returns 0 for values
// with too small a magnitude.
return !math.IsInf(float64(float32(f)), 0)
f32, _ := exact.Float32Val(x)
f := float64(f32)
return !math.IsInf(f, 0)
}
func roundFloat32(x exact.Value) exact.Value {
f, _ := exact.Float64Val(x)
f = float64(float32(f))
f32, _ := exact.Float32Val(x)
f := float64(f32)
if !math.IsInf(f, 0) {
return exact.MakeFloat64(f)
}

View File

@ -119,7 +119,6 @@ func TestStdTest(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
"sigchld.go", // don't work on Windows; testTestDir should consult build tags
"float_lit2.go", // TODO(gri) float32 constant conversion requires (missing) Rat.Float32
)
}

View File

@ -14,3 +14,10 @@ func issue7035() {
fmt := new(T)
_ = fmt.X
}
func issue8066() {
const (
_ = float32(340282356779733661637539395458142568447)
_ = float32(340282356779733661637539395458142568448 /* ERROR cannot convert */ )
)
}