diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs
index b76e5a04f5ce11..2b6a79956453d6 100644
--- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs
@@ -285,7 +285,46 @@ public static explicit operator double(UInt128 value)
/// Explicitly converts a 128-bit unsigned integer to a value.
/// The value to convert.
/// converted to a .
- public static explicit operator Half(UInt128 value) => (Half)(double)(value);
+ public static explicit operator Half(UInt128 value)
+ {
+ return value._upper != 0 || value._lower >= 65520u
+ ? Half.PositiveInfinity
+ : BitConverter.Int16BitsToHalf((short)ToHalfPartial((uint)value._lower));
+
+ static int ToHalfPartial(uint value)
+ {
+ Debug.Assert(value <= 65519u);
+
+ const int exponentBias = Half.ExponentBias;
+ const int mantissaBits = Half.TrailingSignificandLength;
+
+ if (value == 0u)
+ {
+ return 0;
+ }
+
+ // Count leading zeros to find the position of the highest set bit
+ int leadingZeros = BitOperations.LeadingZeroCount(value);
+
+ int exponent = 32 - 1 + exponentBias - leadingZeros;
+
+ uint shifted = value << (1 + leadingZeros);
+
+ uint mantissa = shifted >>> (32 - mantissaBits);
+
+ // Remaining bits for rounding (bits 21-0)
+ uint remaining = shifted & 0x3FFFFFu;
+
+ // Apply rounding (round to nearest, ties to even)
+ if (remaining > 0x200000u || (remaining == 0x200000u && (mantissa & 1u) != 0u))
+ {
+ ++mantissa;
+ }
+
+ // Combine into half-precision format (sign bit is 0 for unsigned input)
+ return (exponent << mantissaBits) + (int)mantissa;
+ }
+ }
/// Explicitly converts a 128-bit unsigned integer to a value.
/// The value to convert.
@@ -402,7 +441,56 @@ public static explicit operator checked sbyte(UInt128 value)
/// Explicitly converts a 128-bit unsigned integer to a value.
/// The value to convert.
/// converted to a .
- public static explicit operator float(UInt128 value) => (float)(double)(value);
+ public static explicit operator float(UInt128 value)
+ {
+ return ToSingle(value._lower, value._upper);
+
+ static float ToSingle(ulong value_lo, ulong value_hi)
+ {
+ return value_hi == 0UL ? (float)value_lo : BitConverter.Int32BitsToSingle(ToSinglePartial(value_lo, value_hi));
+ }
+
+ static int ToSinglePartial(ulong value_lo, ulong value_hi)
+ {
+ Debug.Assert(value_hi != 0UL);
+
+ const int exponentBias = float.ExponentBias;
+ const int mantissaBitCount = float.TrailingSignificandLength;
+ const int nonMantissaBitCount = 32 - mantissaBitCount;
+ const int positiveInfinityBits = (int)float.PositiveInfinityBits;
+
+ if (value_hi >= 0xFFFFFF8000000000UL)
+ {
+ return positiveInfinityBits;
+ }
+
+ // Count leading zeros to find the position of the highest set bit
+ int shiftCount = 1 + BitOperations.LeadingZeroCount(value_hi);
+
+ int exponent = 128 + exponentBias - shiftCount;
+
+ ulong shifted = value_hi == 1UL ? value_lo : (value_lo >>> (64 - shiftCount)) | (value_hi << shiftCount);
+
+ int mantissa = (int)(shifted >> (32 + nonMantissaBitCount));
+
+ // Remaining bits for rounding (bits 40-0)
+ ulong remaining = shifted & 0x1FFFFFFFFFFUL;
+
+ if (value_hi != 1UL && (value_lo << shiftCount) != 0UL)
+ {
+ remaining |= 1UL;
+ }
+
+ // Apply rounding (round to nearest, ties to even)
+ if (remaining > 0x10000000000UL || (remaining == 0x10000000000UL && (mantissa & 1) != 0))
+ {
+ ++mantissa;
+ }
+
+ // Combine into single-precision format (sign bit is 0 for unsigned input)
+ return (exponent << mantissaBitCount) + mantissa;
+ }
+ }
/// Explicitly converts a 128-bit unsigned integer to a value.
/// The value to convert.