-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Note
This issue was generated by GitHub Copilot CLI based on a review comment by @tannergooding on PR #125799.
Description
The explicit conversion operators from BigInteger to float, Half, and BFloat16 all convert via double as an intermediate step, which risks double rounding bugs:
public static explicit operator float(BigInteger value) => (float)((double)value);
public static explicit operator Half(BigInteger value) => (Half)(double)value;
public static explicit operator BFloat16(BigInteger value) => (BFloat16)(double)value;Problem
Converting BigInteger → double → float (or Half/BFloat16) performs two sequential rounding steps:
- Round the arbitrary-precision integer to
double(53-bit mantissa) - Round the
doubleto the target type (24-bit forfloat, 11-bit forHalf, 8-bit forBFloat16)
The composition of two correctly-rounded operations is not guaranteed to produce a correctly-rounded result. When the BigInteger value falls exactly at a double-rounding boundary, the intermediate double representation can cause the final result to be off by 1 ULP in the target type.
Expected Fix
Each of these conversions should handle the rounding directly from BigInteger to the target floating-point type, without an intermediate double step. This would ensure correctly-rounded results for all inputs.
Affected APIs
(float)(BigInteger)—BigInteger.csline 2120(Half)(BigInteger)—BigInteger.csline 1990(BFloat16)(BigInteger)—BigInteger.csline 1995