Browse Source

Euclid: Log2 implementation using DeBruijn sequence lookup

netstandard
Christoph Ruegg 10 years ago
parent
commit
00eda31645
  1. 21
      src/Numerics/Euclid.cs
  2. 18
      src/UnitTests/EuclidTests/IntegerTheoryTest.cs

21
src/Numerics/Euclid.cs

@ -271,6 +271,27 @@ namespace MathNet.Numerics
return ((long)1) << (int)exponent;
}
/// <summary>
/// Evaluate the binary logarithm of an integer number.
/// </summary>
/// <remarks>Two-step method using a De Bruijn-like sequence table lookup.</remarks>
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
};
/// <summary>
/// Find the closest perfect power of two that is larger or equal to the provided
/// 32 bit integer.

18
src/UnitTests/EuclidTests/IntegerTheoryTest.cs

@ -442,6 +442,24 @@ namespace MathNet.Numerics.UnitTests.EuclidTests
() => ((long)0).PowerOfTwo());
}
/// <summary>
/// Log2 matches floating point for int32.
/// </summary>
[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());
}
}
}
/// <summary>
/// Test if int32 is perfect square.
/// </summary>

Loading…
Cancel
Save