mirror of
https://github.com/golang/go
synced 2024-11-24 15:50:11 -07:00
math: handle int64 overflows when checking for odd integer exponents in Pow(-0, y)
The existing implementation does a float64 to int64 comversion in order to check whether the number is odd, however it does not check for overflows. If an overflow occurs, the result is implementation-defined and while it happens to work on amd64 and i386, it produces an incorrect result on arm64 and possibly other architectures. This change fixes that and also avoids calling isOddInt altogether if the base is +0, because it's unnecessary. (I was considering avoiding the extra check if runtime.GOARCH is "amd64" or "i386", but I can't see this pattern being used anywhere outside the tests. And having separate files with build tags just for isOddInt() seems like an overkill) Fixes #57465
This commit is contained in:
parent
e870de9936
commit
9a6d4584a8
@ -1687,6 +1687,9 @@ var vfpowSC = [][2]float64{
|
||||
{Nextafter(1, -2), float64(1 << 63)},
|
||||
{Nextafter(-1, 2), float64(1 << 63)},
|
||||
{Nextafter(-1, -2), float64(1 << 63)},
|
||||
|
||||
// Issue #57465, exponent is an even number that overflows int64
|
||||
{Copysign(0, -1), 1e19},
|
||||
}
|
||||
var powSC = []float64{
|
||||
0, // pow(-Inf, -Pi)
|
||||
@ -1762,6 +1765,9 @@ var powSC = []float64{
|
||||
0, // pow(Nextafter(1, -2), float64(1 << 63))
|
||||
0, // pow(Nextafter(-1, 2), float64(1 << 63))
|
||||
Inf(1), // pow(Nextafter(-1, -2), float64(1 << 63))
|
||||
|
||||
// Issue #57465, exponent is an even number that overflows int64
|
||||
0,
|
||||
}
|
||||
|
||||
var vfpow10SC = []int{
|
||||
|
@ -5,6 +5,10 @@
|
||||
package math
|
||||
|
||||
func isOddInt(x float64) bool {
|
||||
if Abs(x) >= (1 << 53) {
|
||||
return false
|
||||
}
|
||||
|
||||
xi, xf := Modf(x)
|
||||
return xf == 0 && int64(xi)&1 == 1
|
||||
}
|
||||
@ -54,12 +58,12 @@ func pow(x, y float64) float64 {
|
||||
case x == 0:
|
||||
switch {
|
||||
case y < 0:
|
||||
if isOddInt(y) {
|
||||
return Copysign(Inf(1), x)
|
||||
if Signbit(x) && isOddInt(y) {
|
||||
return Inf(-1)
|
||||
}
|
||||
return Inf(1)
|
||||
case y > 0:
|
||||
if isOddInt(y) {
|
||||
if Signbit(x) && isOddInt(y) {
|
||||
return x
|
||||
}
|
||||
return 0
|
||||
|
Loading…
Reference in New Issue
Block a user