<Compile Include="$(MSBuildThisFileDirectory)System\AttributeUsageAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\BadImageFormatException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\BitConverter.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\BitOps.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Boolean.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPoolEventSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Number.NumberBuffer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Number.NumberToFloatingPointBits.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Number.Parsing.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\BitOperations.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Hashing\HashHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NullReferenceException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Object.cs" />
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Numerics;
using System.Runtime.CompilerServices;
namespace System.Buffers.Binary
// Testing shows that throughput increases if the AND
// is performed before the ROL / ROR.
- return BitOps.RotateRight(value & 0x00FF00FFu, 8) // xx zz
- + BitOps.RotateLeft(value & 0xFF00FF00u, 8); // ww yy
+ return BitOperations.RotateRight(value & 0x00FF00FFu, 8) // xx zz
+ + BitOperations.RotateLeft(value & 0xFF00FF00u, 8); // ww yy
}
/// <summary>
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using System.Runtime.CompilerServices;
namespace System.Buffers.Text
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int CountHexDigits(ulong value)
{
- return (64 - BitOps.LeadingZeroCount(value | 1) + 3) >> 2;
+ return (64 - BitOperations.LeadingZeroCount(value | 1) + 3) >> 2;
}
// Counts the number of trailing '0' digits in a decimal number.
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using System.Runtime.CompilerServices;
namespace System.Buffers
{
Debug.Assert(bufferSize >= 0);
uint bits = ((uint)bufferSize - 1) >> 4;
- return 32 - BitOps.LeadingZeroCount(bits);
+ return 32 - BitOperations.LeadingZeroCount(bits);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
if (hiRes > 2)
{
newScale = (int)hiRes * 32 - 64 - 1;
- newScale -= BitOps.LeadingZeroCount(result[hiRes]);
+ newScale -= BitOperations.LeadingZeroCount(result[hiRes]);
// Multiply bit position by log10(2) to figure it's power of 10.
// We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
if (tmp == 0)
tmp = d2.Mid;
- curScale = BitOps.LeadingZeroCount(tmp);
+ curScale = BitOperations.LeadingZeroCount(tmp);
// Shift both dividend and divisor left by curScale.
//
uint tmp = d2.High;
if (tmp == 0)
tmp = d2.Mid;
- int shift = BitOps.LeadingZeroCount(tmp);
+ int shift = BitOperations.LeadingZeroCount(tmp);
Buf28 b;
_ = &b; // workaround for CS0165
return new decimal(value);
}
-
public static explicit operator decimal(float value)
{
return new decimal(value);
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.Numerics;
using System.Reflection;
using System.Resources;
using System.Security;
{
for (int i = 16; i != 80; i++)
{
- this.w[i] = BitOps.RotateLeft((this.w[i - 3] ^ this.w[i - 8] ^ this.w[i - 14] ^ this.w[i - 16]), 1);
+ this.w[i] = BitOperations.RotateLeft((this.w[i - 3] ^ this.w[i - 8] ^ this.w[i - 14] ^ this.w[i - 16]), 1);
}
unchecked
{
const uint k = 0x5A827999;
uint f = (b & c) | ((~b) & d);
- uint temp = BitOps.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOps.RotateLeft(b, 30); b = a; a = temp;
+ uint temp = BitOperations.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOperations.RotateLeft(b, 30); b = a; a = temp;
}
for (int i = 20; i != 40; i++)
{
uint f = b ^ c ^ d;
const uint k = 0x6ED9EBA1;
- uint temp = BitOps.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOps.RotateLeft(b, 30); b = a; a = temp;
+ uint temp = BitOperations.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOperations.RotateLeft(b, 30); b = a; a = temp;
}
for (int i = 40; i != 60; i++)
{
uint f = (b & c) | (b & d) | (c & d);
const uint k = 0x8F1BBCDC;
- uint temp = BitOps.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOps.RotateLeft(b, 30); b = a; a = temp;
+ uint temp = BitOperations.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOperations.RotateLeft(b, 30); b = a; a = temp;
}
for (int i = 60; i != 80; i++)
{
uint f = b ^ c ^ d;
const uint k = 0xCA62C1D6;
- uint temp = BitOps.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOps.RotateLeft(b, 30); b = a; a = temp;
+ uint temp = BitOperations.RotateLeft(a, 5) + f + e + k + this.w[i]; e = d; d = c; c = BitOperations.RotateLeft(b, 30); b = a; a = temp;
}
this.w[80] += a;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Numerics;
using System.Runtime.CompilerServices;
namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Round(uint hash, uint input)
{
- return BitOps.RotateLeft(hash + input * Prime2, 13) * Prime1;
+ return BitOperations.RotateLeft(hash + input * Prime2, 13) * Prime1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint QueueRound(uint hash, uint queuedValue)
{
- return BitOps.RotateLeft(hash + queuedValue * Prime3, 17) * Prime4;
+ return BitOperations.RotateLeft(hash + queuedValue * Prime3, 17) * Prime4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint MixState(uint v1, uint v2, uint v3, uint v4)
{
- return BitOps.RotateLeft(v1, 1) + BitOps.RotateLeft(v2, 7) + BitOps.RotateLeft(v3, 12) + BitOps.RotateLeft(v4, 18);
+ return BitOperations.RotateLeft(v1, 1) + BitOperations.RotateLeft(v2, 7) + BitOperations.RotateLeft(v3, 12) + BitOperations.RotateLeft(v4, 18);
}
private static uint MixEmptyState()
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
uint p1 = rp1;
p1 ^= p0;
- p0 = BitOps.RotateLeft(p0, 20);
+ p0 = BitOperations.RotateLeft(p0, 20);
p0 += p1;
- p1 = BitOps.RotateLeft(p1, 9);
+ p1 = BitOperations.RotateLeft(p1, 9);
p1 ^= p0;
- p0 = BitOps.RotateLeft(p0, 27);
+ p0 = BitOperations.RotateLeft(p0, 27);
p0 += p1;
- p1 = BitOps.RotateLeft(p1, 19);
+ p1 = BitOperations.RotateLeft(p1, 19);
rp0 = p0;
rp1 = p1;
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
public static uint CountSignificantBits(uint value)
{
- return 32 - (uint)BitOps.LeadingZeroCount(value);
+ return 32 - (uint)BitOperations.LeadingZeroCount(value);
}
public static uint CountSignificantBits(ulong value)
{
- return 64 - (uint)BitOps.LeadingZeroCount(value);
+ return 64 - (uint)BitOperations.LeadingZeroCount(value);
}
public static uint CountSignificantBits(ref BigInteger value)
uint divLo = rhs._blocks[rhsLength - 2];
// We measure the leading zeros of the divisor
- int shiftLeft = BitOps.LeadingZeroCount(divHi);
+ int shiftLeft = BitOperations.LeadingZeroCount(divHi);
int shiftRight = 32 - shiftLeft;
// And, we make sure the most significant bit is set
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
namespace System
{
// and subtract once.
Debug.Assert(f != 0);
- int lzcnt = BitOps.LeadingZeroCount(f);
+ int lzcnt = BitOperations.LeadingZeroCount(f);
return new DiyFp((f << lzcnt), (e - lzcnt));
}
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Numerics;
using Internal.Runtime.CompilerServices;
namespace System
else
{
Debug.Assert(mantissa != 0);
- mantissaHighBitIdx = (uint)BitOps.Log2(mantissa);
+ mantissaHighBitIdx = (uint)BitOperations.Log2(mantissa);
}
int length = (int)(Dragon4(mantissa, exponent, mantissaHighBitIdx, hasUnequalMargins, cutoffNumber, isSignificantDigits, number.Digits, out int decimalExponent));
else
{
Debug.Assert(mantissa != 0);
- mantissaHighBitIdx = (uint)BitOps.Log2(mantissa);
+ mantissaHighBitIdx = (uint)BitOperations.Log2(mantissa);
}
int length = (int)(Dragon4(mantissa, exponent, mantissaHighBitIdx, hasUnequalMargins, cutoffNumber, isSignificantDigits, number.Digits, out int decimalExponent));
// This is safe because (2^28 - 1) = 268435455 which is less than 429496729.
// This means that all values with a highest bit at index 27 are within range.
Debug.Assert(hiBlock != 0);
- uint hiBlockLog2 = (uint)BitOps.Log2(hiBlock);
+ uint hiBlockLog2 = (uint)BitOperations.Log2(hiBlock);
Debug.Assert((hiBlockLog2 < 3) || (hiBlockLog2 > 27));
uint shift = (32 + 27 - hiBlockLog2) % 32;
// Some routines inspired by the Stanford Bit Twiddling Hacks by Sean Eron Anderson:
// http://graphics.stanford.edu/~seander/bithacks.html
-namespace System
+namespace System.Numerics
{
/// <summary>
/// Utility methods for intrinsic bit-twiddling operations.
/// The methods use hardware intrinsics when available on the underlying platform,
/// otherwise they use optimized software fallbacks.
/// </summary>
- internal static class BitOps
+ public static class BitOperations
{
// C# no-alloc optimization that directly wraps the data section of the dll (similar to string constants)
// https://github.com/dotnet/roslyn/pull/24621
};
/// <summary>
- /// Count the number of trailing zero bits in an integer value.
- /// Similar in behavior to the x86 instruction TZCNT.
- /// </summary>
- /// <param name="value">The value.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int TrailingZeroCount(int value)
- => TrailingZeroCount((uint)value);
-
- /// <summary>
- /// Count the number of trailing zero bits in an integer value.
- /// Similar in behavior to the x86 instruction TZCNT.
- /// </summary>
- /// <param name="value">The value.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int TrailingZeroCount(uint value)
- {
- if (Bmi1.IsSupported)
- {
- // TZCNT contract is 0->32
- return (int)Bmi1.TrailingZeroCount(value);
- }
-
- // Unguarded fallback contract is 0->0
- if (value == 0)
- {
- return 32;
- }
-
- // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
- return Unsafe.AddByteOffset(
- // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_0111_1100_1011_0101_0011_0001u
- ref MemoryMarshal.GetReference(s_TrailingZeroCountDeBruijn),
- // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
- (IntPtr)(int)(((value & (uint)-(int)value) * 0x077CB531u) >> 27)); // Multi-cast mitigates redundant conv.u8
- }
-
- /// <summary>
- /// Count the number of trailing zero bits in a mask.
- /// Similar in behavior to the x86 instruction TZCNT.
- /// </summary>
- /// <param name="value">The value.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int TrailingZeroCount(long value)
- => TrailingZeroCount((ulong)value);
-
- /// <summary>
- /// Count the number of trailing zero bits in a mask.
- /// Similar in behavior to the x86 instruction TZCNT.
- /// </summary>
- /// <param name="value">The value.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int TrailingZeroCount(ulong value)
- {
- if (Bmi1.X64.IsSupported)
- {
- // TZCNT contract is 0->64
- return (int)Bmi1.X64.TrailingZeroCount(value);
- }
-
- uint lo = (uint)value;
-
- if (lo == 0)
- {
- return 32 + TrailingZeroCount((uint)(value >> 32));
- }
-
- return TrailingZeroCount(lo);
- }
-
- /// <summary>
/// Count the number of leading zero bits in a mask.
/// Similar in behavior to the x86 instruction LZCNT.
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int LeadingZeroCount(uint value)
{
if (Lzcnt.IsSupported)
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int LeadingZeroCount(ulong value)
{
if (Lzcnt.X64.IsSupported)
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int Log2(uint value)
{
// value lzcnt actual expected
/// <summary>
/// Returns the integer (floor) log of the specified value, base 2.
/// Note that by convention, input value 0 returns 0 since Log(0) is undefined.
- /// Does not directly use any hardware intrinsics, nor does it incur branching.
- /// </summary>
- /// <param name="value">The value.</param>
- private static int Log2SoftwareFallback(uint value)
- {
- // No AggressiveInlining due to large method size
- // Has conventional contract 0->0 (Log(0) is undefined)
-
- // Fill trailing zeros with ones, eg 00010010 becomes 00011111
- value |= value >> 01;
- value |= value >> 02;
- value |= value >> 04;
- value |= value >> 08;
- value |= value >> 16;
-
- // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
- return Unsafe.AddByteOffset(
- // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u
- ref MemoryMarshal.GetReference(s_Log2DeBruijn),
- // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
- (IntPtr)(int)((value * 0x07C4ACDDu) >> 27));
- }
-
- /// <summary>
- /// Returns the integer (floor) log of the specified value, base 2.
- /// Note that by convention, input value 0 returns 0 since Log(0) is undefined.
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int Log2(ulong value)
{
if (Lzcnt.X64.IsSupported)
}
/// <summary>
- /// Rotates the specified value left by the specified number of bits.
- /// Similar in behavior to the x86 instruction ROL.
- /// </summary>
- /// <param name="value">The value to rotate.</param>
- /// <param name="offset">The number of bits to rotate by.
- /// Any value outside the range [0..31] is treated as congruent mod 32.</param>
- /// <returns>The rotated value.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint RotateLeft(uint value, int offset)
- => (value << offset) | (value >> (32 - offset));
-
- /// <summary>
- /// Rotates the specified value left by the specified number of bits.
- /// Similar in behavior to the x86 instruction ROL.
+ /// Returns the integer (floor) log of the specified value, base 2.
+ /// Note that by convention, input value 0 returns 0 since Log(0) is undefined.
+ /// Does not directly use any hardware intrinsics, nor does it incur branching.
/// </summary>
- /// <param name="value">The value to rotate.</param>
- /// <param name="offset">The number of bits to rotate by.
- /// Any value outside the range [0..63] is treated as congruent mod 64.</param>
- /// <returns>The rotated value.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong RotateLeft(ulong value, int offset)
- => (value << offset) | (value >> (64 - offset));
+ /// <param name="value">The value.</param>
+ private static int Log2SoftwareFallback(uint value)
+ {
+ // No AggressiveInlining due to large method size
+ // Has conventional contract 0->0 (Log(0) is undefined)
- /// <summary>
- /// Rotates the specified value right by the specified number of bits.
- /// Similar in behavior to the x86 instruction ROR.
- /// </summary>
- /// <param name="value">The value to rotate.</param>
- /// <param name="offset">The number of bits to rotate by.
- /// Any value outside the range [0..31] is treated as congruent mod 32.</param>
- /// <returns>The rotated value.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint RotateRight(uint value, int offset)
- => (value >> offset) | (value << (32 - offset));
+ // Fill trailing zeros with ones, eg 00010010 becomes 00011111
+ value |= value >> 01;
+ value |= value >> 02;
+ value |= value >> 04;
+ value |= value >> 08;
+ value |= value >> 16;
- /// <summary>
- /// Rotates the specified value right by the specified number of bits.
- /// Similar in behavior to the x86 instruction ROR.
- /// </summary>
- /// <param name="value">The value to rotate.</param>
- /// <param name="offset">The number of bits to rotate by.
- /// Any value outside the range [0..63] is treated as congruent mod 64.</param>
- /// <returns>The rotated value.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong RotateRight(ulong value, int offset)
- => (value >> offset) | (value << (64 - offset));
+ // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
+ return Unsafe.AddByteOffset(
+ // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u
+ ref MemoryMarshal.GetReference(s_Log2DeBruijn),
+ // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
+ (IntPtr)(int)((value * 0x07C4ACDDu) >> 27));
+ }
/// <summary>
/// Returns the population count (number of bits set) of a mask.
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int PopCount(uint value)
{
if (Popcnt.IsSupported)
/// </summary>
/// <param name="value">The value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
public static int PopCount(ulong value)
{
if (Popcnt.X64.IsSupported)
}
#endif
}
+
+ /// <summary>
+ /// Count the number of trailing zero bits in an integer value.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int TrailingZeroCount(int value)
+ => TrailingZeroCount((uint)value);
+
+ /// <summary>
+ /// Count the number of trailing zero bits in an integer value.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int TrailingZeroCount(uint value)
+ {
+ if (Bmi1.IsSupported)
+ {
+ // TZCNT contract is 0->32
+ return (int)Bmi1.TrailingZeroCount(value);
+ }
+
+ // Unguarded fallback contract is 0->0
+ if (value == 0)
+ {
+ return 32;
+ }
+
+ // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
+ return Unsafe.AddByteOffset(
+ // Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_0111_1100_1011_0101_0011_0001u
+ ref MemoryMarshal.GetReference(s_TrailingZeroCountDeBruijn),
+ // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
+ (IntPtr)(int)(((value & (uint)-(int)value) * 0x077CB531u) >> 27)); // Multi-cast mitigates redundant conv.u8
+ }
+
+ /// <summary>
+ /// Count the number of trailing zero bits in a mask.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int TrailingZeroCount(long value)
+ => TrailingZeroCount((ulong)value);
+
+ /// <summary>
+ /// Count the number of trailing zero bits in a mask.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static int TrailingZeroCount(ulong value)
+ {
+ if (Bmi1.X64.IsSupported)
+ {
+ // TZCNT contract is 0->64
+ return (int)Bmi1.X64.TrailingZeroCount(value);
+ }
+
+ uint lo = (uint)value;
+
+ if (lo == 0)
+ {
+ return 32 + TrailingZeroCount((uint)(value >> 32));
+ }
+
+ return TrailingZeroCount(lo);
+ }
+
+ /// <summary>
+ /// Rotates the specified value left by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROL.
+ /// </summary>
+ /// <param name="value">The value to rotate.</param>
+ /// <param name="offset">The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32.</param>
+ /// <returns>The rotated value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static uint RotateLeft(uint value, int offset)
+ => (value << offset) | (value >> (32 - offset));
+
+ /// <summary>
+ /// Rotates the specified value left by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROL.
+ /// </summary>
+ /// <param name="value">The value to rotate.</param>
+ /// <param name="offset">The number of bits to rotate by.
+ /// Any value outside the range [0..63] is treated as congruent mod 64.</param>
+ /// <returns>The rotated value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static ulong RotateLeft(ulong value, int offset)
+ => (value << offset) | (value >> (64 - offset));
+
+ /// <summary>
+ /// Rotates the specified value right by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROR.
+ /// </summary>
+ /// <param name="value">The value to rotate.</param>
+ /// <param name="offset">The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32.</param>
+ /// <returns>The rotated value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static uint RotateRight(uint value, int offset)
+ => (value >> offset) | (value << (32 - offset));
+
+ /// <summary>
+ /// Rotates the specified value right by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROR.
+ /// </summary>
+ /// <param name="value">The value to rotate.</param>
+ /// <param name="offset">The number of bits to rotate by.
+ /// Any value outside the range [0..63] is treated as congruent mod 64.</param>
+ /// <returns>The rotated value.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static ulong RotateRight(ulong value, int offset)
+ => (value >> offset) | (value << (64 - offset));
}
}
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.CompilerServices;
using System.Numerics;
+using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
else
{
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
}
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
} while ((byte*)lengthToExamine > (byte*)offset);
}
else
{
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
}
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
if ((int)(byte*)offset < length)
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
} while ((byte*)lengthToExamine > (byte*)offset);
}
else
{
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
}
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
if ((int)(byte*)offset < length)
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
} while ((byte*)lengthToExamine > (byte*)offset);
}
else
{
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
}
}
// Find bitflag offset of first match and add to current offset
- return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
+ return ((int)(byte*)offset) + BitOperations.TrailingZeroCount(matches);
}
if ((int)(byte*)offset < length)
// Invert matches to find differences
uint differences = ~matches;
// Find bitflag offset of first difference and add to current offset
- offset = (IntPtr)((int)(byte*)offset + BitOps.TrailingZeroCount((int)differences));
+ offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
Debug.Assert(result != 0);
// Invert matches to find differences
uint differences = ~matches;
// Find bitflag offset of first difference and add to current offset
- offset = (IntPtr)((int)(byte*)offset + BitOps.TrailingZeroCount((int)differences));
+ offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
Debug.Assert(result != 0);
// Invert matches to find differences
uint differences = ~matches;
// Find bitflag offset of first difference and add to current offset
- offset = (IntPtr)((int)(byte*)offset + BitOps.TrailingZeroCount((int)differences));
+ offset = (IntPtr)((int)(byte*)offset + BitOperations.TrailingZeroCount((int)differences));
int result = Unsafe.AddByteOffset(ref first, offset).CompareTo(Unsafe.AddByteOffset(ref second, offset));
Debug.Assert(result != 0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(ulong match)
{
- return 7 - (BitOps.LeadingZeroCount(match) >> 3);
+ return 7 - (BitOperations.LeadingZeroCount(match) >> 3);
}
private const ulong XorPowerOfTwoToHighByte = (0x07ul |
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.CompilerServices;
using System.Numerics;
+using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics.X86;
using Internal.Runtime.CompilerServices;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundChar(ulong match)
{
- return 3 - (BitOps.LeadingZeroCount(match) >> 4);
+ return 3 - (BitOperations.LeadingZeroCount(match) >> 4);
}
}
}
using System.Diagnostics;
using System.Globalization;
+using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
{
length -= 4;
// Where length is 4n-1 (e.g. 3,7,11,15,19) this additionally consumes the null terminator
- hash1 = (BitOps.RotateLeft(hash1, 5) + hash1) ^ ptr[0];
- hash2 = (BitOps.RotateLeft(hash2, 5) + hash2) ^ ptr[1];
+ hash1 = (BitOperations.RotateLeft(hash1, 5) + hash1) ^ ptr[0];
+ hash2 = (BitOperations.RotateLeft(hash2, 5) + hash2) ^ ptr[1];
ptr += 2;
}
if (length > 0)
{
// Where length is 4n-3 (e.g. 1,5,9,13,17) this additionally consumes the null terminator
- hash2 = (BitOps.RotateLeft(hash2, 5) + hash2) ^ ptr[0];
+ hash2 = (BitOperations.RotateLeft(hash2, 5) + hash2) ^ ptr[0];
}
return (int)(hash1 + (hash2 * 1566083941));