Skip to content

Commit

Permalink
Refactor double Read/Write implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
xtqqczze committed Dec 23, 2024
1 parent 208b974 commit b19bea6
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ public static partial class BinaryPrimitives
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="source"/> is too small to contain a <see cref="double" />.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ReadDoubleBigEndian(ReadOnlySpan<byte> source)
{
return BitConverter.IsLittleEndian ?
BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read<long>(source))) :
MemoryMarshal.Read<double>(source);
}
public static double ReadDoubleBigEndian(ReadOnlySpan<byte> source) => double.ReadBigEndian(source);

/// <summary>
/// Reads a <see cref="Half" /> from the beginning of a read-only span of bytes, as big endian.
Expand Down Expand Up @@ -243,18 +237,7 @@ public static nuint ReadUIntPtrBigEndian(ReadOnlySpan<byte> source)
/// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
/// </returns>
/// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryReadDoubleBigEndian(ReadOnlySpan<byte> 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<byte> source, out double value) => double.TryReadBigEndian(out value, source);

/// <summary>
/// Reads a <see cref="Half" /> from the beginning of a read-only span of bytes, as big endian.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ public static partial class BinaryPrimitives
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="source"/> is too small to contain a <see cref="double" />.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ReadDoubleLittleEndian(ReadOnlySpan<byte> source)
{
return !BitConverter.IsLittleEndian ?
BitConverter.Int64BitsToDouble(ReverseEndianness(MemoryMarshal.Read<long>(source))) :
MemoryMarshal.Read<double>(source);
}
public static double ReadDoubleLittleEndian(ReadOnlySpan<byte> source) => double.ReadLittleEndian(source);

/// <summary>
/// Reads a <see cref="Half" /> from the beginning of a read-only span of bytes, as little endian.
Expand Down Expand Up @@ -243,18 +237,7 @@ public static nuint ReadUIntPtrLittleEndian(ReadOnlySpan<byte> source)
/// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
/// </returns>
/// <remarks>Reads exactly 8 bytes from the beginning of the span.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryReadDoubleLittleEndian(ReadOnlySpan<byte> 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<byte> source, out double value) => double.TryReadLittleEndian(out value, source);

/// <summary>
/// Reads a <see cref="Half" /> from the beginning of a read-only span of bytes, as little endian.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,7 @@ public static partial class BinaryPrimitives
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="destination" /> is too small to contain a <see cref="double" />.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteDoubleBigEndian(Span<byte> 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<byte> destination, double value) => double.WriteBigEndian(in value, destination);

/// <summary>
/// Writes a <see cref="Half" /> into a span of bytes, as big endian.
Expand Down Expand Up @@ -321,17 +309,7 @@ public static void WriteUIntPtrBigEndian(Span<byte> destination, nuint value)
/// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
/// </returns>
/// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryWriteDoubleBigEndian(Span<byte> 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<byte> destination, double value) => double.TryWriteBigEndian(in value, destination);

/// <summary>
/// Writes a <see cref="Half" /> into a span of bytes, as big endian.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,7 @@ public static partial class BinaryPrimitives
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="destination" /> is too small to contain a <see cref="double" />.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteDoubleLittleEndian(Span<byte> 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<byte> destination, double value) => double.WriteLittleEndian(in value, destination);

/// <summary>
/// Writes a <see cref="Half" /> into a span of bytes, as little endian.
Expand Down Expand Up @@ -321,17 +309,7 @@ public static void WriteUIntPtrLittleEndian(Span<byte> destination, nuint value)
/// <see langword="true" /> if the span is large enough to contain a <see cref="double" />; otherwise, <see langword="false" />.
/// </returns>
/// <remarks>Writes exactly 8 bytes to the beginning of the span.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryWriteDoubleLittleEndian(Span<byte> 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<byte> destination, double value) => double.TryWriteLittleEndian(in value, destination);

/// <summary>
/// Writes a <see cref="Half" /> into a span of bytes, as little endian.
Expand Down
94 changes: 94 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Double.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,100 @@ internal ulong TrailingSignificand
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ReadBigEndian(ReadOnlySpan<byte> source)
{
return BitConverter.IsLittleEndian ?
BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read<long>(source))) :
MemoryMarshal.Read<double>(source);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double ReadLittleEndian(ReadOnlySpan<byte> source)
{
return !BitConverter.IsLittleEndian ?
BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read<long>(source))) :
MemoryMarshal.Read<double>(source);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryReadBigEndian(out double value, ReadOnlySpan<byte> 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<byte> 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<byte> 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<byte> 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<byte> 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<byte> 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);
Expand Down

1 comment on commit b19bea6

@xtqqczze
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.