From 206c0c298c5f4f439d0795bc14e024d01fd9efea Mon Sep 17 00:00:00 2001
From: axexlck
Date: Thu, 1 Aug 2024 22:08:11 +0200
Subject: [PATCH] WIP #1034 code formatting org.matheclipse.core.numerics
---
.../numerics/integral/ClenshawCurtis.java | 1107 ++++----
.../core/numerics/integral/GaussKronrod.java | 2299 +++++++++--------
.../core/numerics/integral/GaussLegendre.java | 368 +--
.../core/numerics/integral/GaussLobatto.java | 184 +-
.../core/numerics/integral/NewtonCotes.java | 467 ++--
.../core/numerics/integral/Quadrature.java | 328 ++-
.../core/numerics/integral/RmsRule.java | 1631 ++++++------
.../core/numerics/integral/Romberg.java | 1474 ++++++-----
.../core/numerics/integral/Simpson.java | 13 +-
.../series/special/EulerMaclaurin.java | 535 ++--
.../core/numerics/utils/Constants.java | 56 +-
.../core/numerics/utils/SimpleMath.java | 145 +-
12 files changed, 4304 insertions(+), 4303 deletions(-)
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/ClenshawCurtis.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/ClenshawCurtis.java
index e585b1fc8..44cec5c07 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/ClenshawCurtis.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/ClenshawCurtis.java
@@ -5,584 +5,581 @@
import org.matheclipse.core.numerics.utils.SimpleMath;
/**
- * An adaptive numerical integrator based on the Clenshaw-Curtis quadrature
- * rule. There are two implementations:
+ * An adaptive numerical integrator based on the Clenshaw-Curtis quadrature rule. There are two
+ * implementations:
*
- * - Havie : the integral is approximated by Chebychev polynomials over each
- * subinterval, as introduced in [1]. This code is a translation of the Fortran
- * subroutine by John Burkardt.
- * - Oliver : a doubly-adaptive Clenshaw-Curtis algorithm also using Chebychev
- * polynomials as introduced in [2].
+ * - Havie : the integral is approximated by Chebychev polynomials over each subinterval, as
+ * introduced in [1]. This code is a translation of the Fortran subroutine by John Burkardt.
+ * - Oliver : a doubly-adaptive Clenshaw-Curtis algorithm also using Chebychev polynomials as
+ * introduced in [2].
*
*
*
* References:
*
- * - [1] H�vie, T. "On a modification of the Clenshaw-Curtis quadrature
- * formula." BIT Numerical Mathematics 9.4 (1969): 338-350.
- * - [2] Oliver, J. "A doubly-adaptive Clenshaw-Curtis quadrature method." The
- * Computer Journal 15.2 (1972): 141-147.
+ * - [1] H�vie, T. "On a modification of the Clenshaw-Curtis quadrature formula." BIT Numerical
+ * Mathematics 9.4 (1969): 338-350.
+ * - [2] Oliver, J. "A doubly-adaptive Clenshaw-Curtis quadrature method." The Computer Journal
+ * 15.2 (1972): 141-147.
*
*
*/
public final class ClenshawCurtis extends Quadrature {
- /**
- * The extrapolation method to use for Clenshaw-Curtis integration.
- */
- public static enum ClenshawCurtisExtrapolationMethod {
- HAVIE, OLIVER
+ /**
+ * The extrapolation method to use for Clenshaw-Curtis integration.
+ */
+ public static enum ClenshawCurtisExtrapolationMethod {
+ HAVIE, OLIVER
+ }
+
+ private static final double[][] SIGMA = { //
+ {0.455, 0.272, 0.606, 0.811, 0.908}, {0.550, 0.144, 0.257, 0.376, 0.511},
+ {0.667, 0.243, 0.366, 0.449, 0.522}, {0.780, 0.283, 0.468, 0.565, 0.624},
+ {0.855, 0.290, 0.494, 0.634, 0.714}, {-1.00, 0.292, 0.499, 0.644, 0.745}};
+
+ private final ClenshawCurtisExtrapolationMethod myMethod;
+
+ /**
+ * Creates a new instance of the Clenshaw-Curtis integrator.
+ *
+ * @param tolerance the smallest acceptable absolute change in integral estimates in consecutive
+ * iterations that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of evaluations of each function permitted
+ * @param method the extrapolation method to use
+ */
+ public ClenshawCurtis(final double tolerance, final int maxEvaluations,
+ final ClenshawCurtisExtrapolationMethod method) {
+ super(tolerance, maxEvaluations);
+ myMethod = method;
+ }
+
+ public ClenshawCurtis(final double tolerance, final int maxEvaluations) {
+ this(tolerance, maxEvaluations, ClenshawCurtisExtrapolationMethod.OLIVER);
+ }
+
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+ switch (myMethod) {
+ case HAVIE:
+ return havie(f, a, b);
+ case OLIVER:
+ return oliver(f, a, b);
+ default:
+ return new QuadratureResult(Double.NaN, Double.NaN, 0, false);
}
-
- private static final double[][] SIGMA = { //
- { 0.455, 0.272, 0.606, 0.811, 0.908 }, { 0.550, 0.144, 0.257, 0.376, 0.511 },
- { 0.667, 0.243, 0.366, 0.449, 0.522 }, { 0.780, 0.283, 0.468, 0.565, 0.624 },
- { 0.855, 0.290, 0.494, 0.634, 0.714 }, { -1.00, 0.292, 0.499, 0.644, 0.745 } };
-
- private final ClenshawCurtisExtrapolationMethod myMethod;
-
- /**
- * Creates a new instance of the Clenshaw-Curtis integrator.
- *
- * @param tolerance the smallest acceptable absolute change in integral
- * estimates in consecutive iterations that indicates the
- * algorithm has converged
- * @param maxEvaluations the maximum number of evaluations of each function
- * permitted
- * @param method the extrapolation method to use
- */
- public ClenshawCurtis(final double tolerance, final int maxEvaluations,
- final ClenshawCurtisExtrapolationMethod method) {
- super(tolerance, maxEvaluations);
- myMethod = method;
- }
-
- public ClenshawCurtis(final double tolerance, final int maxEvaluations) {
- this(tolerance, maxEvaluations, ClenshawCurtisExtrapolationMethod.OLIVER);
- }
-
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
- switch (myMethod) {
- case HAVIE:
- return havie(f, a, b);
- case OLIVER:
- return oliver(f, a, b);
- default:
- return new QuadratureResult(Double.NaN, Double.NaN, 0, false);
- }
- }
-
- @Override
- public final String getName() {
- return "Clenshaw-Curtis-" + myMethod.toString();
- }
-
- private final QuadratureResult havie(final DoubleUnaryOperator f, double a, double b) {
- final double[] result = new double[1];
- final double[] epsout = new double[1];
- final int[] fev = new int[1];
- final boolean[] success = new boolean[1];
- final double epsin = myTol;
- final int nupper = SimpleMath.log2Int(myMaxEvals) - 1;
- havie(f, a, b, nupper, epsin, epsout, result, fev, success);
- return new QuadratureResult(result[0], epsout[0], fev[0], success[0]);
- }
-
- private final void havie(final DoubleUnaryOperator f, double a, double b, final int nupper,
- final double epsin, final double[] epsout, final double[] result, final int[] fev,
- final boolean[] success) {
- double a0, a1, a2, alf, alfnj, alfno, bet, betnj, betno, bounds, cof, cofmax, const1, const2, deln, deltan,
- error, etank, gamman, hnstep;
- double r1, r2, rk, rn, rnderr, rounde, tend, tnew, triarg, umid, wmean, xmin, xplus, xsink;
- final int mem = 1 << (nupper - 1);
- final double[] acof = new double[mem + 1];
- final double[] bcof = new double[mem + 1];
- final double[] ccof = new double[(mem << 1) + 1];
- int i, index, j, k, ksign, n, ncof, nhalf, nn;
-
- // Set coefficients in formula for accumulated roundoff error.
- // N is the current number of function values used.
- fev[0] = 0;
- rnderr = Constants.EPSILON;
- success[0] = true;
-
- r1 = 1.0;
- r2 = 2.0;
- error = epsin;
-
- // Integration interval parameters.
- alf = 0.5 * (b - a);
- bet = 0.5 * (b + a);
-
- // Parameters for trigonometric recurrence relations.
- triarg = Math.atan(1.0);
- alfno = -1.0;
-
- // Parameters for integration stepsize and loops.
- rn = 2.0;
- n = 2;
- nhalf = 1;
- hnstep = 1.0;
-
- // Initial calculation for the end-point approximation.
+ }
+
+ @Override
+ public final String getName() {
+ return "Clenshaw-Curtis-" + myMethod.toString();
+ }
+
+ private final QuadratureResult havie(final DoubleUnaryOperator f, double a, double b) {
+ final double[] result = new double[1];
+ final double[] epsout = new double[1];
+ final int[] fev = new int[1];
+ final boolean[] success = new boolean[1];
+ final double epsin = myTol;
+ final int nupper = SimpleMath.log2Int(myMaxEvals) - 1;
+ havie(f, a, b, nupper, epsin, epsout, result, fev, success);
+ return new QuadratureResult(result[0], epsout[0], fev[0], success[0]);
+ }
+
+ private final void havie(final DoubleUnaryOperator f, double a, double b, final int nupper,
+ final double epsin, final double[] epsout, final double[] result, final int[] fev,
+ final boolean[] success) {
+ double a0, a1, a2, alf, alfnj, alfno, bet, betnj, betno, bounds, cof, cofmax, const1, const2,
+ deln, deltan, error, etank, gamman, hnstep;
+ double r1, r2, rk, rn, rnderr, rounde, tend, tnew, triarg, umid, wmean, xmin, xplus, xsink;
+ final int mem = 1 << (nupper - 1);
+ final double[] acof = new double[mem + 1];
+ final double[] bcof = new double[mem + 1];
+ final double[] ccof = new double[(mem << 1) + 1];
+ int i, index, j, k, ksign, n, ncof, nhalf, nn;
+
+ // Set coefficients in formula for accumulated roundoff error.
+ // N is the current number of function values used.
+ fev[0] = 0;
+ rnderr = Constants.EPSILON;
+ success[0] = true;
+
+ r1 = 1.0;
+ r2 = 2.0;
+ error = epsin;
+
+ // Integration interval parameters.
+ alf = 0.5 * (b - a);
+ bet = 0.5 * (b + a);
+
+ // Parameters for trigonometric recurrence relations.
+ triarg = Math.atan(1.0);
+ alfno = -1.0;
+
+ // Parameters for integration stepsize and loops.
+ rn = 2.0;
+ n = 2;
+ nhalf = 1;
+ hnstep = 1.0;
+
+ // Initial calculation for the end-point approximation.
const1 = 0.5 * (f.applyAsDouble(a) + f.applyAsDouble(b));
- fev[0] += 2;
+ fev[0] += 2;
const2 = f.applyAsDouble(bet);
- acof[1 - 1] = 0.5 * (const1 + const2);
- acof[2 - 1] = 0.5 * (const1 - const2);
- bcof[2 - 1] = acof[2 - 1];
- tend = 2.0 * (acof[1 - 1] - acof[2 - 1] / 3.0);
-
- // Start actual calculations.
- for (i = 1; i <= nupper; ++i) {
-
- // Compute function values.
- const1 = -Math.sin(triarg);
- const2 = 0.5 * alfno / const1;
- alfno = const1;
- betno = const2;
- gamman = 1.0 - 2.0 * alfno * alfno;
- deltan = -2.0 * alfno * betno;
- bcof[1 - 1] = 0.0;
- for (j = 1; j <= nhalf; ++j) {
- alfnj = gamman * const1 + deltan * const2;
- betnj = gamman * const2 - deltan * const1;
- xplus = alf * alfnj + bet;
- xmin = -alf * alfnj + bet;
+ acof[1 - 1] = 0.5 * (const1 + const2);
+ acof[2 - 1] = 0.5 * (const1 - const2);
+ bcof[2 - 1] = acof[2 - 1];
+ tend = 2.0 * (acof[1 - 1] - acof[2 - 1] / 3.0);
+
+ // Start actual calculations.
+ for (i = 1; i <= nupper; ++i) {
+
+ // Compute function values.
+ const1 = -Math.sin(triarg);
+ const2 = 0.5 * alfno / const1;
+ alfno = const1;
+ betno = const2;
+ gamman = 1.0 - 2.0 * alfno * alfno;
+ deltan = -2.0 * alfno * betno;
+ bcof[1 - 1] = 0.0;
+ for (j = 1; j <= nhalf; ++j) {
+ alfnj = gamman * const1 + deltan * const2;
+ betnj = gamman * const2 - deltan * const1;
+ xplus = alf * alfnj + bet;
+ xmin = -alf * alfnj + bet;
ccof[j - 1] = f.applyAsDouble(xplus) + f.applyAsDouble(xmin);
- fev[0] += 2;
- bcof[1 - 1] += ccof[j - 1];
- const1 = alfnj;
- const2 = betnj;
- }
- bcof[1 - 1] *= 0.5 * hnstep;
-
- // Calculation of first B-coefficient finished compute the higher
- // coefficients if NHALF greater than one.
- if (nhalf > 1) {
-
- const1 = 1.0;
- const2 = 0.0;
- ncof = nhalf - 1;
- ksign = -1;
- for (k = 1; k <= ncof; ++k) {
-
- // Compute trigonometric sum for B-coefficient.
- etank = gamman * const1 - deltan * const2;
- xsink = gamman * const2 + deltan * const1;
- cof = 2.0 * (2.0 * etank * etank - 1.0);
- a2 = a1 = 0.0;
- a0 = ccof[nhalf - 1];
- for (j = 1; j <= ncof; ++j) {
- a2 = a1;
- a1 = a0;
- index = nhalf - j;
- a0 = ccof[index - 1] + cof * a1 - a2;
- }
- bcof[k + 1 - 1] = hnstep * (a0 - a1) * etank;
- bcof[k + 1 - 1] *= ksign;
- ksign = -ksign;
- const1 = etank;
- const2 = xsink;
- }
- }
-
- // Compute new modified mid-point approximation when the interval
- // of integration is divided in N equal sub intervals.
- umid = 0.0;
- rk = rn;
- nn = nhalf + 1;
- for (k = 1; k <= nn; ++k) {
- index = nn + 1 - k;
- umid += bcof[index - 1] / (rk * rk - 1.0);
- rk -= 2.0;
- }
- umid *= -2.0;
-
- // Compute new C-coefficients for end-point approximation and largest
- // absolute value of coefficients.
- nn = n + 2;
- cofmax = 0.0;
- for (j = 1; j <= nhalf; ++j) {
- index = nn - j;
- ccof[j - 1] = 0.5 * (acof[j - 1] + bcof[j - 1]);
- ccof[index - 1] = 0.5 * (acof[j - 1] - bcof[j - 1]);
- const1 = Math.abs(ccof[j - 1]);
- cofmax = Math.max(cofmax, const1);
- const1 = Math.abs(ccof[index - 1]);
- cofmax = Math.max(cofmax, const1);
- }
- ccof[nhalf + 1 - 1] = acof[nhalf + 1 - 1];
-
- // Compute new end-point approximation when the interval of
- // integration is divided in 2N equal sub intervals.
- wmean = 0.5 * (tend + umid);
- bounds = 0.5 * (tend - umid);
- deln = 0.0;
- rk = 2.0 * rn;
- for (j = 1; j <= nhalf; ++j) {
- index = n + 2 - j;
- deln += ccof[index - 1] / (rk * rk - 1.0);
- rk -= 2.0;
- }
- deln *= -2.0;
- tnew = wmean + deln;
- epsout[0] = Math.abs(bounds / tnew);
- if (cofmax >= rnderr) {
- rounde = rnderr * (r1 + r2 * rn);
- epsout[0] = Math.max(epsout[0], rounde);
- error = Math.max(error, rounde);
- if (error >= epsout[0]) {
-
- // Required accuracy obtained or the maximum number of function
- // values used without obtaining the required accuracy.
- n = 2 * n + 1;
- tend = alf * (tend + deln);
- umid = alf * (umid + deln);
- deln *= alf;
- result[0] = alf * tnew;
- success[0] = true;
- return;
- }
- }
-
- // If I = NUPPER then the required accuracy is not obtained.
- if (i == nupper) {
-
- // Required accuracy obtained or the maximum number of function
- // values used without obtaining the required accuracy.
- n = (n << 1) + 1;
- tend = alf * (tend + deln);
- umid = alf * (umid + deln);
- deln *= alf;
- result[0] = alf * tnew;
- success[0] = false;
- return;
- }
- System.arraycopy(ccof, 0, acof, 0, n + 1);
- bcof[n + 1 - 1] = ccof[n + 1 - 1];
- tend = tnew;
- nhalf = n;
- n <<= 1;
- rn *= 2.0;
- hnstep *= 0.5;
- triarg *= 0.5;
- }
+ fev[0] += 2;
+ bcof[1 - 1] += ccof[j - 1];
+ const1 = alfnj;
+ const2 = betnj;
+ }
+ bcof[1 - 1] *= 0.5 * hnstep;
+
+ // Calculation of first B-coefficient finished compute the higher
+ // coefficients if NHALF greater than one.
+ if (nhalf > 1) {
+
+ const1 = 1.0;
+ const2 = 0.0;
+ ncof = nhalf - 1;
+ ksign = -1;
+ for (k = 1; k <= ncof; ++k) {
+
+ // Compute trigonometric sum for B-coefficient.
+ etank = gamman * const1 - deltan * const2;
+ xsink = gamman * const2 + deltan * const1;
+ cof = 2.0 * (2.0 * etank * etank - 1.0);
+ a2 = a1 = 0.0;
+ a0 = ccof[nhalf - 1];
+ for (j = 1; j <= ncof; ++j) {
+ a2 = a1;
+ a1 = a0;
+ index = nhalf - j;
+ a0 = ccof[index - 1] + cof * a1 - a2;
+ }
+ bcof[k + 1 - 1] = hnstep * (a0 - a1) * etank;
+ bcof[k + 1 - 1] *= ksign;
+ ksign = -ksign;
+ const1 = etank;
+ const2 = xsink;
+ }
+ }
+
+ // Compute new modified mid-point approximation when the interval
+ // of integration is divided in N equal sub intervals.
+ umid = 0.0;
+ rk = rn;
+ nn = nhalf + 1;
+ for (k = 1; k <= nn; ++k) {
+ index = nn + 1 - k;
+ umid += bcof[index - 1] / (rk * rk - 1.0);
+ rk -= 2.0;
+ }
+ umid *= -2.0;
+
+ // Compute new C-coefficients for end-point approximation and largest
+ // absolute value of coefficients.
+ nn = n + 2;
+ cofmax = 0.0;
+ for (j = 1; j <= nhalf; ++j) {
+ index = nn - j;
+ ccof[j - 1] = 0.5 * (acof[j - 1] + bcof[j - 1]);
+ ccof[index - 1] = 0.5 * (acof[j - 1] - bcof[j - 1]);
+ const1 = Math.abs(ccof[j - 1]);
+ cofmax = Math.max(cofmax, const1);
+ const1 = Math.abs(ccof[index - 1]);
+ cofmax = Math.max(cofmax, const1);
+ }
+ ccof[nhalf + 1 - 1] = acof[nhalf + 1 - 1];
+
+ // Compute new end-point approximation when the interval of
+ // integration is divided in 2N equal sub intervals.
+ wmean = 0.5 * (tend + umid);
+ bounds = 0.5 * (tend - umid);
+ deln = 0.0;
+ rk = 2.0 * rn;
+ for (j = 1; j <= nhalf; ++j) {
+ index = n + 2 - j;
+ deln += ccof[index - 1] / (rk * rk - 1.0);
+ rk -= 2.0;
+ }
+ deln *= -2.0;
+ tnew = wmean + deln;
+ epsout[0] = Math.abs(bounds / tnew);
+ if (cofmax >= rnderr) {
+ rounde = rnderr * (r1 + r2 * rn);
+ epsout[0] = Math.max(epsout[0], rounde);
+ error = Math.max(error, rounde);
+ if (error >= epsout[0]) {
+
+ // Required accuracy obtained or the maximum number of function
+ // values used without obtaining the required accuracy.
+ n = 2 * n + 1;
+ tend = alf * (tend + deln);
+ umid = alf * (umid + deln);
+ deln *= alf;
+ result[0] = alf * tnew;
+ success[0] = true;
+ return;
+ }
+ }
+
+ // If I = NUPPER then the required accuracy is not obtained.
+ if (i == nupper) {
+
+ // Required accuracy obtained or the maximum number of function
+ // values used without obtaining the required accuracy.
+ n = (n << 1) + 1;
+ tend = alf * (tend + deln);
+ umid = alf * (umid + deln);
+ deln *= alf;
+ result[0] = alf * tnew;
+ success[0] = false;
+ return;
+ }
+ System.arraycopy(ccof, 0, acof, 0, n + 1);
+ bcof[n + 1 - 1] = ccof[n + 1 - 1];
+ tend = tnew;
+ nhalf = n;
+ n <<= 1;
+ rn *= 2.0;
+ hnstep *= 0.5;
+ triarg *= 0.5;
}
-
- private final QuadratureResult oliver(final DoubleUnaryOperator f, double a, double b) {
- final double eps = myTol;
- final double acc = 0.0;
- final double eta = SimpleMath.D1MACH[1 - 1];
- final int divmax = 256;
- final double[] ans = new double[1];
- final double[] error = new double[1];
- final int[] fev = new int[1];
- final boolean[] success = new boolean[1];
- adapquad(f, a, b, eps, acc, eta, divmax, ans, error, fev, myMaxEvals, success);
- return new QuadratureResult(ans[0], error[0], fev[0], success[0]);
+ }
+
+ private final QuadratureResult oliver(final DoubleUnaryOperator f, double a, double b) {
+ final double eps = myTol;
+ final double acc = 0.0;
+ final double eta = SimpleMath.D1MACH[1 - 1];
+ final int divmax = 256;
+ final double[] ans = new double[1];
+ final double[] error = new double[1];
+ final int[] fev = new int[1];
+ final boolean[] success = new boolean[1];
+ adapquad(f, a, b, eps, acc, eta, divmax, ans, error, fev, myMaxEvals, success);
+ return new QuadratureResult(ans[0], error[0], fev[0], success[0]);
+ }
+
+ private static final void adapquad(final DoubleUnaryOperator f, double a, double b, double eps,
+ double acc, final double eta, final int divmax, final double[] ans, final double[] error,
+ final int[] fev, final int maxfev, final boolean[] success) {
+ int i, j = 0, m, mmax, n, n2, nmax, maxrule, order = 0, div;
+ double c, cprev = 0, e = 0, eprev = 0, fmax = 0, fmin = 0, h = 0, hmin, iint = 0, intprev = 0,
+ k = 0, k1 = 0, re = 0, x, xa, xb, xc;
+ boolean caution = false;
+ final double[] ec = new double[6];
+ final double[] fs = new double[divmax];
+ final double[] xs = new double[divmax];
+ final double[] fx = new double[129];
+ final double[] w1 = new double[129];
+ final double[] t = new double[65];
+ final double[] w = new double[126];
+
+ ans[0] = error[0] = 0.0;
+ fev[0] = 0;
+ success[0] = true;
+ if (a > b) {
+ c = b;
+ b = a;
+ a = c;
}
-
- private static final void adapquad(final DoubleUnaryOperator f, double a, double b, double eps,
- double acc, final double eta, final int divmax, final double[] ans, final double[] error, final int[] fev,
- final int maxfev, final boolean[] success) {
- int i, j = 0, m, mmax, n, n2, nmax, maxrule, order = 0, div;
- double c, cprev = 0, e = 0, eprev = 0, fmax = 0, fmin = 0, h = 0, hmin, iint = 0, intprev = 0, k = 0, k1 = 0,
- re = 0, x, xa, xb, xc;
- boolean caution = false;
- final double[] ec = new double[6];
- final double[] fs = new double[divmax];
- final double[] xs = new double[divmax];
- final double[] fx = new double[129];
- final double[] w1 = new double[129];
- final double[] t = new double[65];
- final double[] w = new double[126];
-
- ans[0] = error[0] = 0.0;
- fev[0] = 0;
- success[0] = true;
- if (a > b) {
- c = b;
- b = a;
- a = c;
- }
- hmin = (b - a) / SimpleMath.pow(2, divmax);
- if (acc < eta) {
- acc = eta;
- }
- acc *= 16;
- x = 4;
- xa = 64;
- for (i = 1; i <= 6; ++i) {
- ec[i - 1] = xa / ((x * x - 1) * (x * x - 9));
- x = x + x;
- xa = xa + xa;
- }
- n = 4;
- n2 = 2;
- nmax = 128;
- m = mmax = nmax / n;
- t[0] = 1;
- t[nmax >> 1] = 0;
- maxrule = div = 0;
- w1[0] = -1;
- maxrule = quadrule(t, w, w1, n, n2, m, maxrule);
- xa = xc = a;
- xb = b;
+ hmin = (b - a) / SimpleMath.pow(2, divmax);
+ if (acc < eta) {
+ acc = eta;
+ }
+ acc *= 16;
+ x = 4;
+ xa = 64;
+ for (i = 1; i <= 6; ++i) {
+ ec[i - 1] = xa / ((x * x - 1) * (x * x - 9));
+ x = x + x;
+ xa = xa + xa;
+ }
+ n = 4;
+ n2 = 2;
+ nmax = 128;
+ m = mmax = nmax / n;
+ t[0] = 1;
+ t[nmax >> 1] = 0;
+ maxrule = div = 0;
+ w1[0] = -1;
+ maxrule = quadrule(t, w, w1, n, n2, m, maxrule);
+ xa = xc = a;
+ xb = b;
fx[0] = f.applyAsDouble(b);
fx[n] = f.applyAsDouble(a);
- fev[0] = 2;
-
- // next is one of the following values:
- // 0 : NEXT
- // 1 : AGAIN
- // 2 : EVAL
- // 3 : TEST
- // 4 : UPDATE
- // 5 : DOUBLE
- // 6 : SPLIT
- int next = 0;
- while (true) {
-
- if (next == 0) {
-
- // NEXT: Integration over new subinterval
- n = 4;
- n2 = 2;
- m = mmax;
- order = 1;
- caution = xa < xc;
- h = xb - xa;
- k1 = h / (b - xa);
- if (k1 < 0.1) {
- k1 = 0.1;
- }
- h *= 0.5;
- j = 1;
+ fev[0] = 2;
+
+ // next is one of the following values:
+ // 0 : NEXT
+ // 1 : AGAIN
+ // 2 : EVAL
+ // 3 : TEST
+ // 4 : UPDATE
+ // 5 : DOUBLE
+ // 6 : SPLIT
+ int next = 0;
+ while (true) {
+
+ if (next == 0) {
+
+ // NEXT: Integration over new subinterval
+ n = 4;
+ n2 = 2;
+ m = mmax;
+ order = 1;
+ caution = xa < xc;
+ h = xb - xa;
+ k1 = h / (b - xa);
+ if (k1 < 0.1) {
+ k1 = 0.1;
+ }
+ h *= 0.5;
+ j = 1;
fx[n2] = f.applyAsDouble(xa + h);
- ++fev[0];
- fmin = fmax = fx[0];
- if (fmax < fx[n]) {
- fmax = fx[n];
- } else if (fmin > fx[n]) {
- fmin = fx[n];
- }
- if (fmax < fx[n2]) {
- fmax = fx[n2];
- } else if (fmin > fx[n2]) {
- fmin = fx[n2];
- }
- next = 1;
- if (fev[0] > maxfev) {
- success[0] = false;
- return;
- }
- }
-
- if (next == 1) {
-
- // AGAIN: Calculate new integrand values, Chebyshev coefficients and error
- // estimate
- for (i = 1; i <= n2 - 1; i += j) {
+ ++fev[0];
+ fmin = fmax = fx[0];
+ if (fmax < fx[n]) {
+ fmax = fx[n];
+ } else if (fmin > fx[n]) {
+ fmin = fx[n];
+ }
+ if (fmax < fx[n2]) {
+ fmax = fx[n2];
+ } else if (fmin > fx[n2]) {
+ fmin = fx[n2];
+ }
+ next = 1;
+ if (fev[0] > maxfev) {
+ success[0] = false;
+ return;
+ }
+ }
+
+ if (next == 1) {
+
+ // AGAIN: Calculate new integrand values, Chebyshev coefficients and error
+ // estimate
+ for (i = 1; i <= n2 - 1; i += j) {
fx[i] = f.applyAsDouble(xa + (1 + t[i * m]) * h);
- ++fev[0];
- if (fmax < fx[i]) {
- fmax = fx[i];
- } else if (fmin > fx[i]) {
- fmin = fx[i];
- }
- fx[n - i] = f.applyAsDouble(xa + (1 - t[i * m]) * h);
- ++fev[0];
- if (fmax < fx[n - i]) {
- fmax = fx[n - i];
- } else if (fmin > fx[n - i]) {
- fmin = fx[n - i];
- }
- if (fev[0] > maxfev) {
- success[0] = false;
- return;
- }
- }
- re = acc * Math.max(Math.abs(fmax), Math.abs(fmin));
- j = n == 4 ? 4 : 6;
- k = 0;
- c = Math.abs(cheb(-1, fx, n)) / n;
- for (i = 2; i <= j; i += 2) {
- if (i <= n2) {
- x = -t[i * m];
- } else {
- x = t[(n - i) * m];
- }
- cprev = c;
- c = Math.abs(cheb(x, fx, n)) / n2;
- if (c > re) {
- if (k < cprev / c) {
- k = cprev / c;
- }
- } else if (cprev > re) {
- k = 1;
- }
- }
- next = 2;
- if (k > SIGMA[order - 1][4]) {
- if (n == 4) {
- next = 6;
- }
- } else {
- if (n == 4) {
- cprev = c;
- } else if (cprev < re) {
- cprev = k * c;
- }
- e = h * cprev * ec[order - 1] * k * k * k;
- for (i = 0; k > SIGMA[order - 1][i]; ++i) {
- e *= 2;
- }
- re = h * re;
- }
- }
-
- if (next == 2) {
-
- // EVAL: Evaluate integral and select appropriate error estimate
- iint = w1[n] * (fx[0] + fx[n]) + w[n - 3] * fx[n2];
- for (i = 1; i <= n2 - 1; ++i) {
- iint += w[n2 + i - 3] * (fx[i] + fx[n - i]);
- }
- iint *= h;
- if (n != 4) {
- c = Math.abs(iint - intprev);
- if (c > eprev) {
- caution = true;
- if (xc < xb) {
- xc = xb;
- }
- } else {
- caution = false;
- }
- if (k > SIGMA[order - 1][4] || caution) {
- e = c;
- }
- if (e > c) {
- e = c;
- }
- }
- next = 3;
- }
-
- if (next == 3) {
-
- // TEST: Finish consideration of current subinterval if local error acceptable
- if (e < re || e <= k1 * eps) {
- next = 4;
- } else if (k > SIGMA[order - 1][0]) {
- next = 6;
- } else {
- next = 5;
- }
- }
-
- if (next == 4) {
-
- // UPDATE
- if (n != 4 || !(caution || (xa == a && div == 0))) {
- if (e < re) {
- e = re;
- }
- error[0] += e;
- eps -= e;
- if (eps < 0.1 * error[0]) {
- eps = 0.1 * error[0];
- }
- ans[0] += iint;
- if (div == 0) {
- success[0] = true;
- return;
- }
- --div;
- xa = xb;
- xb = xs[div];
- fx[4] = fx[0];
- fx[0] = fs[div];
- next = 0;
- } else {
- next = 5;
- }
- }
-
- if (next == 5) {
-
- // DOUBLE: Double order of formula
- for (i = n; i >= 1; --i) {
- fx[i << 1] = fx[i];
- }
- n2 = n;
- n <<= 1;
- m *= 0.5;
- ++order;
- eprev = e;
- intprev = iint;
- if (eprev < re) {
- eprev = re;
- }
- if (n > maxrule) {
- maxrule = quadrule(t, w, w1, n, n2, m, maxrule);
- }
- j = 2;
- next = 1;
- }
-
- if (next == 6) {
-
- // SPLIT: Split current subinterval unless simple error estimate acceptable and
- // consider left half
- e = 2 * h * (fmax - fmin);
- if (e < re || e <= k1 * eps) {
- iint = h * (fmax + fmin);
- next = 4;
- } else {
- if (h < hmin) {
- success[0] = false;
- return;
- }
- xs[div] = xb;
- xb = xa + h;
- fs[div] = fx[0];
- fx[0] = fx[n2];
- fx[4] = fx[n];
- ++div;
- next = 0;
- }
- }
- }
+ ++fev[0];
+ if (fmax < fx[i]) {
+ fmax = fx[i];
+ } else if (fmin > fx[i]) {
+ fmin = fx[i];
+ }
+ fx[n - i] = f.applyAsDouble(xa + (1 - t[i * m]) * h);
+ ++fev[0];
+ if (fmax < fx[n - i]) {
+ fmax = fx[n - i];
+ } else if (fmin > fx[n - i]) {
+ fmin = fx[n - i];
+ }
+ if (fev[0] > maxfev) {
+ success[0] = false;
+ return;
+ }
+ }
+ re = acc * Math.max(Math.abs(fmax), Math.abs(fmin));
+ j = n == 4 ? 4 : 6;
+ k = 0;
+ c = Math.abs(cheb(-1, fx, n)) / n;
+ for (i = 2; i <= j; i += 2) {
+ if (i <= n2) {
+ x = -t[i * m];
+ } else {
+ x = t[(n - i) * m];
+ }
+ cprev = c;
+ c = Math.abs(cheb(x, fx, n)) / n2;
+ if (c > re) {
+ if (k < cprev / c) {
+ k = cprev / c;
+ }
+ } else if (cprev > re) {
+ k = 1;
+ }
+ }
+ next = 2;
+ if (k > SIGMA[order - 1][4]) {
+ if (n == 4) {
+ next = 6;
+ }
+ } else {
+ if (n == 4) {
+ cprev = c;
+ } else if (cprev < re) {
+ cprev = k * c;
+ }
+ e = h * cprev * ec[order - 1] * k * k * k;
+ for (i = 0; k > SIGMA[order - 1][i]; ++i) {
+ e *= 2;
+ }
+ re = h * re;
+ }
+ }
+
+ if (next == 2) {
+
+ // EVAL: Evaluate integral and select appropriate error estimate
+ iint = w1[n] * (fx[0] + fx[n]) + w[n - 3] * fx[n2];
+ for (i = 1; i <= n2 - 1; ++i) {
+ iint += w[n2 + i - 3] * (fx[i] + fx[n - i]);
+ }
+ iint *= h;
+ if (n != 4) {
+ c = Math.abs(iint - intprev);
+ if (c > eprev) {
+ caution = true;
+ if (xc < xb) {
+ xc = xb;
+ }
+ } else {
+ caution = false;
+ }
+ if (k > SIGMA[order - 1][4] || caution) {
+ e = c;
+ }
+ if (e > c) {
+ e = c;
+ }
+ }
+ next = 3;
+ }
+
+ if (next == 3) {
+
+ // TEST: Finish consideration of current subinterval if local error acceptable
+ if (e < re || e <= k1 * eps) {
+ next = 4;
+ } else if (k > SIGMA[order - 1][0]) {
+ next = 6;
+ } else {
+ next = 5;
+ }
+ }
+
+ if (next == 4) {
+
+ // UPDATE
+ if (n != 4 || !(caution || (xa == a && div == 0))) {
+ if (e < re) {
+ e = re;
+ }
+ error[0] += e;
+ eps -= e;
+ if (eps < 0.1 * error[0]) {
+ eps = 0.1 * error[0];
+ }
+ ans[0] += iint;
+ if (div == 0) {
+ success[0] = true;
+ return;
+ }
+ --div;
+ xa = xb;
+ xb = xs[div];
+ fx[4] = fx[0];
+ fx[0] = fs[div];
+ next = 0;
+ } else {
+ next = 5;
+ }
+ }
+
+ if (next == 5) {
+
+ // DOUBLE: Double order of formula
+ for (i = n; i >= 1; --i) {
+ fx[i << 1] = fx[i];
+ }
+ n2 = n;
+ n <<= 1;
+ m *= 0.5;
+ ++order;
+ eprev = e;
+ intprev = iint;
+ if (eprev < re) {
+ eprev = re;
+ }
+ if (n > maxrule) {
+ maxrule = quadrule(t, w, w1, n, n2, m, maxrule);
+ }
+ j = 2;
+ next = 1;
+ }
+
+ if (next == 6) {
+
+ // SPLIT: Split current subinterval unless simple error estimate acceptable and
+ // consider left half
+ e = 2 * h * (fmax - fmin);
+ if (e < re || e <= k1 * eps) {
+ iint = h * (fmax + fmin);
+ next = 4;
+ } else {
+ if (h < hmin) {
+ success[0] = false;
+ return;
+ }
+ xs[div] = xb;
+ xb = xa + h;
+ fs[div] = fx[0];
+ fx[0] = fx[n2];
+ fx[4] = fx[n];
+ ++div;
+ next = 0;
+ }
+ }
}
+ }
- private static final int quadrule(final double[] t, final double[] w, final double[] w1, final int n, final int n2,
- final int m, final int maxrule) {
- for (int i = 1; i <= n2 - 1; i += 2) {
- t[i * m] = Math.cos((Math.PI * i) / n);
- }
- for (int i = (maxrule >> 1) + 2; i <= n; i += 2) {
- w1[i - 1] = 0;
- w1[i] = 1.0 / (i * i - 1);
- }
- for (int i = 1; i <= n2; ++i) {
- w[n2 + i - 3] = -4 * cheb(t[i * m], w1, n) / n;
- }
- return n;
+ private static final int quadrule(final double[] t, final double[] w, final double[] w1,
+ final int n, final int n2, final int m, final int maxrule) {
+ for (int i = 1; i <= n2 - 1; i += 2) {
+ t[i * m] = Math.cos((Math.PI * i) / n);
}
-
- private static final double cheb(final double x, final double[] a, final int n) {
- double b1 = 0.0;
- double b0 = 0.5 * a[n];
- final double twox = 2.0 * x;
- for (int r = n - 1; r >= 1; --r) {
- final double b2 = b1;
- b1 = b0;
- b0 = twox * b1 - b2 + a[r];
- }
- return x * b0 - b1 + 0.5 * a[0];
+ for (int i = (maxrule >> 1) + 2; i <= n; i += 2) {
+ w1[i - 1] = 0;
+ w1[i] = 1.0 / (i * i - 1);
+ }
+ for (int i = 1; i <= n2; ++i) {
+ w[n2 + i - 3] = -4 * cheb(t[i * m], w1, n) / n;
+ }
+ return n;
+ }
+
+ private static final double cheb(final double x, final double[] a, final int n) {
+ double b1 = 0.0;
+ double b0 = 0.5 * a[n];
+ final double twox = 2.0 * x;
+ for (int r = n - 1; r >= 1; --r) {
+ final double b2 = b1;
+ b1 = b0;
+ b0 = twox * b1 - b2 + a[r];
}
+ return x * b0 - b1 + 0.5 * a[0];
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussKronrod.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussKronrod.java
index 98d96ecc7..10534b669 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussKronrod.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussKronrod.java
@@ -5,1191 +5,1196 @@
import org.matheclipse.core.numerics.utils.SimpleMath;
/**
- * Integrate a real function of one variable using a globally adaptive
- * Gauss-Kronrod quadrature rule. This algorithm is a translation of subroutines
- * from the QUADPACK library and well-documented in [1].
+ * Integrate a real function of one variable using a globally adaptive Gauss-Kronrod quadrature
+ * rule. This algorithm is a translation of subroutines from the QUADPACK library and
+ * well-documented in [1].
*
*
* References:
*
- * - [1] Piessens, Robert, et al. QUADPACK: A subroutine package for automatic
- * integration. Vol. 1. Springer Science & Business Media, 2012.
+ * - [1] Piessens, Robert, et al. QUADPACK: A subroutine package for automatic integration. Vol.
+ * 1. Springer Science & Business Media, 2012.
*
*
*/
public final class GaussKronrod extends Quadrature {
- private static final double EPMACH = SimpleMath.D1MACH[4 - 1];
- private static final double UFLOW = SimpleMath.D1MACH[1 - 1];
- private static final double OFLOW = SimpleMath.D1MACH[2 - 1];
-
- private static final double[] WG21 = { //
- 0.066671344308688137593568809893332, 0.149451349150580593145776339657697,
- 0.219086362515982043995534934228163, 0.269266719309996355091226921569469,
- 0.295524224714752870173892994651338 };
- private static final double[] XGK21 = { //
- 0.995657163025808080735527280689003, 0.973906528517171720077964012084452,
- 0.930157491355708226001207180059508, 0.865063366688984510732096688423493,
- 0.780817726586416897063717578345042, 0.679409568299024406234327365114874,
- 0.562757134668604683339000099272694, 0.433395394129247190799265943165784,
- 0.294392862701460198131126603103866, 0.148874338981631210884826001129720,
- 0.000000000000000000000000000000000 };
- private static final double[] WGK21 = { //
- 0.011694638867371874278064396062192, 0.032558162307964727478818972459390,
- 0.054755896574351996031381300244580, 0.075039674810919952767043140916190,
- 0.093125454583697605535065465083366, 0.109387158802297641899210590325805,
- 0.123491976262065851077958109831074, 0.134709217311473325928054001771707,
- 0.142775938577060080797094273138717, 0.147739104901338491374841515972068,
- 0.149445554002916905664936468389821 };
-
- private static final double[] WG15I = { //
- 0.0000000000000000, 0.1294849661688697, 0.0000000000000000, //
- 0.2797053914892767, 0.0000000000000000, 0.3818300505051189, //
- 0.0000000000000000, 0.4179591836734694 };
- private static final double[] XGK15I = { //
- 0.9914553711208126, 0.9491079123427585, 0.8648644233597691, //
- 0.7415311855993944, 0.5860872354676911, 0.4058451513773972, //
- 0.2077849550078985, 0.0000000000000000 };
- private static final double[] WGK15I = { //
- 0.02293532201052922, 0.06309209262997855, 0.1047900103222502, //
- 0.1406532597155259, 0.1690047266392679, 0.1903505780647854, //
- 0.2044329400752989, 0.2094821410847278 };
-
- private final double myRelTol;
-
- /**
- * Creates a new instance of the Gauss-Kronrod quadrature integrator.
- *
- * @param relativeTolerance the smallest acceptable relative change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param tolerance the smallest acceptable absolute change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param maxEvaluations the maximum number of evaluations of each function
- * permitted
- */
- public GaussKronrod(final double tolerance, final double relativeTolerance, final int maxEvaluations) {
- super(tolerance, maxEvaluations);
- myRelTol = relativeTolerance;
+ private static final double EPMACH = SimpleMath.D1MACH[4 - 1];
+ private static final double UFLOW = SimpleMath.D1MACH[1 - 1];
+ private static final double OFLOW = SimpleMath.D1MACH[2 - 1];
+
+ private static final double[] WG21 = { //
+ 0.066671344308688137593568809893332, 0.149451349150580593145776339657697,
+ 0.219086362515982043995534934228163, 0.269266719309996355091226921569469,
+ 0.295524224714752870173892994651338};
+ private static final double[] XGK21 = { //
+ 0.995657163025808080735527280689003, 0.973906528517171720077964012084452,
+ 0.930157491355708226001207180059508, 0.865063366688984510732096688423493,
+ 0.780817726586416897063717578345042, 0.679409568299024406234327365114874,
+ 0.562757134668604683339000099272694, 0.433395394129247190799265943165784,
+ 0.294392862701460198131126603103866, 0.148874338981631210884826001129720,
+ 0.000000000000000000000000000000000};
+ private static final double[] WGK21 = { //
+ 0.011694638867371874278064396062192, 0.032558162307964727478818972459390,
+ 0.054755896574351996031381300244580, 0.075039674810919952767043140916190,
+ 0.093125454583697605535065465083366, 0.109387158802297641899210590325805,
+ 0.123491976262065851077958109831074, 0.134709217311473325928054001771707,
+ 0.142775938577060080797094273138717, 0.147739104901338491374841515972068,
+ 0.149445554002916905664936468389821};
+
+ private static final double[] WG15I = { //
+ 0.0000000000000000, 0.1294849661688697, 0.0000000000000000, //
+ 0.2797053914892767, 0.0000000000000000, 0.3818300505051189, //
+ 0.0000000000000000, 0.4179591836734694};
+ private static final double[] XGK15I = { //
+ 0.9914553711208126, 0.9491079123427585, 0.8648644233597691, //
+ 0.7415311855993944, 0.5860872354676911, 0.4058451513773972, //
+ 0.2077849550078985, 0.0000000000000000};
+ private static final double[] WGK15I = { //
+ 0.02293532201052922, 0.06309209262997855, 0.1047900103222502, //
+ 0.1406532597155259, 0.1690047266392679, 0.1903505780647854, //
+ 0.2044329400752989, 0.2094821410847278};
+
+ private final double myRelTol;
+
+ /**
+ * Creates a new instance of the Gauss-Kronrod quadrature integrator.
+ *
+ * @param relativeTolerance the smallest acceptable relative change in integral estimates in
+ * consecutive iterations that indicates the algorithm has converged
+ * @param tolerance the smallest acceptable absolute change in integral estimates in consecutive
+ * iterations that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of evaluations of each function permitted
+ */
+ public GaussKronrod(final double tolerance, final double relativeTolerance,
+ final int maxEvaluations) {
+ super(tolerance, maxEvaluations);
+ myRelTol = relativeTolerance;
+ }
+
+ public GaussKronrod(final double tolerance, final int maxEvaluations) {
+ this(tolerance, 50.0 * Constants.EPSILON, maxEvaluations);
+ }
+
+ @Override
+ protected final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+
+ // prepare variables
+ final double[] result = new double[1];
+ final double[] abserr = new double[1];
+ final int[] neval = new int[1];
+ final int[] ier = new int[1];
+
+ // call main subroutine
+ dqags(f, a, b, myTol, myRelTol, result, abserr, neval, ier, myMaxEvals);
+ return new QuadratureResult(result[0], abserr[0], neval[0], ier[0] == 0);
+ }
+
+ @Override
+ public final QuadratureResult integrate(DoubleUnaryOperator f, final double a, final double b) {
+
+ // null integral
+ if (a == b) {
+ return new QuadratureResult(0.0, 0.0, 0, true);
}
- public GaussKronrod(final double tolerance, final int maxEvaluations) {
- this(tolerance, 50.0 * Constants.EPSILON, maxEvaluations);
+ // make sure a < b
+ if (a > b) {
+ return integrate(f, b, a);
}
- @Override
- protected final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
+ // both are finite
+ if (Double.isFinite(a) && Double.isFinite(b)) {
+ return properIntegral(f, a, b);
+ }
- // prepare variables
- final double[] result = new double[1];
- final double[] abserr = new double[1];
- final int[] neval = new int[1];
- final int[] ier = new int[1];
+ // infinite bounds case
+ final double[] result = new double[1], abserr = new double[1];
+ final int[] neval = new int[1], ier = new int[1];
+ final int inf;
+ final double bound;
+ if (Double.isInfinite(a) && Double.isInfinite(b)) {
+ inf = 2;
+ bound = 0.0;
+ } else if (Double.isFinite(a)) {
+ inf = 1;
+ bound = a;
+ } else {
+ inf = -1;
+ bound = b;
+ }
- // call main subroutine
- dqags(f, a, b, myTol, myRelTol, result, abserr, neval, ier, myMaxEvals);
- return new QuadratureResult(result[0], abserr[0], neval[0], ier[0] == 0);
+ // call main subroutine
+ dqagi1(f, bound, inf, myTol, myRelTol, result, abserr, neval, ier, myMaxEvals);
+ return new QuadratureResult(result[0], abserr[0], neval[0], ier[0] == 0);
+ }
+
+ @Override
+ public final String getName() {
+ return "Gauss-Kronrod";
+ }
+
+ // *******************************************************************************
+ // FINITE BOUNDS INTEGRATION (DQAGS)
+ // *******************************************************************************
+ private static final void dqags(final DoubleUnaryOperator f, final double a, final double b,
+ final double epsabs, final double epsrel, final double[] result, final double[] abserr,
+ final int[] neval, final int[] ier, final int limit) {
+ final int[] last = new int[1];
+
+ // CHECK VALIDITY OF LIMIT AND LENW
+ ier[0] = 6;
+ neval[0] = last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ if (limit < 1) {
+ return;
}
- @Override
- public final QuadratureResult integrate(DoubleUnaryOperator f, final double a, final double b) {
-
- // null integral
- if (a == b) {
- return new QuadratureResult(0.0, 0.0, 0, true);
- }
-
- // make sure a < b
- if (a > b) {
- return integrate(f, b, a);
- }
-
- // both are finite
- if (Double.isFinite(a) && Double.isFinite(b)) {
- return properIntegral(f, a, b);
- }
-
- // infinite bounds case
- final double[] result = new double[1], abserr = new double[1];
- final int[] neval = new int[1], ier = new int[1];
- final int inf;
- final double bound;
- if (Double.isInfinite(a) && Double.isInfinite(b)) {
- inf = 2;
- bound = 0.0;
- } else if (Double.isFinite(a)) {
- inf = 1;
- bound = a;
- } else {
- inf = -1;
- bound = b;
- }
-
- // call main subroutine
- dqagi1(f, bound, inf, myTol, myRelTol, result, abserr, neval, ier, myMaxEvals);
- return new QuadratureResult(result[0], abserr[0], neval[0], ier[0] == 0);
+ // PREPARE CALL FOR DQAGSE
+ final double[] alist = new double[limit], blist = new double[limit], rlist = new double[limit],
+ elist = new double[limit];
+ final int[] iwork = new int[limit];
+ dqagse(f, a, b, epsabs, epsrel, limit, result, abserr, neval, ier, alist, blist, rlist, elist,
+ iwork, last);
+ }
+
+ private static final void dqagse(final DoubleUnaryOperator f, final double a, final double b,
+ final double epsabs, final double epsrel, final int limit, final double[] result,
+ final double[] abserr, final int[] neval, final int[] ier, final double[] alist,
+ final double[] blist, final double[] rlist, final double[] elist, final int[] iord,
+ final int[] last) {
+ double area, area12, a1, a2, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast, errbnd,
+ erro12, errsum, ertest = 0.0, oflow, small = 0.0, uflow;
+ int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
+ boolean extrap, noext;
+ final double[] res3la = new double[3];
+ final double[] rlist2 = new double[52];
+ final double[] abseps = new double[1], area1 = new double[1], area2 = new double[1],
+ defabs = new double[1], defab1 = new double[1], defab2 = new double[1],
+ errmax = new double[1], error1 = new double[1], error2 = new double[1],
+ resabs = new double[1], reseps = new double[1];
+ final int[] maxerr = new int[1], nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
+
+ epmach = EPMACH;
+
+ // TEST ON VALIDITY OF PARAMETERS
+ ier[0] = neval[0] = last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ alist[1 - 1] = a;
+ blist[1 - 1] = b;
+ rlist[1 - 1] = elist[1 - 1] = 0.0;
+ if (epsabs <= 0.0 && epsrel < Math.max(50.0 * epmach, 0.5e-28)) {
+ ier[0] = 6;
+ return;
}
- @Override
- public final String getName() {
- return "Gauss-Kronrod";
+ // FIRST APPROXIMATION TO THE INTEGRAL
+ uflow = UFLOW;
+ oflow = OFLOW;
+ ierro = 0;
+ dqk21(f, a, b, result, abserr, defabs, resabs);
+
+ // TEST ON ACCURACY
+ dres = Math.abs(result[0]);
+ errbnd = Math.max(epsabs, epsrel * dres);
+ last[0] = 1;
+ rlist[1 - 1] = result[0];
+ elist[1 - 1] = abserr[0];
+ iord[1 - 1] = 1;
+ if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
+ ier[0] = 2;
+ }
+ if (limit == 1) {
+ ier[0] = 1;
+ }
+ if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || abserr[0] == 0.0) {
+ neval[0] = 42 * last[0] - 21;
+ return;
}
- // *******************************************************************************
- // FINITE BOUNDS INTEGRATION (DQAGS)
- // *******************************************************************************
- private static final void dqags(final DoubleUnaryOperator f, final double a, final double b,
- final double epsabs, final double epsrel, final double[] result, final double[] abserr, final int[] neval,
- final int[] ier, final int limit) {
- final int[] last = new int[1];
-
- // CHECK VALIDITY OF LIMIT AND LENW
- ier[0] = 6;
- neval[0] = last[0] = 0;
- result[0] = abserr[0] = 0.0;
- if (limit < 1) {
- return;
- }
-
- // PREPARE CALL FOR DQAGSE
- final double[] alist = new double[limit], blist = new double[limit], rlist = new double[limit],
- elist = new double[limit];
- final int[] iwork = new int[limit];
- dqagse(f, a, b, epsabs, epsrel, limit, result, abserr, neval, ier, alist, blist, rlist, elist, iwork, last);
+ // INITIALIZATION
+ rlist2[1 - 1] = result[0];
+ errmax[0] = abserr[0];
+ maxerr[0] = 1;
+ area = result[0];
+ errsum = abserr[0];
+ abserr[0] = oflow;
+ nrmax[0] = 1;
+ nres[0] = 0;
+ numrl2[0] = 2;
+ ktmin = 0;
+ extrap = noext = false;
+ iroff1 = iroff2 = iroff3 = 0;
+ ksgn = -1;
+ if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
+ ksgn = 1;
}
- private static final void dqagse(final DoubleUnaryOperator f, final double a, final double b,
- final double epsabs, final double epsrel, final int limit, final double[] result, final double[] abserr,
- final int[] neval, final int[] ier, final double[] alist, final double[] blist, final double[] rlist,
- final double[] elist, final int[] iord, final int[] last) {
- double area, area12, a1, a2, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast, errbnd, erro12, errsum,
- ertest = 0.0, oflow, small = 0.0, uflow;
- int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
- boolean extrap, noext;
- final double[] res3la = new double[3];
- final double[] rlist2 = new double[52];
- final double[] abseps = new double[1], area1 = new double[1], area2 = new double[1], defabs = new double[1],
- defab1 = new double[1], defab2 = new double[1], errmax = new double[1], error1 = new double[1],
- error2 = new double[1], resabs = new double[1], reseps = new double[1];
- final int[] maxerr = new int[1], nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
-
- epmach = EPMACH;
-
- // TEST ON VALIDITY OF PARAMETERS
- ier[0] = neval[0] = last[0] = 0;
- result[0] = abserr[0] = 0.0;
- alist[1 - 1] = a;
- blist[1 - 1] = b;
- rlist[1 - 1] = elist[1 - 1] = 0.0;
- if (epsabs <= 0.0 && epsrel < Math.max(50.0 * epmach, 0.5e-28)) {
- ier[0] = 6;
- return;
- }
-
- // FIRST APPROXIMATION TO THE INTEGRAL
- uflow = UFLOW;
- oflow = OFLOW;
- ierro = 0;
- dqk21(f, a, b, result, abserr, defabs, resabs);
-
- // TEST ON ACCURACY
- dres = Math.abs(result[0]);
- errbnd = Math.max(epsabs, epsrel * dres);
- last[0] = 1;
- rlist[1 - 1] = result[0];
- elist[1 - 1] = abserr[0];
- iord[1 - 1] = 1;
- if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
- ier[0] = 2;
- }
- if (limit == 1) {
- ier[0] = 1;
- }
- if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || abserr[0] == 0.0) {
- neval[0] = 42 * last[0] - 21;
- return;
- }
-
- // INITIALIZATION
- rlist2[1 - 1] = result[0];
- errmax[0] = abserr[0];
- maxerr[0] = 1;
- area = result[0];
- errsum = abserr[0];
- abserr[0] = oflow;
- nrmax[0] = 1;
- nres[0] = 0;
- numrl2[0] = 2;
- ktmin = 0;
- extrap = noext = false;
- iroff1 = iroff2 = iroff3 = 0;
- ksgn = -1;
- if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
- ksgn = 1;
- }
-
- // MAIN DO-LOOP
- for (last[0] = 2; last[0] <= limit; ++last[0]) {
-
- // BISECT THE SUBINTERVAL WITH THE NRMAX-TH LARGEST ERROR ESTIMATE
- a1 = alist[maxerr[0] - 1];
- b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
- a2 = b1;
- b2 = blist[maxerr[0] - 1];
- erlast = errmax[0];
- dqk21(f, a1, b1, area1, error1, resabs, defab1);
- dqk21(f, a2, b2, area2, error2, resabs, defab2);
-
- // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL AND ERROR AND TEST FOR ACCURACY
- area12 = area1[0] + area2[0];
- erro12 = error1[0] + error2[0];
- errsum += erro12 - errmax[0];
- area += area12 - rlist[maxerr[0] - 1];
- if (defab1[0] != error1[0] && defab2[0] != error2[0]) {
- final double reltol = 1e-5 * Math.abs(area12);
- if (Math.abs(rlist[maxerr[0] - 1] - area12) <= reltol && erro12 >= 0.99 * errmax[0]) {
- if (extrap) {
- ++iroff2;
- } else {
- ++iroff1;
- }
- }
- if (last[0] > 10 && erro12 > errmax[0]) {
- ++iroff3;
- }
- }
- rlist[maxerr[0] - 1] = area1[0];
- rlist[last[0] - 1] = area2[0];
- errbnd = Math.max(epsabs, epsrel * Math.abs(area));
-
- // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG
- if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
- ier[0] = 2;
- }
- if (iroff2 >= 5) {
- ierro = 3;
- }
-
- // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF SUBINTERVALS EQUALS LIMIT
- if (last[0] == limit) {
- ier[0] = 1;
- }
-
- // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
- // AT A POINT OF THE INTEGRATION RANGE
- if (Math.max(Math.abs(a1), Math.abs(b2)) <= (1.0 + 100.0 * epmach) * (Math.abs(a2) + 1000.0 * uflow)) {
- ier[0] = 4;
- }
-
- // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST
- if (error2[0] > error1[0]) {
- alist[maxerr[0] - 1] = a2;
- alist[last[0] - 1] = a1;
- blist[last[0] - 1] = b1;
- rlist[maxerr[0] - 1] = area2[0];
- rlist[last[0] - 1] = area1[0];
- elist[maxerr[0] - 1] = error2[0];
- elist[last[0] - 1] = error1[0];
- } else {
- alist[last[0] - 1] = a2;
- blist[maxerr[0] - 1] = b1;
- blist[last[0] - 1] = b2;
- elist[maxerr[0] - 1] = error1[0];
- elist[last[0] - 1] = error2[0];
- }
-
- // CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING
- // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
- // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT)
- dqpsrt(limit, last[0], maxerr, errmax, elist, iord, nrmax);
- if (errsum <= errbnd) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
- if (ier[0] != 0) {
- break;
- }
- if (last[0] == 2) {
- small = Math.abs(b - a) * 0.375;
- erlarg = errsum;
- ertest = errbnd;
- rlist2[2 - 1] = area;
- continue;
- }
- if (noext) {
- continue;
- }
- erlarg -= erlast;
- if (Math.abs(b1 - a1) > small) {
- erlarg += erro12;
- }
- if (!extrap) {
-
- // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE SMALLEST INTERVAL
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- continue;
- }
- extrap = true;
- nrmax[0] = 2;
- }
-
- if (ierro != 3 && erlarg > ertest) {
-
- // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
- // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
- // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION
- id = nrmax[0];
- jupbnd = last[0];
- if (last[0] > 2 + (limit >> 1)) {
- jupbnd = limit + 3 - last[0];
- }
- boolean skipto90 = false;
- for (k = id; k <= jupbnd; ++k) {
- maxerr[0] = iord[nrmax[0] - 1];
- errmax[0] = elist[maxerr[0] - 1];
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- skipto90 = true;
- break;
- }
- ++nrmax[0];
- }
- if (skipto90) {
- continue;
- }
- }
-
- // PERFORM EXTRAPOLATION
- ++numrl2[0];
- rlist2[numrl2[0] - 1] = area;
- dqelg(numrl2, rlist2, reseps, abseps, res3la, nres);
- ++ktmin;
- if (ktmin > 5 && abserr[0] < 1e-3 * errsum) {
- ier[0] = 5;
- }
- if (abseps[0] < abserr[0]) {
- ktmin = 0;
- abserr[0] = abseps[0];
- result[0] = reseps[0];
- correc = erlarg;
- ertest = Math.max(epsabs, epsrel * Math.abs(reseps[0]));
- if (abserr[0] <= ertest) {
- break;
- }
- }
-
- // PREPARE BISECTION OF THE SMALLEST INTERVAL
- if (numrl2[0] == 1) {
- noext = true;
- }
- if (ier[0] == 5) {
- break;
- }
- maxerr[0] = iord[1 - 1];
- errmax[0] = elist[maxerr[0] - 1];
- nrmax[0] = 1;
- extrap = false;
- small *= 0.5;
- erlarg = errsum;
- }
-
- // SET FINAL RESULT AND ERROR ESTIMATE
- if (abserr[0] == oflow) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
-
- if (ier[0] + ierro != 0) {
- if (ierro == 3) {
- abserr[0] += correc;
- }
- if (ier[0] == 0) {
- ier[0] = 3;
- }
- if (result[0] != 0.0 && area != 0.0) {
- if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
- } else {
- if (abserr[0] > errsum) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
- if (area == 0.0) {
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
- }
- }
-
- // TEST ON DIVERGENCE
- if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.01) {
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
- return;
- }
- if (0.01 > (result[0] / area) || (result[0] / area) > 100.0 || errsum > Math.abs(area)) {
- ier[0] = 6;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- neval[0] = 42 * last[0] - 21;
+ // MAIN DO-LOOP
+ for (last[0] = 2; last[0] <= limit; ++last[0]) {
+
+ // BISECT THE SUBINTERVAL WITH THE NRMAX-TH LARGEST ERROR ESTIMATE
+ a1 = alist[maxerr[0] - 1];
+ b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
+ a2 = b1;
+ b2 = blist[maxerr[0] - 1];
+ erlast = errmax[0];
+ dqk21(f, a1, b1, area1, error1, resabs, defab1);
+ dqk21(f, a2, b2, area2, error2, resabs, defab2);
+
+ // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL AND ERROR AND TEST FOR ACCURACY
+ area12 = area1[0] + area2[0];
+ erro12 = error1[0] + error2[0];
+ errsum += erro12 - errmax[0];
+ area += area12 - rlist[maxerr[0] - 1];
+ if (defab1[0] != error1[0] && defab2[0] != error2[0]) {
+ final double reltol = 1e-5 * Math.abs(area12);
+ if (Math.abs(rlist[maxerr[0] - 1] - area12) <= reltol && erro12 >= 0.99 * errmax[0]) {
+ if (extrap) {
+ ++iroff2;
+ } else {
+ ++iroff1;
+ }
+ }
+ if (last[0] > 10 && erro12 > errmax[0]) {
+ ++iroff3;
+ }
+ }
+ rlist[maxerr[0] - 1] = area1[0];
+ rlist[last[0] - 1] = area2[0];
+ errbnd = Math.max(epsabs, epsrel * Math.abs(area));
+
+ // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG
+ if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
+ ier[0] = 2;
+ }
+ if (iroff2 >= 5) {
+ ierro = 3;
+ }
+
+ // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF SUBINTERVALS EQUALS LIMIT
+ if (last[0] == limit) {
+ ier[0] = 1;
+ }
+
+ // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
+ // AT A POINT OF THE INTEGRATION RANGE
+ if (Math.max(Math.abs(a1), Math.abs(b2)) <= (1.0 + 100.0 * epmach)
+ * (Math.abs(a2) + 1000.0 * uflow)) {
+ ier[0] = 4;
+ }
+
+ // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST
+ if (error2[0] > error1[0]) {
+ alist[maxerr[0] - 1] = a2;
+ alist[last[0] - 1] = a1;
+ blist[last[0] - 1] = b1;
+ rlist[maxerr[0] - 1] = area2[0];
+ rlist[last[0] - 1] = area1[0];
+ elist[maxerr[0] - 1] = error2[0];
+ elist[last[0] - 1] = error1[0];
+ } else {
+ alist[last[0] - 1] = a2;
+ blist[maxerr[0] - 1] = b1;
+ blist[last[0] - 1] = b2;
+ elist[maxerr[0] - 1] = error1[0];
+ elist[last[0] - 1] = error2[0];
+ }
+
+ // CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING
+ // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
+ // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT)
+ dqpsrt(limit, last[0], maxerr, errmax, elist, iord, nrmax);
+ if (errsum <= errbnd) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
+ }
+ if (ier[0] != 0) {
+ break;
+ }
+ if (last[0] == 2) {
+ small = Math.abs(b - a) * 0.375;
+ erlarg = errsum;
+ ertest = errbnd;
+ rlist2[2 - 1] = area;
+ continue;
+ }
+ if (noext) {
+ continue;
+ }
+ erlarg -= erlast;
+ if (Math.abs(b1 - a1) > small) {
+ erlarg += erro12;
+ }
+ if (!extrap) {
+
+ // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE SMALLEST INTERVAL
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ continue;
+ }
+ extrap = true;
+ nrmax[0] = 2;
+ }
+
+ if (ierro != 3 && erlarg > ertest) {
+
+ // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
+ // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
+ // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION
+ id = nrmax[0];
+ jupbnd = last[0];
+ if (last[0] > 2 + (limit >> 1)) {
+ jupbnd = limit + 3 - last[0];
+ }
+ boolean skipto90 = false;
+ for (k = id; k <= jupbnd; ++k) {
+ maxerr[0] = iord[nrmax[0] - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ skipto90 = true;
+ break;
+ }
+ ++nrmax[0];
+ }
+ if (skipto90) {
+ continue;
+ }
+ }
+
+ // PERFORM EXTRAPOLATION
+ ++numrl2[0];
+ rlist2[numrl2[0] - 1] = area;
+ dqelg(numrl2, rlist2, reseps, abseps, res3la, nres);
+ ++ktmin;
+ if (ktmin > 5 && abserr[0] < 1e-3 * errsum) {
+ ier[0] = 5;
+ }
+ if (abseps[0] < abserr[0]) {
+ ktmin = 0;
+ abserr[0] = abseps[0];
+ result[0] = reseps[0];
+ correc = erlarg;
+ ertest = Math.max(epsabs, epsrel * Math.abs(reseps[0]));
+ if (abserr[0] <= ertest) {
+ break;
+ }
+ }
+
+ // PREPARE BISECTION OF THE SMALLEST INTERVAL
+ if (numrl2[0] == 1) {
+ noext = true;
+ }
+ if (ier[0] == 5) {
+ break;
+ }
+ maxerr[0] = iord[1 - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ nrmax[0] = 1;
+ extrap = false;
+ small *= 0.5;
+ erlarg = errsum;
}
- private static final void dqelg(final int[] n, final double[] epstab, final double[] result, final double[] abserr,
- final double[] res3la, final int[] nres) {
- double delta1, delta2, delta3, epsinf, error, err1, err2, err3, e0, e1, e1abs, e2, e3, res, ss, tol1, tol2,
- tol3;
- int i, ib, ib2, ie, indx, k1, k2, k3, limexp, newelm, num;
-
- ++nres[0];
- abserr[0] = OFLOW;
- result[0] = epstab[n[0] - 1];
- if (n[0] < 3) {
- abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
- return;
- }
-
- limexp = 50;
- epstab[n[0] + 2 - 1] = epstab[n[0] - 1];
- newelm = (n[0] - 1) >> 1;
- epstab[n[0] - 1] = OFLOW;
- num = k1 = n[0];
- for (i = 1; i <= newelm; ++i) {
- k2 = k1 - 1;
- k3 = k1 - 2;
- res = epstab[k1 + 2 - 1];
- e0 = epstab[k3 - 1];
- e1 = epstab[k2 - 1];
- e2 = res;
- e1abs = Math.abs(e1);
- delta2 = e2 - e1;
- err2 = Math.abs(delta2);
- tol2 = Math.max(Math.abs(e2), e1abs) * EPMACH;
- delta3 = e1 - e0;
- err3 = Math.abs(delta3);
- tol3 = Math.max(e1abs, Math.abs(e0)) * EPMACH;
- if (err2 <= tol2 && err3 <= tol3) {
-
- // if e0, e1 and e2 are equal to within machine accuracy, convergence is
- // assumed.
- result[0] = res;
- abserr[0] = err2 + err3;
- abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
- return;
- }
-
- e3 = epstab[k1 - 1];
- epstab[k1 - 1] = e1;
- delta1 = e1 - e3;
- err1 = Math.abs(delta1);
- tol1 = Math.max(e1abs, Math.abs(e3)) * EPMACH;
-
- // if two elements are very close to each other, omit a part of the table by
- // adjusting the value of n
- if (err1 <= tol1 || err2 <= tol2 || err3 <= tol3) {
- n[0] = i + i - 1;
- break;
- }
- ss = 1.0 / delta1 + 1.0 / delta2 - 1.0 / delta3;
- epsinf = Math.abs(ss * e1);
-
- // test to detect irregular behaviour in the table, and eventually omit a part
- // of the table adjusting the value of n
- if (epsinf <= 0.1E-3) {
- n[0] = i + i - 1;
- break;
- }
-
- // compute a new element and eventually adjust the value of result.
- res = e1 + 1.0 / ss;
- epstab[k1 - 1] = res;
- k1 -= 2;
- error = err2 + Math.abs(res - e2) + err3;
- if (error <= abserr[0]) {
- abserr[0] = error;
- result[0] = res;
- }
- }
-
- // shift the table.
- if (n[0] == limexp) {
- n[0] = ((limexp >> 1) << 1) - 1;
- }
- ib = 1;
- if (((num >> 1) << 1) == num) {
- ib = 2;
- }
- ie = newelm + 1;
- for (i = 1; i <= ie; ++i) {
- ib2 = ib + 2;
- epstab[ib - 1] = epstab[ib2 - 1];
- ib = ib2;
- }
- if (num != n[0]) {
- indx = num - n[0] + 1;
- for (i = 1; i <= n[0]; ++i) {
- epstab[i - 1] = epstab[indx - 1];
- ++indx;
- }
- }
-
- if (nres[0] >= 4) {
-
- // compute error estimate
- abserr[0] = Math.abs(result[0] - res3la[3 - 1]) + Math.abs(result[0] - res3la[2 - 1])
- + Math.abs(result[0] - res3la[1 - 1]);
- res3la[1 - 1] = res3la[2 - 1];
- res3la[2 - 1] = res3la[3 - 1];
- res3la[3 - 1] = result[0];
- } else {
- res3la[nres[0] - 1] = result[0];
- abserr[0] = OFLOW;
- }
- abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
+ // SET FINAL RESULT AND ERROR ESTIMATE
+ if (abserr[0] == oflow) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
}
- private static final void dqpsrt(final int limit, final int last, final int[] maxerr, final double[] ermax,
- final double[] elist, final int[] iord, final int[] nrmax) {
- double errmax, errmin;
- int i, ibeg, ido, isucc, j, jbnd, jupbn, k;
-
- if (last <= 2) {
- iord[1 - 1] = 1;
- iord[2 - 1] = 2;
-
- // set maxerr and ermax.
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
-
- // this part of the routine is only executed if, due to a
- // difficult integrand, subdivision increased the error
- // estimate. in the normal case the insert procedure should
- // start after the nrmax-th largest error estimate.
- errmax = elist[maxerr[0] - 1];
- if (nrmax[0] != 1) {
- ido = nrmax[0] - 1;
- for (i = 1; i <= ido; ++i) {
- isucc = iord[nrmax[0] - 1];
- if (errmax <= elist[isucc - 1]) {
- break;
- }
- iord[nrmax[0] - 1] = isucc;
- --nrmax[0];
- }
- }
-
- // compute the number of elements in the list to be maintained
- // in descending order. this number depends on the number of
- // subdivisions still allowed.
- jupbn = last;
- if (last > ((limit >> 1) + 2)) {
- jupbn = limit + 3 - last;
- }
- errmin = elist[last - 1];
-
- // insert errmax by traversing the list top-down,
- // starting comparison from the element elist(iord(nrmax+1)).
- jbnd = jupbn - 1;
- ibeg = nrmax[0] + 1;
- if (ibeg <= jbnd) {
- for (i = ibeg; i <= jbnd; ++i) {
- isucc = iord[i - 1];
- if (errmax >= elist[isucc - 1]) {
-
- // insert errmin by traversing the list bottom-up.
- iord[i - 1 - 1] = maxerr[0];
- k = jbnd;
- for (j = 1; j <= jbnd; ++j) {
- isucc = iord[k - 1];
- if (errmin < elist[isucc - 1]) {
- iord[k + 1 - 1] = last;
-
- // set maxerr and ermax.
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
- iord[k + 1 - 1] = isucc;
- --k;
- }
- iord[i - 1] = last;
-
- // set maxerr and ermax.
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
- iord[i - 1 - 1] = isucc;
- }
- }
- iord[jbnd - 1] = maxerr[0];
- iord[jupbn - 1] = last;
-
- // set maxerr and ermax.
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
+ if (ier[0] + ierro != 0) {
+ if (ierro == 3) {
+ abserr[0] += correc;
+ }
+ if (ier[0] == 0) {
+ ier[0] = 3;
+ }
+ if (result[0] != 0.0 && area != 0.0) {
+ if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
+ }
+ } else {
+ if (abserr[0] > errsum) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
+ }
+ if (area == 0.0) {
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
+ }
+ }
}
- private static final void dqk21(final DoubleUnaryOperator f, final double a, final double b,
- final double[] result, final double[] abserr, final double[] resabs, final double[] resasc) {
- double absc, centr, dhlgth, fc, fsum, fval1, fval2, hlgth, resg, resk, reskh;
- int j, jtw, jtwm1;
- final double[] fv1 = new double[10];
- final double[] fv2 = new double[10];
+ // TEST ON DIVERGENCE
+ if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.01) {
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ return;
+ }
+ if (0.01 > (result[0] / area) || (result[0] / area) > 100.0 || errsum > Math.abs(area)) {
+ ier[0] = 6;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ neval[0] = 42 * last[0] - 21;
+ }
+
+ private static final void dqelg(final int[] n, final double[] epstab, final double[] result,
+ final double[] abserr, final double[] res3la, final int[] nres) {
+ double delta1, delta2, delta3, epsinf, error, err1, err2, err3, e0, e1, e1abs, e2, e3, res, ss,
+ tol1, tol2, tol3;
+ int i, ib, ib2, ie, indx, k1, k2, k3, limexp, newelm, num;
+
+ ++nres[0];
+ abserr[0] = OFLOW;
+ result[0] = epstab[n[0] - 1];
+ if (n[0] < 3) {
+ abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
+ return;
+ }
- centr = 0.5 * (a + b);
- hlgth = 0.5 * (b - a);
- dhlgth = Math.abs(hlgth);
+ limexp = 50;
+ epstab[n[0] + 2 - 1] = epstab[n[0] - 1];
+ newelm = (n[0] - 1) >> 1;
+ epstab[n[0] - 1] = OFLOW;
+ num = k1 = n[0];
+ for (i = 1; i <= newelm; ++i) {
+ k2 = k1 - 1;
+ k3 = k1 - 2;
+ res = epstab[k1 + 2 - 1];
+ e0 = epstab[k3 - 1];
+ e1 = epstab[k2 - 1];
+ e2 = res;
+ e1abs = Math.abs(e1);
+ delta2 = e2 - e1;
+ err2 = Math.abs(delta2);
+ tol2 = Math.max(Math.abs(e2), e1abs) * EPMACH;
+ delta3 = e1 - e0;
+ err3 = Math.abs(delta3);
+ tol3 = Math.max(e1abs, Math.abs(e0)) * EPMACH;
+ if (err2 <= tol2 && err3 <= tol3) {
+
+ // if e0, e1 and e2 are equal to within machine accuracy, convergence is
+ // assumed.
+ result[0] = res;
+ abserr[0] = err2 + err3;
+ abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
+ return;
+ }
+
+ e3 = epstab[k1 - 1];
+ epstab[k1 - 1] = e1;
+ delta1 = e1 - e3;
+ err1 = Math.abs(delta1);
+ tol1 = Math.max(e1abs, Math.abs(e3)) * EPMACH;
+
+ // if two elements are very close to each other, omit a part of the table by
+ // adjusting the value of n
+ if (err1 <= tol1 || err2 <= tol2 || err3 <= tol3) {
+ n[0] = i + i - 1;
+ break;
+ }
+ ss = 1.0 / delta1 + 1.0 / delta2 - 1.0 / delta3;
+ epsinf = Math.abs(ss * e1);
+
+ // test to detect irregular behaviour in the table, and eventually omit a part
+ // of the table adjusting the value of n
+ if (epsinf <= 0.1E-3) {
+ n[0] = i + i - 1;
+ break;
+ }
+
+ // compute a new element and eventually adjust the value of result.
+ res = e1 + 1.0 / ss;
+ epstab[k1 - 1] = res;
+ k1 -= 2;
+ error = err2 + Math.abs(res - e2) + err3;
+ if (error <= abserr[0]) {
+ abserr[0] = error;
+ result[0] = res;
+ }
+ }
- // compute the 21-point kronrod approximation to the integral, and estimate the
- // absolute error.
- resg = 0.0;
- fc = f.applyAsDouble(centr);
- resk = WGK21[11 - 1] * fc;
- resabs[0] = Math.abs(resk);
- for (j = 1; j <= 5; ++j) {
- jtw = j << 1;
- absc = hlgth * XGK21[jtw - 1];
- fval1 = f.applyAsDouble(centr - absc);
- fval2 = f.applyAsDouble(centr + absc);
- fv1[jtw - 1] = fval1;
- fv2[jtw - 1] = fval2;
- fsum = fval1 + fval2;
- resg += WG21[j - 1] * fsum;
- resk += WGK21[jtw - 1] * fsum;
- resabs[0] += WGK21[jtw - 1] * (Math.abs(fval1) + Math.abs(fval2));
- }
- for (j = 1; j <= 5; ++j) {
- jtwm1 = (j << 1) - 1;
- absc = hlgth * XGK21[jtwm1 - 1];
- fval1 = f.applyAsDouble(centr - absc);
- fval2 = f.applyAsDouble(centr + absc);
- fv1[jtwm1 - 1] = fval1;
- fv2[jtwm1 - 1] = fval2;
- fsum = fval1 + fval2;
- resk += WGK21[jtwm1 - 1] * fsum;
- resabs[0] += WGK21[jtwm1 - 1] * (Math.abs(fval1) + Math.abs(fval2));
- }
- reskh = resk * 0.5;
- resasc[0] = WGK21[11 - 1] * Math.abs(fc - reskh);
- for (j = 1; j <= 10; ++j) {
- resasc[0] += WGK21[j - 1] * (Math.abs(fv1[j - 1] - reskh) + Math.abs(fv2[j - 1] - reskh));
- }
- result[0] = resk * hlgth;
- resabs[0] *= dhlgth;
- resasc[0] *= dhlgth;
- abserr[0] = Math.abs((resk - resg) * hlgth);
- if (resasc[0] != 0.0 && abserr[0] != 0.0) {
- abserr[0] = resasc[0] * Math.min(10.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
- }
- if (resabs[0] > UFLOW / (50.0 * EPMACH)) {
- abserr[0] = Math.max((EPMACH * 50.0) * resabs[0], abserr[0]);
- }
+ // shift the table.
+ if (n[0] == limexp) {
+ n[0] = ((limexp >> 1) << 1) - 1;
+ }
+ ib = 1;
+ if (((num >> 1) << 1) == num) {
+ ib = 2;
+ }
+ ie = newelm + 1;
+ for (i = 1; i <= ie; ++i) {
+ ib2 = ib + 2;
+ epstab[ib - 1] = epstab[ib2 - 1];
+ ib = ib2;
+ }
+ if (num != n[0]) {
+ indx = num - n[0] + 1;
+ for (i = 1; i <= n[0]; ++i) {
+ epstab[i - 1] = epstab[indx - 1];
+ ++indx;
+ }
}
- // *******************************************************************************
- // INFINITE BOUNDS INTEGRATION (DQAGI)
- // *******************************************************************************
- private static void dqk15i(final DoubleUnaryOperator f, final double boun, final int inf,
- final double a, final double b, final double[] result, final double[] abserr, final double[] resabs,
- final double[] resasc) {
-
- double absc, absc1, absc2, centr, dinf, epmach, fc, fsum, fval1, fval2, hlgth, resg, resk, reskh, tabsc1,
- tabsc2, uflow;
- int j;
- final double[] fv1 = new double[8], fv2 = new double[8];
-
- epmach = EPMACH;
- uflow = UFLOW;
- dinf = Math.min(1.0, inf);
- centr = 0.5 * (a + b);
- hlgth = 0.5 * (b - a);
- tabsc1 = boun + dinf * (1.0 - centr) / centr;
+ if (nres[0] >= 4) {
+
+ // compute error estimate
+ abserr[0] = Math.abs(result[0] - res3la[3 - 1]) + Math.abs(result[0] - res3la[2 - 1])
+ + Math.abs(result[0] - res3la[1 - 1]);
+ res3la[1 - 1] = res3la[2 - 1];
+ res3la[2 - 1] = res3la[3 - 1];
+ res3la[3 - 1] = result[0];
+ } else {
+ res3la[nres[0] - 1] = result[0];
+ abserr[0] = OFLOW;
+ }
+ abserr[0] = Math.max(abserr[0], 5.0 * EPMACH * Math.abs(result[0]));
+ }
+
+ private static final void dqpsrt(final int limit, final int last, final int[] maxerr,
+ final double[] ermax, final double[] elist, final int[] iord, final int[] nrmax) {
+ double errmax, errmin;
+ int i, ibeg, ido, isucc, j, jbnd, jupbn, k;
+
+ if (last <= 2) {
+ iord[1 - 1] = 1;
+ iord[2 - 1] = 2;
+
+ // set maxerr and ermax.
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
+ }
+
+ // this part of the routine is only executed if, due to a
+ // difficult integrand, subdivision increased the error
+ // estimate. in the normal case the insert procedure should
+ // start after the nrmax-th largest error estimate.
+ errmax = elist[maxerr[0] - 1];
+ if (nrmax[0] != 1) {
+ ido = nrmax[0] - 1;
+ for (i = 1; i <= ido; ++i) {
+ isucc = iord[nrmax[0] - 1];
+ if (errmax <= elist[isucc - 1]) {
+ break;
+ }
+ iord[nrmax[0] - 1] = isucc;
+ --nrmax[0];
+ }
+ }
+
+ // compute the number of elements in the list to be maintained
+ // in descending order. this number depends on the number of
+ // subdivisions still allowed.
+ jupbn = last;
+ if (last > ((limit >> 1) + 2)) {
+ jupbn = limit + 3 - last;
+ }
+ errmin = elist[last - 1];
+
+ // insert errmax by traversing the list top-down,
+ // starting comparison from the element elist(iord(nrmax+1)).
+ jbnd = jupbn - 1;
+ ibeg = nrmax[0] + 1;
+ if (ibeg <= jbnd) {
+ for (i = ibeg; i <= jbnd; ++i) {
+ isucc = iord[i - 1];
+ if (errmax >= elist[isucc - 1]) {
+
+ // insert errmin by traversing the list bottom-up.
+ iord[i - 1 - 1] = maxerr[0];
+ k = jbnd;
+ for (j = 1; j <= jbnd; ++j) {
+ isucc = iord[k - 1];
+ if (errmin < elist[isucc - 1]) {
+ iord[k + 1 - 1] = last;
+
+ // set maxerr and ermax.
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
+ }
+ iord[k + 1 - 1] = isucc;
+ --k;
+ }
+ iord[i - 1] = last;
+
+ // set maxerr and ermax.
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
+ }
+ iord[i - 1 - 1] = isucc;
+ }
+ }
+ iord[jbnd - 1] = maxerr[0];
+ iord[jupbn - 1] = last;
+
+ // set maxerr and ermax.
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ }
+
+ private static final void dqk21(final DoubleUnaryOperator f, final double a, final double b,
+ final double[] result, final double[] abserr, final double[] resabs, final double[] resasc) {
+ double absc, centr, dhlgth, fc, fsum, fval1, fval2, hlgth, resg, resk, reskh;
+ int j, jtw, jtwm1;
+ final double[] fv1 = new double[10];
+ final double[] fv2 = new double[10];
+
+ centr = 0.5 * (a + b);
+ hlgth = 0.5 * (b - a);
+ dhlgth = Math.abs(hlgth);
+
+ // compute the 21-point kronrod approximation to the integral, and estimate the
+ // absolute error.
+ resg = 0.0;
+ fc = f.applyAsDouble(centr);
+ resk = WGK21[11 - 1] * fc;
+ resabs[0] = Math.abs(resk);
+ for (j = 1; j <= 5; ++j) {
+ jtw = j << 1;
+ absc = hlgth * XGK21[jtw - 1];
+ fval1 = f.applyAsDouble(centr - absc);
+ fval2 = f.applyAsDouble(centr + absc);
+ fv1[jtw - 1] = fval1;
+ fv2[jtw - 1] = fval2;
+ fsum = fval1 + fval2;
+ resg += WG21[j - 1] * fsum;
+ resk += WGK21[jtw - 1] * fsum;
+ resabs[0] += WGK21[jtw - 1] * (Math.abs(fval1) + Math.abs(fval2));
+ }
+ for (j = 1; j <= 5; ++j) {
+ jtwm1 = (j << 1) - 1;
+ absc = hlgth * XGK21[jtwm1 - 1];
+ fval1 = f.applyAsDouble(centr - absc);
+ fval2 = f.applyAsDouble(centr + absc);
+ fv1[jtwm1 - 1] = fval1;
+ fv2[jtwm1 - 1] = fval2;
+ fsum = fval1 + fval2;
+ resk += WGK21[jtwm1 - 1] * fsum;
+ resabs[0] += WGK21[jtwm1 - 1] * (Math.abs(fval1) + Math.abs(fval2));
+ }
+ reskh = resk * 0.5;
+ resasc[0] = WGK21[11 - 1] * Math.abs(fc - reskh);
+ for (j = 1; j <= 10; ++j) {
+ resasc[0] += WGK21[j - 1] * (Math.abs(fv1[j - 1] - reskh) + Math.abs(fv2[j - 1] - reskh));
+ }
+ result[0] = resk * hlgth;
+ resabs[0] *= dhlgth;
+ resasc[0] *= dhlgth;
+ abserr[0] = Math.abs((resk - resg) * hlgth);
+ if (resasc[0] != 0.0 && abserr[0] != 0.0) {
+ abserr[0] = resasc[0] * Math.min(10.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
+ }
+ if (resabs[0] > UFLOW / (50.0 * EPMACH)) {
+ abserr[0] = Math.max((EPMACH * 50.0) * resabs[0], abserr[0]);
+ }
+ }
+
+ // *******************************************************************************
+ // INFINITE BOUNDS INTEGRATION (DQAGI)
+ // *******************************************************************************
+ private static void dqk15i(final DoubleUnaryOperator f, final double boun, final int inf,
+ final double a, final double b, final double[] result, final double[] abserr,
+ final double[] resabs, final double[] resasc) {
+
+ double absc, absc1, absc2, centr, dinf, epmach, fc, fsum, fval1, fval2, hlgth, resg, resk,
+ reskh, tabsc1, tabsc2, uflow;
+ int j;
+ final double[] fv1 = new double[8], fv2 = new double[8];
+
+ epmach = EPMACH;
+ uflow = UFLOW;
+ dinf = Math.min(1.0, inf);
+ centr = 0.5 * (a + b);
+ hlgth = 0.5 * (b - a);
+ tabsc1 = boun + dinf * (1.0 - centr) / centr;
fval1 = f.applyAsDouble(tabsc1);
- if (inf == 2) {
+ if (inf == 2) {
fval1 += f.applyAsDouble(-tabsc1);
- }
- fc = (fval1 / centr) / centr;
-
- // COMPUTE THE 15-POINT KRONROD APPROXIMATION TO THE INTEGRAL, AND ESTIMATE THE
- // ERROR
- resg = WG15I[8 - 1] * fc;
- resk = WGK15I[8 - 1] * fc;
- resabs[0] = Math.abs(resk);
- for (j = 1; j <= 7; ++j) {
- absc = hlgth * XGK15I[j - 1];
- absc1 = centr - absc;
- absc2 = centr + absc;
- tabsc1 = boun + dinf * (1.0 - absc1) / absc1;
- tabsc2 = boun + dinf * (1.0 - absc2) / absc2;
- fval1 = f.applyAsDouble(tabsc1);
- fval2 = f.applyAsDouble(tabsc2);
- if (inf == 2) {
- fval1 += f.applyAsDouble(-tabsc1);
- fval2 += f.applyAsDouble(-tabsc2);
- }
- fval1 = (fval1 / absc1) / absc1;
- fval2 = (fval2 / absc2) / absc2;
- fv1[j - 1] = fval1;
- fv2[j - 1] = fval2;
- fsum = fval1 + fval2;
- resg += WG15I[j - 1] * fsum;
- resk += WGK15I[j - 1] * fsum;
- resabs[0] += WGK15I[j - 1] * (Math.abs(fval1) + Math.abs(fval2));
- }
-
- reskh = resk * 0.5;
- resasc[0] = WGK15I[8 - 1] * Math.abs(fc - reskh);
- for (j = 1; j <= 7; ++j) {
- resasc[0] += WGK15I[j - 1] * (Math.abs(fv1[j - 1] - reskh) + Math.abs(fv2[j - 1] - reskh));
- }
- result[0] = resk * hlgth;
- resasc[0] *= hlgth;
- resabs[0] *= hlgth;
- abserr[0] = Math.abs((resk - resg) * hlgth);
- if (resasc[0] != 0.0 && abserr[0] != 0.0) {
- abserr[0] = resasc[0] * Math.min(1.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
- }
- if (resabs[0] > uflow / (50.0 * epmach)) {
- abserr[0] = Math.max((epmach * 50.0) * resabs[0], abserr[0]);
- }
+ }
+ fc = (fval1 / centr) / centr;
+
+ // COMPUTE THE 15-POINT KRONROD APPROXIMATION TO THE INTEGRAL, AND ESTIMATE THE
+ // ERROR
+ resg = WG15I[8 - 1] * fc;
+ resk = WGK15I[8 - 1] * fc;
+ resabs[0] = Math.abs(resk);
+ for (j = 1; j <= 7; ++j) {
+ absc = hlgth * XGK15I[j - 1];
+ absc1 = centr - absc;
+ absc2 = centr + absc;
+ tabsc1 = boun + dinf * (1.0 - absc1) / absc1;
+ tabsc2 = boun + dinf * (1.0 - absc2) / absc2;
+ fval1 = f.applyAsDouble(tabsc1);
+ fval2 = f.applyAsDouble(tabsc2);
+ if (inf == 2) {
+ fval1 += f.applyAsDouble(-tabsc1);
+ fval2 += f.applyAsDouble(-tabsc2);
+ }
+ fval1 = (fval1 / absc1) / absc1;
+ fval2 = (fval2 / absc2) / absc2;
+ fv1[j - 1] = fval1;
+ fv2[j - 1] = fval2;
+ fsum = fval1 + fval2;
+ resg += WG15I[j - 1] * fsum;
+ resk += WGK15I[j - 1] * fsum;
+ resabs[0] += WGK15I[j - 1] * (Math.abs(fval1) + Math.abs(fval2));
+ }
+
+ reskh = resk * 0.5;
+ resasc[0] = WGK15I[8 - 1] * Math.abs(fc - reskh);
+ for (j = 1; j <= 7; ++j) {
+ resasc[0] += WGK15I[j - 1] * (Math.abs(fv1[j - 1] - reskh) + Math.abs(fv2[j - 1] - reskh));
+ }
+ result[0] = resk * hlgth;
+ resasc[0] *= hlgth;
+ resabs[0] *= hlgth;
+ abserr[0] = Math.abs((resk - resg) * hlgth);
+ if (resasc[0] != 0.0 && abserr[0] != 0.0) {
+ abserr[0] = resasc[0] * Math.min(1.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
+ }
+ if (resabs[0] > uflow / (50.0 * epmach)) {
+ abserr[0] = Math.max((epmach * 50.0) * resabs[0], abserr[0]);
+ }
+ }
+
+ private static void dqagie(final DoubleUnaryOperator f, final double bound, final int inf,
+ final double epsabs, final double epsrel, final int limit, final double[] result,
+ final double[] abserr, final int[] neval, final int[] ier, final double[] alist,
+ final double[] blist, final double[] rlist, final double[] elist, final int[] iord,
+ final int[] last) {
+
+ double area, area12, a1, a2, boun, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast,
+ errbnd, erro12, errsum, ertest = 0.0, oflow, small = 0.0, uflow;
+ final double[] res3la = new double[4], rlist2 = new double[53], defabs = new double[1],
+ resabs = new double[1], reseps = new double[1], area1 = new double[1],
+ area2 = new double[1], defab1 = new double[1], defab2 = new double[1],
+ error1 = new double[1], error2 = new double[1], errmax = new double[1],
+ abseps = new double[1];
+ int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
+ final int[] maxerr = new int[1], nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
+ boolean extrap, noext;
+
+ epmach = EPMACH;
+
+ // TEST ON VALIDITY OF PARAMETERS
+ ier[0] = neval[0] = last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ alist[1 - 1] = 0.0;
+ blist[1 - 1] = 1.0;
+ rlist[1 - 1] = elist[1 - 1] = 0.0;
+ iord[1 - 1] = 0;
+ if (epsabs <= 0.0 && epsrel < Math.max(50.0 * epmach, 0.5e-28)) {
+ ier[0] = 6;
+ }
+ if (ier[0] == 6) {
+ return;
+ }
+
+ // FIRST APPROXIMATION TO THE INTEGRAL
+ // -----------------------------------
+ //
+ // DETERMINE THE INTERVAL TO BE MAPPED ONTO (0,1).
+ // IF INF = 2 THE INTEGRAL IS COMPUTED AS I = I1+I2, WHERE
+ // I1 = INTEGRAL OF F OVER (-INFINITY,0),
+ // I2 = INTEGRAL OF F OVER (0,+INFINITY).
+ boun = bound;
+ if (inf == 2) {
+ boun = 0.0;
+ }
+ dqk15i(f, boun, inf, 0.0, 1.0, result, abserr, defabs, resabs);
+
+ // TEST ON ACCURACY
+ last[0] = 1;
+ rlist[1 - 1] = result[0];
+ elist[1 - 1] = abserr[0];
+ iord[1 - 1] = 1;
+ dres = Math.abs(result[0]);
+ errbnd = Math.max(epsabs, epsrel * dres);
+ if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
+ ier[0] = 2;
+ }
+ if (limit == 1) {
+ ier[0] = 1;
+ }
+ if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || abserr[0] == 0.0) {
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+
+ // INITIALIZATION
+ uflow = UFLOW;
+ oflow = OFLOW;
+ rlist2[1 - 1] = result[0];
+ errmax[0] = abserr[0];
+ maxerr[0] = 1;
+ area = result[0];
+ errsum = abserr[0];
+ abserr[0] = oflow;
+ nrmax[0] = 1;
+ nres[0] = ktmin = 0;
+ numrl2[0] = 2;
+ extrap = noext = false;
+ ierro = iroff1 = iroff2 = iroff3 = 0;
+ ksgn = -1;
+ if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
+ ksgn = 1;
+ }
+
+ // MAIN DO-LOOP
+ for (last[0] = 2; last[0] <= limit; ++last[0]) {
+
+ // BISECT THE SUBINTERVAL WITH NRMAX-TH LARGEST ERROR ESTIMATE
+ a1 = alist[maxerr[0] - 1];
+ b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
+ a2 = b1;
+ b2 = blist[maxerr[0] - 1];
+ erlast = errmax[0];
+ dqk15i(f, boun, inf, a1, b1, area1, error1, resabs, defab1);
+ dqk15i(f, boun, inf, a2, b2, area2, error2, resabs, defab2);
+
+ // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL
+ // AND ERROR AND TEST FOR ACCURACY
+ area12 = area1[0] + area2[0];
+ erro12 = error1[0] + error2[0];
+ errsum += (erro12 - errmax[0]);
+ area += (area12 - rlist[maxerr[0] - 1]);
+ if (defab1[0] != error1[0] && defab2[0] != error2[0]) {
+ final double reltol = 1e-5 * Math.abs(area12);
+ if (Math.abs(rlist[maxerr[0] - 1] - area12) <= reltol && erro12 >= 0.99 * errmax[0]) {
+ if (extrap) {
+ ++iroff2;
+ } else {
+ ++iroff1;
+ }
+ }
+ if (last[0] > 10 && erro12 > errmax[0]) {
+ ++iroff3;
+ }
+ }
+ rlist[maxerr[0] - 1] = area1[0];
+ rlist[last[0] - 1] = area2[0];
+ errbnd = Math.max(epsabs, epsrel * Math.abs(area));
+
+ // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG
+ if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
+ ier[0] = 2;
+ }
+ if (iroff2 >= 5) {
+ ierro = 3;
+ }
+
+ // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF
+ // SUBINTERVALS EQUALS LIMIT
+ if (last[0] == limit) {
+ ier[0] = 1;
+ }
+
+ // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
+ // AT SOME POINTS OF THE INTEGRATION RANGE
+ if (Math.max(Math.abs(a1), Math.abs(b2)) <= (1.0 + 100.0 * epmach)
+ * (Math.abs(a2) + 1.0e3 * uflow)) {
+ ier[0] = 4;
+ }
+
+ // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST
+ if (error2[0] > error1[0]) {
+ alist[maxerr[0] - 1] = a2;
+ alist[last[0] - 1] = a1;
+ blist[last[0] - 1] = b1;
+ rlist[maxerr[0] - 1] = area2[0];
+ rlist[last[0] - 1] = area1[0];
+ elist[maxerr[0] - 1] = error2[0];
+ elist[last[0] - 1] = error1[0];
+ } else {
+ alist[last[0] - 1] = a2;
+ blist[maxerr[0] - 1] = b1;
+ blist[last[0] - 1] = b2;
+ elist[maxerr[0] - 1] = error1[0];
+ elist[last[0] - 1] = error2[0];
+ }
+
+ // CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING
+ // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
+ // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT)
+ dqpsrt(limit, last[0], maxerr, errmax, elist, iord, nrmax);
+ if (errsum <= errbnd) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ if (ier[0] != 0) {
+ break;
+ }
+ if (last[0] == 2) {
+ small = 0.375;
+ erlarg = errsum;
+ ertest = errbnd;
+ rlist2[2 - 1] = area;
+ continue;
+ }
+ if (noext) {
+ continue;
+ }
+ erlarg -= erlast;
+ if (Math.abs(b1 - a1) > small) {
+ erlarg += erro12;
+ }
+ if (!extrap) {
+
+ // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE
+ // SMALLEST INTERVAL
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ continue;
+ }
+ extrap = true;
+ nrmax[0] = 2;
+ }
+
+ if (ierro != 3 && erlarg > ertest) {
+
+ // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
+ // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
+ // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION
+ id = nrmax[0];
+ jupbnd = last[0];
+ if (last[0] > 2 + (limit >> 1)) {
+ jupbnd = limit + 3 - last[0];
+ }
+ boolean skipto90 = false;
+ for (k = id; k <= jupbnd; ++k) {
+ maxerr[0] = iord[nrmax[0] - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ skipto90 = true;
+ break;
+ }
+ ++nrmax[0];
+ }
+ if (skipto90) {
+ continue;
+ }
+ }
+
+ // PERFORM EXTRAPOLATION
+ ++numrl2[0];
+ rlist2[numrl2[0] - 1] = area;
+ dqelg(numrl2, rlist2, reseps, abseps, res3la, nres);
+ ++ktmin;
+ if (ktmin > 5 && abserr[0] < 1.0e-3 * errsum) {
+ ier[0] = 5;
+ }
+ if (abseps[0] < abserr[0]) {
+ ktmin = 0;
+ abserr[0] = abseps[0];
+ result[0] = reseps[0];
+ correc = erlarg;
+ ertest = Math.max(epsabs, epsrel * Math.abs(reseps[0]));
+ if (abserr[0] <= ertest) {
+ break;
+ }
+ }
+
+ // PREPARE BISECTION OF THE SMALLEST INTERVAL
+ if (numrl2[0] == 1) {
+ noext = true;
+ }
+ if (ier[0] == 5) {
+ break;
+ }
+ maxerr[0] = iord[1 - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ nrmax[0] = 1;
+ extrap = false;
+ small *= 0.5;
+ erlarg = errsum;
}
- private static void dqagie(final DoubleUnaryOperator f, final double bound, final int inf,
- final double epsabs, final double epsrel, final int limit, final double[] result, final double[] abserr,
- final int[] neval, final int[] ier, final double[] alist, final double[] blist, final double[] rlist,
- final double[] elist, final int[] iord, final int[] last) {
-
- double area, area12, a1, a2, boun, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast, errbnd, erro12,
- errsum, ertest = 0.0, oflow, small = 0.0, uflow;
- final double[] res3la = new double[4], rlist2 = new double[53], defabs = new double[1], resabs = new double[1],
- reseps = new double[1], area1 = new double[1], area2 = new double[1], defab1 = new double[1],
- defab2 = new double[1], error1 = new double[1], error2 = new double[1], errmax = new double[1],
- abseps = new double[1];
- int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
- final int[] maxerr = new int[1], nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
- boolean extrap, noext;
-
- epmach = EPMACH;
-
- // TEST ON VALIDITY OF PARAMETERS
- ier[0] = neval[0] = last[0] = 0;
- result[0] = abserr[0] = 0.0;
- alist[1 - 1] = 0.0;
- blist[1 - 1] = 1.0;
- rlist[1 - 1] = elist[1 - 1] = 0.0;
- iord[1 - 1] = 0;
- if (epsabs <= 0.0 && epsrel < Math.max(50.0 * epmach, 0.5e-28)) {
- ier[0] = 6;
- }
- if (ier[0] == 6) {
- return;
- }
-
- // FIRST APPROXIMATION TO THE INTEGRAL
- // -----------------------------------
- //
- // DETERMINE THE INTERVAL TO BE MAPPED ONTO (0,1).
- // IF INF = 2 THE INTEGRAL IS COMPUTED AS I = I1+I2, WHERE
- // I1 = INTEGRAL OF F OVER (-INFINITY,0),
- // I2 = INTEGRAL OF F OVER (0,+INFINITY).
- boun = bound;
- if (inf == 2) {
- boun = 0.0;
- }
- dqk15i(f, boun, inf, 0.0, 1.0, result, abserr, defabs, resabs);
-
- // TEST ON ACCURACY
- last[0] = 1;
- rlist[1 - 1] = result[0];
- elist[1 - 1] = abserr[0];
- iord[1 - 1] = 1;
- dres = Math.abs(result[0]);
- errbnd = Math.max(epsabs, epsrel * dres);
- if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
- ier[0] = 2;
- }
- if (limit == 1) {
- ier[0] = 1;
- }
- if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || abserr[0] == 0.0) {
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
-
- // INITIALIZATION
- uflow = UFLOW;
- oflow = OFLOW;
- rlist2[1 - 1] = result[0];
- errmax[0] = abserr[0];
- maxerr[0] = 1;
- area = result[0];
- errsum = abserr[0];
- abserr[0] = oflow;
- nrmax[0] = 1;
- nres[0] = ktmin = 0;
- numrl2[0] = 2;
- extrap = noext = false;
- ierro = iroff1 = iroff2 = iroff3 = 0;
- ksgn = -1;
- if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
- ksgn = 1;
- }
-
- // MAIN DO-LOOP
- for (last[0] = 2; last[0] <= limit; ++last[0]) {
-
- // BISECT THE SUBINTERVAL WITH NRMAX-TH LARGEST ERROR ESTIMATE
- a1 = alist[maxerr[0] - 1];
- b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
- a2 = b1;
- b2 = blist[maxerr[0] - 1];
- erlast = errmax[0];
- dqk15i(f, boun, inf, a1, b1, area1, error1, resabs, defab1);
- dqk15i(f, boun, inf, a2, b2, area2, error2, resabs, defab2);
-
- // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL
- // AND ERROR AND TEST FOR ACCURACY
- area12 = area1[0] + area2[0];
- erro12 = error1[0] + error2[0];
- errsum += (erro12 - errmax[0]);
- area += (area12 - rlist[maxerr[0] - 1]);
- if (defab1[0] != error1[0] && defab2[0] != error2[0]) {
- final double reltol = 1e-5 * Math.abs(area12);
- if (Math.abs(rlist[maxerr[0] - 1] - area12) <= reltol && erro12 >= 0.99 * errmax[0]) {
- if (extrap) {
- ++iroff2;
- } else {
- ++iroff1;
- }
- }
- if (last[0] > 10 && erro12 > errmax[0]) {
- ++iroff3;
- }
- }
- rlist[maxerr[0] - 1] = area1[0];
- rlist[last[0] - 1] = area2[0];
- errbnd = Math.max(epsabs, epsrel * Math.abs(area));
-
- // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG
- if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
- ier[0] = 2;
- }
- if (iroff2 >= 5) {
- ierro = 3;
- }
-
- // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF
- // SUBINTERVALS EQUALS LIMIT
- if (last[0] == limit) {
- ier[0] = 1;
- }
-
- // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
- // AT SOME POINTS OF THE INTEGRATION RANGE
- if (Math.max(Math.abs(a1), Math.abs(b2)) <= (1.0 + 100.0 * epmach) * (Math.abs(a2) + 1.0e3 * uflow)) {
- ier[0] = 4;
- }
-
- // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST
- if (error2[0] > error1[0]) {
- alist[maxerr[0] - 1] = a2;
- alist[last[0] - 1] = a1;
- blist[last[0] - 1] = b1;
- rlist[maxerr[0] - 1] = area2[0];
- rlist[last[0] - 1] = area1[0];
- elist[maxerr[0] - 1] = error2[0];
- elist[last[0] - 1] = error1[0];
- } else {
- alist[last[0] - 1] = a2;
- blist[maxerr[0] - 1] = b1;
- blist[last[0] - 1] = b2;
- elist[maxerr[0] - 1] = error1[0];
- elist[last[0] - 1] = error2[0];
- }
-
- // CALL SUBROUTINE DQPSRT TO MAINTAIN THE DESCENDING ORDERING
- // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
- // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT)
- dqpsrt(limit, last[0], maxerr, errmax, elist, iord, nrmax);
- if (errsum <= errbnd) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- if (ier[0] != 0) {
- break;
- }
- if (last[0] == 2) {
- small = 0.375;
- erlarg = errsum;
- ertest = errbnd;
- rlist2[2 - 1] = area;
- continue;
- }
- if (noext) {
- continue;
- }
- erlarg -= erlast;
- if (Math.abs(b1 - a1) > small) {
- erlarg += erro12;
- }
- if (!extrap) {
-
- // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT IS THE
- // SMALLEST INTERVAL
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- continue;
- }
- extrap = true;
- nrmax[0] = 2;
- }
-
- if (ierro != 3 && erlarg > ertest) {
-
- // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
- // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
- // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION
- id = nrmax[0];
- jupbnd = last[0];
- if (last[0] > 2 + (limit >> 1)) {
- jupbnd = limit + 3 - last[0];
- }
- boolean skipto90 = false;
- for (k = id; k <= jupbnd; ++k) {
- maxerr[0] = iord[nrmax[0] - 1];
- errmax[0] = elist[maxerr[0] - 1];
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- skipto90 = true;
- break;
- }
- ++nrmax[0];
- }
- if (skipto90) {
- continue;
- }
- }
-
- // PERFORM EXTRAPOLATION
- ++numrl2[0];
- rlist2[numrl2[0] - 1] = area;
- dqelg(numrl2, rlist2, reseps, abseps, res3la, nres);
- ++ktmin;
- if (ktmin > 5 && abserr[0] < 1.0e-3 * errsum) {
- ier[0] = 5;
- }
- if (abseps[0] < abserr[0]) {
- ktmin = 0;
- abserr[0] = abseps[0];
- result[0] = reseps[0];
- correc = erlarg;
- ertest = Math.max(epsabs, epsrel * Math.abs(reseps[0]));
- if (abserr[0] <= ertest) {
- break;
- }
- }
-
- // PREPARE BISECTION OF THE SMALLEST INTERVAL
- if (numrl2[0] == 1) {
- noext = true;
- }
- if (ier[0] == 5) {
- break;
- }
- maxerr[0] = iord[1 - 1];
- errmax[0] = elist[maxerr[0] - 1];
- nrmax[0] = 1;
- extrap = false;
- small *= 0.5;
- erlarg = errsum;
- }
-
- // SET FINAL RESULT AND ERROR ESTIMATE
- if (abserr[0] == oflow) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
-
- if (ier[0] + ierro != 0) {
- if (ierro == 3) {
- abserr[0] += correc;
- }
- if (ier[0] == 0) {
- ier[0] = 3;
- }
- if (result[0] != 0.0 && area != 0.0) {
- if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- } else {
- if (abserr[0] > errsum) {
-
- // COMPUTE GLOBAL INTEGRAL SUM
- result[0] = 0.0;
- for (k = 1; k <= last[0]; ++k) {
- result[0] += rlist[k - 1];
- }
- abserr[0] = errsum;
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- if (area == 0.0) {
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- }
- }
-
- // TEST ON DIVERGENCE
- if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.01) {
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- if (0.01 > (result[0] / area) || (result[0] / area) > 100.0 || errsum > Math.abs(area)) {
- ier[0] = 6;
- }
- neval[0] = 30 * last[0] - 15;
- if (inf == 2) {
- neval[0] <<= 1;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
+ // SET FINAL RESULT AND ERROR ESTIMATE
+ if (abserr[0] == oflow) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
}
- private static void dqagi1(final DoubleUnaryOperator f, final double boun, final int inf,
- final double epsabs, final double epsrel, final double[] result, final double[] abserr, final int[] neval,
- final int[] ier, final int limit) {
-
- final int[] last = new int[1];
-
- // CHECK VALIDITY OF LIMIT AND LENW
- ier[0] = 6;
- neval[0] = last[0] = 0;
- result[0] = abserr[0] = 0.0;
- if (limit < 1) {
- return;
- }
-
- // PREPARE CALL FOR DQAGIE
- final double[] alist = new double[limit], blist = new double[limit], rlist = new double[limit],
- elist = new double[limit];
- final int[] iwork = new int[limit];
- dqagie(f, boun, inf, epsabs, epsrel, limit, result, abserr, neval, ier, alist, blist, rlist, elist, iwork,
- last);
+ if (ier[0] + ierro != 0) {
+ if (ierro == 3) {
+ abserr[0] += correc;
+ }
+ if (ier[0] == 0) {
+ ier[0] = 3;
+ }
+ if (result[0] != 0.0 && area != 0.0) {
+ if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ } else {
+ if (abserr[0] > errsum) {
+
+ // COMPUTE GLOBAL INTEGRAL SUM
+ result[0] = 0.0;
+ for (k = 1; k <= last[0]; ++k) {
+ result[0] += rlist[k - 1];
+ }
+ abserr[0] = errsum;
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ if (area == 0.0) {
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ }
+ }
+
+ // TEST ON DIVERGENCE
+ if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.01) {
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ if (0.01 > (result[0] / area) || (result[0] / area) > 100.0 || errsum > Math.abs(area)) {
+ ier[0] = 6;
+ }
+ neval[0] = 30 * last[0] - 15;
+ if (inf == 2) {
+ neval[0] <<= 1;
}
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ }
+
+ private static void dqagi1(final DoubleUnaryOperator f, final double boun, final int inf,
+ final double epsabs, final double epsrel, final double[] result, final double[] abserr,
+ final int[] neval, final int[] ier, final int limit) {
+
+ final int[] last = new int[1];
+
+ // CHECK VALIDITY OF LIMIT AND LENW
+ ier[0] = 6;
+ neval[0] = last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ if (limit < 1) {
+ return;
+ }
+
+ // PREPARE CALL FOR DQAGIE
+ final double[] alist = new double[limit], blist = new double[limit], rlist = new double[limit],
+ elist = new double[limit];
+ final int[] iwork = new int[limit];
+ dqagie(f, boun, inf, epsabs, epsrel, limit, result, abserr, neval, ier, alist, blist, rlist,
+ elist, iwork, last);
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLegendre.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLegendre.java
index 27fcafeb3..37d3677e7 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLegendre.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLegendre.java
@@ -5,196 +5,196 @@
import org.matheclipse.core.numerics.utils.SimpleMath;
/**
- * Integrate a real function of one variable over a finite interval using an
- * adaptive 8-point Legendre-Gauss algorithm. This algorithm is a translation of
- * the corresponding subroutine dgaus8 from the SLATEC library.
+ * Integrate a real function of one variable over a finite interval using an adaptive 8-point
+ * Legendre-Gauss algorithm. This algorithm is a translation of the corresponding subroutine dgaus8
+ * from the SLATEC library.
*/
public final class GaussLegendre extends Quadrature {
- private static final double X1 = 1.83434642495649805e-1;
- private static final double X2 = 5.25532409916328986e-1;
- private static final double X3 = 7.96666477413626740e-1;
- private static final double X4 = 9.60289856497536232e-1;
- private static final double W1 = 3.62683783378361983e-1;
- private static final double W2 = 3.13706645877887287e-1;
- private static final double W3 = 2.22381034453374471e-1;
- private static final double W4 = 1.01228536290376259e-1;
- private static final double SQ2 = Constants.SQRT2;
-
- public GaussLegendre(final double tolerance, final int maxEvaluations) {
- super(tolerance, maxEvaluations);
+ private static final double X1 = 1.83434642495649805e-1;
+ private static final double X2 = 5.25532409916328986e-1;
+ private static final double X3 = 7.96666477413626740e-1;
+ private static final double X4 = 9.60289856497536232e-1;
+ private static final double W1 = 3.62683783378361983e-1;
+ private static final double W2 = 3.13706645877887287e-1;
+ private static final double W3 = 2.22381034453374471e-1;
+ private static final double W4 = 1.01228536290376259e-1;
+ private static final double SQ2 = Constants.SQRT2;
+
+ public GaussLegendre(final double tolerance, final int maxEvaluations) {
+ super(tolerance, maxEvaluations);
+ }
+
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+
+ // prepare variables
+ final double[] err = {myTol};
+ final double[] ans = new double[1];
+ final int[] ierr = new int[1];
+ final int[] fev = new int[1];
+
+ // call main subroutine
+ dgaus8(f, a, b, err, ans, ierr, fev);
+ return new QuadratureResult(ans[0], err[0], fev[0], ierr[0] == 1 || ierr[0] == -1);
+ }
+
+ @Override
+ public final String getName() {
+ return "Gauss-Legendre";
+ }
+
+ private void dgaus8(final DoubleUnaryOperator fun, final double a, final double b,
+ final double[] err, final double[] ans, final int[] ierr, final int[] fev) {
+ int k, kml = 6, kmx = 5000, l, lmx, mxl, nbits, nib, nlmx;
+ double ae, anib, area, c, ce, ee, ef, eps, est, gl, glr, tol, vr;
+ final int[] lr = new int[61];
+ final double[] aa = new double[61], hh = new double[61], vl = new double[61],
+ gr = new double[61];
+
+ // Initialize
+ fev[0] = 0;
+ k = 53;
+ anib = SimpleMath.D1MACH[5 - 1] * k / 0.30102000;
+ nbits = (int) anib;
+ nlmx = Math.min(60, (nbits * 5) / 8);
+ ans[0] = 0.0;
+ ierr[0] = 1;
+ ce = 0.0;
+ if (a == b) {
+ if (err[0] < 0.0) {
+ err[0] = ce;
+ }
+ return;
}
-
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
-
- // prepare variables
- final double[] err = { myTol };
- final double[] ans = new double[1];
- final int[] ierr = new int[1];
- final int[] fev = new int[1];
-
- // call main subroutine
- dgaus8(f, a, b, err, ans, ierr, fev);
- return new QuadratureResult(ans[0], err[0], fev[0], ierr[0] == 1 || ierr[0] == -1);
+ lmx = nlmx;
+ if (b != 0.0 && SimpleMath.sign(1.0, b) * a > 0.0) {
+ c = Math.abs(1.0 - a / b);
+ if (c <= 0.1) {
+ if (c <= 0.0) {
+ if (err[0] < 0.0) {
+ err[0] = ce;
+ }
+ return;
+ }
+ anib = 0.5 - Math.log(c) * Constants.LOG2_INV;
+ nib = (int) anib;
+ lmx = Math.min(nlmx, nbits - nib - 7);
+ if (lmx < 1) {
+ ierr[0] = -1;
+ if (err[0] < 0.0) {
+ err[0] = ce;
+ }
+ return;
+ }
+ }
}
- @Override
- public final String getName() {
- return "Gauss-Legendre";
+ tol = Math.max(Math.abs(err[0]), SimpleMath.pow(2.0, 5 - nbits)) / 2.0;
+ if (err[0] == 0.0) {
+ tol = Math.sqrt(SimpleMath.D1MACH[4 - 1]);
}
-
- private void dgaus8(final DoubleUnaryOperator fun, final double a, final double b,
- final double[] err,
- final double[] ans, final int[] ierr, final int[] fev) {
- int k, kml = 6, kmx = 5000, l, lmx, mxl, nbits, nib, nlmx;
- double ae, anib, area, c, ce, ee, ef, eps, est, gl, glr, tol, vr;
- final int[] lr = new int[61];
- final double[] aa = new double[61], hh = new double[61], vl = new double[61], gr = new double[61];
-
- // Initialize
- fev[0] = 0;
- k = 53;
- anib = SimpleMath.D1MACH[5 - 1] * k / 0.30102000;
- nbits = (int) anib;
- nlmx = Math.min(60, (nbits * 5) / 8);
- ans[0] = 0.0;
- ierr[0] = 1;
- ce = 0.0;
- if (a == b) {
- if (err[0] < 0.0) {
- err[0] = ce;
- }
- return;
- }
- lmx = nlmx;
- if (b != 0.0 && SimpleMath.sign(1.0, b) * a > 0.0) {
- c = Math.abs(1.0 - a / b);
- if (c <= 0.1) {
- if (c <= 0.0) {
- if (err[0] < 0.0) {
- err[0] = ce;
- }
- return;
- }
- anib = 0.5 - Math.log(c) * Constants.LOG2_INV;
- nib = (int) anib;
- lmx = Math.min(nlmx, nbits - nib - 7);
- if (lmx < 1) {
- ierr[0] = -1;
- if (err[0] < 0.0) {
- err[0] = ce;
- }
- return;
- }
- }
- }
-
- tol = Math.max(Math.abs(err[0]), SimpleMath.pow(2.0, 5 - nbits)) / 2.0;
- if (err[0] == 0.0) {
- tol = Math.sqrt(SimpleMath.D1MACH[4 - 1]);
- }
- eps = tol;
- hh[1 - 1] = (b - a) / 4.0;
- aa[1 - 1] = a;
- lr[1 - 1] = 1;
- l = 1;
- est = g8(fun, aa[l - 1] + 2.0 * hh[l - 1], 2.0 * hh[l - 1]);
- fev[0] += 8;
- k = 8;
- area = Math.abs(est);
- ef = 0.5;
- mxl = 0;
-
- while (true) {
-
- // Compute refined estimates, estimate the error, etc.
- if (fev[0] - 8 >= myMaxEvals) {
- // ans[0] = Double.NaN;
- ierr[0] = 2;
- return;
- }
- gl = g8(fun, aa[l - 1] + hh[l - 1], hh[l - 1]);
- fev[0] += 8;
- if (fev[0] - 8 >= myMaxEvals) {
- // ans[0] = Double.NaN;
- ierr[0] = 2;
- return;
- }
- gr[l - 1] = g8(fun, aa[l - 1] + 3.0 * hh[l - 1], hh[l - 1]);
- fev[0] += 8;
-
- k += 16;
- area += (Math.abs(gl) + Math.abs(gr[l - 1]) - Math.abs(est));
- glr = gl + gr[l - 1];
- ee = Math.abs(est - glr) * ef;
- ae = Math.max(eps * area, tol * Math.abs(glr));
- if (ee - ae > 0.0) {
-
- // Consider the left half of this level
- if (k > kmx) {
- lmx = kml;
- }
- if (l >= lmx) {
- mxl = 1;
- } else {
- ++l;
- eps *= 0.5;
- ef /= SQ2;
- hh[l - 1] = hh[l - 1 - 1] * 0.5;
- lr[l - 1] = -1;
- aa[l - 1] = aa[l - 1 - 1];
- est = gl;
- continue;
- }
- }
-
- ce += (est - glr);
- if (lr[l - 1] <= 0.0) {
-
- // Proceed to right half at this level
- vl[l - 1] = glr;
- est = gr[l - 1 - 1];
- lr[l - 1] = 1;
- aa[l - 1] += 4.0 * hh[l - 1];
- } else {
-
- // Return one level
- vr = glr;
- while (true) {
- if (l <= 1) {
- ans[0] = vr;
- if (mxl != 0 && Math.abs(ce) > 2.0 * tol * area) {
- ierr[0] = 2;
- }
- if (err[0] < 0.0) {
- err[0] = ce;
- }
- return;
- }
- --l;
- eps *= 2.0;
- ef *= SQ2;
- if (lr[l - 1] <= 0.0) {
- vl[l - 1] = vl[l + 1 - 1] + vr;
- est = gr[l - 1 - 1];
- lr[l - 1] = 1;
- aa[l - 1] += 4.0 * hh[l - 1];
- break;
- } else {
- vr += vl[l + 1 - 1];
- }
- }
- }
- }
- }
-
- private static double g8(final DoubleUnaryOperator fun, final double x, final double h) {
- final double fx1 = fun.applyAsDouble(x - X1 * h) + fun.applyAsDouble(x + X1 * h);
- final double fx2 = fun.applyAsDouble(x - X2 * h) + fun.applyAsDouble(x + X2 * h);
- final double fx3 = fun.applyAsDouble(x - X3 * h) + fun.applyAsDouble(x + X3 * h);
- final double fx4 = fun.applyAsDouble(x - X4 * h) + fun.applyAsDouble(x + X4 * h);
- return h * (W1 * fx1 + W2 * fx2 + W3 * fx3 + W4 * fx4);
+ eps = tol;
+ hh[1 - 1] = (b - a) / 4.0;
+ aa[1 - 1] = a;
+ lr[1 - 1] = 1;
+ l = 1;
+ est = g8(fun, aa[l - 1] + 2.0 * hh[l - 1], 2.0 * hh[l - 1]);
+ fev[0] += 8;
+ k = 8;
+ area = Math.abs(est);
+ ef = 0.5;
+ mxl = 0;
+
+ while (true) {
+
+ // Compute refined estimates, estimate the error, etc.
+ if (fev[0] - 8 >= myMaxEvals) {
+ // ans[0] = Double.NaN;
+ ierr[0] = 2;
+ return;
+ }
+ gl = g8(fun, aa[l - 1] + hh[l - 1], hh[l - 1]);
+ fev[0] += 8;
+ if (fev[0] - 8 >= myMaxEvals) {
+ // ans[0] = Double.NaN;
+ ierr[0] = 2;
+ return;
+ }
+ gr[l - 1] = g8(fun, aa[l - 1] + 3.0 * hh[l - 1], hh[l - 1]);
+ fev[0] += 8;
+
+ k += 16;
+ area += (Math.abs(gl) + Math.abs(gr[l - 1]) - Math.abs(est));
+ glr = gl + gr[l - 1];
+ ee = Math.abs(est - glr) * ef;
+ ae = Math.max(eps * area, tol * Math.abs(glr));
+ if (ee - ae > 0.0) {
+
+ // Consider the left half of this level
+ if (k > kmx) {
+ lmx = kml;
+ }
+ if (l >= lmx) {
+ mxl = 1;
+ } else {
+ ++l;
+ eps *= 0.5;
+ ef /= SQ2;
+ hh[l - 1] = hh[l - 1 - 1] * 0.5;
+ lr[l - 1] = -1;
+ aa[l - 1] = aa[l - 1 - 1];
+ est = gl;
+ continue;
+ }
+ }
+
+ ce += (est - glr);
+ if (lr[l - 1] <= 0.0) {
+
+ // Proceed to right half at this level
+ vl[l - 1] = glr;
+ est = gr[l - 1 - 1];
+ lr[l - 1] = 1;
+ aa[l - 1] += 4.0 * hh[l - 1];
+ } else {
+
+ // Return one level
+ vr = glr;
+ while (true) {
+ if (l <= 1) {
+ ans[0] = vr;
+ if (mxl != 0 && Math.abs(ce) > 2.0 * tol * area) {
+ ierr[0] = 2;
+ }
+ if (err[0] < 0.0) {
+ err[0] = ce;
+ }
+ return;
+ }
+ --l;
+ eps *= 2.0;
+ ef *= SQ2;
+ if (lr[l - 1] <= 0.0) {
+ vl[l - 1] = vl[l + 1 - 1] + vr;
+ est = gr[l - 1 - 1];
+ lr[l - 1] = 1;
+ aa[l - 1] += 4.0 * hh[l - 1];
+ break;
+ } else {
+ vr += vl[l + 1 - 1];
+ }
+ }
+ }
}
+ }
+
+ private static double g8(final DoubleUnaryOperator fun, final double x, final double h) {
+ final double fx1 = fun.applyAsDouble(x - X1 * h) + fun.applyAsDouble(x + X1 * h);
+ final double fx2 = fun.applyAsDouble(x - X2 * h) + fun.applyAsDouble(x + X2 * h);
+ final double fx3 = fun.applyAsDouble(x - X3 * h) + fun.applyAsDouble(x + X3 * h);
+ final double fx4 = fun.applyAsDouble(x - X4 * h) + fun.applyAsDouble(x + X4 * h);
+ return h * (W1 * fx1 + W2 * fx2 + W3 * fx3 + W4 * fx4);
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLobatto.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLobatto.java
index dd57e27f9..dee2535a7 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLobatto.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/GaussLobatto.java
@@ -4,50 +4,52 @@
import org.matheclipse.core.numerics.utils.Constants;
/**
- * Implements an adaptive numerical integrator based on the 7-point
- * Gauss-Lobatto rule, as described in [1].
+ * Implements an adaptive numerical integrator based on the 7-point Gauss-Lobatto rule, as described
+ * in [1].
*
*
* References:
*
- * - [1] Gander, W., Gautschi, W. Adaptive Quadrature�Revisited. BIT Numerical
- * Mathematics 40, 84�101 (2000). https://doi.org/10.1023/A:1022318402393
+ * - [1] Gander, W., Gautschi, W. Adaptive Quadrature�Revisited. BIT Numerical Mathematics 40,
+ * 84�101 (2000). https://doi.org/10.1023/A:1022318402393
*
*
*/
public final class GaussLobatto extends Quadrature {
- private static final double ALPHA = Constants.SQRT2 / Constants.SQRT3;
- private static final double BETA = 1.0 / Constants.SQRT5;
+ private static final double ALPHA = Constants.SQRT2 / Constants.SQRT3;
+ private static final double BETA = 1.0 / Constants.SQRT5;
- private static final double[] X = { 0.94288241569547971906, 0.64185334234578130578, 0.23638319966214988028 };
- private static final double[] Y = { 0.0158271919734801831, 0.0942738402188500455, 0.1550719873365853963,
- 0.1888215739601824544, 0.1997734052268585268, 0.2249264653333395270, 0.2426110719014077338 };
- private static final double[] C = { 77.0, 432.0, 625.0, 672.0 };
+ private static final double[] X =
+ {0.94288241569547971906, 0.64185334234578130578, 0.23638319966214988028};
+ private static final double[] Y =
+ {0.0158271919734801831, 0.0942738402188500455, 0.1550719873365853963, 0.1888215739601824544,
+ 0.1997734052268585268, 0.2249264653333395270, 0.2426110719014077338};
+ private static final double[] C = {77.0, 432.0, 625.0, 672.0};
- private int fev;
+ private int fev;
- public GaussLobatto(final double tolerance, final int maxEvaluations) {
- super(tolerance, maxEvaluations);
- }
+ public GaussLobatto(final double tolerance, final int maxEvaluations) {
+ super(tolerance, maxEvaluations);
+ }
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
- return dlob8e(f, a, b);
- }
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+ return dlob8e(f, a, b);
+ }
- @Override
- public final String getName() {
- return "Gauss-Lobatto";
- }
+ @Override
+ public final String getName() {
+ return "Gauss-Lobatto";
+ }
- private final QuadratureResult dlob8e(final DoubleUnaryOperator f, final double a,
- final double b) {
+ private final QuadratureResult dlob8e(final DoubleUnaryOperator f, final double a,
+ final double b) {
- // compute interpolation points
- final double mid = 0.5 * (a + b);
- final double h = 0.5 * (b - a);
+ // compute interpolation points
+ final double mid = 0.5 * (a + b);
+ final double h = 0.5 * (b - a);
final double y1 = f.applyAsDouble(a);
final double y3 = f.applyAsDouble(mid - h * ALPHA);
final double y5 = f.applyAsDouble(mid - h * BETA);
@@ -61,78 +63,78 @@ private final QuadratureResult dlob8e(final DoubleUnaryOperator f, final double
final double f4 = f.applyAsDouble(mid + h * X[1]);
final double f5 = f.applyAsDouble(mid - h * X[2]);
final double f6 = f.applyAsDouble(mid + h * X[2]);
- fev = 13;
-
- // compute a crude initial estimate of the integral
- final double est1 = (y1 + y13 + 5.0 * (y5 + y9)) * (h / 6.0);
-
- // compute a more refined estimate of the integral
- double est2 = C[0] * (y1 + y13) + C[1] * (y3 + y11) + C[2] * (y5 + y9) + C[3] * y7;
- est2 *= (h / 1470.0);
-
- // compute the error estimate
- double s = Y[0] * (y1 + y13) + Y[1] * (f1 + f2);
- s += Y[2] * (y3 + y11) + Y[3] * (f3 + f4);
- s += Y[4] * (y5 + y9) + Y[5] * (f5 + f6) + Y[6] * y7;
- s *= h;
- double rtol = myTol;
- if (est1 != s) {
- final double r = Math.abs(est2 - s) / Math.abs(est1 - s);
- if (r > 0.0 && r < 1.0) {
- rtol /= r;
- }
- }
- double sign = Math.signum(s);
- if (sign == 0) {
- sign = 1.0;
- }
- double s1 = sign * Math.abs(s) * rtol / Constants.EPSILON;
- if (s == 0) {
- s1 = Math.abs(b - a);
- }
-
- // call the recursive subroutine
- final double result = dlob8(f, a, b, y1, y13, s1, rtol);
- return new QuadratureResult(result, Double.NaN, fev, Double.isFinite(result));
+ fev = 13;
+
+ // compute a crude initial estimate of the integral
+ final double est1 = (y1 + y13 + 5.0 * (y5 + y9)) * (h / 6.0);
+
+ // compute a more refined estimate of the integral
+ double est2 = C[0] * (y1 + y13) + C[1] * (y3 + y11) + C[2] * (y5 + y9) + C[3] * y7;
+ est2 *= (h / 1470.0);
+
+ // compute the error estimate
+ double s = Y[0] * (y1 + y13) + Y[1] * (f1 + f2);
+ s += Y[2] * (y3 + y11) + Y[3] * (f3 + f4);
+ s += Y[4] * (y5 + y9) + Y[5] * (f5 + f6) + Y[6] * y7;
+ s *= h;
+ double rtol = myTol;
+ if (est1 != s) {
+ final double r = Math.abs(est2 - s) / Math.abs(est1 - s);
+ if (r > 0.0 && r < 1.0) {
+ rtol /= r;
+ }
}
+ double sign = Math.signum(s);
+ if (sign == 0) {
+ sign = 1.0;
+ }
+ double s1 = sign * Math.abs(s) * rtol / Constants.EPSILON;
+ if (s == 0) {
+ s1 = Math.abs(b - a);
+ }
+
+ // call the recursive subroutine
+ final double result = dlob8(f, a, b, y1, y13, s1, rtol);
+ return new QuadratureResult(result, Double.NaN, fev, Double.isFinite(result));
+ }
- private final double dlob8(final DoubleUnaryOperator f, final double a, final double b,
- final double fa, final double fb, final double s, final double rtol) {
-
- // check the budget of evaluations
- if (fev >= myMaxEvals) {
- return Double.NaN;
- }
-
- // compute the interpolation points
- final double h = 0.5 * (b - a);
- final double mid = 0.5 * (a + b);
- final double mll = mid - h * ALPHA;
- final double ml = mid - h * BETA;
- final double mr = mid + BETA * h;
- final double mrr = mid + h * ALPHA;
+ private final double dlob8(final DoubleUnaryOperator f, final double a, final double b,
+ final double fa, final double fb, final double s, final double rtol) {
+
+ // check the budget of evaluations
+ if (fev >= myMaxEvals) {
+ return Double.NaN;
+ }
+
+ // compute the interpolation points
+ final double h = 0.5 * (b - a);
+ final double mid = 0.5 * (a + b);
+ final double mll = mid - h * ALPHA;
+ final double ml = mid - h * BETA;
+ final double mr = mid + BETA * h;
+ final double mrr = mid + h * ALPHA;
final double fmll = f.applyAsDouble(mll);
final double fml = f.applyAsDouble(ml);
final double fmid = f.applyAsDouble(mid);
final double fmr = f.applyAsDouble(mr);
final double fmrr = f.applyAsDouble(mrr);
- fev += 8;
+ fev += 8;
- // compute a crude estimate of the integral
- final double est1 = (fa + fb + 5.0 * (fml + fmr)) * (h / 6.0);
+ // compute a crude estimate of the integral
+ final double est1 = (fa + fb + 5.0 * (fml + fmr)) * (h / 6.0);
- // compute a more refined estimate of the integral
- double est2 = C[0] * (fa + fb) + C[1] * (fmll + fmrr) + C[2] * (fml + fmr) + C[3] * fmid;
- est2 *= (h / 1470.0);
+ // compute a more refined estimate of the integral
+ double est2 = C[0] * (fa + fb) + C[1] * (fmll + fmrr) + C[2] * (fml + fmr) + C[3] * fmid;
+ est2 *= (h / 1470.0);
- // check the convergence
- if (s + (est2 - est1) == s || mll <= a || b <= mrr) {
- return est2;
- }
-
- // subdivide the integration region and repeat
- return dlob8(f, a, mll, fa, fmll, s, rtol) + dlob8(f, mll, ml, fmll, fml, s, rtol)
- + dlob8(f, ml, mid, fml, fmid, s, rtol) + dlob8(f, mid, mr, fmid, fmr, s, rtol)
- + dlob8(f, mr, mrr, fmr, fmrr, s, rtol) + dlob8(f, mrr, b, fmrr, fb, s, rtol);
+ // check the convergence
+ if (s + (est2 - est1) == s || mll <= a || b <= mrr) {
+ return est2;
}
+
+ // subdivide the integration region and repeat
+ return dlob8(f, a, mll, fa, fmll, s, rtol) + dlob8(f, mll, ml, fmll, fml, s, rtol)
+ + dlob8(f, ml, mid, fml, fmid, s, rtol) + dlob8(f, mid, mr, fmid, fmr, s, rtol)
+ + dlob8(f, mr, mrr, fmr, fmrr, s, rtol) + dlob8(f, mrr, b, fmrr, fb, s, rtol);
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/NewtonCotes.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/NewtonCotes.java
index cef27d7db..d25800c4c 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/NewtonCotes.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/NewtonCotes.java
@@ -5,247 +5,248 @@
import org.matheclipse.core.numerics.utils.SimpleMath;
/**
- * Integrate a function using a 7-point adaptive Newton-Cotes quadrature rule.
- * This algorithm is a translation of the corresponding subroutine dqnc79 from
- * the SLATEC library.
+ * Integrate a function using a 7-point adaptive Newton-Cotes quadrature rule. This algorithm is a
+ * translation of the corresponding subroutine dqnc79 from the SLATEC library.
*/
public final class NewtonCotes extends Quadrature {
- private static final double W1 = 41.0 / 140.0;
- private static final double W2 = 216.0 / 140.0;
- private static final double W3 = 27.0 / 140.0;
- private static final double W4 = 272.0 / 140.0;
-
- public NewtonCotes(final double tolerance, final int maxEvaluations) {
- super(tolerance, maxEvaluations);
+ private static final double W1 = 41.0 / 140.0;
+ private static final double W2 = 216.0 / 140.0;
+ private static final double W3 = 27.0 / 140.0;
+ private static final double W4 = 272.0 / 140.0;
+
+ public NewtonCotes(final double tolerance, final int maxEvaluations) {
+ super(tolerance, maxEvaluations);
+ }
+
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+ return dqnc79(f, a, b);
+ }
+
+ @Override
+ public final String getName() {
+ return "Newton-Cotes";
+ }
+
+ private final QuadratureResult dqnc79(final DoubleUnaryOperator fun, final double a,
+ final double b) {
+ double ae, area, bank, blocal, c, ce, ee, ef, eps, q13, q7, q7l, sq2 = Constants.SQRT2, test,
+ tol, vr, ans;
+ int i, kml = 7, kmx = 5000, l, lmn, lmx, nbits, nib, nlmn = 2, nlmx, fev = 0, k = 0;
+ final double[] aa = new double[100], f = new double[14], f1 = new double[100],
+ f2 = new double[100], f3 = new double[100], f4 = new double[100], f5 = new double[100],
+ f6 = new double[100], f7 = new double[100], hh = new double[100], q7r = new double[100],
+ vl = new double[100];
+ final int[] lr = new int[100];
+
+ nbits = (int) (SimpleMath.D1MACH[5 - 1] * 53 / 0.30102000);
+ nlmx = Math.min(99, (nbits * 4) / 5);
+ ce = 0.0;
+ ans = 0.0;
+ if (a == b) {
+ return new QuadratureResult(ans, ce, fev, true);
}
-
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
- return dqnc79(f, a, b);
+ lmx = nlmx;
+ lmn = nlmn;
+ if (b != 0.0 && SimpleMath.sign(1.0, b) * a > 0.0) {
+ c = Math.abs(1.0 - a / b);
+ if (c <= 0.1) {
+ if (c <= 0.0) {
+ return new QuadratureResult(ans, ce, fev, true);
+ }
+ nib = (int) (0.5 - Math.log(c) * Constants.LOG2_INV);
+ lmx = Math.min(nlmx, nbits - nib - 4);
+ if (lmx < 2) {
+ return new QuadratureResult(ans, ce, fev, true);
+ }
+ lmn = Math.min(lmn, lmx);
+ }
}
- @Override
- public final String getName() {
- return "Newton-Cotes";
+ tol = Math.max(Math.abs(myTol), SimpleMath.pow(2.0, 5 - nbits));
+ if (myTol == 0.0) {
+ tol = Math.sqrt(SimpleMath.D1MACH[4 - 1]);
}
-
- private final QuadratureResult dqnc79(final DoubleUnaryOperator fun, final double a,
- final double b) {
- double ae, area, bank, blocal, c, ce, ee, ef, eps, q13, q7, q7l, sq2 = Constants.SQRT2, test, tol, vr, ans;
- int i, kml = 7, kmx = 5000, l, lmn, lmx, nbits, nib, nlmn = 2, nlmx, fev = 0, k = 0;
- final double[] aa = new double[100], f = new double[14], f1 = new double[100], f2 = new double[100],
- f3 = new double[100], f4 = new double[100], f5 = new double[100], f6 = new double[100],
- f7 = new double[100], hh = new double[100], q7r = new double[100], vl = new double[100];
- final int[] lr = new int[100];
-
- nbits = (int) (SimpleMath.D1MACH[5 - 1] * 53 / 0.30102000);
- nlmx = Math.min(99, (nbits * 4) / 5);
- ce = 0.0;
- ans = 0.0;
- if (a == b) {
- return new QuadratureResult(ans, ce, fev, true);
- }
- lmx = nlmx;
- lmn = nlmn;
- if (b != 0.0 && SimpleMath.sign(1.0, b) * a > 0.0) {
- c = Math.abs(1.0 - a / b);
- if (c <= 0.1) {
- if (c <= 0.0) {
- return new QuadratureResult(ans, ce, fev, true);
- }
- nib = (int) (0.5 - Math.log(c) * Constants.LOG2_INV);
- lmx = Math.min(nlmx, nbits - nib - 4);
- if (lmx < 2) {
- return new QuadratureResult(ans, ce, fev, true);
- }
- lmn = Math.min(lmn, lmx);
- }
- }
-
- tol = Math.max(Math.abs(myTol), SimpleMath.pow(2.0, 5 - nbits));
- if (myTol == 0.0) {
- tol = Math.sqrt(SimpleMath.D1MACH[4 - 1]);
- }
- eps = tol;
- hh[1 - 1] = (b - a) / 12.0;
- aa[1 - 1] = a;
- lr[1 - 1] = 1;
- for (i = 1; i <= 11; i += 2) {
+ eps = tol;
+ hh[1 - 1] = (b - a) / 12.0;
+ aa[1 - 1] = a;
+ lr[1 - 1] = 1;
+ for (i = 1; i <= 11; i += 2) {
f[i - 1] = fun.applyAsDouble(a + (i - 1) * hh[1 - 1]);
- ++fev;
- }
- blocal = b;
+ ++fev;
+ }
+ blocal = b;
f[13 - 1] = fun.applyAsDouble(blocal);
- ++fev;
- k = 7;
- l = 1;
- area = q7 = 0.0;
- ef = 256.0 / 255.0;
- bank = 0.0;
-
- while (true) {
-
- // Compute refined estimates, estimate the error, etc
- for (i = 2; i <= 12; i += 2) {
- f[i - 1] = fun.applyAsDouble(aa[l - 1] + (i - 1) * hh[l - 1]);
- ++fev;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(ans, ce, fev, false);
- }
- }
- k += 6;
-
- // Compute left and right half estimates
- q7l = hh[l - 1] * ((W1 * (f[1 - 1] + f[7 - 1]) + W2 * (f[2 - 1] + f[6 - 1]))
- + (W3 * (f[3 - 1] + f[5 - 1]) + W4 * f[4 - 1]));
- q7r[l - 1] = hh[l - 1] * ((W1 * (f[7 - 1] + f[13 - 1]) + W2 * (f[8 - 1] + f[12 - 1]))
- + (W3 * (f[9 - 1] + f[11 - 1]) + W4 * f[10 - 1]));
-
- // Update estimate of integral of absolute value
- area += (Math.abs(q7l) + Math.abs(q7r[l - 1]) - Math.abs(q7));
-
- // Do not bother to test convergence before minimum refinement level
- if (l < lmn) {
- ++l;
- eps *= 0.5;
- if (l <= 17) {
- ef /= sq2;
- }
- hh[l - 1] = hh[l - 1 - 1] * 0.5;
- lr[l - 1] = -1;
- aa[l - 1] = aa[l - 1 - 1];
- q7 = q7l;
- f1[l - 1] = f[7 - 1];
- f2[l - 1] = f[8 - 1];
- f3[l - 1] = f[9 - 1];
- f4[l - 1] = f[10 - 1];
- f5[l - 1] = f[11 - 1];
- f6[l - 1] = f[12 - 1];
- f7[l - 1] = f[13 - 1];
- f[13 - 1] = f[7 - 1];
- f[11 - 1] = f[6 - 1];
- f[9 - 1] = f[5 - 1];
- f[7 - 1] = f[4 - 1];
- f[5 - 1] = f[3 - 1];
- f[3 - 1] = f[2 - 1];
- continue;
- }
-
- // Estimate the error in new value for whole interval, Q13
- q13 = q7l + q7r[l - 1];
- ee = Math.abs(q7 - q13) * ef;
-
- // Compute nominal allowed error
- ae = eps * area;
-
- // Borrow from bank account, but not too much
- test = Math.min(ae + 0.8 * bank, 10.0 * ae);
-
- // Don't ask for excessive accuracy
- test = Math.max(test, Math.max(tol * Math.abs(q13), 3.0e-5 * tol * area));
-
- // Now, did this interval pass or not?
- if (ee - test <= 0.0) {
-
- // On good intervals accumulate the theoretical estimate
- ce += (q7 - q13) / 255.0;
- } else {
-
- // Consider the left half of next deeper level
- if (k > kmx) {
- lmx = Math.min(kml, lmx);
- }
- if (l >= lmx) {
-
- // Have hit maximum refinement level --
- // penalize the cumulative error
- ce += (q7 - q13);
- } else {
- ++l;
- eps *= 0.5;
- if (l <= 17) {
- ef /= sq2;
- }
- hh[l - 1] = hh[l - 1 - 1] * 0.5;
- lr[l - 1] = -1;
- aa[l - 1] = aa[l - 1 - 1];
- q7 = q7l;
- f1[l - 1] = f[7 - 1];
- f2[l - 1] = f[8 - 1];
- f3[l - 1] = f[9 - 1];
- f4[l - 1] = f[10 - 1];
- f5[l - 1] = f[11 - 1];
- f6[l - 1] = f[12 - 1];
- f7[l - 1] = f[13 - 1];
- f[13 - 1] = f[7 - 1];
- f[11 - 1] = f[6 - 1];
- f[9 - 1] = f[5 - 1];
- f[7 - 1] = f[4 - 1];
- f[5 - 1] = f[3 - 1];
- f[3 - 1] = f[2 - 1];
- continue;
- }
- }
-
- // Update the bank account. Don't go into debt.
- bank += (ae - ee);
- if (bank < 0.0) {
- bank = 0.0;
- }
-
- // Did we just finish a left half or a right half?
- if (lr[l - 1] <= 0.0) {
-
- // Proceed to right half at this level
- vl[l - 1] = q13;
- q7 = q7r[l - 1 - 1];
- lr[l - 1] = 1;
- aa[l - 1] += 12.0 * hh[l - 1];
- f[1 - 1] = f1[l - 1];
- f[3 - 1] = f2[l - 1];
- f[5 - 1] = f3[l - 1];
- f[7 - 1] = f4[l - 1];
- f[9 - 1] = f5[l - 1];
- f[11 - 1] = f6[l - 1];
- f[13 - 1] = f7[l - 1];
- } else {
-
- // Left and right halves are done, so go back up a level
- vr = q13;
- while (true) {
- if (l <= 1) {
- ans = vr;
- if (Math.abs(ce) > 2.0 * tol * area) {
- return new QuadratureResult(ans, Math.abs(ce), fev, false);
- } else {
- return new QuadratureResult(ans, Math.abs(ce), fev, true);
- }
- }
- if (l <= 17) {
- ef *= sq2;
- }
- eps *= 2.0;
- --l;
- if (lr[l - 1] <= 0.0) {
- vl[l - 1] = vl[l + 1 - 1] + vr;
- q7 = q7r[l - 1 - 1];
- lr[l - 1] = 1;
- aa[l - 1] += 12.0 * hh[l - 1];
- f[1 - 1] = f1[l - 1];
- f[3 - 1] = f2[l - 1];
- f[5 - 1] = f3[l - 1];
- f[7 - 1] = f4[l - 1];
- f[9 - 1] = f5[l - 1];
- f[11 - 1] = f6[l - 1];
- f[13 - 1] = f7[l - 1];
- break;
- } else {
- vr += vl[l + 1 - 1];
- }
- }
- }
- }
+ ++fev;
+ k = 7;
+ l = 1;
+ area = q7 = 0.0;
+ ef = 256.0 / 255.0;
+ bank = 0.0;
+
+ while (true) {
+
+ // Compute refined estimates, estimate the error, etc
+ for (i = 2; i <= 12; i += 2) {
+ f[i - 1] = fun.applyAsDouble(aa[l - 1] + (i - 1) * hh[l - 1]);
+ ++fev;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(ans, ce, fev, false);
+ }
+ }
+ k += 6;
+
+ // Compute left and right half estimates
+ q7l = hh[l - 1] * ((W1 * (f[1 - 1] + f[7 - 1]) + W2 * (f[2 - 1] + f[6 - 1]))
+ + (W3 * (f[3 - 1] + f[5 - 1]) + W4 * f[4 - 1]));
+ q7r[l - 1] = hh[l - 1] * ((W1 * (f[7 - 1] + f[13 - 1]) + W2 * (f[8 - 1] + f[12 - 1]))
+ + (W3 * (f[9 - 1] + f[11 - 1]) + W4 * f[10 - 1]));
+
+ // Update estimate of integral of absolute value
+ area += (Math.abs(q7l) + Math.abs(q7r[l - 1]) - Math.abs(q7));
+
+ // Do not bother to test convergence before minimum refinement level
+ if (l < lmn) {
+ ++l;
+ eps *= 0.5;
+ if (l <= 17) {
+ ef /= sq2;
+ }
+ hh[l - 1] = hh[l - 1 - 1] * 0.5;
+ lr[l - 1] = -1;
+ aa[l - 1] = aa[l - 1 - 1];
+ q7 = q7l;
+ f1[l - 1] = f[7 - 1];
+ f2[l - 1] = f[8 - 1];
+ f3[l - 1] = f[9 - 1];
+ f4[l - 1] = f[10 - 1];
+ f5[l - 1] = f[11 - 1];
+ f6[l - 1] = f[12 - 1];
+ f7[l - 1] = f[13 - 1];
+ f[13 - 1] = f[7 - 1];
+ f[11 - 1] = f[6 - 1];
+ f[9 - 1] = f[5 - 1];
+ f[7 - 1] = f[4 - 1];
+ f[5 - 1] = f[3 - 1];
+ f[3 - 1] = f[2 - 1];
+ continue;
+ }
+
+ // Estimate the error in new value for whole interval, Q13
+ q13 = q7l + q7r[l - 1];
+ ee = Math.abs(q7 - q13) * ef;
+
+ // Compute nominal allowed error
+ ae = eps * area;
+
+ // Borrow from bank account, but not too much
+ test = Math.min(ae + 0.8 * bank, 10.0 * ae);
+
+ // Don't ask for excessive accuracy
+ test = Math.max(test, Math.max(tol * Math.abs(q13), 3.0e-5 * tol * area));
+
+ // Now, did this interval pass or not?
+ if (ee - test <= 0.0) {
+
+ // On good intervals accumulate the theoretical estimate
+ ce += (q7 - q13) / 255.0;
+ } else {
+
+ // Consider the left half of next deeper level
+ if (k > kmx) {
+ lmx = Math.min(kml, lmx);
+ }
+ if (l >= lmx) {
+
+ // Have hit maximum refinement level --
+ // penalize the cumulative error
+ ce += (q7 - q13);
+ } else {
+ ++l;
+ eps *= 0.5;
+ if (l <= 17) {
+ ef /= sq2;
+ }
+ hh[l - 1] = hh[l - 1 - 1] * 0.5;
+ lr[l - 1] = -1;
+ aa[l - 1] = aa[l - 1 - 1];
+ q7 = q7l;
+ f1[l - 1] = f[7 - 1];
+ f2[l - 1] = f[8 - 1];
+ f3[l - 1] = f[9 - 1];
+ f4[l - 1] = f[10 - 1];
+ f5[l - 1] = f[11 - 1];
+ f6[l - 1] = f[12 - 1];
+ f7[l - 1] = f[13 - 1];
+ f[13 - 1] = f[7 - 1];
+ f[11 - 1] = f[6 - 1];
+ f[9 - 1] = f[5 - 1];
+ f[7 - 1] = f[4 - 1];
+ f[5 - 1] = f[3 - 1];
+ f[3 - 1] = f[2 - 1];
+ continue;
+ }
+ }
+
+ // Update the bank account. Don't go into debt.
+ bank += (ae - ee);
+ if (bank < 0.0) {
+ bank = 0.0;
+ }
+
+ // Did we just finish a left half or a right half?
+ if (lr[l - 1] <= 0.0) {
+
+ // Proceed to right half at this level
+ vl[l - 1] = q13;
+ q7 = q7r[l - 1 - 1];
+ lr[l - 1] = 1;
+ aa[l - 1] += 12.0 * hh[l - 1];
+ f[1 - 1] = f1[l - 1];
+ f[3 - 1] = f2[l - 1];
+ f[5 - 1] = f3[l - 1];
+ f[7 - 1] = f4[l - 1];
+ f[9 - 1] = f5[l - 1];
+ f[11 - 1] = f6[l - 1];
+ f[13 - 1] = f7[l - 1];
+ } else {
+
+ // Left and right halves are done, so go back up a level
+ vr = q13;
+ while (true) {
+ if (l <= 1) {
+ ans = vr;
+ if (Math.abs(ce) > 2.0 * tol * area) {
+ return new QuadratureResult(ans, Math.abs(ce), fev, false);
+ } else {
+ return new QuadratureResult(ans, Math.abs(ce), fev, true);
+ }
+ }
+ if (l <= 17) {
+ ef *= sq2;
+ }
+ eps *= 2.0;
+ --l;
+ if (lr[l - 1] <= 0.0) {
+ vl[l - 1] = vl[l + 1 - 1] + vr;
+ q7 = q7r[l - 1 - 1];
+ lr[l - 1] = 1;
+ aa[l - 1] += 12.0 * hh[l - 1];
+ f[1 - 1] = f1[l - 1];
+ f[3 - 1] = f2[l - 1];
+ f[5 - 1] = f3[l - 1];
+ f[7 - 1] = f4[l - 1];
+ f[9 - 1] = f5[l - 1];
+ f[11 - 1] = f6[l - 1];
+ f[13 - 1] = f7[l - 1];
+ break;
+ } else {
+ vr += vl[l + 1 - 1];
+ }
+ }
+ }
}
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Quadrature.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Quadrature.java
index 0d4618a65..c4b457044 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Quadrature.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Quadrature.java
@@ -9,180 +9,176 @@
*/
public abstract class Quadrature {
- /**
- *
- */
- public static final class QuadratureResult {
-
- public final double estimate;
- public final double error;
- public final int evaluations;
- public final boolean converged;
-
- public QuadratureResult(final double est, final double err, final int evals, final boolean success) {
- estimate = est;
- error = err;
- evaluations = evals;
- converged = success;
- }
-
- @Override
- public String toString() {
- return String.format("%.08f", estimate) + " +- " + String.format("%.08f", error) + "\n" + "evaluations: "
- + evaluations + "\n" + "converged: " + converged;
- }
+ /**
+ *
+ */
+ public static final class QuadratureResult {
+
+ public final double estimate;
+ public final double error;
+ public final int evaluations;
+ public final boolean converged;
+
+ public QuadratureResult(final double est, final double err, final int evals,
+ final boolean success) {
+ estimate = est;
+ error = err;
+ evaluations = evals;
+ converged = success;
}
- protected final double myTol;
- protected final int myMaxEvals;
-
- /**
- * Creates a new instance of the current numerical integrator.
- *
- * @param tolerance the smallest acceptable change in integral estimates in
- * consecutive iterations that indicates the algorithm has
- * converged
- * @param maxEvaluations the maximum number of evaluations of each function
- * permitted
- */
- public Quadrature(final double tolerance, final int maxEvaluations) {
- myTol = tolerance;
- myMaxEvals = maxEvaluations;
+ @Override
+ public String toString() {
+ return String.format("%.08f", estimate) + " +- " + String.format("%.08f", error) + "\n"
+ + "evaluations: " + evaluations + "\n" + "converged: " + converged;
+ }
+ }
+
+ protected final double myTol;
+ protected final int myMaxEvals;
+
+ /**
+ * Creates a new instance of the current numerical integrator.
+ *
+ * @param tolerance the smallest acceptable change in integral estimates in consecutive iterations
+ * that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of evaluations of each function permitted
+ */
+ public Quadrature(final double tolerance, final int maxEvaluations) {
+ myTol = tolerance;
+ myMaxEvals = maxEvaluations;
+ }
+
+ abstract QuadratureResult properIntegral(DoubleUnaryOperator f, double a, double b);
+
+ /**
+ * Returns a string representation of the current algorithm.
+ *
+ * @return a string representation of the current algorithm
+ */
+ public abstract String getName();
+
+ /**
+ * Estimates a definite integral, or indefinite integral in some limited cases. All algorithms
+ * support definite integrals. The only algorithm that currently supports indefinite integrals is
+ * Gauss Kronrod.
+ *
+ * @param f the function to integrate
+ * @param a the left endpoint of the integration interval
+ * @param b the right endpoint of the integration interval
+ * @return an estimate of the definite or indefinite integral
+ */
+ public QuadratureResult integrate(final DoubleUnaryOperator f, final double a, final double b) {
+
+ // empty integral (a, a)
+ if (a == b) {
+ return new QuadratureResult(0.0, 0.0, 0, true);
}
- abstract QuadratureResult properIntegral(DoubleUnaryOperator f, double a, double b);
-
- /**
- * Returns a string representation of the current algorithm.
- *
- * @return a string representation of the current algorithm
- */
- public abstract String getName();
-
- /**
- * Estimates a definite integral, or indefinite integral in some limited cases.
- * All algorithms support definite integrals. The only algorithm that currently
- * supports indefinite integrals is Gauss Kronrod.
- *
- * @param f the function to integrate
- * @param a the left endpoint of the integration interval
- * @param b the right endpoint of the integration interval
- * @return an estimate of the definite or indefinite integral
- */
- public QuadratureResult integrate(final DoubleUnaryOperator f, final double a,
- final double b) {
-
- // empty integral (a, a)
- if (a == b) {
- return new QuadratureResult(0.0, 0.0, 0, true);
- }
-
- // opposite bounds
- if (a > b) {
- return integrate(f, b, a);
- }
-
- // finite integral (a, b)
- if (Double.isFinite(a) && Double.isFinite(b)) {
- return properIntegral(f, a, b);
- }
-
- // improper integral of the form [a, infinity]
- if (Double.isFinite(a) && !Double.isFinite(b)) {
- final DoubleUnaryOperator ft = t -> {
- if (t <= 0.0) {
- return 0.0;
- }
- final double x = a - 1.0 + 1.0 / t;
- final double dx = 1.0 / t / t;
- return f.applyAsDouble(x) * dx;
- };
- return properIntegral(ft, 0.0, 1.0);
- }
-
- // improper integral of the form [-infinity, b]
- if (!Double.isFinite(a) && Double.isFinite(b)) {
- final DoubleUnaryOperator ft = t -> {
- if (t <= 0.0) {
- return 0.0;
- }
- final double x = b + 1.0 - 1.0 / t;
- final double dx = 1.0 / t / t;
- return f.applyAsDouble(x) * dx;
- };
- return properIntegral(ft, 0.0, 1.0);
- }
-
- // doubly improper integral
- final QuadratureResult left = integrate(f, a, 0.0);
- final QuadratureResult right = integrate(f, 0.0, b);
- return new QuadratureResult(left.estimate + right.estimate, left.error + right.error,
- left.evaluations + right.evaluations, left.converged && right.converged);
+ // opposite bounds
+ if (a > b) {
+ return integrate(f, b, a);
}
- /**
- * Estimates a definite integral of a function by first applying a change of
- * variable to the function, suitable for estimating indefinite integrals. Given
- * a function to integrate, f, and a differentiable function t, this method
- * integrates f(t(x)) * t'(x).
- *
- * @param f the function to integrate
- * @param t the change of variable
- * @param dt the derivative of the change of variable function t
- * @param a the left endpoint of the integration interval
- * @param b the right endpoint of the integration interval
- * @return an estimate of the definite integral
- */
- public QuadratureResult integrate(final Function super Double, Double> f,
- final Function super Double, Double> t, final Function super Double, Double> dt, final double a,
- final double b) {
-
- // construct the integrand f(t(x)) t(x) dt(x)
- final DoubleUnaryOperator func = (x) -> f.apply(t.apply(x)) * dt.apply(x);
+ // finite integral (a, b)
+ if (Double.isFinite(a) && Double.isFinite(b)) {
+ return properIntegral(f, a, b);
+ }
- // dispatch to integration routine
- return integrate(func, a, b);
+ // improper integral of the form [a, infinity]
+ if (Double.isFinite(a) && !Double.isFinite(b)) {
+ final DoubleUnaryOperator ft = t -> {
+ if (t <= 0.0) {
+ return 0.0;
+ }
+ final double x = a - 1.0 + 1.0 / t;
+ final double dx = 1.0 / t / t;
+ return f.applyAsDouble(x) * dx;
+ };
+ return properIntegral(ft, 0.0, 1.0);
}
- /**
- * This method splits a potentially indefinite integration interval into
- * disjoint definite intervals. It returns a sequence of integral estimates on
- * each interval. This is very useful for evaluating highly oscillating
- * integrals on infinite intervals, called Longman's method [1].
- *
- *
- * References:
- *
- * - [1] Longman, I. (1956). Note on a method for computing infinite integrals
- * of oscillatory functions. Mathematical Proceedings of the Cambridge
- * Philosophical Society, 52(4), 764-768. doi:10.1017/S030500410003187X
- *
- *
- *
- * @param f the function to integrate
- * @param splitPoints the points at which to split the integration region when
- * defining definite integrals
- * @return an Iterable representing the sequence of definite integrals
- */
- public Iterable integratePiecewise(final DoubleUnaryOperator f,
- final Iterable splitPoints) {
- return () -> new Iterator<>() {
-
- private final Iterator it = splitPoints.iterator();
- private double left = 0.0;
- private double right = it.hasNext() ? it.next() : Double.NaN;
-
- @Override
- public final boolean hasNext() {
- return it.hasNext();
- }
-
- @Override
- public final Double next() {
- left = right;
- right = it.next();
- return integrate(f, left, right).estimate;
- }
- };
+ // improper integral of the form [-infinity, b]
+ if (!Double.isFinite(a) && Double.isFinite(b)) {
+ final DoubleUnaryOperator ft = t -> {
+ if (t <= 0.0) {
+ return 0.0;
+ }
+ final double x = b + 1.0 - 1.0 / t;
+ final double dx = 1.0 / t / t;
+ return f.applyAsDouble(x) * dx;
+ };
+ return properIntegral(ft, 0.0, 1.0);
}
+
+ // doubly improper integral
+ final QuadratureResult left = integrate(f, a, 0.0);
+ final QuadratureResult right = integrate(f, 0.0, b);
+ return new QuadratureResult(left.estimate + right.estimate, left.error + right.error,
+ left.evaluations + right.evaluations, left.converged && right.converged);
+ }
+
+ /**
+ * Estimates a definite integral of a function by first applying a change of variable to the
+ * function, suitable for estimating indefinite integrals. Given a function to integrate, f, and a
+ * differentiable function t, this method integrates f(t(x)) * t'(x).
+ *
+ * @param f the function to integrate
+ * @param t the change of variable
+ * @param dt the derivative of the change of variable function t
+ * @param a the left endpoint of the integration interval
+ * @param b the right endpoint of the integration interval
+ * @return an estimate of the definite integral
+ */
+ public QuadratureResult integrate(final Function super Double, Double> f,
+ final Function super Double, Double> t, final Function super Double, Double> dt,
+ final double a, final double b) {
+
+ // construct the integrand f(t(x)) t(x) dt(x)
+ final DoubleUnaryOperator func = (x) -> f.apply(t.apply(x)) * dt.apply(x);
+
+ // dispatch to integration routine
+ return integrate(func, a, b);
+ }
+
+ /**
+ * This method splits a potentially indefinite integration interval into disjoint definite
+ * intervals. It returns a sequence of integral estimates on each interval. This is very useful
+ * for evaluating highly oscillating integrals on infinite intervals, called Longman's method [1].
+ *
+ *
+ * References:
+ *
+ * - [1] Longman, I. (1956). Note on a method for computing infinite integrals of oscillatory
+ * functions. Mathematical Proceedings of the Cambridge Philosophical Society, 52(4), 764-768.
+ * doi:10.1017/S030500410003187X
+ *
+ *
+ *
+ * @param f the function to integrate
+ * @param splitPoints the points at which to split the integration region when defining definite
+ * integrals
+ * @return an Iterable representing the sequence of definite integrals
+ */
+ public Iterable integratePiecewise(final DoubleUnaryOperator f,
+ final Iterable splitPoints) {
+ return () -> new Iterator<>() {
+
+ private final Iterator it = splitPoints.iterator();
+ private double left = 0.0;
+ private double right = it.hasNext() ? it.next() : Double.NaN;
+
+ @Override
+ public final boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public final Double next() {
+ left = right;
+ right = it.next();
+ return integrate(f, left, right).estimate;
+ }
+ };
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/RmsRule.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/RmsRule.java
index 8e9a4ab18..00992d940 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/RmsRule.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/RmsRule.java
@@ -4,856 +4,861 @@
import org.matheclipse.core.numerics.utils.Constants;
/**
- * An adaptive integrator obtained by replacing the Gauss-Kronrod rules in
- * QUADPACK with recursive monotone stable (RMS) formulas [1]. A translation of
- * a corresponding Fortran subroutine by Alan Miller.
+ * An adaptive integrator obtained by replacing the Gauss-Kronrod rules in QUADPACK with recursive
+ * monotone stable (RMS) formulas [1]. A translation of a corresponding Fortran subroutine by Alan
+ * Miller.
*
*
* References:
*
- * - [1] Favati, Paola, Grazia Lotti, and Francesco Romani. "Algorithm 691:
- * Improving QUADPACK automatic integration routines." ACM Transactions on
- * Mathematical Software (TOMS) 17.2 (1991): 218-232.
+ * - [1] Favati, Paola, Grazia Lotti, and Francesco Romani. "Algorithm 691: Improving QUADPACK
+ * automatic integration routines." ACM Transactions on Mathematical Software (TOMS) 17.2 (1991):
+ * 218-232.
*
*
*/
public final class RmsRule extends Quadrature {
- private static final int[] istart = { 0, 7, 17, 31 };
- private static final int[] length = { 7, 10, 14, 21 };
-
- private static final double[] xx = { 0.0, .25000000000000000000E+00, .50000000000000000000E+00,
- .75000000000000000000E+00, .87500000000000000000E+00, .93750000000000000000E+00, .10000000000000000000E+01,
- .37500000000000000000E+00, .62500000000000000000E+00, .96875000000000000000E+00, .12500000000000000000E+00,
- .68750000000000000000E+00, .81250000000000000000E+00, .98437500000000000000E+00, .18750000000000000000E+00,
- .31250000000000000000E+00, .43750000000000000000E+00, .56250000000000000000E+00, .84375000000000000000E+00,
- .90625000000000000000E+00, .99218750000000000000E+00 };
-
- private static final double[] ww = { 1.303262173284849021810473057638590518409112513421E-1,
- 2.390632866847646220320329836544615917290026806242E-1,
- 2.630626354774670227333506083741355715758124943143E-1,
- 2.186819313830574175167853094864355208948886875898E-1,
- 2.757897646642836865859601197607471574336674206700E-2,
- 1.055750100538458443365034879086669791305550493830E-1,
- 1.571194260595182254168429283636656908546309467968E-2,
- 1.298751627936015783241173611320651866834051160074E-1,
- 2.249996826462523640447834514709508786970828213187E-1,
- 1.680415725925575286319046726692683040162290325505E-1,
- 1.415567675701225879892811622832845252125600939627E-1,
- 1.006482260551160175038684459742336605269707889822E-1,
- 2.510604860724282479058338820428989444699235030871E-2,
- 9.402964360009747110031098328922608224934320397592E-3,
- 5.542699233295875168406783695143646338274805359780E-2,
- 9.986735247403367525720377847755415293097913496236E-2,
- 4.507523056810492466415880450799432587809828791196E-2,
- 6.300942249647773931746170540321811473310938661469E-2,
- 1.261383225537664703012999637242003647020326905948E-1,
- 1.273864433581028272878709981850307363453523117880E-1,
- 8.576500414311820514214087864326799153427368592787E-2,
- 7.102884842310253397447305465997026228407227220665E-2,
- 5.026383572857942403759829860675892897279675661654E-2,
- 4.683670010609093810432609684738393586390722052124E-3,
- 1.235837891364555000245004813294817451524633100256E-1,
- 1.148933497158144016800199601785309838604146040215E-1,
- 1.252575774226122633391477702593585307254527198070E-2,
- 1.239572396231834242194189674243818619042280816640E-1,
- 2.501306413750310579525950767549691151739047969345E-2,
- 4.915957918146130094258849161350510503556792927578E-2,
- 2.259167374956474713302030584548274729936249753832E-2,
- 6.362762978782724559269342300509058175967124446839E-2,
- 9.950065827346794643193261975720606296171462239514E-2,
- 7.048220002718565366098742295389607994441704889441E-2,
- 6.512297339398335645872697307762912795346716454337E-2,
- 3.998229150313659724790527138690215186863915308702E-2,
- 3.456512257080287509832054272964315588028252136044E-2,
- 2.212167975884114432760321569298651047876071264944E-3,
- 8.140326425945938045967829319725797511040878579808E-2,
- 6.583213447600552906273539578430361199084485578379E-2,
- 2.592913726450792546064232192976262988065252032902E-2,
- 1.187141856692283347609436153545356484256869129472E-1,
- 5.999947605385971985589674757013565610751028128731E-2,
- 5.500937980198041736910257988346101839062581489820E-2,
- 5.264422421764655969760271538981443718440340270116E-3,
- 1.533126874056586959338368742803997744815413565014E-2,
- 3.527159369750123100455704702965541866345781113903E-2,
- 5.000556431653955124212795201196389006184693561679E-2,
- 5.744164831179720106340717579281831675999717767532E-2,
- 1.598823797283813438301248206397233634639162043386E-2,
- 2.635660410220884993472478832884065450876913559421E-2,
- 1.196003937945541091670106760660561117114584656319E-2 };
-
- private final double myRelTol;
-
- /**
- * Creates a new instance of the RMS quadrature integrator.
- *
- * @param relativeTolerance the smallest acceptable relative change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param tolerance the smallest acceptable absolute change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param maxEvaluations the maximum number of evaluations of each function
- * permitted
- */
- public RmsRule(final double tolerance, final double relativeTolerance, final int maxEvaluations) {
- super(tolerance, maxEvaluations);
- myRelTol = relativeTolerance;
+ private static final int[] istart = {0, 7, 17, 31};
+ private static final int[] length = {7, 10, 14, 21};
+
+ private static final double[] xx = {0.0, .25000000000000000000E+00, .50000000000000000000E+00,
+ .75000000000000000000E+00, .87500000000000000000E+00, .93750000000000000000E+00,
+ .10000000000000000000E+01, .37500000000000000000E+00, .62500000000000000000E+00,
+ .96875000000000000000E+00, .12500000000000000000E+00, .68750000000000000000E+00,
+ .81250000000000000000E+00, .98437500000000000000E+00, .18750000000000000000E+00,
+ .31250000000000000000E+00, .43750000000000000000E+00, .56250000000000000000E+00,
+ .84375000000000000000E+00, .90625000000000000000E+00, .99218750000000000000E+00};
+
+ private static final double[] ww = {1.303262173284849021810473057638590518409112513421E-1,
+ 2.390632866847646220320329836544615917290026806242E-1,
+ 2.630626354774670227333506083741355715758124943143E-1,
+ 2.186819313830574175167853094864355208948886875898E-1,
+ 2.757897646642836865859601197607471574336674206700E-2,
+ 1.055750100538458443365034879086669791305550493830E-1,
+ 1.571194260595182254168429283636656908546309467968E-2,
+ 1.298751627936015783241173611320651866834051160074E-1,
+ 2.249996826462523640447834514709508786970828213187E-1,
+ 1.680415725925575286319046726692683040162290325505E-1,
+ 1.415567675701225879892811622832845252125600939627E-1,
+ 1.006482260551160175038684459742336605269707889822E-1,
+ 2.510604860724282479058338820428989444699235030871E-2,
+ 9.402964360009747110031098328922608224934320397592E-3,
+ 5.542699233295875168406783695143646338274805359780E-2,
+ 9.986735247403367525720377847755415293097913496236E-2,
+ 4.507523056810492466415880450799432587809828791196E-2,
+ 6.300942249647773931746170540321811473310938661469E-2,
+ 1.261383225537664703012999637242003647020326905948E-1,
+ 1.273864433581028272878709981850307363453523117880E-1,
+ 8.576500414311820514214087864326799153427368592787E-2,
+ 7.102884842310253397447305465997026228407227220665E-2,
+ 5.026383572857942403759829860675892897279675661654E-2,
+ 4.683670010609093810432609684738393586390722052124E-3,
+ 1.235837891364555000245004813294817451524633100256E-1,
+ 1.148933497158144016800199601785309838604146040215E-1,
+ 1.252575774226122633391477702593585307254527198070E-2,
+ 1.239572396231834242194189674243818619042280816640E-1,
+ 2.501306413750310579525950767549691151739047969345E-2,
+ 4.915957918146130094258849161350510503556792927578E-2,
+ 2.259167374956474713302030584548274729936249753832E-2,
+ 6.362762978782724559269342300509058175967124446839E-2,
+ 9.950065827346794643193261975720606296171462239514E-2,
+ 7.048220002718565366098742295389607994441704889441E-2,
+ 6.512297339398335645872697307762912795346716454337E-2,
+ 3.998229150313659724790527138690215186863915308702E-2,
+ 3.456512257080287509832054272964315588028252136044E-2,
+ 2.212167975884114432760321569298651047876071264944E-3,
+ 8.140326425945938045967829319725797511040878579808E-2,
+ 6.583213447600552906273539578430361199084485578379E-2,
+ 2.592913726450792546064232192976262988065252032902E-2,
+ 1.187141856692283347609436153545356484256869129472E-1,
+ 5.999947605385971985589674757013565610751028128731E-2,
+ 5.500937980198041736910257988346101839062581489820E-2,
+ 5.264422421764655969760271538981443718440340270116E-3,
+ 1.533126874056586959338368742803997744815413565014E-2,
+ 3.527159369750123100455704702965541866345781113903E-2,
+ 5.000556431653955124212795201196389006184693561679E-2,
+ 5.744164831179720106340717579281831675999717767532E-2,
+ 1.598823797283813438301248206397233634639162043386E-2,
+ 2.635660410220884993472478832884065450876913559421E-2,
+ 1.196003937945541091670106760660561117114584656319E-2};
+
+ private final double myRelTol;
+
+ /**
+ * Creates a new instance of the RMS quadrature integrator.
+ *
+ * @param relativeTolerance the smallest acceptable relative change in integral estimates in
+ * consecutive iterations that indicates the algorithm has converged
+ * @param tolerance the smallest acceptable absolute change in integral estimates in consecutive
+ * iterations that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of evaluations of each function permitted
+ */
+ public RmsRule(final double tolerance, final double relativeTolerance, final int maxEvaluations) {
+ super(tolerance, maxEvaluations);
+ myRelTol = relativeTolerance;
+ }
+
+ public RmsRule(final double tolerance, final int maxEvaluations) {
+ this(tolerance, 50.0 * Constants.EPSILON, maxEvaluations);
+ }
+
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+ return qxgs(f, a, b, myTol, myRelTol, myMaxEvals);
+ }
+
+ @Override
+ public final String getName() {
+ return "RMS Rule";
+ }
+
+ private final QuadratureResult qxgs(final DoubleUnaryOperator f, final double a, final double b,
+ final double epsabs, final double epsrel, final int limit) {
+
+ // prepare variables
+ final int[] ier = new int[1];
+ final double[] result = new double[1];
+ final double[] abserr = new double[1];
+ final int[] last = new int[1];
+ final int[] fev = new int[1];
+
+ // call main subroutine
+ qxgs(f, a, b, epsabs, epsrel, result, abserr, ier, limit, last, fev);
+ return new QuadratureResult(result[0], abserr[0], fev[0], ier[0] == 0);
+ }
+
+ private static void qxgs(final DoubleUnaryOperator f, final double a, final double b,
+ final double epsabs, final double epsrel, final double[] result, final double[] abserr,
+ final int[] ier, final int limit, final int[] last, final int[] fev) {
+ ier[0] = 6;
+ last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ fev[0] = 0;
+ if (limit < 1) {
+ return;
}
- public RmsRule(final double tolerance, final int maxEvaluations) {
- this(tolerance, 50.0 * Constants.EPSILON, maxEvaluations);
+ // PREPARE CALL FOR QXGSE.
+ qxgse1(f, a, b, epsabs, epsrel, limit, result, abserr, ier, last, fev);
+ }
+
+ private static void qxgse1(final DoubleUnaryOperator f, final double a, final double b,
+ final double epsabs, final double epsrel, final int limit, final double[] result,
+ final double[] abserr, final int[] ier, final int[] last, final int[] fev) {
+
+ // THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A
+ // DEFINITE INTEGRAL I = INTEGRAL OF F OVER (A,B),
+ // HOPEFULLY SATISFYING FOLLOWING CLAIM FOR ACCURACY
+ // ABS(I-RESULT).LE.MAX(EPSABS,EPSREL*ABS(I)).
+ boolean extrap, noext;
+ int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
+ double area, area12, a1, a2, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast, errbnd,
+ erro12, errsum, ertest = 0.0, oflow, rerr, small = 0.0, t, uflow;
+ final int[] ln1 = new int[1], lp1 = new int[1], ln2 = new int[1], lp2 = new int[1],
+ maxerr = new int[1], nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
+ final double[] resabs = new double[1], defabs = new double[1], area1 = new double[1],
+ error1 = new double[1], defab1 = new double[1], defab2 = new double[1],
+ area2 = new double[1], error2 = new double[1], errmax = new double[1],
+ reseps = new double[1], abseps = new double[1];
+ final double[] alist = new double[limit];
+ final double[] blist = new double[limit];
+ final double[] elist = new double[limit];
+ final double[] res3la = new double[3];
+ final double[] rlist = new double[limit];
+ final double[] rlist2 = new double[52];
+ final double[][] valp = new double[limit][21];
+ final double[][] valn = new double[limit][21];
+ final double[] vp1 = new double[21];
+ final double[] vp2 = new double[21];
+ final double[] vn1 = new double[21];
+ final double[] vn2 = new double[21];
+ final int[] iord = new int[limit];
+ final int[] lp = new int[limit];
+ final int[] ln = new int[limit];
+
+ // MACHINE DEPENDENT CONSTANTS
+ epmach = Constants.EPSILON;
+ uflow = Double.MIN_VALUE;
+ oflow = Double.MAX_VALUE;
+
+ // TEST ON VALIDITY OF parameterS
+ last[0] = 0;
+ result[0] = abserr[0] = 0.0;
+ alist[1 - 1] = a;
+ blist[1 - 1] = b;
+ rlist[1 - 1] = elist[1 - 1] = 0.0;
+ ier[0] = 6;
+ if (epsabs < 0.0 || epsrel < 0.0) {
+ return;
}
+ ier[0] = 0;
+ rerr = Math.max(epsrel, 50.0 * epmach);
+ fev[0] = 0;
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
- return qxgs(f, a, b, myTol, myRelTol, myMaxEvals);
+ // FIRST APPROXIMATION TO THE INTEGRAL
+ ierro = 0;
+ lp[1 - 1] = ln[1 - 1] = 1;
+ valp[1 - 1][1 - 1] = f.applyAsDouble((a + b) * 0.5);
+ ++fev[0];
+ valn[1 - 1][1 - 1] = valp[1 - 1][1 - 1];
+ qxlqm(f, a, b, result, abserr, resabs, defabs, valp[1 - 1], valn[1 - 1], lp, ln, 2, epmach,
+ uflow, oflow, fev);
+
+ // TEST ON ACCURACY.
+ dres = Math.abs(result[0]);
+ errbnd = Math.max(epsabs, rerr * dres);
+ last[0] = 1;
+ rlist[1 - 1] = result[0];
+ elist[1 - 1] = abserr[0];
+ iord[1 - 1] = 1;
+ if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
+ ier[0] = 2;
}
-
- @Override
- public final String getName() {
- return "RMS Rule";
+ if (limit == 1) {
+ ier[0] = 1;
}
-
- private final QuadratureResult qxgs(final DoubleUnaryOperator f, final double a, final double b,
- final double epsabs, final double epsrel, final int limit) {
-
- // prepare variables
- final int[] ier = new int[1];
- final double[] result = new double[1];
- final double[] abserr = new double[1];
- final int[] last = new int[1];
- final int[] fev = new int[1];
-
- // call main subroutine
- qxgs(f, a, b, epsabs, epsrel, result, abserr, ier, limit, last, fev);
- return new QuadratureResult(result[0], abserr[0], fev[0], ier[0] == 0);
+ if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || (abserr[0] == 0.0)) {
+ return;
}
- private static void qxgs(final DoubleUnaryOperator f, final double a, final double b,
- final double epsabs, final double epsrel, final double[] result, final double[] abserr, final int[] ier,
- final int limit, final int[] last, final int[] fev) {
- ier[0] = 6;
- last[0] = 0;
- result[0] = abserr[0] = 0.0;
- fev[0] = 0;
- if (limit < 1) {
- return;
- }
-
- // PREPARE CALL FOR QXGSE.
- qxgse1(f, a, b, epsabs, epsrel, limit, result, abserr, ier, last, fev);
+ // INITIALIZATION
+ rlist2[1 - 1] = result[0];
+ errmax[0] = abserr[0];
+ maxerr[0] = 1;
+ area = result[0];
+ errsum = abserr[0];
+ abserr[0] = oflow;
+ nrmax[0] = 1;
+ nres[0] = 0;
+ numrl2[0] = 2;
+ ktmin = 0;
+ extrap = noext = false;
+ iroff1 = iroff2 = iroff3 = 0;
+ ksgn = -1;
+ if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
+ ksgn = 1;
}
-
- private static void qxgse1(final DoubleUnaryOperator f, final double a, final double b,
- final double epsabs, final double epsrel, final int limit, final double[] result, final double[] abserr,
- final int[] ier, final int[] last, final int[] fev) {
-
- // THE ROUTINE CALCULATES AN APPROXIMATION RESULT TO A
- // DEFINITE INTEGRAL I = INTEGRAL OF F OVER (A,B),
- // HOPEFULLY SATISFYING FOLLOWING CLAIM FOR ACCURACY
- // ABS(I-RESULT).LE.MAX(EPSABS,EPSREL*ABS(I)).
- boolean extrap, noext;
- int id, ierro, iroff1, iroff2, iroff3, jupbnd, k, ksgn, ktmin;
- double area, area12, a1, a2, b1, b2, correc = 0.0, dres, epmach, erlarg = 0.0, erlast, errbnd, erro12, errsum,
- ertest = 0.0, oflow, rerr, small = 0.0, t, uflow;
- final int[] ln1 = new int[1], lp1 = new int[1], ln2 = new int[1], lp2 = new int[1], maxerr = new int[1],
- nrmax = new int[1], numrl2 = new int[1], nres = new int[1];
- final double[] resabs = new double[1], defabs = new double[1], area1 = new double[1], error1 = new double[1],
- defab1 = new double[1], defab2 = new double[1], area2 = new double[1], error2 = new double[1],
- errmax = new double[1], reseps = new double[1], abseps = new double[1];
- final double[] alist = new double[limit];
- final double[] blist = new double[limit];
- final double[] elist = new double[limit];
- final double[] res3la = new double[3];
- final double[] rlist = new double[limit];
- final double[] rlist2 = new double[52];
- final double[][] valp = new double[limit][21];
- final double[][] valn = new double[limit][21];
- final double[] vp1 = new double[21];
- final double[] vp2 = new double[21];
- final double[] vn1 = new double[21];
- final double[] vn2 = new double[21];
- final int[] iord = new int[limit];
- final int[] lp = new int[limit];
- final int[] ln = new int[limit];
-
- // MACHINE DEPENDENT CONSTANTS
- epmach = Constants.EPSILON;
- uflow = Double.MIN_VALUE;
- oflow = Double.MAX_VALUE;
-
- // TEST ON VALIDITY OF parameterS
- last[0] = 0;
- result[0] = abserr[0] = 0.0;
- alist[1 - 1] = a;
- blist[1 - 1] = b;
- rlist[1 - 1] = elist[1 - 1] = 0.0;
- ier[0] = 6;
- if (epsabs < 0.0 || epsrel < 0.0) {
- return;
- }
- ier[0] = 0;
- rerr = Math.max(epsrel, 50.0 * epmach);
- fev[0] = 0;
-
- // FIRST APPROXIMATION TO THE INTEGRAL
- ierro = 0;
- lp[1 - 1] = ln[1 - 1] = 1;
- valp[1 - 1][1 - 1] = f.applyAsDouble((a + b) * 0.5);
- ++fev[0];
- valn[1 - 1][1 - 1] = valp[1 - 1][1 - 1];
- qxlqm(f, a, b, result, abserr, resabs, defabs, valp[1 - 1], valn[1 - 1], lp, ln, 2, epmach, uflow, oflow, fev);
-
- // TEST ON ACCURACY.
- dres = Math.abs(result[0]);
- errbnd = Math.max(epsabs, rerr * dres);
- last[0] = 1;
- rlist[1 - 1] = result[0];
- elist[1 - 1] = abserr[0];
- iord[1 - 1] = 1;
- if (abserr[0] <= 100.0 * epmach * defabs[0] && abserr[0] > errbnd) {
- ier[0] = 2;
- }
- if (limit == 1) {
- ier[0] = 1;
- }
- if (ier[0] != 0 || (abserr[0] <= errbnd && abserr[0] != resabs[0]) || (abserr[0] == 0.0)) {
- return;
- }
-
- // INITIALIZATION
- rlist2[1 - 1] = result[0];
- errmax[0] = abserr[0];
- maxerr[0] = 1;
- area = result[0];
- errsum = abserr[0];
- abserr[0] = oflow;
- nrmax[0] = 1;
- nres[0] = 0;
- numrl2[0] = 2;
- ktmin = 0;
- extrap = noext = false;
- iroff1 = iroff2 = iroff3 = 0;
- ksgn = -1;
- if (dres >= (1.0 - 50.0 * epmach) * defabs[0]) {
- ksgn = 1;
- }
- t = 1.0 + 100.0 * epmach;
-
- // MAIN DO-LOOP
- int exit = 100;
- for (last[0] = 2; last[0] <= limit; ++last[0]) {
-
- // BISECT THE SUBINTERVAL WITH THE NRMAX-TH LARGEST ERROR ESTIMATE.
- a1 = alist[maxerr[0] - 1];
- b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
- a2 = b1;
- b2 = blist[maxerr[0] - 1];
- erlast = errmax[0];
- qxrrd(f, valn[maxerr[0] - 1], ln[maxerr[0] - 1], b1, a1, vn1, vp1, ln1, lp1, fev);
- qxlqm(f, a1, b1, area1, error1, resabs, defab1, vp1, vn1, lp1, ln1, 2, epmach, uflow, oflow, fev);
- qxrrd(f, valp[maxerr[0] - 1], lp[maxerr[0] - 1], a2, b2, vp2, vn2, lp2, ln2, fev);
- qxlqm(f, a2, b2, area2, error2, resabs, defab2, vp2, vn2, lp2, ln2, 2, epmach, uflow, oflow, fev);
-
- // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL
- // AND ERROR AND TEST FOR ACCURACY.
- area12 = area1[0] + area2[0];
- erro12 = error1[0] + error2[0];
- errsum = errsum + erro12 - errmax[0];
- area = area + area12 - rlist[maxerr[0] - 1];
- if (defab1[0] == error1[0] || defab2[0] == error2[0]) {
- } else {
- if (Math.abs(rlist[maxerr[0] - 1] - area12) > 0.1e-4 * Math.abs(area12) || erro12 < 0.99 * errmax[0]) {
- } else {
- if (extrap) {
- ++iroff2;
- }
- if (!extrap) {
- ++iroff1;
- }
- }
- if (last[0] > 10 && erro12 > errmax[0]) {
- ++iroff3;
- }
- }
- rlist[maxerr[0] - 1] = area1[0];
- rlist[last[0] - 1] = area2[0];
- errbnd = Math.max(epsabs, rerr * Math.abs(area));
-
- // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG.
- if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
- ier[0] = 2;
- }
- if (iroff2 >= 5) {
- ierro = 3;
- }
-
- // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF SUBINTERVALS
- // EQUALS LIMIT.
- if (last[0] == limit) {
- ier[0] = 1;
- }
-
- // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
- // AT A POINT OF THE INTEGRATION RANGE.
- if (Math.max(Math.abs(a1), Math.abs(b2)) <= t * (Math.abs(a2) + 1.0e3 * uflow)) {
- ier[0] = 4;
- }
-
- // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST.
- if (error2[0] > error1[0]) {
- alist[maxerr[0] - 1] = a2;
- alist[last[0] - 1] = a1;
- blist[last[0] - 1] = b1;
- rlist[maxerr[0] - 1] = area2[0];
- rlist[last[0] - 1] = area1[0];
- elist[maxerr[0] - 1] = error2[0];
- elist[last[0] - 1] = error1[0];
- qxcpy(valp[maxerr[0] - 1], vp2, lp2[0]);
- lp[maxerr[0] - 1] = lp2[0];
- qxcpy(valn[maxerr[0] - 1], vn2, ln2[0]);
- ln[maxerr[0] - 1] = ln2[0];
- qxcpy(valp[last[0] - 1], vp1, lp1[0]);
- lp[last[0] - 1] = lp1[0];
- qxcpy(valn[last[0] - 1], vn1, ln1[0]);
- ln[last[0] - 1] = ln1[0];
- } else {
- alist[last[0] - 1] = a2;
- blist[maxerr[0] - 1] = b1;
- blist[last[0] - 1] = b2;
- elist[maxerr[0] - 1] = error1[0];
- elist[last[0] - 1] = error2[0];
- qxcpy(valp[maxerr[0] - 1], vp1, lp1[0]);
- lp[maxerr[0] - 1] = lp1[0];
- qxcpy(valn[maxerr[0] - 1], vn1, ln1[0]);
- ln[maxerr[0] - 1] = ln1[0];
- qxcpy(valp[last[0] - 1], vp2, lp2[0]);
- lp[last[0] - 1] = lp2[0];
- qxcpy(valn[last[0] - 1], vn2, ln2[0]);
- ln[last[0] - 1] = ln2[0];
- }
-
- // 30: CALL subroutine QPSRT TO MAINTAIN THE DESCENDING ORDERING
- // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
- // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT).
- qpsrt(limit, last, maxerr, errmax, elist, iord, nrmax);
- if (errsum <= errbnd) {
- exit = 115;
- break;
- }
- if (ier[0] != 0) {
- break;
- }
- if (last[0] == 2) {
- small = Math.abs(b - a) * 0.375;
- erlarg = errsum;
- ertest = errbnd;
- rlist2[2 - 1] = area;
- continue;
- }
- if (noext) {
- continue;
- }
- erlarg -= erlast;
- if (Math.abs(b1 - a1) > small) {
- erlarg += erro12;
- }
- if (extrap) {
- } else {
-
- // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT
- // IS THE SMALLEST INTERVAL.
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- continue;
- }
- extrap = true;
- nrmax[0] = 2;
- }
-
- // 40: THE BOUND 0.3*ERTEST HAS BEEN INTRODUCED TO PERFORM A
- // MORE CAUTIOUS EXTRAPOLATION THAN IN THE ORIGINAL DQAGSE R(out)INE
- if (ierro == 3 || erlarg <= 0.3 * ertest) {
- } else {
-
- // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
- // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
- // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION.
- id = nrmax[0];
- jupbnd = last[0];
- if (last[0] > (2 + (limit >> 1))) {
- jupbnd = limit + 3 - last[0];
- }
- for (k = id; k <= jupbnd; ++k) {
- maxerr[0] = iord[nrmax[0] - 1];
- errmax[0] = elist[maxerr[0] - 1];
- if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
- continue;
- }
- ++nrmax[0];
- }
- }
-
- // 60: PERFORM EXTRAPOLATION.
- ++numrl2[0];
- rlist2[numrl2[0] - 1] = area;
- qelg(numrl2, rlist2, reseps, abseps, res3la, nres, epmach, oflow);
- ++ktmin;
- if (ktmin > 5 && abserr[0] < 0.1e-2 * errsum) {
- ier[0] = 5;
- }
- if (abseps[0] >= abserr[0]) {
- } else {
- ktmin = 0;
- abserr[0] = abseps[0];
- result[0] = reseps[0];
- correc = erlarg;
- ertest = Math.max(epsabs, rerr * Math.abs(reseps[0]));
- if (abserr[0] <= ertest) {
- break;
- }
- }
-
- // 70: PREPARE BISECTION OF THE SMALLEST INTERVAL.
- if (numrl2[0] == 1) {
- noext = true;
- }
- if (ier[0] == 5) {
- break;
- }
- maxerr[0] = iord[1 - 1];
- errmax[0] = elist[maxerr[0] - 1];
- nrmax[0] = 1;
- extrap = false;
- small *= 0.5;
- erlarg = errsum;
- }
-
- if (exit == 100) {
-
- // 100: SET FINAL RESULT AND ERROR ESTIMATE.
- if (abserr[0] == oflow) {
- exit = 115;
- } else if (ier[0] + ierro == 0) {
- exit = 110;
- } else {
- if (ierro == 3) {
- abserr[0] += correc;
- }
- if (ier[0] == 0) {
- ier[0] = 3;
- }
- if (result[0] != 0.0 && area != 0.0) {
- if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
- exit = 115;
- } else {
- exit = 110;
- }
- } else if (abserr[0] > errsum) {
- exit = 115;
- } else {
- if (area == 0.0) {
- if (ier[0] > 2) {
- --ier[0];
- }
- return;
- }
- exit = 110;
- }
- }
- }
-
- if (exit == 110) {
-
- // 110: TEST ON DIVERGENCE.
- if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.1e-1) {
- } else if (0.1e-1 > (result[0] / area) || (result[0] / area) > 0.1e3 || errsum > Math.abs(area)) {
- ier[0] = 6;
- }
- if (ier[0] > 2) {
- --ier[0];
- }
- } else {
-
- // 115: COMPUTE GLOBAL INTEGRAL SUM.
- result[0] = 0.0;
- for (int ii = 1; ii <= last[0]; ++ii) {
- result[0] += rlist[ii - 1];
- }
- abserr[0] = errsum;
- if (ier[0] > 2) {
- --ier[0];
- }
- }
+ t = 1.0 + 100.0 * epmach;
+
+ // MAIN DO-LOOP
+ int exit = 100;
+ for (last[0] = 2; last[0] <= limit; ++last[0]) {
+
+ // BISECT THE SUBINTERVAL WITH THE NRMAX-TH LARGEST ERROR ESTIMATE.
+ a1 = alist[maxerr[0] - 1];
+ b1 = 0.5 * (alist[maxerr[0] - 1] + blist[maxerr[0] - 1]);
+ a2 = b1;
+ b2 = blist[maxerr[0] - 1];
+ erlast = errmax[0];
+ qxrrd(f, valn[maxerr[0] - 1], ln[maxerr[0] - 1], b1, a1, vn1, vp1, ln1, lp1, fev);
+ qxlqm(f, a1, b1, area1, error1, resabs, defab1, vp1, vn1, lp1, ln1, 2, epmach, uflow, oflow,
+ fev);
+ qxrrd(f, valp[maxerr[0] - 1], lp[maxerr[0] - 1], a2, b2, vp2, vn2, lp2, ln2, fev);
+ qxlqm(f, a2, b2, area2, error2, resabs, defab2, vp2, vn2, lp2, ln2, 2, epmach, uflow, oflow,
+ fev);
+
+ // IMPROVE PREVIOUS APPROXIMATIONS TO INTEGRAL
+ // AND ERROR AND TEST FOR ACCURACY.
+ area12 = area1[0] + area2[0];
+ erro12 = error1[0] + error2[0];
+ errsum = errsum + erro12 - errmax[0];
+ area = area + area12 - rlist[maxerr[0] - 1];
+ if (defab1[0] == error1[0] || defab2[0] == error2[0]) {
+ } else {
+ if (Math.abs(rlist[maxerr[0] - 1] - area12) > 0.1e-4 * Math.abs(area12)
+ || erro12 < 0.99 * errmax[0]) {
+ } else {
+ if (extrap) {
+ ++iroff2;
+ }
+ if (!extrap) {
+ ++iroff1;
+ }
+ }
+ if (last[0] > 10 && erro12 > errmax[0]) {
+ ++iroff3;
+ }
+ }
+ rlist[maxerr[0] - 1] = area1[0];
+ rlist[last[0] - 1] = area2[0];
+ errbnd = Math.max(epsabs, rerr * Math.abs(area));
+
+ // TEST FOR ROUNDOFF ERROR AND EVENTUALLY SET ERROR FLAG.
+ if (iroff1 + iroff2 >= 10 || iroff3 >= 20) {
+ ier[0] = 2;
+ }
+ if (iroff2 >= 5) {
+ ierro = 3;
+ }
+
+ // SET ERROR FLAG IN THE CASE THAT THE NUMBER OF SUBINTERVALS
+ // EQUALS LIMIT.
+ if (last[0] == limit) {
+ ier[0] = 1;
+ }
+
+ // SET ERROR FLAG IN THE CASE OF BAD INTEGRAND BEHAVIOUR
+ // AT A POINT OF THE INTEGRATION RANGE.
+ if (Math.max(Math.abs(a1), Math.abs(b2)) <= t * (Math.abs(a2) + 1.0e3 * uflow)) {
+ ier[0] = 4;
+ }
+
+ // APPEND THE NEWLY-CREATED INTERVALS TO THE LIST.
+ if (error2[0] > error1[0]) {
+ alist[maxerr[0] - 1] = a2;
+ alist[last[0] - 1] = a1;
+ blist[last[0] - 1] = b1;
+ rlist[maxerr[0] - 1] = area2[0];
+ rlist[last[0] - 1] = area1[0];
+ elist[maxerr[0] - 1] = error2[0];
+ elist[last[0] - 1] = error1[0];
+ qxcpy(valp[maxerr[0] - 1], vp2, lp2[0]);
+ lp[maxerr[0] - 1] = lp2[0];
+ qxcpy(valn[maxerr[0] - 1], vn2, ln2[0]);
+ ln[maxerr[0] - 1] = ln2[0];
+ qxcpy(valp[last[0] - 1], vp1, lp1[0]);
+ lp[last[0] - 1] = lp1[0];
+ qxcpy(valn[last[0] - 1], vn1, ln1[0]);
+ ln[last[0] - 1] = ln1[0];
+ } else {
+ alist[last[0] - 1] = a2;
+ blist[maxerr[0] - 1] = b1;
+ blist[last[0] - 1] = b2;
+ elist[maxerr[0] - 1] = error1[0];
+ elist[last[0] - 1] = error2[0];
+ qxcpy(valp[maxerr[0] - 1], vp1, lp1[0]);
+ lp[maxerr[0] - 1] = lp1[0];
+ qxcpy(valn[maxerr[0] - 1], vn1, ln1[0]);
+ ln[maxerr[0] - 1] = ln1[0];
+ qxcpy(valp[last[0] - 1], vp2, lp2[0]);
+ lp[last[0] - 1] = lp2[0];
+ qxcpy(valn[last[0] - 1], vn2, ln2[0]);
+ ln[last[0] - 1] = ln2[0];
+ }
+
+ // 30: CALL subroutine QPSRT TO MAINTAIN THE DESCENDING ORDERING
+ // IN THE LIST OF ERROR ESTIMATES AND SELECT THE SUBINTERVAL
+ // WITH NRMAX-TH LARGEST ERROR ESTIMATE (TO BE BISECTED NEXT).
+ qpsrt(limit, last, maxerr, errmax, elist, iord, nrmax);
+ if (errsum <= errbnd) {
+ exit = 115;
+ break;
+ }
+ if (ier[0] != 0) {
+ break;
+ }
+ if (last[0] == 2) {
+ small = Math.abs(b - a) * 0.375;
+ erlarg = errsum;
+ ertest = errbnd;
+ rlist2[2 - 1] = area;
+ continue;
+ }
+ if (noext) {
+ continue;
+ }
+ erlarg -= erlast;
+ if (Math.abs(b1 - a1) > small) {
+ erlarg += erro12;
+ }
+ if (extrap) {
+ } else {
+
+ // TEST WHETHER THE INTERVAL TO BE BISECTED NEXT
+ // IS THE SMALLEST INTERVAL.
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ continue;
+ }
+ extrap = true;
+ nrmax[0] = 2;
+ }
+
+ // 40: THE BOUND 0.3*ERTEST HAS BEEN INTRODUCED TO PERFORM A
+ // MORE CAUTIOUS EXTRAPOLATION THAN IN THE ORIGINAL DQAGSE R(out)INE
+ if (ierro == 3 || erlarg <= 0.3 * ertest) {
+ } else {
+
+ // THE SMALLEST INTERVAL HAS THE LARGEST ERROR.
+ // BEFORE BISECTING DECREASE THE SUM OF THE ERRORS OVER THE
+ // LARGER INTERVALS (ERLARG) AND PERFORM EXTRAPOLATION.
+ id = nrmax[0];
+ jupbnd = last[0];
+ if (last[0] > (2 + (limit >> 1))) {
+ jupbnd = limit + 3 - last[0];
+ }
+ for (k = id; k <= jupbnd; ++k) {
+ maxerr[0] = iord[nrmax[0] - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ if (Math.abs(blist[maxerr[0] - 1] - alist[maxerr[0] - 1]) > small) {
+ continue;
+ }
+ ++nrmax[0];
+ }
+ }
+
+ // 60: PERFORM EXTRAPOLATION.
+ ++numrl2[0];
+ rlist2[numrl2[0] - 1] = area;
+ qelg(numrl2, rlist2, reseps, abseps, res3la, nres, epmach, oflow);
+ ++ktmin;
+ if (ktmin > 5 && abserr[0] < 0.1e-2 * errsum) {
+ ier[0] = 5;
+ }
+ if (abseps[0] >= abserr[0]) {
+ } else {
+ ktmin = 0;
+ abserr[0] = abseps[0];
+ result[0] = reseps[0];
+ correc = erlarg;
+ ertest = Math.max(epsabs, rerr * Math.abs(reseps[0]));
+ if (abserr[0] <= ertest) {
+ break;
+ }
+ }
+
+ // 70: PREPARE BISECTION OF THE SMALLEST INTERVAL.
+ if (numrl2[0] == 1) {
+ noext = true;
+ }
+ if (ier[0] == 5) {
+ break;
+ }
+ maxerr[0] = iord[1 - 1];
+ errmax[0] = elist[maxerr[0] - 1];
+ nrmax[0] = 1;
+ extrap = false;
+ small *= 0.5;
+ erlarg = errsum;
}
- private static void qxlqm(final DoubleUnaryOperator f, final double a, final double b,
- final double[] result, final double[] abserr, final double[] resabs, final double[] resasc,
- final double[] vr, final double[] vs, final int[] lr, final int[] ls, final int key, final double epmach,
- final double uflow, final double oflow, final int[] fev) {
-
- // TO COMPUTE I = INTEGRAL OF F OVER (A, B), WITH ERROR ESTIMATE
- // J = INTEGRAL OF ABS(F) OVER (A,B)
- final double[] resg = new double[1];
- final double[] resk = new double[1];
- double t, errold;
- int k, k0, k1, k2, key1;
-
- key1 = Math.max(key, 0);
- key1 = Math.min(key1, 4);
- k0 = Math.max(key1 - 2, 0);
- k1 = k0 + 1;
- k2 = Math.min(key1 + 1, 3);
- qxrul(f, a, b, resg, resabs, resasc, k0, k1, vr, vs, lr, ls, fev);
- errold = oflow;
- t = 10.0 * epmach;
- for (k = k1; k <= k2; ++k) {
- qxrul(f, a, b, resk, resabs, resasc, k, k1, vr, vs, lr, ls, fev);
- result[0] = resk[0];
- abserr[0] = Math.abs(resk[0] - resg[0]);
- if (resasc[0] != 0.0 && abserr[0] != 0.0) {
- abserr[0] = resasc[0] * Math.min(1.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
- }
- if (resabs[0] > uflow / t) {
- abserr[0] = Math.max(t * resabs[0], abserr[0]);
- }
- resg[0] = resk[0];
- if (abserr[0] > errold * 0.16) {
- break;
- }
- if (abserr[0] < 1000.0 * epmach * resabs[0]) {
- continue;
- }
- errold = abserr[0];
- }
+ if (exit == 100) {
+
+ // 100: SET FINAL RESULT AND ERROR ESTIMATE.
+ if (abserr[0] == oflow) {
+ exit = 115;
+ } else if (ier[0] + ierro == 0) {
+ exit = 110;
+ } else {
+ if (ierro == 3) {
+ abserr[0] += correc;
+ }
+ if (ier[0] == 0) {
+ ier[0] = 3;
+ }
+ if (result[0] != 0.0 && area != 0.0) {
+ if (abserr[0] / Math.abs(result[0]) > errsum / Math.abs(area)) {
+ exit = 115;
+ } else {
+ exit = 110;
+ }
+ } else if (abserr[0] > errsum) {
+ exit = 115;
+ } else {
+ if (area == 0.0) {
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ return;
+ }
+ exit = 110;
+ }
+ }
}
- private static void qxrul(final DoubleUnaryOperator f, final double xl, final double xu,
- final double[] y, final double[] ya, final double[] ym, final int ke, final int k1, final double[] fv1,
- final double[] fv2, final int[] l1, final int[] l2, final int[] fev) {
-
- // TO COMPUTE I = INTEGRAL OF F OVER (A,B), WITH ERROR ESTIMATE
- // AND CONDITIONALLY COMPUTE J = INTEGRAL OF ABS(F) OVER (A,B)
- // BY USING AN RMS RULE
- double ldl, y2, aa, bb, c;
- int j, i, is, k, ks;
-
- k = ke + 1;
- is = istart[k - 1];
- ks = length[k - 1];
- ldl = xu - xl;
- bb = ldl * 0.5;
- aa = xl + bb;
- y[0] = 0.0;
- for (i = 1; i <= ks; ++i) {
- c = bb * xx[i - 1];
- if (i > l1[0]) {
- fv1[i - 1] = f.applyAsDouble(aa + c);
- ++fev[0];
- if (aa + c >= xu && !Double.isFinite(fv1[i - 1])) {
- fv1[i - 1] = 0.0;
- }
- }
- if (i > l2[0]) {
- fv2[i - 1] = f.applyAsDouble(aa - c);
- ++fev[0];
- if (aa - c <= xl && !Double.isFinite(fv2[i - 1])) {
- fv2[i - 1] = 0.0;
- }
- }
- j = is + i;
- y[0] += (fv1[i - 1] + fv2[i - 1]) * ww[j - 1];
- }
- y2 = y[0];
- y[0] *= bb;
- if (l1[0] < ks) {
- l1[0] = ks;
- }
- if (l2[0] < ks) {
- l2[0] = ks;
- }
- if (ke != k1) {
- return;
- }
- ya[0] = 0.0;
- for (i = 1; i <= ks; ++i) {
- j = is + i;
- ya[0] += (Math.abs(fv1[i - 1]) + Math.abs(fv2[i - 1])) * ww[j - 1];
- }
- ya[0] *= Math.abs(bb);
- y2 *= 0.5;
- ym[0] = 0.0;
- for (i = 1; i <= ks; ++i) {
- j = is + i;
- ym[0] += (Math.abs(fv1[i - 1] - y2) + Math.abs(fv2[i - 1] - y2)) * ww[j - 1];
- }
- ym[0] *= Math.abs(bb);
+ if (exit == 110) {
+
+ // 110: TEST ON DIVERGENCE.
+ if (ksgn == -1 && Math.max(Math.abs(result[0]), Math.abs(area)) <= defabs[0] * 0.1e-1) {
+ } else if (0.1e-1 > (result[0] / area) || (result[0] / area) > 0.1e3
+ || errsum > Math.abs(area)) {
+ ier[0] = 6;
+ }
+ if (ier[0] > 2) {
+ --ier[0];
+ }
+ } else {
+
+ // 115: COMPUTE GLOBAL INTEGRAL SUM.
+ result[0] = 0.0;
+ for (int ii = 1; ii <= last[0]; ++ii) {
+ result[0] += rlist[ii - 1];
+ }
+ abserr[0] = errsum;
+ if (ier[0] > 2) {
+ --ier[0];
+ }
}
-
- private static void qxrrd(final DoubleUnaryOperator f, final double[] z, final int lz,
- final double xl,
- final double xu, final double[] r, final double[] s, final int[] lr, final int[] ls, final int[] fev) {
-
- // TO REORDER THE COMPUTED FUNCTIONAL VALUES BEFORE THE BISECTION
- // OF AN INTERVAL
- final double dlen = 0.5 * (xu - xl);
- final double centr = xl + dlen;
- r[1 - 1] = z[3 - 1];
- r[2 - 1] = z[9 - 1];
- r[3 - 1] = z[4 - 1];
- r[4 - 1] = z[5 - 1];
- r[5 - 1] = z[6 - 1];
- r[6 - 1] = z[10 - 1];
- r[7 - 1] = z[7 - 1];
- s[1 - 1] = z[3 - 1];
- s[2 - 1] = z[8 - 1];
- s[3 - 1] = z[2 - 1];
- s[7 - 1] = z[1 - 1];
- if (lz <= 11) {
+ }
+
+ private static void qxlqm(final DoubleUnaryOperator f, final double a, final double b,
+ final double[] result, final double[] abserr, final double[] resabs, final double[] resasc,
+ final double[] vr, final double[] vs, final int[] lr, final int[] ls, final int key,
+ final double epmach, final double uflow, final double oflow, final int[] fev) {
+
+ // TO COMPUTE I = INTEGRAL OF F OVER (A, B), WITH ERROR ESTIMATE
+ // J = INTEGRAL OF ABS(F) OVER (A,B)
+ final double[] resg = new double[1];
+ final double[] resk = new double[1];
+ double t, errold;
+ int k, k0, k1, k2, key1;
+
+ key1 = Math.max(key, 0);
+ key1 = Math.min(key1, 4);
+ k0 = Math.max(key1 - 2, 0);
+ k1 = k0 + 1;
+ k2 = Math.min(key1 + 1, 3);
+ qxrul(f, a, b, resg, resabs, resasc, k0, k1, vr, vs, lr, ls, fev);
+ errold = oflow;
+ t = 10.0 * epmach;
+ for (k = k1; k <= k2; ++k) {
+ qxrul(f, a, b, resk, resabs, resasc, k, k1, vr, vs, lr, ls, fev);
+ result[0] = resk[0];
+ abserr[0] = Math.abs(resk[0] - resg[0]);
+ if (resasc[0] != 0.0 && abserr[0] != 0.0) {
+ abserr[0] = resasc[0] * Math.min(1.0, Math.pow(200.0 * abserr[0] / resasc[0], 1.5));
+ }
+ if (resabs[0] > uflow / t) {
+ abserr[0] = Math.max(t * resabs[0], abserr[0]);
+ }
+ resg[0] = resk[0];
+ if (abserr[0] > errold * 0.16) {
+ break;
+ }
+ if (abserr[0] < 1000.0 * epmach * resabs[0]) {
+ continue;
+ }
+ errold = abserr[0];
+ }
+ }
+
+ private static void qxrul(final DoubleUnaryOperator f, final double xl, final double xu,
+ final double[] y, final double[] ya, final double[] ym, final int ke, final int k1,
+ final double[] fv1, final double[] fv2, final int[] l1, final int[] l2, final int[] fev) {
+
+ // TO COMPUTE I = INTEGRAL OF F OVER (A,B), WITH ERROR ESTIMATE
+ // AND CONDITIONALLY COMPUTE J = INTEGRAL OF ABS(F) OVER (A,B)
+ // BY USING AN RMS RULE
+ double ldl, y2, aa, bb, c;
+ int j, i, is, k, ks;
+
+ k = ke + 1;
+ is = istart[k - 1];
+ ks = length[k - 1];
+ ldl = xu - xl;
+ bb = ldl * 0.5;
+ aa = xl + bb;
+ y[0] = 0.0;
+ for (i = 1; i <= ks; ++i) {
+ c = bb * xx[i - 1];
+ if (i > l1[0]) {
+ fv1[i - 1] = f.applyAsDouble(aa + c);
+ ++fev[0];
+ if (aa + c >= xu && !Double.isFinite(fv1[i - 1])) {
+ fv1[i - 1] = 0.0;
+ }
+ }
+ if (i > l2[0]) {
+ fv2[i - 1] = f.applyAsDouble(aa - c);
+ ++fev[0];
+ if (aa - c <= xl && !Double.isFinite(fv2[i - 1])) {
+ fv2[i - 1] = 0.0;
+ }
+ }
+ j = is + i;
+ y[0] += (fv1[i - 1] + fv2[i - 1]) * ww[j - 1];
+ }
+ y2 = y[0];
+ y[0] *= bb;
+ if (l1[0] < ks) {
+ l1[0] = ks;
+ }
+ if (l2[0] < ks) {
+ l2[0] = ks;
+ }
+ if (ke != k1) {
+ return;
+ }
+ ya[0] = 0.0;
+ for (i = 1; i <= ks; ++i) {
+ j = is + i;
+ ya[0] += (Math.abs(fv1[i - 1]) + Math.abs(fv2[i - 1])) * ww[j - 1];
+ }
+ ya[0] *= Math.abs(bb);
+ y2 *= 0.5;
+ ym[0] = 0.0;
+ for (i = 1; i <= ks; ++i) {
+ j = is + i;
+ ym[0] += (Math.abs(fv1[i - 1] - y2) + Math.abs(fv2[i - 1] - y2)) * ww[j - 1];
+ }
+ ym[0] *= Math.abs(bb);
+ }
+
+ private static void qxrrd(final DoubleUnaryOperator f, final double[] z, final int lz,
+ final double xl, final double xu, final double[] r, final double[] s, final int[] lr,
+ final int[] ls, final int[] fev) {
+
+ // TO REORDER THE COMPUTED FUNCTIONAL VALUES BEFORE THE BISECTION
+ // OF AN INTERVAL
+ final double dlen = 0.5 * (xu - xl);
+ final double centr = xl + dlen;
+ r[1 - 1] = z[3 - 1];
+ r[2 - 1] = z[9 - 1];
+ r[3 - 1] = z[4 - 1];
+ r[4 - 1] = z[5 - 1];
+ r[5 - 1] = z[6 - 1];
+ r[6 - 1] = z[10 - 1];
+ r[7 - 1] = z[7 - 1];
+ s[1 - 1] = z[3 - 1];
+ s[2 - 1] = z[8 - 1];
+ s[3 - 1] = z[2 - 1];
+ s[7 - 1] = z[1 - 1];
+ if (lz <= 11) {
r[8 - 1] = f.applyAsDouble(centr + 0.375 * dlen);
r[9 - 1] = f.applyAsDouble(centr + 0.625 * dlen);
r[10 - 1] = f.applyAsDouble(centr + 0.96875 * dlen);
- fev[0] += 3;
- lr[0] = 10;
- if (lz != 11) {
- s[4 - 1] = f.applyAsDouble(centr - dlen * 0.75);
- ++fev[0];
- }
- if (lz == 11) {
- s[4 - 1] = z[11 - 1];
- }
- s[5 - 1] = f.applyAsDouble(centr - dlen * 0.875);
- s[6 - 1] = f.applyAsDouble(centr - dlen * 0.9375);
- s[8 - 1] = f.applyAsDouble(centr - dlen * 0.375);
- s[9 - 1] = f.applyAsDouble(centr - dlen * 0.625);
- s[10 - 1] = f.applyAsDouble(centr - dlen * 0.96875);
- fev[0] += 5;
- ls[0] = 10;
- return;
- }
- r[8 - 1] = z[12 - 1];
- r[9 - 1] = z[13 - 1];
- r[10 - 1] = z[14 - 1];
- lr[0] = 10;
- s[4 - 1] = z[11 - 1];
+ fev[0] += 3;
+ lr[0] = 10;
+ if (lz != 11) {
+ s[4 - 1] = f.applyAsDouble(centr - dlen * 0.75);
+ ++fev[0];
+ }
+ if (lz == 11) {
+ s[4 - 1] = z[11 - 1];
+ }
+ s[5 - 1] = f.applyAsDouble(centr - dlen * 0.875);
+ s[6 - 1] = f.applyAsDouble(centr - dlen * 0.9375);
+ s[8 - 1] = f.applyAsDouble(centr - dlen * 0.375);
+ s[9 - 1] = f.applyAsDouble(centr - dlen * 0.625);
+ s[10 - 1] = f.applyAsDouble(centr - dlen * 0.96875);
+ fev[0] += 5;
+ ls[0] = 10;
+ return;
+ }
+ r[8 - 1] = z[12 - 1];
+ r[9 - 1] = z[13 - 1];
+ r[10 - 1] = z[14 - 1];
+ lr[0] = 10;
+ s[4 - 1] = z[11 - 1];
s[5 - 1] = f.applyAsDouble(centr - dlen * 0.875);
s[6 - 1] = f.applyAsDouble(centr - dlen * 0.9375);
- fev[0] += 2;
- if (lz <= 14) {
+ fev[0] += 2;
+ if (lz <= 14) {
s[8 - 1] = f.applyAsDouble(centr - dlen * 0.375);
s[9 - 1] = f.applyAsDouble(centr - dlen * 0.625);
s[10 - 1] = f.applyAsDouble(centr - dlen * 0.96875);
- fev[0] += 3;
- ls[0] = 10;
- return;
- }
- r[11 - 1] = z[18 - 1];
- r[12 - 1] = z[19 - 1];
- r[13 - 1] = z[20 - 1];
- r[14 - 1] = z[21 - 1];
- lr[0] = 14;
- s[8 - 1] = z[16 - 1];
- s[9 - 1] = z[15 - 1];
+ fev[0] += 3;
+ ls[0] = 10;
+ return;
+ }
+ r[11 - 1] = z[18 - 1];
+ r[12 - 1] = z[19 - 1];
+ r[13 - 1] = z[20 - 1];
+ r[14 - 1] = z[21 - 1];
+ lr[0] = 14;
+ s[8 - 1] = z[16 - 1];
+ s[9 - 1] = z[15 - 1];
s[10 - 1] = f.applyAsDouble(centr - dlen * 0.96875);
- ++fev[0];
- s[11 - 1] = z[17 - 1];
- ls[0] = 11;
+ ++fev[0];
+ s[11 - 1] = z[17 - 1];
+ ls[0] = 11;
+ }
+
+ private static void qxcpy(final double[] a, final double[] b, final int l) {
+
+ // TO COPY THE REAL VECTOR B OF LENGTH L INTO THE REAL VECTOR A OF LENGTH L
+ System.arraycopy(b, 0, a, 0, l);
+ }
+
+ private static void qpsrt(final int limit, final int[] last, final int[] maxerr,
+ final double[] ermax, final double[] elist, final int[] iord, final int[] nrmax) {
+ double errmax, errmin;
+ int i, ibeg, ido, isucc, j, jbnd, jupbn, k;
+
+ // CHECK WHETHER THE LIST CONTAINS MORE THAN TWO ERROR ESTIMATES.
+ if (last[0] <= 2) {
+ iord[1 - 1] = 1;
+ iord[2 - 1] = 2;
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
}
- private static void qxcpy(final double[] a, final double[] b, final int l) {
-
- // TO COPY THE REAL VECTOR B OF LENGTH L INTO THE REAL VECTOR A OF LENGTH L
- System.arraycopy(b, 0, a, 0, l);
+ // 10: THIS PART OF THE ROUTINE IS ONLY EXECUTED IF,
+ // DUE TO A DIFFICULT INTEGRAND, SUBDIVISION INCREASED
+ // THE ERROR ESTIMATE. IN THE NORMAL CASE THE INSERT PROCEDURE
+ // SHOULD START AFTER THE NRMAX-TH LARGEST ERROR ESTIMATE.
+ errmax = elist[maxerr[0] - 1];
+ if (nrmax[0] != 1) {
+ ido = nrmax[0] - 1;
+ for (i = 1; i <= ido; ++i) {
+ isucc = iord[nrmax[0] - 1 - 1];
+ if (errmax <= elist[isucc - 1]) {
+ break;
+ }
+ iord[nrmax[0] - 1] = isucc;
+ --nrmax[0];
+ }
}
- private static void qpsrt(final int limit, final int[] last, final int[] maxerr, final double[] ermax,
- final double[] elist, final int[] iord, final int[] nrmax) {
- double errmax, errmin;
- int i, ibeg, ido, isucc, j, jbnd, jupbn, k;
-
- // CHECK WHETHER THE LIST CONTAINS MORE THAN TWO ERROR ESTIMATES.
- if (last[0] <= 2) {
- iord[1 - 1] = 1;
- iord[2 - 1] = 2;
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
-
- // 10: THIS PART OF THE ROUTINE IS ONLY EXECUTED IF,
- // DUE TO A DIFFICULT INTEGRAND, SUBDIVISION INCREASED
- // THE ERROR ESTIMATE. IN THE NORMAL CASE THE INSERT PROCEDURE
- // SHOULD START AFTER THE NRMAX-TH LARGEST ERROR ESTIMATE.
- errmax = elist[maxerr[0] - 1];
- if (nrmax[0] != 1) {
- ido = nrmax[0] - 1;
- for (i = 1; i <= ido; ++i) {
- isucc = iord[nrmax[0] - 1 - 1];
- if (errmax <= elist[isucc - 1]) {
- break;
- }
- iord[nrmax[0] - 1] = isucc;
- --nrmax[0];
- }
- }
-
- // 30: COMPUTE THE NUMBER OF ELEMENTS IN THE LIST TO BE MAINTAINED
- // IN DESCENDING ORDER. THIS NUMBER DEPENDS ON THE NUMBER OF
- // SUBDIVISIONS STILL ALLOWED.
- jupbn = last[0];
- if (last[0] > ((limit >> 1) + 2)) {
- jupbn = limit + 3 - last[0];
- }
- errmin = elist[last[0] - 1];
-
- // INSERT ERRMAX BY TRAVERSING THE LIST TOP-DOWN,
- // STARTING COMPARISON FROM THE ELEMENT ELIST(IORD(NRMAX+1)).
- jbnd = jupbn - 1;
- ibeg = nrmax[0] + 1;
- for (i = ibeg; i <= jbnd; ++i) {
- isucc = iord[i - 1];
- if (errmax >= elist[isucc - 1]) {
-
- // 60: INSERT ERRMIN BY TRAVERSING THE LIST BOTTOM-UP.
- iord[i - 1 - 1] = maxerr[0];
- k = jbnd;
- for (j = 1; j <= jbnd; ++j) {
- isucc = iord[k - 1];
- if (errmin < elist[isucc - 1]) {
- iord[k + 1 - 1] = last[0];
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
- iord[k + 1 - 1] = isucc;
- --k;
- }
- iord[i - 1] = last[0];
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
- return;
- }
- iord[i - 1 - 1] = isucc;
- }
- iord[jbnd - 1] = maxerr[0];
- iord[jupbn - 1] = last[0];
- maxerr[0] = iord[nrmax[0] - 1];
- ermax[0] = elist[maxerr[0] - 1];
+ // 30: COMPUTE THE NUMBER OF ELEMENTS IN THE LIST TO BE MAINTAINED
+ // IN DESCENDING ORDER. THIS NUMBER DEPENDS ON THE NUMBER OF
+ // SUBDIVISIONS STILL ALLOWED.
+ jupbn = last[0];
+ if (last[0] > ((limit >> 1) + 2)) {
+ jupbn = limit + 3 - last[0];
+ }
+ errmin = elist[last[0] - 1];
+
+ // INSERT ERRMAX BY TRAVERSING THE LIST TOP-DOWN,
+ // STARTING COMPARISON FROM THE ELEMENT ELIST(IORD(NRMAX+1)).
+ jbnd = jupbn - 1;
+ ibeg = nrmax[0] + 1;
+ for (i = ibeg; i <= jbnd; ++i) {
+ isucc = iord[i - 1];
+ if (errmax >= elist[isucc - 1]) {
+
+ // 60: INSERT ERRMIN BY TRAVERSING THE LIST BOTTOM-UP.
+ iord[i - 1 - 1] = maxerr[0];
+ k = jbnd;
+ for (j = 1; j <= jbnd; ++j) {
+ isucc = iord[k - 1];
+ if (errmin < elist[isucc - 1]) {
+ iord[k + 1 - 1] = last[0];
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
+ }
+ iord[k + 1 - 1] = isucc;
+ --k;
+ }
+ iord[i - 1] = last[0];
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ return;
+ }
+ iord[i - 1 - 1] = isucc;
+ }
+ iord[jbnd - 1] = maxerr[0];
+ iord[jupbn - 1] = last[0];
+ maxerr[0] = iord[nrmax[0] - 1];
+ ermax[0] = elist[maxerr[0] - 1];
+ }
+
+ private static void qelg(final int[] n, final double[] epstab, final double[] result,
+ final double[] abserr, final double[] res3la, final int[] nres, final double epmach,
+ final double oflow) {
+ double delta1, delta2, delta3, epsinf, error, err1, err2, err3, e0, e1, e1abs, e2, e3, res, ss,
+ tol1, tol2, tol3;
+ int i, ib, ib2, ie, indx, k1, k2, k3, limexp, newelm, num;
+
+ ++nres[0];
+ abserr[0] = oflow;
+ result[0] = epstab[n[0] - 1];
+ if (n[0] < 3) {
+ abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
+ return;
+ }
+ limexp = 50;
+ epstab[n[0] + 2 - 1] = epstab[n[0] - 1];
+ newelm = (n[0] - 1) >> 1;
+ epstab[n[0] - 1] = oflow;
+ num = k1 = n[0];
+ for (i = 1; i <= newelm; ++i) {
+ k2 = k1 - 1;
+ k3 = k1 - 2;
+ res = epstab[k1 + 2 - 1];
+ e0 = epstab[k3 - 1];
+ e1 = epstab[k2 - 1];
+ e2 = res;
+ e1abs = Math.abs(e1);
+ delta2 = e2 - e1;
+ err2 = Math.abs(delta2);
+ tol2 = Math.max(Math.abs(e2), e1abs) * epmach;
+ delta3 = e1 - e0;
+ err3 = Math.abs(delta3);
+ tol3 = Math.max(e1abs, Math.abs(e0)) * epmach;
+ if (err2 <= tol2 && err3 <= tol3) {
+
+ // IF E0, E1 AND E2 ARE EQUAL TO WITHIN MACHINE
+ // ACCURACY, CONVERGENCE IS ASSUMED.
+ // RESULT = E2
+ // ABSERR = ABS(E1-E0) + ABS(E2-E1)
+ result[0] = res;
+ abserr[0] = err2 + err3;
+ abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
+ return;
+ }
+ e3 = epstab[k1 - 1];
+ epstab[k1 - 1] = e1;
+ delta1 = e1 - e3;
+ err1 = Math.abs(delta1);
+ tol1 = Math.max(e1abs, Math.abs(e3)) * epmach;
+
+ // IF TWO ELEMENTS ARE VERY CLOSE TO EACH OTHER, OMIT
+ // A PART OF THE TABLE BY ADJUSTING THE VALUE OF N
+ if (err1 <= tol1 || err2 <= tol2 || err3 <= tol3) {
+ n[0] = i + i - 1;
+ break;
+ }
+ ss = 1.0 / delta1 + 1.0 / delta2 - 1.0 / delta3;
+ epsinf = Math.abs(ss * e1);
+
+ // TEST TO DETECT IRREGULAR BEHAVIOUR IN THE TABLE, AND EVENTUALLY
+ // OMIT A PART OF THE TABLE ADJUSTING THE VALUE OF N.
+ if (epsinf <= 0.1e-3) {
+ n[0] = i + i - 1;
+ break;
+ }
+
+ // 30: COMPUTE A NEW ELEMENT AND EVENTUALLY ADJUST THE VALUE
+ // OF RESULT.
+ res = e1 + 1.0 / ss;
+ epstab[k1 - 1] = res;
+ k1 -= 2;
+ error = err2 + Math.abs(res - e2) + err3;
+ if (error > abserr[0]) {
+ continue;
+ }
+ abserr[0] = error;
+ result[0] = res;
}
- private static void qelg(final int[] n, final double[] epstab, final double[] result, final double[] abserr,
- final double[] res3la, final int[] nres, final double epmach, final double oflow) {
- double delta1, delta2, delta3, epsinf, error, err1, err2, err3, e0, e1, e1abs, e2, e3, res, ss, tol1, tol2,
- tol3;
- int i, ib, ib2, ie, indx, k1, k2, k3, limexp, newelm, num;
-
- ++nres[0];
- abserr[0] = oflow;
- result[0] = epstab[n[0] - 1];
- if (n[0] < 3) {
- abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
- return;
- }
- limexp = 50;
- epstab[n[0] + 2 - 1] = epstab[n[0] - 1];
- newelm = (n[0] - 1) >> 1;
- epstab[n[0] - 1] = oflow;
- num = k1 = n[0];
- for (i = 1; i <= newelm; ++i) {
- k2 = k1 - 1;
- k3 = k1 - 2;
- res = epstab[k1 + 2 - 1];
- e0 = epstab[k3 - 1];
- e1 = epstab[k2 - 1];
- e2 = res;
- e1abs = Math.abs(e1);
- delta2 = e2 - e1;
- err2 = Math.abs(delta2);
- tol2 = Math.max(Math.abs(e2), e1abs) * epmach;
- delta3 = e1 - e0;
- err3 = Math.abs(delta3);
- tol3 = Math.max(e1abs, Math.abs(e0)) * epmach;
- if (err2 <= tol2 && err3 <= tol3) {
-
- // IF E0, E1 AND E2 ARE EQUAL TO WITHIN MACHINE
- // ACCURACY, CONVERGENCE IS ASSUMED.
- // RESULT = E2
- // ABSERR = ABS(E1-E0) + ABS(E2-E1)
- result[0] = res;
- abserr[0] = err2 + err3;
- abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
- return;
- }
- e3 = epstab[k1 - 1];
- epstab[k1 - 1] = e1;
- delta1 = e1 - e3;
- err1 = Math.abs(delta1);
- tol1 = Math.max(e1abs, Math.abs(e3)) * epmach;
-
- // IF TWO ELEMENTS ARE VERY CLOSE TO EACH OTHER, OMIT
- // A PART OF THE TABLE BY ADJUSTING THE VALUE OF N
- if (err1 <= tol1 || err2 <= tol2 || err3 <= tol3) {
- n[0] = i + i - 1;
- break;
- }
- ss = 1.0 / delta1 + 1.0 / delta2 - 1.0 / delta3;
- epsinf = Math.abs(ss * e1);
-
- // TEST TO DETECT IRREGULAR BEHAVIOUR IN THE TABLE, AND EVENTUALLY
- // OMIT A PART OF THE TABLE ADJUSTING THE VALUE OF N.
- if (epsinf <= 0.1e-3) {
- n[0] = i + i - 1;
- break;
- }
-
- // 30: COMPUTE A NEW ELEMENT AND EVENTUALLY ADJUST THE VALUE
- // OF RESULT.
- res = e1 + 1.0 / ss;
- epstab[k1 - 1] = res;
- k1 -= 2;
- error = err2 + Math.abs(res - e2) + err3;
- if (error > abserr[0]) {
- continue;
- }
- abserr[0] = error;
- result[0] = res;
- }
-
- // 50: SHIFT THE TABLE.
- if (n[0] == limexp) {
- n[0] = ((limexp >> 1) << 1) - 1;
- }
- ib = 1;
- if (((num >> 1) << 1) == num) {
- ib = 2;
- }
- ie = newelm + 1;
- for (i = 1; i <= ie; ++i) {
- ib2 = ib + 2;
- epstab[ib - 1] = epstab[ib2 - 1];
- ib = ib2;
- }
- if (num != n[0]) {
- indx = num - n[0] + 1;
- for (i = 1; i <= n[0]; ++i) {
- epstab[i - 1] = epstab[indx - 1];
- ++indx;
- }
- }
- if (nres[0] < 4) {
- res3la[nres[0] - 1] = result[0];
- abserr[0] = oflow;
- abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
- return;
- }
-
- // 90: COMPUTE ERROR ESTIMATE
- abserr[0] = Math.abs(result[0] - res3la[3 - 1]) + Math.abs(result[0] - res3la[2 - 1])
- + Math.abs(result[0] - res3la[1 - 1]);
- res3la[1 - 1] = res3la[2 - 1];
- res3la[2 - 1] = res3la[3 - 1];
- res3la[3 - 1] = result[0];
- abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
+ // 50: SHIFT THE TABLE.
+ if (n[0] == limexp) {
+ n[0] = ((limexp >> 1) << 1) - 1;
+ }
+ ib = 1;
+ if (((num >> 1) << 1) == num) {
+ ib = 2;
+ }
+ ie = newelm + 1;
+ for (i = 1; i <= ie; ++i) {
+ ib2 = ib + 2;
+ epstab[ib - 1] = epstab[ib2 - 1];
+ ib = ib2;
}
+ if (num != n[0]) {
+ indx = num - n[0] + 1;
+ for (i = 1; i <= n[0]; ++i) {
+ epstab[i - 1] = epstab[indx - 1];
+ ++indx;
+ }
+ }
+ if (nres[0] < 4) {
+ res3la[nres[0] - 1] = result[0];
+ abserr[0] = oflow;
+ abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
+ return;
+ }
+
+ // 90: COMPUTE ERROR ESTIMATE
+ abserr[0] = Math.abs(result[0] - res3la[3 - 1]) + Math.abs(result[0] - res3la[2 - 1])
+ + Math.abs(result[0] - res3la[1 - 1]);
+ res3la[1 - 1] = res3la[2 - 1];
+ res3la[2 - 1] = res3la[3 - 1];
+ res3la[3 - 1] = result[0];
+ abserr[0] = Math.max(abserr[0], 5.0 * epmach * Math.abs(result[0]));
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Romberg.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Romberg.java
index 172268496..6f054e1a6 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Romberg.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Romberg.java
@@ -7,10 +7,8 @@
/**
* Implements three versions of the Romberg numerical integrator:
*
- * - Richardson is the simplest and is based on Richardson extrapolation
- * [4]
- * - CADRE is a translation of the Cautious Adaptive Romberg Extrapolator
- * (CADRE) [1, 2]
+ * - Richardson is the simplest and is based on Richardson extrapolation [4]
+ * - CADRE is a translation of the Cautious Adaptive Romberg Extrapolator (CADRE) [1, 2]
* - Havie is a translation of the Havie integrator introduced in [3]
*
* All three versions are translated from the INTLIB package by John Burkardt.
@@ -18,759 +16,759 @@
*
* References:
*
- * - [1] Philip Davis, Philip Rabinowitz. Methods of Numerical Integration,
- * Second Edition, Dover, 2007.
- * - [2] de Boor, Carl. "CADRE: An algorithm for numerical quadrature."
- * Mathematical software. Academic Press, 1971. 417-449.
- * - [3] Robert N. Kubik. 1965. Algorithm 257: Havie integrator. Commun. ACM
- * 8, 6 (June 1965), 381. DOI:https://doi.org/10.1145/364955.364978
- * - [4] CF Dunkl, Romberg quadrature to prescribed accuracy, SHARE file
- * number 7090-1481 TYQUAD
+ * - [1] Philip Davis, Philip Rabinowitz. Methods of Numerical Integration, Second Edition, Dover,
+ * 2007.
+ * - [2] de Boor, Carl. "CADRE: An algorithm for numerical quadrature." Mathematical software.
+ * Academic Press, 1971. 417-449.
+ * - [3] Robert N. Kubik. 1965. Algorithm 257: Havie integrator. Commun. ACM 8, 6 (June 1965),
+ * 381. DOI:https://doi.org/10.1145/364955.364978
+ * - [4] CF Dunkl, Romberg quadrature to prescribed accuracy, SHARE file number 7090-1481
+ * TYQUAD
*
*
*/
public final class Romberg extends Quadrature {
- private final double myRelTol;
- private final RombergExtrapolationMethod myMethod;
-
- /**
- * The extrapolation method to use for Romberg integration.
- */
- public static enum RombergExtrapolationMethod {
- RICHARDSON, CADRE, HAVIE
- }
-
- /**
- * Creates a new instance of the Romberg integrator.
- *
- * @param relativeTolerance the smallest acceptable relative change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param absoluteTolerance the smallest acceptable absolute change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param maxEvaluations the maximum number of function evaluations
- * @param method the extrapolation method to use
- */
- public Romberg(final double absoluteTolerance, final double relativeTolerance, final int maxEvaluations,
- final RombergExtrapolationMethod method) {
- super(absoluteTolerance, maxEvaluations);
- myRelTol = relativeTolerance;
- myMethod = method;
- }
-
- /**
- * Creates a new instance of the Romberg integrator.
- *
- * @param absoluteTolerance the smallest acceptable absolute change in integral
- * estimates in consecutive iterations that indicates
- * the algorithm has converged
- * @param maxEvaluations the maximum number of function evaluations
- * @param method the extrapolation method to use
- *
- */
- public Romberg(final double absoluteTolerance, final int maxEvaluations, final RombergExtrapolationMethod method) {
- this(absoluteTolerance, 100.0 * Constants.EPSILON, maxEvaluations, method);
- }
-
- public Romberg(final double absoluteTolerance, final int maxEvaluations) {
- this(absoluteTolerance, maxEvaluations, RombergExtrapolationMethod.CADRE);
- }
-
- @Override
- final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
- final double b) {
- switch (myMethod) {
- case RICHARDSON:
- return romberg(f, a, b);
- case CADRE:
- return cadre(f, a, b);
- case HAVIE:
- return havie(f, a, b, 2);
- default:
- return new QuadratureResult(Double.NaN, Double.NaN, 0, false);
- }
- }
-
- @Override
- public final String getName() {
- return "Romberg-" + myMethod.toString();
+ private final double myRelTol;
+ private final RombergExtrapolationMethod myMethod;
+
+ /**
+ * The extrapolation method to use for Romberg integration.
+ */
+ public static enum RombergExtrapolationMethod {
+ RICHARDSON, CADRE, HAVIE
+ }
+
+ /**
+ * Creates a new instance of the Romberg integrator.
+ *
+ * @param relativeTolerance the smallest acceptable relative change in integral estimates in
+ * consecutive iterations that indicates the algorithm has converged
+ * @param absoluteTolerance the smallest acceptable absolute change in integral estimates in
+ * consecutive iterations that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of function evaluations
+ * @param method the extrapolation method to use
+ */
+ public Romberg(final double absoluteTolerance, final double relativeTolerance,
+ final int maxEvaluations, final RombergExtrapolationMethod method) {
+ super(absoluteTolerance, maxEvaluations);
+ myRelTol = relativeTolerance;
+ myMethod = method;
+ }
+
+ /**
+ * Creates a new instance of the Romberg integrator.
+ *
+ * @param absoluteTolerance the smallest acceptable absolute change in integral estimates in
+ * consecutive iterations that indicates the algorithm has converged
+ * @param maxEvaluations the maximum number of function evaluations
+ * @param method the extrapolation method to use
+ *
+ */
+ public Romberg(final double absoluteTolerance, final int maxEvaluations,
+ final RombergExtrapolationMethod method) {
+ this(absoluteTolerance, 100.0 * Constants.EPSILON, maxEvaluations, method);
+ }
+
+ public Romberg(final double absoluteTolerance, final int maxEvaluations) {
+ this(absoluteTolerance, maxEvaluations, RombergExtrapolationMethod.CADRE);
+ }
+
+ @Override
+ final QuadratureResult properIntegral(final DoubleUnaryOperator f, final double a,
+ final double b) {
+ switch (myMethod) {
+ case RICHARDSON:
+ return romberg(f, a, b);
+ case CADRE:
+ return cadre(f, a, b);
+ case HAVIE:
+ return havie(f, a, b, 2);
+ default:
+ return new QuadratureResult(Double.NaN, Double.NaN, 0, false);
}
-
- private final QuadratureResult romberg(final DoubleUnaryOperator func, final double a,
- final double b) {
-
- // prepare variables
- final double[] work = new double[myMaxEvals + 1];
- double rnderr = Constants.EPSILON;
- double qx1 = 0.0;
- double qx2 = 0.0;
- double h = b - a;
+ }
+
+ @Override
+ public final String getName() {
+ return "Romberg-" + myMethod.toString();
+ }
+
+ private final QuadratureResult romberg(final DoubleUnaryOperator func, final double a,
+ final double b) {
+
+ // prepare variables
+ final double[] work = new double[myMaxEvals + 1];
+ double rnderr = Constants.EPSILON;
+ double qx1 = 0.0;
+ double qx2 = 0.0;
+ double h = b - a;
double fcna = func.applyAsDouble(a);
double fcnb = func.applyAsDouble(b);
- double tabs = Math.abs(h) * (Math.abs(fcna) + Math.abs(fcnb)) * 0.5;
- double t = h * (fcna + fcnb) * 0.5;
- int nx = 1;
- int nfev = 2;
- final int nleast = 6;
-
- // main iterations
- for (int i = 1; nfev < myMaxEvals; ++i) {
- h *= 0.5;
- double sum1 = 0.0;
- double sumabs = 0.0;
- for (int j = 1; j <= nx; ++j) {
- final double fcnxi = func.applyAsDouble(a + h * ((j << 1) - 1));
- sumabs += Math.abs(fcnxi);
- sum1 += fcnxi;
- ++nfev;
- if (nfev >= myMaxEvals) {
- return new QuadratureResult(work[0], Double.NaN, nfev, false);
- }
- }
- t = 0.5 * t + h * sum1;
- tabs = tabs * 0.5 + Math.abs(h) * sumabs;
- work[i - 1] = 2.0 * (t + h * sum1) / 3.0;
- if (1 < i) {
-
- // Construct difference table for Richardson extrapolation.
- double f = 4.0;
- for (int j = 2; j <= i; ++j) {
- final int k = i + 1 - j;
- f *= 4.0;
- work[k - 1] = work[k] + (work[k] - work[k - 1]) / (f - 1.0);
- }
-
- // Perform acceptance check.
- if (nleast <= i) {
- final double x = Math.abs(work[0] - qx2) + Math.abs(qx2 - qx1);
- if (x <= 3.0 * tabs * (Math.abs(myRelTol) + rnderr) || x <= 3.0 * Math.abs(myTol)) {
- return new QuadratureResult(work[0], x, nfev, true);
- }
- }
-
- // Save old result, perform bisection, repeat.
- qx1 = qx2;
- }
- qx2 = work[0];
- nx <<= 1;
- }
- return new QuadratureResult(work[0], Double.NaN, nfev, false);
+ double tabs = Math.abs(h) * (Math.abs(fcna) + Math.abs(fcnb)) * 0.5;
+ double t = h * (fcna + fcnb) * 0.5;
+ int nx = 1;
+ int nfev = 2;
+ final int nleast = 6;
+
+ // main iterations
+ for (int i = 1; nfev < myMaxEvals; ++i) {
+ h *= 0.5;
+ double sum1 = 0.0;
+ double sumabs = 0.0;
+ for (int j = 1; j <= nx; ++j) {
+ final double fcnxi = func.applyAsDouble(a + h * ((j << 1) - 1));
+ sumabs += Math.abs(fcnxi);
+ sum1 += fcnxi;
+ ++nfev;
+ if (nfev >= myMaxEvals) {
+ return new QuadratureResult(work[0], Double.NaN, nfev, false);
+ }
+ }
+ t = 0.5 * t + h * sum1;
+ tabs = tabs * 0.5 + Math.abs(h) * sumabs;
+ work[i - 1] = 2.0 * (t + h * sum1) / 3.0;
+ if (1 < i) {
+
+ // Construct difference table for Richardson extrapolation.
+ double f = 4.0;
+ for (int j = 2; j <= i; ++j) {
+ final int k = i + 1 - j;
+ f *= 4.0;
+ work[k - 1] = work[k] + (work[k] - work[k - 1]) / (f - 1.0);
+ }
+
+ // Perform acceptance check.
+ if (nleast <= i) {
+ final double x = Math.abs(work[0] - qx2) + Math.abs(qx2 - qx1);
+ if (x <= 3.0 * tabs * (Math.abs(myRelTol) + rnderr) || x <= 3.0 * Math.abs(myTol)) {
+ return new QuadratureResult(work[0], x, nfev, true);
+ }
+ }
+
+ // Save old result, perform bisection, repeat.
+ qx1 = qx2;
+ }
+ qx2 = work[0];
+ nx <<= 1;
}
-
- private final QuadratureResult cadre(final DoubleUnaryOperator func, final double a,
- final double b) {
- final int mxstge = 30, maxtbl = 10, maxts = 2049;
- final double aitlow = 1.1, aittol = 0.1, h2tol = 0.15, tljump = 0.01;
- final boolean[] reglsv = new boolean[mxstge];
- final int[] ibegs = new int[mxstge];
- final double[] ait = new double[maxtbl], begin = new double[mxstge], dif = new double[maxtbl],
- est = new double[mxstge], finis = new double[mxstge], r = new double[maxtbl], rn = new double[4],
- ts = new double[maxts];
- final double[][] t = new double[maxtbl][maxtbl];
- boolean aitken, h2conv, reglar, right;
- int i = 0, ibeg, iend, ii, iii, istage, istep, istep2, it = 0, l, lm1 = 0, n, n2, nnleft, fev = 0, ind;
- double astep, beg, bma, curest, diff = 0.0, end, ergoal = 0.0, erra, errer = 0.0, errr, fbeg, fbeg2 = 0.0, fend,
- fextm1, fextrp = 0.0, fn, fnsize, h2next = 0.0, h2tfex, hovn, prever, rnderr, sing, singnx = 0.0,
- slope = 0.0, stage, step, stepmn, sum1, sumabs, tabs, tabtlm = 0.0, vint, result = 0.0, error = 0.0;
-
- vint = 0.0;
- rn[0] = 0.7142005;
- rn[1] = 0.3466282;
- rn[2] = 0.8437510;
- rn[3] = 0.1263305;
- rnderr = Constants.EPSILON;
- ind = 1;
- bma = Math.abs(b - a);
- errr = Math.min(0.1, Math.max(Math.abs(myRelTol), 10.0 * rnderr));
- erra = Math.abs(myTol);
- final double absmax = Math.max(Math.abs(a), Math.abs(b));
- stepmn = Math.max(bma / SimpleMath.pow(2.0, mxstge), Math.max(bma, absmax) * rnderr);
- stage = 0.5;
- istage = 1;
- curest = fnsize = prever = 0.0;
- reglar = false;
- beg = a;
+ return new QuadratureResult(work[0], Double.NaN, nfev, false);
+ }
+
+ private final QuadratureResult cadre(final DoubleUnaryOperator func, final double a,
+ final double b) {
+ final int mxstge = 30, maxtbl = 10, maxts = 2049;
+ final double aitlow = 1.1, aittol = 0.1, h2tol = 0.15, tljump = 0.01;
+ final boolean[] reglsv = new boolean[mxstge];
+ final int[] ibegs = new int[mxstge];
+ final double[] ait = new double[maxtbl], begin = new double[mxstge], dif = new double[maxtbl],
+ est = new double[mxstge], finis = new double[mxstge], r = new double[maxtbl],
+ rn = new double[4], ts = new double[maxts];
+ final double[][] t = new double[maxtbl][maxtbl];
+ boolean aitken, h2conv, reglar, right;
+ int i = 0, ibeg, iend, ii, iii, istage, istep, istep2, it = 0, l, lm1 = 0, n, n2, nnleft,
+ fev = 0, ind;
+ double astep, beg, bma, curest, diff = 0.0, end, ergoal = 0.0, erra, errer = 0.0, errr, fbeg,
+ fbeg2 = 0.0, fend, fextm1, fextrp = 0.0, fn, fnsize, h2next = 0.0, h2tfex, hovn, prever,
+ rnderr, sing, singnx = 0.0, slope = 0.0, stage, step, stepmn, sum1, sumabs, tabs,
+ tabtlm = 0.0, vint, result = 0.0, error = 0.0;
+
+ vint = 0.0;
+ rn[0] = 0.7142005;
+ rn[1] = 0.3466282;
+ rn[2] = 0.8437510;
+ rn[3] = 0.1263305;
+ rnderr = Constants.EPSILON;
+ ind = 1;
+ bma = Math.abs(b - a);
+ errr = Math.min(0.1, Math.max(Math.abs(myRelTol), 10.0 * rnderr));
+ erra = Math.abs(myTol);
+ final double absmax = Math.max(Math.abs(a), Math.abs(b));
+ stepmn = Math.max(bma / SimpleMath.pow(2.0, mxstge), Math.max(bma, absmax) * rnderr);
+ stage = 0.5;
+ istage = 1;
+ curest = fnsize = prever = 0.0;
+ reglar = false;
+ beg = a;
fbeg = func.applyAsDouble(beg) / 2.0;
- fev = 1;
- ts[1 - 1] = fbeg;
- ibeg = 1;
- end = b;
+ fev = 1;
+ ts[1 - 1] = fbeg;
+ ibeg = 1;
+ end = b;
fend = func.applyAsDouble(end) / 2.0;
- ++fev;
- ts[2 - 1] = fend;
- iend = 2;
-
- right = false;
- step = end - beg;
- astep = Math.abs(step);
- if (astep < stepmn) {
- ind = 5;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- t[1 - 1][1 - 1] = fbeg + fend;
- tabs = Math.abs(fbeg) + Math.abs(fend);
- l = n = 1;
- h2conv = aitken = false;
-
- int flag = 40;
- while (true) {
-
- if (flag == 40) {
- lm1 = l;
- ++l;
- n2 = n << 1;
- fn = n2;
- istep = (iend - ibeg) / n;
- if (1 >= istep) {
- ii = iend;
- iend += n;
- if (maxts < iend) {
- ind = 4;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- hovn = step / fn;
- iii = iend;
- for (i = 1; i <= n2; i += 2) {
- ts[iii - 1] = ts[ii - 1];
+ ++fev;
+ ts[2 - 1] = fend;
+ iend = 2;
+
+ right = false;
+ step = end - beg;
+ astep = Math.abs(step);
+ if (astep < stepmn) {
+ ind = 5;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ t[1 - 1][1 - 1] = fbeg + fend;
+ tabs = Math.abs(fbeg) + Math.abs(fend);
+ l = n = 1;
+ h2conv = aitken = false;
+
+ int flag = 40;
+ while (true) {
+
+ if (flag == 40) {
+ lm1 = l;
+ ++l;
+ n2 = n << 1;
+ fn = n2;
+ istep = (iend - ibeg) / n;
+ if (1 >= istep) {
+ ii = iend;
+ iend += n;
+ if (maxts < iend) {
+ ind = 4;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ hovn = step / fn;
+ iii = iend;
+ for (i = 1; i <= n2; i += 2) {
+ ts[iii - 1] = ts[ii - 1];
ts[iii - 1 - 1] = func.applyAsDouble(end - i * hovn);
- ++fev;
- iii -= 2;
- --ii;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, error, fev, false);
- }
- }
- istep = 2;
- }
-
- istep2 = ibeg + (istep >> 1);
- sum1 = sumabs = 0.0;
- for (i = istep2; i <= iend; i += istep) {
- sum1 += ts[i - 1];
- sumabs += Math.abs(ts[i - 1]);
- }
-
- t[l - 1][1 - 1] = t[l - 1 - 1][1 - 1] / 2.0 + sum1 / fn;
- tabs = tabs / 2.0 + sumabs / fn;
- n = n2;
- it = 1;
- vint = step * t[l - 1][1 - 1];
- tabtlm = tabs * rnderr;
- fnsize = Math.max(fnsize, Math.abs(t[l - 1][1 - 1]));
- ergoal = Math.max(astep * rnderr * fnsize, stage * Math.max(erra, errr * Math.abs(curest + vint)));
- fextrp = 1.0;
- for (i = 1; i <= lm1; ++i) {
- fextrp *= 4.0;
- t[i - 1][l - 1] = t[l - 1][i - 1] - t[l - 1 - 1][i - 1];
- t[l - 1][i + 1 - 1] = t[l - 1][i - 1] + t[i - 1][l - 1] / (fextrp - 1.0);
- }
-
- errer = astep * Math.abs(t[1 - 1][l - 1]);
- if (2 >= l) {
- if (Math.abs(t[1 - 1][2 - 1]) <= tabtlm) {
- slope = (fend - fbeg) * 2.0;
- fbeg2 = fbeg * 2.0;
- int next = 340;
- for (i = 1; i <= 4; ++i) {
+ ++fev;
+ iii -= 2;
+ --ii;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, error, fev, false);
+ }
+ }
+ istep = 2;
+ }
+
+ istep2 = ibeg + (istep >> 1);
+ sum1 = sumabs = 0.0;
+ for (i = istep2; i <= iend; i += istep) {
+ sum1 += ts[i - 1];
+ sumabs += Math.abs(ts[i - 1]);
+ }
+
+ t[l - 1][1 - 1] = t[l - 1 - 1][1 - 1] / 2.0 + sum1 / fn;
+ tabs = tabs / 2.0 + sumabs / fn;
+ n = n2;
+ it = 1;
+ vint = step * t[l - 1][1 - 1];
+ tabtlm = tabs * rnderr;
+ fnsize = Math.max(fnsize, Math.abs(t[l - 1][1 - 1]));
+ ergoal = Math.max(astep * rnderr * fnsize,
+ stage * Math.max(erra, errr * Math.abs(curest + vint)));
+ fextrp = 1.0;
+ for (i = 1; i <= lm1; ++i) {
+ fextrp *= 4.0;
+ t[i - 1][l - 1] = t[l - 1][i - 1] - t[l - 1 - 1][i - 1];
+ t[l - 1][i + 1 - 1] = t[l - 1][i - 1] + t[i - 1][l - 1] / (fextrp - 1.0);
+ }
+
+ errer = astep * Math.abs(t[1 - 1][l - 1]);
+ if (2 >= l) {
+ if (Math.abs(t[1 - 1][2 - 1]) <= tabtlm) {
+ slope = (fend - fbeg) * 2.0;
+ fbeg2 = fbeg * 2.0;
+ int next = 340;
+ for (i = 1; i <= 4; ++i) {
+ diff =
+ Math.abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
+ ++fev;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, error, fev, false);
+ }
+ if (tabtlm < diff) {
+ next = 330;
+ break;
+ }
+ }
+ if (next == 330) {
+ flag = 330;
+ } else {
+ flag = 340;
+ }
+ }
+ continue;
+ }
+
+ for (i = 2; i <= lm1; ++i) {
+ if (tabtlm < Math.abs(t[i - 1 - 1][l - 1])) {
+ diff = t[i - 1 - 1][lm1 - 1] / t[i - 1 - 1][l - 1];
+ } else {
+ diff = 0.0;
+ }
+ t[i - 1 - 1][lm1 - 1] = diff;
+ }
+
+ if (Math.abs(4.0 - t[1 - 1][lm1 - 1]) > h2tol) {
+ if (t[1 - 1][lm1 - 1] == 0.0) {
+ if (errer <= ergoal) {
+ slope = (fend - fbeg) * 2.0;
+ fbeg2 = fbeg * 2.0;
+ i = 1;
diff =
Math.abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
- ++fev;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, error, fev, false);
- }
- if (tabtlm < diff) {
- next = 330;
- break;
- }
- }
- if (next == 330) {
- flag = 330;
- } else {
- flag = 340;
- }
- }
- continue;
- }
-
- for (i = 2; i <= lm1; ++i) {
- if (tabtlm < Math.abs(t[i - 1 - 1][l - 1])) {
- diff = t[i - 1 - 1][lm1 - 1] / t[i - 1 - 1][l - 1];
- } else {
- diff = 0.0;
- }
- t[i - 1 - 1][lm1 - 1] = diff;
- }
-
- if (Math.abs(4.0 - t[1 - 1][lm1 - 1]) > h2tol) {
- if (t[1 - 1][lm1 - 1] == 0.0) {
- if (errer <= ergoal) {
- slope = (fend - fbeg) * 2.0;
- fbeg2 = fbeg * 2.0;
- i = 1;
- diff = Math
- .abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
- ++fev;
- flag = 330;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, error, fev, false);
- }
- } else {
- flag = 380;
- }
- } else if (Math.abs(2.0 - Math.abs(t[1 - 1][lm1 - 1])) < tljump) {
- if (ergoal < errer) {
- reglar = true;
- flag = 380;
- } else {
- diff = Math.abs(t[1 - 1][l - 1]) * 2.0 * fn;
- flag = 340;
- }
- } else if (l == 3) {
- flag = 40;
- } else {
- h2conv = false;
- if (Math.abs((t[1 - 1][lm1 - 1] - t[1 - 1][l - 2 - 1]) / t[1 - 1][lm1 - 1]) <= aittol) {
- flag = 160;
- } else if (!reglar && l == 4) {
- flag = 40;
- } else if (errer <= ergoal) {
- slope = (fend - fbeg) * 2.0;
- fbeg2 = fbeg * 2.0;
- i = 1;
- diff = Math
- .abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
- ++fev;
- flag = 330;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, error, fev, false);
- }
- } else {
- flag = 380;
- }
- }
- continue;
- } else {
- if (!h2conv) {
- aitken = false;
- h2conv = true;
- }
- fextrp = 4.0;
- flag = 150;
- }
- }
-
- if (flag == 150) {
- while (true) {
- ++it;
- vint = step * t[l - 1][it - 1];
- errer = Math.abs(step / (fextrp - 1.0) * t[it - 1 - 1][l - 1]);
- if (errer <= ergoal) {
- flag = 340;
- break;
- } else if (it == lm1) {
- flag = 270;
- break;
- } else if (t[it - 1][lm1 - 1] == 0.0) {
- } else if (t[it - 1][lm1 - 1] <= fextrp) {
- flag = 270;
- break;
- } else if (Math.abs(t[it - 1][lm1 - 1] / 4.0 - fextrp) / fextrp < aittol) {
- fextrp *= 4.0;
- }
- }
- }
-
- if (flag == 160) {
- if (t[1 - 1][lm1 - 1] < aitlow) {
- flag = 380;
- } else {
- if (!aitken) {
- h2conv = false;
- aitken = true;
- }
- fextrp = t[l - 2 - 1][lm1 - 1];
- if (4.5 < fextrp) {
- fextrp = 4.0;
- flag = 150;
- continue;
- } else if (fextrp < aitlow
- || h2tol < Math.abs(fextrp - t[l - 3 - 1][lm1 - 1]) / t[1 - 1][lm1 - 1]) {
- flag = 380;
- } else {
- sing = fextrp;
- fextm1 = fextrp - 1.0;
- ait[1 - 1] = 0.0;
- for (i = 2; i <= l; ++i) {
- ait[i - 1] = t[i - 1][1 - 1] + (t[i - 1][1 - 1] - t[i - 1 - 1][1 - 1]) / fextm1;
- r[i - 1] = t[1 - 1][i - 1 - 1];
- dif[i - 1] = ait[i - 1] - ait[i - 1 - 1];
- }
- it = 2;
-
- while (true) {
- vint = step * ait[l - 1];
- errer /= fextm1;
- if (errer <= ergoal) {
- ind = Math.max(ind, 2);
- flag = 340;
- break;
- }
- ++it;
- if (it == lm1) {
- flag = 270;
- break;
- }
- if (it <= 3) {
- h2next = 4.0;
- singnx = 2.0 * sing;
- }
- if (h2next < singnx) {
- fextrp = h2next;
- h2next *= 4.0;
- } else {
- fextrp = singnx;
- singnx *= 2.0;
- }
-
- for (i = it; i <= lm1; ++i) {
- if (tabtlm < Math.abs(dif[i + 1 - 1])) {
- r[i + 1 - 1] = dif[i - 1] / dif[i + 1 - 1];
- } else {
- r[i + 1 - 1] = 0.0;
- }
- }
- h2tfex = -h2tol * fextrp;
- if (r[l - 1] - fextrp >= h2tfex && r[l - 1 - 1] - fextrp >= h2tfex) {
- errer = astep * Math.abs(dif[l - 1]);
- fextm1 = fextrp - 1.0;
- for (i = it; i <= l; ++i) {
- ait[i - 1] += (dif[i - 1] / fextm1);
- dif[i - 1] = ait[i - 1] - ait[i - 1 - 1];
- }
- } else {
- flag = 270;
- break;
- }
- }
- }
- }
- }
-
- if (flag == 270) {
- fextrp = Math.max(prever / errer, aitlow);
- prever = errer;
- if (l < 5) {
- flag = 40;
- continue;
- } else if (2.0 < l - it && istage < mxstge) {
- reglar = true;
- flag = 380;
- } else if (errer / SimpleMath.pow(fextrp, maxtbl - l) < ergoal) {
- flag = 40;
- continue;
- } else {
- reglar = true;
- flag = 380;
- }
- }
-
- if (flag == 330) {
- while (true) {
- errer = Math.max(errer, astep * diff);
- if (ergoal < errer) {
- flag = 380;
- break;
- }
- ++i;
- if (i <= 4) {
+ ++fev;
+ flag = 330;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, error, fev, false);
+ }
+ } else {
+ flag = 380;
+ }
+ } else if (Math.abs(2.0 - Math.abs(t[1 - 1][lm1 - 1])) < tljump) {
+ if (ergoal < errer) {
+ reglar = true;
+ flag = 380;
+ } else {
+ diff = Math.abs(t[1 - 1][l - 1]) * 2.0 * fn;
+ flag = 340;
+ }
+ } else if (l == 3) {
+ flag = 40;
+ } else {
+ h2conv = false;
+ if (Math.abs((t[1 - 1][lm1 - 1] - t[1 - 1][l - 2 - 1]) / t[1 - 1][lm1 - 1]) <= aittol) {
+ flag = 160;
+ } else if (!reglar && l == 4) {
+ flag = 40;
+ } else if (errer <= ergoal) {
+ slope = (fend - fbeg) * 2.0;
+ fbeg2 = fbeg * 2.0;
+ i = 1;
diff =
Math.abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
- ++fev;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, error, fev, false);
- }
- } else {
- ind = 3;
- flag = 340;
- break;
- }
- }
- }
-
- if (flag == 340) {
- result += vint;
- error += errer;
- if (right) {
- curest += vint;
- stage *= 2.0;
- iend = ibeg;
- ibeg = ibegs[istage - 1];
- end = beg;
- beg = begin[istage - 1];
- fend = fbeg;
- fbeg = ts[ibeg - 1];
- right = false;
- } else {
- --istage;
- if (istage == 0) {
- return new QuadratureResult(result, error, fev, true);
- }
- reglar = reglsv[istage - 1];
- beg = begin[istage - 1];
- end = finis[istage - 1];
- curest = curest - est[istage + 1 - 1] + vint;
- iend = ibeg - 1;
- fend = ts[iend - 1];
- ibeg = ibegs[istage - 1];
- right = true;
- beg = (beg + end) / 2.0;
- ibeg = (ibeg + iend) >> 1;
- ts[ibeg - 1] /= 2.0;
- fbeg = ts[ibeg - 1];
- }
- step = end - beg;
- astep = Math.abs(step);
- if (astep < stepmn) {
- ind = 5;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- t[1 - 1][1 - 1] = fbeg + fend;
- tabs = Math.abs(fbeg) + Math.abs(fend);
- l = n = 1;
- h2conv = aitken = false;
- flag = 40;
- continue;
- }
-
- if (flag == 380) {
- if (istage == mxstge) {
- ind = 5;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- if (!right) {
- reglsv[istage + 1 - 1] = reglar;
- begin[istage - 1] = beg;
- ibegs[istage - 1] = ibeg;
- stage /= 2.0;
- right = true;
- beg = (beg + end) / 2.0;
- ibeg = (ibeg + iend) >> 1;
- ts[ibeg - 1] /= 2.0;
- fbeg = ts[ibeg - 1];
- } else {
-
- nnleft = ibeg - ibegs[istage - 1];
- if (maxts <= end + nnleft) {
- ind = 4;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- iii = ibegs[istage - 1];
- ii = iend;
- for (i = iii; i <= ibeg; ++i) {
- ++ii;
- ts[ii - 1] = ts[i - 1];
- }
- for (i = ibeg; i <= ii; ++i) {
- ts[iii - 1] = ts[i - 1];
- ++iii;
- }
-
- ++iend;
- ibeg = iend - nnleft;
- fend = fbeg;
- fbeg = ts[ibeg - 1];
- finis[istage - 1] = end;
- end = beg;
- beg = begin[istage - 1];
- begin[istage - 1] = end;
- reglsv[istage - 1] = reglar;
- ++istage;
- reglar = reglsv[istage - 1];
- est[istage - 1] = vint;
- curest += est[istage - 1];
- right = false;
- }
- step = end - beg;
- astep = Math.abs(step);
- if (astep < stepmn) {
- ind = 5;
- return new QuadratureResult(curest + vint, error, fev, true);
- }
- t[1 - 1][1 - 1] = fbeg + fend;
- tabs = Math.abs(fbeg) + Math.abs(fend);
- l = n = 1;
- h2conv = aitken = false;
- flag = 40;
- }
- }
+ ++fev;
+ flag = 330;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, error, fev, false);
+ }
+ } else {
+ flag = 380;
+ }
+ }
+ continue;
+ } else {
+ if (!h2conv) {
+ aitken = false;
+ h2conv = true;
+ }
+ fextrp = 4.0;
+ flag = 150;
+ }
+ }
+
+ if (flag == 150) {
+ while (true) {
+ ++it;
+ vint = step * t[l - 1][it - 1];
+ errer = Math.abs(step / (fextrp - 1.0) * t[it - 1 - 1][l - 1]);
+ if (errer <= ergoal) {
+ flag = 340;
+ break;
+ } else if (it == lm1) {
+ flag = 270;
+ break;
+ } else if (t[it - 1][lm1 - 1] == 0.0) {
+ } else if (t[it - 1][lm1 - 1] <= fextrp) {
+ flag = 270;
+ break;
+ } else if (Math.abs(t[it - 1][lm1 - 1] / 4.0 - fextrp) / fextrp < aittol) {
+ fextrp *= 4.0;
+ }
+ }
+ }
+
+ if (flag == 160) {
+ if (t[1 - 1][lm1 - 1] < aitlow) {
+ flag = 380;
+ } else {
+ if (!aitken) {
+ h2conv = false;
+ aitken = true;
+ }
+ fextrp = t[l - 2 - 1][lm1 - 1];
+ if (4.5 < fextrp) {
+ fextrp = 4.0;
+ flag = 150;
+ continue;
+ } else if (fextrp < aitlow
+ || h2tol < Math.abs(fextrp - t[l - 3 - 1][lm1 - 1]) / t[1 - 1][lm1 - 1]) {
+ flag = 380;
+ } else {
+ sing = fextrp;
+ fextm1 = fextrp - 1.0;
+ ait[1 - 1] = 0.0;
+ for (i = 2; i <= l; ++i) {
+ ait[i - 1] = t[i - 1][1 - 1] + (t[i - 1][1 - 1] - t[i - 1 - 1][1 - 1]) / fextm1;
+ r[i - 1] = t[1 - 1][i - 1 - 1];
+ dif[i - 1] = ait[i - 1] - ait[i - 1 - 1];
+ }
+ it = 2;
+
+ while (true) {
+ vint = step * ait[l - 1];
+ errer /= fextm1;
+ if (errer <= ergoal) {
+ ind = Math.max(ind, 2);
+ flag = 340;
+ break;
+ }
+ ++it;
+ if (it == lm1) {
+ flag = 270;
+ break;
+ }
+ if (it <= 3) {
+ h2next = 4.0;
+ singnx = 2.0 * sing;
+ }
+ if (h2next < singnx) {
+ fextrp = h2next;
+ h2next *= 4.0;
+ } else {
+ fextrp = singnx;
+ singnx *= 2.0;
+ }
+
+ for (i = it; i <= lm1; ++i) {
+ if (tabtlm < Math.abs(dif[i + 1 - 1])) {
+ r[i + 1 - 1] = dif[i - 1] / dif[i + 1 - 1];
+ } else {
+ r[i + 1 - 1] = 0.0;
+ }
+ }
+ h2tfex = -h2tol * fextrp;
+ if (r[l - 1] - fextrp >= h2tfex && r[l - 1 - 1] - fextrp >= h2tfex) {
+ errer = astep * Math.abs(dif[l - 1]);
+ fextm1 = fextrp - 1.0;
+ for (i = it; i <= l; ++i) {
+ ait[i - 1] += (dif[i - 1] / fextm1);
+ dif[i - 1] = ait[i - 1] - ait[i - 1 - 1];
+ }
+ } else {
+ flag = 270;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (flag == 270) {
+ fextrp = Math.max(prever / errer, aitlow);
+ prever = errer;
+ if (l < 5) {
+ flag = 40;
+ continue;
+ } else if (2.0 < l - it && istage < mxstge) {
+ reglar = true;
+ flag = 380;
+ } else if (errer / SimpleMath.pow(fextrp, maxtbl - l) < ergoal) {
+ flag = 40;
+ continue;
+ } else {
+ reglar = true;
+ flag = 380;
+ }
+ }
+
+ if (flag == 330) {
+ while (true) {
+ errer = Math.max(errer, astep * diff);
+ if (ergoal < errer) {
+ flag = 380;
+ break;
+ }
+ ++i;
+ if (i <= 4) {
+ diff = Math.abs(func.applyAsDouble(beg + rn[i - 1] * step) - fbeg2 - rn[i - 1] * slope);
+ ++fev;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, error, fev, false);
+ }
+ } else {
+ ind = 3;
+ flag = 340;
+ break;
+ }
+ }
+ }
+
+ if (flag == 340) {
+ result += vint;
+ error += errer;
+ if (right) {
+ curest += vint;
+ stage *= 2.0;
+ iend = ibeg;
+ ibeg = ibegs[istage - 1];
+ end = beg;
+ beg = begin[istage - 1];
+ fend = fbeg;
+ fbeg = ts[ibeg - 1];
+ right = false;
+ } else {
+ --istage;
+ if (istage == 0) {
+ return new QuadratureResult(result, error, fev, true);
+ }
+ reglar = reglsv[istage - 1];
+ beg = begin[istage - 1];
+ end = finis[istage - 1];
+ curest = curest - est[istage + 1 - 1] + vint;
+ iend = ibeg - 1;
+ fend = ts[iend - 1];
+ ibeg = ibegs[istage - 1];
+ right = true;
+ beg = (beg + end) / 2.0;
+ ibeg = (ibeg + iend) >> 1;
+ ts[ibeg - 1] /= 2.0;
+ fbeg = ts[ibeg - 1];
+ }
+ step = end - beg;
+ astep = Math.abs(step);
+ if (astep < stepmn) {
+ ind = 5;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ t[1 - 1][1 - 1] = fbeg + fend;
+ tabs = Math.abs(fbeg) + Math.abs(fend);
+ l = n = 1;
+ h2conv = aitken = false;
+ flag = 40;
+ continue;
+ }
+
+ if (flag == 380) {
+ if (istage == mxstge) {
+ ind = 5;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ if (!right) {
+ reglsv[istage + 1 - 1] = reglar;
+ begin[istage - 1] = beg;
+ ibegs[istage - 1] = ibeg;
+ stage /= 2.0;
+ right = true;
+ beg = (beg + end) / 2.0;
+ ibeg = (ibeg + iend) >> 1;
+ ts[ibeg - 1] /= 2.0;
+ fbeg = ts[ibeg - 1];
+ } else {
+
+ nnleft = ibeg - ibegs[istage - 1];
+ if (maxts <= end + nnleft) {
+ ind = 4;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ iii = ibegs[istage - 1];
+ ii = iend;
+ for (i = iii; i <= ibeg; ++i) {
+ ++ii;
+ ts[ii - 1] = ts[i - 1];
+ }
+ for (i = ibeg; i <= ii; ++i) {
+ ts[iii - 1] = ts[i - 1];
+ ++iii;
+ }
+
+ ++iend;
+ ibeg = iend - nnleft;
+ fend = fbeg;
+ fbeg = ts[ibeg - 1];
+ finis[istage - 1] = end;
+ end = beg;
+ beg = begin[istage - 1];
+ begin[istage - 1] = end;
+ reglsv[istage - 1] = reglar;
+ ++istage;
+ reglar = reglsv[istage - 1];
+ est[istage - 1] = vint;
+ curest += est[istage - 1];
+ right = false;
+ }
+ step = end - beg;
+ astep = Math.abs(step);
+ if (astep < stepmn) {
+ ind = 5;
+ return new QuadratureResult(curest + vint, error, fev, true);
+ }
+ t[1 - 1][1 - 1] = fbeg + fend;
+ tabs = Math.abs(fbeg) + Math.abs(fend);
+ l = n = 1;
+ h2conv = aitken = false;
+ flag = 40;
+ }
}
+ }
+
+ private final QuadratureResult havie(final DoubleUnaryOperator func, final double a,
+ final double b, final int iop) {
+ double alf, alfnj, alfno = 0.0, ar = 0.0, bet, betnj, betno, const1, const2, deltan,
+ endpts = 0.0, error, fac1 = 0.411233516712057, fac2 = 0.822467033441132, factor, gamman,
+ hnstep, pi = Math.PI, r1, r2, rn, rnderr, rounde, tend = 0.0, triarg = 0.0, umid, xmin,
+ xplus, epsout = Double.NaN;
+ int i, index = 0, iout = 0, j, n, nhalf, nupper = 9, fev = 0;
+ final double[] acof = new double[11], bcof = new double[nupper + 1];
+
+ // Set coefficients in formula for accumulated roundoff error,
+ // rounde = rnderr*(r1+r2*n), where r1, r2 are two empirical constants
+ // and n is the current number of function values used.
+ rnderr = Constants.EPSILON;
+ if (iop == 2) {
+ r1 = 50.0;
+ } else {
+ r1 = 1.0;
+ }
+ if (iop == 1) {
+ r2 = 0.02;
+ } else {
+ r2 = 2.0;
+ }
+ error = myTol;
- private final QuadratureResult havie(final DoubleUnaryOperator func, final double a,
- final double b,
- final int iop) {
- double alf, alfnj, alfno = 0.0, ar = 0.0, bet, betnj, betno, const1, const2, deltan, endpts = 0.0, error,
- fac1 = 0.411233516712057, fac2 = 0.822467033441132, factor, gamman, hnstep, pi = Math.PI, r1, r2, rn,
- rnderr, rounde, tend = 0.0, triarg = 0.0, umid, xmin, xplus, epsout = Double.NaN;
- int i, index = 0, iout = 0, j, n, nhalf, nupper = 9, fev = 0;
- final double[] acof = new double[11], bcof = new double[nupper + 1];
-
- // Set coefficients in formula for accumulated roundoff error,
- // rounde = rnderr*(r1+r2*n), where r1, r2 are two empirical constants
- // and n is the current number of function values used.
- rnderr = Constants.EPSILON;
- if (iop == 2) {
- r1 = 50.0;
- } else {
- r1 = 1.0;
- }
- if (iop == 1) {
- r2 = 0.02;
- } else {
- r2 = 2.0;
- }
- error = myTol;
-
- // Initial calculations.
- alf = 0.5 * (b - a);
- bet = 0.5 * (a + b);
+ // Initial calculations.
+ alf = 0.5 * (b - a);
+ bet = 0.5 * (a + b);
acof[1 - 1] = func.applyAsDouble(a) + func.applyAsDouble(b);
- fev += 2;
+ fev += 2;
bcof[1 - 1] = func.applyAsDouble(bet);
- ++fev;
-
- // Modified Romberg algorithm, ordinary case.
- if (iop != 2) {
- hnstep = 2.0;
- bcof[1 - 1] *= hnstep;
- factor = 1.0;
- } else {
-
- // Modified Romberg, cosine transformed case.
- hnstep = pi;
- ar = fac1;
- endpts = acof[1 - 1];
- acof[1 - 1] *= fac2;
- bcof[1 - 1] = hnstep * bcof[1 - 1] - ar * endpts;
- factor = 4.0;
- ar /= 4.0;
- triarg = pi / 4.0;
- alfno = -1.0;
- }
- hnstep *= 0.5;
- nhalf = 1;
- n = 2;
- rn = 2.0;
- acof[1 - 1] = 0.5 * (acof[1 - 1] + bcof[1 - 1]);
- acof[2 - 1] = acof[1 - 1] - (acof[1 - 1] - bcof[1 - 1]) / (4.0 * factor - 1.0);
-
- // End of initial calculation. Start actual calculations.
- for (i = 1; i <= nupper; ++i) {
- umid = 0.0;
-
- if (iop == 1) {
-
- // Modified Romberg algorithm, ordinary case.
- // compute first element in mid-point formula for ordinary case
- alfnj = 0.5 * hnstep;
- for (j = 1; j <= nhalf; ++j) {
- xplus = alf * alfnj + bet;
- xmin = -alf * alfnj + bet;
- umid += (func.applyAsDouble(xplus) + func.applyAsDouble(xmin));
- fev += 2;
- alfnj += hnstep;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, epsout, fev, false);
- }
- }
- umid *= hnstep;
- } else if (iop == 2) {
-
- // Modified Romberg algorithm, cosine transformed case
- // compute first element in mid-point formula for cosine
- // transformed Romberg algorithm.
- const1 = -Math.sin(triarg);
- const2 = 0.5 * alfno / const1;
- alfno = const1;
- betno = const2;
- gamman = 1.0 - 2.0 * alfno * alfno;
- deltan = -2.0 * alfno * betno;
- for (j = 1; j <= nhalf; ++j) {
- alfnj = gamman * const1 + deltan * const2;
- betnj = gamman * const2 - deltan * const1;
- xplus = alf * alfnj + bet;
- xmin = -alf * alfnj + bet;
- umid += betnj * (func.applyAsDouble(xplus) + func.applyAsDouble(xmin));
- fev += 2;
- const1 = alfnj;
- const2 = betnj;
- if (fev >= myMaxEvals) {
- return new QuadratureResult(Double.NaN, epsout, fev, false);
- }
- }
- umid = hnstep * umid - ar * endpts;
- ar /= 4.0;
- }
-
- // Modified Romberg algorithm, calculate (i+1)-th row in the U table.
- const1 = 4.0 * factor;
- index = i + 1;
- for (j = 2; j <= i + 1; ++j) {
- tend = umid + (umid - bcof[j - 1 - 1]) / (const1 - 1.0);
- bcof[j - 1 - 1] = umid;
- umid = tend;
- const1 *= 4.0;
- }
- bcof[i + 1 - 1] = tend;
- xplus = const1;
-
- // Calculation of (i+1)-th row in the U table is finished
- // Test to see if the required accuracy has been obtained.
- epsout = 1.0;
- iout = 1;
- for (j = 1; j <= index; ++j) {
- const1 = 0.5 * (acof[j - 1] + bcof[j - 1]);
- const2 = 0.5 * Math.abs((acof[j - 1] - bcof[j - 1]) / const1);
- if (const2 <= epsout) {
- epsout = const2;
- iout = j;
- }
- acof[j - 1] = const1;
- }
-
- // Testing on accuracy finished
- if (iout == index) {
- ++iout;
- }
- acof[index + 1 - 1] = acof[index - 1] - (acof[index - 1] - bcof[index - 1]) / (xplus - 1.0);
- rounde = rnderr * (r1 + r2 * rn);
- epsout = Math.max(epsout, rounde);
- error = Math.max(error, rounde);
- if (epsout <= error) {
-
- // Calculation for modified Romberg algorithm finished.
- n <<= 1;
- --index;
- ++n;
- return new QuadratureResult(alf * acof[iout - 1], epsout, fev, true);
- }
- nhalf = n;
- n <<= 1;
- rn *= 2.0;
- hnstep *= 0.5;
- if (1 < iop) {
- triarg *= 0.5;
- }
- }
-
- // Accuracy not reached with maximum number of subdivisions.
- n = nhalf;
-
- // Calculation for modified Romberg algorithm finished.
- n <<= 1;
- --index;
- ++n;
- return new QuadratureResult(alf * acof[iout - 1], epsout, fev, true);
+ ++fev;
+
+ // Modified Romberg algorithm, ordinary case.
+ if (iop != 2) {
+ hnstep = 2.0;
+ bcof[1 - 1] *= hnstep;
+ factor = 1.0;
+ } else {
+
+ // Modified Romberg, cosine transformed case.
+ hnstep = pi;
+ ar = fac1;
+ endpts = acof[1 - 1];
+ acof[1 - 1] *= fac2;
+ bcof[1 - 1] = hnstep * bcof[1 - 1] - ar * endpts;
+ factor = 4.0;
+ ar /= 4.0;
+ triarg = pi / 4.0;
+ alfno = -1.0;
+ }
+ hnstep *= 0.5;
+ nhalf = 1;
+ n = 2;
+ rn = 2.0;
+ acof[1 - 1] = 0.5 * (acof[1 - 1] + bcof[1 - 1]);
+ acof[2 - 1] = acof[1 - 1] - (acof[1 - 1] - bcof[1 - 1]) / (4.0 * factor - 1.0);
+
+ // End of initial calculation. Start actual calculations.
+ for (i = 1; i <= nupper; ++i) {
+ umid = 0.0;
+
+ if (iop == 1) {
+
+ // Modified Romberg algorithm, ordinary case.
+ // compute first element in mid-point formula for ordinary case
+ alfnj = 0.5 * hnstep;
+ for (j = 1; j <= nhalf; ++j) {
+ xplus = alf * alfnj + bet;
+ xmin = -alf * alfnj + bet;
+ umid += (func.applyAsDouble(xplus) + func.applyAsDouble(xmin));
+ fev += 2;
+ alfnj += hnstep;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, epsout, fev, false);
+ }
+ }
+ umid *= hnstep;
+ } else if (iop == 2) {
+
+ // Modified Romberg algorithm, cosine transformed case
+ // compute first element in mid-point formula for cosine
+ // transformed Romberg algorithm.
+ const1 = -Math.sin(triarg);
+ const2 = 0.5 * alfno / const1;
+ alfno = const1;
+ betno = const2;
+ gamman = 1.0 - 2.0 * alfno * alfno;
+ deltan = -2.0 * alfno * betno;
+ for (j = 1; j <= nhalf; ++j) {
+ alfnj = gamman * const1 + deltan * const2;
+ betnj = gamman * const2 - deltan * const1;
+ xplus = alf * alfnj + bet;
+ xmin = -alf * alfnj + bet;
+ umid += betnj * (func.applyAsDouble(xplus) + func.applyAsDouble(xmin));
+ fev += 2;
+ const1 = alfnj;
+ const2 = betnj;
+ if (fev >= myMaxEvals) {
+ return new QuadratureResult(Double.NaN, epsout, fev, false);
+ }
+ }
+ umid = hnstep * umid - ar * endpts;
+ ar /= 4.0;
+ }
+
+ // Modified Romberg algorithm, calculate (i+1)-th row in the U table.
+ const1 = 4.0 * factor;
+ index = i + 1;
+ for (j = 2; j <= i + 1; ++j) {
+ tend = umid + (umid - bcof[j - 1 - 1]) / (const1 - 1.0);
+ bcof[j - 1 - 1] = umid;
+ umid = tend;
+ const1 *= 4.0;
+ }
+ bcof[i + 1 - 1] = tend;
+ xplus = const1;
+
+ // Calculation of (i+1)-th row in the U table is finished
+ // Test to see if the required accuracy has been obtained.
+ epsout = 1.0;
+ iout = 1;
+ for (j = 1; j <= index; ++j) {
+ const1 = 0.5 * (acof[j - 1] + bcof[j - 1]);
+ const2 = 0.5 * Math.abs((acof[j - 1] - bcof[j - 1]) / const1);
+ if (const2 <= epsout) {
+ epsout = const2;
+ iout = j;
+ }
+ acof[j - 1] = const1;
+ }
+
+ // Testing on accuracy finished
+ if (iout == index) {
+ ++iout;
+ }
+ acof[index + 1 - 1] = acof[index - 1] - (acof[index - 1] - bcof[index - 1]) / (xplus - 1.0);
+ rounde = rnderr * (r1 + r2 * rn);
+ epsout = Math.max(epsout, rounde);
+ error = Math.max(error, rounde);
+ if (epsout <= error) {
+
+ // Calculation for modified Romberg algorithm finished.
+ n <<= 1;
+ --index;
+ ++n;
+ return new QuadratureResult(alf * acof[iout - 1], epsout, fev, true);
+ }
+ nhalf = n;
+ n <<= 1;
+ rn *= 2.0;
+ hnstep *= 0.5;
+ if (1 < iop) {
+ triarg *= 0.5;
+ }
}
+
+ // Accuracy not reached with maximum number of subdivisions.
+ n = nhalf;
+
+ // Calculation for modified Romberg algorithm finished.
+ n <<= 1;
+ --index;
+ ++n;
+ return new QuadratureResult(alf * acof[iout - 1], epsout, fev, true);
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Simpson.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Simpson.java
index 5a406612d..37b5f3a5e 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Simpson.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/integral/Simpson.java
@@ -94,9 +94,8 @@ public final String getName() {
return myMethod.toString() + "-Simpson";
}
- private static final double[] simpson13(final DoubleUnaryOperator func,
- final double a, final double mid, final double b, final double fa, final double fmid,
- final double fb) {
+ private static final double[] simpson13(final DoubleUnaryOperator func, final double a,
+ final double mid, final double b, final double fa, final double fmid, final double fb) {
final double lmid = 0.5 * (a + mid);
final double rmid = 0.5 * (mid + b);
final double flmid = func.applyAsDouble(lmid);
@@ -110,8 +109,8 @@ private static final double[] simpson13(final DoubleUnaryOperator func,
return result;
}
- private final QuadratureResult globalSimpson(final DoubleUnaryOperator func,
- final double a, final double b) {
+ private final QuadratureResult globalSimpson(final DoubleUnaryOperator func, final double a,
+ final double b) {
// estimate the error on [a, b] using Lyness'-Richardson
final double m0 = 0.5 * (a + b);
@@ -182,8 +181,8 @@ private final QuadratureResult globalSimpson(final DoubleUnaryOperator func,
return new QuadratureResult(est, error, fev, true);
}
- private final QuadratureResult localSimpson(final DoubleUnaryOperator func,
- final double a, final double b) {
+ private final QuadratureResult localSimpson(final DoubleUnaryOperator func, final double a,
+ final double b) {
// initialize the first interval
final double m0 = 0.5 * (a + b);
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/series/special/EulerMaclaurin.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/series/special/EulerMaclaurin.java
index 5e19fbc04..2eeb030a4 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/series/special/EulerMaclaurin.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/series/special/EulerMaclaurin.java
@@ -15,282 +15,283 @@
*/
public final class EulerMaclaurin {
- public static enum EulerMaclaurinErrorCode {
- NO_ERROR, TOO_MANY_EVALS, BIN_TOO_LARGE, DERIVATIVE_ESTIMATION_FAILED, INTEGRAL_LOWER_BOUND_SEARCH_FAILED,
- SERIES_ACCELERATION_FAILED, PIECEWISE_INTEGRATION_FAILED
+ public static enum EulerMaclaurinErrorCode {
+ NO_ERROR, TOO_MANY_EVALS, BIN_TOO_LARGE, DERIVATIVE_ESTIMATION_FAILED, INTEGRAL_LOWER_BOUND_SEARCH_FAILED, SERIES_ACCELERATION_FAILED, PIECEWISE_INTEGRATION_FAILED
+ }
+
+ private static final double STEP = 1.4;
+ private static final double DECAY = 0.1;
+ private static final int WORK_MEMORY_FOR_RIDDER = 100;
+ private static final int MAX_RANGE = 1 << 12;
+ private static final double MAX_BIN = 1e30;
+
+ private final boolean myVerbose;
+ private final double myTol;
+ private final Quadrature myQuad;
+ private final SeriesAlgorithm myAccelerator;
+ private final Function super Long, Double> myBins;
+
+ private int myFEvals, myDEvals;
+ private final double[] myWorkArray = new double[2];
+ private List myErrorCodes;
+
+ /**
+ *
+ * @param tolerance
+ * @param integrator
+ * @param accelerator
+ * @param binSequence
+ */
+ public EulerMaclaurin(final double tolerance, final Quadrature integrator,
+ final SeriesAlgorithm accelerator, final Function super Long, Double> binSequence,
+ final boolean verbose) {
+ myTol = tolerance;
+ myQuad = integrator;
+ myAccelerator = accelerator;
+ myBins = binSequence;
+ myVerbose = verbose;
+ }
+
+ /**
+ *
+ * @param tolerance
+ * @param integrator
+ * @param binSequence
+ */
+ public EulerMaclaurin(final double tolerance, final Quadrature integrator,
+ final SeriesAlgorithm accelerator, final Function super Long, Double> binSequence) {
+ this(tolerance, integrator, accelerator, binSequence, false);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public final int getEvaluations() {
+ return myFEvals;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public final int getDEvaluations() {
+ return myDEvals;
+ }
+
+ /*
+ *
+ */
+ public final List getErrorStack() {
+ return Collections.unmodifiableList(myErrorCodes);
+ }
+
+ // ==========================================================================
+ // SERIES EVALUATION USING EULER-MACLAURIN INTEGRATION
+ // ==========================================================================
+ /**
+ *
+ * @param f
+ * @param df
+ * @param start
+ * @return
+ */
+ public final double limit(final Function super Double, Double> f,
+ final Function super Double, Double> df, final long start) {
+ myFEvals = myDEvals = 0;
+ myErrorCodes = new ArrayList<>();
+
+ // find an N large enough so that the error estimate <= tol
+ final long n = determineLowerBound(f, df, start);
+ if (n < 0) {
+ myErrorCodes.add(EulerMaclaurinErrorCode.INTEGRAL_LOWER_BOUND_SEARCH_FAILED);
+ return Double.NaN;
}
- private static final double STEP = 1.4;
- private static final double DECAY = 0.1;
- private static final int WORK_MEMORY_FOR_RIDDER = 100;
- private static final int MAX_RANGE = 1 << 12;
- private static final double MAX_BIN = 1e30;
-
- private final boolean myVerbose;
- private final double myTol;
- private final Quadrature myQuad;
- private final SeriesAlgorithm myAccelerator;
- private final Function super Long, Double> myBins;
-
- private int myFEvals, myDEvals;
- private final double[] myWorkArray = new double[2];
- private List myErrorCodes;
-
- /**
- *
- * @param tolerance
- * @param integrator
- * @param accelerator
- * @param binSequence
- */
- public EulerMaclaurin(final double tolerance, final Quadrature integrator, final SeriesAlgorithm accelerator,
- final Function super Long, Double> binSequence, final boolean verbose) {
- myTol = tolerance;
- myQuad = integrator;
- myAccelerator = accelerator;
- myBins = binSequence;
- myVerbose = verbose;
- }
-
- /**
- *
- * @param tolerance
- * @param integrator
- * @param binSequence
- */
- public EulerMaclaurin(final double tolerance, final Quadrature integrator, final SeriesAlgorithm accelerator,
- final Function super Long, Double> binSequence) {
- this(tolerance, integrator, accelerator, binSequence, false);
- }
-
- /**
- *
- * @return
- */
- public final int getEvaluations() {
- return myFEvals;
- }
-
- /**
- *
- * @return
- */
- public final int getDEvaluations() {
- return myDEvals;
- }
-
- /*
- *
- */
- public final List getErrorStack() {
- return Collections.unmodifiableList(myErrorCodes);
- }
-
- // ==========================================================================
- // SERIES EVALUATION USING EULER-MACLAURIN INTEGRATION
- // ==========================================================================
- /**
- *
- * @param f
- * @param df
- * @param start
- * @return
- */
- public final double limit(final Function super Double, Double> f, final Function super Double, Double> df,
- final long start) {
- myFEvals = myDEvals = 0;
- myErrorCodes = new ArrayList<>();
-
- // find an N large enough so that the error estimate <= tol
- final long n = determineLowerBound(f, df, start);
- if (n < 0) {
- myErrorCodes.add(EulerMaclaurinErrorCode.INTEGRAL_LOWER_BOUND_SEARCH_FAILED);
- return Double.NaN;
- }
-
- // estimate sum
- final double sum = finiteSum(f, start, n);
-
- // compute the two lower bounds using an integral from N + 1/2 to infinity
- final double integral = improperIntegral(f, n);
- final double lower = lowerBound(f, df, n);
- final double upper = upperBound(f, df, n);
- return 0.5 * (lower + upper) + sum + integral;
- }
-
- /**
- *
- * @param f
- * @param start
- * @return
- */
- public final double limit(final Function super Double, Double> f, final long start) {
- return limit(f, null, start);
- }
-
- private final double improperIntegral(final Function super Double, Double> f, final long n) {
- myWorkArray[0] = 0.0;
- final Function seq = k -> {
-
- // compute bounds of integration according to provided bins
- final double s1 = myWorkArray[0];
- final double s2 = s1 + myBins.apply(k);
- myWorkArray[0] = s2;
- if (s2 > MAX_BIN) {
- myErrorCodes.add(EulerMaclaurinErrorCode.BIN_TOO_LARGE);
- return Double.NaN;
- }
-
- // perform a change of variable to integrate on [0, 1]
+ // estimate sum
+ final double sum = finiteSum(f, start, n);
+
+ // compute the two lower bounds using an integral from N + 1/2 to infinity
+ final double integral = improperIntegral(f, n);
+ final double lower = lowerBound(f, df, n);
+ final double upper = upperBound(f, df, n);
+ return 0.5 * (lower + upper) + sum + integral;
+ }
+
+ /**
+ *
+ * @param f
+ * @param start
+ * @return
+ */
+ public final double limit(final Function super Double, Double> f, final long start) {
+ return limit(f, null, start);
+ }
+
+ private final double improperIntegral(final Function super Double, Double> f, final long n) {
+ myWorkArray[0] = 0.0;
+ final Function seq = k -> {
+
+ // compute bounds of integration according to provided bins
+ final double s1 = myWorkArray[0];
+ final double s2 = s1 + myBins.apply(k);
+ myWorkArray[0] = s2;
+ if (s2 > MAX_BIN) {
+ myErrorCodes.add(EulerMaclaurinErrorCode.BIN_TOO_LARGE);
+ return Double.NaN;
+ }
+
+ // perform a change of variable to integrate on [0, 1]
final DoubleUnaryOperator f01 = t -> {
- final double interp = (1.0 - t) * s1 + t * s2;
- return f.apply(n + 0.5 + interp);
- };
-
- // apply numerical integration to this new function
- double integrand = myQuad.integrate(f01, 0.0, 1.0).estimate;
- if (Double.isNaN(integrand)) {
- myErrorCodes.add(EulerMaclaurinErrorCode.PIECEWISE_INTEGRATION_FAILED);
- }
- integrand *= (s2 - s1);
- return integrand;
- };
-
- // accelerate the series of definite integrals
- final double result = myAccelerator.limit(Sequences.toIterable(seq, 1L), true).limit;
- if (Double.isNaN(result)) {
- myErrorCodes.add(EulerMaclaurinErrorCode.SERIES_ACCELERATION_FAILED);
- }
- return result;
+ final double interp = (1.0 - t) * s1 + t * s2;
+ return f.apply(n + 0.5 + interp);
+ };
+
+ // apply numerical integration to this new function
+ double integrand = myQuad.integrate(f01, 0.0, 1.0).estimate;
+ if (Double.isNaN(integrand)) {
+ myErrorCodes.add(EulerMaclaurinErrorCode.PIECEWISE_INTEGRATION_FAILED);
+ }
+ integrand *= (s2 - s1);
+ return integrand;
+ };
+
+ // accelerate the series of definite integrals
+ final double result = myAccelerator.limit(Sequences.toIterable(seq, 1L), true).limit;
+ if (Double.isNaN(result)) {
+ myErrorCodes.add(EulerMaclaurinErrorCode.SERIES_ACCELERATION_FAILED);
}
-
- private final double finiteSum(final Function super Double, Double> f, final long start, final long end) {
- double sum = 0.0;
- for (long k = start; k <= end; ++k) {
- sum += f.apply((double) k);
- }
- myFEvals += end - start + 1;
- return sum;
- }
-
- private final long determineLowerBound(final Function super Double, Double> f,
- final Function super Double, Double> df, final long start) {
- long a = start;
- long b = MAX_RANGE;
- long n = -1L;
-
- // do binary search to find a suitable bound
- while (a != b) {
- final long mid = SimpleMath.average(a, b);
- final double error = estimateError(f, df, mid);
- if (Double.isNaN(error)) {
- return -1L;
- } else if (!Double.isFinite(error)) {
- b = mid;
- } else if (error > myTol) {
- a = mid + 1L;
- } else {
- b = n = mid;
- }
- }
- final double error = estimateError(f, df, a);
- if (error <= myTol) {
- n = a;
- }
- if (myVerbose) {
- System.out.println("Lower bound of integral = " + n + " with error = " + error + ".");
- }
- return n;
+ return result;
+ }
+
+ private final double finiteSum(final Function super Double, Double> f, final long start,
+ final long end) {
+ double sum = 0.0;
+ for (long k = start; k <= end; ++k) {
+ sum += f.apply((double) k);
}
-
- // ==========================================================================
- // ERROR ESTIMATION FOR MACLAURIN FORMULA
- // ==========================================================================
- private final double estimateError(final Function super Double, Double> f,
- final Function super Double, Double> df, final long x) {
- return Math.abs(upperBound(f, df, x) - lowerBound(f, df, x)) / 2.0;
+ myFEvals += end - start + 1;
+ return sum;
+ }
+
+ private final long determineLowerBound(final Function super Double, Double> f,
+ final Function super Double, Double> df, final long start) {
+ long a = start;
+ long b = MAX_RANGE;
+ long n = -1L;
+
+ // do binary search to find a suitable bound
+ while (a != b) {
+ final long mid = SimpleMath.average(a, b);
+ final double error = estimateError(f, df, mid);
+ if (Double.isNaN(error)) {
+ return -1L;
+ } else if (!Double.isFinite(error)) {
+ b = mid;
+ } else if (error > myTol) {
+ a = mid + 1L;
+ } else {
+ b = n = mid;
+ }
}
-
- private final double lowerBound(final Function super Double, Double> f, final Function super Double, Double> df,
- final long x) {
- return deriv(f, df, -0.5 + x) / 24.0;
+ final double error = estimateError(f, df, a);
+ if (error <= myTol) {
+ n = a;
}
-
- private final double upperBound(final Function super Double, Double> f, final Function super Double, Double> df,
- final long x) {
- return deriv(f, df, +1.5 + x) / 24.0;
+ if (myVerbose) {
+ System.out.println("Lower bound of integral = " + n + " with error = " + error + ".");
}
-
- // ==========================================================================
- // APPROXIMATE AND EXACT NUMERICAL DIFFERENTIATION
- // ==========================================================================
- private final double deriv(final Function super Double, Double> f, final Function super Double, Double> df,
- final double x) {
- if (df == null) {
- return derivRidder(f, x);
- } else {
- ++myDEvals;
- return df.apply(x);
- }
+ return n;
+ }
+
+ // ==========================================================================
+ // ERROR ESTIMATION FOR MACLAURIN FORMULA
+ // ==========================================================================
+ private final double estimateError(final Function super Double, Double> f,
+ final Function super Double, Double> df, final long x) {
+ return Math.abs(upperBound(f, df, x) - lowerBound(f, df, x)) / 2.0;
+ }
+
+ private final double lowerBound(final Function super Double, Double> f,
+ final Function super Double, Double> df, final long x) {
+ return deriv(f, df, -0.5 + x) / 24.0;
+ }
+
+ private final double upperBound(final Function super Double, Double> f,
+ final Function super Double, Double> df, final long x) {
+ return deriv(f, df, +1.5 + x) / 24.0;
+ }
+
+ // ==========================================================================
+ // APPROXIMATE AND EXACT NUMERICAL DIFFERENTIATION
+ // ==========================================================================
+ private final double deriv(final Function super Double, Double> f,
+ final Function super Double, Double> df, final double x) {
+ if (df == null) {
+ return derivRidder(f, x);
+ } else {
+ ++myDEvals;
+ return df.apply(x);
}
-
- private final double derivRidder(final Function super Double, Double> f, final double x) {
- double h = 1.0;
- final double[][] work = new double[WORK_MEMORY_FOR_RIDDER][WORK_MEMORY_FOR_RIDDER];
- while (h > Double.MIN_VALUE / DECAY) {
- updateRidder(f, x, h, WORK_MEMORY_FOR_RIDDER, work);
- if (Double.isNaN(myWorkArray[0])) {
- break;
- } else if (Math.abs(myWorkArray[1]) <= myTol) {
- return myWorkArray[0];
- }
- h *= DECAY;
- }
- myErrorCodes.add(EulerMaclaurinErrorCode.DERIVATIVE_ESTIMATION_FAILED);
- return Double.NaN;
+ }
+
+ private final double derivRidder(final Function super Double, Double> f, final double x) {
+ double h = 1.0;
+ final double[][] work = new double[WORK_MEMORY_FOR_RIDDER][WORK_MEMORY_FOR_RIDDER];
+ while (h > Double.MIN_VALUE / DECAY) {
+ updateRidder(f, x, h, WORK_MEMORY_FOR_RIDDER, work);
+ if (Double.isNaN(myWorkArray[0])) {
+ break;
+ } else if (Math.abs(myWorkArray[1]) <= myTol) {
+ return myWorkArray[0];
+ }
+ h *= DECAY;
}
-
- private final void updateRidder(final Function super Double, Double> f, final double x, double s, final int iwork,
- final double[][] work) {
- myWorkArray[0] = myWorkArray[1] = 0.0;
- double result = 0.0;
- double error = Double.POSITIVE_INFINITY;
- final double step2 = STEP * STEP;
-
- // uses Ridder's extrapolation method to numerically differentiate
- work[0][0] = (f.apply(x + s) - f.apply(x - s)) / (2.0 * s);
- myFEvals += 2;
- for (int i = 1; i < iwork; ++i) {
-
- // update tableau
- s /= STEP;
- work[0][i] = (f.apply(x + s) - f.apply(x - s)) / (2.0 * s);
- myFEvals += 2;
- double fx = step2;
- for (int j = 1; j <= i; ++j) {
-
- // update the tableau
- work[j][i] = (work[j - 1][i] * fx - work[j - 1][i - 1]) / (fx - 1.0);
- fx *= step2;
-
- // check for a lower-error estimate
- final double dif1 = work[j][i] - work[j - 1][i];
- final double dif2 = work[j][i] - work[j - 1][i - 1];
- final double new_error = Math.max(Math.abs(dif1), Math.abs(dif2));
- if (new_error <= error) {
- error = new_error;
- result = work[j][i];
- }
- }
-
- // check whether we can return result
- if (Math.abs(work[i][i] - work[i - 1][i - 1]) >= 2.0 * error) {
- myWorkArray[0] = result;
- myWorkArray[1] = error;
- return;
- }
- }
- myWorkArray[0] = Double.NaN;
- myWorkArray[1] = Double.POSITIVE_INFINITY;
+ myErrorCodes.add(EulerMaclaurinErrorCode.DERIVATIVE_ESTIMATION_FAILED);
+ return Double.NaN;
+ }
+
+ private final void updateRidder(final Function super Double, Double> f, final double x,
+ double s, final int iwork, final double[][] work) {
+ myWorkArray[0] = myWorkArray[1] = 0.0;
+ double result = 0.0;
+ double error = Double.POSITIVE_INFINITY;
+ final double step2 = STEP * STEP;
+
+ // uses Ridder's extrapolation method to numerically differentiate
+ work[0][0] = (f.apply(x + s) - f.apply(x - s)) / (2.0 * s);
+ myFEvals += 2;
+ for (int i = 1; i < iwork; ++i) {
+
+ // update tableau
+ s /= STEP;
+ work[0][i] = (f.apply(x + s) - f.apply(x - s)) / (2.0 * s);
+ myFEvals += 2;
+ double fx = step2;
+ for (int j = 1; j <= i; ++j) {
+
+ // update the tableau
+ work[j][i] = (work[j - 1][i] * fx - work[j - 1][i - 1]) / (fx - 1.0);
+ fx *= step2;
+
+ // check for a lower-error estimate
+ final double dif1 = work[j][i] - work[j - 1][i];
+ final double dif2 = work[j][i] - work[j - 1][i - 1];
+ final double new_error = Math.max(Math.abs(dif1), Math.abs(dif2));
+ if (new_error <= error) {
+ error = new_error;
+ result = work[j][i];
+ }
+ }
+
+ // check whether we can return result
+ if (Math.abs(work[i][i] - work[i - 1][i - 1]) >= 2.0 * error) {
+ myWorkArray[0] = result;
+ myWorkArray[1] = error;
+ return;
+ }
}
+ myWorkArray[0] = Double.NaN;
+ myWorkArray[1] = Double.POSITIVE_INFINITY;
+ }
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/Constants.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/Constants.java
index a32b0a98c..1a2e57737 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/Constants.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/Constants.java
@@ -1,33 +1,33 @@
package org.matheclipse.core.numerics.utils;
+import org.matheclipse.core.basic.Config;
+
public final class Constants {
- /**
- * The machine epsilon.
- */
- public static final double EPSILON = Math.ulp(1.0);
-
- /**
- * The closest {@code double} value to the square root of two.
- */
- public static final double SQRT2 = Math.sqrt(2.0);
-
- /**
- * The closest {@code double} value to the square root of three.
- */
- public static final double SQRT3 = Math.sqrt(3.0);
-
- /**
- * The closest {@code double} value to the square root of five.
- */
- public static final double SQRT5 = Math.sqrt(5.0);
-
- /**
- * The closest {@code double} value to the number 1 divided by the natural-base
- * logarithm of 2.
- */
- public static final double LOG2_INV = 1.4426950408889634073599;
-
- private Constants() {
- }
+ /**
+ * The machine epsilon.
+ */
+ public static final double EPSILON = Config.DOUBLE_EPSILON;
+
+ /**
+ * The closest {@code double} value to the square root of two.
+ */
+ public static final double SQRT2 = Math.sqrt(2.0);
+
+ /**
+ * The closest {@code double} value to the square root of three.
+ */
+ public static final double SQRT3 = Math.sqrt(3.0);
+
+ /**
+ * The closest {@code double} value to the square root of five.
+ */
+ public static final double SQRT5 = Math.sqrt(5.0);
+
+ /**
+ * The closest {@code double} value to the number 1 divided by the natural-base logarithm of 2.
+ */
+ public static final double LOG2_INV = 1.4426950408889634073599;
+
+ private Constants() {}
}
diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/SimpleMath.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/SimpleMath.java
index 357aa39f7..6280aefcd 100644
--- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/SimpleMath.java
+++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/numerics/utils/SimpleMath.java
@@ -2,89 +2,86 @@
public final class SimpleMath {
- // ==========================================================================
- // INTEGER MATH
- // ==========================================================================
- /**
- * Computes the integer average of two integers.
- */
- public static final int average(final int x, final int y) {
+ // ==========================================================================
+ // INTEGER MATH
+ // ==========================================================================
+ /**
+ * Computes the integer average of two integers.
+ */
+ public static final int average(final int x, final int y) {
+ // Hacker's delight 2-5 (3)
+ return (x & y) + ((x ^ y) >> 1);
+ }
- // Hacker's delight 2-5 (3)
- return (x & y) + ((x ^ y) >> 1);
- }
-
- /**
- * Computes the long average of two long values.
- */
- public static final long average(final long x, final long y) {
-
- // Hacker's delight 2-5 (3)
- return (x & y) + ((x ^ y) >> 1);
- }
+ /**
+ * Computes the long average of two long values.
+ */
+ public static final long average(final long x, final long y) {
+ // Hacker's delight 2-5 (3)
+ return (x & y) + ((x ^ y) >> 1);
+ }
- /**
- * Computes the floor of the base-two logarith of the specified integer.
- */
- public static final int log2Int(final int n) {
- if (n <= 0) {
- throw new IllegalArgumentException();
- }
- return 31 - Integer.numberOfLeadingZeros(n);
+ /**
+ * Computes the floor of the base-two logarith of the specified integer.
+ */
+ public static final int log2Int(final int n) {
+ if (n <= 0) {
+ throw new IllegalArgumentException();
}
+ return 31 - Integer.numberOfLeadingZeros(n);
+ }
- // ==========================================================================
- // FLOATING POINT MATH
- // ==========================================================================
- public static final double[] D1MACH = { Double.MIN_VALUE, Double.MAX_VALUE, pow(2.0, -52), pow(2.0, -51),
- Math.log(2.0) / Math.log(10.0) };
+ // ==========================================================================
+ // FLOATING POINT MATH
+ // ==========================================================================
+ public static final double[] D1MACH = {Double.MIN_VALUE, Double.MAX_VALUE, pow(2.0, -52),
+ pow(2.0, -51), Math.log(2.0) / Math.log(10.0)};
- /**
- * Applies the sign of b to a.
- */
- public static final double sign(final double a, final double b) {
- return b >= 0.0 ? Math.abs(a) : -Math.abs(a);
- }
-
- /**
- * Computes the exponent of x raised to y, using exponentiation by squaring.
- */
- public static final double pow(double x, int y) {
+ /**
+ * Applies the sign of b to a.
+ */
+ public static final double sign(final double a, final double b) {
+ return b >= 0.0 ? Math.abs(a) : -Math.abs(a);
+ }
- // negative power
- if (y < 0) {
- return pow(1.0 / x, -y);
- }
+ /**
+ * Computes the exponent of x raised to y, using exponentiation by squaring.
+ */
+ public static final double pow(double x, int y) {
- // trivial cases
- switch (y) {
- case 0:
- return 1.0;
- case 1:
- return x;
- case 2:
- return x * x;
- default:
- break;
- }
+ // negative power
+ if (y < 0) {
+ return pow(1.0 / x, -y);
+ }
- // non trivial case
- double res = 1.0;
- while (y != 0) {
- switch (y & 1) {
- case 0:
- x *= x;
- y >>>= 1;
- break;
- default:
- res *= x;
- --y;
- break;
- }
- }
- return res;
+ // trivial cases
+ switch (y) {
+ case 0:
+ return 1.0;
+ case 1:
+ return x;
+ case 2:
+ return x * x;
+ default:
+ break;
}
- private SimpleMath() {
+ // non trivial case
+ double res = 1.0;
+ while (y != 0) {
+ switch (y & 1) {
+ case 0:
+ x *= x;
+ y >>>= 1;
+ break;
+ default:
+ res *= x;
+ --y;
+ break;
+ }
}
+ return res;
+ }
+
+ private SimpleMath() {}
}