From 3663a437a781f4e7ce242aa334af2f2ce71ecef9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 25 Jan 2021 15:18:56 -0800 Subject: [PATCH] [dev.typeparams] go/constant: in ToFloat, convert to rational numbers, not floats Floating-point constants are represented as rational numbers when possible (i.e., when numerators and denominators are not too large). If we convert to floats when not necessary, we risk losing precision. This is the minimal fix for the specific issue, but it's too aggressive: If the numbers are too large, we still want to convert to floats. Will address in a separate CL that also does a few related cleanups. Fixes #43908. Change-Id: Id575e34fa18361a347c43701cfb4dd7221997f66 Reviewed-on: https://go-review.googlesource.com/c/go/+/286552 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/go/constant/value.go | 4 ++-- test/fixedbugs/issue43908.go | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue43908.go diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 223c363d9b9..2ed6115d1b7 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -871,9 +871,9 @@ func ToInt(x Value) Value { func ToFloat(x Value) Value { switch x := x.(type) { case int64Val: - return i64tof(x) + return i64tor(x) case intVal: - return itof(x) + return itor(x) case ratVal, floatVal: return x case complexVal: diff --git a/test/fixedbugs/issue43908.go b/test/fixedbugs/issue43908.go new file mode 100644 index 00000000000..47709eb191e --- /dev/null +++ b/test/fixedbugs/issue43908.go @@ -0,0 +1,21 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Verify exact constant evaluation independent of +// (mathematically equivalent) expression form. + +package main + +import "fmt" + +const ulp1 = imag(1i + 2i / 3 - 5i / 3) +const ulp2 = imag(1i + complex(0, 2) / 3 - 5i / 3) + +func main() { + if ulp1 != ulp2 { + panic(fmt.Sprintf("%g != %g\n", ulp1, ulp2)) + } +}