BinaryTransformations
Provides various binary transformations.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers.Binary
{
public static class BinaryTransformations
{
[StructLayout(LayoutKind.Sequential, Size = 1)]
private readonly struct BitwiseAndTransformation : IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
static Vector<byte> IBinaryTransformation<Vector<byte>>.Transform(Vector<byte> x, Vector<byte> y)
{
return Vector.BitwiseAnd(x, y);
}
unsafe static UIntPtr IBinaryTransformation<UIntPtr>.Transform(UIntPtr x, UIntPtr y)
{
return (UIntPtr)(void*)((long)(ulong)x & (long)(ulong)y);
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private readonly struct BitwiseOrTransformation : IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
static Vector<byte> IBinaryTransformation<Vector<byte>>.Transform(Vector<byte> x, Vector<byte> y)
{
return Vector.BitwiseOr(x, y);
}
unsafe static UIntPtr IBinaryTransformation<UIntPtr>.Transform(UIntPtr x, UIntPtr y)
{
return (UIntPtr)(void*)((long)(ulong)x | (long)(ulong)y);
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private readonly struct BitwiseXorTransformation : IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
static Vector<byte> IBinaryTransformation<Vector<byte>>.Transform(Vector<byte> x, Vector<byte> y)
{
return Vector.Xor(x, y);
}
unsafe static UIntPtr IBinaryTransformation<UIntPtr>.Transform(UIntPtr x, UIntPtr y)
{
return (UIntPtr)(void*)((long)(ulong)x ^ (long)(ulong)y);
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private readonly struct BitwiseAndNotTransformation : IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
static Vector<byte> IBinaryTransformation<Vector<byte>>.Transform(Vector<byte> x, Vector<byte> y)
{
return Vector.AndNot(x, y);
}
unsafe static UIntPtr IBinaryTransformation<UIntPtr>.Transform(UIntPtr x, UIntPtr y)
{
return (UIntPtr)(void*)((long)(ulong)x & (long)(IntPtr)(void*)(~(ulong)y));
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private readonly struct OnesComplementTransformation : IUnaryTransformation<UIntPtr>, IUnaryTransformation<Vector<byte>>
{
static Vector<byte> IUnaryTransformation<Vector<byte>>.Transform(Vector<byte> value)
{
return Vector.OnesComplement(value);
}
unsafe static UIntPtr IUnaryTransformation<UIntPtr>.Transform(UIntPtr value)
{
return (UIntPtr)(void*)(~(ulong)value);
}
}
private interface IUnaryTransformation<[IsUnmanaged] T> where T : struct
{
T Transform(T value);
}
private interface IBinaryTransformation<[IsUnmanaged] T> where T : struct
{
T Transform(T x, T y);
}
public static void BitwiseAnd<[IsUnmanaged] T>(this ReadOnlySpan<T> x, Span<T> y) where T : struct
{
ArgumentOutOfRangeException.ThrowIfNotEqual<int>(x.Length, y.Length, "y");
Transform<T, BitwiseAndTransformation>(x, y);
}
public static void AndNot<[IsUnmanaged] T>(this ReadOnlySpan<T> x, Span<T> y) where T : struct
{
ArgumentOutOfRangeException.ThrowIfNotEqual<int>(x.Length, y.Length, "y");
Transform<T, BitwiseAndNotTransformation>(x, y);
}
public static void BitwiseOr<[IsUnmanaged] T>(this ReadOnlySpan<T> x, Span<T> y) where T : struct
{
ArgumentOutOfRangeException.ThrowIfNotEqual<int>(x.Length, y.Length, "y");
Transform<T, BitwiseOrTransformation>(x, y);
}
public static void BitwiseXor<[IsUnmanaged] T>(this ReadOnlySpan<T> x, Span<T> y) where T : struct
{
ArgumentOutOfRangeException.ThrowIfNotEqual<int>(x.Length, y.Length, "y");
Transform<T, BitwiseXorTransformation>(x, y);
}
public static void OnesComplement<[IsUnmanaged] T>(this Span<T> values) where T : struct
{
Transform<T, OnesComplementTransformation>(values);
}
private unsafe static void Transform<TTransformation>(ref byte x, int length) where TTransformation : struct, IUnaryTransformation<UIntPtr>, IUnaryTransformation<Vector<byte>>
{
if (Vector.IsHardwareAccelerated) {
while (length >= Vector<byte>.Count) {
Vector<byte> vector = ((IUnaryTransformation<Vector<byte>>)x).Transform(Unsafe.ReadUnaligned<Vector<byte>>(ref x));
Unsafe.WriteUnaligned<Vector<byte>>(ref *(byte*), vector);
ref x = ref Unsafe.Add<byte>(ref x, Vector<byte>.Count);
length -= Vector<byte>.Count;
}
}
while (length >= UIntPtr.Size) {
UIntPtr intPtr = ((IUnaryTransformation<UIntPtr>)x).Transform(Unsafe.ReadUnaligned<UIntPtr>(ref x));
Unsafe.WriteUnaligned<UIntPtr>(ref *(byte*), intPtr);
ref x = ref Unsafe.Add<byte>(ref x, UIntPtr.Size);
length -= UIntPtr.Size;
}
while (length > 0) {
byte num = (byte)(ulong)((IUnaryTransformation<UIntPtr>)x).Transform((UIntPtr)(void*)x);
*(sbyte*)(long)(IntPtr)(void*) = (sbyte)num;
ref x = ref Unsafe.Add<byte>(ref x, 1);
length--;
}
}
private unsafe static void Transform<[IsUnmanaged] T, TTransformation>(Span<T> values) where T : struct where TTransformation : struct, IUnaryTransformation<UIntPtr>, IUnaryTransformation<Vector<byte>>
{
int val = Array.get_MaxLength() / sizeof(T);
while (!values.IsEmpty) {
int num = Math.Min(val, values.Length);
Transform<TTransformation>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), num * sizeof(T));
values = values.Slice(num);
}
}
private unsafe static void Transform<TTransformation>([In] ref byte x, ref byte y, int length) where TTransformation : struct, IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
if (Vector.IsHardwareAccelerated) {
while (length >= Vector<byte>.Count) {
Vector<byte> vector = ((IBinaryTransformation<Vector<byte>>)y).Transform(Unsafe.ReadUnaligned<Vector<byte>>(ref x), Unsafe.ReadUnaligned<Vector<byte>>(ref y));
Unsafe.WriteUnaligned<Vector<byte>>(ref *(byte*), vector);
ref x = ref Unsafe.Add<byte>(ref x, Vector<byte>.Count);
ref y = ref Unsafe.Add<byte>(ref y, Vector<byte>.Count);
length -= Vector<byte>.Count;
}
}
while (length >= UIntPtr.Size) {
UIntPtr intPtr = ((IBinaryTransformation<UIntPtr>)y).Transform(Unsafe.ReadUnaligned<UIntPtr>(ref x), Unsafe.ReadUnaligned<UIntPtr>(ref y));
Unsafe.WriteUnaligned<UIntPtr>(ref *(byte*), intPtr);
ref x = ref Unsafe.Add<byte>(ref x, UIntPtr.Size);
ref y = ref Unsafe.Add<byte>(ref y, UIntPtr.Size);
length -= UIntPtr.Size;
}
while (length > 0) {
byte num = (byte)(ulong)((IBinaryTransformation<UIntPtr>)y).Transform((UIntPtr)(void*)x, (UIntPtr)(void*)y);
*(sbyte*)(long)(IntPtr)(void*) = (sbyte)num;
ref x = ref Unsafe.Add<byte>(ref x, 1);
ref y = ref Unsafe.Add<byte>(ref y, 1);
length--;
}
}
private unsafe static void Transform<[IsUnmanaged] T, TTransformation>(ReadOnlySpan<T> x, Span<T> y) where T : struct where TTransformation : struct, IBinaryTransformation<UIntPtr>, IBinaryTransformation<Vector<byte>>
{
int val = Array.get_MaxLength() / sizeof(T);
while (!x.IsEmpty) {
int num = Math.Min(val, x.Length);
Transform<TTransformation>(ref Unsafe.As<T, byte>(ref Unsafe.AsRef<T>(ref MemoryMarshal.GetReference(x))), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(y)), num * sizeof(T));
x = x.Slice(num);
y = y.Slice(num);
}
}
public static void Reverse<[IsUnmanaged] T>(ref T value) where T : struct
{
Span.AsBytes(ref value).Reverse();
}
}
}