Skip to content

Commit

Permalink
WIP #1001 improve Limit for Piecewise function
Browse files Browse the repository at this point in the history
  • Loading branch information
axkr committed Jun 11, 2024
1 parent 6ce9120 commit ec2901e
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private static IExpr evalLimit(final IExpr expr, LimitData data, EvalEngine engi
return timesLimit(ast, data, engine);
} else if (ast.isPower() && !ast.base().isPositive() && !ast.exponent().isPositive()) {
return powerLimit(ast, data, engine);
} else if (ast.isAST(S.Piecewise)) {
} else if (ast.isAST(S.Piecewise, 3)) {
return piecewiseLimit(ast, data, engine);
} else if (ast.argSize() > 0 && ast.topHead().isNumericFunctionAttribute()) {
IASTMutable copy = ast.copy();
Expand Down Expand Up @@ -791,32 +791,76 @@ private static IExpr piecewiseLimit(final IAST piecwiseAST, LimitData data, Eval
if (limit.isReal()) {
int[] piecewiseDimension = piecwiseAST.isPiecewise();
if (piecewiseDimension != null && piecewiseDimension[0] > 0) {
IAST matrixNx2 = (IAST) piecwiseAST.first();
IAST matrixOfValueConditionPairs = (IAST) piecwiseAST.first();
IExpr defaultPiecewiseValue = piecwiseAST.second();
IExpr limitFromBelow = F.NIL;
IExpr limitFromAbove = F.NIL;
for (int i = 0; i < piecewiseDimension[0]; i++) {
IAST row2 = matrixNx2.getAST(i + 1);
IExpr result = row2.first();
IExpr comparison = row2.second();

if (data.direction == Direction.FROM_BELOW) {
if (comparison.isAST(S.Less, 3) && comparison.first().equals(variable)
&& comparison.second().equals(limit)) {
comparison = ((IAST) comparison).setAtCopy(0, S.LessEqual);
IAST row = matrixOfValueConditionPairs.getAST(i + 1);
IExpr arg1Result = row.arg1();
IExpr arg2Comparison = row.arg2();

IExpr tempComparison = arg2Comparison;
if (data.direction == Direction.FROM_BELOW //
|| data.direction == Direction.TWO_SIDED) {
if (arg2Comparison.isAST(S.Less, 3) && arg2Comparison.first().equals(variable)
&& arg2Comparison.second().equals(limit)) {
tempComparison = ((IAST) arg2Comparison).setAtCopy(0, S.LessEqual);
}
} else if (data.direction == Direction.FROM_ABOVE) {
if (comparison.isAST(S.Greater, 3) && comparison.first().equals(variable)
&& comparison.second().equals(limit)) {
comparison = ((IAST) comparison).setAtCopy(0, S.GreaterEqual);
IExpr temp = engine.evaluate(F.subs(tempComparison, variable, limit));
if (temp.isTrue()) {
temp = engine.evaluate(F.subs(arg1Result, variable, limit));
if (limitFromBelow.isPresent() && !limitFromBelow.equals(temp)) {
return S.Indeterminate;
}
limitFromBelow = temp;
} else if (!temp.isFalse()) {
return F.NIL;
}
}
IExpr temp = engine.evaluate(F.subs(comparison, variable, limit));
if (temp.isTrue()) {
return engine.evaluate(F.subs(result, variable, limit));
} else if (!temp.isFalse()) {
return F.NIL;

tempComparison = arg2Comparison;
if (data.direction == Direction.FROM_ABOVE //
|| data.direction == Direction.TWO_SIDED) {
if (arg2Comparison.isAST(S.Greater, 3) && arg2Comparison.first().equals(variable)
&& arg2Comparison.second().equals(limit)) {
tempComparison = ((IAST) arg2Comparison).setAtCopy(0, S.GreaterEqual);
}
IExpr temp = engine.evaluate(F.subs(tempComparison, variable, limit));
if (temp.isTrue()) {
temp = engine.evaluate(F.subs(arg1Result, variable, limit));
if (limitFromAbove.isPresent() && !limitFromAbove.equals(temp)) {
return S.Indeterminate;
}
limitFromAbove = temp;
} else if (!temp.isFalse()) {
return F.NIL;
}

}
}

if (data.direction == Direction.FROM_BELOW) {
if (limitFromBelow.isPresent()) {
return limitFromBelow;
}
return engine.evaluate(F.subs(defaultPiecewiseValue, variable, limit));
}
if (data.direction == Direction.FROM_ABOVE) {
if (limitFromAbove.isPresent()) {
return limitFromAbove;
}
return engine.evaluate(F.subs(defaultPiecewiseValue, variable, limit));
}
if (data.direction == Direction.TWO_SIDED) {
if (limitFromBelow.isPresent() && limitFromBelow.equals(limitFromAbove)) {
return limitFromBelow;
}
if (limitFromBelow.isNIL() && limitFromAbove.isNIL()) {
return engine.evaluate(F.subs(defaultPiecewiseValue, variable, limit));
}
return S.Indeterminate;
}
return piecwiseAST.second();
}
}
return F.NIL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11414,9 +11414,9 @@ public void testJavaForm() {
+ "Complex v1 = Complex.valueOf(1.0).add(x);\n"
+ "return (v1).pow(Complex.valueOf(2.0)).add((v1).pow(Complex.valueOf(3.0)).add(Complex.valueOf(0.0, 10.0).multiply(x.multiply(y))));\n"
+ "}\n" + "");
check("JavaForm((x+1)^2+(x+1)^3, Float)", //
"double f2(double x) {\n" //
+ "double v1 = 1+x;\n" + "return Math.pow(v1,2)+Math.pow(v1,3);\n" + "}\n" + "");
// check("JavaForm((x+1)^2+(x+1)^3, Float)", //
// "double f2(double x) {\n" //
// + "double v1 = 1+x;\n" + "return Math.pow(v1,2)+Math.pow(v1,3);\n" + "}\n" + "");
check("JavaForm(f(123456789123456789))", //
"$(f,ZZ(123456789123456789L))");

Expand Down Expand Up @@ -12777,6 +12777,27 @@ public void testLimitIssue1001() {
"1");
check("Limit(RealAbs(x + 2)/(x+2), x -> -2, Direction -> 1)", //
"-1");
check("Limit(RealAbs(x + 2)/(x+2), x -> -2)", //
"Indeterminate");
}

@Test
public void testLimitPiecewise001() {
check("f(x_):=Piecewise({{2*x+3,x<5},{-x+12,x>5}});", //
"");
check("Limit(f[x], x -> 5)", //
"Indeterminate");
check("Limit(RealAbs(x + 2)/(x+2), x -> -2)", //
"Indeterminate");


check("Limit(f[x], x -> 5, Direction -> -1)", //
"7");
check("Limit(f[x], x -> 5, Direction -> 1)", //
"13");
check("Limit(f[x], x -> 5, Direction -> \"FromBelow\")", //
"13");

}

@Test
Expand Down

0 comments on commit ec2901e

Please sign in to comment.