diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/AlphabetValidationBenchmarks.cs b/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/AlphabetValidationBenchmarks.cs deleted file mode 100644 index 3bfceb4..0000000 --- a/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/AlphabetValidationBenchmarks.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using BenchmarkDotNet.Attributes; - -namespace FastIDs.TypeId.Benchmarks.InternalBenchmarks; - -[MemoryDiagnoser] -public class AlphabetValidationBenchmarks -{ - [Params(3, 6, 10, 16, 30, 63)] - public int PrefixLength; - - private string _prefix = ""; - - private const string AlphabetStr = "abcdefghijklmnopqrstuvwxyz"; - private readonly HashSet _alphabetSet = new(AlphabetStr); - private const int LoopIterationsCount = 100_000; - private const int UnrollValue = 4; - - [GlobalSetup] - public void Setup() - { - var random = new Random(42); - _prefix = ""; - for (var i = 0; i < PrefixLength; i++) - { - _prefix += (char) random.Next('a', 'z'); - } - } - - [Benchmark(Baseline = true)] - public bool CharCheck() - { - var isValid = false; - for (var i = 0; i < LoopIterationsCount; i++) - { - foreach (var c in _prefix) - { - isValid &= c is >= 'a' and <= 'z'; - } - } - - return isValid; - } - - [Benchmark] - public bool Simd() - { - var isValid = false; - for (var i = 0; i < LoopIterationsCount; i++) - { - var lower = new Vector((short)'a'); - var higher = new Vector((short)'z'); - - var shorts = MemoryMarshal.Cast(_prefix.AsSpan()); - - for (var j = 0; j < shorts.Length; j += Vector.Count) - { - var span = Vector.Count < shorts.Length - j - ? shorts.Slice(j, Vector.Count) - : shorts[^Vector.Count..]; - - var curVector = new Vector(span); - - var isGreater = Vector.GreaterThanOrEqualAll(curVector, lower); - var isLower = Vector.LessThanOrEqualAll(curVector, higher); - isValid &= isGreater && isLower; - } - } - - return isValid; - } - - [Benchmark] - public bool CharCheckUnroll() - { - var isValid = false; - for (var i = 0; i < LoopIterationsCount; i++) - { - if (_prefix.Length < UnrollValue) - { - foreach (var c in _prefix) - { - isValid &= c is >= 'a' and <= 'z'; - } - } - else - { - var j = 0; - ref var prefixStart = ref MemoryMarshal.GetReference(_prefix.AsSpan()); - - // unroll loop - for (; j + UnrollValue < _prefix.Length; j += UnrollValue) - { - isValid &= Unsafe.Add(ref prefixStart, j) is >= 'a' and <= 'z'; - isValid &= Unsafe.Add(ref prefixStart, j + 1) is >= 'a' and <= 'z'; - isValid &= Unsafe.Add(ref prefixStart, j + 2) is >= 'a' and <= 'z'; - isValid &= Unsafe.Add(ref prefixStart, j + 3) is >= 'a' and <= 'z'; - } - - for (; j < _prefix.Length; j++) - { - isValid &= Unsafe.Add(ref prefixStart, j) is >= 'a' and <= 'z'; - } - } - - } - - return isValid; - } -} \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/IdAlphabetValidationBenchmarks.cs b/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/IdAlphabetValidationBenchmarks.cs new file mode 100644 index 0000000..ba4ac88 --- /dev/null +++ b/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/IdAlphabetValidationBenchmarks.cs @@ -0,0 +1,285 @@ +using System.Buffers; +using System.Runtime.CompilerServices; +using BenchmarkDotNet.Attributes; + +namespace FastIDs.TypeId.Benchmarks.InternalBenchmarks; + +[MemoryDiagnoser] +[MarkdownExporter] +[MarkdownExporterAttribute.Default] +[MarkdownExporterAttribute.GitHub] +[GroupBenchmarksBy(BenchmarkDotNet.Configs.BenchmarkLogicalGroupRule.ByCategory)] +public class IdAlphabetValidationBenchmarks +{ + private const string AlphabetStr = "0123456789abcdefghjkmnpqrstvwxyz"; + + private readonly SearchValues _searchValues = SearchValues.Create(AlphabetStr); + private readonly HashSet _alphabetSet = new(AlphabetStr); + + private string[] _validIds = []; + private string[] _invalidIds = []; + + [GlobalSetup] + public void Setup() + { + const int idsCount = 100_000; + _validIds = new string[idsCount]; + _invalidIds = new string[idsCount]; + for (var i = 0; i < idsCount; i++) + { + var id = TypeId.New("", false).ToString(); + _validIds[i] = id; + _invalidIds[i] = id[..^1] + ','; // invalid char + + } + } + + [Benchmark(Baseline = true)] + [BenchmarkCategory("Valid")] + public bool CharCheckUnrolledValid() + { + var isValid = false; + foreach (var id in _validIds) + { + isValid &= IsValidAlphabet(id); + } + + return isValid; + } + + [Benchmark(Baseline = true)] + [BenchmarkCategory("Invalid")] + public bool CharCheckUnrolledInvalid() + { + var isValid = false; + foreach (var id in _invalidIds) + { + isValid &= IsValidAlphabet(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Valid")] + public bool SearchValuesLoopValid() + { + var isValid = false; + foreach (var id in _validIds) + { + isValid &= IsValidAlphabetSearchValues(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Valid")] + public bool SearchValuesUnrollValid() + { + var isValid = false; + foreach (var id in _validIds) + { + isValid &= IsValidAlphabetSearchValuesUnrolled(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Invalid")] + public bool SearchValuesLoopInvalid() + { + var isValid = false; + foreach (var id in _invalidIds) + { + isValid &= IsValidAlphabetSearchValues(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Invalid")] + public bool SearchValuesUnrollInvalid() + { + var isValid = false; + foreach (var id in _invalidIds) + { + isValid &= IsValidAlphabetSearchValuesUnrolled(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Valid")] + public bool HashSetLoopValid() + { + var isValid = false; + foreach (var id in _validIds) + { + isValid &= IsValidAlphabetHashSet(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Valid")] + public bool HashSetUnrollValid() + { + var isValid = false; + foreach (var id in _validIds) + { + isValid &= IsValidAlphabetHashSetUnrolled(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Invalid")] + public bool HashSetLoopInvalid() + { + var isValid = false; + foreach (var id in _invalidIds) + { + isValid &= IsValidAlphabetHashSet(id); + } + + return isValid; + } + + [Benchmark] + [BenchmarkCategory("Invalid")] + public bool HashSetUnrollInvalid() + { + var isValid = false; + foreach (var id in _invalidIds) + { + isValid &= IsValidAlphabetHashSetUnrolled(id); + } + + return isValid; + } + + private static bool IsValidAlphabet(ReadOnlySpan chars) => + IsValidChar(chars[0]) + && IsValidChar(chars[1]) + && IsValidChar(chars[2]) + && IsValidChar(chars[3]) + && IsValidChar(chars[4]) + && IsValidChar(chars[5]) + && IsValidChar(chars[6]) + && IsValidChar(chars[7]) + && IsValidChar(chars[8]) + && IsValidChar(chars[9]) + && IsValidChar(chars[10]) + && IsValidChar(chars[11]) + && IsValidChar(chars[12]) + && IsValidChar(chars[13]) + && IsValidChar(chars[14]) + && IsValidChar(chars[15]) + && IsValidChar(chars[16]) + && IsValidChar(chars[17]) + && IsValidChar(chars[18]) + && IsValidChar(chars[19]) + && IsValidChar(chars[20]) + && IsValidChar(chars[21]) + && IsValidChar(chars[22]) + && IsValidChar(chars[23]) + && IsValidChar(chars[24]) + && IsValidChar(chars[25]); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsValidChar(char c) + { + if (c >= '0' && c <= '9') + return true; + + return c is >= 'a' and <= 'h' + or >= 'j' and <= 'k' + or >= 'm' and <= 'n' + or >= 'p' and <= 't' + or >= 'v' and <= 'z'; + } + + private bool IsValidAlphabetSearchValues(ReadOnlySpan chars) + { + foreach (var c in chars) + { + if (!_searchValues.Contains(c)) + return false; + } + + return true; + } + + private bool IsValidAlphabetSearchValuesUnrolled(ReadOnlySpan chars) => + _searchValues.Contains(chars[0]) + && _searchValues.Contains(chars[1]) + && _searchValues.Contains(chars[2]) + && _searchValues.Contains(chars[3]) + && _searchValues.Contains(chars[4]) + && _searchValues.Contains(chars[5]) + && _searchValues.Contains(chars[6]) + && _searchValues.Contains(chars[7]) + && _searchValues.Contains(chars[8]) + && _searchValues.Contains(chars[9]) + && _searchValues.Contains(chars[10]) + && _searchValues.Contains(chars[11]) + && _searchValues.Contains(chars[12]) + && _searchValues.Contains(chars[13]) + && _searchValues.Contains(chars[14]) + && _searchValues.Contains(chars[15]) + && _searchValues.Contains(chars[16]) + && _searchValues.Contains(chars[17]) + && _searchValues.Contains(chars[18]) + && _searchValues.Contains(chars[19]) + && _searchValues.Contains(chars[20]) + && _searchValues.Contains(chars[21]) + && _searchValues.Contains(chars[22]) + && _searchValues.Contains(chars[23]) + && _searchValues.Contains(chars[24]) + && _searchValues.Contains(chars[25]); + + private bool IsValidAlphabetHashSet(ReadOnlySpan chars) + { + foreach (var c in chars) + { + if (!_alphabetSet.Contains(c)) + return false; + } + + return true; + } + + private bool IsValidAlphabetHashSetUnrolled(ReadOnlySpan chars) => + _alphabetSet.Contains(chars[0]) + && _alphabetSet.Contains(chars[1]) + && _alphabetSet.Contains(chars[2]) + && _alphabetSet.Contains(chars[3]) + && _alphabetSet.Contains(chars[4]) + && _alphabetSet.Contains(chars[5]) + && _alphabetSet.Contains(chars[6]) + && _alphabetSet.Contains(chars[7]) + && _alphabetSet.Contains(chars[8]) + && _alphabetSet.Contains(chars[9]) + && _alphabetSet.Contains(chars[10]) + && _alphabetSet.Contains(chars[11]) + && _alphabetSet.Contains(chars[12]) + && _alphabetSet.Contains(chars[13]) + && _alphabetSet.Contains(chars[14]) + && _alphabetSet.Contains(chars[15]) + && _alphabetSet.Contains(chars[16]) + && _alphabetSet.Contains(chars[17]) + && _alphabetSet.Contains(chars[18]) + && _alphabetSet.Contains(chars[19]) + && _alphabetSet.Contains(chars[20]) + && _alphabetSet.Contains(chars[21]) + && _alphabetSet.Contains(chars[22]) + && _alphabetSet.Contains(chars[23]) + && _alphabetSet.Contains(chars[24]) + && _alphabetSet.Contains(chars[25]); +} \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/TypeAlphabetValidationBenchmarks.cs b/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/TypeAlphabetValidationBenchmarks.cs new file mode 100644 index 0000000..fc48803 --- /dev/null +++ b/src/FastIDs.TypeId/TypeId.Benchmarks/InternalBenchmarks/TypeAlphabetValidationBenchmarks.cs @@ -0,0 +1,130 @@ +using System.Buffers; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; +using BenchmarkDotNet.Attributes; + +namespace FastIDs.TypeId.Benchmarks.InternalBenchmarks; + +[MemoryDiagnoser] +[MarkdownExporter] +[MarkdownExporterAttribute.Default] +[MarkdownExporterAttribute.GitHub] +public class TypeAlphabetValidationBenchmarks +{ + [Params(3, 6, 8, 14, 30, 63)] + public int PrefixLength; + + private string[] _prefixes = []; + + private const string AlphabetStr = "abcdefghijklmnopqrstuvwxyz"; + private readonly SearchValues _searchValues = SearchValues.Create(AlphabetStr); + private const int UnrollValue = 4; + + [GlobalSetup] + public void Setup() + { + var random = new Random(); + + const int count = 100_000; + _prefixes = new string[count]; + var sb = new StringBuilder(PrefixLength); + + for (var i = 0; i < count; i++) + { + sb.Clear(); + + for (var j = 0; j < PrefixLength; j++) + { + sb.Append((char)random.Next('a', 'z')); + } + + _prefixes[i] = sb.ToString(); + } + } + + [Benchmark(Baseline = true)] + public bool CharCheck() + { + var isValid = false; + foreach (var prefix in _prefixes) + { + foreach (var c in prefix.AsSpan()) + { + isValid &= c is >= 'a' and <= 'z'; + } + } + + return isValid; + } + + [Benchmark] + public bool CharCheckAscii() + { + var isValid = false; + foreach (var prefix in _prefixes) + { + foreach (var c in prefix.AsSpan()) + { + isValid &= char.IsAsciiLetterLower(c); + } + } + + return isValid; + } + + [Benchmark] + public bool SearchValuesCheck() + { + var isValid = false; + foreach (var prefix in _prefixes) + { + foreach (var c in prefix.AsSpan()) + { + isValid &= _searchValues.Contains(c); + } + } + + return isValid; + } + + [Benchmark] + public bool SearchValuesInRangeCheck() + { + var isValid = false; + foreach (var prefix in _prefixes) + { + isValid &= !prefix.AsSpan().ContainsAnyExceptInRange('a', 'z'); + } + + return isValid; + } + + [Benchmark] + public bool Simd() + { + var isValid = false; + foreach (var prefix in _prefixes) + { + var lower = new Vector((short)'a'); + var higher = new Vector((short)'z'); + + var shorts = MemoryMarshal.Cast(prefix.AsSpan()); + + for (var j = 0; j < shorts.Length; j += Vector.Count) + { + var span = Vector.Count < shorts.Length - j + ? shorts.Slice(j, Vector.Count) + : shorts[^Vector.Count..]; + + var curVector = new Vector(span); + + var isGreater = Vector.GreaterThanOrEqualAll(curVector, lower); + var isLower = Vector.LessThanOrEqualAll(curVector, higher); + isValid &= isGreater && isLower; + } + } + + return isValid; + } +} \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/LibraryComparison/TypeIdParsing.cs b/src/FastIDs.TypeId/TypeId.Benchmarks/LibraryComparison/TypeIdParsing.cs index aba0cc4..1e04cdf 100644 --- a/src/FastIDs.TypeId/TypeId.Benchmarks/LibraryComparison/TypeIdParsing.cs +++ b/src/FastIDs.TypeId/TypeId.Benchmarks/LibraryComparison/TypeIdParsing.cs @@ -6,6 +6,7 @@ namespace FastIDs.TypeId.Benchmarks.LibraryComparison; [MemoryDiagnoser] [MarkdownExporter] [MarkdownExporterAttribute.Default] +[MarkdownExporterAttribute.GitHub] public class TypeIdParsing { [Params(0, 5, 10, 30, 63)] diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/Program.cs b/src/FastIDs.TypeId/TypeId.Benchmarks/Program.cs index 5bca60a..a404c6b 100644 --- a/src/FastIDs.TypeId/TypeId.Benchmarks/Program.cs +++ b/src/FastIDs.TypeId/TypeId.Benchmarks/Program.cs @@ -1,4 +1,13 @@ using System.Reflection; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Running; -BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(); \ No newline at end of file +var config = DefaultConfig.Instance; + +// config.AddJob(Job.Default.WithId("Scalar").WithEnvironmentVariable("DOTNET_EnableHWIntrinsic", "0").AsBaseline()) +// .AddJob(Job.Default.WithId("Vector128").WithEnvironmentVariable("DOTNET_EnableAVX512F", "0").WithEnvironmentVariable("DOTNET_EnableAVX2", "0")) +// .AddJob(Job.Default.WithId("Vector256").WithEnvironmentVariable("DOTNET_EnableAVX512F", "0")) +// .AddJob(Job.Default.WithId("Vector512")); + +BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(config: config); \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Benchmarks/TypeId.Benchmarks.csproj b/src/FastIDs.TypeId/TypeId.Benchmarks/TypeId.Benchmarks.csproj index e3553bf..68aae44 100644 --- a/src/FastIDs.TypeId/TypeId.Benchmarks/TypeId.Benchmarks.csproj +++ b/src/FastIDs.TypeId/TypeId.Benchmarks/TypeId.Benchmarks.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable enable Nullable @@ -10,7 +10,7 @@ - + diff --git a/src/FastIDs.TypeId/TypeId.Core/Base32.cs b/src/FastIDs.TypeId/TypeId.Core/Base32.cs index 659fdcc..883783b 100644 --- a/src/FastIDs.TypeId/TypeId.Core/Base32.cs +++ b/src/FastIDs.TypeId/TypeId.Core/Base32.cs @@ -1,5 +1,4 @@ -using System.Runtime.CompilerServices; -using System.Text; +using System.Text; namespace FastIDs.TypeId; @@ -91,75 +90,14 @@ public static bool IsValid(ReadOnlySpan input) return IsValidAlphabet(input); } - private static bool IsValidAlphabet(ReadOnlySpan chars) => - IsValidChar(chars[0]) - && IsValidChar(chars[1]) - && IsValidChar(chars[2]) - && IsValidChar(chars[3]) - && IsValidChar(chars[4]) - && IsValidChar(chars[5]) - && IsValidChar(chars[6]) - && IsValidChar(chars[7]) - && IsValidChar(chars[8]) - && IsValidChar(chars[9]) - && IsValidChar(chars[10]) - && IsValidChar(chars[11]) - && IsValidChar(chars[12]) - && IsValidChar(chars[13]) - && IsValidChar(chars[14]) - && IsValidChar(chars[15]) - && IsValidChar(chars[16]) - && IsValidChar(chars[17]) - && IsValidChar(chars[18]) - && IsValidChar(chars[19]) - && IsValidChar(chars[20]) - && IsValidChar(chars[21]) - && IsValidChar(chars[22]) - && IsValidChar(chars[23]) - && IsValidChar(chars[24]) - && IsValidChar(chars[25]); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsValidChar(char c) + private static bool IsValidAlphabet(ReadOnlySpan chars) { - if (c >= '0' && c <= '9') - return true; - - return c is >= 'a' and <= 'h' - or >= 'j' and <= 'k' - or >= 'm' and <= 'n' - or >= 'p' and <= 't' - or >= 'v' and <= 'z'; - } + foreach (var c in chars) + { + if (!Base32Constants.AlphabetValues.Contains(c)) + return false; + } - private static bool AreValidBytes(ReadOnlySpan bytes) - { - var dec = Base32Constants.DecodingTable; - return dec[bytes[0]] != 0xFF - && dec[bytes[1]] != 0xFF - && dec[bytes[2]] != 0xFF - && dec[bytes[3]] != 0xFF - && dec[bytes[4]] != 0xFF - && dec[bytes[5]] != 0xFF - && dec[bytes[6]] != 0xFF - && dec[bytes[7]] != 0xFF - && dec[bytes[8]] != 0xFF - && dec[bytes[9]] != 0xFF - && dec[bytes[10]] != 0xFF - && dec[bytes[11]] != 0xFF - && dec[bytes[12]] != 0xFF - && dec[bytes[13]] != 0xFF - && dec[bytes[14]] != 0xFF - && dec[bytes[15]] != 0xFF - && dec[bytes[16]] != 0xFF - && dec[bytes[17]] != 0xFF - && dec[bytes[18]] != 0xFF - && dec[bytes[19]] != 0xFF - && dec[bytes[20]] != 0xFF - && dec[bytes[21]] != 0xFF - && dec[bytes[22]] != 0xFF - && dec[bytes[23]] != 0xFF - && dec[bytes[24]] != 0xFF - && dec[bytes[25]] != 0xFF; + return true; } } \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Core/Base32Constants.cs b/src/FastIDs.TypeId/TypeId.Core/Base32Constants.cs index 8d145b2..a031784 100644 --- a/src/FastIDs.TypeId/TypeId.Core/Base32Constants.cs +++ b/src/FastIDs.TypeId/TypeId.Core/Base32Constants.cs @@ -1,9 +1,13 @@ -namespace FastIDs.TypeId; +using System.Buffers; + +namespace FastIDs.TypeId; internal static class Base32Constants { public const string Alphabet = "0123456789abcdefghjkmnpqrstvwxyz"; + public static readonly SearchValues AlphabetValues = SearchValues.Create(Alphabet); + public const int DecodedLength = 16; public const int EncodedLength = 26; diff --git a/src/FastIDs.TypeId/TypeId.Core/TypeId.Core.csproj b/src/FastIDs.TypeId/TypeId.Core/TypeId.Core.csproj index 34a906d..624dbe7 100644 --- a/src/FastIDs.TypeId/TypeId.Core/TypeId.Core.csproj +++ b/src/FastIDs.TypeId/TypeId.Core/TypeId.Core.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable enable Nullable diff --git a/src/FastIDs.TypeId/TypeId.Core/TypeIdParser.cs b/src/FastIDs.TypeId/TypeId.Core/TypeIdParser.cs index 878006e..700505b 100644 --- a/src/FastIDs.TypeId/TypeId.Core/TypeIdParser.cs +++ b/src/FastIDs.TypeId/TypeId.Core/TypeIdParser.cs @@ -1,7 +1,7 @@ using System.Buffers.Binary; -using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; namespace FastIDs.TypeId; @@ -25,47 +25,18 @@ public static void FormatUuidBytes(Span bytes) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool ValidateTypeAlphabet(ReadOnlySpan type) { - return Vector.IsHardwareAccelerated && type.Length >= Vector.Count - ? ValidateTypeAlphabetVectorized(type) - : ValidateTypeAlphabetSequential(type); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool ValidateTypeAlphabetSequential(ReadOnlySpan type) - { + // Vectorized version is faster for strings with length >= 8. + const int vectorizedThreshold = 8; + if (Vector128.IsHardwareAccelerated && type.Length >= vectorizedThreshold) + return !type.ContainsAnyExceptInRange('a', 'z'); + + // Fallback to scalar version for strings with length < 8 or when hardware intrinsics are not available. foreach (var c in type) { - if (c is < 'a' or > 'z') + if (!char.IsAsciiLetterLower(c)) return false; } return true; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool ValidateTypeAlphabetVectorized(ReadOnlySpan type) - { - var lower = new Vector('a'); - var upper = new Vector('z'); - - var shorts = MemoryMarshal.Cast(type); - for (var i = 0; i < shorts.Length; i += Vector.Count) - { - var span = Vector.Count < shorts.Length - i - ? shorts.Slice(i, Vector.Count) - : shorts[^Vector.Count..]; - - var curVector = new Vector(span); - - var isGreater = Vector.GreaterThanOrEqualAll(curVector, lower); - if (!isGreater) - return false; - - var isLower = Vector.LessThanOrEqualAll(curVector, upper); - if (!isLower) - return false; - } - - return true; - } } \ No newline at end of file diff --git a/src/FastIDs.TypeId/TypeId.Tests/TypeId.Tests.csproj b/src/FastIDs.TypeId/TypeId.Tests/TypeId.Tests.csproj index 4006d26..870fd67 100644 --- a/src/FastIDs.TypeId/TypeId.Tests/TypeId.Tests.csproj +++ b/src/FastIDs.TypeId/TypeId.Tests/TypeId.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable Nullable