Skip to content

Instantly share code, notes, and snippets.

@hypeartist
Created January 10, 2020 19:56
Show Gist options
  • Save hypeartist/19124f0e1e2214f37223df87d9f7a981 to your computer and use it in GitHub Desktop.
Save hypeartist/19124f0e1e2214f37223df87d9f7a981 to your computer and use it in GitHub Desktop.
.NET Core 3.1, IndexOf(char)
internal static unsafe class Intrinsics
{
private static ReadOnlySpan<byte> TrailingZeroCountDeBruijnTable => new byte[]
{
00, 01, 28, 02, 29, 14, 24, 03,
30, 22, 20, 15, 25, 17, 04, 08,
31, 27, 13, 23, 21, 19, 16, 07,
26, 12, 18, 06, 11, 05, 10, 09
};
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static int IndexOf(char* chars, int charCount, char c)
{
const int charsPerPass = 8; // Vector128<ushort>.Count
var charsStart = chars;
var stopChar = chars + (charCount & 0b_1111_1111_1111_1111_1111_1111_1111_1000);
var endChar = stopChar + (charCount & 0b_0111);
var vC = Vector128.Create(c);
while (chars != stopChar)
{
var vChars = Sse2.LoadVector128((ushort*) chars);
var vCompRes = Sse2.CompareEqual(vChars, vC);
var hitsBitMask = Sse2.MoveMask(Sse2.ShiftRightLogical(vCompRes, 8).AsByte());
if (hitsBitMask != 0)
{
if (Bmi1.IsSupported)
{
return (int) (chars - charsStart + (Bmi1.TrailingZeroCount((uint) hitsBitMask) >> 1));
}
return (int) (chars - charsStart) + (TrailingZeroCountDeBruijnTable[(int) ((uint)((hitsBitMask & -hitsBitMask) * 0x077CB531U) >> 27)] >> 1);
}
chars += charsPerPass;
}
while (chars != endChar)
{
if (*chars == c)
{
return (int) (chars - charsStart);
}
chars++;
}
return -1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment