Skip to content

Inconsistent Double to UInt64 conversion on ARM vs x64 Architectures #94922

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

Closed
OceanOak opened this issue Nov 17, 2023 · 2 comments
Closed

Inconsistent Double to UInt64 conversion on ARM vs x64 Architectures #94922

OceanOak opened this issue Nov 17, 2023 · 2 comments

Comments

@OceanOak
Copy link

OceanOak commented Nov 17, 2023

Description

When converting the double value 1.8446744073709552E+19 to a uint64, the result of the conversion changes based on the architecture

Reproduction Steps

In dotnet fsi run
uint64(1.8446744073709552E+19);;

Expected behavior

The conversion of 1.8446744073709552E+19 to uint64 should be consistent across different architectures

Actual behavior

  • On ARM architecture: uint64(1.8446744073709552E+19) = 18446744073709551615.
  • On x64 architecture: uint64(1.8446744073709552E+19) = 0
@ghost ghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners untriaged New issue has not been triaged by the area owner labels Nov 17, 2023
@danmoseley danmoseley added area-System.Numerics and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Nov 17, 2023
@ghost
Copy link

ghost commented Nov 17, 2023

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

When converting the double value 1.8446744073709552E+19 to a uint64, the result of the conversion changes based on the architecture

Reproduction Steps

In dotnet fsi run
uint64(1.8446744073709552E+19);;

Expected behavior

The conversion of 1.8446744073709552E+19 to uint64 should be consistent across different architectures

Actual behavior

  • On ARM architecture: uint64(1.8446744073709552E+19) = 18446744073709551615.
  • On x64 architecture: uint64(1.8446744073709552E+19) = 0
Author: OceanOak
Assignees: -
Labels:

area-System.Numerics, untriaged

Milestone: -

@tannergooding
Copy link
Member

tannergooding commented Nov 17, 2023

This is a known difference as the exact semantics for floating-point values which cannot be represented in the destination format is considered undefined behavior (by IEEE 754, by the runtime, and by most languages).

Many platforms have standardized on saturation as the "correct" behavior as it best matches the IEEE 754 semantics required for other operations, which is to say results are computed as if to infinite precision and unbounded range; then rounded (using the current/targeted rounding mode) to the nearest representable result. -- The behavior of NaN handling is often still left undefined, but many platforms have defaulted to converting it to integer 0.

Adjusting .NET to have deterministic behavior here is tracked by #61885 and is being actively worked on. We plan on matching the saturating behavior that many platforms expect and converting NaN to integer 0. -- AVX10 (for x86/x64) will be adding new instructions that support this semantic behavior directly which can help mitigate the long term performance impact. AVX512 can use vfixupimmps to help handle some cases and there will be a slightly more complex required for downlevel hardware.

@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 17, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants