diff --git a/src/Managed.UnitTests/NumberTheoryTests/IntegerTheoryTest.cs b/src/Managed.UnitTests/NumberTheoryTests/IntegerTheoryTest.cs
index 8741ee6e..8f8db543 100644
--- a/src/Managed.UnitTests/NumberTheoryTests/IntegerTheoryTest.cs
+++ b/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()
{
diff --git a/src/Managed/NumberTheory/IntegerTheory.cs b/src/Managed/NumberTheory/IntegerTheory.cs
index 3130d667..dfe0bf8a 100644
--- a/src/Managed/NumberTheory/IntegerTheory.cs
+++ b/src/Managed/NumberTheory/IntegerTheory.cs
@@ -95,6 +95,65 @@ namespace MathNet.Numerics.NumberTheory
return number > 0 && (number & (number - 1)) == 0x0;
}
+ ///
+ /// Find the closest perfect power of two that is larger or equal to the provided
+ /// 32 bit integer.
+ ///
+ /// The number of which to find the closest upper power of two.
+ /// A power of two.
+ ///
+ 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;
+ }
+
+ ///
+ /// Find the closest perfect power of two that is larger or equal to the provided
+ /// 64 bit integer.
+ ///
+ /// The number of which to find the closest upper power of two.
+ /// A power of two.
+ ///
+ 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;
+ }
+
///
/// Find out whether the provided 32 bit integer is a perfect square, i.e. a square of an integer.
///