SSE2.cs (4205B)
1 using Std.Clone; 2 using Std.Convert; 3 using static Std.Hashbrown.Raw.Functions; 4 using Std.Hashbrown.Raw.Bitmask; 5 using Std.Result; 6 using System; 7 using System.Runtime.CompilerServices; 8 using System.Runtime.InteropServices; 9 using System.Runtime.Intrinsics; 10 using System.Runtime.Intrinsics.X86; 11 #region Namespaces 12 namespace Std.Hashbrown.Raw.SSE2 { 13 #region Types 14 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 0, Size = 16)] 15 readonly struct Group: IClone<Group>, IInto<Group> { 16 17 #region Type-level Constructors 18 #endregion 19 20 #region Instance Constructors 21 public Group() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!"); 22 [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 internal Group(Vector128<sbyte> m128i) => _m128i = m128i; 24 #endregion 25 26 #region Type-level Fields 27 internal static readonly byte[] EMPTY_GROUP = new byte[16] { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY }; 28 internal const ulong WIDTH = 16ul; 29 internal const ushort BITMASK_MASK = 0xffff; 30 internal const ulong BITMASK_STRIDE = 1ul; 31 static readonly Vector128<sbyte> LEADING_ONE = Vector128.Create(sbyte.MinValue); 32 #endregion 33 34 #region Instance Fields 35 [FieldOffset(0)] internal readonly Vector128<sbyte> _m128i; 36 #endregion 37 38 #region Type-level Properties 39 #endregion 40 41 #region Instance Properties 42 #endregion 43 44 #region Type-level Functions 45 [MethodImpl(MethodImplOptions.AggressiveInlining)] 46 internal static unsafe Group Load(byte* ptr) => new(Sse2.LoadVector128((sbyte*)ptr)); 47 // This function is only named this for ease of compatibility with Rust's implementation. 48 // Sadly, one can't force base alignment of managed types; so we must always use unaligned instructions. 49 [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 internal static unsafe Group LoadAligned(byte* ptr) => new(Sse2.LoadVector128((sbyte*)ptr)); 51 #endregion 52 53 #region Instance Functions 54 public readonly Group Clone() => this; 55 [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 internal readonly Group ConvertSpecialToEmptyAndFullToDeleted() { 57 unsafe { 58 return new(Sse2.Or(Sse2.CompareGreaterThan(Vector128<sbyte>.Zero, _m128i), LEADING_ONE)); 59 } 60 } 61 public override readonly bool Equals(object? _) => false; 62 public override readonly int GetHashCode() => 0; 63 public readonly Group Into() => this; 64 [MethodImpl(MethodImplOptions.AggressiveInlining)] 65 internal readonly BitMask MatchByte(byte val) { 66 unsafe { 67 return new((ushort)Sse2.MoveMask(Sse2.CompareEqual(_m128i, Vector128.Create((sbyte)val)))); 68 } 69 } 70 [MethodImpl(MethodImplOptions.AggressiveInlining)] 71 internal readonly BitMask MatchEmpty() => MatchByte(EMPTY); 72 [MethodImpl(MethodImplOptions.AggressiveInlining)] 73 internal readonly BitMask MatchEmptyOrDeleted() { 74 unsafe { 75 return new((ushort)Sse2.MoveMask(_m128i)); 76 } 77 } 78 [MethodImpl(MethodImplOptions.AggressiveInlining)] 79 internal readonly BitMask MatchFull() => MatchEmptyOrDeleted().Invert(); 80 // This function is only named this for ease of compatibility with Rust's implementation. 81 // Sadly, one can't force base alignment of managed types; so we must always use unaligned instructions. 82 [MethodImpl(MethodImplOptions.AggressiveInlining)] 83 internal readonly unsafe Unit StoreAligned(byte* ptr) { 84 Sse2.Store((sbyte*)ptr, _m128i); 85 return new Unit(); 86 } 87 public override readonly string ToString() => string.Empty; 88 readonly Result<Group, Bottom> ITryInto<Group, Bottom>.TryInto() => new(this); 89 #endregion 90 91 #region Operators 92 #endregion 93 94 #region Types 95 #endregion 96 } 97 #endregion 98 99 #region Namespaces 100 #endregion 101 } 102 #endregion