package org.matheclipse.core.eval;

import org.matheclipse.core.basic.Alloc;
import org.matheclipse.core.eval.interfaces.INumericComplex;
import org.matheclipse.core.eval.interfaces.INumericComplexConstant;
import org.matheclipse.core.eval.interfaces.ISignedNumberConstant;
import org.matheclipse.core.eval.util.DoubleStack;
import org.matheclipse.core.expression.ComplexNum;
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;

public class EvalComplex {
	public static double[] eval(final DoubleStack stack, final int top, final IExpr expr) {
		if (expr instanceof IAST) {
			return evalAST(stack, top, (IAST) expr);
		}
		if (expr instanceof ISignedNumber) {
			final double[] result = Alloc.vector(2);
			result[0] = ((ISignedNumber) expr).doubleValue();
			result[1] = 0.0;
			return result;
		}
		if (expr instanceof ComplexNum) {
			final double[] res = Alloc.vector(2);
			res[0] = ((ComplexNum) expr).getRealPart();
			res[1] = ((ComplexNum) expr).getImaginaryPart();
			return res;
		}
		if (expr instanceof ISymbol) {
			return evalSymbol(((ISymbol) expr));
		}
		throw new UnsupportedOperationException();
	}

	public static double[] evalAST(final DoubleStack stack, final int top, final IAST ast) {
		final int newTop = top;
		final ISymbol symbol = (ISymbol) ast.get(0);
		final IEvaluator module = symbol.getEvaluator();
		if (module instanceof INumericComplex) {
			// fast evaluation path
			stack.ensureCapacity(top + ast.size() * 2);
			for (int i = 1; i < ast.size(); i++) {
				final double[] result = eval(stack, newTop, ast.get(i));
				stack.push(result[0]);
				stack.push(result[1]);
			}
			return ((INumericComplex) module).evalComplex(stack, ast.size() - 1);
		}
		// slow evaluation path
		final IExpr result = F.evaln(ast);
		if (result instanceof ComplexNum) {
			final double[] res = Alloc.vector(2);
			res[0] = ((ComplexNum) result).getRealPart();
			res[1] = ((ComplexNum) result).getImaginaryPart();
			return res;
		}
		if (result instanceof Num) {
			final double[] res = Alloc.vector(2);
			res[0] = ((Num) result).doubleValue();
			res[1] = 0.0;
			return res;
		}
		throw new UnsupportedOperationException();
	}

	public static double[] evalSymbol(final ISymbol symbol) {
		if (symbol.hasLocalVariableStack()) {
			final IExpr expr = symbol.get();
			if (expr instanceof ISignedNumber) {
				final double[] result = Alloc.vector(2);
				result[0] = ((ISignedNumber) expr).doubleValue();
				result[1] = 0.0;
				return result;
			}
			if (expr instanceof ComplexNum) {
				final double[] result = Alloc.vector(2);
				result[0] = ((ComplexNum) expr).getRealPart();
				result[1] = ((ComplexNum) expr).getImaginaryPart();
				return result;
			}
		}
		final IEvaluator module = symbol.getEvaluator();
		if (module instanceof ISignedNumberConstant) {
			// fast evaluation path
			final double[] result = Alloc.vector(2);
			result[0] = ((ISignedNumberConstant) module).evalReal();
			result[1] = 0.0;
			return result;
		} else if (module instanceof INumericComplexConstant) {
			// fast evaluation path
			return ((INumericComplexConstant) module).evalComplex();
		}

		// slow evaluation path
		final IExpr result = F.evaln(symbol);
		if (result instanceof ComplexNum) {
			final double[] res = Alloc.vector(2);
			res[0] = ((ComplexNum) result).getRealPart();
			res[1] = ((ComplexNum) result).getImaginaryPart();
			return res;
		}
		if (result instanceof Num) {
			final double[] res = Alloc.vector(2);
			res[0] = ((Num) result).doubleValue();
			res[1] = 0.0;
			return res;
		}
		throw new UnsupportedOperationException();
	}
}

 

Ads help maintain this website.