public void SeperableIntegrals() { // Integrates \Pi_{j=0}^{d-1} \int_0^1 \! dx \, x_j^j = \Pi_{j=0}^{d-1} \frac{1}{j+1} = \frac{1}{d!} // This is a simple test of a seperable integral Func <IList <double>, double> f = delegate(IList <double> x) { double y = 1.0; for (int j = 0; j < x.Count; j++) { y *= MoreMath.Pow(x[j], j); } return(y); }; for (int d = 1; d <= 10; d++) { Console.WriteLine(d); IntegrationResult r = MultiFunctionMath.Integrate(f, UnitCube(d)); Console.WriteLine("{0}: {1} ({2}) ?= {3}", r.EvaluationCount, r.Value, r.Precision, 1.0 / AdvancedIntegerMath.Factorial(d)); Assert.IsTrue(TestUtilities.IsNearlyEqual( r.Value, 1.0 / AdvancedIntegerMath.Factorial(d), new EvaluationSettings() { AbsolutePrecision = 2.0 * r.Precision } )); } }
public void ZetaIntegrals() { // By expanding 1/(1-x) = 1 + x + x^2 + ... and integrating term-by-term // it's easy to show that this integral is \zeta(d) Func <IList <double>, double> f = delegate(IList <double> x) { double p = 1.0; for (int i = 0; i < x.Count; i++) { p *= x[i]; } return(1.0 / (1.0 - p)); }; // \zeta(1) is infinite, so skip d=1 for (int d = 2; d <= 10; d++) { Console.WriteLine(d); IntegrationResult result = MultiFunctionMath.Integrate(f, UnitCube(d)); Console.WriteLine("{0} ({1}) {2}", result.Value, result.Precision, AdvancedMath.RiemannZeta(d)); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Value, AdvancedMath.RiemannZeta(d), new EvaluationSettings() { AbsolutePrecision = 2.0 * result.Precision })); } }
public void SteinmetzVolume() { // Steinmetz solid is intersection of unit cylinders along all axes. This is another hard-edged integral. Analytic values are known for d=2-5. // http://www.math.illinois.edu/~hildebr/ugresearch/cylinder-spring2013report.pdf // http://www.math.uiuc.edu/~hildebr/igl/nvolumes-fall2012report.pdf EvaluationSettings settings = new EvaluationSettings() { EvaluationBudget = 1000000, RelativePrecision = 1.0E-2 }; for (int d = 2; d <= 5; d++) { IntegrationResult v1 = MultiFunctionMath.Integrate((IList <double> x) => { for (int i = 0; i < d; i++) { double s = 0.0; for (int j = 0; j < d; j++) { if (j != i) { s += x[j] * x[j]; } } if (s > 1.0) { return(0.0); } } return(1.0); }, SymmetricUnitCube(d), settings); double v2 = 0.0; switch (d) { case 2: // trivial square v2 = 4.0; break; case 3: v2 = 16.0 - 8.0 * Math.Sqrt(2.0); break; case 4: v2 = 48.0 * (Math.PI / 4.0 - Math.Atan(Math.Sqrt(2.0)) / Math.Sqrt(2.0)); break; case 5: v2 = 256.0 * (Math.PI / 12.0 - Math.Atan(1.0 / (2.0 * Math.Sqrt(2.0))) / Math.Sqrt(2.0)); break; } Console.WriteLine("{0} {1} {2}", d, v1.Value, v2); Assert.IsTrue(TestUtilities.IsNearlyEqual(v1.Value, v2, new EvaluationSettings() { AbsolutePrecision = 4.0 * v1.Precision })); } }
public void SeperableIntegrals() { // Integrates \Pi_{j=0}^{d-1} \int_0^1 \! dx \, x_j^j = \Pi_{j=0}^{d-1} \frac{1}{j+1} = \frac{1}{d!} // This is a simple test of a seperable integral Func <IReadOnlyList <double>, double> f = delegate(IReadOnlyList <double> x) { double y = 1.0; for (int j = 0; j < x.Count; j++) { y *= MoreMath.Pow(x[j], j); } return(y); }; for (int d = 1; d <= 10; d++) { Console.WriteLine(d); // Result gets very small, so rely on relative rather than absolute precision. IntegrationSettings s = new IntegrationSettings() { AbsolutePrecision = 0, RelativePrecision = Math.Pow(10.0, -(6.0 - d / 2.0)) }; IntegrationResult r = MultiFunctionMath.Integrate(f, UnitCube(d), s); Assert.IsTrue(r.Estimate.ConfidenceInterval(0.95).ClosedContains(1.0 / AdvancedIntegerMath.Factorial(d))); } }
public void WatsonIntegrals() { // Watson defined and analytically integrated three complicated triple integrals related to random walks in three dimension // See http://mathworld.wolfram.com/WatsonsTripleIntegrals.html Interval watsonWidth = Interval.FromEndpoints(0.0, Math.PI); Interval[] watsonBox = new Interval[] { watsonWidth, watsonWidth, watsonWidth }; Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])), watsonBox ).Estimate.ConfidenceInterval(0.99).ClosedContains( MoreMath.Pow(AdvancedMath.Gamma(1.0 / 4.0), 4) / 4.0 ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (3.0 - Math.Cos(x[0]) * Math.Cos(x[1]) - Math.Cos(x[1]) * Math.Cos(x[2]) - Math.Cos(x[0]) * Math.Cos(x[2])), watsonBox ).Estimate.ConfidenceInterval(0.99).ClosedContains( 3.0 * MoreMath.Pow(AdvancedMath.Gamma(1.0 / 3.0), 6) / Math.Pow(2.0, 14.0 / 3.0) / Math.PI ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (3.0 - Math.Cos(x[0]) - Math.Cos(x[1]) - Math.Cos(x[2])), watsonBox ).Estimate.ConfidenceInterval(0.99).ClosedContains( Math.Sqrt(6.0) / 96.0 * AdvancedMath.Gamma(1.0 / 24.0) * AdvancedMath.Gamma(5.0 / 24.0) * AdvancedMath.Gamma(7.0 / 24.0) * AdvancedMath.Gamma(11.0 / 24.0) ) ); }
private IntegrationResult RambleIntegral(int d, int s, IntegrationSettings settings) { return(MultiFunctionMath.Integrate((IReadOnlyList <double> x) => { Complex z = 0.0; for (int k = 0; k < d; k++) { z += ComplexMath.Exp(2.0 * Math.PI * Complex.I * x[k]); } return (MoreMath.Pow(ComplexMath.Abs(z), s)); }, UnitCube(d), settings)); }
public double BoxIntegralB(int d, int r, IntegrationSettings settings) { return(MultiFunctionMath.Integrate((IReadOnlyList <double> x) => { double s = 0.0; for (int k = 0; k < d; k++) { s += x[k] * x[k]; } return (Math.Pow(s, r / 2.0)); }, UnitCube(d), settings).Value); }
public void UnitSquareIntegrals() { // http://mathworld.wolfram.com/UnitSquareIntegral.html has a long list of integrals over the unit square. // Many are taken from Guillera and Sondow, // "Double Integrals and Infinite Products for Some Classical Constants Via Analytic Continuations of Lerch's Transcendent.", // 16 June 2005. (http://arxiv.org/abs/math.NT/0506319) Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 - x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.RiemannZeta(2.0) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => - Math.Log(x[0] * x[1]) / (1.0 - x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( 2.0 * AdvancedMath.RiemannZeta(3.0) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => (x[0] - 1.0) / (1.0 - x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.EulerGamma ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => (x[0] - 1.0) / (1.0 + x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( Math.Log(4.0 / Math.PI) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 + MoreMath.Sqr(x[0] * x[1])), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.Catalan ) ); }
public double BoxIntegralD(int d, int r, EvaluationSettings settings) { return(MultiFunctionMath.Integrate((IList <double> x) => { double s = 0.0; for (int k = 0; k < d; k++) { double z = x[k] - x[k + d]; s += z * z; } return (Math.Pow(s, r / 2.0)); }, UnitCube(2 * d), settings).Value); }
public void GaussianIntegrals() { Random rng = new Random(1); for (int d = 2; d < 4; d++) { if (d == 4 || d == 5 || d == 6) { continue; } Console.WriteLine(d); // Create a symmetric matrix SymmetricMatrix A = new SymmetricMatrix(d); for (int r = 0; r < d; r++) { for (int c = 0; c < r; c++) { A[r, c] = rng.NextDouble(); } // Ensure it is positive definite by diagonal dominance A[r, r] = r + 1.0; } // Compute its determinant, which appears in the analytic value of the integral CholeskyDecomposition CD = A.CholeskyDecomposition(); double detA = CD.Determinant(); // Compute the integral Func <IList <double>, double> f = (IList <double> x) => { ColumnVector v = new ColumnVector(x); double s = v.Transpose() * (A * v); return(Math.Exp(-s)); }; Interval[] volume = new Interval[d]; for (int i = 0; i < d; i++) { volume[i] = Interval.FromEndpoints(Double.NegativeInfinity, Double.PositiveInfinity); } IntegrationResult I = MultiFunctionMath.Integrate(f, volume); // Compare to the analytic result Console.WriteLine("{0} ({1}) {2}", I.Value, I.Precision, Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA)); Assert.IsTrue(TestUtilities.IsNearlyEqual(I.Value, Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA), new EvaluationSettings() { AbsolutePrecision = 2.0 * I.Precision })); } }
public void DoubleIntegrals() { // At http://mathworld.wolfram.com/DoubleIntegral.html, Mathworld // lists a few double integrals with known values that we take as // tests. // One of the integrals listed there is just the zeta integral for d=2 // which we do above, so we omit it here. // Because these are non-ocsilatory and have relatively low // dimension, we can demand fairly high accuracy. IntegrationResult i1 = MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (1.0 - x[0] * x[0] * x[1] * x[1]), UnitCube(2) ); Console.WriteLine("{0} ({1})", i1.Value, i1.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i1.Value, Math.PI * Math.PI / 8.0, new EvaluationSettings() { AbsolutePrecision = 2.0 * i1.Precision })); //Assert.IsTrue(i1.Estimate.ConfidenceInterval(0.99).ClosedContains(Math.PI * Math.PI / 8.0)); IntegrationResult i2 = MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (x[0] + x[1]) / Math.Sqrt((1.0 - x[0]) * (1.0 - x[1])), UnitCube(2), new EvaluationSettings() { RelativePrecision = 1.0E-5, EvaluationBudget = 1000000 } ); Console.WriteLine("{0} ({1})", i2.Value, i2.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i2.Value, 4.0 * AdvancedMath.Catalan, new EvaluationSettings() { AbsolutePrecision = 2.0 * i2.Precision })); // For higher precision demands on this integral, we start getting Infinity +/- NaN for estimate and never terminate, look into this. IntegrationResult i3 = MultiFunctionMath.Integrate( (IList <double> x) => (x[0] - 1.0) / (1.0 - x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ); Console.WriteLine("{0} ({1})", i3.Value, i3.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i3.Value, AdvancedMath.EulerGamma, new EvaluationSettings() { AbsolutePrecision = 2.0 * i3.Precision })); }
public void GaussianIntegrals() { Random rng = new Random(1); for (int d = 2; d < 8; d++) { Console.WriteLine(d); // Create a symmetric matrix SymmetricMatrix A = new SymmetricMatrix(d); for (int r = 0; r < d; r++) { for (int c = 0; c < r; c++) { A[r, c] = rng.NextDouble(); } // Ensure it is positive definite by diagonal dominance A[r, r] = r + 1.0; } // Compute its determinant, which appears in the analytic value of the integral CholeskyDecomposition CD = A.CholeskyDecomposition(); double detA = CD.Determinant(); // Compute the integral Func <IReadOnlyList <double>, double> f = (IReadOnlyList <double> x) => { ColumnVector v = new ColumnVector(x); double s = v.Transpose * (A * v); return(Math.Exp(-s)); }; Interval[] volume = new Interval[d]; for (int i = 0; i < d; i++) { volume[i] = Interval.FromEndpoints(Double.NegativeInfinity, Double.PositiveInfinity); } // These are difficult integrals; demand reduced precision. IntegrationSettings settings = new IntegrationSettings() { RelativePrecision = Math.Pow(10.0, -(4.0 - d / 2.0)) }; IntegrationResult I = MultiFunctionMath.Integrate(f, volume, settings); // Compare to the analytic result Assert.IsTrue(I.Estimate.ConfidenceInterval(0.95).ClosedContains(Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA))); } }
public void BallVolumeIntegrals() { // The volume of a d-sphere is \frac{\pi^{d/2}}{\Gamma(d/2 + 1)} // and the fraction in the first quadrant is 1/2^d of that // This is a simple test of the integration of a discontinuous function Func <IList <double>, double> f = delegate(IList <double> x) { double r2 = 0.0; for (int j = 0; j < x.Count; j++) { r2 += x[j] * x[j]; } if (r2 <= 1.0) { return(1.0); } else { return(0.0); } }; for (int d = 1; d <= 8; d++) { if (d == 6) { continue; //. For d=6, integral returns after just ~300 evaluation with an underestimated error; look into this } Console.WriteLine(d); IntegrationResult result = MultiFunctionMath.Integrate(f, UnitCube(d), new EvaluationSettings() { AbsolutePrecision = 0.0, RelativePrecision = 5.0E-3, EvaluationBudget = 1000000 }); double V = Math.Pow(Math.PI, d / 2.0) / AdvancedMath.Gamma(d / 2.0 + 1.0) * MoreMath.Pow(2.0, -d); Console.WriteLine("{0} ({1}) {2}: {3}", result.Value, result.Precision, result.Value - V, result.EvaluationCount); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Value, V, new EvaluationSettings() { AbsolutePrecision = 4.0 * result.Precision })); } }
public void ExponentialBox() { // Mentioned in passing in http://crd-legacy.lbl.gov/~dhbailey/dhbpapers/BoxII.pdf // This is easy because the integrand is seperable and smooth. for (int d = 2; d <= 10; d++) { IntegrationResult result = MultiFunctionMath.Integrate((IReadOnlyList <double> r) => { double s = 0.0; foreach (double x in r) { s += x * x; } return(Math.Exp(-s)); }, UnitCube(d)); Assert.IsTrue(result.Estimate.ConfidenceInterval(0.95).ClosedContains( MoreMath.Pow(Math.Sqrt(Math.PI) / 2.0 * AdvancedMath.Erf(1.0), d) )); } }
public void BallVolumeIntegrals() { // The volume of a d-sphere is \frac{\pi^{d/2}}{\Gamma(d/2 + 1)} // and the fraction in the first quadrant is 1/2^d of that. // This is a simple test of the integration of a discontinuous function. Func <IReadOnlyList <double>, double> f = delegate(IReadOnlyList <double> x) { double r2 = 0.0; for (int j = 0; j < x.Count; j++) { r2 += x[j] * x[j]; } if (r2 <= 1.0) { return(1.0); } else { return(0.0); } }; for (int d = 1; d <= 8; d++) { if (d == 6) { continue; //. For d=6, integral returns after just ~300 evaluation with an underestimated error; look into this } Console.WriteLine(d); IntegrationSettings settings = new IntegrationSettings() { AbsolutePrecision = 0.0, RelativePrecision = 1.0E-2 }; IntegrationResult result = MultiFunctionMath.Integrate(f, UnitCube(d), settings); double V = Math.Pow(Math.PI, d / 2.0) / AdvancedMath.Gamma(d / 2.0 + 1.0) * MoreMath.Pow(2.0, -d); Assert.IsTrue(result.Estimate.ConfidenceInterval(0.95).ClosedContains(V)); } }
public void WatsonIntegrals() { // Watson defined and analytically integrated three complicated triple integrals related to random walks in three dimension // See http://mathworld.wolfram.com/WatsonsTripleIntegrals.html // These integrals are difficult, so up the budget to about 1,000,000 and reduce the target accuracy to about 10^{-4} EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 1.0E-4, EvaluationBudget = 1000000 }; Interval watsonWidth = Interval.FromEndpoints(0.0, Math.PI); Interval[] watsonBox = new Interval[] { watsonWidth, watsonWidth, watsonWidth }; Assert.IsTrue( MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])), watsonBox, settings ).Estimate.ConfidenceInterval(0.99).ClosedContains( MoreMath.Pow(AdvancedMath.Gamma(1.0 / 4.0), 4) / 4.0 ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (3.0 - Math.Cos(x[0]) * Math.Cos(x[1]) - Math.Cos(x[1]) * Math.Cos(x[2]) - Math.Cos(x[0]) * Math.Cos(x[2])), watsonBox, settings ).Estimate.ConfidenceInterval(0.99).ClosedContains( 3.0 * MoreMath.Pow(AdvancedMath.Gamma(1.0 / 3.0), 6) / Math.Pow(2.0, 14.0 / 3.0) / Math.PI ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (3.0 - Math.Cos(x[0]) - Math.Cos(x[1]) - Math.Cos(x[2])), watsonBox, settings ).Estimate.ConfidenceInterval(0.99).ClosedContains( Math.Sqrt(6.0) / 96.0 * AdvancedMath.Gamma(1.0 / 24.0) * AdvancedMath.Gamma(5.0 / 24.0) * AdvancedMath.Gamma(7.0 / 24.0) * AdvancedMath.Gamma(11.0 / 24.0) ) ); }
public void ZetaIntegrals() { // By expanding 1/(1-x) = 1 + x + x^2 + ... and integrating term-by-term // it's easy to show that this integral is \zeta(d) Func <IReadOnlyList <double>, double> f = delegate(IReadOnlyList <double> x) { double p = 1.0; for (int i = 0; i < x.Count; i++) { p *= x[i]; } return(1.0 / (1.0 - p)); }; // \zeta(1) is infinite, so skip d=1 for (int d = 2; d <= 15; d++) { Console.WriteLine(d); IntegrationResult result = MultiFunctionMath.Integrate(f, UnitCube(d)); Assert.IsTrue(result.Estimate.ConfidenceInterval(0.95).ClosedContains(AdvancedMath.RiemannZeta(d))); } }
public void DoubleIntegrals() { // At http://mathworld.wolfram.com/DoubleIntegral.html, Mathworld // lists a few double integrals with known values that we take as // tests. // One of the integrals listed there is just the zeta integral for d=2 // which we do above, so we omit it here. // Because these are non-ocsilatory and have relatively low // dimension, we can demand fairly high accuracy. IntegrationResult i1 = MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 - x[0] * x[0] * x[1] * x[1]), UnitCube(2) ); Assert.IsTrue(i1.Estimate.ConfidenceInterval(0.95).ClosedContains(Math.PI * Math.PI / 8.0)); IntegrationResult i2 = MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (x[0] + x[1]) / Math.Sqrt((1.0 - x[0]) * (1.0 - x[1])), UnitCube(2), new IntegrationSettings() { RelativePrecision = 1.0E-6 } ); Assert.IsTrue(i2.Estimate.ConfidenceInterval(0.95).ClosedContains(4.0 * AdvancedMath.Catalan)); // For higher precision demands on this integral, we start getting Infinity +/- NaN for estimate and never terminate, look into this. IntegrationResult i3 = MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => (x[0] - 1.0) / (1.0 - x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ); Assert.IsTrue(i3.Estimate.ConfidenceInterval(0.95).ClosedContains(AdvancedMath.EulerGamma)); }
public void IsingIntegrals() { // See http://www.davidhbailey.com/dhbpapers/ising.pdf. IntegrationSettings settings = new IntegrationSettings() { RelativePrecision = 1.0E-3, EvaluationBudget = 1000000 }; int d = 4; Interval[] volume = new Interval[d]; for (int i = 0; i < volume.Length; i++) { volume[i] = Interval.FromEndpoints(0.0, Double.PositiveInfinity); } IntegrationResult r = MultiFunctionMath.Integrate((IReadOnlyList <double> x) => { double p = 1.0; double q = 0.0; for (int i = 0; i < x.Count; i++) { double u = x[i]; double v = 1.0 / u; q += (u + v); p *= v; } return(p / MoreMath.Sqr(q)); }, volume, settings); double c = 4.0 / AdvancedIntegerMath.Factorial(d); Console.WriteLine("{0} {1}", c * r.Estimate, r.EvaluationCount); Console.WriteLine(7.0 * AdvancedMath.RiemannZeta(3.0) / 12.0); Assert.IsTrue((c * r.Estimate).ConfidenceInterval(0.99).ClosedContains(7.0 * AdvancedMath.RiemannZeta(3.0) / 12.0)); }
public static void Integration() { // This is the area of the upper half-circle, so the value should be pi/2. IntegrationResult i = FunctionMath.Integrate(x => Math.Sqrt(1.0 - x * x), -1.0, +1.0); Console.WriteLine($"i = {i.Estimate} after {i.EvaluationCount} evaluations."); Interval zeroToPi = Interval.FromEndpoints(0.0, Math.PI); IntegrationResult watson = MultiFunctionMath.Integrate( x => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])), new Interval[] { zeroToPi, zeroToPi, zeroToPi } ); IntegrationResult i2 = FunctionMath.Integrate( x => Math.Sqrt(1.0 - x * x), -1.0, +1.0, new IntegrationSettings() { RelativePrecision = 1.0E-4 } ); // This integrand has a log singularity at x = 0. // The value of this integral is the Catalan constant. IntegrationResult soft = FunctionMath.Integrate( x => - Math.Log(x) / (1.0 + x * x), 0.0, 1.0 ); // This integral has a power law singularity at x = 0. // The value of this integral is 4. IntegrationResult hard = FunctionMath.Integrate( x => Math.Pow(x, -3.0 / 4.0), 0.0, 1.0, new IntegrationSettings() { RelativePrecision = 1.0E-6 } ); // The value of this infinite integral is sqrt(pi) IntegrationResult infinite = FunctionMath.Integrate( x => Math.Exp(-x * x), Double.NegativeInfinity, Double.PositiveInfinity ); Func <IReadOnlyList <double>, double> distance = z => { ColumnVector x = new ColumnVector(z[0], z[1], z[2]); ColumnVector y = new ColumnVector(z[3], z[4], z[5]); ColumnVector d = x - y; return(d.Norm()); }; Interval oneBox = Interval.FromEndpoints(0.0, 1.0); Interval[] sixBox = new Interval[] { oneBox, oneBox, oneBox, oneBox, oneBox, oneBox }; IntegrationSettings settings = new IntegrationSettings() { RelativePrecision = 1.0E-4, AbsolutePrecision = 0.0, Listener = r => { Console.WriteLine($"Estimate {r.Estimate} after {r.EvaluationCount} evaluations."); } }; IntegrationResult numeric = MultiFunctionMath.Integrate(distance, sixBox, settings); Console.WriteLine($"The numeric result is {numeric.Estimate}."); double analytic = 4.0 / 105.0 + 17.0 / 105.0 * Math.Sqrt(2.0) - 2.0 / 35.0 * Math.Sqrt(3.0) + Math.Log(1.0 + Math.Sqrt(2.0)) / 5.0 + 2.0 / 5.0 * Math.Log(2.0 + Math.Sqrt(3.0)) - Math.PI / 15.0; Console.WriteLine($"The analytic result is {analytic}."); }