public void StirlingNumber2SpecialCases() { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(0, 0) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(1, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(1, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(2, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(2, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(2, 2) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(3, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(3, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(3, 2) == 3); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(3, 3) == 1); foreach (int m in TestUtilities.GenerateIntegerValues(2, 100, 4)) { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(m, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(m, 1) == 1); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.StirlingNumber2(m, 2), MoreMath.Pow(2, m - 1) - 1 )); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(m, m) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber2(m, m - 1) == AdvancedIntegerMath.BinomialCoefficient(m, 2)); } }
//[TestMethod] // Cancellation too bad to be useful public void BernoulliStirlingRelationship() { // This involves significant cancellation, so don't pick n too high foreach (int n in TestUtilities.GenerateIntegerValues(2, 16, 4)) { double S = 0.0; for (int k = 0; k <= n; k++) { double dS = AdvancedIntegerMath.Factorial(k) / (k + 1) * AdvancedIntegerMath.StirlingNumber2(n, k); if (k % 2 != 0) { dS = -dS; } S += dS; } Assert.IsTrue(TestUtilities.IsNearlyEqual(S, AdvancedIntegerMath.BernoulliNumber(n))); } }
public void StirlingNumbers2ColumnSum() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 4)) { foreach (int k in TestUtilities.GenerateIntegerValues(1, n, 4)) { double sum = 0.0; for (int m = k; m <= n; m++) { sum += AdvancedIntegerMath.BinomialCoefficient(n, m) * AdvancedIntegerMath.StirlingNumber2(m, k); } Assert.IsTrue(TestUtilities.IsNearlyEqual(sum, AdvancedIntegerMath.StirlingNumber2(n + 1, k + 1))); } } }
public void StirlingNumber2Parity() { // Sterling numbers of the 2nd kind provably have the same parity // as a particular related binomial coefficient. // This is actually quite a difficult test because it tests the least // significant bits of the numbers. We can't operate on values // with more than 52 bits, since for those numbers we will loose // the least significant bits. foreach (int n in TestUtilities.GenerateIntegerValues(1, 50, 4)) { foreach (int k in TestUtilities.GenerateIntegerValues(1, n, 4)) { long B = (long)AdvancedIntegerMath.BinomialCoefficient(n - k / 2 - 1, n - k); long S = (long)AdvancedIntegerMath.StirlingNumber2(n, k); Assert.IsTrue(B % 2 == S % 2); } } }
public void StirlingNumberInequality() { // Rows are log-concave foreach (int n in TestUtilities.GenerateIntegerValues(10, 100, 4)) { foreach (int k in TestUtilities.GenerateRealValues(2, n - 1, 4)) { Assert.IsTrue( MoreMath.Sqr(AdvancedIntegerMath.StirlingNumber1(n, k)) >= AdvancedIntegerMath.StirlingNumber1(n, k - 1) * AdvancedIntegerMath.StirlingNumber1(n, k + 1) ); Assert.IsTrue( MoreMath.Sqr(AdvancedIntegerMath.StirlingNumber2(n, k)) >= AdvancedIntegerMath.StirlingNumber2(n, k - 1) * AdvancedIntegerMath.StirlingNumber2(n, k + 1) ); } } }