diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/BooleanFunctions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/BooleanFunctions.java index a47dff276a..ecd65cbb91 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/BooleanFunctions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/BooleanFunctions.java @@ -1733,6 +1733,12 @@ public IExpr evaluate(final IAST ast, EvalEngine engine) { if (ast.exists(x -> x.equals(S.Undefined))) { return S.Undefined; } + + IAST evalArgs = engine.evalArgsN(ast, ISymbol.NOATTRIBUTE); + if (evalArgs.isPresent()) { + return evalArgs; + } + if (ast.size() > 2) { IExpr.COMPARE_TERNARY b = IExpr.COMPARE_TERNARY.UNDECIDABLE; if (ast.isAST2()) { @@ -2210,6 +2216,11 @@ public IExpr evaluate(IAST ast, EvalEngine engine) { return S.True; } + IASTMutable evalArgs = engine.evalArgsN(ast, ISymbol.NOATTRIBUTE); + if (evalArgs.isPresent()) { + return evalArgs; + } + IASTAppendable flattened; if ((flattened = EvalAttributes.flattenDeep(ast)).isPresent()) { ast = flattened; @@ -4660,6 +4671,10 @@ private static final class Unequal extends Equal { @Override public IExpr evaluate(final IAST ast, EvalEngine engine) { + IASTMutable evalArgs = engine.evalArgsN(ast, ISymbol.NOATTRIBUTE); + if (evalArgs.isPresent()) { + return evalArgs; + } if (ast.exists(x -> x.equals(S.Undefined))) { return S.Undefined; } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/GraphicsFunctions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/GraphicsFunctions.java index 6f08db3398..df4814f44d 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/GraphicsFunctions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/GraphicsFunctions.java @@ -7,6 +7,7 @@ import org.matheclipse.core.convert.RGBColor; import org.matheclipse.core.eval.Errors; import org.matheclipse.core.eval.EvalEngine; +import org.matheclipse.core.eval.interfaces.AbstractCoreFunctionEvaluator; import org.matheclipse.core.eval.interfaces.AbstractEvaluator; import org.matheclipse.core.eval.interfaces.AbstractSymbolEvaluator; import org.matheclipse.core.eval.util.OptionArgs; @@ -660,6 +661,7 @@ private static void init() { S.Cylinder.setEvaluator(new Cylinder()); S.Dodecahedron.setEvaluator(new Dodecahedron()); S.Icosahedron.setEvaluator(new Icosahedron()); + S.Labeled.setEvaluator(new Labeled()); S.Line.setEvaluator(new Line()); S.Octahedron.setEvaluator(new Octahedron()); S.Point.setEvaluator(new Point()); @@ -677,6 +679,24 @@ private static void init() { } } + private static final class Labeled extends AbstractCoreFunctionEvaluator { + + @Override + public IExpr evaluate(final IAST ast, EvalEngine engine) { + IASTMutable evalArgs = engine.evalArgsN(ast, ISymbol.NOATTRIBUTE); + if (evalArgs.isPresent()) { + return evalArgs; + } + return F.NIL; + } + + @Override + public int[] expectedArgSize(IAST ast) { + return ARGS_2_3; + } + + } + private static class Line extends AbstractEvaluator implements IGraphics2D, IGraphics3D { @Override diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/EvalEngine.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/EvalEngine.java index 68532c65f5..54dc139aae 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/EvalEngine.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/eval/EvalEngine.java @@ -826,6 +826,22 @@ public void evalArg(final IASTMutable[] result0, final IAST ast, final IExpr arg } + /** + * Evaluate the arguments of the given ast numerically, if {@link #isNumericMode()} + * is true taking the attributes + * HoldFirst, NHoldFirst, HoldRest, NHoldRest, NumericFunction into account. + * + * @param ast + * @param attributes + * @return F.NIL is no evaluation was possible + */ + public IASTMutable evalArgsN(final IAST ast, final int attributes) { + if (isNumericMode()) { + return evalArgs(ast, attributes, true); + } + return F.NIL; + } + /** * Evaluate the arguments of the given ast, taking the attributes * HoldFirst, NHoldFirst, HoldRest, NHoldRest, NumericFunction into account. 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 832f50cd14..72f446bd0d 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 @@ -4044,20 +4044,23 @@ public boolean isNumericFunction(boolean allowList) { } } } - if (allowList) { - if (head().isSymbol() && ((ISymbol) head()).isNumericFunctionAttribute() || isList()) { - // check if all arguments are "numeric" - boolean forAll = forAll(x -> x.isNumericFunction(allowList), 1); - addEvalFlags( - forAll ? IAST.IS_NUMERIC_FUNCTION_OR_LIST : IAST.IS_NOT_NUMERIC_FUNCTION_OR_LIST); - return forAll; - } - } else { - if (head().isSymbol() && ((ISymbol) head()).isNumericFunctionAttribute()) { - // check if all arguments are "numeric" - boolean forAll = forAll(x -> x.isNumericFunction(allowList), 1); - addEvalFlags(forAll ? IAST.IS_NUMERIC_FUNCTION : IAST.IS_NOT_NUMERIC_FUNCTION); - return forAll; + if (head().isSymbol()) { + ISymbol header = (ISymbol) head(); + if (allowList) { + if (header.isNumericFunctionAttribute() || isList()) { + // check if all arguments are "numeric" + boolean forAll = forAll(x -> x.isNumericFunction(allowList), 1); + addEvalFlags( + forAll ? IAST.IS_NUMERIC_FUNCTION_OR_LIST : IAST.IS_NOT_NUMERIC_FUNCTION_OR_LIST); + return forAll; + } + } else { + if (header.isNumericFunctionAttribute()) { + // check if all arguments are "numeric" + boolean forAll = forAll(x -> x.isNumericFunction(allowList), 1); + addEvalFlags(forAll ? IAST.IS_NUMERIC_FUNCTION : IAST.IS_NOT_NUMERIC_FUNCTION); + return forAll; + } } } return false; diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/S.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/S.java index ccc3b9a8c4..94f2652cce 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/S.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/S.java @@ -11685,4 +11685,8 @@ public static boolean isDomain(ISymbol domain) { return domain == Algebraics || domain == Booleans || domain == Complexes || domain == Integers || domain == Primes || domain == Rationals || domain == Reals; } + + static { + C.setAttributes(ISymbol.NHOLDALL); + } } 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 272a06ffe0..262f01578d 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 @@ -15979,6 +15979,11 @@ public void testDeterminePrecision() { @Test public void testN() { + // issue #937 + check("(x==-157079632679/100000000000) // N", // + "x==-1.5708"); + check("ConditionalExpression(x==-157079632679/100000000000*C(1),C(1)∈Integers) // N", // + "ConditionalExpression(x==-1.5708*C(1),C(1)∈Integers)"); check("N({Labeled(4/3,\"test\")})", // "{Labeled(1.33333,test)}"); check("N(Labeled(4/3,\"test\"))", //