diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/AbstractAST.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/AbstractAST.java index 035b211484..069e50ab40 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/AbstractAST.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/AbstractAST.java @@ -3464,6 +3464,7 @@ public final boolean isFreeOfPatterns() { return false; } boolean isFreeOfPatterns = true; + int defaultOrOptionalCounter = 0; for (int i = 0; i < size(); i++) { // all elements including head element IExpr temp = getRule(i); @@ -3471,6 +3472,7 @@ public final boolean isFreeOfPatterns() { isFreeOfPatterns = false; if (temp.isOptional()) { addEvalFlags(IAST.CONTAINS_DEFAULT_PATTERN | IAST.CONTAINS_PATTERN); + defaultOrOptionalCounter++; } else { addEvalFlags(((IAST) temp).getEvalFlags() & IAST.CONTAINS_PATTERN_EXPR); } @@ -3480,12 +3482,14 @@ public final boolean isFreeOfPatterns() { if (temp instanceof IPatternSequence) { if (temp.isPatternDefault()) { addEvalFlags(IAST.CONTAINS_DEFAULT_PATTERN | IAST.CONTAINS_PATTERN_SEQUENCE); + defaultOrOptionalCounter++; } else { addEvalFlags(IAST.CONTAINS_PATTERN_SEQUENCE); } } else { if (temp.isPatternDefault()) { addEvalFlags(IAST.CONTAINS_DEFAULT_PATTERN | IAST.CONTAINS_PATTERN); + defaultOrOptionalCounter++; } else { addEvalFlags(IAST.CONTAINS_PATTERN); } @@ -3494,6 +3498,10 @@ public final boolean isFreeOfPatterns() { } if (isFreeOfPatterns) { addEvalFlags(IAST.CONTAINS_NO_PATTERN); + } else { + if (defaultOrOptionalCounter == argSize()) { + addEvalFlags(IAST.CONTAINS_ALL_DEFAULT_PATTERN); + } } return isFreeOfPatterns; } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/interfaces/IAST.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/interfaces/IAST.java index 88d0c15c7a..e943d80b35 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/interfaces/IAST.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/interfaces/IAST.java @@ -64,10 +64,17 @@ public enum PROPERTY { public static final int BUILT_IN_EVALED = 0x00040000; /** - * One of the arguments of the list contains a pattern object which can be set to a default value. + * One of the arguments of the list contains a pattern object which can be set to a default value + * (or optional value). */ public static final int CONTAINS_DEFAULT_PATTERN = 0x0004; + /** + * All of the arguments of the list are pattern objects which can be set to a default value (or + * optional value). + */ + public static final int CONTAINS_ALL_DEFAULT_PATTERN = 0x10000000; + /** Negative flag mask for CONTAINS_DEFAULT_PATTERN */ public static final int CONTAINS_NO_DEFAULT_PATTERN_MASK = 0xFFFB; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/IPatternMap.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/IPatternMap.java index c0b3fc64a7..4e793564a5 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/IPatternMap.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/IPatternMap.java @@ -3183,7 +3183,8 @@ static IPatternMap determinePatterns(final IExpr lhsPatternExpr, int[] priority, return new PatternMap0(); } - public static IPatternMap createSymbolToValueMap(List> patternIndexMap) { + public static IPatternMap createSymbolToValueMap( + List> patternIndexMap) { int size = patternIndexMap.size(); switch (size) { case 1: @@ -3374,18 +3375,24 @@ private static int determinePatternsRecursive( determinePatternsRecursive(condition, patternIndexMap, dummyPriority, ruleWithoutPattern, listEvalFlags, treeLevel); } else { + // int[] dummyPriority = new int[] {IPatternMap.DEFAULT_RULE_PRIORITY}; + // determinePatternsRecursive(lhsPatternExpr, patternIndexMap, dummyPriority, + // ruleWithoutPattern, + // listEvalFlags, treeLevel); + // get the patterns from right argument to left argument, to get the pattern x_ in D(f,x_) and // Integrate(f,x_) as first pattern in the pattern map for (int i = lhsPatternExpr.size() - 1; i >= 0; i--) { determinePatternsRecursive(i == 0 ? lhsPatternExpr.getValue(i) : lhsPatternExpr.getRule(i), patternIndexMap, priority, ruleWithoutPattern, listEvalFlags, treeLevel); } - // lhsPatternExpr.forEachRule(x -> determinePatternsRecursive(x, patternIndexMap, priority, - // ruleWithoutPattern, listEvalFlags, treeLevel), 0); } lhsPatternExpr.setEvalFlags(listEvalFlags[0]); - // disable flag "pattern with default value" - // listEvalFlags &= IAST.CONTAINS_NO_DEFAULT_PATTERN_MASK; + if (lhsPatternExpr.size() > 1 // + && ((listEvalFlags[0] & IAST.CONTAINS_DEFAULT_PATTERN) == IAST.CONTAINS_DEFAULT_PATTERN)// + && lhsPatternExpr.forAll(IExpr::isPatternDefault)) { + lhsPatternExpr.addEvalFlags(IAST.CONTAINS_ALL_DEFAULT_PATTERN); + } return listEvalFlags[0]; } @@ -3401,7 +3408,11 @@ private static void determinePatternsRecursive(final IExpr x, ruleWithoutPattern, treeLevel + 1); priority[0] -= 11; if (x.isPatternDefault()) { - listEvalFlags[0] |= IAST.CONTAINS_DEFAULT_PATTERN; + listEvalFlags[0] |= IAST.CONTAINS_DEFAULT_PATTERN | IAST.CONTAINS_ALL_DEFAULT_PATTERN; + } else if (lhsPatternAST.size() > 1 // + && ((listEvalFlags[0] & IAST.CONTAINS_DEFAULT_PATTERN) == IAST.CONTAINS_DEFAULT_PATTERN) // + && lhsPatternAST.forAll(IExpr::isPatternDefault)) { + lhsPatternAST.addEvalFlags(IAST.CONTAINS_ALL_DEFAULT_PATTERN); } } else if (x instanceof IPatternObject) { ruleWithoutPattern[0] = false; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/PatternMatcher.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/PatternMatcher.java index 24c56db3e5..0f849f69e0 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/PatternMatcher.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/patternmatching/PatternMatcher.java @@ -881,23 +881,25 @@ private boolean matchASTExpr(IAST lhsPatternAST, final IExpr lhsEvalExpr, EvalEn if (head.isSymbol()) { ISymbol patternHead = (ISymbol) head; IExpr evalHead = lhsEvalExpr.head(); - // if (patternHead.hasOneIdentityAttribute() && lhsPatternAST.isOrderlessAST()) { - // if (patternHead.equals(evalHead) && lhsEvalExpr.isAST()) { - // if (lhsPatternAST.size() - 1 >= lhsEvalExpr.size()) { - // IAST lhsEvalAST = (IAST) lhsEvalExpr; - // int[] ignoredPositions = new int[lhsEvalAST.size()]; - // matched = matchDefaultArgsRecursive(patternHead, evalHead, lhsPatternAST, - // lhsEvalAST, 1, patternValues, lastStackSize, ignoredPositions, engine, - // stackMatcher); - // } - // } else { - // IAST lhsEvalAST = F.unaryAST1(patternHead, lhsEvalExpr); - // int[] ignoredPositions = new int[lhsEvalAST.size()]; - // matched = - // matchDefaultArgsRecursive(patternHead, evalHead, lhsPatternAST, lhsEvalAST, 1, - // patternValues, lastStackSize, ignoredPositions, engine, stackMatcher); - // } - // } + if ((lhsPatternAST.getEvalFlags() + & IAST.CONTAINS_ALL_DEFAULT_PATTERN) == IAST.CONTAINS_ALL_DEFAULT_PATTERN + && patternHead.hasOneIdentityAttribute() && lhsPatternAST.isOrderlessAST()) { + if (patternHead.equals(evalHead) && lhsEvalExpr.isAST()) { + if (lhsPatternAST.size() - 1 >= lhsEvalExpr.size()) { + IAST lhsEvalAST = (IAST) lhsEvalExpr; + int[] ignoredPositions = new int[lhsEvalAST.size()]; + matched = matchDefaultArgsRecursive(patternHead, evalHead, lhsPatternAST, + lhsEvalAST, 1, patternValues, lastStackSize, ignoredPositions, engine, + stackMatcher); + } + } else { + IAST lhsEvalAST = F.unaryAST1(patternHead, lhsEvalExpr); + int[] ignoredPositions = new int[lhsEvalAST.size()]; + matched = + matchDefaultArgsRecursive(patternHead, evalHead, lhsPatternAST, lhsEvalAST, 1, + patternValues, lastStackSize, ignoredPositions, engine, stackMatcher); + } + } if (!matched) { IExpr temp = matchDefaultArgumentsAST(patternHead, lhsPatternAST, engine); if (temp.isPresent()) { diff --git a/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/LowercaseTestCase.java b/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/LowercaseTestCase.java index 13c623c346..b870464bdd 100644 --- a/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/LowercaseTestCase.java +++ b/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/LowercaseTestCase.java @@ -14211,12 +14211,12 @@ public void testMatchQRubi002() { "{x,0}"); check("f( a_. + b_. ):={a,b}", // ""); - // check("f( x ) ", // - // "{x,0}"); - // check("MatchQ(2+x, ( a_. + b_. ) )", // - // "True"); - // check("MatchQ(x, ( a_. + b_. ) )", // - // "True"); + check("f( x ) ", // + "{x,0}"); + check("MatchQ(2+x, ( a_. + b_. ) )", // + "True"); + check("MatchQ(x, ( a_. + b_. ) )", // + "True"); } @Test