diff --git a/src/Numerics/Euclid.cs b/src/Numerics/Euclid.cs
index 808505c2..394884e5 100644
--- a/src/Numerics/Euclid.cs
+++ b/src/Numerics/Euclid.cs
@@ -271,6 +271,27 @@ namespace MathNet.Numerics
return ((long)1) << (int)exponent;
}
+ ///
+ /// Evaluate the binary logarithm of an integer number.
+ ///
+ /// Two-step method using a De Bruijn-like sequence table lookup.
+ public static int Log2(this int number)
+ {
+ number |= number >> 1;
+ number |= number >> 2;
+ number |= number >> 4;
+ number |= number >> 8;
+ number |= number >> 16;
+
+ return MultiplyDeBruijnBitPosition[(uint)(number * 0x07C4ACDDU) >> 27];
+ }
+
+ static readonly int[] MultiplyDeBruijnBitPosition = new int[32]
+ {
+ 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
+ 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
+ };
+
///
/// Find the closest perfect power of two that is larger or equal to the provided
/// 32 bit integer.
diff --git a/src/UnitTests/EuclidTests/IntegerTheoryTest.cs b/src/UnitTests/EuclidTests/IntegerTheoryTest.cs
index 7df6eeaf..9d8db87d 100644
--- a/src/UnitTests/EuclidTests/IntegerTheoryTest.cs
+++ b/src/UnitTests/EuclidTests/IntegerTheoryTest.cs
@@ -442,6 +442,24 @@ namespace MathNet.Numerics.UnitTests.EuclidTests
() => ((long)0).PowerOfTwo());
}
+ ///
+ /// Log2 matches floating point for int32.
+ ///
+ [Test]
+ public void Log2MatchesFloatingPoint32()
+ {
+ for (var i = 0; i < 31; i++)
+ {
+ int number = i.PowerOfTwo();
+ Assert.AreEqual((int)Math.Log(number, 2), number.Log2());
+ Assert.AreEqual((int)Math.Log(number + 1, 2), (number + 1).Log2());
+ if (number > 1)
+ {
+ Assert.AreEqual((int)Math.Log(number - 1, 2), (number - 1).Log2());
+ }
+ }
+ }
+
///
/// Test if int32 is perfect square.
///