New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
math: Pow(negativeZero, number_that_overflows_int64) produces incorrect result on arm64 #57465
Comments
Does seem to break the documented special case:
|
cc @griesemer @rsc |
For non-constants conversion involve floating-point, the result value is implementation dependent (see previously #56023), so I think the result is reasonable because
|
I disagree. It explains why the result is different, however, nowhere in the specification does it say that Besides, it just makes sense from the math point of view. |
It is also very trivial to fix. |
The param is a float64, so you need to convert it to an int64 to check whether it's odd or even, no? |
Not necessarily. For example I can do a comparison with In any case, it's implementation details, the specification does not say how it's determined that |
If it does overflow, how could you claim it's an even integer? 1e19 and 1e19-1 are both overflow, your claim:
is not true. |
I can claim it because 1e19-1 has exactly the same float64 representation as 1e19 and the operand type (as you rightly mentioned earlier) is float64. |
I'm leaning towards fixing this, as the fix is simple. But it's kind of weird to use the terms "even" and "odd" for floats larger than 2^52, as the binary digit that matters is less than the precision that is represented. What's the last odd number? 2^53-1, maybe? |
…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 golang#57465
Change https://go.dev/cl/459815 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
https://go.dev/play/p/r5lmTzi5NYw
What did you expect to see?
0
What did you see instead?
-0
I did some digging, it turns out that isOddInt does a float64 to int64 conversion without checking for overflows. If an overflow occurs the behaviour is implementation-dependent and on amd64 it returns 0x80000000_00000000 (which is an even number), but on arm64 it returns '0x7fffffff_ffffffff which is an odd number.
I think for any values that overflow int64 the function should return
true
.The text was updated successfully, but these errors were encountered: