namespace System.Buffers
{
- internal sealed class IndexOfAnyAsciiByteValues<TOptimizations> : IndexOfAnyValues<byte>
- where TOptimizations : struct, IndexOfAnyAsciiSearcher.IOptimizations
+ internal sealed class IndexOfAnyAsciiByteValues : IndexOfAnyValues<byte>
{
private readonly Vector128<byte> _bitmap;
private readonly BitVector256 _lookup;
- public IndexOfAnyAsciiByteValues(Vector128<byte> bitmap, BitVector256 lookup)
- {
- _bitmap = bitmap;
- _lookup = lookup;
- }
+ public IndexOfAnyAsciiByteValues(ReadOnlySpan<byte> values) =>
+ IndexOfAnyAsciiSearcher.ComputeBitmap(values, out _bitmap, out _lookup);
internal override byte[] GetValues() => _lookup.GetByteValues();
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
{
return IndexOfAnyAsciiSearcher.IsVectorizationSupported && searchSpaceLength >= sizeof(ulong)
- ? IndexOfAnyAsciiSearcher.IndexOfAnyVectorized<TNegator, TOptimizations>(ref searchSpace, searchSpaceLength, _bitmap)
+ ? IndexOfAnyAsciiSearcher.IndexOfAnyVectorized<TNegator>(ref searchSpace, searchSpaceLength, _bitmap)
: IndexOfAnyScalar<TNegator>(ref searchSpace, searchSpaceLength);
}
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
{
return IndexOfAnyAsciiSearcher.IsVectorizationSupported && searchSpaceLength >= sizeof(ulong)
- ? IndexOfAnyAsciiSearcher.LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref searchSpace, searchSpaceLength, _bitmap)
+ ? IndexOfAnyAsciiSearcher.LastIndexOfAnyVectorized<TNegator>(ref searchSpace, searchSpaceLength, _bitmap)
: LastIndexOfAnyScalar<TNegator>(ref searchSpace, searchSpaceLength);
}
return -1;
}
- internal static int IndexOfAnyVectorized<TNegator, TOptimizations>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
+ internal static int IndexOfAnyVectorized<TNegator>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
where TNegator : struct, INegator
- where TOptimizations : struct, IOptimizations
{
ref byte currentSearchSpace = ref searchSpace;
{
Vector256<byte> source = Vector256.LoadUnsafe(ref currentSearchSpace);
- Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
+ Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
if (result != Vector256<byte>.Zero)
{
return ComputeFirstIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
Vector128<byte> source1 = Vector128.LoadUnsafe(ref halfVectorAwayFromEnd);
Vector256<byte> source = Vector256.Create(source0, source1);
- Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
+ Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
if (result != Vector256<byte>.Zero)
{
return ComputeFirstIndexOverlapped<byte, TNegator>(ref searchSpace, ref firstVector, ref halfVectorAwayFromEnd, result);
{
Vector128<byte> source = Vector128.LoadUnsafe(ref currentSearchSpace);
- Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
+ Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
if (result != Vector128<byte>.Zero)
{
return ComputeFirstIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
ulong source1 = Unsafe.ReadUnaligned<ulong>(ref halfVectorAwayFromEnd);
Vector128<byte> source = Vector128.Create(source0, source1).AsByte();
- Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
+ Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
if (result != Vector128<byte>.Zero)
{
return ComputeFirstIndexOverlapped<byte, TNegator>(ref searchSpace, ref firstVector, ref halfVectorAwayFromEnd, result);
return -1;
}
- internal static int LastIndexOfAnyVectorized<TNegator, TOptimizations>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
+ internal static int LastIndexOfAnyVectorized<TNegator>(ref byte searchSpace, int searchSpaceLength, Vector128<byte> bitmap)
where TNegator : struct, INegator
- where TOptimizations : struct, IOptimizations
{
ref byte currentSearchSpace = ref Unsafe.Add(ref searchSpace, searchSpaceLength);
Vector256<byte> source = Vector256.LoadUnsafe(ref currentSearchSpace);
- Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
+ Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
if (result != Vector256<byte>.Zero)
{
return ComputeLastIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
Vector128<byte> source1 = Vector128.LoadUnsafe(ref secondVector);
Vector256<byte> source = Vector256.Create(source0, source1);
- Vector256<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap256);
+ Vector256<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap256));
if (result != Vector256<byte>.Zero)
{
return ComputeLastIndexOverlapped<byte, TNegator>(ref searchSpace, ref secondVector, result);
Vector128<byte> source = Vector128.LoadUnsafe(ref currentSearchSpace);
- Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
+ Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
if (result != Vector128<byte>.Zero)
{
return ComputeLastIndex<byte, TNegator>(ref searchSpace, ref currentSearchSpace, result);
ulong source1 = Unsafe.ReadUnaligned<ulong>(ref secondVector);
Vector128<byte> source = Vector128.Create(source0, source1).AsByte();
- Vector128<byte> result = IndexOfAnyLookup<TNegator, TOptimizations>(source, bitmap);
+ Vector128<byte> result = TNegator.NegateIfNeeded(IndexOfAnyLookupCore(source, bitmap));
if (result != Vector128<byte>.Zero)
{
return ComputeLastIndexOverlapped<byte, TNegator>(ref searchSpace, ref secondVector, result);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector128<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector128<byte> source, Vector128<byte> bitmapLookup)
- where TNegator : struct, INegator
- where TOptimizations : struct, IOptimizations
- {
- Vector128<byte> result = IndexOfAnyLookupCore(source, bitmapLookup);
-
- // On X86, values above 127 will map to 0. If 0 is present in the needle, we must clear the false positives.
- if (TOptimizations.NeedleContainsZero)
- {
- Vector128<byte> ascii = Vector128.LessThan(source, Vector128.Create((byte)128));
- result &= ascii;
- }
-
- return TNegator.NegateIfNeeded(result);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector128<byte> IndexOfAnyLookupCore(Vector128<byte> source, Vector128<byte> bitmapLookup)
{
// On X86, the Ssse3.Shuffle instruction will already perform an implicit 'AND 0xF' on the indices, so we can skip it.
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector256<byte> IndexOfAnyLookup<TNegator, TOptimizations>(Vector256<byte> source, Vector256<byte> bitmapLookup)
- where TNegator : struct, INegator
- where TOptimizations : struct, IOptimizations
- {
- // See comments in IndexOfAnyLookup(Vector128<byte>) above for more details.
- Vector256<byte> result = IndexOfAnyLookupCore(source, bitmapLookup);
-
- if (TOptimizations.NeedleContainsZero)
- {
- Vector256<byte> ascii = Vector256.LessThan(source, Vector256.Create((byte)128));
- result &= ascii;
- }
-
- return TNegator.NegateIfNeeded(result);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector256<byte> IndexOfAnyLookupCore(Vector256<byte> source, Vector256<byte> bitmapLookup)
{
// See comments in IndexOfAnyLookupCore(Vector128<byte>) above for more details.