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)
                        );
                }
            }
        }