BitOps.cs 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.InteropServices;
  6. using System.Runtime.Intrinsics.X86;
  7. using Internal.Runtime.CompilerServices;
  8. namespace System
  9. {
  10. internal static class BitOps
  11. {
  12. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  13. public static int TrailingZeroCount(int matches)
  14. {
  15. if (Bmi1.IsSupported)
  16. {
  17. return (int)Bmi1.TrailingZeroCount((uint)matches);
  18. }
  19. else // Software fallback
  20. {
  21. // https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
  22. // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
  23. return Unsafe.AddByteOffset(
  24. ref MemoryMarshal.GetReference(TrailingCountMultiplyDeBruijn),
  25. ((uint)((matches & -matches) * 0x077CB531U)) >> 27);
  26. }
  27. }
  28. private static ReadOnlySpan<byte> TrailingCountMultiplyDeBruijn => new byte[32]
  29. {
  30. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  31. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  32. };
  33. }
  34. }