diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 854cd9d58e3eac..c665b746232878 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -574,6 +574,8 @@ namespace System.Buffers.Binary { public static partial class BinaryPrimitives { + public static System.Numerics.BFloat16 ReadBFloat16BigEndian(System.ReadOnlySpan source) { throw null; } + public static System.Numerics.BFloat16 ReadBFloat16LittleEndian(System.ReadOnlySpan source) { throw null; } public static double ReadDoubleBigEndian(System.ReadOnlySpan source) { throw null; } public static double ReadDoubleLittleEndian(System.ReadOnlySpan source) { throw null; } public static System.Half ReadHalfBigEndian(System.ReadOnlySpan source) { throw null; } @@ -643,6 +645,8 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System public static void ReverseEndianness(System.ReadOnlySpan source, System.Span destination) { } [System.CLSCompliant(false)] public static void ReverseEndianness(System.ReadOnlySpan source, System.Span destination) { } + public static bool TryReadBFloat16BigEndian(System.ReadOnlySpan source, out System.Numerics.BFloat16 value) { throw null; } + public static bool TryReadBFloat16LittleEndian(System.ReadOnlySpan source, out System.Numerics.BFloat16 value) { throw null; } public static bool TryReadDoubleBigEndian(System.ReadOnlySpan source, out double value) { throw null; } public static bool TryReadDoubleLittleEndian(System.ReadOnlySpan source, out double value) { throw null; } public static bool TryReadHalfBigEndian(System.ReadOnlySpan source, out System.Half value) { throw null; } @@ -679,6 +683,8 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryReadUIntPtrBigEndian(System.ReadOnlySpan source, out nuint value) { throw null; } [System.CLSCompliantAttribute(false)] public static bool TryReadUIntPtrLittleEndian(System.ReadOnlySpan source, out nuint value) { throw null; } + public static bool TryWriteBFloat16BigEndian(System.Span destination, System.Numerics.BFloat16 value) { throw null; } + public static bool TryWriteBFloat16LittleEndian(System.Span destination, System.Numerics.BFloat16 value) { throw null; } public static bool TryWriteDoubleBigEndian(System.Span destination, double value) { throw null; } public static bool TryWriteDoubleLittleEndian(System.Span destination, double value) { throw null; } public static bool TryWriteHalfBigEndian(System.Span destination, System.Half value) { throw null; } @@ -715,6 +721,8 @@ public static void ReverseEndianness(System.ReadOnlySpan source, System. public static bool TryWriteUIntPtrBigEndian(System.Span destination, nuint value) { throw null; } [System.CLSCompliantAttribute(false)] public static bool TryWriteUIntPtrLittleEndian(System.Span destination, nuint value) { throw null; } + public static void WriteBFloat16BigEndian(System.Span destination, System.Numerics.BFloat16 value) { } + public static void WriteBFloat16LittleEndian(System.Span destination, System.Numerics.BFloat16 value) { } public static void WriteDoubleBigEndian(System.Span destination, double value) { } public static void WriteDoubleLittleEndian(System.Span destination, double value) { } public static void WriteHalfBigEndian(System.Span destination, System.Half value) { } diff --git a/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs b/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs index 8f3f01c7105d62..bd5a13fb84c55d 100644 --- a/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs +++ b/src/libraries/System.Memory/tests/Binary/BinaryReaderUnitTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Xunit; @@ -140,6 +141,16 @@ public void SpanRead() Assert.True(TryReadInt128LittleEndian(span, out int128Value)); Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), int128Value); + BFloat16 expectedBFloat16 = BitConverter.Int16BitsToBFloat16(0x1122); + Assert.Equal(expectedBFloat16, ReadBFloat16BigEndian(span)); + Assert.True(TryReadBFloat16BigEndian(span, out BFloat16 bFloat16Value)); + Assert.Equal(expectedBFloat16, bFloat16Value); + + expectedBFloat16 = BitConverter.Int16BitsToBFloat16(0x2211); + Assert.Equal(expectedBFloat16, ReadBFloat16LittleEndian(span)); + Assert.True(TryReadBFloat16LittleEndian(span, out bFloat16Value)); + Assert.Equal(expectedBFloat16, bFloat16Value); + Half expectedHalf = BitConverter.Int16BitsToHalf(0x1122); Assert.Equal(expectedHalf, ReadHalfBigEndian(span)); Assert.True(TryReadHalfBigEndian(span, out Half halfValue)); @@ -300,6 +311,16 @@ public void ReadOnlySpanRead() Assert.True(TryReadInt128LittleEndian(span, out int128Value)); Assert.Equal(new Int128(0x00FFEEDDCCBBAA99, 0x8877665544332211), int128Value); + BFloat16 expectedBFloat16 = BitConverter.Int16BitsToBFloat16(0x1122); + Assert.Equal(expectedBFloat16, ReadBFloat16BigEndian(span)); + Assert.True(TryReadBFloat16BigEndian(span, out BFloat16 bFloat16Value)); + Assert.Equal(expectedBFloat16, bFloat16Value); + + expectedBFloat16 = BitConverter.Int16BitsToBFloat16(0x2211); + Assert.Equal(expectedBFloat16, ReadBFloat16LittleEndian(span)); + Assert.True(TryReadBFloat16LittleEndian(span, out bFloat16Value)); + Assert.Equal(expectedBFloat16, bFloat16Value); + Half expectedHalf = BitConverter.Int16BitsToHalf(0x1122); Assert.Equal(expectedHalf, ReadHalfBigEndian(span)); Assert.True(TryReadHalfBigEndian(span, out Half halfValue)); @@ -362,6 +383,8 @@ public void SpanReadFail() TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out UInt128 uint128Value)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out BFloat16 bFloat16Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out Half halfValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); @@ -405,6 +428,8 @@ public void ReadOnlySpanReadFail() TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out UInt128 uint128Value)); + TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); + Assert.False(MemoryMarshal.TryRead(span, out BFloat16 bFloat16Value)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); Assert.False(MemoryMarshal.TryRead(span, out Half halfValue)); TestHelpers.AssertThrows(span, (_span) => MemoryMarshal.Read(_span)); @@ -444,20 +469,22 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() WriteInt128BigEndian(spanBE.Slice(100), s_testStruct.I128_1); WriteUInt128BigEndian(spanBE.Slice(116), s_testStruct.U128_0); WriteUInt128BigEndian(spanBE.Slice(132), s_testStruct.U128_1); + WriteBFloat16BigEndian(spanBE.Slice(148), s_testStruct.BF16_0); + WriteBFloat16BigEndian(spanBE.Slice(150), s_testStruct.BF16_1); if (Environment.Is64BitProcess) { - WriteIntPtrBigEndian(spanBE.Slice(148), s_testStruct.N0); - WriteIntPtrBigEndian(spanBE.Slice(156), s_testStruct.N1); - WriteUIntPtrBigEndian(spanBE.Slice(164), s_testStruct.UN0); - WriteUIntPtrBigEndian(spanBE.Slice(172), s_testStruct.UN1); + WriteIntPtrBigEndian(spanBE.Slice(152), s_testStruct.N0); + WriteIntPtrBigEndian(spanBE.Slice(160), s_testStruct.N1); + WriteUIntPtrBigEndian(spanBE.Slice(168), s_testStruct.UN0); + WriteUIntPtrBigEndian(spanBE.Slice(176), s_testStruct.UN1); } else { - WriteIntPtrBigEndian(spanBE.Slice(148), s_testStruct.N0); - WriteIntPtrBigEndian(spanBE.Slice(152), s_testStruct.N1); - WriteUIntPtrBigEndian(spanBE.Slice(156), s_testStruct.UN0); - WriteUIntPtrBigEndian(spanBE.Slice(160), s_testStruct.UN1); + WriteIntPtrBigEndian(spanBE.Slice(152), s_testStruct.N0); + WriteIntPtrBigEndian(spanBE.Slice(156), s_testStruct.N1); + WriteUIntPtrBigEndian(spanBE.Slice(160), s_testStruct.UN0); + WriteUIntPtrBigEndian(spanBE.Slice(164), s_testStruct.UN1); } ReadOnlySpan readOnlySpanBE = new ReadOnlySpan(spanBE.ToArray()); @@ -486,21 +513,23 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() I128_1 = ReadInt128BigEndian(spanBE.Slice(100)), U128_0 = ReadUInt128BigEndian(spanBE.Slice(116)), U128_1 = ReadUInt128BigEndian(spanBE.Slice(132)), + BF16_0 = ReadBFloat16BigEndian(spanBE.Slice(148)), + BF16_1 = ReadBFloat16BigEndian(spanBE.Slice(150)), }; if (Environment.Is64BitProcess) { - readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(148)); - readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(156)); - readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(164)); - readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(172)); + readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(152)); + readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(160)); + readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(168)); + readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(176)); } else { - readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(148)); - readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(152)); - readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(156)); - readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(160)); + readStruct.N0 = ReadIntPtrBigEndian(spanBE.Slice(152)); + readStruct.N1 = ReadIntPtrBigEndian(spanBE.Slice(156)); + readStruct.UN0 = ReadUIntPtrBigEndian(spanBE.Slice(160)); + readStruct.UN1 = ReadUIntPtrBigEndian(spanBE.Slice(164)); } var readStructFromReadOnlySpan = new TestStruct @@ -527,21 +556,23 @@ public void SpanWriteAndReadBigEndianHeterogeneousStruct() I128_1 = ReadInt128BigEndian(readOnlySpanBE.Slice(100)), U128_0 = ReadUInt128BigEndian(readOnlySpanBE.Slice(116)), U128_1 = ReadUInt128BigEndian(readOnlySpanBE.Slice(132)), + BF16_0 = ReadBFloat16BigEndian(readOnlySpanBE.Slice(148)), + BF16_1 = ReadBFloat16BigEndian(readOnlySpanBE.Slice(150)), }; if (Environment.Is64BitProcess) { - readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(148)); - readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(156)); - readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(164)); - readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(172)); + readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(152)); + readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(160)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(168)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(176)); } else { - readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(148)); - readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(152)); - readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(156)); - readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(160)); + readStructFromReadOnlySpan.N0 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(152)); + readStructFromReadOnlySpan.N1 = ReadIntPtrBigEndian(readOnlySpanBE.Slice(156)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(160)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrBigEndian(readOnlySpanBE.Slice(164)); } Assert.Equal(s_testStruct, readStruct); @@ -575,20 +606,22 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() WriteInt128LittleEndian(spanLE.Slice(100), s_testStruct.I128_1); WriteUInt128LittleEndian(spanLE.Slice(116), s_testStruct.U128_0); WriteUInt128LittleEndian(spanLE.Slice(132), s_testStruct.U128_1); + WriteBFloat16LittleEndian(spanLE.Slice(148), s_testStruct.BF16_0); + WriteBFloat16LittleEndian(spanLE.Slice(150), s_testStruct.BF16_1); if (Environment.Is64BitProcess) { - WriteIntPtrLittleEndian(spanLE.Slice(148), s_testStruct.N0); - WriteIntPtrLittleEndian(spanLE.Slice(156), s_testStruct.N1); - WriteUIntPtrLittleEndian(spanLE.Slice(164), s_testStruct.UN0); - WriteUIntPtrLittleEndian(spanLE.Slice(172), s_testStruct.UN1); + WriteIntPtrLittleEndian(spanLE.Slice(152), s_testStruct.N0); + WriteIntPtrLittleEndian(spanLE.Slice(160), s_testStruct.N1); + WriteUIntPtrLittleEndian(spanLE.Slice(168), s_testStruct.UN0); + WriteUIntPtrLittleEndian(spanLE.Slice(176), s_testStruct.UN1); } else { - WriteIntPtrLittleEndian(spanLE.Slice(148), s_testStruct.N0); - WriteIntPtrLittleEndian(spanLE.Slice(152), s_testStruct.N1); - WriteUIntPtrLittleEndian(spanLE.Slice(156), s_testStruct.UN0); - WriteUIntPtrLittleEndian(spanLE.Slice(160), s_testStruct.UN1); + WriteIntPtrLittleEndian(spanLE.Slice(152), s_testStruct.N0); + WriteIntPtrLittleEndian(spanLE.Slice(156), s_testStruct.N1); + WriteUIntPtrLittleEndian(spanLE.Slice(160), s_testStruct.UN0); + WriteUIntPtrLittleEndian(spanLE.Slice(164), s_testStruct.UN1); } ReadOnlySpan readOnlySpanLE = new ReadOnlySpan(spanLE.ToArray()); @@ -617,21 +650,23 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() I128_1 = ReadInt128LittleEndian(spanLE.Slice(100)), U128_0 = ReadUInt128LittleEndian(spanLE.Slice(116)), U128_1 = ReadUInt128LittleEndian(spanLE.Slice(132)), + BF16_0 = ReadBFloat16LittleEndian(spanLE.Slice(148)), + BF16_1 = ReadBFloat16LittleEndian(spanLE.Slice(150)), }; if (Environment.Is64BitProcess) { - readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(148)); - readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(156)); - readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(164)); - readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(172)); + readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(152)); + readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(160)); + readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(168)); + readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(176)); } else { - readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(148)); - readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(152)); - readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(156)); - readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(160)); + readStruct.N0 = ReadIntPtrLittleEndian(spanLE.Slice(152)); + readStruct.N1 = ReadIntPtrLittleEndian(spanLE.Slice(156)); + readStruct.UN0 = ReadUIntPtrLittleEndian(spanLE.Slice(160)); + readStruct.UN1 = ReadUIntPtrLittleEndian(spanLE.Slice(164)); } var readStructFromReadOnlySpan = new TestStruct @@ -658,21 +693,23 @@ public void SpanWriteAndReadLittleEndianHeterogeneousStruct() I128_1 = ReadInt128LittleEndian(readOnlySpanLE.Slice(100)), U128_0 = ReadUInt128LittleEndian(readOnlySpanLE.Slice(116)), U128_1 = ReadUInt128LittleEndian(readOnlySpanLE.Slice(132)), + BF16_0 = ReadBFloat16LittleEndian(readOnlySpanLE.Slice(148)), + BF16_1 = ReadBFloat16LittleEndian(readOnlySpanLE.Slice(150)), }; if (Environment.Is64BitProcess) { - readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(148)); - readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(156)); - readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(164)); - readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(172)); + readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(152)); + readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(160)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(168)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(176)); } else { - readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(148)); - readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(152)); - readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(156)); - readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(160)); + readStructFromReadOnlySpan.N0 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(152)); + readStructFromReadOnlySpan.N1 = ReadIntPtrLittleEndian(readOnlySpanLE.Slice(156)); + readStructFromReadOnlySpan.UN0 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(160)); + readStructFromReadOnlySpan.UN1 = ReadUIntPtrLittleEndian(readOnlySpanLE.Slice(164)); } Assert.Equal(s_testStruct, readStruct); @@ -814,6 +851,8 @@ public void ReadingStructFieldByFieldOrReadAndReverseEndianness() I128_1 = Int128.MinValue, U128_1 = UInt128.MinValue, U128_0 = UIntPtr.MaxValue, + BF16_0 = BFloat16.MaxValue, + BF16_1 = BFloat16.MinValue, N0 = nint.MaxValue, N1 = nint.MinValue, UN1 = nuint.MinValue, @@ -845,6 +884,8 @@ private struct TestStruct public Int128 I128_1; public UInt128 U128_1; public UInt128 U128_0; + public BFloat16 BF16_0; + public BFloat16 BF16_1; public nint N0; public nint N1; public nuint UN1; diff --git a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs index 5c776c4fdcb4af..9a79d97beece67 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BitConverter.cs @@ -308,6 +308,34 @@ public static bool TryWriteBytes(Span destination, UInt128 value) return true; } + /// + /// Returns the specified value as an array of bytes. + /// + /// The number to convert. + /// An array of bytes with length 2. + public static unsafe byte[] GetBytes(BFloat16 value) + { + byte[] bytes = new byte[sizeof(BFloat16)]; + bool success = TryWriteBytes(bytes, value); + Debug.Assert(success); + return bytes; + } + + /// + /// Converts a value into a span of bytes. + /// + /// When this method returns, the bytes representing the converted value. + /// The value to convert. + /// if the conversion was successful; otherwise. + public static unsafe bool TryWriteBytes(Span destination, BFloat16 value) + { + if (destination.Length < sizeof(BFloat16)) + return false; + + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value); + return true; + } + /// /// Returns the specified half-precision floating point value as an array of bytes. /// @@ -693,6 +721,31 @@ public static UInt128 ToUInt128(ReadOnlySpan value) return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(value)); } + /// + /// Returns a number converted from two bytes at a specified position in a byte array. + /// + /// An array of bytes. + /// The starting position within . + /// A number signed integer formed by two bytes beginning at . + /// equals the length of minus 1. + /// is null. + /// is less than zero or greater than the length of minus 1. + public static BFloat16 ToBFloat16(byte[] value, int startIndex) => Int16BitsToBFloat16(ToInt16(value, startIndex)); + + /// + /// Converts a read-only byte span into a value. + /// + /// A read-only span containing the bytes to convert. + /// A value representing the converted bytes. + /// The length of is less than 2. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe BFloat16 ToBFloat16(ReadOnlySpan value) + { + if (value.Length < sizeof(BFloat16)) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value); + return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(value)); + } + /// /// Returns a half-precision floating point number converted from two bytes at a specified position in a byte array. /// @@ -948,9 +1001,21 @@ public static bool ToBoolean(ReadOnlySpan value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Half Int16BitsToHalf(short value) => new Half((ushort)(value)); - internal static short BFloat16BitsToInt16(BFloat16 value) => (short)value._value; + /// + /// Converts the specified number to a 16-bit signed integer. + /// + /// The number to convert. + /// A 16-bit signed integer whose bits are identical to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static short BFloat16ToInt16Bits(BFloat16 value) => (short)value._value; - internal static BFloat16 Int16BitsToBFloat16(short value) => new BFloat16((ushort)(value)); + /// + /// Converts the specified 16-bit signed integer to a number. + /// + /// The number to convert. + /// A number whose bits are identical to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BFloat16 Int16BitsToBFloat16(short value) => new BFloat16((ushort)(value)); /// /// Converts the specified double-precision floating point number to a 64-bit unsigned integer. @@ -1006,8 +1071,22 @@ public static bool ToBoolean(ReadOnlySpan value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Half UInt16BitsToHalf(ushort value) => new Half(value); - internal static ushort BFloat16BitsToUInt16(BFloat16 value) => value._value; + /// + /// Converts the specified 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 ushort BFloat16ToUInt16Bits(BFloat16 value) => value._value; - internal static BFloat16 UInt16BitsToBFloat16(ushort value) => new BFloat16(value); + /// + /// Converts the specified 16-bit unsigned integer to a number. + /// + /// The number to convert. + /// A number whose bits are identical to . + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BFloat16 UInt16BitsToBFloat16(ushort value) => new BFloat16(value); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs index 4065daf8621500..0fab95d6978332 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadBigEndian.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -42,6 +43,23 @@ public static Half ReadHalfBigEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// The read-only span to read. + /// The big endian value. + /// Reads exactly 2 bytes from the beginning of the span. + /// + /// is too small to contain a . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BFloat16 ReadBFloat16BigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + BitConverter.Int16BitsToBFloat16(ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as big endian. /// @@ -278,6 +296,28 @@ public static bool TryReadHalfBigEndian(ReadOnlySpan source, out Half valu return MemoryMarshal.TryRead(source, out value); } + /// + /// Reads a from the beginning of a read-only span of bytes, as big endian. + /// + /// The read-only span of bytes to read. + /// When this method returns, contains the value read out of the read-only span of bytes, as big endian. + /// + /// if the span is large enough to contain a ; otherwise, . + /// + /// Reads exactly 2 bytes from the beginning of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadBFloat16BigEndian(ReadOnlySpan source, out BFloat16 value) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out short tmp); + value = BitConverter.Int16BitsToBFloat16(ReverseEndianness(tmp)); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + /// /// Reads a from the beginning of a read-only span of bytes, as big endian. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs index c21624da2aafc8..8f5304adf6f742 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.ReadLittleEndian.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -42,6 +43,23 @@ public static Half ReadHalfLittleEndian(ReadOnlySpan source) MemoryMarshal.Read(source); } + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// The read-only span to read. + /// The little endian value. + /// Reads exactly 2 bytes from the beginning of the span. + /// + /// is too small to contain a . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BFloat16 ReadBFloat16LittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + BitConverter.Int16BitsToBFloat16(ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + /// /// Reads a from the beginning of a read-only span of bytes, as little endian. /// @@ -278,6 +296,28 @@ public static bool TryReadHalfLittleEndian(ReadOnlySpan source, out Half v return MemoryMarshal.TryRead(source, out value); } + /// + /// Reads a from the beginning of a read-only span of bytes, as little endian. + /// + /// The read-only span of bytes to read. + /// When this method returns, contains the value read out of the read-only span of bytes, as little endian. + /// + /// if the span is large enough to contain a ; otherwise, . + /// + /// Reads exactly 2 bytes from the beginning of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryReadBFloat16LittleEndian(ReadOnlySpan source, out BFloat16 value) + { + if (!BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out short tmp); + value = BitConverter.Int16BitsToBFloat16(ReverseEndianness(tmp)); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + /// /// Reads a from the beginning of a read-only span of bytes, as little endian. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs index 159ade3dbdf6f7..87db2165b46441 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteBigEndian.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -54,6 +55,29 @@ public static void WriteHalfBigEndian(Span destination, Half value) } } + /// + /// Writes a into a span of bytes, as big endian. + /// + /// The span of bytes where the value is to be written, as big endian. + /// The value to write into the span of bytes. + /// Writes exactly 2 bytes to the beginning of the span. + /// + /// is too small to contain a . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteBFloat16BigEndian(Span destination, BFloat16 value) + { + if (BitConverter.IsLittleEndian) + { + short tmp = ReverseEndianness(BitConverter.BFloat16ToInt16Bits(value)); + MemoryMarshal.Write(destination, in tmp); + } + else + { + MemoryMarshal.Write(destination, in value); + } + } + /// /// Writes a into a span of bytes, as big endian. /// @@ -354,6 +378,27 @@ public static bool TryWriteHalfBigEndian(Span destination, Half value) return MemoryMarshal.TryWrite(destination, in value); } + /// + /// Writes a into a span of bytes, as big endian. + /// + /// The span of bytes where the value is to be written, as big endian. + /// The value to write into the span of bytes. + /// + /// if the span is large enough to contain a ; otherwise, . + /// + /// Writes exactly 2 bytes to the beginning of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteBFloat16BigEndian(Span destination, BFloat16 value) + { + if (BitConverter.IsLittleEndian) + { + short tmp = ReverseEndianness(BitConverter.BFloat16ToInt16Bits(value)); + return MemoryMarshal.TryWrite(destination, in tmp); + } + + return MemoryMarshal.TryWrite(destination, in value); + } + /// /// Writes a into a span of bytes, as big endian. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs index 5da64da58368a5..9e035cd7fc17a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Binary/BinaryPrimitives.WriteLittleEndian.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -54,6 +55,29 @@ public static void WriteHalfLittleEndian(Span destination, Half value) } } + /// + /// Writes a into a span of bytes, as little endian. + /// + /// The span of bytes where the value is to be written, as little endian. + /// The value to write into the span of bytes. + /// Writes exactly 2 bytes to the beginning of the span. + /// + /// is too small to contain a . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteBFloat16LittleEndian(Span destination, BFloat16 value) + { + if (!BitConverter.IsLittleEndian) + { + short tmp = ReverseEndianness(BitConverter.BFloat16ToInt16Bits(value)); + MemoryMarshal.Write(destination, in tmp); + } + else + { + MemoryMarshal.Write(destination, in value); + } + } + /// /// Writes a into a span of bytes, as little endian. /// @@ -354,6 +378,27 @@ public static bool TryWriteHalfLittleEndian(Span destination, Half value) return MemoryMarshal.TryWrite(destination, in value); } + /// + /// Writes a into a span of bytes, as little endian. + /// + /// The span of bytes where the value is to be written, as little endian. + /// The value to write into the span of bytes. + /// + /// if the span is large enough to contain a ; otherwise, . + /// + /// Writes exactly 2 bytes to the beginning of the span. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool TryWriteBFloat16LittleEndian(Span destination, BFloat16 value) + { + if (!BitConverter.IsLittleEndian) + { + short tmp = ReverseEndianness(BitConverter.BFloat16ToInt16Bits(value)); + return MemoryMarshal.TryWrite(destination, in tmp); + } + + return MemoryMarshal.TryWrite(destination, in value); + } + /// /// Writes a into a span of bytes, as little endian. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs index 1effc397dc816b..bc03c9874393fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs @@ -6,8 +6,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using static System.Reflection.Emit.TypeNameBuilder; namespace System.Numerics { diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 6869aeb397ceb0..00d8b98fe5e711 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -783,6 +783,9 @@ public enum Base64FormattingOptions public static partial class BitConverter { public static readonly bool IsLittleEndian; + public static short BFloat16ToInt16Bits(System.Numerics.BFloat16 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static ushort BFloat16ToUInt16Bits(System.Numerics.BFloat16 value) { throw null; } public static long DoubleToInt64Bits(double value) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong DoubleToUInt64Bits(double value) { throw null; } @@ -803,15 +806,19 @@ public static partial class BitConverter public static byte[] GetBytes(uint value) { throw null; } [System.CLSCompliantAttribute(false)] public static byte[] GetBytes(ulong value) { throw null; } + public static byte[] GetBytes(System.Numerics.BFloat16 value) { throw null; } public static short HalfToInt16Bits(System.Half value) { throw null; } [System.CLSCompliantAttribute(false)] public static ushort HalfToUInt16Bits(System.Half value) { throw null; } + public static System.Numerics.BFloat16 Int16BitsToBFloat16(short value) { throw null; } public static System.Half Int16BitsToHalf(short value) { throw null; } 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 uint SingleToUInt32Bits(float value) { throw null; } + public static System.Numerics.BFloat16 ToBFloat16(byte[] value, int startIndex) { throw null; } + public static System.Numerics.BFloat16 ToBFloat16(System.ReadOnlySpan 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; } @@ -866,6 +873,9 @@ public static partial class BitConverter public static bool TryWriteBytes(System.Span destination, uint value) { throw null; } [System.CLSCompliantAttribute(false)] public static bool TryWriteBytes(System.Span destination, ulong value) { throw null; } + public static bool TryWriteBytes(System.Span destination, System.Numerics.BFloat16 value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Numerics.BFloat16 UInt16BitsToBFloat16(ushort value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Half UInt16BitsToHalf(ushort value) { throw null; } [System.CLSCompliantAttribute(false)] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/BitConverter.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/BitConverter.cs index 87b1ad5860fe83..c255c5e57782ba 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/BitConverter.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/BitConverter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Linq; +using System.Numerics; using System.Text; using Xunit; @@ -26,6 +27,7 @@ public static unsafe void IsLittleEndianReflection() [Fact] public static void ValueArgumentNull() { + AssertExtensions.Throws("value", () => BitConverter.ToBFloat16(null, 0)); AssertExtensions.Throws("value", () => BitConverter.ToBoolean(null, 0)); AssertExtensions.Throws("value", () => BitConverter.ToChar(null, 0)); AssertExtensions.Throws("value", () => BitConverter.ToDouble(null, 0)); @@ -47,6 +49,10 @@ public static void ValueArgumentNull() [Fact] public static void StartIndexBeyondLength() { + AssertExtensions.Throws("startIndex", () => BitConverter.ToBFloat16(new byte[2], -1)); + AssertExtensions.Throws("startIndex", () => BitConverter.ToBFloat16(new byte[2], 2)); + AssertExtensions.Throws("startIndex", () => BitConverter.ToBFloat16(new byte[2], 3)); + AssertExtensions.Throws("startIndex", () => BitConverter.ToBoolean(new byte[1], -1)); AssertExtensions.Throws("startIndex", () => BitConverter.ToBoolean(new byte[1], 1)); AssertExtensions.Throws("startIndex", () => BitConverter.ToBoolean(new byte[1], 2)); @@ -113,6 +119,7 @@ public static void StartIndexBeyondLength() [Fact] public static void StartIndexPlusNeededLengthTooLong() { + AssertExtensions.Throws("value", null, () => BitConverter.ToBFloat16(new byte[2], 1)); AssertExtensions.Throws("startIndex", () => BitConverter.ToBoolean(new byte[0], 0)); AssertExtensions.Throws("value", null, () => BitConverter.ToChar(new byte[2], 1)); AssertExtensions.Throws("value", null, () => BitConverter.ToDouble(new byte[8], 1)); @@ -185,6 +192,14 @@ public static void RoundtripHalf() VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToHalf, input, expected); } + [Fact] + public static void RoundtripBFloat16() + { + BFloat16 input = (BFloat16)123.456f; + byte[] expected = { 0xf7, 0x42 }; + VerifyRoundtrip(BitConverter.GetBytes, BitConverter.ToBFloat16, input, expected); + } + [Fact] public static void RoundtripInt16() { @@ -331,6 +346,16 @@ public static void HalfToInt16Bits() Assert.Equal(input, roundtripped); } + [Fact] + public static void BFloat16ToInt16Bits() + { + BFloat16 input = (BFloat16)123.456f; + short result = BitConverter.BFloat16ToInt16Bits(input); + Assert.Equal((short)17143, result); + BFloat16 roundtripped = BitConverter.Int16BitsToBFloat16(result); + Assert.Equal(input, roundtripped); + } + [Fact] public static void DoubleToUInt64Bits() { @@ -360,5 +385,15 @@ public static void HalfToUInt16Bits() Half roundtripped = BitConverter.UInt16BitsToHalf(result); Assert.Equal(input, roundtripped); } + + [Fact] + public static void BFloat16ToUInt16Bits() + { + BFloat16 input = (BFloat16)123.456f; + ushort result = BitConverter.BFloat16ToUInt16Bits(input); + Assert.Equal((ushort)17143, result); + BFloat16 roundtripped = BitConverter.UInt16BitsToBFloat16(result); + Assert.Equal(input, roundtripped); + } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Numerics/BFloat16Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Numerics/BFloat16Tests.cs index 8b4a5352b97f4a..041dccf8528618 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Numerics/BFloat16Tests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Numerics/BFloat16Tests.cs @@ -8,7 +8,6 @@ using System.Text; using Xunit; using Xunit.Sdk; -using static System.Tests.CreateDelegateTests; namespace System.Numerics.Tests { @@ -16,66 +15,62 @@ public class BFloat16Tests { private static BFloat16 CrossPlatformMachineEpsilon => (BFloat16)3.90625e-03f; - private static ushort BFloat16ToUInt16Bits(BFloat16 value) => Unsafe.BitCast(value); - - private static BFloat16 UInt16BitsToBFloat16(ushort value) => Unsafe.BitCast(value); - [Fact] public static void Epsilon() { - Assert.Equal(0x0001u, BFloat16ToUInt16Bits(BFloat16.Epsilon)); + Assert.Equal(0x0001u, BitConverter.BFloat16ToUInt16Bits(BFloat16.Epsilon)); } [Fact] public static void PositiveInfinity() { - Assert.Equal(0x7F80u, BFloat16ToUInt16Bits(BFloat16.PositiveInfinity)); + Assert.Equal(0x7F80u, BitConverter.BFloat16ToUInt16Bits(BFloat16.PositiveInfinity)); } [Fact] public static void NegativeInfinity() { - Assert.Equal(0xFF80u, BFloat16ToUInt16Bits(BFloat16.NegativeInfinity)); + Assert.Equal(0xFF80u, BitConverter.BFloat16ToUInt16Bits(BFloat16.NegativeInfinity)); } [Fact] public static void NaN() { - Assert.Equal(0xFFC0u, BFloat16ToUInt16Bits(BFloat16.NaN)); + Assert.Equal(0xFFC0u, BitConverter.BFloat16ToUInt16Bits(BFloat16.NaN)); } [Fact] public static void MinValue() { - Assert.Equal(0xFF7Fu, BFloat16ToUInt16Bits(BFloat16.MinValue)); + Assert.Equal(0xFF7Fu, BitConverter.BFloat16ToUInt16Bits(BFloat16.MinValue)); } [Fact] public static void MaxValue() { - Assert.Equal(0x7F7Fu, BFloat16ToUInt16Bits(BFloat16.MaxValue)); + Assert.Equal(0x7F7Fu, BitConverter.BFloat16ToUInt16Bits(BFloat16.MaxValue)); } [Fact] public static void Ctor_Empty() { var value = new BFloat16(); - Assert.Equal(0x0000, BFloat16ToUInt16Bits(value)); + Assert.Equal(0x0000, BitConverter.BFloat16ToUInt16Bits(value)); } public static IEnumerable IsFinite_TestData() { yield return new object[] { BFloat16.NegativeInfinity, false }; // Negative Infinity yield return new object[] { BFloat16.MinValue, true }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8400), true }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x83FF), true }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8000), true }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8400), true }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x83FF), true }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), true }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), true }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), true }; // Positive Zero yield return new object[] { BFloat16.Epsilon, true }; // Min Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x03FF), true }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0400), true }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x03FF), true }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0400), true }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, true }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -91,15 +86,15 @@ public static IEnumerable IsInfinity_TestData() { yield return new object[] { BFloat16.NegativeInfinity, true }; // Negative Infinity yield return new object[] { BFloat16.MinValue, false }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal (Positive Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, true }; // Positive Infinity } @@ -115,15 +110,15 @@ public static IEnumerable IsNaN_TestData() { yield return new object[] { BFloat16.NegativeInfinity, false }; // Negative Infinity yield return new object[] { BFloat16.MinValue, false }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, true }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal (Positive Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -139,15 +134,15 @@ public static IEnumerable IsNegative_TestData() { yield return new object[] { BFloat16.NegativeInfinity, true }; // Negative Infinity yield return new object[] { BFloat16.MinValue, true }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), true }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), true }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8000), true }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), true }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), true }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), true }; // Negative Zero yield return new object[] { BFloat16.NaN, true }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -163,15 +158,15 @@ public static IEnumerable IsNegativeInfinity_TestData() { yield return new object[] { BFloat16.NegativeInfinity, true }; // Negative Infinity yield return new object[] { BFloat16.MinValue, false }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal (Positive Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -187,15 +182,15 @@ public static IEnumerable IsNormal_TestData() { yield return new object[] { BFloat16.NegativeInfinity, false }; // Negative Infinity yield return new object[] { BFloat16.MinValue, true }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), true }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), true }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), true }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), true }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, true }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -211,15 +206,15 @@ public static IEnumerable IsPositiveInfinity_TestData() { yield return new object[] { BFloat16.NegativeInfinity, false }; // Negative Infinity yield return new object[] { BFloat16.MinValue, false }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), false }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), false }; // Max Negative Subnormal (Negative Epsilon) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, false }; // Min Positive Subnormal (Positive Epsilon) - yield return new object[] { UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), false }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, true }; // Positive Infinity } @@ -235,15 +230,15 @@ public static IEnumerable IsSubnormal_TestData() { yield return new object[] { BFloat16.NegativeInfinity, false }; // Negative Infinity yield return new object[] { BFloat16.MinValue, false }; // Min Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal - yield return new object[] { UInt16BitsToBFloat16(0x807F), true }; // Min Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x8000), false }; // Negative Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8080), false }; // Max Negative Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x807F), true }; // Min Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8001), true }; // Max Negative Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), false }; // Negative Zero yield return new object[] { BFloat16.NaN, false }; // NaN - yield return new object[] { UInt16BitsToBFloat16(0x0000), false }; // Positive Zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), false }; // Positive Zero yield return new object[] { BFloat16.Epsilon, true }; // Min Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x007F), true }; // Max Positive Subnormal - yield return new object[] { UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x007F), true }; // Max Positive Subnormal + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0080), false }; // Min Positive Normal yield return new object[] { BFloat16.MaxValue, false }; // Max Positive Normal yield return new object[] { BFloat16.PositiveInfinity, false }; // Positive Infinity } @@ -272,19 +267,19 @@ public static IEnumerable CompareTo_TestData() { yield return new object[] { BFloat16.MaxValue, BFloat16.MaxValue, 0 }; yield return new object[] { BFloat16.MaxValue, BFloat16.MinValue, 1 }; - yield return new object[] { BFloat16.Epsilon, UInt16BitsToBFloat16(0x8001), 1 }; - yield return new object[] { BFloat16.MaxValue, UInt16BitsToBFloat16(0x0000), 1 }; + yield return new object[] { BFloat16.Epsilon, BitConverter.UInt16BitsToBFloat16(0x8001), 1 }; + yield return new object[] { BFloat16.MaxValue, BitConverter.UInt16BitsToBFloat16(0x0000), 1 }; yield return new object[] { BFloat16.MaxValue, BFloat16.Epsilon, 1 }; yield return new object[] { BFloat16.MaxValue, BFloat16.PositiveInfinity, -1 }; yield return new object[] { BFloat16.MinValue, BFloat16.MaxValue, -1 }; yield return new object[] { BFloat16.MaxValue, BFloat16.NaN, 1 }; yield return new object[] { BFloat16.NaN, BFloat16.NaN, 0 }; - yield return new object[] { BFloat16.NaN, UInt16BitsToBFloat16(0x0000), -1 }; + yield return new object[] { BFloat16.NaN, BitConverter.UInt16BitsToBFloat16(0x0000), -1 }; yield return new object[] { BFloat16.MaxValue, null, 1 }; yield return new object[] { BFloat16.MinValue, BFloat16.NegativeInfinity, 1 }; yield return new object[] { BFloat16.NegativeInfinity, BFloat16.MinValue, -1 }; - yield return new object[] { UInt16BitsToBFloat16(0x8000), BFloat16.NegativeInfinity, 1 }; // Negative zero - yield return new object[] { BFloat16.NegativeInfinity, UInt16BitsToBFloat16(0x8000), -1 }; // Negative zero + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), BFloat16.NegativeInfinity, 1 }; // Negative zero + yield return new object[] { BFloat16.NegativeInfinity, BitConverter.UInt16BitsToBFloat16(0x8000), -1 }; // Negative zero yield return new object[] { BFloat16.NegativeInfinity, BFloat16.NegativeInfinity, 0 }; yield return new object[] { BFloat16.PositiveInfinity, BFloat16.PositiveInfinity, 0 }; yield return new object[] { (BFloat16)(-180f), (BFloat16)(-180f), 0 }; @@ -341,7 +336,7 @@ public static IEnumerable Equals_TestData() { yield return new object[] { BFloat16.MaxValue, BFloat16.MaxValue, true }; yield return new object[] { BFloat16.MaxValue, BFloat16.MinValue, false }; - yield return new object[] { BFloat16.MaxValue, UInt16BitsToBFloat16(0x0000), false }; + yield return new object[] { BFloat16.MaxValue, BitConverter.UInt16BitsToBFloat16(0x0000), false }; yield return new object[] { BFloat16.MaxValue, 789.0f, false }; yield return new object[] { BFloat16.MaxValue, "789", false }; } @@ -357,41 +352,41 @@ public static IEnumerable ExplicitConversion_ToSingle_TestData() { (BFloat16 Original, float Expected)[] data = // Fraction is truncated for lower 16 bits { - (UInt16BitsToBFloat16(0b0_01111111_0000000), 1f), // 1 - (UInt16BitsToBFloat16(0b1_01111111_0000000), -1f), // -1 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_0000000), 1f), // 1 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_0000000), -1f), // -1 (BFloat16.MaxValue, BitConverter.UInt32BitsToSingle(0x7F7F0000)), // 3.3895314E+38 (BFloat16.MinValue, BitConverter.UInt32BitsToSingle(0xFF7F0000)), // -3.3895314E+38 - (UInt16BitsToBFloat16(0b0_01111011_1001101), 0.10009765625f), // 0.1ish - (UInt16BitsToBFloat16(0b1_01111011_1001101), -0.10009765625f), // -0.1ish - (UInt16BitsToBFloat16(0b0_10000100_0101000), 42f), // 42 - (UInt16BitsToBFloat16(0b1_10000100_0101000), -42f), // -42 + (BitConverter.UInt16BitsToBFloat16(0b0_01111011_1001101), 0.10009765625f), // 0.1ish + (BitConverter.UInt16BitsToBFloat16(0b1_01111011_1001101), -0.10009765625f), // -0.1ish + (BitConverter.UInt16BitsToBFloat16(0b0_10000100_0101000), 42f), // 42 + (BitConverter.UInt16BitsToBFloat16(0b1_10000100_0101000), -42f), // -42 (BFloat16.PositiveInfinity, float.PositiveInfinity), // PosInfinity (BFloat16.NegativeInfinity, float.NegativeInfinity), // NegInfinity - (UInt16BitsToBFloat16(0b0_11111111_1000000), BitConverter.UInt32BitsToSingle(0x7FC00000)), // Positive Quiet NaN + (BitConverter.UInt16BitsToBFloat16(0b0_11111111_1000000), BitConverter.UInt32BitsToSingle(0x7FC00000)), // Positive Quiet NaN (BFloat16.NaN, float.NaN), // Negative Quiet NaN - (UInt16BitsToBFloat16(0b0_11111111_1010101), BitConverter.UInt32BitsToSingle(0x7FD50000)), // Positive Signalling NaN - Should preserve payload - (UInt16BitsToBFloat16(0b1_11111111_1010101), BitConverter.UInt32BitsToSingle(0xFFD50000)), // Negative Signalling NaN - Should preserve payload + (BitConverter.UInt16BitsToBFloat16(0b0_11111111_1010101), BitConverter.UInt32BitsToSingle(0x7FD50000)), // Positive Signalling NaN - Should preserve payload + (BitConverter.UInt16BitsToBFloat16(0b1_11111111_1010101), BitConverter.UInt32BitsToSingle(0xFFD50000)), // Negative Signalling NaN - Should preserve payload (BFloat16.Epsilon, BitConverter.UInt32BitsToSingle(0x00010000)), // PosEpsilon = 9.1835E-41 - (UInt16BitsToBFloat16(0), 0), // 0 - (UInt16BitsToBFloat16(0b1_00000000_0000000), -0f), // -0 - (UInt16BitsToBFloat16(0b0_10000000_1001001), 3.140625f), // 3.140625 - (UInt16BitsToBFloat16(0b1_10000000_1001001), -3.140625f), // -3.140625 - (UInt16BitsToBFloat16(0b0_10000000_0101110), 2.71875f), // 2.71875 - (UInt16BitsToBFloat16(0b1_10000000_0101110), -2.71875f), // -2.71875 - (UInt16BitsToBFloat16(0b0_01111111_1000000), 1.5f), // 1.5 - (UInt16BitsToBFloat16(0b1_01111111_1000000), -1.5f), // -1.5 - (UInt16BitsToBFloat16(0b0_01111111_1000001), 1.5078125f), // 1.5078125 - (UInt16BitsToBFloat16(0b1_01111111_1000001), -1.5078125f), // -1.5078125 - (UInt16BitsToBFloat16(0b0_00000001_0000000), BitConverter.UInt32BitsToSingle(0x00800000)), // smallest normal - (UInt16BitsToBFloat16(0b0_00000000_1111111), BitConverter.UInt32BitsToSingle(0x007F0000)), // largest subnormal - (UInt16BitsToBFloat16(0b0_00000000_1000000), BitConverter.UInt32BitsToSingle(0x00400000)), // middle subnormal - (UInt16BitsToBFloat16(0b0_00000000_0111111), BitConverter.UInt32BitsToSingle(0x003F0000)), // just below middle subnormal - (UInt16BitsToBFloat16(0b0_00000000_0000001), BitConverter.UInt32BitsToSingle(0x00010000)), // smallest subnormal - (UInt16BitsToBFloat16(0b1_00000000_0000001), BitConverter.UInt32BitsToSingle(0x80010000)), // highest negative subnormal - (UInt16BitsToBFloat16(0b1_00000000_0111111), BitConverter.UInt32BitsToSingle(0x803F0000)), // just above negative middle subnormal - (UInt16BitsToBFloat16(0b1_00000000_1000000), BitConverter.UInt32BitsToSingle(0x80400000)), // negative middle subnormal - (UInt16BitsToBFloat16(0b1_00000000_1111111), BitConverter.UInt32BitsToSingle(0x807F0000)), // lowest negative subnormal - (UInt16BitsToBFloat16(0b1_00000001_0000000), BitConverter.UInt32BitsToSingle(0x80800000)) // highest negative normal + (BitConverter.UInt16BitsToBFloat16(0), 0), // 0 + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000), -0f), // -0 + (BitConverter.UInt16BitsToBFloat16(0b0_10000000_1001001), 3.140625f), // 3.140625 + (BitConverter.UInt16BitsToBFloat16(0b1_10000000_1001001), -3.140625f), // -3.140625 + (BitConverter.UInt16BitsToBFloat16(0b0_10000000_0101110), 2.71875f), // 2.71875 + (BitConverter.UInt16BitsToBFloat16(0b1_10000000_0101110), -2.71875f), // -2.71875 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000000), 1.5f), // 1.5 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000000), -1.5f), // -1.5 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000001), 1.5078125f), // 1.5078125 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000001), -1.5078125f), // -1.5078125 + (BitConverter.UInt16BitsToBFloat16(0b0_00000001_0000000), BitConverter.UInt32BitsToSingle(0x00800000)), // smallest normal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1111111), BitConverter.UInt32BitsToSingle(0x007F0000)), // largest subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000000), BitConverter.UInt32BitsToSingle(0x00400000)), // middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0111111), BitConverter.UInt32BitsToSingle(0x003F0000)), // just below middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000001), BitConverter.UInt32BitsToSingle(0x00010000)), // smallest subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000001), BitConverter.UInt32BitsToSingle(0x80010000)), // highest negative subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0111111), BitConverter.UInt32BitsToSingle(0x803F0000)), // just above negative middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000000), BitConverter.UInt32BitsToSingle(0x80400000)), // negative middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1111111), BitConverter.UInt32BitsToSingle(0x807F0000)), // lowest negative subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000001_0000000), BitConverter.UInt32BitsToSingle(0x80800000)) // highest negative normal }; foreach ((BFloat16 original, float expected) in data) @@ -412,41 +407,41 @@ public static IEnumerable ExplicitConversion_ToDouble_TestData() { (BFloat16 Original, double Expected)[] data = { - (UInt16BitsToBFloat16(0b0_01111111_0000000), 1d), // 1 - (UInt16BitsToBFloat16(0b1_01111111_0000000), -1d), // -1 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_0000000), 1d), // 1 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_0000000), -1d), // -1 (BFloat16.MaxValue, BitConverter.UInt64BitsToDouble(0x47EFE000_00000000)), // 3.3895314E+38 (BFloat16.MinValue, BitConverter.UInt64BitsToDouble(0xC7EFE000_00000000)), // -3.3895314E+38 - (UInt16BitsToBFloat16(0b0_01111011_1001101), 0.10009765625d), // 0.1ish - (UInt16BitsToBFloat16(0b1_01111011_1001101), -0.10009765625d), // -0.1ish - (UInt16BitsToBFloat16(0b0_10000100_0101000), 42d), // 42 - (UInt16BitsToBFloat16(0b1_10000100_0101000), -42d), // -42 + (BitConverter.UInt16BitsToBFloat16(0b0_01111011_1001101), 0.10009765625d), // 0.1ish + (BitConverter.UInt16BitsToBFloat16(0b1_01111011_1001101), -0.10009765625d), // -0.1ish + (BitConverter.UInt16BitsToBFloat16(0b0_10000100_0101000), 42d), // 42 + (BitConverter.UInt16BitsToBFloat16(0b1_10000100_0101000), -42d), // -42 (BFloat16.PositiveInfinity, double.PositiveInfinity), // PosInfinity (BFloat16.NegativeInfinity, double.NegativeInfinity), // NegInfinity - (UInt16BitsToBFloat16(0b0_11111111_1000000), BitConverter.UInt64BitsToDouble(0x7FF80000_00000000)), // Positive Quiet NaN + (BitConverter.UInt16BitsToBFloat16(0b0_11111111_1000000), BitConverter.UInt64BitsToDouble(0x7FF80000_00000000)), // Positive Quiet NaN (BFloat16.NaN, double.NaN), // Negative Quiet NaN - (UInt16BitsToBFloat16(0b0_11111111_1010101), BitConverter.UInt64BitsToDouble(0x7FFAA000_00000000)), // Positive Signalling NaN - Should preserve payload - (UInt16BitsToBFloat16(0b1_11111111_1010101), BitConverter.UInt64BitsToDouble(0xFFFAA000_00000000)), // Negative Signalling NaN - Should preserve payload + (BitConverter.UInt16BitsToBFloat16(0b0_11111111_1010101), BitConverter.UInt64BitsToDouble(0x7FFAA000_00000000)), // Positive Signalling NaN - Should preserve payload + (BitConverter.UInt16BitsToBFloat16(0b1_11111111_1010101), BitConverter.UInt64BitsToDouble(0xFFFAA000_00000000)), // Negative Signalling NaN - Should preserve payload (BFloat16.Epsilon, BitConverter.UInt64BitsToDouble(0x37A00000_00000000)), // PosEpsilon = 9.1835E-41 - (UInt16BitsToBFloat16(0), 0d), // 0 - (UInt16BitsToBFloat16(0b1_00000000_0000000), -0d), // -0 - (UInt16BitsToBFloat16(0b0_10000000_1001001), 3.140625d), // 3.140625 - (UInt16BitsToBFloat16(0b1_10000000_1001001), -3.140625d), // -3.140625 - (UInt16BitsToBFloat16(0b0_10000000_0101110), 2.71875d), // 2.71875 - (UInt16BitsToBFloat16(0b1_10000000_0101110), -2.71875d), // -2.71875 - (UInt16BitsToBFloat16(0b0_01111111_1000000), 1.5d), // 1.5 - (UInt16BitsToBFloat16(0b1_01111111_1000000), -1.5d), // -1.5 - (UInt16BitsToBFloat16(0b0_01111111_1000001), 1.5078125d), // 1.5078125 - (UInt16BitsToBFloat16(0b1_01111111_1000001), -1.5078125d), // -1.5078125 - (UInt16BitsToBFloat16(0b0_00000001_0000000), BitConverter.UInt64BitsToDouble(0x3810000000000000)), // smallest normal - (UInt16BitsToBFloat16(0b0_00000000_1111111), BitConverter.UInt64BitsToDouble(0x380FC00000000000)), // largest subnormal - (UInt16BitsToBFloat16(0b0_00000000_1000000), BitConverter.UInt64BitsToDouble(0x3800000000000000)), // middle subnormal - (UInt16BitsToBFloat16(0b0_00000000_0111111), BitConverter.UInt64BitsToDouble(0x37FF800000000000)), // just below middle subnormal - (UInt16BitsToBFloat16(0b0_00000000_0000001), BitConverter.UInt64BitsToDouble(0x37A0000000000000)), // smallest subnormal - (UInt16BitsToBFloat16(0b1_00000000_0000001), BitConverter.UInt64BitsToDouble(0xB7A0000000000000)), // highest negative subnormal - (UInt16BitsToBFloat16(0b1_00000000_0111111), BitConverter.UInt64BitsToDouble(0xB7FF800000000000)), // just above negative middle subnormal - (UInt16BitsToBFloat16(0b1_00000000_1000000), BitConverter.UInt64BitsToDouble(0xB800000000000000)), // negative middle subnormal - (UInt16BitsToBFloat16(0b1_00000000_1111111), BitConverter.UInt64BitsToDouble(0xB80FC00000000000)), // lowest negative subnormal - (UInt16BitsToBFloat16(0b1_00000001_0000000), BitConverter.UInt64BitsToDouble(0xB810000000000000)) // highest negative normal + (BitConverter.UInt16BitsToBFloat16(0), 0d), // 0 + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000), -0d), // -0 + (BitConverter.UInt16BitsToBFloat16(0b0_10000000_1001001), 3.140625d), // 3.140625 + (BitConverter.UInt16BitsToBFloat16(0b1_10000000_1001001), -3.140625d), // -3.140625 + (BitConverter.UInt16BitsToBFloat16(0b0_10000000_0101110), 2.71875d), // 2.71875 + (BitConverter.UInt16BitsToBFloat16(0b1_10000000_0101110), -2.71875d), // -2.71875 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000000), 1.5d), // 1.5 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000000), -1.5d), // -1.5 + (BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000001), 1.5078125d), // 1.5078125 + (BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000001), -1.5078125d), // -1.5078125 + (BitConverter.UInt16BitsToBFloat16(0b0_00000001_0000000), BitConverter.UInt64BitsToDouble(0x3810000000000000)), // smallest normal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1111111), BitConverter.UInt64BitsToDouble(0x380FC00000000000)), // largest subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000000), BitConverter.UInt64BitsToDouble(0x3800000000000000)), // middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0111111), BitConverter.UInt64BitsToDouble(0x37FF800000000000)), // just below middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000001), BitConverter.UInt64BitsToDouble(0x37A0000000000000)), // smallest subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000001), BitConverter.UInt64BitsToDouble(0xB7A0000000000000)), // highest negative subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0111111), BitConverter.UInt64BitsToDouble(0xB7FF800000000000)), // just above negative middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000000), BitConverter.UInt64BitsToDouble(0xB800000000000000)), // negative middle subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1111111), BitConverter.UInt64BitsToDouble(0xB80FC00000000000)), // lowest negative subnormal + (BitConverter.UInt16BitsToBFloat16(0b1_00000001_0000000), BitConverter.UInt64BitsToDouble(0xB810000000000000)) // highest negative normal }; foreach ((BFloat16 original, double expected) in data) @@ -467,72 +462,72 @@ public static IEnumerable ExplicitConversion_FromSingle_TestData() { (float, BFloat16)[] data = { - (MathF.PI, UInt16BitsToBFloat16(0b0_10000000_1001001)), // 3.140625 - (MathF.E, UInt16BitsToBFloat16(0b0_10000000_0101110)), // 2.71875 - (-MathF.PI, UInt16BitsToBFloat16(0b1_10000000_1001001)), // -3.140625 - (-MathF.E, UInt16BitsToBFloat16(0b1_10000000_0101110)), // -2.71875 - (float.MaxValue, UInt16BitsToBFloat16(0b0_11111111_0000000)), // Overflow - (float.MinValue, UInt16BitsToBFloat16(0b1_11111111_0000000)), // Overflow + (MathF.PI, BitConverter.UInt16BitsToBFloat16(0b0_10000000_1001001)), // 3.140625 + (MathF.E, BitConverter.UInt16BitsToBFloat16(0b0_10000000_0101110)), // 2.71875 + (-MathF.PI, BitConverter.UInt16BitsToBFloat16(0b1_10000000_1001001)), // -3.140625 + (-MathF.E, BitConverter.UInt16BitsToBFloat16(0b1_10000000_0101110)), // -2.71875 + (float.MaxValue, BitConverter.UInt16BitsToBFloat16(0b0_11111111_0000000)), // Overflow + (float.MinValue, BitConverter.UInt16BitsToBFloat16(0b1_11111111_0000000)), // Overflow (float.PositiveInfinity, BFloat16.PositiveInfinity), // Overflow (float.NegativeInfinity, BFloat16.NegativeInfinity), // Overflow (float.NaN, BFloat16.NaN), // Quiet Negative NaN - (BitConverter.UInt32BitsToSingle(0x7FC00000), UInt16BitsToBFloat16(0b0_11111111_1000000)), // Quiet Positive NaN - (BitConverter.UInt32BitsToSingle(0xFFD55555), UInt16BitsToBFloat16(0b1_11111111_1010101)), // Signalling Negative NaN - (BitConverter.UInt32BitsToSingle(0x7FD55555), UInt16BitsToBFloat16(0b0_11111111_1010101)), // Signalling Positive NaN - (float.Epsilon, UInt16BitsToBFloat16(0)), // Underflow - (-float.Epsilon, UInt16BitsToBFloat16(0b1_00000000_0000000)), // Underflow - (1f, UInt16BitsToBFloat16(0b0_01111111_0000000)), // 1 - (-1f, UInt16BitsToBFloat16(0b1_01111111_0000000)), // -1 - (0f, UInt16BitsToBFloat16(0)), // 0 - (-0f, UInt16BitsToBFloat16(0b1_00000000_0000000)), // -0 - (42f, UInt16BitsToBFloat16(0b0_10000100_0101000)), // 42 - (-42f, UInt16BitsToBFloat16(0b1_10000100_0101000)), // -42 - (0.1f, UInt16BitsToBFloat16(0b0_01111011_1001101)), // 0.10009765625 - (-0.1f, UInt16BitsToBFloat16(0b1_01111011_1001101)), // -0.10009765625 - (1.5f, UInt16BitsToBFloat16(0b0_01111111_1000000)), // 1.5 - (-1.5f, UInt16BitsToBFloat16(0b1_01111111_1000000)), // -1.5 - (1.5078125f, UInt16BitsToBFloat16(0b0_01111111_1000001)), // 1.5078125 - (-1.5078125f, UInt16BitsToBFloat16(0b1_01111111_1000001)), // -1.5078125 - (BitConverter.UInt32BitsToSingle(0x00800000), UInt16BitsToBFloat16(0b0_00000001_0000000)), // smallest normal - (BitConverter.UInt32BitsToSingle(0x007F0000), UInt16BitsToBFloat16(0b0_00000000_1111111)), // largest subnormal - (BitConverter.UInt32BitsToSingle(0x00400000), UInt16BitsToBFloat16(0b0_00000000_1000000)), // middle subnormal - (BitConverter.UInt32BitsToSingle(0x003F0000), UInt16BitsToBFloat16(0b0_00000000_0111111)), // just below middle subnormal - (BitConverter.UInt32BitsToSingle(0x00010000), UInt16BitsToBFloat16(0b0_00000000_0000001)), // smallest subnormal - (BitConverter.UInt32BitsToSingle(0x80010000), UInt16BitsToBFloat16(0b1_00000000_0000001)), // highest negative subnormal - (BitConverter.UInt32BitsToSingle(0x803F0000), UInt16BitsToBFloat16(0b1_00000000_0111111)), // just above negative middle subnormal - (BitConverter.UInt32BitsToSingle(0x80400000), UInt16BitsToBFloat16(0b1_00000000_1000000)), // negative middle subnormal - (BitConverter.UInt32BitsToSingle(0x807F0000), UInt16BitsToBFloat16(0b1_00000000_1111111)), // lowest negative subnormal - (BitConverter.UInt32BitsToSingle(0x80800000), UInt16BitsToBFloat16(0b1_00000001_0000000)), // highest negative normal + (BitConverter.UInt32BitsToSingle(0x7FC00000), BitConverter.UInt16BitsToBFloat16(0b0_11111111_1000000)), // Quiet Positive NaN + (BitConverter.UInt32BitsToSingle(0xFFD55555), BitConverter.UInt16BitsToBFloat16(0b1_11111111_1010101)), // Signalling Negative NaN + (BitConverter.UInt32BitsToSingle(0x7FD55555), BitConverter.UInt16BitsToBFloat16(0b0_11111111_1010101)), // Signalling Positive NaN + (float.Epsilon, BitConverter.UInt16BitsToBFloat16(0)), // Underflow + (-float.Epsilon, BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000)), // Underflow + (1f, BitConverter.UInt16BitsToBFloat16(0b0_01111111_0000000)), // 1 + (-1f, BitConverter.UInt16BitsToBFloat16(0b1_01111111_0000000)), // -1 + (0f, BitConverter.UInt16BitsToBFloat16(0)), // 0 + (-0f, BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000)), // -0 + (42f, BitConverter.UInt16BitsToBFloat16(0b0_10000100_0101000)), // 42 + (-42f, BitConverter.UInt16BitsToBFloat16(0b1_10000100_0101000)), // -42 + (0.1f, BitConverter.UInt16BitsToBFloat16(0b0_01111011_1001101)), // 0.10009765625 + (-0.1f, BitConverter.UInt16BitsToBFloat16(0b1_01111011_1001101)), // -0.10009765625 + (1.5f, BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000000)), // 1.5 + (-1.5f, BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000000)), // -1.5 + (1.5078125f, BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000001)), // 1.5078125 + (-1.5078125f, BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000001)), // -1.5078125 + (BitConverter.UInt32BitsToSingle(0x00800000), BitConverter.UInt16BitsToBFloat16(0b0_00000001_0000000)), // smallest normal + (BitConverter.UInt32BitsToSingle(0x007F0000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_1111111)), // largest subnormal + (BitConverter.UInt32BitsToSingle(0x00400000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000000)), // middle subnormal + (BitConverter.UInt32BitsToSingle(0x003F0000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_0111111)), // just below middle subnormal + (BitConverter.UInt32BitsToSingle(0x00010000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000001)), // smallest subnormal + (BitConverter.UInt32BitsToSingle(0x80010000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000001)), // highest negative subnormal + (BitConverter.UInt32BitsToSingle(0x803F0000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_0111111)), // just above negative middle subnormal + (BitConverter.UInt32BitsToSingle(0x80400000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000000)), // negative middle subnormal + (BitConverter.UInt32BitsToSingle(0x807F0000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_1111111)), // lowest negative subnormal + (BitConverter.UInt32BitsToSingle(0x80800000), BitConverter.UInt16BitsToBFloat16(0b1_00000001_0000000)), // highest negative normal (BitConverter.UInt32BitsToSingle(0b0_10001001_00000111000000000000001), - UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052+ULP rounds up + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052+ULP rounds up (BitConverter.UInt32BitsToSingle(0b0_10001001_00000111000000000000000), - UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052 rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052 rounds to even (BitConverter.UInt32BitsToSingle(0b0_10001001_00000110111111111111111), - UInt16BitsToBFloat16(0b0_10001001_0000011)), // 1052-ULP rounds down + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000011)), // 1052-ULP rounds down (BitConverter.UInt32BitsToSingle(0b0_10001001_00000101000000000000000), - UInt16BitsToBFloat16(0b0_10001001_0000010)), // 1044 rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000010)), // 1044 rounds to even (BitConverter.UInt32BitsToSingle(0b1_10001001_00000110111111111111111), - UInt16BitsToBFloat16(0b1_10001001_0000011)), // -1052+ULP rounds towards zero + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000011)), // -1052+ULP rounds towards zero (BitConverter.UInt32BitsToSingle(0b1_10001001_00000111000000000000000), - UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052 rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052 rounds to even (BitConverter.UInt32BitsToSingle(0b1_10001001_00000111000000000000001), - UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052-ULP rounds away from zero + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052-ULP rounds away from zero (BitConverter.UInt32BitsToSingle(0b1_10001001_00000101000000000000000), - UInt16BitsToBFloat16(0b1_10001001_0000010)), // -1044 rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000010)), // -1044 rounds to even (BitConverter.UInt32BitsToSingle(0b0_00000000_10000111000000000000001), - UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal + ULP rounds up + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal + ULP rounds up (BitConverter.UInt32BitsToSingle(0b0_00000000_10000111000000000000000), - UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal rounds to even (BitConverter.UInt32BitsToSingle(0b0_00000000_10000110111111111111111), - UInt16BitsToBFloat16(0b0_00000000_1000011)), // subnormal - ULP rounds down + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000011)), // subnormal - ULP rounds down (BitConverter.UInt32BitsToSingle(0b1_00000000_10000110111111111111111), - UInt16BitsToBFloat16(0b1_00000000_1000011)), // neg subnormal + ULP rounds higher + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000011)), // neg subnormal + ULP rounds higher (BitConverter.UInt32BitsToSingle(0b1_00000000_10000111000000000000000), - UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal rounds to even (BitConverter.UInt32BitsToSingle(0b1_00000000_10000111000000000000001), - UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal - ULP rounds lower, + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal - ULP rounds lower, (BitConverter.UInt32BitsToSingle(0b0_00000000_00000000110000000000000), - UInt16BitsToBFloat16(0b0_00000000_0000000)), // (BFloat16 minimum subnormal / 2) should underflow to zero + BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000000)), // (BFloat16 minimum subnormal / 2) should underflow to zero }; foreach ((float original, BFloat16 expected) in data) @@ -553,71 +548,71 @@ public static IEnumerable ExplicitConversion_FromDouble_TestData() { (double, BFloat16)[] data = { - (Math.PI, UInt16BitsToBFloat16(0b0_10000000_1001001)), // 3.140625 - (Math.E, UInt16BitsToBFloat16(0b0_10000000_0101110)), // 2.71875 - (-Math.PI, UInt16BitsToBFloat16(0b1_10000000_1001001)), // -3.140625 - (-Math.E, UInt16BitsToBFloat16(0b1_10000000_0101110)), // -2.71875 + (Math.PI, BitConverter.UInt16BitsToBFloat16(0b0_10000000_1001001)), // 3.140625 + (Math.E, BitConverter.UInt16BitsToBFloat16(0b0_10000000_0101110)), // 2.71875 + (-Math.PI, BitConverter.UInt16BitsToBFloat16(0b1_10000000_1001001)), // -3.140625 + (-Math.E, BitConverter.UInt16BitsToBFloat16(0b1_10000000_0101110)), // -2.71875 (double.MaxValue, BFloat16.PositiveInfinity), // Overflow (double.MinValue, BFloat16.NegativeInfinity), // Overflow (double.PositiveInfinity, BFloat16.PositiveInfinity), // Overflow (double.NegativeInfinity, BFloat16.NegativeInfinity), // Overflow (double.NaN, BFloat16.NaN), // Quiet Negative NaN - (BitConverter.UInt64BitsToDouble(0x7FF80000_00000000), UInt16BitsToBFloat16(0b0_11111111_1000000)), // Quiet Positive NaN - (BitConverter.UInt64BitsToDouble(0xFFFAAAAA_AAAAAAAA), UInt16BitsToBFloat16(0b1_11111111_1010101)), // Signalling Negative NaN - (BitConverter.UInt64BitsToDouble(0x7FFAAAAA_AAAAAAAA), UInt16BitsToBFloat16(0b0_11111111_1010101)), // Signalling Positive NaN - (double.Epsilon, UInt16BitsToBFloat16(0)), // Underflow - (-double.Epsilon, UInt16BitsToBFloat16(0b1_00000000_0000000)), // Underflow - (1f, UInt16BitsToBFloat16(0b0_01111111_0000000)), // 1 - (-1d, UInt16BitsToBFloat16(0b1_01111111_0000000)), // -1 - (0d, UInt16BitsToBFloat16(0)), // 0 - (-0d, UInt16BitsToBFloat16(0b1_00000000_0000000)), // -0 - (42d, UInt16BitsToBFloat16(0b0_10000100_0101000)), // 42 - (-42d, UInt16BitsToBFloat16(0b1_10000100_0101000)), // -42 - (0.1d, UInt16BitsToBFloat16(0b0_01111011_1001101)), // 0.10009765625 - (-0.1d, UInt16BitsToBFloat16(0b1_01111011_1001101)), // -0.10009765625 - (1.5d, UInt16BitsToBFloat16(0b0_01111111_1000000)), // 1.5 - (-1.5d, UInt16BitsToBFloat16(0b1_01111111_1000000)), // -1.5 - (1.5078125d, UInt16BitsToBFloat16(0b0_01111111_1000001)), // 1.5078125 - (-1.5078125d, UInt16BitsToBFloat16(0b1_01111111_1000001)), // -1.5078125 - (BitConverter.UInt64BitsToDouble(0x3810000000000000), UInt16BitsToBFloat16(0b0_00000001_0000000)), // smallest normal - (BitConverter.UInt64BitsToDouble(0x380FC00000000000), UInt16BitsToBFloat16(0b0_00000000_1111111)), // largest subnormal - (BitConverter.UInt64BitsToDouble(0x3800000000000000), UInt16BitsToBFloat16(0b0_00000000_1000000)), // middle subnormal - (BitConverter.UInt64BitsToDouble(0x37FF800000000000), UInt16BitsToBFloat16(0b0_00000000_0111111)), // just below middle subnormal - (BitConverter.UInt64BitsToDouble(0x37A0000000000000), UInt16BitsToBFloat16(0b0_00000000_0000001)), // smallest subnormal - (BitConverter.UInt64BitsToDouble(0xB7A0000000000000), UInt16BitsToBFloat16(0b1_00000000_0000001)), // highest negative subnormal - (BitConverter.UInt64BitsToDouble(0xB7FF800000000000), UInt16BitsToBFloat16(0b1_00000000_0111111)), // just above negative middle subnormal - (BitConverter.UInt64BitsToDouble(0xB800000000000000), UInt16BitsToBFloat16(0b1_00000000_1000000)), // negative middle subnormal - (BitConverter.UInt64BitsToDouble(0xB80FC00000000000), UInt16BitsToBFloat16(0b1_00000000_1111111)), // lowest negative subnormal - (BitConverter.UInt64BitsToDouble(0xB810000000000000), UInt16BitsToBFloat16(0b1_00000001_0000000)), // highest negative normal + (BitConverter.UInt64BitsToDouble(0x7FF80000_00000000), BitConverter.UInt16BitsToBFloat16(0b0_11111111_1000000)), // Quiet Positive NaN + (BitConverter.UInt64BitsToDouble(0xFFFAAAAA_AAAAAAAA), BitConverter.UInt16BitsToBFloat16(0b1_11111111_1010101)), // Signalling Negative NaN + (BitConverter.UInt64BitsToDouble(0x7FFAAAAA_AAAAAAAA), BitConverter.UInt16BitsToBFloat16(0b0_11111111_1010101)), // Signalling Positive NaN + (double.Epsilon, BitConverter.UInt16BitsToBFloat16(0)), // Underflow + (-double.Epsilon, BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000)), // Underflow + (1f, BitConverter.UInt16BitsToBFloat16(0b0_01111111_0000000)), // 1 + (-1d, BitConverter.UInt16BitsToBFloat16(0b1_01111111_0000000)), // -1 + (0d, BitConverter.UInt16BitsToBFloat16(0)), // 0 + (-0d, BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000)), // -0 + (42d, BitConverter.UInt16BitsToBFloat16(0b0_10000100_0101000)), // 42 + (-42d, BitConverter.UInt16BitsToBFloat16(0b1_10000100_0101000)), // -42 + (0.1d, BitConverter.UInt16BitsToBFloat16(0b0_01111011_1001101)), // 0.10009765625 + (-0.1d, BitConverter.UInt16BitsToBFloat16(0b1_01111011_1001101)), // -0.10009765625 + (1.5d, BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000000)), // 1.5 + (-1.5d, BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000000)), // -1.5 + (1.5078125d, BitConverter.UInt16BitsToBFloat16(0b0_01111111_1000001)), // 1.5078125 + (-1.5078125d, BitConverter.UInt16BitsToBFloat16(0b1_01111111_1000001)), // -1.5078125 + (BitConverter.UInt64BitsToDouble(0x3810000000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000001_0000000)), // smallest normal + (BitConverter.UInt64BitsToDouble(0x380FC00000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_1111111)), // largest subnormal + (BitConverter.UInt64BitsToDouble(0x3800000000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000000)), // middle subnormal + (BitConverter.UInt64BitsToDouble(0x37FF800000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_0111111)), // just below middle subnormal + (BitConverter.UInt64BitsToDouble(0x37A0000000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000001)), // smallest subnormal + (BitConverter.UInt64BitsToDouble(0xB7A0000000000000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000001)), // highest negative subnormal + (BitConverter.UInt64BitsToDouble(0xB7FF800000000000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_0111111)), // just above negative middle subnormal + (BitConverter.UInt64BitsToDouble(0xB800000000000000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000000)), // negative middle subnormal + (BitConverter.UInt64BitsToDouble(0xB80FC00000000000), BitConverter.UInt16BitsToBFloat16(0b1_00000000_1111111)), // lowest negative subnormal + (BitConverter.UInt64BitsToDouble(0xB810000000000000), BitConverter.UInt16BitsToBFloat16(0b1_00000001_0000000)), // highest negative normal (BitConverter.UInt64BitsToDouble(0x4090700000000001), - UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052+ULP rounds up + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052+ULP rounds up (BitConverter.UInt64BitsToDouble(0x4090700000000000), - UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052 rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000100)), // 1052 rounds to even (BitConverter.UInt64BitsToDouble(0x40906FFFFFFFFFFF), - UInt16BitsToBFloat16(0b0_10001001_0000011)), // 1052-ULP rounds down + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000011)), // 1052-ULP rounds down (BitConverter.UInt64BitsToDouble(0x4090500000000000), - UInt16BitsToBFloat16(0b0_10001001_0000010)), // 1044 rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_10001001_0000010)), // 1044 rounds to even (BitConverter.UInt64BitsToDouble(0xC0906FFFFFFFFFFF), - UInt16BitsToBFloat16(0b1_10001001_0000011)), // -1052+ULP rounds towards zero + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000011)), // -1052+ULP rounds towards zero (BitConverter.UInt64BitsToDouble(0xC090700000000000), - UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052 rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052 rounds to even (BitConverter.UInt64BitsToDouble(0xC090700000000001), - UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052-ULP rounds away from zero + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000100)), // -1052-ULP rounds away from zero (BitConverter.UInt64BitsToDouble(0xC090500000000000), - UInt16BitsToBFloat16(0b1_10001001_0000010)), // -1044 rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_10001001_0000010)), // -1044 rounds to even (BitConverter.UInt64BitsToDouble(0x3800E00000000001), - UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal + ULP rounds up + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal + ULP rounds up (BitConverter.UInt64BitsToDouble(0x3800E00000000000), - UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal rounds to even + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000100)), // subnormal rounds to even (BitConverter.UInt64BitsToDouble(0x3800DFFFFFFFFFFF), - UInt16BitsToBFloat16(0b0_00000000_1000011)), // subnormal - ULP rounds down + BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000011)), // subnormal - ULP rounds down (BitConverter.UInt64BitsToDouble(0xB800DFFFFFFFFFFF), - UInt16BitsToBFloat16(0b1_00000000_1000011)), // neg subnormal + ULP rounds higher + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000011)), // neg subnormal + ULP rounds higher (BitConverter.UInt64BitsToDouble(0xB800E00000000000), - UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal rounds to even + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal rounds to even (BitConverter.UInt64BitsToDouble(0xB800E00000000001), - UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal - ULP rounds lower - (BitConverter.UInt64BitsToDouble(0x3788000000000000), UInt16BitsToBFloat16(0b0_00000000_0000000)), // (BFloat16 minimum subnormal / 2) should underflow to zero + BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000100)), // neg subnormal - ULP rounds lower + (BitConverter.UInt64BitsToDouble(0x3788000000000000), BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000000)), // (BFloat16 minimum subnormal / 2) should underflow to zero }; foreach ((double original, BFloat16 expected) in data) @@ -638,20 +633,20 @@ public static IEnumerable ExplicitConversion_FromInt32_TestData() { (int, BFloat16)[] data = { - (-0x103_0001, UInt16BitsToBFloat16(0xCB82)), // -16973824 - 1 rounds lower - (-0x103_0000, UInt16BitsToBFloat16(0xCB82)), // -16973824 rounds to even - (-0x102_FFFF, UInt16BitsToBFloat16(0xCB81)), // -16973824 + 1 rounds higher - (-0x101_0001, UInt16BitsToBFloat16(0xCB81)), // -16842752 - 1 rounds lower - (-0x101_0000, UInt16BitsToBFloat16(0xCB80)), // -16842752 rounds to even - (-0x100_FFFF, UInt16BitsToBFloat16(0xCB80)), // -16842752 + 1 rounds higher + (-0x103_0001, BitConverter.UInt16BitsToBFloat16(0xCB82)), // -16973824 - 1 rounds lower + (-0x103_0000, BitConverter.UInt16BitsToBFloat16(0xCB82)), // -16973824 rounds to even + (-0x102_FFFF, BitConverter.UInt16BitsToBFloat16(0xCB81)), // -16973824 + 1 rounds higher + (-0x101_0001, BitConverter.UInt16BitsToBFloat16(0xCB81)), // -16842752 - 1 rounds lower + (-0x101_0000, BitConverter.UInt16BitsToBFloat16(0xCB80)), // -16842752 rounds to even + (-0x100_FFFF, BitConverter.UInt16BitsToBFloat16(0xCB80)), // -16842752 + 1 rounds higher (0, BFloat16.Zero), - (0x100_FFFF, UInt16BitsToBFloat16(0x4B80)), // 16842752 - 1 rounds lower - (0x101_0000, UInt16BitsToBFloat16(0x4B80)), // 16842752 rounds to even - (0x101_0001, UInt16BitsToBFloat16(0x4B81)), // 16842752 + 1 rounds higher - (0x102_FFFF, UInt16BitsToBFloat16(0x4B81)), // 16973824 - 1 rounds lower - (0x103_0000, UInt16BitsToBFloat16(0x4B82)), // 16973824 rounds to even - (0x103_0001, UInt16BitsToBFloat16(0x4B82)), // 16973824 + 1 rounds higher - (int.MinValue, UInt16BitsToBFloat16(0xCF00)), + (0x100_FFFF, BitConverter.UInt16BitsToBFloat16(0x4B80)), // 16842752 - 1 rounds lower + (0x101_0000, BitConverter.UInt16BitsToBFloat16(0x4B80)), // 16842752 rounds to even + (0x101_0001, BitConverter.UInt16BitsToBFloat16(0x4B81)), // 16842752 + 1 rounds higher + (0x102_FFFF, BitConverter.UInt16BitsToBFloat16(0x4B81)), // 16973824 - 1 rounds lower + (0x103_0000, BitConverter.UInt16BitsToBFloat16(0x4B82)), // 16973824 rounds to even + (0x103_0001, BitConverter.UInt16BitsToBFloat16(0x4B82)), // 16973824 + 1 rounds higher + (int.MinValue, BitConverter.UInt16BitsToBFloat16(0xCF00)), }; foreach ((int original, BFloat16 expected) in data) @@ -673,17 +668,17 @@ public static IEnumerable ExplicitConversion_FromUInt32_TestData() (uint, BFloat16)[] data = { (0, BFloat16.Zero), - (0x100_FFFF, UInt16BitsToBFloat16(0x4B80)), // 16842752 - 1 rounds lower - (0x101_0000, UInt16BitsToBFloat16(0x4B80)), // 16842752 rounds to even - (0x101_0001, UInt16BitsToBFloat16(0x4B81)), // 16842752 + 1 rounds higher - (0x102_FFFF, UInt16BitsToBFloat16(0x4B81)), // 16973824 - 1 rounds lower - (0x103_0000, UInt16BitsToBFloat16(0x4B82)), // 16973824 rounds to even - (0x103_0001, UInt16BitsToBFloat16(0x4B82)), // 16973824 + 1 rounds higher - (0x8000_0000, UInt16BitsToBFloat16(0x4F00)), - (0xFF7F_FFFF, UInt16BitsToBFloat16(0x4F7F)), // 4286578688 - 1 rounds lower - (0xFF80_0000, UInt16BitsToBFloat16(0x4F80)), // 4286578688 rounds to even - (0xFF80_0001, UInt16BitsToBFloat16(0x4F80)), // 4286578688 + 1 rounds higher - (0xFFFF_FFFF, UInt16BitsToBFloat16(0x4F80)), + (0x100_FFFF, BitConverter.UInt16BitsToBFloat16(0x4B80)), // 16842752 - 1 rounds lower + (0x101_0000, BitConverter.UInt16BitsToBFloat16(0x4B80)), // 16842752 rounds to even + (0x101_0001, BitConverter.UInt16BitsToBFloat16(0x4B81)), // 16842752 + 1 rounds higher + (0x102_FFFF, BitConverter.UInt16BitsToBFloat16(0x4B81)), // 16973824 - 1 rounds lower + (0x103_0000, BitConverter.UInt16BitsToBFloat16(0x4B82)), // 16973824 rounds to even + (0x103_0001, BitConverter.UInt16BitsToBFloat16(0x4B82)), // 16973824 + 1 rounds higher + (0x8000_0000, BitConverter.UInt16BitsToBFloat16(0x4F00)), + (0xFF7F_FFFF, BitConverter.UInt16BitsToBFloat16(0x4F7F)), // 4286578688 - 1 rounds lower + (0xFF80_0000, BitConverter.UInt16BitsToBFloat16(0x4F80)), // 4286578688 rounds to even + (0xFF80_0001, BitConverter.UInt16BitsToBFloat16(0x4F80)), // 4286578688 + 1 rounds higher + (0xFFFF_FFFF, BitConverter.UInt16BitsToBFloat16(0x4F80)), }; foreach ((uint original, BFloat16 expected) in data) @@ -1136,16 +1131,16 @@ public static IEnumerable ToStringRoundtrip_TestData() yield return new object[] { BFloat16.MaxValue }; yield return new object[] { BFloat16.PositiveInfinity }; - yield return new object[] { (UInt16BitsToBFloat16(0b0_00000001_0000000)) }; // smallest normal - yield return new object[] { (UInt16BitsToBFloat16(0b0_00000000_1111111)) }; // largest subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b0_00000000_1000000)) }; // middle subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b0_00000000_0111111)) }; // just below middle subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b0_00000000_0000000)) }; // smallest subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b1_00000000_0000000)) }; // highest negative subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b1_00000000_0111111)) }; // just above negative middle subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b1_00000000_1000000)) }; // negative middle subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b1_00000000_1111111)) }; // lowest negative subnormal - yield return new object[] { (UInt16BitsToBFloat16(0b1_00000001_0000000)) }; // highest negative normal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b0_00000001_0000000)) }; // smallest normal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1111111)) }; // largest subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b0_00000000_1000000)) }; // middle subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0111111)) }; // just below middle subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b0_00000000_0000000)) }; // smallest subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0000000)) }; // highest negative subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b1_00000000_0111111)) }; // just above negative middle subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1000000)) }; // negative middle subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b1_00000000_1111111)) }; // lowest negative subnormal + yield return new object[] { (BitConverter.UInt16BitsToBFloat16(0b1_00000001_0000000)) }; // highest negative normal } [Theory] @@ -2078,37 +2073,37 @@ public static void TanPiTest(BFloat16 value, BFloat16 expectedResult, BFloat16 a public static IEnumerable BitDecrement_TestData() { yield return new object[] { BFloat16.NegativeInfinity, BFloat16.NegativeInfinity }; - yield return new object[] { UInt16BitsToBFloat16(0xC049), UInt16BitsToBFloat16(0xC04A) }; // value: -(pi) - yield return new object[] { UInt16BitsToBFloat16(0xC02E), UInt16BitsToBFloat16(0xC02F) }; // value: -(e) - yield return new object[] { UInt16BitsToBFloat16(0xC013), UInt16BitsToBFloat16(0xC014) }; // value: -(ln(10)) - yield return new object[] { UInt16BitsToBFloat16(0xBFC9), UInt16BitsToBFloat16(0xBFCA) }; // value: -(pi / 2) - yield return new object[] { UInt16BitsToBFloat16(0xBFB9), UInt16BitsToBFloat16(0xBFBA) }; // value: -(log2(e)) - yield return new object[] { UInt16BitsToBFloat16(0xBFB5), UInt16BitsToBFloat16(0xBFB6) }; // value: -(sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF90), UInt16BitsToBFloat16(0xBF91) }; // value: -(2 / sqrt(pi)) - yield return new object[] { UInt16BitsToBFloat16(0xBF80), UInt16BitsToBFloat16(0xBF81) }; - yield return new object[] { UInt16BitsToBFloat16(0xBF49), UInt16BitsToBFloat16(0xBF4A) }; // value: -(pi / 4) - yield return new object[] { UInt16BitsToBFloat16(0xBF35), UInt16BitsToBFloat16(0xBF36) }; // value: -(1 / sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF31), UInt16BitsToBFloat16(0xBF32) }; // value: -(ln(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF23), UInt16BitsToBFloat16(0xBF24) }; // value: -(2 / pi) - yield return new object[] { UInt16BitsToBFloat16(0xBEDE), UInt16BitsToBFloat16(0xBEDF) }; // value: -(log10(e)) - yield return new object[] { UInt16BitsToBFloat16(0xBEA3), UInt16BitsToBFloat16(0xBEA4) }; // value: -(1 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x8000), -BFloat16.Epsilon }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC049), BitConverter.UInt16BitsToBFloat16(0xC04A) }; // value: -(pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC02E), BitConverter.UInt16BitsToBFloat16(0xC02F) }; // value: -(e) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC013), BitConverter.UInt16BitsToBFloat16(0xC014) }; // value: -(ln(10)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFC9), BitConverter.UInt16BitsToBFloat16(0xBFCA) }; // value: -(pi / 2) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFB9), BitConverter.UInt16BitsToBFloat16(0xBFBA) }; // value: -(log2(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFB5), BitConverter.UInt16BitsToBFloat16(0xBFB6) }; // value: -(sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF90), BitConverter.UInt16BitsToBFloat16(0xBF91) }; // value: -(2 / sqrt(pi)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF80), BitConverter.UInt16BitsToBFloat16(0xBF81) }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF49), BitConverter.UInt16BitsToBFloat16(0xBF4A) }; // value: -(pi / 4) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF35), BitConverter.UInt16BitsToBFloat16(0xBF36) }; // value: -(1 / sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF31), BitConverter.UInt16BitsToBFloat16(0xBF32) }; // value: -(ln(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF23), BitConverter.UInt16BitsToBFloat16(0xBF24) }; // value: -(2 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBEDE), BitConverter.UInt16BitsToBFloat16(0xBEDF) }; // value: -(log10(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBEA3), BitConverter.UInt16BitsToBFloat16(0xBEA4) }; // value: -(1 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), -BFloat16.Epsilon }; yield return new object[] { BFloat16.NaN, BFloat16.NaN }; - yield return new object[] { UInt16BitsToBFloat16(0x0000), -BFloat16.Epsilon }; - yield return new object[] { UInt16BitsToBFloat16(0x3EA3), UInt16BitsToBFloat16(0x3EA2) }; // value: (1 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x3EDE), UInt16BitsToBFloat16(0x3EDD) }; // value: (log10(e)) - yield return new object[] { UInt16BitsToBFloat16(0x3F23), UInt16BitsToBFloat16(0x3F22) }; // value: (2 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x3F31), UInt16BitsToBFloat16(0x3F30) }; // value: (ln(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3F35), UInt16BitsToBFloat16(0x3F34) }; // value: (1 / sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3F49), UInt16BitsToBFloat16(0x3F48) }; // value: (pi / 4) - yield return new object[] { UInt16BitsToBFloat16(0x3F80), UInt16BitsToBFloat16(0x3F7F) }; - yield return new object[] { UInt16BitsToBFloat16(0x3F90), UInt16BitsToBFloat16(0x3F8F) }; // value: (2 / sqrt(pi)) - yield return new object[] { UInt16BitsToBFloat16(0x3FB5), UInt16BitsToBFloat16(0x3FB4) }; // value: (sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3FB9), UInt16BitsToBFloat16(0x3FB8) }; // value: (log2(e)) - yield return new object[] { UInt16BitsToBFloat16(0x3FC9), UInt16BitsToBFloat16(0x3FC8) }; // value: (pi / 2) - yield return new object[] { UInt16BitsToBFloat16(0x4013), UInt16BitsToBFloat16(0x4012) }; // value: (ln(10)) - yield return new object[] { UInt16BitsToBFloat16(0x402E), UInt16BitsToBFloat16(0x402D) }; // value: (e) - yield return new object[] { UInt16BitsToBFloat16(0x4049), UInt16BitsToBFloat16(0x4048) }; // value: (pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), -BFloat16.Epsilon }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3EA3), BitConverter.UInt16BitsToBFloat16(0x3EA2) }; // value: (1 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3EDE), BitConverter.UInt16BitsToBFloat16(0x3EDD) }; // value: (log10(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F23), BitConverter.UInt16BitsToBFloat16(0x3F22) }; // value: (2 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F31), BitConverter.UInt16BitsToBFloat16(0x3F30) }; // value: (ln(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F35), BitConverter.UInt16BitsToBFloat16(0x3F34) }; // value: (1 / sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F49), BitConverter.UInt16BitsToBFloat16(0x3F48) }; // value: (pi / 4) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F80), BitConverter.UInt16BitsToBFloat16(0x3F7F) }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F90), BitConverter.UInt16BitsToBFloat16(0x3F8F) }; // value: (2 / sqrt(pi)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FB5), BitConverter.UInt16BitsToBFloat16(0x3FB4) }; // value: (sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FB9), BitConverter.UInt16BitsToBFloat16(0x3FB8) }; // value: (log2(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FC9), BitConverter.UInt16BitsToBFloat16(0x3FC8) }; // value: (pi / 2) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x4013), BitConverter.UInt16BitsToBFloat16(0x4012) }; // value: (ln(10)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x402E), BitConverter.UInt16BitsToBFloat16(0x402D) }; // value: (e) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x4049), BitConverter.UInt16BitsToBFloat16(0x4048) }; // value: (pi) yield return new object[] { BFloat16.PositiveInfinity, BFloat16.MaxValue }; } @@ -2122,37 +2117,37 @@ public static void BitDecrement(BFloat16 value, BFloat16 expectedResult) public static IEnumerable BitIncrement_TestData() { yield return new object[] { BFloat16.NegativeInfinity, BFloat16.MinValue }; - yield return new object[] { UInt16BitsToBFloat16(0xC049), UInt16BitsToBFloat16(0xC048) }; // value: -(pi) - yield return new object[] { UInt16BitsToBFloat16(0xC02E), UInt16BitsToBFloat16(0xC02D) }; // value: -(e) - yield return new object[] { UInt16BitsToBFloat16(0xC013), UInt16BitsToBFloat16(0xC012) }; // value: -(ln(10)) - yield return new object[] { UInt16BitsToBFloat16(0xBFC9), UInt16BitsToBFloat16(0xBFC8) }; // value: -(pi / 2) - yield return new object[] { UInt16BitsToBFloat16(0xBFB9), UInt16BitsToBFloat16(0xBFB8) }; // value: -(log2(e)) - yield return new object[] { UInt16BitsToBFloat16(0xBFB5), UInt16BitsToBFloat16(0xBFB4) }; // value: -(sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF90), UInt16BitsToBFloat16(0xBF8F) }; // value: -(2 / sqrt(pi)) - yield return new object[] { UInt16BitsToBFloat16(0xBF80), UInt16BitsToBFloat16(0xBF7F) }; - yield return new object[] { UInt16BitsToBFloat16(0xBF49), UInt16BitsToBFloat16(0xBF48) }; // value: -(pi / 4) - yield return new object[] { UInt16BitsToBFloat16(0xBF35), UInt16BitsToBFloat16(0xBF34) }; // value: -(1 / sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF31), UInt16BitsToBFloat16(0xBF30) }; // value: -(ln(2)) - yield return new object[] { UInt16BitsToBFloat16(0xBF23), UInt16BitsToBFloat16(0xBF22) }; // value: -(2 / pi) - yield return new object[] { UInt16BitsToBFloat16(0xBEDE), UInt16BitsToBFloat16(0xBEDD) }; // value: -(log10(e)) - yield return new object[] { UInt16BitsToBFloat16(0xBEA3), UInt16BitsToBFloat16(0xBEA2) }; // value: -(1 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x8000), BFloat16.Epsilon }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC049), BitConverter.UInt16BitsToBFloat16(0xC048) }; // value: -(pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC02E), BitConverter.UInt16BitsToBFloat16(0xC02D) }; // value: -(e) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xC013), BitConverter.UInt16BitsToBFloat16(0xC012) }; // value: -(ln(10)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFC9), BitConverter.UInt16BitsToBFloat16(0xBFC8) }; // value: -(pi / 2) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFB9), BitConverter.UInt16BitsToBFloat16(0xBFB8) }; // value: -(log2(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBFB5), BitConverter.UInt16BitsToBFloat16(0xBFB4) }; // value: -(sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF90), BitConverter.UInt16BitsToBFloat16(0xBF8F) }; // value: -(2 / sqrt(pi)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF80), BitConverter.UInt16BitsToBFloat16(0xBF7F) }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF49), BitConverter.UInt16BitsToBFloat16(0xBF48) }; // value: -(pi / 4) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF35), BitConverter.UInt16BitsToBFloat16(0xBF34) }; // value: -(1 / sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF31), BitConverter.UInt16BitsToBFloat16(0xBF30) }; // value: -(ln(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBF23), BitConverter.UInt16BitsToBFloat16(0xBF22) }; // value: -(2 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBEDE), BitConverter.UInt16BitsToBFloat16(0xBEDD) }; // value: -(log10(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0xBEA3), BitConverter.UInt16BitsToBFloat16(0xBEA2) }; // value: -(1 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x8000), BFloat16.Epsilon }; yield return new object[] { BFloat16.NaN, BFloat16.NaN }; - yield return new object[] { UInt16BitsToBFloat16(0x0000), BFloat16.Epsilon }; - yield return new object[] { UInt16BitsToBFloat16(0x3EA3), UInt16BitsToBFloat16(0x3EA4) }; // value: (1 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x3EDE), UInt16BitsToBFloat16(0x3EDF) }; // value: (log10(e)) - yield return new object[] { UInt16BitsToBFloat16(0x3F23), UInt16BitsToBFloat16(0x3F24) }; // value: (2 / pi) - yield return new object[] { UInt16BitsToBFloat16(0x3F31), UInt16BitsToBFloat16(0x3F32) }; // value: (ln(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3F35), UInt16BitsToBFloat16(0x3F36) }; // value: (1 / sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3F49), UInt16BitsToBFloat16(0x3F4A) }; // value: (pi / 4) - yield return new object[] { UInt16BitsToBFloat16(0x3F80), UInt16BitsToBFloat16(0x3F81) }; - yield return new object[] { UInt16BitsToBFloat16(0x3F90), UInt16BitsToBFloat16(0x3F91) }; // value: (2 / sqrt(pi)) - yield return new object[] { UInt16BitsToBFloat16(0x3FB5), UInt16BitsToBFloat16(0x3FB6) }; // value: (sqrt(2)) - yield return new object[] { UInt16BitsToBFloat16(0x3FB9), UInt16BitsToBFloat16(0x3FBA) }; // value: (log2(e)) - yield return new object[] { UInt16BitsToBFloat16(0x3FC9), UInt16BitsToBFloat16(0x3FCA) }; // value: (pi / 2) - yield return new object[] { UInt16BitsToBFloat16(0x4013), UInt16BitsToBFloat16(0x4014) }; // value: (ln(10)) - yield return new object[] { UInt16BitsToBFloat16(0x402E), UInt16BitsToBFloat16(0x402F) }; // value: (e) - yield return new object[] { UInt16BitsToBFloat16(0x4049), UInt16BitsToBFloat16(0x404A) }; // value: (pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x0000), BFloat16.Epsilon }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3EA3), BitConverter.UInt16BitsToBFloat16(0x3EA4) }; // value: (1 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3EDE), BitConverter.UInt16BitsToBFloat16(0x3EDF) }; // value: (log10(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F23), BitConverter.UInt16BitsToBFloat16(0x3F24) }; // value: (2 / pi) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F31), BitConverter.UInt16BitsToBFloat16(0x3F32) }; // value: (ln(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F35), BitConverter.UInt16BitsToBFloat16(0x3F36) }; // value: (1 / sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F49), BitConverter.UInt16BitsToBFloat16(0x3F4A) }; // value: (pi / 4) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F80), BitConverter.UInt16BitsToBFloat16(0x3F81) }; + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3F90), BitConverter.UInt16BitsToBFloat16(0x3F91) }; // value: (2 / sqrt(pi)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FB5), BitConverter.UInt16BitsToBFloat16(0x3FB6) }; // value: (sqrt(2)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FB9), BitConverter.UInt16BitsToBFloat16(0x3FBA) }; // value: (log2(e)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x3FC9), BitConverter.UInt16BitsToBFloat16(0x3FCA) }; // value: (pi / 2) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x4013), BitConverter.UInt16BitsToBFloat16(0x4014) }; // value: (ln(10)) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x402E), BitConverter.UInt16BitsToBFloat16(0x402F) }; // value: (e) + yield return new object[] { BitConverter.UInt16BitsToBFloat16(0x4049), BitConverter.UInt16BitsToBFloat16(0x404A) }; // value: (pi) yield return new object[] { BFloat16.PositiveInfinity, BFloat16.PositiveInfinity }; } @@ -2279,12 +2274,12 @@ public static void RadiansToDegreesTest(BFloat16 value, BFloat16 expectedResult, #region AssertExtentions static bool IsNegativeZero(BFloat16 value) { - return BFloat16ToUInt16Bits(value) == 0x8000; + return BitConverter.BFloat16ToUInt16Bits(value) == 0x8000; } static bool IsPositiveZero(BFloat16 value) { - return BFloat16ToUInt16Bits(value) == 0; + return BitConverter.BFloat16ToUInt16Bits(value) == 0; } static string ToStringPadded(BFloat16 value) @@ -2321,7 +2316,7 @@ static string ToStringPadded(BFloat16 value) /// Thrown when the representations are not identical private static void AssertEqual(BFloat16 expected, BFloat16 actual) { - if (BFloat16ToUInt16Bits(expected) == BFloat16ToUInt16Bits(actual)) + if (BitConverter.BFloat16ToUInt16Bits(expected) == BitConverter.BFloat16ToUInt16Bits(actual)) { return; }