Skip to content

Commit

Permalink
WIP #1064 Added error message for not converging integral
Browse files Browse the repository at this point in the history
- idiv - Integral of `1` does not converge on `2`.
- JUnit test for this issue `testXReciprocalIssue1064()`
- `NIntegrate` with `LegendreGauss` method was called as default, other
`NIntegrate` methods don't return a result
  • Loading branch information
axkr committed Sep 13, 2024
1 parent 5c37de0 commit 87689e1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public static void initGeneralMessages() {
"herm", "The matrix `1` is not hermitian or real and symmetric.", //
"idim", "`1` and `2` must have the same length.", //
"idir", "Direction vector `1` has zero magnitude.", //
"idiv", "Integral of `1` does not converge on `2`.", //
"ifun", "Inverse functions are being used. Values may be lost for multivalued inverses.", //
"ilsmn",
"Single or list of non-negative machine-sized integers expected at position `1` of `2`.", //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public IExpr evaluate(IAST holdallAST, final int argSize, final IExpr[] option,
IAST copy = holdallAST.setAtCopy(2, xList.arg1());
IExpr temp = engine.evaluate(copy);
if (temp.isFreeAST(S.Integrate)) {
return definiteIntegral(temp, xList, engine);
return definiteIntegral(temp, xList, holdallAST, engine);
}
return F.NIL;
}
Expand Down Expand Up @@ -633,7 +633,8 @@ private static IExpr integrateAbs(IExpr function, final IExpr x) {
* @param engine the evaluation engine
* @return
*/
private static IExpr definiteIntegral(IExpr function, IAST xValueList, EvalEngine engine) {
private static IExpr definiteIntegral(IExpr function, IAST xValueList, IAST originalAST,
EvalEngine engine) {
// see Rubi rule for definite integrals
IExpr x = xValueList.arg1();
IExpr lower = xValueList.arg2();
Expand All @@ -653,11 +654,21 @@ private static IExpr definiteIntegral(IExpr function, IAST xValueList, EvalEngin
}
IExpr lowerLimit = engine.evaluate(F.Limit(function, F.Rule(x, lower), lowerDirection));
if (!lowerLimit.isFree(S.DirectedInfinity, true) || !lowerLimit.isFree(S.Indeterminate, true)) {
if (lowerLimit.isDirectedInfinity() || lowerLimit.isIndeterminate()) {
// Integral of `1` does not converge on `2`.
return Errors.printMessage(S.Integrate, "idiv", F.List(originalAST.arg1(), xValueList),
engine);
}
LOGGER.log(engine.getLogLevel(), "Not integrable: {} for limit {} -> {}", function, x, lower);
return F.NIL;
}
IExpr upperLimit = engine.evaluate(F.Limit(function, F.Rule(x, upper), upperDirection));
if (!upperLimit.isFree(S.DirectedInfinity, true) || !upperLimit.isFree(S.Indeterminate, true)) {
if (upperLimit.isDirectedInfinity() || upperLimit.isIndeterminate()) {
// Integral of `1` does not converge on `2`.
return Errors.printMessage(S.Integrate, "idiv", F.List(originalAST.arg1(), xValueList),
engine);
}
LOGGER.log(engine.getLogLevel(), "Not integrable: {} for limit {} -> {}", function, x, upper);
return F.NIL;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.matheclipse.core.generic.UnaryNumerical;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IReal;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.core.numerics.integral.ClenshawCurtis;
import org.matheclipse.core.numerics.integral.GaussLobatto;
Expand Down Expand Up @@ -109,8 +108,6 @@ public class NIntegrate extends AbstractFunctionEvaluator {
*/
public static double integrate(String method, IAST list, final double min, final double max,
IExpr function, int maxPoints, int maxIterations) throws MathIllegalStateException {
GaussIntegratorFactory factory = new GaussIntegratorFactory();

if (!list.arg1().isSymbol()) {
// `1` is not a valid variable.
String str = Errors.getMessage("ivar", F.list(list.arg1()), EvalEngine.get());
Expand Down Expand Up @@ -173,7 +170,9 @@ public static double integrate(String method, IAST list, final double min, final
if (min == Double.NEGATIVE_INFINITY || max == Double.POSITIVE_INFINITY) {
return gausKronrodRule(maxIterations, f, min, max);
}

// default: LegendreGauss
GaussIntegratorFactory factory = new GaussIntegratorFactory();
GaussIntegrator integ = factory.legendre(maxPoints, min, max);
return integ.integrate(f);
}
Expand Down Expand Up @@ -242,7 +241,7 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
}
option = options.getOption(S.MaxPoints);
if (option.isReal()) {
maxPoints = ((IReal) option).toIntDefault(-1);
maxPoints = option.toIntDefault(-1);
if (maxPoints <= 0) {
// Inappropriate parameter: `1`.
return Errors.printMessage(ast.topHead(), "par", F.List(S.MaxPoints), engine);
Expand All @@ -258,7 +257,7 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
}
option = options.getOption(S.PrecisionGoal);
if (option.isReal()) {
precisionGoal = ((IReal) option).toIntDefault(-1);
precisionGoal = option.toIntDefault(-1);
if (precisionGoal <= 0) {
// Inappropriate parameter: `1`.
return Errors.printMessage(ast.topHead(), "par", F.List(S.PrecisionGoal), engine);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,19 @@ public void testN_Integrate() {
"6.36777");
}

@Test
public void testXReciprocalIssue1064() {
// message - NIntegrate: maximal count (10,000) exceeded.
check("NIntegrate(1/x, {x,0,1},Method->\"GaussKronrod\")", //
"NIntegrate(1/x,{x,0,1},Method->GaussKronrod)");
check("NIntegrate(1/x, {x,0,1},Method->\"LegendreGauss\")", //
"10.37476");
check("N(Integrate(1/x, {x,0,1}))", //
"10.37476");

// message - Integrate: Integral of 1/x does not converge on {x,0,1}.
check("Integrate(1/x, {x,0,1})", //
"Integrate(1/x,{x,0,1})");
}

}

0 comments on commit 87689e1

Please sign in to comment.