From 36a7e76f712cef7fa7926e6711fac0ba1875187e Mon Sep 17 00:00:00 2001
From: MichalPetryka <35800402+MichalPetryka@users.noreply.github.com>
Date: Wed, 9 Jun 2021 01:46:57 +0200
Subject: [PATCH] Add unsigned variants for BitConverter float bit APIs
(#53784)
* Add unsigned variants for BitConverter bit APIs
Adds DoubleToUInt64Bits, UInt64BitsToDouble, SingleToUInt32Bits,
UInt32BitsToSingle, HalfToUInt16Bits and UInt16BitsToHalf.
Implementations were based on existing signed integer variants.
Convert usages of existing APIs to unsigned variants when appropriate.
Fix #36469
* Revert comment change
Reverted a comment change made in the existing code by mistake.
* Use existing code for implementations
Use the existing signed methods with a cast, less code with the same codegen.
* Cast correction
Corrected the type used in a cast.
---
.../src/System/Variant.cs | 4 +-
.../tests/System/RealParserTestsBase.cs | 12 +-
.../src/System/BitConverter.cs | 54 ++
.../System.Private.CoreLib/src/System/Half.cs | 18 +-
.../System.Private.CoreLib/src/System/Math.cs | 4 +-
.../src/System/MathF.cs | 4 +-
.../src/System/Number.Formatting.cs | 6 +-
.../Number.NumberToFloatingPointBits.cs | 10 +-
.../src/System/Number.Parsing.cs | 4 +-
.../src/System/Xml/Xsl/XPathConvert.cs | 12 +-
.../tests/System/BitConverter.cs | 30 +
.../System.Runtime/ref/System.Runtime.cs | 12 +
.../tests/System/DoubleTests.cs | 17 +-
.../System.Runtime/tests/System/HalfTests.cs | 564 +++++++++---------
.../tests/System/SingleTests.cs | 17 +-
15 files changed, 422 insertions(+), 346 deletions(-)
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs
index 0ac65575793..8d2c5544407 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs
@@ -198,7 +198,7 @@ public Variant(float val)
{
_objref = null;
_flags = CV_R4;
- _data = (uint)BitConverter.SingleToInt32Bits(val);
+ _data = BitConverter.SingleToUInt32Bits(val);
}
public Variant(double val)
@@ -328,7 +328,7 @@ CVType switch
CV_U4 => (uint)_data,
CV_I8 => _data,
CV_U8 => (ulong)_data,
- CV_R4 => BitConverter.Int32BitsToSingle((int)_data),
+ CV_R4 => BitConverter.UInt32BitsToSingle((uint)_data),
CV_R8 => BitConverter.Int64BitsToDouble(_data),
CV_DATETIME => new DateTime(_data),
CV_TIMESPAN => new TimeSpan(_data),
diff --git a/src/libraries/Common/tests/System/RealParserTestsBase.cs b/src/libraries/Common/tests/System/RealParserTestsBase.cs
index 12ebf61f7cb..a42b9da9bf5 100644
--- a/src/libraries/Common/tests/System/RealParserTestsBase.cs
+++ b/src/libraries/Common/tests/System/RealParserTestsBase.cs
@@ -410,7 +410,7 @@ public void TestParserDouble_SpecificPowers(int b, int start, int end)
for (int i = start; i != end; i++)
{
double d = Math.Pow(b, i);
- ulong bits = (ulong)BitConverter.DoubleToInt64Bits(d);
+ ulong bits = BitConverter.DoubleToUInt64Bits(d);
TestRoundTripDouble(bits - 1);
TestRoundTripDouble(bits);
@@ -594,7 +594,7 @@ public void TestParserSingle_SpecificPowers(int b, int start, int end)
for (int i = start; i != end; ++i)
{
float f = MathF.Pow(b, i);
- uint bits = (uint)BitConverter.SingleToInt32Bits(f);
+ uint bits = BitConverter.SingleToUInt32Bits(f);
TestRoundTripSingle(bits - 1);
TestRoundTripSingle(bits);
@@ -604,7 +604,7 @@ public void TestParserSingle_SpecificPowers(int b, int start, int end)
private void CheckOneDouble(string s, ulong expectedBits)
{
- CheckOneDouble(s, BitConverter.Int64BitsToDouble((long)(expectedBits)));
+ CheckOneDouble(s, BitConverter.UInt64BitsToDouble(expectedBits));
}
private void CheckOneDouble(string s, double expected)
@@ -620,7 +620,7 @@ private void CheckOneDouble(string s, double expected)
private void CheckOneSingle(string s, uint expectedBits)
{
- CheckOneSingle(s, BitConverter.Int32BitsToSingle((int)(expectedBits)));
+ CheckOneSingle(s, BitConverter.UInt32BitsToSingle(expectedBits));
}
private void CheckOneSingle(string s, float expected)
@@ -642,7 +642,7 @@ private void TestRoundTripDouble(double d)
private void TestRoundTripDouble(ulong bits)
{
- double d = BitConverter.Int64BitsToDouble((long)(bits));
+ double d = BitConverter.UInt64BitsToDouble(bits);
if (double.IsFinite(d))
{
@@ -659,7 +659,7 @@ private void TestRoundTripSingle(float d)
private void TestRoundTripSingle(uint bits)
{
- float d = BitConverter.Int32BitsToSingle((int)(bits));
+ float d = BitConverter.UInt32BitsToSingle(bits);
if (float.IsFinite(d))
{
diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
index e063fa47fe6..5945c6252dc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs
@@ -857,5 +857,59 @@ public static unsafe Half Int16BitsToHalf(short value)
{
return *(Half*)&value;
}
+
+ ///
+ /// Converts the specified double-precision floating point number to a 64-bit unsigned integer.
+ ///
+ /// The number to convert.
+ /// A 64-bit unsigned integer whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe ulong DoubleToUInt64Bits(double value) => (ulong)DoubleToInt64Bits(value);
+
+ ///
+ /// Converts the specified 64-bit unsigned integer to a double-precision floating point number.
+ ///
+ /// The number to convert.
+ /// A double-precision floating point number whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe double UInt64BitsToDouble(ulong value) => Int64BitsToDouble((long)value);
+
+ ///
+ /// Converts the specified single-precision floating point number to a 32-bit unsigned integer.
+ ///
+ /// The number to convert.
+ /// A 32-bit unsigned integer whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe uint SingleToUInt32Bits(float value) => (uint)SingleToInt32Bits(value);
+
+ ///
+ /// Converts the specified 32-bit unsigned integer to a single-precision floating point number.
+ ///
+ /// The number to convert.
+ /// A single-precision floating point number whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe float UInt32BitsToSingle(uint value) => Int32BitsToSingle((int)value);
+
+ ///
+ /// Converts the specified half-precision floating point number to a 16-bit unsigned integer.
+ ///
+ /// The number to convert.
+ /// A 16-bit unsigned integer whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe ushort HalfToUInt16Bits(Half value) => (ushort)HalfToInt16Bits(value);
+
+ ///
+ /// Converts the specified 16-bit unsigned integer to a half-precision floating point number.
+ ///
+ /// The number to convert.
+ /// A half-precision floating point number whose bits are identical to .
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Half UInt16BitsToHalf(ushort value) => Int16BitsToHalf((short)value);
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs
index 63d81ec68af..c5c5b353581 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Half.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs
@@ -491,7 +491,7 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
{
const int SingleMaxExponent = 0xFF;
- uint floatInt = (uint)BitConverter.SingleToInt32Bits(value);
+ uint floatInt = BitConverter.SingleToUInt32Bits(value);
bool sign = (floatInt & float.SignMask) >> float.SignShift != 0;
int exp = (int)(floatInt & float.ExponentMask) >> float.ExponentShift;
uint sig = floatInt & float.SignificandMask;
@@ -519,7 +519,7 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
{
const int DoubleMaxExponent = 0x7FF;
- ulong doubleInt = (ulong)BitConverter.DoubleToInt64Bits(value);
+ ulong doubleInt = BitConverter.DoubleToUInt64Bits(value);
bool sign = (doubleInt & double.SignMask) >> double.SignShift != 0;
int exp = (int)((doubleInt & double.ExponentMask) >> double.ExponentShift);
ulong sig = doubleInt & double.SignificandMask;
@@ -561,7 +561,7 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
{
if (sig == 0)
{
- return BitConverter.Int32BitsToSingle((int)(sign ? float.SignMask : 0)); // Positive / Negative zero
+ return BitConverter.UInt32BitsToSingle(sign ? float.SignMask : 0); // Positive / Negative zero
}
(exp, sig) = NormSubnormalF16Sig(sig);
exp -= 1;
@@ -589,7 +589,7 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
{
if (sig == 0)
{
- return BitConverter.Int64BitsToDouble((long)(sign ? double.SignMask : 0)); // Positive / Negative zero
+ return BitConverter.UInt64BitsToDouble(sign ? double.SignMask : 0); // Positive / Negative zero
}
(exp, sig) = NormSubnormalF16Sig(sig);
exp -= 1;
@@ -621,7 +621,7 @@ private static Half CreateHalfNaN(bool sign, ulong significand)
uint signInt = (sign ? 1U : 0U) << SignShift;
uint sigInt = (uint)(significand >> 54);
- return BitConverter.Int16BitsToHalf((short)(signInt | NaNBits | sigInt));
+ return BitConverter.UInt16BitsToHalf((ushort)(signInt | NaNBits | sigInt));
}
private static ushort RoundPackToHalf(bool sign, short exp, ushort sig)
@@ -670,7 +670,7 @@ private static float CreateSingleNaN(bool sign, ulong significand)
uint signInt = (sign ? 1U : 0U) << float.SignShift;
uint sigInt = (uint)(significand >> 41);
- return BitConverter.Int32BitsToSingle((int)(signInt | NaNBits | sigInt));
+ return BitConverter.UInt32BitsToSingle(signInt | NaNBits | sigInt);
}
private static double CreateDoubleNaN(bool sign, ulong significand)
@@ -680,14 +680,14 @@ private static double CreateDoubleNaN(bool sign, ulong significand)
ulong signInt = (sign ? 1UL : 0UL) << double.SignShift;
ulong sigInt = significand >> 12;
- return BitConverter.Int64BitsToDouble((long)(signInt | NaNBits | sigInt));
+ return BitConverter.UInt64BitsToDouble(signInt | NaNBits | sigInt);
}
private static float CreateSingle(bool sign, byte exp, uint sig)
- => BitConverter.Int32BitsToSingle((int)(((sign ? 1U : 0U) << float.SignShift) + ((uint)exp << float.ExponentShift) + sig));
+ => BitConverter.UInt32BitsToSingle(((sign ? 1U : 0U) << float.SignShift) + ((uint)exp << float.ExponentShift) + sig);
private static double CreateDouble(bool sign, ushort exp, ulong sig)
- => BitConverter.Int64BitsToDouble((long)(((sign ? 1UL : 0UL) << double.SignShift) + ((ulong)exp << double.ExponentShift) + sig));
+ => BitConverter.UInt64BitsToDouble(((sign ? 1UL : 0UL) << double.SignShift) + ((ulong)exp << double.ExponentShift) + sig);
#endregion
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs
index c215d7a68ef..bb7fa0d4d3c 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Math.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs
@@ -1175,7 +1175,7 @@ public static double Round(double a)
// This is based on the 'Berkeley SoftFloat Release 3e' algorithm
- ulong bits = (ulong)BitConverter.DoubleToInt64Bits(a);
+ ulong bits = BitConverter.DoubleToUInt64Bits(a);
int exponent = double.ExtractExponentFromBits(bits);
if (exponent <= 0x03FE)
@@ -1231,7 +1231,7 @@ public static double Round(double a)
bits &= ~roundBitsMask;
}
- return BitConverter.Int64BitsToDouble((long)bits);
+ return BitConverter.UInt64BitsToDouble(bits);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs
index 0050f5d4336..9d1b75c8b16 100644
--- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs
@@ -325,7 +325,7 @@ public static float Round(float x)
// This is based on the 'Berkeley SoftFloat Release 3e' algorithm
- uint bits = (uint)BitConverter.SingleToInt32Bits(x);
+ uint bits = BitConverter.SingleToUInt32Bits(x);
int exponent = float.ExtractExponentFromBits(bits);
if (exponent <= 0x7E)
@@ -381,7 +381,7 @@ public static float Round(float x)
bits &= ~roundBitsMask;
}
- return BitConverter.Int32BitsToSingle((int)bits);
+ return BitConverter.UInt32BitsToSingle(bits);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
index be13d587923..408c83cb050 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
@@ -2629,7 +2629,7 @@ private static uint Int64DivMod1E9(ref ulong value)
private static ulong ExtractFractionAndBiasedExponent(double value, out int exponent)
{
- ulong bits = (ulong)(BitConverter.DoubleToInt64Bits(value));
+ ulong bits = BitConverter.DoubleToUInt64Bits(value);
ulong fraction = (bits & 0xFFFFFFFFFFFFF);
exponent = ((int)(bits >> 52) & 0x7FF);
@@ -2661,7 +2661,7 @@ private static ulong ExtractFractionAndBiasedExponent(double value, out int expo
private static ushort ExtractFractionAndBiasedExponent(Half value, out int exponent)
{
- ushort bits = (ushort)BitConverter.HalfToInt16Bits(value);
+ ushort bits = BitConverter.HalfToUInt16Bits(value);
ushort fraction = (ushort)(bits & 0x3FF);
exponent = ((int)(bits >> 10) & 0x1F);
@@ -2693,7 +2693,7 @@ private static ushort ExtractFractionAndBiasedExponent(Half value, out int expon
private static uint ExtractFractionAndBiasedExponent(float value, out int exponent)
{
- uint bits = (uint)(BitConverter.SingleToInt32Bits(value));
+ uint bits = BitConverter.SingleToUInt32Bits(value);
uint fraction = (bits & 0x7FFFFF);
exponent = ((int)(bits >> 23) & 0xFF);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
index 1c839aea90f..e6465da384e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
@@ -388,7 +388,7 @@ private static ulong NumberToDoubleFloatingPointBits(ref NumberBuffer number, in
result *= scale;
}
- return (ulong)(BitConverter.DoubleToInt64Bits(result));
+ return BitConverter.DoubleToUInt64Bits(result);
}
return NumberToFloatingPointBitsSlow(ref number, in info, positiveExponent, integerDigitsPresent, fractionalDigitsPresent);
@@ -450,7 +450,7 @@ private static ushort NumberToHalfFloatingPointBits(ref NumberBuffer number, in
result *= scale;
}
- return (ushort)(BitConverter.HalfToInt16Bits((Half)result));
+ return BitConverter.HalfToUInt16Bits((Half)result);
}
if ((totalDigits <= 15) && (fastExponent <= 22))
@@ -467,7 +467,7 @@ private static ushort NumberToHalfFloatingPointBits(ref NumberBuffer number, in
result *= scale;
}
- return (ushort)(BitConverter.HalfToInt16Bits((Half)(result)));
+ return BitConverter.HalfToUInt16Bits((Half)(result));
}
return (ushort)NumberToFloatingPointBitsSlow(ref number, in info, positiveExponent, integerDigitsPresent, fractionalDigitsPresent);
@@ -529,7 +529,7 @@ private static uint NumberToSingleFloatingPointBits(ref NumberBuffer number, in
result *= scale;
}
- return (uint)(BitConverter.SingleToInt32Bits(result));
+ return BitConverter.SingleToUInt32Bits(result);
}
if ((totalDigits <= 15) && (fastExponent <= 22))
@@ -546,7 +546,7 @@ private static uint NumberToSingleFloatingPointBits(ref NumberBuffer number, in
result *= scale;
}
- return (uint)(BitConverter.SingleToInt32Bits((float)(result)));
+ return BitConverter.SingleToUInt32Bits((float)(result));
}
return (uint)NumberToFloatingPointBitsSlow(ref number, in info, positiveExponent, integerDigitsPresent, fractionalDigitsPresent);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
index 382eb1ccf82..40e2fa9a76e 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
@@ -2143,7 +2143,7 @@ internal static double NumberToDouble(ref NumberBuffer number)
else
{
ulong bits = NumberToDoubleFloatingPointBits(ref number, in FloatingPointInfo.Double);
- result = BitConverter.Int64BitsToDouble((long)(bits));
+ result = BitConverter.UInt64BitsToDouble(bits);
}
return number.IsNegative ? -result : result;
@@ -2187,7 +2187,7 @@ internal static float NumberToSingle(ref NumberBuffer number)
else
{
uint bits = NumberToSingleFloatingPointBits(ref number, in FloatingPointInfo.Single);
- result = BitConverter.Int32BitsToSingle((int)(bits));
+ result = BitConverter.UInt32BitsToSingle(bits);
}
return number.IsNegative ? -result : result;
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
index ed6d5cc482e..c6de12ea8bb 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs
@@ -21,12 +21,12 @@ internal static class XPathConvert
{
public static uint DblHi(double dbl)
{
- return (uint)(BitConverter.DoubleToInt64Bits(dbl) >> 32);
+ return (uint)(BitConverter.DoubleToUInt64Bits(dbl) >> 32);
}
public static uint DblLo(double dbl)
{
- return unchecked((uint)BitConverter.DoubleToInt64Bits(dbl));
+ return unchecked((uint)BitConverter.DoubleToUInt64Bits(dbl));
}
// Returns true if value is infinite or NaN (exponent bits are all ones)
@@ -659,7 +659,7 @@ private void Mul(ref BigNumber numOp)
AddU(ref dblHi, 1);
}
}
- return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
+ return BitConverter.UInt64BitsToDouble((ulong)dblHi << 32 | dblLo);
}
// Lop off the integer part and return it.
@@ -1112,7 +1112,7 @@ public static void DblToRgbPrecise(double dbl, byte[] mantissa, out int exponent
dblHi = DblHi(dblT);
dblHi &= 0x000FFFFF;
dblHi |= 0x3FF00000;
- dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | DblLo(dblT));
+ dblT = BitConverter.UInt64BitsToDouble((ulong)dblHi << 32 | DblLo(dblT));
// Adjust wExp2 because we don't have the implicit bit.
wExp2++;
@@ -1123,7 +1123,7 @@ public static void DblToRgbPrecise(double dbl, byte[] mantissa, out int exponent
// First multiply by a power of 2 to get a normalized value.
dblHi &= 0x000FFFFF;
dblHi |= 0x3FF00000;
- dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
+ dblT = BitConverter.UInt64BitsToDouble((ulong)dblHi << 32 | dblLo);
// This is the power of 2.
w1 = wExp2 + 52;
@@ -2307,7 +2307,7 @@ public uint DivRem(BigInteger bi)
}
}
}
- return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
+ return BitConverter.UInt64BitsToDouble((ulong)dblHi << 32 | dblLo);
}
#endif
};
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.cs b/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.cs
index bfc9d6950fc..420de69f547 100644
--- a/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.cs
+++ b/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.cs
@@ -295,5 +295,35 @@ public static void HalfToInt16Bits()
Half roundtripped = BitConverter.Int16BitsToHalf(result);
Assert.Equal(input, roundtripped);
}
+
+ [Fact]
+ public static void DoubleToUInt64Bits()
+ {
+ double input = 123456.3234;
+ ulong result = BitConverter.DoubleToUInt64Bits(input);
+ Assert.Equal(4683220267154373240UL, result);
+ double roundtripped = BitConverter.UInt64BitsToDouble(result);
+ Assert.Equal(input, roundtripped);
+ }
+
+ [Fact]
+ public static void SingleToUInt32Bits()
+ {
+ float input = 12345.63f;
+ uint result = BitConverter.SingleToUInt32Bits(input);
+ Assert.Equal(1178658437U, result);
+ float roundtripped = BitConverter.UInt32BitsToSingle(result);
+ Assert.Equal(input, roundtripped);
+ }
+
+ [Fact]
+ public static void HalfToUInt16Bits()
+ {
+ Half input = (Half)12.34;
+ ushort result = BitConverter.HalfToUInt16Bits(input);
+ Assert.Equal((ushort)18988, result);
+ Half roundtripped = BitConverter.UInt16BitsToHalf(result);
+ Assert.Equal(input, roundtripped);
+ }
}
}
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index 6cf3d99701d..184d8f4c9b8 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -600,6 +600,18 @@ public static partial class BitConverter
public static float Int32BitsToSingle(int value) { throw null; }
public static double Int64BitsToDouble(long value) { throw null; }
public static int SingleToInt32Bits(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong DoubleToUInt64Bits(double value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static double UInt64BitsToDouble(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint SingleToUInt32Bits(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static float UInt32BitsToSingle(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort HalfToUInt16Bits(System.Half value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.Half UInt16BitsToHalf(ushort value) { throw null; }
public static bool ToBoolean(byte[] value, int startIndex) { throw null; }
public static bool ToBoolean(System.ReadOnlySpan value) { throw null; }
public static char ToChar(byte[] value, int startIndex) { throw null; }
diff --git a/src/libraries/System.Runtime/tests/System/DoubleTests.cs b/src/libraries/System.Runtime/tests/System/DoubleTests.cs
index 2a0ba4a217c..cfe3690e588 100644
--- a/src/libraries/System.Runtime/tests/System/DoubleTests.cs
+++ b/src/libraries/System.Runtime/tests/System/DoubleTests.cs
@@ -13,11 +13,6 @@ public class DoubleTests
{
// NOTE: Consider duplicating any tests added here in SingleTests.cs
- private static ulong DoubleToUInt64Bits(double value)
- {
- return (ulong)(BitConverter.DoubleToInt64Bits(value));
- }
-
[Theory]
[InlineData("a")]
[InlineData(234.0f)]
@@ -103,7 +98,7 @@ public static void Ctor_Value()
public static void Epsilon()
{
Assert.Equal(4.9406564584124654E-324, double.Epsilon);
- Assert.Equal(0x00000000_00000001u, DoubleToUInt64Bits(double.Epsilon));
+ Assert.Equal(0x00000000_00000001u, BitConverter.DoubleToUInt64Bits(double.Epsilon));
}
[Theory]
@@ -221,28 +216,28 @@ public static void IsPositiveInfinity(double d, bool expected)
public static void MaxValue()
{
Assert.Equal(1.7976931348623157E+308, double.MaxValue);
- Assert.Equal(0x7FEFFFFF_FFFFFFFFu, DoubleToUInt64Bits(double.MaxValue));
+ Assert.Equal(0x7FEFFFFF_FFFFFFFFu, BitConverter.DoubleToUInt64Bits(double.MaxValue));
}
[Fact]
public static void MinValue()
{
Assert.Equal(-1.7976931348623157E+308, double.MinValue);
- Assert.Equal(0xFFEFFFFF_FFFFFFFFu, DoubleToUInt64Bits(double.MinValue));
+ Assert.Equal(0xFFEFFFFF_FFFFFFFFu, BitConverter.DoubleToUInt64Bits(double.MinValue));
}
[Fact]
public static void NaN()
{
Assert.Equal(0.0 / 0.0, double.NaN);
- Assert.Equal(0xFFF80000_00000000u, DoubleToUInt64Bits(double.NaN));
+ Assert.Equal(0xFFF80000_00000000u, BitConverter.DoubleToUInt64Bits(double.NaN));
}
[Fact]
public static void NegativeInfinity()
{
Assert.Equal(-1.0 / 0.0, double.NegativeInfinity);
- Assert.Equal(0xFFF00000_00000000u, DoubleToUInt64Bits(double.NegativeInfinity));
+ Assert.Equal(0xFFF00000_00000000u, BitConverter.DoubleToUInt64Bits(double.NegativeInfinity));
}
public static IEnumerable