package org.matheclipse.core.eval;

import org.matheclipse.core.basic.Alloc;
import org.matheclipse.core.eval.interfaces.INumeric;
import org.matheclipse.core.eval.interfaces.ISignedNumberConstant;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.expression.Num;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IEvaluator;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.parser.client.ast.ASTNode;
import org.matheclipse.parser.client.eval.DoubleEvaluator;

public class EvalDouble extends DoubleEvaluator {
	static {
		// initialize the global available symbols
		F.initSymbols();
	}

	public EvalDouble() {
		this(null, false);
	}

	public EvalDouble(boolean relaxedSyntax) {
		this(null, relaxedSyntax);
	}

	public EvalDouble(ASTNode node, boolean relaxedSyntax) {
		super(node, relaxedSyntax);
		setCallbackFunction(CoreCallbackFunction.CONST);
	}

	public static double eval(final double[] stack, final int top, final IExpr expr) {
		if (expr instanceof IAST) {
			return evalAST(stack, top, (IAST) expr);
		}
		if (expr instanceof ISignedNumber) {
			return ((ISignedNumber) expr).doubleValue();
		}
		if (expr instanceof ISymbol) {
			return evalSymbol(((ISymbol) expr));
		}
		throw new UnsupportedOperationException("EvalDouble#eval(): " + expr);
	}

	public static double evalAST(double[] stack, final int top, final IAST ast) {
		final ISymbol symbol = (ISymbol) ast.get(0);
		final IEvaluator module = symbol.getEvaluator();
		if (module instanceof INumeric) {
			int newTop = top;
			// fast evaluation path
			if (top + ast.size() >= stack.length) {
				stack = Alloc.vector(ast.size() + 50);
			}
			for (int i = 1; i < ast.size(); i++) {
				++newTop;
				stack[newTop] = eval(stack, newTop, ast.get(i));
			}
			return ((INumeric) module).evalReal(stack, newTop, ast.size() - 1);
		}
		// slow evaluation path
		final IExpr result = F.evaln(ast);
		if (result instanceof Num) {
			return ((Num) result).doubleValue();
		}
		throw new UnsupportedOperationException("EvalDouble#evalAST(): " + ast);
	}

	public static double evalSymbol(final ISymbol symbol) {
		if (symbol.hasLocalVariableStack()) {
			return ((ISignedNumber) symbol.get()).doubleValue();
		}
		final IEvaluator module = symbol.getEvaluator();
		if (module instanceof ISignedNumberConstant) {
			// fast evaluation path
			return ((ISignedNumberConstant) module).evalReal();
		}
		// slow evaluation path
		final IExpr result = F.evaln(symbol);
		if (result instanceof Num) {
			return ((Num) result).doubleValue();
		}
		throw new UnsupportedOperationException("EvalDouble#evalSymbol() - no value assigned for symbol: " + symbol);
	}
}

 

Ads help maintain this website.