DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="5.12.1" />

 BinaryTransformations

public static class 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(); } } }