mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 19:28:48 +00:00
Add PopCount for built-in integer types
This commit is contained in:
parent
7231c41466
commit
b1eadf61f4
@ -14,6 +14,7 @@
|
||||
- X10D: Added `Point.ToVector2()`
|
||||
- X10D: Added `PointF.ToSizeF()`
|
||||
- X10D: Added `PointF.ToVector2()` for .NET < 6
|
||||
- X10D: Added `PopCount()` for built-in integer types
|
||||
- X10D: Added `RoundUpToPowerOf2()` for built-in integer types
|
||||
- X10D: Added `Size.ToPoint()`
|
||||
- X10D: Added `Size.ToPointF()`
|
||||
|
@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
|
||||
[TestClass]
|
||||
public class ByteTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, ((byte)0).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, ((byte)0b11010101).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe8_Given11111111()
|
||||
{
|
||||
Assert.AreEqual(8, ((byte)0b11111111).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
|
||||
[TestClass]
|
||||
public class Int16Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, ((short)0).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, ((short)0b11010101).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe15_Given0111111111111111()
|
||||
{
|
||||
Assert.AreEqual(15, ((short)0b0111111111111111).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
|
||||
[TestClass]
|
||||
public class Int32Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, ((uint)0).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, ((uint)0b11010101).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe31_Given11111111111111111111111111111111()
|
||||
{
|
||||
Assert.AreEqual(31, 0b01111111111111111111111111111111.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
|
||||
[TestClass]
|
||||
public class Int64Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, 0L.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, 0b11010101L.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe63_Given0111111111111111111111111111111111111111111111111111111111111111()
|
||||
{
|
||||
Assert.AreEqual(63, 0b0111111111111111111111111111111111111111111111111111111111111111L.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public class SByteTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, ((sbyte)0).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe4_Given01010101()
|
||||
{
|
||||
Assert.AreEqual(4, ((sbyte)0b01010101).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe7_Given01111111()
|
||||
{
|
||||
Assert.AreEqual(7, ((sbyte)0b01111111).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public class UInt16Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, ((ushort)0).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, ((ushort)0b11010101).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe16_Given1111111111111111()
|
||||
{
|
||||
Assert.AreEqual(16, ((ushort)0b1111111111111111).PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public class UInt32Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, 0U.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, 0b11010101U.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe32_Given11111111111111111111111111111111()
|
||||
{
|
||||
Assert.AreEqual(32, 0b11111111111111111111111111111111U.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public class UInt64Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe0_Given0()
|
||||
{
|
||||
Assert.AreEqual(0, 0UL.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe5_Given11010101()
|
||||
{
|
||||
Assert.AreEqual(5, 0b11010101UL.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PopCount_ShouldBe64_Given1111111111111111111111111111111111111111111111111111111111111111()
|
||||
{
|
||||
Assert.AreEqual(64, 0b1111111111111111111111111111111111111111111111111111111111111111UL.PopCount());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RotateLeft_ShouldRotateCorrectly()
|
||||
{
|
||||
|
@ -9,6 +9,26 @@ namespace X10D.Numerics;
|
||||
/// </summary>
|
||||
public static class ByteExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this byte value)
|
||||
{
|
||||
return ((uint)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -8,6 +8,26 @@ namespace X10D.Numerics;
|
||||
/// </summary>
|
||||
public static class Int16Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this short value)
|
||||
{
|
||||
return ((uint)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -8,6 +8,26 @@ namespace X10D.Numerics;
|
||||
/// </summary>
|
||||
public static class Int32Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this int value)
|
||||
{
|
||||
return ((uint)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -8,6 +8,26 @@ namespace X10D.Numerics;
|
||||
/// </summary>
|
||||
public static class Int64Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this long value)
|
||||
{
|
||||
return ((ulong)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -9,6 +9,26 @@ namespace X10D.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public static class SByteExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this sbyte value)
|
||||
{
|
||||
return ((uint)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace X10D.Numerics;
|
||||
@ -9,6 +10,26 @@ namespace X10D.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt16Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this ushort value)
|
||||
{
|
||||
return ((uint)value).PopCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -10,6 +10,39 @@ namespace X10D.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt32Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this uint value)
|
||||
{
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
return BitOperations.PopCount(value);
|
||||
#else
|
||||
const uint c1 = 0x_55555555u;
|
||||
const uint c2 = 0x_33333333u;
|
||||
const uint c3 = 0x_0F0F0F0Fu;
|
||||
const uint c4 = 0x_01010101u;
|
||||
|
||||
value -= (value >> 1) & c1;
|
||||
value = (value & c2) + ((value >> 2) & c2);
|
||||
value = (((value + (value >> 4)) & c3) * c4) >> 24;
|
||||
|
||||
return (int)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
@ -10,6 +10,39 @@ namespace X10D.Numerics;
|
||||
[CLSCompliant(false)]
|
||||
public static class UInt64Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the population count (number of bits set) of a mask.
|
||||
/// </summary>
|
||||
/// <param name="value">The mask.</param>
|
||||
/// <returns>The population count of <paramref name="value" />.</returns>
|
||||
/// <remarks>
|
||||
/// This method is similar in behavior to the x86 instruction
|
||||
/// <a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.x86.popcnt?view=net-6.0">POPCNT</a>
|
||||
/// </remarks>
|
||||
[Pure]
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static int PopCount(this ulong value)
|
||||
{
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
return BitOperations.PopCount(value);
|
||||
#else
|
||||
const uint c1 = 0x_55555555u;
|
||||
const uint c2 = 0x_33333333u;
|
||||
const uint c3 = 0x_0F0F0F0Fu;
|
||||
const uint c4 = 0x_01010101u;
|
||||
|
||||
value -= (value >> 1) & c1;
|
||||
value = (value & c2) + ((value >> 2) & c2);
|
||||
value = (((value + (value >> 4)) & c3) * c4) >> 24;
|
||||
|
||||
return (int)value;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the current value left by the specified number of bits.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user