public void CompanionMatrixEigenvalues() { SquareMatrix CM = new SquareMatrix(3); CM[0, 2] = -1.0; CM[1, 0] = 1.0; CM[1, 2] = -3.0; CM[2, 1] = 1.0; CM[2, 2] = -3.0; ComplexEigendecomposition EM = CM.Eigendecomposition(); for (int d = 2; d <= 8; d++) { Console.WriteLine(d); SquareMatrix C = new SquareMatrix(d); for (int r = 1; r < d; r++) { C[r, r - 1] = 1.0; } for (int r = 0; r < d; r++) { C[r, d - 1] = -AdvancedIntegerMath.BinomialCoefficient(d, r); } ComplexEigendecomposition e = C.Eigendecomposition(); } }
public void HermiteAddition() { foreach (int n in orders) { if (n > 100) { continue; } foreach (double x in aArguments) { foreach (double y in aArguments) { double value = OrthogonalPolynomials.HermiteH(n, x + y); double[] terms = new double[n + 1]; double sum = 0.0; for (int k = 0; k <= n; k++) { terms[k] = AdvancedIntegerMath.BinomialCoefficient(n, k) * OrthogonalPolynomials.HermiteH(k, x) * Math.Pow(2 * y, n - k); sum += terms[k]; } Console.WriteLine("n={0}, x={1}, y={2}, H(x+y)={3}, sum={4}", n, x, y, value, sum); Assert.IsTrue(TestUtilities.IsSumNearlyEqual(terms, value)); } } } }
public void StirlingNumber1SpecialCases() { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(0, 0) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(1, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(1, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 2) == 1); foreach (int m in TestUtilities.GenerateIntegerValues(2, 100, 4)) { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, 1) == AdvancedIntegerMath.Factorial(m - 1)); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.StirlingNumber1(m, 2), AdvancedIntegerMath.Factorial(m - 1) * AdvancedIntegerMath.HarmonicNumber(m - 1) )); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, m) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, m - 1) == AdvancedIntegerMath.BinomialCoefficient(m, 2)); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.StirlingNumber1(m, m - 2), (3 * m - 1) * AdvancedIntegerMath.BinomialCoefficient(m, 3) / 4 )); } }
// The definition of the central moment produces: // C_{r} = \sum{k=0}^{n} (k - np)^r { n \choose k } p^k q^{n-k} // This requires a large number of terms when n is large. // There is a well-known recurrsion: // C_{r+1} = p q [ n r C_{r-1} + \frac{d}{dp} C_{r} ] // but this requires symbolic differentiation and produces polynomials whose evaluation may be subject to cancelation. // A numerically useful recurrsion: // C_{r} = \sum_{k=0}^{r-2} { r-1 \choose k } ( n p q C_{k} - p C_{k+1} ) // is derived in Shenton, Bowman, & Sheehan, "Sampling Moments of Moments Associated with Univariate Distributions", // Journal of the Royal Statistical Society B, 33 (1971) 444 /// <inheritdoc /> public override double MomentAboutMean(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(1.0); } else if (r == 1) { return(0.0); } else { // This requires computing r(r-1)/2 binomial coefficients. Summing over all values requires computing n binomial coefficients. double[] C = new double[r + 1]; C[0] = 1.0; C[1] = 0.0; for (int i = 2; i <= r; i++) { double s = 0.0; for (int j = 0; j <= i - 2; j++) { s += AdvancedIntegerMath.BinomialCoefficient(i - 1, j) * (n * q * C[j] - C[j + 1]); } C[i] = p * s; } return(C[r]); } }
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)); } }
/// <inheritdoc /> public override double Moment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(1.0); } else if (r == 1) { return(Mean); } else { double M = MomentAboutMode(r); double t = 1.0; for (int k = r - 1; k >= 0; k--) { t *= b; M += AdvancedIntegerMath.BinomialCoefficient(r, k) * MomentAboutMode(k) * t; } return(M); } }
/// <inheritdoc /> public override double MomentAboutMean(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(1.0); } else if (r == 1) { return(0.0); } else { double M = MomentAboutMode(r); double s = -MomentAboutMode(1); double t = 1.0; for (int k = r - 1; k >= 0; k--) { t *= s; M += AdvancedIntegerMath.BinomialCoefficient(r, k) * MomentAboutMode(k) * t; } //Console.WriteLine("n={0}, M={1}", n, M); return(M); } }
public void BinomialCoefficientSpecialCases() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 6)) { Assert.IsTrue(AdvancedIntegerMath.BinomialCoefficient(n, 0) == 1); Assert.IsTrue(AdvancedIntegerMath.BinomialCoefficient(n, 1) == n); Assert.IsTrue(AdvancedIntegerMath.BinomialCoefficient(n, n - 1) == n); Assert.IsTrue(AdvancedIntegerMath.BinomialCoefficient(n, n) == 1); } }
public override double ProbabilityMass(int k) { if ((k < Minimum) || (k > Maximum)) { return(0.0); } else { int c = k * ((int)AdvancedIntegerMath.GCF(n, m)); int c1 = (k - 1) * ((int)AdvancedIntegerMath.GCF(n, m)); return((LatticePathSum(c) - LatticePathSum(c1)) / AdvancedIntegerMath.BinomialCoefficient(n + m, n)); } }
public void BinomialCoefficientInequality() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 6)) { foreach (int m in TestUtilities.GenerateUniformIntegerValues(0, n, 4)) { double lower = Math.Pow(1.0 * n / m, m); double upper = Math.Pow(Math.E * n / m, m); double value = AdvancedIntegerMath.BinomialCoefficient(n, m); Assert.IsTrue((lower <= value) && (value <= upper)); } } }
public void BinomialCoefficientAgreement() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 4)) { int m = -1; IEnumerator B = AdvancedIntegerMath.BinomialCoefficients(n).GetEnumerator(); while (B.MoveNext()) { m++; Assert.IsTrue(TestUtilities.IsNearlyEqual((double)B.Current, AdvancedIntegerMath.BinomialCoefficient(n, m))); } } }
/// <inheritdoc /> public override double MomentAboutMean(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(1.0); } else if (r == 1) { return(0.0); } else if (r == 2) { return(Variance); } else { // This follows from a straightforward expansion of (x-m)^n and substitution of expressions for M_k. // It eliminates some arithmetic but is still subject to loss of significance due to cancelation. double s2 = sigma * sigma / 2.0; double C = 0.0; for (int i = 0; i <= r; i++) { double dC = AdvancedIntegerMath.BinomialCoefficient(r, i) * Math.Exp((MoreMath.Sqr(r - i) + i) * s2); if (i % 2 != 0) { dC = -dC; } C += dC; } return(Math.Exp(r * mu) * C); // this isn't great, but it does the job // expand in terms of moments about the origin // there is likely to be some cancelation, but the distribution is wide enough that it may not matter /* * double m = -Mean; * double C = 0.0; * for (int k = 0; k <= n; k++) { * C += AdvancedIntegerMath.BinomialCoefficient(n, k) * Moment(k) * Math.Pow(m, n - k); * } * return (C); */ } }
/// <summary> /// Converts central moments to cumulants. /// </summary> /// <param name="mu">The mean.</param> /// <param name="C">A set of central moments.</param> /// <returns>The corresponding set of cumulants.</returns> /// <exception cref="ArgumentNullException"><paramref name="C"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException">The zeroth central moment is not one, or the first central moment is not zero.</exception> public static double[] CentralToCumulant(double mu, double[] C) { if (C == null) { throw new ArgumentNullException(nameof(C)); } double[] K = new double[C.Length]; if (K.Length == 0) { return(K); } // C0 = 1 and K0 = 0 if (C[0] != 1.0) { throw new ArgumentOutOfRangeException(nameof(C)); } K[0] = 0.0; if (K.Length == 1) { return(K); } // C1 = 0 and K1 = M1 if (C[1] != 0.0) { throw new ArgumentOutOfRangeException(nameof(C)); } K[1] = mu; if (K.Length == 2) { return(K); } // Determine higher K // s = 0 term involves K1 = M1, so ignore // s = r - 1 term involves C1 = 0, so ignore for (int r = 1; r < K.Length - 1; r++) { double t = C[r + 1]; for (int s = 1; s < r - 1; s++) { t -= AdvancedIntegerMath.BinomialCoefficient(r, s) * K[s + 1] * C[r - s]; } K[r + 1] = t; } return(K); }
// compute central moments from raw moments // this is subject to loss of precision from cancelation, so be careful internal virtual double CentralMomentFromRawMoment(int n) { double m = Mean; double mm = 1.0; double C = RawMoment(n); for (int k = 1; k <= n; k++) { mm = mm * (-m); C += AdvancedIntegerMath.BinomialCoefficient(n, k) * mm * RawMoment(n - k); } return(C); }
public override double LeftInclusiveProbability(int k) { if (k < Minimum) { return(0.0); } else if (k >= Maximum) { return(1.0); } else { return(LatticePathSum(k * ((int)AdvancedIntegerMath.GCF(n, m))) / AdvancedIntegerMath.BinomialCoefficient(n + m, n)); } }
/// <inheritdoc /> public override double ProbabilityMass(int k) { if ((k < 0) || (k > n)) { return(0.0); } else { // for small enough integers, use the exact binomial coefficient, // which can be evaluated quickly and exactly return(AdvancedIntegerMath.BinomialCoefficient(n, k) * MoreMath.Pow(p, k) * MoreMath.Pow(q, n - k)); // this could fail if the binomial overflows; should we go do factorials or // use an expansion around the normal approximation? } }
/// <inheritdoc/> public override double ProbabilityMass(int k) { if ((k < Support.LeftEndpoint) || (k > Support.RightEndpoint)) { return(0.0); } else { return( AdvancedIntegerMath.BinomialCoefficient(nSuccessPopulation, k) / AdvancedIntegerMath.BinomialCoefficient(nPopulation, nDraws) * AdvancedIntegerMath.BinomialCoefficient(nFailurePopulation, nDraws - k) ); } }
public static void ComputeSpecialFunctions() { // Compute the value x at which erf(x) is just 10^{-15} from 1. double x = AdvancedMath.InverseErfc(1.0E-15); // The Gamma function at 1/2 is sqrt(pi) double y = AdvancedMath.Gamma(0.5); // Compute a Coulomb Wave Function in the quantum tunneling region SolutionPair s = AdvancedMath.Coulomb(2, 4.5, 3.0); // Compute the Reimann Zeta function at a complex value Complex z = AdvancedComplexMath.RiemannZeta(new Complex(0.75, 6.0)); // Compute the 100th central binomial coefficient double c = AdvancedIntegerMath.BinomialCoefficient(100, 50); }
public void CatalanHankelMatrixDeterminant() { for (int d = 1; d <= 8; d++) { SymmetricMatrix S = new SymmetricMatrix(d); for (int r = 0; r < d; r++) { for (int c = 0; c <= r; c++) { int n = r + c; S[r, c] = AdvancedIntegerMath.BinomialCoefficient(2 * n, n) / (n + 1); } } CholeskyDecomposition CD = S.CholeskyDecomposition(); Assert.IsTrue(TestUtilities.IsNearlyEqual(CD.Determinant(), 1.0)); } }
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 BinomialCoefficientRecurrence() { // this is the Pascal triangle recurrence foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 5)) { foreach (int m in TestUtilities.GenerateUniformIntegerValues(0, n - 1, 5)) { Console.WriteLine("n = {0}, m = {1}", n, m); Console.WriteLine(AdvancedIntegerMath.BinomialCoefficient(n + 1, m + 1)); Console.WriteLine(AdvancedIntegerMath.BinomialCoefficient(n, m + 1)); Console.WriteLine(AdvancedIntegerMath.BinomialCoefficient(n, m)); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.BinomialCoefficient(n + 1, m + 1), AdvancedIntegerMath.BinomialCoefficient(n, m) + AdvancedIntegerMath.BinomialCoefficient(n, m + 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); } } }
/// <inheritdoc /> public override double ProbabilityMass(int k) { if ((k < 0) || (k > n)) { return(0.0); } else { int nmk = n - k; if ((k > 16) && (nmk > 16)) { // For large arguments, use cancellation-corrected Stirling series to // avoid overflow and preserve accuracy. return(Stirling.BinomialProbability(p, k, q, nmk)); } else { // Otherwise, fall back to direct evaluation. return(AdvancedIntegerMath.BinomialCoefficient(n, k) * MoreMath.Pow(p, k) * MoreMath.Pow(q, n - k)); } } }
/// <summary> /// Converts raw moments to cumulants. /// </summary> /// <param name="M">A set of raw moments.</param> /// <returns>The corresponding set of cumulants.</returns> /// <remarks>The computation of cumulants from raw moments is often subject /// to significant cancellation errors, so you should be wary of the higher /// digits of cumulants returned by this method.</remarks> /// <exception cref="ArgumentNullException"><paramref name="M"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException">The zeroth raw moment is not one.</exception> public static double[] RawToCumulant(double[] M) { if (M == null) { throw new ArgumentNullException(nameof(M)); } double[] K = new double[M.Length]; if (K.Length == 0) { return(K); } if (M[0] != 1.0) { throw new ArgumentOutOfRangeException(nameof(M)); } K[0] = 0.0; if (K.Length == 1) { return(K); } for (int r = 0; r < K.Length - 1; r++) { double t = M[r + 1]; for (int s = 0; s < r; s++) { t -= AdvancedIntegerMath.BinomialCoefficient(r, s) * K[s + 1] * M[r - s]; } K[r + 1] = t; } return(K); }
public void CompanionMatrixEigenvalues() { SquareMatrix CM = new SquareMatrix(3); CM[0, 2] = -1.0; CM[1, 0] = 1.0; CM[1, 2] = -3.0; CM[2, 1] = 1.0; CM[2, 2] = -3.0; ComplexEigensystem EM = CM.Eigensystem(); for (int i = 0; i < EM.Dimension; i++) { Console.WriteLine("! {0}", EM.Eigenvalue(i)); } for (int d = 2; d <= 8; d++) { Console.WriteLine(d); SquareMatrix C = new SquareMatrix(d); for (int r = 1; r < d; r++) { C[r, r - 1] = 1.0; } for (int r = 0; r < d; r++) { C[r, d - 1] = -AdvancedIntegerMath.BinomialCoefficient(d, r); } ComplexEigensystem e = C.Eigensystem(); for (int i = 0; i < e.Dimension; i++) { Console.WriteLine("!! {0}", e.Eigenvalue(i)); } } }
public void HermiteSum() { // accuracy of equality falls at high n because of cancelations among large terms for (int n = 0; n < 12; n++) { double sum = 0.0; for (int k = 0; k <= n; k++) { double term = AdvancedIntegerMath.BinomialCoefficient(n, k) * OrthogonalPolynomials.HermiteH(n, k); Console.WriteLine(" k={0}, term={1}", k, term); if ((n - k) % 2 == 0) { sum += term; } else { sum -= term; } } Console.WriteLine("n={0}, sum={1}", n, sum); Assert.IsTrue(TestUtilities.IsNearlyEqual(sum, Math.Pow(2, n) * AdvancedIntegerMath.Factorial(n))); } }
public static void Main(string[] args) { // calculate the factorials of 0 through 10 for (long counter = 0; counter <= 10; ++counter) { Console.WriteLine("{0}! = {1}", counter, Factorial(counter)); } // Compute the value x at which erf(x) is just 10^{-15} from 1. double x = AdvancedMath.InverseErfc(1.0E-15); Console.WriteLine("\n{0}", x); // The Gamma function at 1/2 is sqrt(pi) double y = AdvancedMath.Gamma(0.5); Console.WriteLine("\nThe Gamma function at 1/2 is sqrt(pi) = {0}", y); // Compute a Coulomb Wave Function in the quantum tunneling region SolutionPair s = AdvancedMath.Coulomb(2, 4.5, 3.0); Console.WriteLine("\nCompute a Coulomb Wave Function in the quantum tunneling region = {0}", s); // Compute the Reimann Zeta function at a complex value Complex z = AdvancedComplexMath.RiemannZeta(new Complex(0.75, 6.0)); Console.WriteLine("\nCompute the Reimann Zeta function at a complex value = {0}", z); // Compute the 100th central binomial coefficient double c = AdvancedIntegerMath.BinomialCoefficient(5, 2); Console.WriteLine("\n{0}", c); Console.WriteLine("\nTecle qualquer tecla para finalizar..."); Console.ReadKey(); } // end Main
public void BinomialCoefficientInvalidArgumentTest3() { AdvancedIntegerMath.BinomialCoefficient(2, 3); }
public void BinomialCoefficientInvalidArgumentTest1() { AdvancedIntegerMath.BinomialCoefficient(-1, -1); }