Skip to content

Commit 837d057

Browse files
committed
Edge cases in PolynomialQ, Coeefficient, Exponent - use MMA conventions
1 parent 65bf5b5 commit 837d057

File tree

8 files changed

+204
-58
lines changed

8 files changed

+204
-58
lines changed

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/Algebra.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,8 @@ public int[] expectedArgSize() {
19441944
return IOFunctions.ARGS_1_2;
19451945
}
19461946

1947-
public IExpr factorExpr(final IAST ast, IExpr expr, VariablesSet eVar, boolean factorSquareFree, EvalEngine engine) {
1947+
public IExpr factorExpr(final IAST ast, IExpr expr, VariablesSet eVar, boolean factorSquareFree,
1948+
EvalEngine engine) {
19481949
if (expr.isAST()) {
19491950
IExpr temp;
19501951
// if (expr.isPower()&&expr.base().isPlus()) {
@@ -1953,7 +1954,7 @@ public IExpr factorExpr(final IAST ast, IExpr expr, VariablesSet eVar, boolean f
19531954
// temp = F.Power(temp, expr.exponent());
19541955
// } else
19551956
if (expr.isPower()) {
1956-
IExpr p = factorExpr((IAST) expr, expr.base(), eVar,factorSquareFree, engine);
1957+
IExpr p = factorExpr((IAST) expr, expr.base(), eVar, factorSquareFree, engine);
19571958
if (!p.equals(expr.base())) {
19581959
return F.Power(p, expr.exponent());
19591960
}
@@ -1965,7 +1966,7 @@ public IExpr factorExpr(final IAST ast, IExpr expr, VariablesSet eVar, boolean f
19651966
return factorExpr(ast, x, eVar, factorSquareFree, engine);
19661967
}
19671968
if (x.isPower() && x.base().isPlus()) {
1968-
IExpr p = factorExpr(ast, x.base(), eVar, factorSquareFree,engine);
1969+
IExpr p = factorExpr(ast, x.base(), eVar, factorSquareFree, engine);
19691970
if (!p.equals(x.base())) {
19701971
return F.Power(p, x.exponent());
19711972
}
@@ -2139,7 +2140,7 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
21392140
if (ast.isAST2()) {
21402141
return factorWithOption(ast, expr, varList, true, engine);
21412142
}
2142-
if (expr.isAST()) {
2143+
if (expr.isAST()) {
21432144
return factorExpr((IAST) expr, (IAST) expr, eVar, true, engine);
21442145
}
21452146
return expr;
@@ -3007,7 +3008,18 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
30073008
if (ast.isAST2()) {
30083009
IExpr arg1 = engine.evaluate(ast.arg1());
30093010
IExpr arg2 = engine.evaluate(ast.arg2());
3010-
return F.bool(arg1.isPolynomial(arg2.orNewList()));
3011+
3012+
IAST variablesList = F.NIL;
3013+
if (arg2.isList()) {
3014+
variablesList = (IAST) arg2;
3015+
} else {
3016+
variablesList = F.List(arg2);
3017+
}
3018+
IAST subst = substituteVariablesInPolynomial(arg1, variablesList, "§PolynomialQ");
3019+
return F.bool(subst.arg1().isPolynomial((IAST) subst.arg2()));
3020+
}
3021+
if (ast.isAST1()) {
3022+
return F.True;
30113023
}
30123024
return F.False;
30133025
// if (ast.isAST2()) {
@@ -3017,6 +3029,11 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
30173029
// return F.NIL;
30183030
}
30193031

3032+
@Override
3033+
public int[] expectedArgSize() {
3034+
return IOFunctions.ARGS_1_2;
3035+
}
3036+
30203037
@Override
30213038
public boolean test(final IExpr firstArg, final IExpr secondArg) {
30223039
return firstArg.isPolynomial(secondArg.orNewList());
@@ -5750,6 +5767,31 @@ public static IExpr together(IAST ast, EvalEngine engine) {
57505767
return temp;
57515768
}
57525769

5770+
/**
5771+
* If AST structures are available in the variableList create dummy variables and replace these expressions in
5772+
* polyExpr.
5773+
*
5774+
* @param polyExpr
5775+
* @param variablesList
5776+
* a list of variables, which aren't necessarily symbols
5777+
* @param dummyStr
5778+
* @return <code>F.List(polyExpr, substitutedVariableList)</code>
5779+
*/
5780+
public static IAST substituteVariablesInPolynomial(IExpr polyExpr, IAST variablesList, String dummyStr) {
5781+
IASTAppendable substitutedVariableList = F.ListAlloc(variablesList.size());
5782+
for (int i = 1; i < variablesList.size(); i++) {
5783+
IExpr listArg = variablesList.get(i);
5784+
if (listArg.isAST() && !listArg.isPower()) {
5785+
ISymbol dummy = F.Dummy(dummyStr + i);
5786+
polyExpr = F.subst(polyExpr, F.Rule(listArg, dummy));
5787+
substitutedVariableList.append(dummy);
5788+
} else {
5789+
substitutedVariableList.append(listArg);
5790+
}
5791+
}
5792+
return F.List(polyExpr, substitutedVariableList);
5793+
}
5794+
57535795
public static void initialize() {
57545796
Initializer.init();
57555797
}

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/PolynomialFunctions.java

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -162,38 +162,38 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
162162
// array of corresponding exponents for the list of variables
163163
long[] exponents = null;
164164

165-
if (arg2.isTimes()) {
166-
// Times(x, y^a,...)
167-
IAST arg2AST = (IAST) arg2;
168-
VariablesSet eVar = new VariablesSet(arg2AST);
169-
listOfVariables = eVar.getVarList();
170-
exponents = new long[listOfVariables.argSize()];
171-
for (int i = 0; i < exponents.length; i++) {
172-
exponents[i] = 0L;
173-
}
174-
for (int i = 1; i < arg2AST.size(); i++) {
175-
long value = 1L;
176-
IExpr a1 = arg2AST.get(i);
177-
if (a1.isPower() && a1.exponent().isInteger()) {
178-
a1 = arg2AST.get(i).base();
179-
IInteger ii = (IInteger) arg2AST.get(i).exponent();
180-
try {
181-
value = ii.toLong();
182-
} catch (ArithmeticException ae) {
183-
return F.NIL;
184-
}
185-
}
186-
187-
if (!setExponent(listOfVariables, a1, exponents, value)) {
188-
return F.NIL;
189-
}
190-
}
191-
} else {
192-
listOfVariables = F.ListAlloc();
193-
listOfVariables.append(arg2);
194-
exponents = new long[1];
195-
exponents[0] = 1;
196-
}
165+
// if (arg2.isTimes()) {
166+
// // Times(x, y^a,...)
167+
// IAST arg2AST = (IAST) arg2;
168+
// VariablesSet eVar = new VariablesSet(arg2AST);
169+
// listOfVariables = eVar.getVarList();
170+
// exponents = new long[listOfVariables.argSize()];
171+
// for (int i = 0; i < exponents.length; i++) {
172+
// exponents[i] = 0L;
173+
// }
174+
// for (int i = 1; i < arg2AST.size(); i++) {
175+
// long value = 1L;
176+
// IExpr a1 = arg2AST.get(i);
177+
// if (a1.isPower() && a1.exponent().isInteger()) {
178+
// a1 = arg2AST.get(i).base();
179+
// IInteger ii = (IInteger) arg2AST.get(i).exponent();
180+
// try {
181+
// value = ii.toLong();
182+
// } catch (ArithmeticException ae) {
183+
// return F.NIL;
184+
// }
185+
// }
186+
//
187+
// if (!setExponent(listOfVariables, a1, exponents, value)) {
188+
// return F.NIL;
189+
// }
190+
// }
191+
// } else {
192+
listOfVariables = F.ListAlloc();
193+
listOfVariables.append(arg2);
194+
exponents = new long[1];
195+
exponents[0] = 1;
196+
// }
197197

198198
try {
199199
long n = 1;
@@ -208,6 +208,9 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
208208
}
209209
ExpVectorLong expArr = new ExpVectorLong(exponents);
210210
IExpr expr = F.evalExpandAll(ast.arg1(), engine).normal();
211+
IAST subst = Algebra.substituteVariablesInPolynomial(expr, listOfVariables, "§Coefficient");
212+
expr = subst.arg1();
213+
listOfVariables = (IASTAppendable) subst.arg2();
211214
ExprPolynomialRing ring = new ExprPolynomialRing(ExprRingFactory.CONST, listOfVariables);
212215
ExprPolynomial poly = ring.create(expr, true, false);
213216
IExpr temp = poly.coefficient(expArr);
@@ -239,7 +242,7 @@ private static class CoefficientList extends AbstractFunctionEvaluator {
239242
@Override
240243
public IExpr evaluate(final IAST ast, EvalEngine engine) {
241244
IExpr expr = F.evalExpandAll(ast.arg1(), engine).normal();
242-
IAST list = Validate.checkSymbolOrSymbolList(ast, 2);
245+
IAST list = ast.arg2().orNewList();
243246
return coefficientList(expr, list);
244247
}
245248

@@ -328,9 +331,6 @@ public IExpr evaluate(final IAST ast, final EvalEngine engine) {
328331
symbolList = Validate.checkSymbolOrSymbolList(ast, 2);
329332
varList = new ArrayList<IExpr>(symbolList.argSize());
330333
symbolList.forEach(x -> varList.add(x));
331-
// for (int i = 1; i < symbolList.size(); i++) {
332-
// varList.add(symbolList.get(i));
333-
// }
334334
}
335335
TermOrder termOrder = TermOrderByName.Lexicographic;
336336
try {
@@ -501,7 +501,6 @@ private static IExpr cyclotomic(int n, final IExpr x) {
501501
if (x.isZero()) {
502502
return F.C1;
503503
}
504-
// IASTAppendable result = F.PlusAlloc(n + 1);
505504
if (LongMath.isPrime(n)) {
506505
return F.sum(i -> x.power(i), 0, n - 1);
507506
}
@@ -746,10 +745,11 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
746745
return cached;
747746
}
748747

749-
final IExpr form = engine.evalPattern(ast.arg2());
748+
IExpr form = engine.evalPattern(ast.arg2());
750749
if (form.isList()) {
751750
return ((IAST) form).mapThread(ast, 2);
752751
}
752+
753753
ISymbol sym = F.Max;
754754
if (ast.isAST3()) {
755755
final IExpr arg3 = engine.evaluate(ast.arg3());
@@ -767,6 +767,9 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
767767
// }
768768
// }
769769
IExpr expr = F.evalExpandAll(ast.arg1(), engine).normal();
770+
IAST subst = Algebra.substituteVariablesInPolynomial(expr, F.List(form), "§Exponent");
771+
expr = subst.arg1();
772+
form = subst.arg2().first();
770773
// if (expr.isTimes()) {
771774
// expr =F.Distribute.of(expr);
772775
// }
@@ -811,7 +814,6 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
811814
}
812815

813816
} else if (expr.isSymbol()) {
814-
// final PatternMatcher matcher = new PatternMatcherEvalEngine(form, engine);
815817
final IPatternMatcher matcher = engine.evalPatternMatcher(form);
816818
if (matcher.test(expr)) {
817819
collector.add(F.C1);
@@ -2269,7 +2271,7 @@ public static IAST rootsOfVariable(final IExpr expr, final IExpr denominator, fi
22692271
}
22702272
} else {
22712273
polyRat = jas.expr2JAS(temp, numericSolutions);
2272-
IAST factorComplex = Algebra.factorComplex(temp,polyRat, jas, F.List);
2274+
IAST factorComplex = Algebra.factorComplex(temp, polyRat, jas, F.List);
22732275
for (int k = 1; k < factorComplex.size(); k++) {
22742276
temp = F.evalExpand(factorComplex.get(k));
22752277
quarticResultList = QuarticSolver.solve(temp, variables.arg1());

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/StringFunctions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,8 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) {
429429
}
430430
try {
431431
if (form.equals(F.InputForm)) {
432-
ExprParser fParser = new ExprParser(engine);
433-
IExpr temp = fParser.parse(arg1.toString());
432+
ExprParser parser = new ExprParser(engine);
433+
IExpr temp = parser.parse(arg1.toString());
434434
return temp;
435435
} else if (form.equals(F.TeXForm)) {
436436
TeXParser texParser = new TeXParser(engine);

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/convert/Object2Expr.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import java.math.BigDecimal;
66
import java.math.BigInteger;
7+
import java.util.concurrent.atomic.AtomicInteger;
8+
import java.util.concurrent.atomic.AtomicLong;
79

810
import org.matheclipse.core.eval.EvalEngine;
911
import org.matheclipse.core.expression.AST;
@@ -31,11 +33,13 @@ public class Object2Expr {
3133
* null object F.Null symbol
3234
* IExpr IExpr type
3335
* Boolean True or False symbol
34-
* BigInteger Integer value
35-
* BigDecimal <code>Num</code> with doubleValue() value
36-
* Double <code>Num</code> with doubleValue() value
37-
* Float <code>Num</code> with doubleValue() value
38-
* Number Integer with longValue() value
36+
* BigInteger Symja Integer value
37+
* BigDecimal Symja <code>Num</code> with doubleValue() value
38+
* Double Symja <code>Num</code> with doubleValue() value
39+
* Float Symja <code>Num</code> with doubleValue() value
40+
* Integer Symja Integer with longValue() value
41+
* Long Symja Integer with longValue() value
42+
* Number Symja <code>Num</code> with doubleValue() value
3943
* java.util.Collection list of elements
4044
* 1..nth element of the list give the elements of the List()
4145
* Object[] a list of converted objects
@@ -68,13 +72,25 @@ public static IExpr convert(Object obj) throws ConversionException {
6872
if (obj instanceof Double) {
6973
return F.num(((Double) obj).doubleValue());
7074
}
75+
if (obj instanceof Integer) {
76+
return F.num(((Integer) obj).longValue());
77+
}
78+
if (obj instanceof Long) {
79+
return F.num(((Long) obj).longValue());
80+
}
7181
if (obj instanceof AtomicDouble) {
7282
return F.num(((AtomicDouble) obj).doubleValue());
7383
}
84+
if (obj instanceof AtomicInteger) {
85+
return F.ZZ(((AtomicInteger) obj).longValue());
86+
}
87+
if (obj instanceof AtomicLong) {
88+
return F.ZZ(((AtomicLong) obj).longValue());
89+
}
7490
if (obj instanceof Float) {
7591
return F.num(((Float) obj).doubleValue());
7692
}
77-
return F.integer(((Number) obj).longValue());
93+
return F.num(((Number) obj).doubleValue());
7894
}
7995
if (obj instanceof String) {
8096
final ExprParser parser = new ExprParser(EvalEngine.get());

symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/F.java

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@
8484
import org.matheclipse.core.interfaces.ISignedNumber;
8585
import org.matheclipse.core.interfaces.IStringX;
8686
import org.matheclipse.core.interfaces.ISymbol;
87+
import org.matheclipse.core.parser.ExprParser;
8788
import org.matheclipse.core.parser.ExprParserFactory;
8889
import org.matheclipse.core.patternmatching.IPatternMap.PatternMap;
8990
import org.matheclipse.core.patternmatching.IPatternMatcher;
91+
import org.matheclipse.parser.client.SyntaxError;
9092

9193
import com.google.common.cache.Cache;
9294
import com.google.common.cache.CacheBuilder;
@@ -4395,17 +4397,60 @@ public static IAST Symmetric(final IExpr a0) {
43954397
/**
43964398
* Converts an arbitrary expression to a type that can be used inside Symja.
43974399
*
4398-
* For example, it will convert Java <code>Integer</code> into instance of <code>IntegerSym</code>,
4399-
* <code>Double</code> into instances of <code>Num</code>, etc.
4400+
* <pre>
4401+
* Java Object -&gt; Symja object
4402+
* -------------------------------------
4403+
* null object F.Null symbol
4404+
* IExpr IExpr type
4405+
* Boolean True or False symbol
4406+
* BigInteger Integer value
4407+
* BigDecimal <code>Num</code> with doubleValue() value
4408+
* Double <code>Num</code> with doubleValue() value
4409+
* Float <code>Num</code> with doubleValue() value
4410+
* Integer Symja Integer with longValue() value
4411+
* Long Symja Integer with longValue() value
4412+
* Number Symja <code>Num</code> with doubleValue() value
4413+
* java.util.Collection list of elements
4414+
* 1..nth element of the list give the elements of the List()
4415+
* Object[] a list of converted objects
4416+
* int[] a list of <code>IntegerSym</code> integer values
4417+
* double[] a vector ASTRealVector of <code>double</code> values
4418+
* double[][] a matrix ASTRealMatrix of <code>double</code> values
4419+
* Complex[] a list of <code>ComplexNum</code> values
4420+
* boolean[] a list of True or False symbols
44004421
*
4422+
* </pre>
44014423
*
4402-
* @param object
4403-
* @return
44044424
*/
44054425
public static IExpr symjify(final Object object) {
44064426
return Object2Expr.convert(object);
44074427
}
44084428

4429+
/**
4430+
* Parses a Java string to a Symja expression. May throw an SyntaxError exception, if the string couldn't be parsed.
4431+
*
4432+
* @param str
4433+
* the epression which should be parsed
4434+
* @return
4435+
* @throws SyntaxError
4436+
*/
4437+
public static IExpr symjify(final String str) throws SyntaxError {
4438+
ExprParser parser = new ExprParser(EvalEngine.get());
4439+
return parser.parse(str);
4440+
}
4441+
4442+
public static IExpr symjify(final long value) {
4443+
return F.ZZ(value);
4444+
}
4445+
4446+
public static IExpr symjify(final double value) {
4447+
return F.num(value);
4448+
}
4449+
4450+
public static IExpr symjify(final boolean value) {
4451+
return value ? F.True : F.False;
4452+
}
4453+
44094454
/**
44104455
* <p>
44114456
* Get or create a global predefined symbol which is retrieved from the SYSTEM context map or created or retrieved

0 commit comments

Comments
 (0)