You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The result of converting from a floating-point type to an integral type when the floating-point value is not representable in the target integer type is currently considered "unspecified". The Roslyn compiler currently normalizes this to be 0 across all platforms and architectures for determinism purposes (dotnet/roslyn#37772).
For a conversion from float or double to an integral type, the processing depends on the overflow-checking context (§12.8.19) in which the conversion takes place:
In a checked context, the conversion proceeds as follows:
If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion.
Otherwise, a System.OverflowException is thrown.
In an unchecked context, the conversion always succeeds, and proceeds as follows.
If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion.
Otherwise, the result of the conversion is an unspecified value of the destination type.
If overflow occurs converting a floating-point type to an integer, or if the floating-point value being converted to an integer is a NaN, the value returned is unspecified.
and the IEEE 754 (otherwise known as ISO/IEC 60559) specification (noting that for the IEEE 754 specification, there is allowed disabling of floating-point exceptions, which is how the runtime operates):
When a NaN or infinite operand cannot be represented in the destination format and this cannot otherwise be indicated, the invalid operation exception shall be signaled. When a numeric operand would convert to an integer outside the range of the destination format, the invalid operation exception shall be signaled if this situation cannot otherwise be indicated.
Problem
While the behavior is left up to the implementation by all these specifications, this has lead to problems for users that are targeting different platforms (x64 vs Arm64) and is incompatible with some targets that require a more stringent behavior (WASM).
Accordingly, the runtime has made steps towards normalizing the behavior itself (#61885) and the behavior we landed on is not the same one Roslyn opted for. In particular, we do want NaN -> 0, but for overflow we want it to instead saturate (that is if the source is greater than the maximum value of the target type, it saturates to the maximum value of the target type; if it is less than the minimum, it saturates to the minimum. Thus float.MaxValue -> int.MaxValue, float.MinValue -> int.MinValue).
This decision was made based on the choices made by several other languages (such as Rust and Java), the behavior of more modern platforms (such as Arm64), and the required behavior for key platforms coming online (such as WASM).
Recommended Change
Accordingly, it would be beneficial if the Roslyn compiler could move towards the same behavior so that on .NET 9+ users will see the same results across all target CPU architectures regardless of whether the operation is constant folded by Roslyn, constant folded by the JIT/AOT, or evaluated at runtime.
This would simply entail that NaN -> 0 and overflow is done via saturation, as described above. If appropriate or helpful, the runtime can define a RuntimeFeature flag to help drive this behavior and indicate that the target is expected to saturate.
The text was updated successfully, but these errors were encountered:
Uh oh!
There was an error while loading. Please reload this page.
Current Behavior
The result of converting from a floating-point type to an integral type when the floating-point value is not representable in the target integer type is currently considered "unspecified". The Roslyn compiler currently normalizes this to be
0
across all platforms and architectures for determinism purposes (dotnet/roslyn#37772).References
This is as per the language spec (https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/conversions.md):
The runtime spec (ECMA-335) -- III.3.27 conv.:
and the IEEE 754 (otherwise known as ISO/IEC 60559) specification (noting that for the IEEE 754 specification, there is allowed disabling of floating-point exceptions, which is how the runtime operates):
Problem
While the behavior is left up to the implementation by all these specifications, this has lead to problems for users that are targeting different platforms (x64 vs Arm64) and is incompatible with some targets that require a more stringent behavior (WASM).
Accordingly, the runtime has made steps towards normalizing the behavior itself (#61885) and the behavior we landed on is not the same one Roslyn opted for. In particular, we do want
NaN -> 0
, but foroverflow
we want it to insteadsaturate
(that is if the source is greater than the maximum value of the target type, it saturates to the maximum value of the target type; if it is less than the minimum, it saturates to the minimum. Thusfloat.MaxValue -> int.MaxValue
,float.MinValue -> int.MinValue
).This decision was made based on the choices made by several other languages (such as Rust and Java), the behavior of more modern platforms (such as Arm64), and the required behavior for key platforms coming online (such as WASM).
Recommended Change
Accordingly, it would be beneficial if the Roslyn compiler could move towards the same behavior so that on .NET 9+ users will see the same results across all target CPU architectures regardless of whether the operation is constant folded by Roslyn, constant folded by the JIT/AOT, or evaluated at runtime.
This would simply entail that
NaN -> 0
and overflow is done via saturation, as described above. If appropriate or helpful, the runtime can define aRuntimeFeature
flag to help drive this behavior and indicate that the target is expected to saturate.The text was updated successfully, but these errors were encountered: