mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 13:48:47 +00:00
feat: add Unpack for IBinaryInteger<T>
This introduces an experiment, to add support for generic math in X10D. So far, build and tests remain passing - this is a good sign. There is potential here. This API is subject to change and may be removed without warning.
This commit is contained in:
parent
3ab1ab0b41
commit
87a85b82d9
89
X10D/src/Collections/BinaryIntegerExtensions.cs
Normal file
89
X10D/src/Collections/BinaryIntegerExtensions.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
using X10D.CompilerServices;
|
||||||
|
|
||||||
|
namespace X10D.Collections;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Collection-related extension methods for <see cref="IBinaryInteger{T}" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class BinaryIntegerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <returns>An array of <see cref="bool" /> with a length equal to the size of <typeparamref name="TInteger" />.</returns>
|
||||||
|
[Pure]
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static bool[] Unpack<TInteger>(this TInteger value)
|
||||||
|
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var buffer = new bool[sizeof(TInteger) * 8];
|
||||||
|
value.Unpack(buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpacks this integer into a boolean list, treating it as a bit field.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to unpack.</param>
|
||||||
|
/// <param name="destination">When this method returns, contains the unpacked booleans from <paramref name="value" />.</param>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="destination" /> is not large enough to contain the result.</exception>
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
public static void Unpack<TInteger>(this TInteger value, Span<bool> destination)
|
||||||
|
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
if (destination.Length < sizeof(TInteger) * 8)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(ExceptionMessages.DestinationSpanLengthTooShort, nameof(destination));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case byte valueByte when Sse3.IsSupported:
|
||||||
|
valueByte.UnpackInternal_Ssse3(destination);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case int valueInt32 when Avx2.IsSupported:
|
||||||
|
valueInt32.UnpackInternal_Ssse3(destination);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case int valueInt32 when Sse3.IsSupported:
|
||||||
|
valueInt32.UnpackInternal_Ssse3(destination);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case short valueInt16 when Sse3.IsSupported:
|
||||||
|
valueInt16.UnpackInternal_Ssse3(destination);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnpackInternal_Fallback(value, destination);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
|
internal static void UnpackInternal_Fallback<TInteger>(this TInteger value, Span<bool> destination)
|
||||||
|
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
int bitCount = sizeof(TInteger) * 8;
|
||||||
|
for (var index = 0; index < bitCount; index++)
|
||||||
|
{
|
||||||
|
destination[index] = (value & (TInteger.One << index)) != TInteger.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
#if !NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
|
#endif
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using X10D.CompilerServices;
|
using X10D.CompilerServices;
|
||||||
|
|
||||||
@ -17,6 +19,7 @@ public static class ByteExtensions
|
|||||||
{
|
{
|
||||||
private const int Size = sizeof(byte) * 8;
|
private const int Size = sizeof(byte) * 8;
|
||||||
|
|
||||||
|
#if !NET7_0_OR_GREATER
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unpacks this 8-bit unsigned integer into a boolean list, treating it as a bit field.
|
/// Unpacks this 8-bit unsigned integer into a boolean list, treating it as a bit field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -56,6 +59,7 @@ public static class ByteExtensions
|
|||||||
|
|
||||||
UnpackInternal_Fallback(value, destination);
|
UnpackInternal_Fallback(value, destination);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
internal static void UnpackInternal_Fallback(this byte value, Span<bool> destination)
|
internal static void UnpackInternal_Fallback(this byte value, Span<bool> destination)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
#if !NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
|
#endif
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using X10D.CompilerServices;
|
using X10D.CompilerServices;
|
||||||
|
|
||||||
@ -17,6 +19,7 @@ public static class Int16Extensions
|
|||||||
{
|
{
|
||||||
private const int Size = sizeof(short) * 8;
|
private const int Size = sizeof(short) * 8;
|
||||||
|
|
||||||
|
#if !NET7_0_OR_GREATER
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unpacks this 16-bit signed integer into a boolean list, treating it as a bit field.
|
/// Unpacks this 16-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -56,6 +59,7 @@ public static class Int16Extensions
|
|||||||
|
|
||||||
UnpackInternal_Fallback(value, destination);
|
UnpackInternal_Fallback(value, destination);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
internal static void UnpackInternal_Fallback(this short value, Span<bool> destination)
|
internal static void UnpackInternal_Fallback(this short value, Span<bool> destination)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
#if !NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
|
#endif
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using X10D.CompilerServices;
|
using X10D.CompilerServices;
|
||||||
|
|
||||||
@ -17,6 +19,7 @@ public static class Int32Extensions
|
|||||||
{
|
{
|
||||||
private const int Size = sizeof(int) * 8;
|
private const int Size = sizeof(int) * 8;
|
||||||
|
|
||||||
|
#if !NET7_0_OR_GREATER
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unpacks this 32-bit signed integer into a boolean list, treating it as a bit field.
|
/// Unpacks this 32-bit signed integer into a boolean list, treating it as a bit field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -62,6 +65,7 @@ public static class Int32Extensions
|
|||||||
|
|
||||||
UnpackInternal_Fallback(value, destination);
|
UnpackInternal_Fallback(value, destination);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[MethodImpl(CompilerResources.MethodImplOptions)]
|
[MethodImpl(CompilerResources.MethodImplOptions)]
|
||||||
internal static void UnpackInternal_Fallback(this int value, Span<bool> destination)
|
internal static void UnpackInternal_Fallback(this int value, Span<bool> destination)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics.Contracts;
|
#if !NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
|
||||||
namespace X10D.Collections;
|
namespace X10D.Collections;
|
||||||
|
|
||||||
@ -41,3 +42,4 @@ public static class Int64Extensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user