@@ -207,116 +207,96 @@ private static bool ShouldUseSimpleLoop(int searchSpaceLength, int valuesLength)
207207 || ( searchSpaceLength < 20 && searchSpaceLength < ( valuesLength >> 1 ) ) ;
208208 }
209209
210- public static int IndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength ) =>
211- IndexOfAny < SpanHelpers . DontNegate < char > > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
212-
213- public static int IndexOfAnyExcept ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength ) =>
214- IndexOfAny < SpanHelpers . Negate < char > > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
215-
216- public static int LastIndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength ) =>
217- LastIndexOfAny < SpanHelpers . DontNegate < char > > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
218-
219- public static int LastIndexOfAnyExcept ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength ) =>
220- LastIndexOfAny < SpanHelpers . Negate < char > > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
221-
222- private static int IndexOfAny < TNegator > ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
223- where TNegator : struct , SpanHelpers . INegator < char >
210+ public static int IndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
224211 {
225212 var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
226213
227214 // If the search space is relatively short compared to the needle, do a simple O(n * m) search.
228215 if ( ShouldUseSimpleLoop ( searchSpaceLength , valuesLength ) )
229216 {
230- ref char searchSpaceEnd = ref Unsafe . Add ( ref searchSpace , searchSpaceLength ) ;
231- ref char cur = ref searchSpace ;
217+ return IndexOfAnySimpleLoop < IndexOfAnyAsciiSearcher . DontNegate > ( ref searchSpace , searchSpaceLength , valuesSpan ) ;
218+ }
232219
233- while ( ! Unsafe . AreSame ( ref cur , ref searchSpaceEnd ) )
234- {
235- char c = cur ;
236- if ( TNegator . NegateIfNeeded ( Contains ( valuesSpan , c ) ) )
237- {
238- return ( int ) ( ( nuint ) Unsafe . ByteOffset ( ref searchSpace , ref cur ) / sizeof ( char ) ) ;
239- }
220+ if ( IndexOfAnyAsciiSearcher . TryIndexOfAny ( ref searchSpace , searchSpaceLength , valuesSpan , out int index ) )
221+ {
222+ return index ;
223+ }
240224
241- cur = ref Unsafe . Add ( ref cur , 1 ) ;
242- }
225+ return ProbabilisticIndexOfAny ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
226+ }
243227
244- return - 1 ;
245- }
228+ public static int IndexOfAnyExcept ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
229+ {
230+ var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
246231
247- if ( typeof ( TNegator ) == typeof ( SpanHelpers . DontNegate < char > )
248- ? IndexOfAnyAsciiSearcher . TryIndexOfAny ( ref searchSpace , searchSpaceLength , valuesSpan , out int index )
249- : IndexOfAnyAsciiSearcher . TryIndexOfAnyExcept ( ref searchSpace , searchSpaceLength , valuesSpan , out index ) )
232+ if ( IndexOfAnyAsciiSearcher . IsVectorizationSupported &&
233+ ! ShouldUseSimpleLoop ( searchSpaceLength , valuesLength ) &&
234+ IndexOfAnyAsciiSearcher . TryIndexOfAnyExcept ( ref searchSpace , searchSpaceLength , valuesSpan , out int index ) )
250235 {
251236 return index ;
252237 }
253238
254- return ProbabilisticIndexOfAny < TNegator > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
239+ return IndexOfAnySimpleLoop < IndexOfAnyAsciiSearcher . Negate > ( ref searchSpace , searchSpaceLength , valuesSpan ) ;
255240 }
256241
257- private static int LastIndexOfAny < TNegator > ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
258- where TNegator : struct , SpanHelpers . INegator < char >
242+ public static int LastIndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
259243 {
260244 var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
261245
262246 // If the search space is relatively short compared to the needle, do a simple O(n * m) search.
263247 if ( ShouldUseSimpleLoop ( searchSpaceLength , valuesLength ) )
264248 {
265- for ( int i = searchSpaceLength - 1 ; i >= 0 ; i -- )
266- {
267- char c = Unsafe . Add ( ref searchSpace , i ) ;
268- if ( TNegator . NegateIfNeeded ( Contains ( valuesSpan , c ) ) )
269- {
270- return i ;
271- }
272- }
249+ return LastIndexOfAnySimpleLoop < IndexOfAnyAsciiSearcher . DontNegate > ( ref searchSpace , searchSpaceLength , valuesSpan ) ;
250+ }
273251
274- return - 1 ;
252+ if ( IndexOfAnyAsciiSearcher . TryLastIndexOfAny ( ref searchSpace , searchSpaceLength , valuesSpan , out int index ) )
253+ {
254+ return index ;
275255 }
276256
277- if ( typeof ( TNegator ) == typeof ( SpanHelpers . DontNegate < char > )
278- ? IndexOfAnyAsciiSearcher . TryLastIndexOfAny ( ref searchSpace , searchSpaceLength , valuesSpan , out int index )
279- : IndexOfAnyAsciiSearcher . TryLastIndexOfAnyExcept ( ref searchSpace , searchSpaceLength , valuesSpan , out index ) )
257+ return ProbabilisticLastIndexOfAny ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
258+ }
259+
260+ public static int LastIndexOfAnyExcept ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
261+ {
262+ var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
263+
264+ if ( IndexOfAnyAsciiSearcher . IsVectorizationSupported &&
265+ ! ShouldUseSimpleLoop ( searchSpaceLength , valuesLength ) &&
266+ IndexOfAnyAsciiSearcher . TryLastIndexOfAnyExcept ( ref searchSpace , searchSpaceLength , valuesSpan , out int index ) )
280267 {
281268 return index ;
282269 }
283270
284- return ProbabilisticLastIndexOfAny < TNegator > ( ref searchSpace , searchSpaceLength , ref values , valuesLength ) ;
271+ return LastIndexOfAnySimpleLoop < IndexOfAnyAsciiSearcher . Negate > ( ref searchSpace , searchSpaceLength , valuesSpan ) ;
285272 }
286273
287274 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
288- private static int ProbabilisticIndexOfAny < TNegator > ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
289- where TNegator : struct , SpanHelpers . INegator < char >
275+ private static int ProbabilisticIndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
290276 {
291277 var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
292278
293279 var map = new ProbabilisticMap ( valuesSpan ) ;
294280 ref uint charMap = ref Unsafe . As < ProbabilisticMap , uint > ( ref map ) ;
295281
296- return typeof ( TNegator ) == typeof ( SpanHelpers . DontNegate < char > )
297- ? IndexOfAny < IndexOfAnyAsciiSearcher . DontNegate > ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan )
298- : IndexOfAny < IndexOfAnyAsciiSearcher . Negate > ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan ) ;
282+ return IndexOfAny ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan ) ;
299283 }
300284
301285 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
302- private static int ProbabilisticLastIndexOfAny < TNegator > ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
303- where TNegator : struct , SpanHelpers . INegator < char >
286+ private static int ProbabilisticLastIndexOfAny ( ref char searchSpace , int searchSpaceLength , ref char values , int valuesLength )
304287 {
305288 var valuesSpan = new ReadOnlySpan < char > ( ref values , valuesLength ) ;
306289
307290 var map = new ProbabilisticMap ( valuesSpan ) ;
308291 ref uint charMap = ref Unsafe . As < ProbabilisticMap , uint > ( ref map ) ;
309292
310- return typeof ( TNegator ) == typeof ( SpanHelpers . DontNegate < char > )
311- ? LastIndexOfAny < IndexOfAnyAsciiSearcher . DontNegate > ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan )
312- : LastIndexOfAny < IndexOfAnyAsciiSearcher . Negate > ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan ) ;
293+ return LastIndexOfAny ( ref charMap , ref searchSpace , searchSpaceLength , valuesSpan ) ;
313294 }
314295
315296 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
316- internal static int IndexOfAny < TNegator > ( ref uint charMap , ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
317- where TNegator : struct , IndexOfAnyAsciiSearcher . INegator
297+ internal static int IndexOfAny ( ref uint charMap , ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
318298 {
319- if ( ( Sse41 . IsSupported || AdvSimd . Arm64 . IsSupported ) && typeof ( TNegator ) == typeof ( IndexOfAnyAsciiSearcher . DontNegate ) && searchSpaceLength >= 16 )
299+ if ( ( Sse41 . IsSupported || AdvSimd . Arm64 . IsSupported ) && searchSpaceLength >= 16 )
320300 {
321301 return IndexOfAnyVectorized ( ref charMap , ref searchSpace , searchSpaceLength , values ) ;
322302 }
@@ -327,7 +307,7 @@ internal static int IndexOfAny<TNegator>(ref uint charMap, ref char searchSpace,
327307 while ( ! Unsafe . AreSame ( ref cur , ref searchSpaceEnd ) )
328308 {
329309 int ch = cur ;
330- if ( TNegator . NegateIfNeeded ( Contains ( ref charMap , values , ch ) ) )
310+ if ( Contains ( ref charMap , values , ch ) )
331311 {
332312 return ( int ) ( ( nuint ) Unsafe . ByteOffset ( ref searchSpace , ref cur ) / sizeof ( char ) ) ;
333313 }
@@ -339,13 +319,12 @@ internal static int IndexOfAny<TNegator>(ref uint charMap, ref char searchSpace,
339319 }
340320
341321 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
342- internal static int LastIndexOfAny < TNegator > ( ref uint charMap , ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
343- where TNegator : struct , IndexOfAnyAsciiSearcher . INegator
322+ internal static int LastIndexOfAny ( ref uint charMap , ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
344323 {
345324 for ( int i = searchSpaceLength - 1 ; i >= 0 ; i -- )
346325 {
347326 int ch = Unsafe . Add ( ref searchSpace , i ) ;
348- if ( TNegator . NegateIfNeeded ( Contains ( ref charMap , values , ch ) ) )
327+ if ( Contains ( ref charMap , values , ch ) )
349328 {
350329 return i ;
351330 }
@@ -461,5 +440,42 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace,
461440
462441 return - 1 ;
463442 }
443+
444+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
445+ internal static int IndexOfAnySimpleLoop < TNegator > ( ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
446+ where TNegator : struct , IndexOfAnyAsciiSearcher . INegator
447+ {
448+ ref char searchSpaceEnd = ref Unsafe . Add ( ref searchSpace , searchSpaceLength ) ;
449+ ref char cur = ref searchSpace ;
450+
451+ while ( ! Unsafe . AreSame ( ref cur , ref searchSpaceEnd ) )
452+ {
453+ char c = cur ;
454+ if ( TNegator . NegateIfNeeded ( Contains ( values , c ) ) )
455+ {
456+ return ( int ) ( ( nuint ) Unsafe . ByteOffset ( ref searchSpace , ref cur ) / sizeof ( char ) ) ;
457+ }
458+
459+ cur = ref Unsafe . Add ( ref cur , 1 ) ;
460+ }
461+
462+ return - 1 ;
463+ }
464+
465+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
466+ internal static int LastIndexOfAnySimpleLoop < TNegator > ( ref char searchSpace , int searchSpaceLength , ReadOnlySpan < char > values )
467+ where TNegator : struct , IndexOfAnyAsciiSearcher . INegator
468+ {
469+ for ( int i = searchSpaceLength - 1 ; i >= 0 ; i -- )
470+ {
471+ char c = Unsafe . Add ( ref searchSpace , i ) ;
472+ if ( TNegator . NegateIfNeeded ( Contains ( values , c ) ) )
473+ {
474+ return i ;
475+ }
476+ }
477+
478+ return - 1 ;
479+ }
464480 }
465481}
0 commit comments