Browse Source

number theory: ceiling to power of two

Signed-off-by: Christoph Ruegg <git@cdrnet.ch>
pull/36/head
Christoph Ruegg 17 years ago
parent
commit
0d2e546431
  1. 100
      src/Managed.UnitTests/NumberTheoryTests/IntegerTheoryTest.cs
  2. 59
      src/Managed/NumberTheory/IntegerTheory.cs

100
src/Managed.UnitTests/NumberTheoryTests/IntegerTheoryTest.cs

@ -131,6 +131,106 @@ namespace MathNet.Numerics.UnitTests.NumberTheoryTests
Assert.IsFalse(IntegerTheory.IsPowerOfTwo(Int64.MaxValue-1), "Int32.MaxValue-1 (-)");
}
[Test]
public void CeilingToPowerOfHandlesPositiveIntegersCorrectly32()
{
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(0), "0");
Assert.AreEqual(1, IntegerTheory.CeilingToPowerOfTwo(1), "1");
Assert.AreEqual(2, IntegerTheory.CeilingToPowerOfTwo(2), "2");
Assert.AreEqual(4, IntegerTheory.CeilingToPowerOfTwo(3), "3");
Assert.AreEqual(4, IntegerTheory.CeilingToPowerOfTwo(4), "4");
for (int i = 2; i < 31; i++)
{
int x = 1 << i;
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo(x), x.ToString());
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo(x - 1), x + "-1");
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo((x >> 1) + 1), x + "/2+1");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-x), "-" + x);
}
const int maxPowerOfTwo = 0x40000000;
Assert.AreEqual(maxPowerOfTwo, IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo), "max");
Assert.AreEqual(maxPowerOfTwo, IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo - 1), "max");
}
[Test]
public void CeilingToPowerOfHandlesPositiveIntegersCorrectly64()
{
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo((long)0), "0");
Assert.AreEqual(1, IntegerTheory.CeilingToPowerOfTwo((long)1), "1");
Assert.AreEqual(2, IntegerTheory.CeilingToPowerOfTwo((long)2), "2");
Assert.AreEqual(4, IntegerTheory.CeilingToPowerOfTwo((long)3), "3");
Assert.AreEqual(4, IntegerTheory.CeilingToPowerOfTwo((long)4), "4");
for (int i = 2; i < 63; i++)
{
long x = ((long)1) << i;
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo(x), x.ToString());
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo(x - 1), x + "-1");
Assert.AreEqual(x, IntegerTheory.CeilingToPowerOfTwo((x >> 1) + 1), x + "/2+1");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-x), "-" + x);
}
const long maxPowerOfTwo = 0x4000000000000000;
Assert.AreEqual(maxPowerOfTwo, IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo), "max");
Assert.AreEqual(maxPowerOfTwo, IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo - 1), "max");
}
[Test]
public void CeilingToPowerOfTwoReturnsZeroForNegativeNumbers32()
{
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-1), "-1");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-2), "-2");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-3), "-3");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(-4), "-4");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(Int32.MinValue), "Int32.MinValue");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(Int32.MinValue + 1), "Int32.MinValue+1");
}
[Test]
public void CeilingToPowerOfTwoReturnsZeroForNegativeNumbers64()
{
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo((long)-1), "-1");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo((long)-2), "-2");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo((long)-3), "-3");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo((long)-4), "-4");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(Int64.MinValue), "Int64.MinValue");
Assert.AreEqual(0, IntegerTheory.CeilingToPowerOfTwo(Int64.MinValue + 1), "Int64.MinValue+1");
}
[Test]
public void CeilingToPowerOfTwoThrowsWhenResultWouldOverflow32()
{
Assert.Throws(
typeof (ArgumentOutOfRangeException),
() => IntegerTheory.CeilingToPowerOfTwo(Int32.MaxValue));
const int maxPowerOfTwo = 0x40000000;
Assert.Throws(
typeof(ArgumentOutOfRangeException),
() => IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo + 1));
Assert.DoesNotThrow(
() => IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo - 1));
}
[Test]
public void CeilingToPowerOfTwoThrowsWhenResultWouldOverflow64()
{
Assert.Throws(
typeof(ArgumentOutOfRangeException),
() => IntegerTheory.CeilingToPowerOfTwo(Int64.MaxValue));
const long maxPowerOfTwo = 0x4000000000000000;
Assert.Throws(
typeof(ArgumentOutOfRangeException),
() => IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo + 1));
Assert.DoesNotThrow(
() => IntegerTheory.CeilingToPowerOfTwo(maxPowerOfTwo - 1));
}
[Test]
public void TestIsPerfectSquare32()
{

59
src/Managed/NumberTheory/IntegerTheory.cs

@ -95,6 +95,65 @@ namespace MathNet.Numerics.NumberTheory
return number > 0 && (number & (number - 1)) == 0x0;
}
/// <summary>
/// Find the closest perfect power of two that is larger or equal to the provided
/// 32 bit integer.
/// </summary>
/// <param name="number">The number of which to find the closest upper power of two.</param>
/// <returns>A power of two.</returns>
/// <exception cref="ArgumentOutOfRangeException"/>
public static int CeilingToPowerOfTwo(this int number)
{
if(number == Int32.MinValue)
{
return 0;
}
const int maxPowerOfTwo = 0x40000000;
if(number > maxPowerOfTwo)
{
throw new ArgumentOutOfRangeException("number");
}
number--;
number |= number >> 1;
number |= number >> 2;
number |= number >> 4;
number |= number >> 8;
number |= number >> 16;
return number + 1;
}
/// <summary>
/// Find the closest perfect power of two that is larger or equal to the provided
/// 64 bit integer.
/// </summary>
/// <param name="number">The number of which to find the closest upper power of two.</param>
/// <returns>A power of two.</returns>
/// <exception cref="ArgumentOutOfRangeException"/>
public static long CeilingToPowerOfTwo(this long number)
{
if (number == Int64.MinValue)
{
return 0;
}
const long maxPowerOfTwo = 0x4000000000000000;
if (number > maxPowerOfTwo)
{
throw new ArgumentOutOfRangeException("number");
}
number--;
number |= number >> 1;
number |= number >> 2;
number |= number >> 4;
number |= number >> 8;
number |= number >> 16;
number |= number >> 32;
return number + 1;
}
/// <summary>
/// Find out whether the provided 32 bit integer is a perfect square, i.e. a square of an integer.
/// </summary>

Loading…
Cancel
Save