From 8d4addf5fdee79a7efba356f46f9eebd207e41bf Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Mon, 23 Dec 2024 11:27:28 +0000 Subject: [PATCH] Refactor `double` Read/Write implementations --- .../Binary/BinaryPrimitives.ReadBigEndian.cs | 21 +---- .../BinaryPrimitives.ReadLittleEndian.cs | 21 +---- .../Binary/BinaryPrimitives.WriteBigEndian.cs | 26 +---- .../BinaryPrimitives.WriteLittleEndian.cs | 26 +---- .../src/System/Double.cs | 94 +++++++++++++++++++ 5 files changed, 102 insertions(+), 86 deletions(-) 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 4065daf862150..eb92db4477b41 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 @@ -17,13 +17,7 @@ public static partial class BinaryPrimitives /// /// is too small to contain a . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ReadDoubleBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } + public static double ReadDoubleBigEndian(ReadOnlySpan source) => double.ReadBigEndian(source); /// /// Reads a from the beginning of a read-only span of bytes, as big endian. @@ -243,18 +237,7 @@ public static nuint ReadUIntPtrBigEndian(ReadOnlySpan source) /// if the span is large enough to contain a ; otherwise, . /// /// Reads exactly 8 bytes from the beginning of the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryReadDoubleBigEndian(ReadOnlySpan source, out double value) - { - if (BitConverter.IsLittleEndian) - { - bool success = MemoryMarshal.TryRead(source, out long tmp); - value = BitConverter.Int64BitsToDouble(ReverseEndianness(tmp)); - return success; - } - - return MemoryMarshal.TryRead(source, out value); - } + public static bool TryReadDoubleBigEndian(ReadOnlySpan source, out double value) => double.TryReadBigEndian(out value, source); /// /// 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 c21624da2aafc..a12a89b3ea862 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 @@ -17,13 +17,7 @@ public static partial class BinaryPrimitives /// /// is too small to contain a . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ReadDoubleLittleEndian(ReadOnlySpan source) - { - return !BitConverter.IsLittleEndian ? - BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } + public static double ReadDoubleLittleEndian(ReadOnlySpan source) => double.ReadLittleEndian(source); /// /// Reads a from the beginning of a read-only span of bytes, as little endian. @@ -243,18 +237,7 @@ public static nuint ReadUIntPtrLittleEndian(ReadOnlySpan source) /// if the span is large enough to contain a ; otherwise, . /// /// Reads exactly 8 bytes from the beginning of the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryReadDoubleLittleEndian(ReadOnlySpan source, out double value) - { - if (!BitConverter.IsLittleEndian) - { - bool success = MemoryMarshal.TryRead(source, out long tmp); - value = BitConverter.Int64BitsToDouble(ReverseEndianness(tmp)); - return success; - } - - return MemoryMarshal.TryRead(source, out value); - } + public static bool TryReadDoubleLittleEndian(ReadOnlySpan source, out double value) => double.TryReadLittleEndian(out value, source); /// /// 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 159ade3dbdf6f..e091a2a27ba8e 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 @@ -17,19 +17,7 @@ public static partial class BinaryPrimitives /// /// is too small to contain a . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteDoubleBigEndian(Span destination, double value) - { - if (BitConverter.IsLittleEndian) - { - long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - MemoryMarshal.Write(destination, in tmp); - } - else - { - MemoryMarshal.Write(destination, in value); - } - } + public static void WriteDoubleBigEndian(Span destination, double value) => double.WriteBigEndian(in value, destination); /// /// Writes a into a span of bytes, as big endian. @@ -321,17 +309,7 @@ public static void WriteUIntPtrBigEndian(Span destination, nuint value) /// if the span is large enough to contain a ; otherwise, . /// /// Writes exactly 8 bytes to the beginning of the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryWriteDoubleBigEndian(Span destination, double value) - { - if (BitConverter.IsLittleEndian) - { - long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - return MemoryMarshal.TryWrite(destination, in tmp); - } - - return MemoryMarshal.TryWrite(destination, in value); - } + public static bool TryWriteDoubleBigEndian(Span destination, double value) => double.TryWriteBigEndian(in value, destination); /// /// 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 5da64da58368a..0c207c0a47d21 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 @@ -17,19 +17,7 @@ public static partial class BinaryPrimitives /// /// is too small to contain a . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteDoubleLittleEndian(Span destination, double value) - { - if (!BitConverter.IsLittleEndian) - { - long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - MemoryMarshal.Write(destination, in tmp); - } - else - { - MemoryMarshal.Write(destination, in value); - } - } + public static void WriteDoubleLittleEndian(Span destination, double value) => value.WriteLittleEndian(in value, destination); /// /// Writes a into a span of bytes, as little endian. @@ -321,17 +309,7 @@ public static void WriteUIntPtrLittleEndian(Span destination, nuint value) /// if the span is large enough to contain a ; otherwise, . /// /// Writes exactly 8 bytes to the beginning of the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool TryWriteDoubleLittleEndian(Span destination, double value) - { - if (!BitConverter.IsLittleEndian) - { - long tmp = ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - return MemoryMarshal.TryWrite(destination, in tmp); - } - - return MemoryMarshal.TryWrite(destination, in value); - } + public static bool TryWriteDoubleLittleEndian(Span destination, double value) => double.TryWriteLittleEndian(in value, destination); /// /// Writes a into a span of bytes, as little endian. diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index d38c67b916b18..1887c16b8b443 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -152,6 +152,100 @@ internal ulong TrailingSignificand } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static double ReadBigEndian(ReadOnlySpan source) + { + return BitConverter.IsLittleEndian ? + BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static double ReadLittleEndian(ReadOnlySpan source) + { + return !BitConverter.IsLittleEndian ? + BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : + MemoryMarshal.Read(source); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryReadBigEndian(out double value, ReadOnlySpan source) + { + if (BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out long tmp); + value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(tmp)); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryWriteBigEndian(in double value, Span destination) + { + if (BitConverter.IsLittleEndian) + { + long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); + return MemoryMarshal.TryWrite(destination, in tmp); + } + + return MemoryMarshal.TryWrite(destination, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryReadLittleEndian(out double value, ReadOnlySpan source) + { + if (!BitConverter.IsLittleEndian) + { + bool success = MemoryMarshal.TryRead(source, out long tmp); + value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(tmp)); + return success; + } + + return MemoryMarshal.TryRead(source, out value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryWriteLittleEndian(in double value, Span destination) + { + if (!BitConverter.IsLittleEndian) + { + long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); + return MemoryMarshal.TryWrite(destination, in tmp); + } + + return MemoryMarshal.TryWrite(destination, in value); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void WriteBigEndian(in double value, Span destination) + { + if (BitConverter.IsLittleEndian) + { + long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); + MemoryMarshal.Write(destination, in tmp); + } + else + { + MemoryMarshal.Write(destination, in value); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void WriteLittleEndian(Span destination) + { + if (!BitConverter.IsLittleEndian) + { + long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(m_value)); + MemoryMarshal.Write(destination, in tmp); + } + else + { + MemoryMarshal.Write(destination, in m_value); + } + } + internal static ushort ExtractBiasedExponentFromBits(ulong bits) { return (ushort)((bits >> BiasedExponentShift) & ShiftedExponentMask);