diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs
index b5ffd5e777d984..6a7141cd01cd48 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs
@@ -76,14 +76,15 @@ public static class BitOperations
///
/// The value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static bool IsPow2(nint value) => (value & (value - 1)) == 0 && value > 0;
+ public static bool IsPow2(nint value) => (value & (value - 1)) == 0 && value > 0;
///
/// Evaluate whether a given integral value is a power of 2.
///
/// The value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static bool IsPow2(nuint value) => (value & (value - 1)) == 0 && value != 0;
+ [CLSCompliant(false)]
+ public static bool IsPow2(nuint value) => (value & (value - 1)) == 0 && value != 0;
/// Round the given integral value up to a power of 2.
/// The value.
@@ -115,7 +116,6 @@ public static uint RoundUpToPowerOf2(uint value)
return value + 1;
}
-
///
/// Round the given integral value up to a power of 2.
///
@@ -145,6 +145,25 @@ public static ulong RoundUpToPowerOf2(ulong value)
return value + 1;
}
+ ///
+ /// Round the given integral value up to a power of 2.
+ ///
+ /// The value.
+ ///
+ /// The smallest power of 2 which is greater than or equal to .
+ /// If is 0 or the result overflows, returns 0.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static nuint RoundUpToPowerOf2(nuint value)
+ {
+#if TARGET_64BIT
+ return (nuint)RoundUpToPowerOf2((ulong)value);
+#else
+ return (nuint)RoundUpToPowerOf2((uint)value);
+#endif
+ }
+
///
/// Count the number of leading zero bits in a mask.
/// Similar in behavior to the x86 instruction LZCNT.
@@ -218,6 +237,22 @@ public static int LeadingZeroCount(ulong value)
return LeadingZeroCount(hi);
}
+ ///
+ /// Count the number of leading zero bits in a mask.
+ /// Similar in behavior to the x86 instruction LZCNT.
+ ///
+ /// The value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static int LeadingZeroCount(nuint value)
+ {
+#if TARGET_64BIT
+ return LeadingZeroCount((ulong)value);
+#else
+ return LeadingZeroCount((uint)value);
+#endif
+ }
+
///
/// 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.
@@ -294,6 +329,22 @@ public static int Log2(ulong value)
return 32 + Log2(hi);
}
+ ///
+ /// 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.
+ ///
+ /// The value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static int Log2(nuint value)
+ {
+#if TARGET_64BIT
+ return Log2((ulong)value);
+#else
+ return Log2((uint)value);
+#endif
+ }
+
///
/// 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.
@@ -432,6 +483,22 @@ static int SoftwareFallback(ulong value)
#endif
}
+ ///
+ /// Returns the population count (number of bits set) of a mask.
+ /// Similar in behavior to the x86 instruction POPCNT.
+ ///
+ /// The value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static int PopCount(nuint value)
+ {
+#if TARGET_64BIT
+ return PopCount((ulong)value);
+#else
+ return PopCount((uint)value);
+#endif
+ }
+
///
/// Count the number of trailing zero bits in an integer value.
/// Similar in behavior to the x86 instruction TZCNT.
@@ -525,6 +592,31 @@ public static int TrailingZeroCount(ulong value)
return TrailingZeroCount(lo);
}
+ ///
+ /// Count the number of trailing zero bits in a mask.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ ///
+ /// The value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int TrailingZeroCount(nint value)
+ => TrailingZeroCount((nuint)value);
+
+ ///
+ /// Count the number of trailing zero bits in a mask.
+ /// Similar in behavior to the x86 instruction TZCNT.
+ ///
+ /// The value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static int TrailingZeroCount(nuint value)
+ {
+#if TARGET_64BIT
+ return TrailingZeroCount((ulong)value);
+#else
+ return TrailingZeroCount((uint)value);
+#endif
+ }
+
///
/// Rotates the specified value left by the specified number of bits.
/// Similar in behavior to the x86 instruction ROL.
@@ -551,6 +643,26 @@ public static uint RotateLeft(uint value, int offset)
public static ulong RotateLeft(ulong value, int offset)
=> (value << offset) | (value >> (64 - offset));
+ ///
+ /// Rotates the specified value left by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROL.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32 on a 32-bit process,
+ /// and any value outside the range [0..63] is treated as congruent mod 64 on a 64-bit process.
+ /// The rotated value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static nuint RotateLeft(nuint value, int offset)
+ {
+#if TARGET_64BIT
+ return (nuint)RotateLeft((ulong)value, offset);
+#else
+ return (nuint)RotateLeft((uint)value, offset);
+#endif
+ }
+
///
/// Rotates the specified value right by the specified number of bits.
/// Similar in behavior to the x86 instruction ROR.
@@ -576,5 +688,25 @@ public static uint RotateRight(uint value, int offset)
[CLSCompliant(false)]
public static ulong RotateRight(ulong value, int offset)
=> (value >> offset) | (value << (64 - offset));
+
+ ///
+ /// Rotates the specified value right by the specified number of bits.
+ /// Similar in behavior to the x86 instruction ROR.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate by.
+ /// Any value outside the range [0..31] is treated as congruent mod 32 on a 32-bit process,
+ /// and any value outside the range [0..63] is treated as congruent mod 64 on a 64-bit process.
+ /// The rotated value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static nuint RotateRight(nuint value, int offset)
+ {
+#if TARGET_64BIT
+ return (nuint)RotateRight((ulong)value, offset);
+#else
+ return (nuint)RotateRight((uint)value, offset);
+#endif
+ }
}
}
diff --git a/src/libraries/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj b/src/libraries/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
index 3333157e1ca028..10d77e4c9ec050 100644
--- a/src/libraries/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
+++ b/src/libraries/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
@@ -75,16 +75,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Numerics/BitOperationsTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/Numerics/BitOperationsTests.cs
index 7836538dbe7480..2bfc0d26ad6d29 100644
--- a/src/libraries/System.Runtime.Extensions/tests/System/Numerics/BitOperationsTests.cs
+++ b/src/libraries/System.Runtime.Extensions/tests/System/Numerics/BitOperationsTests.cs
@@ -93,6 +93,90 @@ public static void BitOps_IsPow2_ulong(ulong n, bool expected)
Assert.Equal(expected, actual);
}
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0, false)]
+ [InlineData(0b1, true)]
+ [InlineData(0b10, true)]
+ [InlineData(0b100, true)]
+ [InlineData(0b1000, true)]
+ [InlineData(0b10000, true)]
+ [InlineData(0b100000, true)]
+ [InlineData(0b1000000, true)]
+ [InlineData(-0b1000000, false)]
+ [InlineData(0b1000001, false)]
+ [InlineData(0b1010001, false)]
+ [InlineData(0b1111111, false)]
+ [InlineData(-1, false)]
+ [InlineData(int.MaxValue, false)]
+ [InlineData(int.MinValue, false)]
+ public static void BitOps_IsPow2_nint_32(int n, bool expected)
+ {
+ bool actual = BitOperations.IsPow2((nint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0, false)]
+ [InlineData(0b1, true)]
+ [InlineData(0b10, true)]
+ [InlineData(0b100, true)]
+ [InlineData(0b1000, true)]
+ [InlineData(0b10000, true)]
+ [InlineData(0b100000, true)]
+ [InlineData(0b1000000, true)]
+ [InlineData(-0b1000000, false)]
+ [InlineData(0b1000001, false)]
+ [InlineData(0b1010001, false)]
+ [InlineData(0b1111111, false)]
+ [InlineData(-1, false)]
+ [InlineData(long.MaxValue, false)]
+ [InlineData(long.MinValue, false)]
+ public static void BitOps_IsPow2_nint_64(long n, bool expected)
+ {
+ bool actual = BitOperations.IsPow2((nint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0u, false)]
+ [InlineData(0b1u, true)]
+ [InlineData(0b10u, true)]
+ [InlineData(0b100u, true)]
+ [InlineData(0b1000u, true)]
+ [InlineData(0b10000u, true)]
+ [InlineData(0b100000u, true)]
+ [InlineData(0b1000000u, true)]
+ [InlineData(0b1000001u, false)]
+ [InlineData(0b1010001u, false)]
+ [InlineData(0b1111111u, false)]
+ [InlineData(unchecked((uint)int.MinValue), true)]
+ [InlineData(uint.MaxValue, false)]
+ public static void BitOps_IsPow2_nuint_32(uint n, bool expected)
+ {
+ bool actual = BitOperations.IsPow2((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0u, false)]
+ [InlineData(0b1u, true)]
+ [InlineData(0b10u, true)]
+ [InlineData(0b100u, true)]
+ [InlineData(0b1000u, true)]
+ [InlineData(0b10000u, true)]
+ [InlineData(0b100000u, true)]
+ [InlineData(0b1000000u, true)]
+ [InlineData(0b1000001u, false)]
+ [InlineData(0b1010001u, false)]
+ [InlineData(0b1111111u, false)]
+ [InlineData(unchecked((uint)int.MinValue), true)]
+ [InlineData(ulong.MaxValue, false)]
+ public static void BitOps_IsPow2_nuint_64(ulong n, bool expected)
+ {
+ bool actual = BitOperations.IsPow2((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0u, 32)]
@@ -138,6 +222,51 @@ public static void BitOps_LeadingZeroCount_ulong(ulong n, int expected)
Assert.Equal(expected, actual);
}
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0u, 32)]
+ [InlineData(0b1u, 31)]
+ [InlineData(0b10u, 30)]
+ [InlineData(0b100u, 29)]
+ [InlineData(0b1000u, 28)]
+ [InlineData(0b10000u, 27)]
+ [InlineData(0b100000u, 26)]
+ [InlineData(0b1000000u, 25)]
+ [InlineData(byte.MaxValue << 17, 32 - 8 - 17)]
+ [InlineData(byte.MaxValue << 9, 32 - 8 - 9)]
+ [InlineData(ushort.MaxValue << 11, 32 - 16 - 11)]
+ [InlineData(ushort.MaxValue << 2, 32 - 16 - 2)]
+ [InlineData(5 << 7, 32 - 3 - 7)]
+ [InlineData(uint.MaxValue, 0)]
+ public static void BitOps_LeadingZeroCount_nuint_32(uint n, int expected)
+ {
+ int actual = BitOperations.LeadingZeroCount(n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0ul, 64)]
+ [InlineData(0b1ul, 63)]
+ [InlineData(0b10ul, 62)]
+ [InlineData(0b100ul, 61)]
+ [InlineData(0b1000ul, 60)]
+ [InlineData(0b10000ul, 59)]
+ [InlineData(0b100000ul, 58)]
+ [InlineData(0b1000000ul, 57)]
+ [InlineData((ulong)byte.MaxValue << 41, 64 - 8 - 41)]
+ [InlineData((ulong)byte.MaxValue << 53, 64 - 8 - 53)]
+ [InlineData((ulong)ushort.MaxValue << 31, 64 - 16 - 31)]
+ [InlineData((ulong)ushort.MaxValue << 15, 64 - 16 - 15)]
+ [InlineData(ulong.MaxValue >> 5, 5)]
+ [InlineData(1ul << 63, 0)]
+ [InlineData(1ul << 62, 1)]
+ [InlineData(ulong.MaxValue, 0)]
+ public static void BitOps_LeadingZeroCount_nuint_64(ulong n, int expected)
+ {
+ int actual = BitOperations.LeadingZeroCount(n);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0u, 32)]
[InlineData(0b1u, 0)]
@@ -228,6 +357,96 @@ public static void BitOps_TrailingZeroCount_long(long n, int expected)
Assert.Equal(expected, actual);
}
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0u, 32)]
+ [InlineData(0b1u, 0)]
+ [InlineData(0b10u, 1)]
+ [InlineData(0b100u, 2)]
+ [InlineData(0b1000u, 3)]
+ [InlineData(0b10000u, 4)]
+ [InlineData(0b100000u, 5)]
+ [InlineData(0b1000000u, 6)]
+ [InlineData((uint)byte.MaxValue << 24, 24)]
+ [InlineData((uint)byte.MaxValue << 22, 22)]
+ [InlineData((uint)ushort.MaxValue << 16, 16)]
+ [InlineData((uint)ushort.MaxValue << 19, 19)]
+ [InlineData(uint.MaxValue << 5, 5)]
+ [InlineData(3u << 27, 27)]
+ [InlineData(uint.MaxValue, 0)]
+ public static void BitOps_TrailingZeroCount_nuint_32(uint n, int expected)
+ {
+ int actual = BitOperations.TrailingZeroCount((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0ul, 64)]
+ [InlineData(0b1ul, 0)]
+ [InlineData(0b10ul, 1)]
+ [InlineData(0b100ul, 2)]
+ [InlineData(0b1000ul, 3)]
+ [InlineData(0b10000ul, 4)]
+ [InlineData(0b100000ul, 5)]
+ [InlineData(0b1000000ul, 6)]
+ [InlineData((ulong)byte.MaxValue << 40, 40)]
+ [InlineData((ulong)byte.MaxValue << 57, 57)]
+ [InlineData((ulong)ushort.MaxValue << 31, 31)]
+ [InlineData((ulong)ushort.MaxValue << 15, 15)]
+ [InlineData(ulong.MaxValue << 5, 5)]
+ [InlineData(3ul << 59, 59)]
+ [InlineData(5ul << 63, 63)]
+ [InlineData(ulong.MaxValue, 0)]
+ public static void BitOps_TrailingZeroCount_nuint_64(ulong n, int expected)
+ {
+ int actual = BitOperations.TrailingZeroCount((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0, 32)]
+ [InlineData(0b1, 0)]
+ [InlineData(0b10, 1)]
+ [InlineData(0b100, 2)]
+ [InlineData(0b1000, 3)]
+ [InlineData(0b10000, 4)]
+ [InlineData(0b100000, 5)]
+ [InlineData(0b1000000, 6)]
+ [InlineData(byte.MaxValue << 24, 24)]
+ [InlineData(byte.MaxValue << 22, 22)]
+ [InlineData(ushort.MaxValue << 16, 16)]
+ [InlineData(ushort.MaxValue << 19, 19)]
+ [InlineData(int.MaxValue << 5, 5)]
+ [InlineData(3 << 27, 27)]
+ [InlineData(int.MaxValue, 0)]
+ public static void BitOps_TrailingZeroCount_nint_32(int n, int expected)
+ {
+ int actual = BitOperations.TrailingZeroCount((nint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0L, 64)]
+ [InlineData(0b1L, 0)]
+ [InlineData(0b10L, 1)]
+ [InlineData(0b100L, 2)]
+ [InlineData(0b1000L, 3)]
+ [InlineData(0b10000L, 4)]
+ [InlineData(0b100000L, 5)]
+ [InlineData(0b1000000L, 6)]
+ [InlineData((long)byte.MaxValue << 40, 40)]
+ [InlineData((long)byte.MaxValue << 57, 57)]
+ [InlineData((long)ushort.MaxValue << 31, 31)]
+ [InlineData((long)ushort.MaxValue << 15, 15)]
+ [InlineData(long.MaxValue << 5, 5)]
+ [InlineData(3L << 59, 59)]
+ [InlineData(5L << 63, 63)]
+ [InlineData(long.MaxValue, 0)]
+ public static void BitOps_TrailingZeroCount_nint_64(long n, int expected)
+ {
+ int actual = BitOperations.TrailingZeroCount((nint) n);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0, 0)]
[InlineData(1, 0)]
@@ -269,6 +488,47 @@ public static void BitOps_Log2_ulong(ulong n, int expected)
Assert.Equal(expected, actual);
}
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0, 0)]
+ [InlineData(1, 0)]
+ [InlineData(2, 1)]
+ [InlineData(3, 2 - 1)]
+ [InlineData(4, 2)]
+ [InlineData(5, 3 - 1)]
+ [InlineData(6, 3 - 1)]
+ [InlineData(7, 3 - 1)]
+ [InlineData(8, 3)]
+ [InlineData(9, 4 - 1)]
+ [InlineData(byte.MaxValue, 8 - 1)]
+ [InlineData(ushort.MaxValue, 16 - 1)]
+ [InlineData(uint.MaxValue, 32 - 1)]
+ public static void BitOps_Log2_nuint_32(uint n, int expected)
+ {
+ int actual = BitOperations.Log2((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0, 0)]
+ [InlineData(1, 0)]
+ [InlineData(2, 1)]
+ [InlineData(3, 2 - 1)]
+ [InlineData(4, 2)]
+ [InlineData(5, 3 - 1)]
+ [InlineData(6, 3 - 1)]
+ [InlineData(7, 3 - 1)]
+ [InlineData(8, 3)]
+ [InlineData(9, 4 - 1)]
+ [InlineData(byte.MaxValue, 8 - 1)]
+ [InlineData(ushort.MaxValue, 16 - 1)]
+ [InlineData(uint.MaxValue, 32 - 1)]
+ [InlineData(ulong.MaxValue, 64 - 1)]
+ public static void BitOps_Log2_nuint_64(ulong n, int expected)
+ {
+ int actual = BitOperations.Log2((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0b001, 1)]
[InlineData(0b010, 1)]
@@ -337,6 +597,61 @@ public static void BitOps_PopCount_ulong(ulong n, int expected)
Assert.Equal(expected, actual);
}
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0b001, 1)]
+ [InlineData(0b010, 1)]
+ [InlineData(0b011, 2)]
+ [InlineData(0b100, 1)]
+ [InlineData(0b101, 2)]
+ [InlineData(0b110, 2)]
+ [InlineData(0b111, 3)]
+ [InlineData(0b1101, 3)]
+ [InlineData(0b1111, 4)]
+ [InlineData(0b10111, 4)]
+ [InlineData(0b11111, 5)]
+ [InlineData(0b110111, 5)]
+ [InlineData(0b111111, 6)]
+ [InlineData(0b1111110, 6)]
+ public static void BitOps_PopCount_nuint_32(uint n, int expected)
+ {
+ int actual = BitOperations.PopCount((nuint) n);
+ Assert.Equal(expected, actual);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0b001, 1)]
+ [InlineData(0b010, 1)]
+ [InlineData(0b011, 2)]
+ [InlineData(0b100, 1)]
+ [InlineData(0b101, 2)]
+ [InlineData(0b110, 2)]
+ [InlineData(0b111, 3)]
+ [InlineData(0b1101, 3)]
+ [InlineData(0b1111, 4)]
+ [InlineData(0b10111, 4)]
+ [InlineData(0b11111, 5)]
+ [InlineData(0b110111, 5)]
+ [InlineData(0b111111, 6)]
+ [InlineData(0b1111110, 6)]
+ [InlineData(0b1111111, 7)]
+ [InlineData(byte.MinValue, 0)] // 0
+ [InlineData(byte.MaxValue, 8)] // 255
+ [InlineData(unchecked((ulong)sbyte.MinValue), 57)] // 18446744073709551488
+ [InlineData(sbyte.MaxValue, 7)] // 127
+ [InlineData(ushort.MaxValue, 16)] // 65535
+ [InlineData(unchecked((ulong)short.MinValue), 49)] // 18446744073709518848
+ [InlineData(short.MaxValue, 15)] // 32767
+ [InlineData(unchecked((ulong)int.MinValue), 64 - 31)] // 18446744071562067968
+ [InlineData(int.MaxValue, 31)] // 2147483647
+ [InlineData(ulong.MaxValue >> 9, 64 - 9)] // 36028797018963967
+ [InlineData(ulong.MaxValue << 11, 64 - 11)] // 18446744073709549568
+ [InlineData(ulong.MaxValue, 64)]
+ public static void BitOps_PopCount_nuint_64(ulong n, int expected)
+ {
+ int actual = BitOperations.PopCount((nuint)n);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0b00000000_00000000_00000000_00000001u, int.MaxValue, 0b10000000_00000000_00000000_00000000u)] // % 32 = 31
[InlineData(0b01000000_00000001_00000000_00000001u, 3, 0b00000000_00001000_00000000_00001010u)]
@@ -352,6 +667,50 @@ public static void BitOps_RotateLeft_uint(uint n, int offset, uint expected)
Assert.Equal(expected, BitOperations.RotateLeft(n, offset));
}
+ [Fact]
+ public static void BitOps_RotateLeft_nuint()
+ {
+ unchecked
+ {
+ if (Environment.Is64BitProcess)
+ {
+ nuint value = (nuint)0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101ul;
+ Assert.Equal((nuint)0b10101010_10101010_10101010_10101010_10101010_10101010_10101010_10101010ul,
+ BitOperations.RotateLeft(value, 1));
+ Assert.Equal((nuint)0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101ul,
+ BitOperations.RotateLeft(value, 2));
+ Assert.Equal((nuint)0b10101010_10101010_10101010_10101010_10101010_10101010_10101010_10101010ul,
+ BitOperations.RotateLeft(value, 3));
+ Assert.Equal(value, BitOperations.RotateLeft(value, int.MinValue)); // % 64 = 0
+ Assert.Equal(BitOperations.RotateLeft(value, 63),
+ BitOperations.RotateLeft(value, int.MaxValue)); // % 64 = 63
+ }
+ else
+ {
+ Assert.Equal((nuint)0b10000000_00000000_00000000_00000000u,
+ BitOperations.RotateLeft((nuint)0b00000000_00000000_00000000_00000001u,
+ int.MaxValue)); // % 32 = 31
+ Assert.Equal((nuint)0b00000000_00001000_00000000_00001010u,
+ BitOperations.RotateLeft((nuint)0b01000000_00000001_00000000_00000001u, 3));
+ Assert.Equal((nuint)0b00000000_00000100_00000000_00000101u,
+ BitOperations.RotateLeft((nuint)0b01000000_00000001_00000000_00000001u, 2));
+ Assert.Equal((nuint)0b10101010_10101010_10101010_10101010u,
+ BitOperations.RotateLeft((nuint)0b01010101_01010101_01010101_01010101u, 1));
+ Assert.Equal((nuint)0b01010101_11111111_01010101_01010101u,
+ BitOperations.RotateLeft((nuint)0b01010101_11111111_01010101_01010101u, 0));
+ Assert.Equal((nuint)0b10000000_00000000_00000000_00000000u,
+ BitOperations.RotateLeft((nuint)0b00000000_00000000_00000000_00000001u, -1));
+ Assert.Equal((nuint)0b01000000_00000000_00000000_00000000u,
+ BitOperations.RotateLeft((nuint)0b00000000_00000000_00000000_00000001u, -2));
+ Assert.Equal((nuint)0b00100000_00000000_00000000_00000000u,
+ BitOperations.RotateLeft((nuint)0b00000000_00000000_00000000_00000001u, -3));
+ Assert.Equal((nuint)0b01010101_11111111_01010101_01010101u,
+ BitOperations.RotateLeft((nuint)0b01010101_11111111_01010101_01010101u,
+ int.MinValue)); // % 32 = 0
+ }
+ }
+ }
+
[Fact]
public static void BitOps_RotateLeft_ulong()
{
@@ -389,6 +748,50 @@ public static void BitOps_RotateRight_ulong()
Assert.Equal(BitOperations.RotateLeft(value, 63), BitOperations.RotateRight(value, int.MaxValue)); // % 64 = 63
}
+ [Fact]
+ public static void BitOps_RotateRight_nuint()
+ {
+ unchecked
+ {
+ if (Environment.Is64BitProcess)
+ {
+ const ulong value = 0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101ul;
+ Assert.Equal(0b10101010_10101010_10101010_10101010_10101010_10101010_10101010_10101010ul,
+ BitOperations.RotateRight(value, 1));
+ Assert.Equal(0b01010101_01010101_01010101_01010101_01010101_01010101_01010101_01010101ul,
+ BitOperations.RotateRight(value, 2));
+ Assert.Equal(0b10101010_10101010_10101010_10101010_10101010_10101010_10101010_10101010ul,
+ BitOperations.RotateRight(value, 3));
+ Assert.Equal(value, BitOperations.RotateRight(value, int.MinValue)); // % 64 = 0
+ Assert.Equal(BitOperations.RotateLeft(value, 63),
+ BitOperations.RotateRight(value, int.MaxValue)); // % 64 = 63
+ }
+ else
+ {
+ Assert.Equal((nuint)0b00000000_00000000_00000000_00000001u,
+ BitOperations.RotateRight((nuint)0b10000000_00000000_00000000_00000000u,
+ int.MaxValue)); // % 32 = 31
+ Assert.Equal((nuint)0b01000000_00000001_00000000_00000001u,
+ BitOperations.RotateRight((nuint)0b00000000_00001000_00000000_00001010u, 3));
+ Assert.Equal((nuint)0b01000000_00000001_00000000_00000001u,
+ BitOperations.RotateRight((nuint)0b00000000_00000100_00000000_00000101u, 2));
+ Assert.Equal((nuint)0b10101010_10101010_10101010_10101010u,
+ BitOperations.RotateRight((nuint)0b01010101_01010101_01010101_01010101u, 1));
+ Assert.Equal((nuint)0b01010101_11111111_01010101_01010101u,
+ BitOperations.RotateRight((nuint)0b01010101_11111111_01010101_01010101u, 0));
+ Assert.Equal((nuint)0b00000000_00000000_00000000_00000001u,
+ BitOperations.RotateRight((nuint)0b10000000_00000000_00000000_00000000u, -1));
+ Assert.Equal((nuint)0b00000000_00000000_00000001_00000000u,
+ BitOperations.RotateRight((nuint)0b00000000_00000000_00000000_01000000u, -2));
+ Assert.Equal((nuint)0b00000000_00000000_00000000_00000010u,
+ BitOperations.RotateRight((nuint)0b01000000_00000000_00000000_00000000u, -3));
+ Assert.Equal((nuint)0b01010101_11111111_01010101_01010101u,
+ BitOperations.RotateRight((nuint)0b01010101_11111111_01010101_01010101u,
+ int.MinValue)); // % 32 = 0
+ }
+ }
+ }
+
[Theory]
[InlineData(0u, 0u)]
[InlineData(1u, 1u)]
@@ -436,5 +839,53 @@ public static void BitOps_RoundUpToPow2_ulong(ulong value, ulong expected)
{
Assert.Equal(expected, BitOperations.RoundUpToPowerOf2(value));
}
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))]
+ [InlineData(0u, 0u)]
+ [InlineData(1u, 1u)]
+ [InlineData(2u, 2u)]
+ [InlineData(0x0096u, 0x0100u)]
+ [InlineData(0x05CDu, 0x0800u)]
+ [InlineData(0x0932u, 0x1000u)]
+ [InlineData(0x0004_C911u, 0x0008_0000u)]
+ [InlineData(0x00E0_A2E2u, 0x0100_0000u)]
+ [InlineData(0x0988_0713u, 0x1000_0000u)]
+ [InlineData(0x30A4_9649u, 0x4000_0000u)]
+ [InlineData(0x7FFF_FFFFu, 0x8000_0000u)]
+ [InlineData(0x8000_0000u, 0x8000_0000u)]
+ [InlineData(0x8000_0001u, 0ul)]
+ [InlineData(0xFFFF_FFFFu, 0ul)]
+ public static void BitOps_RoundUpToPow2_nuint_32(uint value, uint expected)
+ {
+ Assert.Equal(expected, BitOperations.RoundUpToPowerOf2((nuint) value));
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [InlineData(0ul, 0ul)]
+ [InlineData(1ul, 1ul)]
+ [InlineData(2ul, 2ul)]
+ [InlineData(0x0096ul, 0x0100ul)]
+ [InlineData(0x05cdul, 0x0800ul)]
+ [InlineData(0x0932ul, 0x1000ul)]
+ [InlineData(0x0004_c911ul, 0x0008_0000ul)]
+ [InlineData(0x00e0_a2b2ul, 0x0100_0000ul)]
+ [InlineData(0x0988_0713ul, 0x1000_0000ul)]
+ [InlineData(0x30a4_9649ul, 0x4000_0000ul)]
+ [InlineData(0x7FFF_FFFFul, 0x8000_0000ul)]
+ [InlineData(0x8000_0000ul, 0x8000_0000ul)]
+ [InlineData(0x8000_0001ul, 0x1_0000_0000ul)]
+ [InlineData(0xFFFF_FFFFul, 0x1_0000_0000ul)]
+ [InlineData(0x0000_0003_343B_0D81ul, 0x0000_0004_0000_0000ul)]
+ [InlineData(0x0000_0D87_5EE2_8F19ul, 0x0000_1000_0000_0000ul)]
+ [InlineData(0x0006_2A08_4A7A_3A2Dul, 0x0008_0000_0000_0000ul)]
+ [InlineData(0x0101_BF76_4398_F791ul, 0x0200_0000_0000_0000ul)]
+ [InlineData(0x7FFF_FFFF_FFFF_FFFFul, 0x8000_0000_0000_0000ul)]
+ [InlineData(0x8000_0000_0000_0000ul, 0x8000_0000_0000_0000ul)]
+ [InlineData(0x8000_0000_0000_0001ul, 0ul)]
+ [InlineData(0xFFFF_FFFF_FFFF_FFFFul, 0ul)]
+ public static void BitOps_RoundUpToPow2_nuint_64(ulong value, ulong expected)
+ {
+ Assert.Equal(expected, BitOperations.RoundUpToPowerOf2((nuint) value));
+ }
}
}
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index 5de2f8d1c1605d..2d2f3ac15fbf05 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -11017,36 +11017,54 @@ public static partial class BitOperations
public static bool IsPow2(long value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static bool IsPow2(ulong value) { throw null; }
+ public static bool IsPow2(nint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool IsPow2(nuint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int LeadingZeroCount(uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int LeadingZeroCount(ulong value) { throw null; }
[System.CLSCompliantAttribute(false)]
+ public static int LeadingZeroCount(nuint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
public static int Log2(uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int Log2(ulong value) { throw null; }
[System.CLSCompliantAttribute(false)]
+ public static int Log2(nuint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
public static int PopCount(uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int PopCount(ulong value) { throw null; }
[System.CLSCompliantAttribute(false)]
+ public static int PopCount(nuint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
public static uint RotateLeft(uint value, int offset) { throw null; }
[System.CLSCompliantAttribute(false)]
public static ulong RotateLeft(ulong value, int offset) { throw null; }
[System.CLSCompliantAttribute(false)]
+ public static nuint RotateLeft(nuint value, int offset) { throw null; }
+ [System.CLSCompliantAttribute(false)]
public static uint RotateRight(uint value, int offset) { throw null; }
[System.CLSCompliantAttribute(false)]
public static ulong RotateRight(ulong value, int offset) { throw null; }
[System.CLSCompliantAttribute(false)]
+ public static nuint RotateRight(nuint value, int offset) { throw null; }
+ [System.CLSCompliantAttribute(false)]
public static uint RoundUpToPowerOf2(uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static ulong RoundUpToPowerOf2(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static nuint RoundUpToPowerOf2(nuint value) { throw null; }
public static int TrailingZeroCount(int value) { throw null; }
public static int TrailingZeroCount(long value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int TrailingZeroCount(uint value) { throw null; }
[System.CLSCompliantAttribute(false)]
public static int TrailingZeroCount(ulong value) { throw null; }
+ public static int TrailingZeroCount(nint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int TrailingZeroCount(nuint value) { throw null; }
}
}
namespace System.Reflection