From 645148a75122f6d28cac2c5449df845b043332b4 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Mon, 22 Nov 2010 18:05:55 +0000 Subject: [PATCH] Added methods for counting the number of bits set in integers git-svn-id: file:///srv/devel/repo-conversion/nusu@210 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/IntegerHelper.Test.cs | 25 ++++++++++++++++++ Source/IntegerHelper.cs | 50 ++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Source/IntegerHelper.Test.cs b/Source/IntegerHelper.Test.cs index 18cc89d..0aaa93b 100644 --- a/Source/IntegerHelper.Test.cs +++ b/Source/IntegerHelper.Test.cs @@ -97,6 +97,31 @@ namespace Nuclex.Support { Assert.AreEqual(1073741824, IntegerHelper.NextPowerOf2(1073741824)); } + /// Verifies that the bit counting method for integers works + [Test] + public void TestCountBitsInInteger() { + Assert.AreEqual(0, IntegerHelper.CountBits(0)); + Assert.AreEqual(32, IntegerHelper.CountBits(-1)); + Assert.AreEqual(16, IntegerHelper.CountBits(0x55555555)); + Assert.AreEqual(16, IntegerHelper.CountBits(0xAAAAAAAA)); + + for (int bitIndex = 0; bitIndex < 32; ++bitIndex) { + Assert.AreEqual(1, IntegerHelper.CountBits(1 << bitIndex)); + } + } + + /// Verifies that the bit counting method for long integers works + [Test] + public void TestCountBitsInLongInteger() { + Assert.AreEqual(0, IntegerHelper.CountBits(0L)); + Assert.AreEqual(64, IntegerHelper.CountBits(-1L)); + Assert.AreEqual(32, IntegerHelper.CountBits(0x5555555555555555)); + Assert.AreEqual(32, IntegerHelper.CountBits(0xAAAAAAAAAAAAAAAA)); + + for (int bitIndex = 0; bitIndex < 64; ++bitIndex) { + Assert.AreEqual(1, IntegerHelper.CountBits(1 << bitIndex)); + } + } } diff --git a/Source/IntegerHelper.cs b/Source/IntegerHelper.cs index 1991106..9090d2f 100644 --- a/Source/IntegerHelper.cs +++ b/Source/IntegerHelper.cs @@ -37,7 +37,7 @@ namespace Nuclex.Support { /// Value of which to return the next highest power of 2 /// The next highest power of 2 to the value public static ulong NextPowerOf2(this ulong value) { - if(value == 0) + if (value == 0) return 1; --value; @@ -63,7 +63,7 @@ namespace Nuclex.Support { /// Value of which to return the next highest power of 2 /// The next highest power of 2 to the value public static uint NextPowerOf2(this uint value) { - if(value == 0) + if (value == 0) return 1; --value; @@ -77,6 +77,52 @@ namespace Nuclex.Support { return value; } + /// Returns the number of bits set in an + /// Value whose bits will be counted + /// The number of bits set in the integer + public static int CountBits(this int value) { + return CountBits((uint)value); + } + + /// Returns the number of bits set in an unsigned integer + /// Value whose bits will be counted + /// The number of bits set in the unsigned integer + /// + /// Based on a trick revealed here: + /// http://stackoverflow.com/questions/109023 + /// + public static int CountBits(this uint value) { + value = value - ((value >> 1) & 0x55555555); + value = (value & 0x33333333) + ((value >> 2) & 0x33333333); + + return (int)unchecked( + ((value + (value >> 4) & 0xF0F0F0F) * 0x1010101) >> 24 + ); + } + + /// Returns the number of bits set in a long integer + /// Value whose bits will be counted + /// The number of bits set in the long integer + public static int CountBits(this long value) { + return CountBits((ulong)value); + } + + /// Returns the number of bits set in an unsigned long integer + /// Value whose bits will be counted + /// The number of bits set in the unsigned long integer + /// + /// Based on a trick revealed here: + /// http://stackoverflow.com/questions/2709430 + /// + public static int CountBits(this ulong value) { + value = value - ((value >> 1) & 0x5555555555555555UL); + value = (value & 0x3333333333333333UL) + ((value >> 2) & 0x3333333333333333UL); + + return (int)unchecked( + (((value + (value >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56 + ); + } + } } // namespace Nuclex.Support