]> Cypherpunks repositories - gostls13.git/commitdiff
math: increase precision of math.SmallestNonzeroFloat64
authorRobert Griesemer <gri@golang.org>
Thu, 29 Apr 2021 22:01:29 +0000 (15:01 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 30 Apr 2021 00:13:38 +0000 (00:13 +0000)
The original value was rounded too early, which lead to the
surprising behavior that float64(math.SmallestNonzeroFloat64 / 2)
wasn't 0. That is, the exact compile-time computation of
math.SmallestNonzeroFloat64 / 2 resulted in a value that was
rounded up when converting to float64. To address this, added 3
more digits to the mantissa, ending in a 0.

While at it, also slightly increased the precision of MaxFloat64
to end in a 0.

Computed exact values via https://play.golang.org/p/yt4KTpIx_wP.

Added a test to verify expected behavior.

In contrast to the other (irrational) constants, expanding these
extreme values to more digits is unlikely to be important as they
are not going to appear in numeric computations except for tests
verifying their correctness (as is the case here).

Re-enabled a disabled test in go/types and types2.

Updates #44057.
Fixes #44058.

Change-Id: I8f363155e02331354e929beabe993c8d8de75646
Reviewed-on: https://go-review.googlesource.com/c/go/+/315170
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
api/except.txt
src/cmd/compile/internal/types2/testdata/check/const1.src
src/go/types/testdata/check/const1.src
src/math/all_test.go
src/math/const.go

index 6f6f839ba604355c0841fac5d71e26d1937d5782..f5a7aa854e6387e5602f1adf7ae016df4f57e781 100644 (file)
@@ -1,4 +1,6 @@
 pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
+pkg math, const MaxFloat64 = 1.79769e+308  // 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+pkg math, const SmallestNonzeroFloat64 = 4.94066e-324  // 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 pkg math/big, const MaxBase = 36
 pkg math/big, type Word uintptr
 pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
index 56b6bd4ca55e75773e5cea3a96f88b788775ce05..c9128017cf72518f73adc4a535cc89f2418541db 100644 (file)
@@ -6,6 +6,8 @@
 
 package const1
 
+import "math"
+
 const(
        mi = ^int(0)
        mu = ^uint(0)
@@ -48,7 +50,7 @@ const (
        //           without overflow. For now we match the compiler.
        //           See also issue #44057.
        // smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
-       smallestFloat64 = 4.940656458412465441765687928682213723651e-324
+       smallestFloat64 = math.SmallestNonzeroFloat64
 )
 
 const (
@@ -63,7 +65,7 @@ const (
        //           without overflow. For now we match the compiler.
        //           See also issue #44057.
        // maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
-       maxFloat64 = 1.797693134862315708145274237317043567981e+308
+       maxFloat64 = math.MaxFloat64
 )
 
 const (
@@ -281,9 +283,7 @@ const (
        _ = assert(float64(smallestFloat32) == smallestFloat32)
        _ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
        _ = assert(float64(smallestFloat64) == smallestFloat64)
-       // TODO(gri) With the change to the declaration of smallestFloat64
-       //           this now fails to be true. See issue #44058.
-       // _ = assert(float64(smallestFloat64/2) == 0)
+       _ = assert(float64(smallestFloat64/2) == 0)
 )
 
 const (
index 56b6bd4ca55e75773e5cea3a96f88b788775ce05..c9128017cf72518f73adc4a535cc89f2418541db 100644 (file)
@@ -6,6 +6,8 @@
 
 package const1
 
+import "math"
+
 const(
        mi = ^int(0)
        mu = ^uint(0)
@@ -48,7 +50,7 @@ const (
        //           without overflow. For now we match the compiler.
        //           See also issue #44057.
        // smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
-       smallestFloat64 = 4.940656458412465441765687928682213723651e-324
+       smallestFloat64 = math.SmallestNonzeroFloat64
 )
 
 const (
@@ -63,7 +65,7 @@ const (
        //           without overflow. For now we match the compiler.
        //           See also issue #44057.
        // maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
-       maxFloat64 = 1.797693134862315708145274237317043567981e+308
+       maxFloat64 = math.MaxFloat64
 )
 
 const (
@@ -281,9 +283,7 @@ const (
        _ = assert(float64(smallestFloat32) == smallestFloat32)
        _ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
        _ = assert(float64(smallestFloat64) == smallestFloat64)
-       // TODO(gri) With the change to the declaration of smallestFloat64
-       //           this now fails to be true. See issue #44058.
-       // _ = assert(float64(smallestFloat64/2) == 0)
+       _ = assert(float64(smallestFloat64/2) == 0)
 )
 
 const (
index d154457999d18329e56f6c027c8ffcb5e9c137ed..55c805e199ed9cd200c3a5322e5a3b11ce917f9e 100644 (file)
@@ -3196,6 +3196,15 @@ func TestFloatMinMax(t *testing.T) {
        }
 }
 
+func TestFloatMinima(t *testing.T) {
+       if q := float32(SmallestNonzeroFloat32 / 2); q != 0 {
+               t.Errorf("float32(SmallestNonzeroFloat32 / 2) = %g, want 0", q)
+       }
+       if q := float64(SmallestNonzeroFloat64 / 2); q != 0 {
+               t.Errorf("float64(SmallestNonzeroFloat64 / 2) = %g, want 0", q)
+       }
+}
+
 var indirectSqrt = Sqrt
 
 // TestFloat32Sqrt checks the correctness of the float32 square root optimization result.
index 0fc8715dd07ce0e38c307956a99b20184ff01316..441b295ed4f653ac9a4a97d4545c5e2a95a9cac4 100644 (file)
@@ -31,8 +31,8 @@ const (
        MaxFloat32             = 3.40282346638528859811704183484516925440e+38  // 2**127 * (2**24 - 1) / 2**23
        SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
 
-       MaxFloat64             = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
-       SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
+       MaxFloat64             = 1.79769313486231570814527423731704356798070e+308   // 2**1023 * (2**53 - 1) / 2**52
+       SmallestNonzeroFloat64 = 4.9406564584124654417656879286822137236505980e-324 // 1 / 2**(1023 - 1 + 52)
 )
 
 // Integer limit values.