Search in sources :

Example 1 with SymbolNode

use of org.matheclipse.parser.client.ast.SymbolNode in project symja_android_library by axkr.

the class Parser method getFactor.

private ASTNode getFactor() throws SyntaxError {
    ASTNode temp;
    if (fToken == TT_PRECEDENCE_OPEN) {
        fRecursionDepth++;
        try {
            getNextToken();
            temp = parseExpression();
            if (fToken != TT_PRECEDENCE_CLOSE) {
                throwSyntaxError("\')\' expected.");
            }
        } finally {
            fRecursionDepth--;
        }
        getNextToken();
        if (fToken == TT_PRECEDENCE_OPEN) {
            return getTimes(temp);
        }
        if (fToken == TT_ARGUMENTS_OPEN) {
            return getFunctionArguments(temp);
        }
        return temp;
    } else if (fToken == TT_LIST_OPEN) {
        return getList();
    } else if (fToken == TT_IDENTIFIER) {
        final SymbolNode symbol = getSymbol();
        if (fToken == TT_BLANK) {
            // read '_'
            if (isWhitespace()) {
                temp = fFactory.createPattern(symbol, null);
                getNextToken();
            } else {
                getNextToken();
                if (fToken == TT_IDENTIFIER) {
                    final ASTNode check = getSymbol();
                    temp = fFactory.createPattern(symbol, check);
                } else {
                    temp = fFactory.createPattern(symbol, null);
                }
            }
        } else if (fToken == TT_BLANK_BLANK) {
            // read '__'
            if (isWhitespace()) {
                temp = fFactory.createPattern2(symbol, null);
                getNextToken();
            } else {
                getNextToken();
                if (fToken == TT_IDENTIFIER) {
                    final ASTNode check = getSymbol();
                    temp = fFactory.createPattern2(symbol, check);
                } else {
                    temp = fFactory.createPattern2(symbol, null);
                }
            }
        } else if (fToken == TT_BLANK_BLANK_BLANK) {
            // read '___'
            if (isWhitespace()) {
                temp = fFactory.createPattern3(symbol, null);
                getNextToken();
            } else {
                getNextToken();
                if (fToken == TT_IDENTIFIER) {
                    final ASTNode check = getSymbol();
                    temp = fFactory.createPattern3(symbol, check);
                } else {
                    temp = fFactory.createPattern3(symbol, null);
                }
            }
        } else if (fToken == TT_BLANK_OPTIONAL) {
            // read '_.'
            if (isWhitespace()) {
                temp = fFactory.createPattern(symbol, null, true);
                getNextToken();
            } else {
                getNextToken();
                if (fToken == TT_IDENTIFIER) {
                    final ASTNode check = getSymbol();
                    temp = fFactory.createPattern(symbol, check, true);
                } else {
                    temp = fFactory.createPattern(symbol, null, true);
                }
            }
        } else if (fToken == TT_BLANK_COLON) {
            // read '_:'
            getNextToken();
            ASTNode defaultValue = parseExpression();
            temp = fFactory.createPattern(symbol, null, defaultValue);
        } else {
            temp = symbol;
        }
        return parseArguments(temp);
    } else if (fToken == TT_BLANK) {
        if (isWhitespace()) {
            getNextToken();
            temp = fFactory.createPattern(null, null);
        } else {
            getNextToken();
            if (fToken == TT_IDENTIFIER) {
                final ASTNode check = getSymbol();
                temp = fFactory.createPattern(null, check);
            } else {
                temp = fFactory.createPattern(null, null);
            }
        }
        return parseArguments(temp);
    } else if (fToken == TT_BLANK_BLANK) {
        // read '__'
        if (isWhitespace()) {
            getNextToken();
            temp = fFactory.createPattern2(null, null);
        } else {
            getNextToken();
            if (fToken == TT_IDENTIFIER) {
                final ASTNode check = getSymbol();
                temp = fFactory.createPattern2(null, check);
            } else {
                temp = fFactory.createPattern2(null, null);
            }
        }
        return parseArguments(temp);
    } else if (fToken == TT_BLANK_BLANK_BLANK) {
        // read '___'
        if (isWhitespace()) {
            getNextToken();
            temp = fFactory.createPattern3(null, null);
        } else {
            getNextToken();
            if (fToken == TT_IDENTIFIER) {
                final ASTNode check = getSymbol();
                temp = fFactory.createPattern3(null, check);
            } else {
                temp = fFactory.createPattern3(null, null);
            }
        }
        return parseArguments(temp);
    } else if (fToken == TT_BLANK_OPTIONAL) {
        // read '_.'
        if (isWhitespace()) {
            getNextToken();
            temp = fFactory.createPattern(null, null, true);
        } else {
            getNextToken();
            if (fToken == TT_IDENTIFIER) {
                final ASTNode check = getSymbol();
                temp = fFactory.createPattern(null, check, true);
            } else {
                temp = fFactory.createPattern(null, null, true);
            }
        }
        return parseArguments(temp);
    } else if (fToken == TT_BLANK_COLON) {
        // read '_:'
        getNextToken();
        ASTNode defaultValue = parseExpression();
        temp = fFactory.createPattern(null, null, defaultValue);
        return parseArguments(temp);
    } else if (fToken == TT_DIGIT) {
        return getNumber(false);
    } else if (fToken == TT_STRING) {
        return getString();
    } else if (fToken == TT_PERCENT) {
        final FunctionNode out = fFactory.createFunction(fFactory.createSymbol(IConstantOperators.Out));
        int countPercent = 1;
        getNextToken();
        if (fToken == TT_DIGIT) {
            countPercent = getIntegerNumber();
            out.add(fFactory.createInteger(countPercent));
            return out;
        }
        while (fToken == TT_PERCENT) {
            countPercent++;
            getNextToken();
        }
        out.add(fFactory.createInteger(-countPercent));
        return parseArguments(out);
    } else if (fToken == TT_SLOT) {
        getNextToken();
        final FunctionNode slot = fFactory.createFunction(fFactory.createSymbol(IConstantOperators.Slot));
        if (fToken == TT_DIGIT) {
            slot.add(getNumber(false));
        } else {
            slot.add(fFactory.createInteger(1));
        }
        return parseArguments(slot);
    } else if (fToken == TT_SLOTSEQUENCE) {
        getNextToken();
        final FunctionNode slotSequencce = fFactory.createFunction(fFactory.createSymbol(IConstantOperators.SlotSequence));
        if (fToken == TT_DIGIT) {
            slotSequencce.add(getNumber(false));
        } else {
            slotSequencce.add(fFactory.createInteger(1));
        }
        return parseArguments(slotSequencce);
    }
    switch(fToken) {
        case TT_PRECEDENCE_CLOSE:
            throwSyntaxError("Too much closing ) in factor.");
            break;
        case TT_LIST_CLOSE:
            throwSyntaxError("Too much closing } in factor.");
            break;
        case TT_ARGUMENTS_CLOSE:
            throwSyntaxError("Too much closing ] in factor.");
            break;
    }
    throwSyntaxError("Error in factor at character: '" + fCurrentChar + "' (" + fToken + ")");
    return null;
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode)

Example 2 with SymbolNode

use of org.matheclipse.parser.client.ast.SymbolNode in project symja_android_library by axkr.

the class AST2Expr method convertNode.

/**
 * Converts a parsed ASTNode expression into a Symja IExpr expression
 *
 * @param node the parsed ASTNode
 * @return the Symja expression
 */
private IExpr convertNode(ASTNode node) {
    if (node == null) {
        return null;
    }
    if (node instanceof FunctionNode) {
        final FunctionNode functionNode = (FunctionNode) node;
        int size = functionNode.size();
        IASTMutable ast;
        switch(size) {
            case 1:
                ast = F.headAST0(convertNode(functionNode.get(0)));
                break;
            case 2:
                ast = F.unaryAST1(convertNode(functionNode.get(0)), convertNode(functionNode.get(1)));
                break;
            case 3:
                ast = F.binaryAST2(convertNode(functionNode.get(0)), convertNode(functionNode.get(1)), convertNode(functionNode.get(2)));
                break;
            case 4:
                ast = F.ternaryAST3(convertNode(functionNode.get(0)), convertNode(functionNode.get(1)), convertNode(functionNode.get(2)), convertNode(functionNode.get(3)));
                break;
            default:
                IASTAppendable appendableAST = F.ast(convertNode(functionNode.get(0)), functionNode.size());
                for (int i = 1; i < functionNode.size(); i++) {
                    appendableAST.append(convertNode(functionNode.get(i)));
                }
                ast = appendableAST;
        }
        int functionID = ast.headID();
        if (functionID > ID.UNKNOWN) {
            IExpr temp = evaluateOnInput(functionID, ast, functionNode);
            if (temp.isPresent()) {
                return temp;
            }
        }
        return ast;
    }
    if (node instanceof SymbolNode) {
        String nodeStr = node.getString();
        return convertSymbol(nodeStr);
    }
    // PatternNode
    if (node instanceof Pattern3Node) {
        final Pattern3Node p3n = (Pattern3Node) node;
        SymbolNode sn = p3n.getSymbol();
        return F.$ps((ISymbol) convertNode(sn), convertNode(p3n.getConstraint()), p3n.isDefault(), true);
    }
    if (node instanceof Pattern2Node) {
        final Pattern2Node p2n = (Pattern2Node) node;
        SymbolNode sn = p2n.getSymbol();
        return F.$ps((ISymbol) convertNode(sn), convertNode(p2n.getConstraint()), p2n.isDefault(), false);
    }
    if (node instanceof PatternNode) {
        final PatternNode pn = (PatternNode) node;
        SymbolNode sn = pn.getSymbol();
        if (sn == null) {
            return F.$b(convertNode(pn.getConstraint()), pn.isDefault());
        }
        ASTNode defaultValue = pn.getDefaultValue();
        if (defaultValue != null) {
            return F.Optional(F.$p((ISymbol) convertNode(pn.getSymbol()), convertNode(pn.getConstraint())), convertNode(defaultValue));
        }
        return F.$p((ISymbol) convertNode(pn.getSymbol()), convertNode(pn.getConstraint()), pn.isDefault());
    }
    if (node instanceof IntegerNode) {
        final IntegerNode integerNode = (IntegerNode) node;
        final String iStr = integerNode.getString();
        if (iStr != null) {
            return F.ZZ(iStr, integerNode.getNumberFormat());
        }
        return F.ZZ(integerNode.getIntValue());
    }
    if (node instanceof FractionNode) {
        FractionNode fr = (FractionNode) node;
        IInteger numerator = (IInteger) convertNode(fr.getNumerator());
        IInteger denominator = (IInteger) convertNode(fr.getDenominator());
        if (denominator.isZero()) {
            return F.Rational(fr.isSign() ? numerator.negate() : numerator, denominator);
        }
        if (denominator.isOne()) {
            return fr.isSign() ? numerator.negate() : numerator;
        }
        // return F.Rational(fr.isSign() ? numerator.negate() : numerator, denominator);
        return F.fraction(fr.isSign() ? numerator.negate() : numerator, denominator);
    }
    if (node instanceof StringNode) {
        return F.$str(node.getString());
    }
    if (node instanceof FloatNode) {
        String nStr = node.getString();
        String floatStr = nStr;
        int index = nStr.indexOf("*^");
        int exponent = 1;
        if (index > 0) {
            floatStr = nStr.substring(0, index);
            exponent = Integer.parseInt(nStr.substring(index + 2));
        }
        if (EvalEngine.isApfloat(fPrecision)) {
            Apfloat apfloatValue = new Apfloat(floatStr, fPrecision);
            if (exponent != 1) {
                // value * 10 ^ exponent
                return F.num(apfloatValue.multiply(ApfloatMath.pow(new Apint(10), new Apint(exponent))));
            }
            return F.num(apfloatValue);
        }
        double doubleValue = Double.parseDouble(floatStr);
        if (exponent != 1) {
            // value * 10 ^ exponent
            return F.num(doubleValue * Math.pow(10, exponent));
        }
        return F.num(doubleValue);
    }
    if (node instanceof DoubleNode) {
        return F.num(((DoubleNode) node).doubleValue());
    }
    return F.symbol(node.toString());
}
Also used : ISymbol(org.matheclipse.core.interfaces.ISymbol) IntegerNode(org.matheclipse.parser.client.ast.IntegerNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) Pattern2Node(org.matheclipse.parser.client.ast.Pattern2Node) FloatNode(org.matheclipse.parser.client.ast.FloatNode) Apint(org.apfloat.Apint) DoubleNode(org.matheclipse.parser.client.eval.DoubleNode) IASTMutable(org.matheclipse.core.interfaces.IASTMutable) FractionNode(org.matheclipse.parser.client.ast.FractionNode) Apint(org.apfloat.Apint) Apfloat(org.apfloat.Apfloat) SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) IASTAppendable(org.matheclipse.core.interfaces.IASTAppendable) PatternNode(org.matheclipse.parser.client.ast.PatternNode) IInteger(org.matheclipse.core.interfaces.IInteger) ASTNode(org.matheclipse.parser.client.ast.ASTNode) StringNode(org.matheclipse.parser.client.ast.StringNode) IExpr(org.matheclipse.core.interfaces.IExpr) Pattern3Node(org.matheclipse.parser.client.ast.Pattern3Node)

Example 3 with SymbolNode

use of org.matheclipse.parser.client.ast.SymbolNode in project symja_android_library by axkr.

the class DoubleEvaluator method derivative.

/**
 * TODO: add more derivation rules
 *
 * @param node
 * @param var
 * @return
 */
public ASTNode derivative(final ASTNode node, SymbolNode var) {
    if (node.isFree(var)) {
        return new DoubleNode(0.0);
    }
    if (node instanceof FunctionNode) {
        FunctionNode f = (FunctionNode) node;
        if (f.size() > 1 && f.getNode(0) instanceof SymbolNode) {
            SymbolNode head = (SymbolNode) f.getNode(0);
            if (f.size() == 2) {
                ASTNode arg1Derived = derivative(f.getNode(1), var);
                if (isSymbol(head, "Exp")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Exp"));
                    fun.add(f.getNode(1));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (isSymbol(head, "Cos")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Times"));
                    fun.add(new DoubleNode(-1.0));
                    fun.add(new FunctionNode(fASTFactory.createSymbol("Cos"), f.getNode(1)));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (isSymbol(head, "Sin")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Cos"));
                    fun.add(f.getNode(1));
                    return getDerivativeResult(arg1Derived, fun);
                }
            } else if (f.size() == 3 && isSymbol(head, "Power")) {
                if (f.get(2).isFree(var)) {
                    // derive x^r
                    ASTNode arg1Derived = derivative(f.getNode(1), var);
                    // (r-1)
                    FunctionNode exponent = fASTFactory.createFunction(fASTFactory.createSymbol("Plus"), new DoubleNode(-1.0), f.get(2));
                    // r*x^(r-1)
                    FunctionNode fun = fASTFactory.createFunction(fASTFactory.createSymbol("Times"), f.get(2), fASTFactory.createFunction(fASTFactory.createSymbol("Power"), f.get(1), exponent));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (f.get(1).isFree(var)) {
                    // derive a^x
                    ASTNode arg2Derived = derivative(f.getNode(2), var);
                    // log(a) * a^x
                    FunctionNode fun = fASTFactory.createFunction(fASTFactory.createSymbol("Times"), fASTFactory.createFunction(fASTFactory.createSymbol("Log"), f.get(1)), f);
                    return getDerivativeResult(arg2Derived, fun);
                }
            } else {
                if (isSymbol(head, "Plus")) {
                    FunctionNode result = new FunctionNode(f.getNode(0));
                    for (int i = 1; i < f.size(); i++) {
                        ASTNode deriv = derivative(f.getNode(i), var);
                        if (!deriv.equals(new DoubleNode(0.0))) {
                            result.add(deriv);
                        }
                    }
                    return result;
                }
                if (isSymbol(head, "Times")) {
                    FunctionNode plusResult = new FunctionNode(fASTFactory.createSymbol("Plus"));
                    for (int i = 1; i < f.size(); i++) {
                        FunctionNode timesResult = new FunctionNode(f.getNode(0));
                        boolean valid = true;
                        for (int j = 1; j < f.size(); j++) {
                            if (j == i) {
                                ASTNode deriv = derivative(f.getNode(j), var);
                                if (deriv.equals(new DoubleNode(0.0))) {
                                    valid = false;
                                } else {
                                    timesResult.add(deriv);
                                }
                            } else {
                                timesResult.add(f.getNode(j));
                            }
                        }
                        if (valid) {
                            plusResult.add(timesResult);
                        }
                    }
                    return plusResult;
                }
            }
        }
        return new FunctionNode(new SymbolNode("D"), node, var);
    // return evaluateFunction((FunctionNode) node);
    }
    if (node instanceof SymbolNode) {
        if (isSymbol((SymbolNode) node, var)) {
            return new DoubleNode(1.0);
        }
        IDoubleValue v = fVariableMap.get(node.toString());
        if (v != null) {
            return new DoubleNode(0.0);
        }
        Double dbl = SYMBOL_DOUBLE_MAP.get(node.toString());
        if (dbl != null) {
            return new DoubleNode(0.0);
        }
        return new DoubleNode(0.0);
    } else if (node instanceof NumberNode) {
        return new DoubleNode(0.0);
    }
    throw new ArithmeticMathException("EvalDouble#evaluate(ASTNode) not possible for: " + node.toString());
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) ArithmeticMathException(org.matheclipse.parser.client.math.ArithmeticMathException) NumberNode(org.matheclipse.parser.client.ast.NumberNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode)

Example 4 with SymbolNode

use of org.matheclipse.parser.client.ast.SymbolNode in project symja_android_library by axkr.

the class DoubleEvaluator method optimizeFunction.

/**
 * Optimize an already parsed in <code>functionNode</code> into an <code>ASTNode</code>.
 *
 * @param functionNode
 * @return
 */
public ASTNode optimizeFunction(final FunctionNode functionNode) {
    if (functionNode.size() > 0) {
        boolean doubleOnly = true;
        ASTNode node;
        for (int i = 1; i < functionNode.size(); i++) {
            node = functionNode.getNode(i);
            if (node instanceof NumberNode) {
                functionNode.set(i, new DoubleNode(((NumberNode) functionNode.getNode(i)).doubleValue()));
            } else if (functionNode.getNode(i) instanceof FunctionNode) {
                ASTNode optNode = optimizeFunction((FunctionNode) functionNode.getNode(i));
                if (!(optNode instanceof DoubleNode)) {
                    doubleOnly = false;
                }
                functionNode.set(i, optNode);
            } else if (node instanceof SymbolNode) {
                Double dbl = SYMBOL_DOUBLE_MAP.get(node.toString());
                if (dbl != null) {
                    functionNode.set(i, new DoubleNode(dbl));
                } else {
                    doubleOnly = false;
                }
            } else {
                doubleOnly = false;
            }
        }
        if (doubleOnly) {
            try {
                return new DoubleNode(evaluateFunction(functionNode));
            } catch (Exception e) {
            }
        }
    }
    return functionNode;
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) NumberNode(org.matheclipse.parser.client.ast.NumberNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) ArithmeticMathException(org.matheclipse.parser.client.math.ArithmeticMathException)

Example 5 with SymbolNode

use of org.matheclipse.parser.client.ast.SymbolNode in project symja_android_library by axkr.

the class Parser method getTimesImplicit.

private ASTNode getTimesImplicit(ASTNode temp) throws SyntaxError {
    FunctionNode func = fFactory.createAST(new SymbolNode("Times"));
    func.add(temp);
    do {
        getNextToken();
        temp = parseExpression();
        func.add(temp);
        if (fToken != TT_PRECEDENCE_CLOSE) {
            throwSyntaxError("\')\' expected.");
        }
        getNextToken();
    } while (fToken == TT_PRECEDENCE_OPEN);
    return func;
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode)

Aggregations

SymbolNode (org.matheclipse.parser.client.ast.SymbolNode)13 FunctionNode (org.matheclipse.parser.client.ast.FunctionNode)11 ASTNode (org.matheclipse.parser.client.ast.ASTNode)9 IExpr (org.matheclipse.core.interfaces.IExpr)3 InfixOperator (org.matheclipse.parser.client.operator.InfixOperator)3 Apfloat (org.apfloat.Apfloat)2 Apint (org.apfloat.Apint)2 IASTAppendable (org.matheclipse.core.interfaces.IASTAppendable)2 IInteger (org.matheclipse.core.interfaces.IInteger)2 ISymbol (org.matheclipse.core.interfaces.ISymbol)2 FloatNode (org.matheclipse.parser.client.ast.FloatNode)2 FractionNode (org.matheclipse.parser.client.ast.FractionNode)2 IntegerNode (org.matheclipse.parser.client.ast.IntegerNode)2 NumberNode (org.matheclipse.parser.client.ast.NumberNode)2 Pattern2Node (org.matheclipse.parser.client.ast.Pattern2Node)2 Pattern3Node (org.matheclipse.parser.client.ast.Pattern3Node)2 PatternNode (org.matheclipse.parser.client.ast.PatternNode)2 StringNode (org.matheclipse.parser.client.ast.StringNode)2 DoubleNode (org.matheclipse.parser.client.eval.DoubleNode)2 ArithmeticMathException (org.matheclipse.parser.client.math.ArithmeticMathException)2