BigFraction
numbers.
+ *
+ * @see org.apache.commons.math3.fraction.BigFraction
+ */
+public class BigFractionEvalVisitor extends AbstractASTVisitorexpression String
and return the resulting
+ * ASTNode
+ *
+ * @param expression
+ * @return
+ * @throws SyntaxError
+ */
+ public static ASTNode parseNode(final int decimalDigits, String expression, boolean relaxedSyntax) {
+ BigFractionEvalVisitor dfpEvaluator = new BigFractionEvalVisitor(relaxedSyntax);
+ return dfpEvaluator.parse(expression);
+ }
+
+ private final BigFractionField fDfpField;
+
+ private final BigFractionNode fZERO;
+
+ private ASTNode fNode;
+
+ private final ASTNodeFactory fASTFactory;
+
+ public BigFractionEvalVisitor() {
+ this(null, false);
+ }
+
+ public BigFractionEvalVisitor(ASTNode node, boolean relaxedSyntax) {
+ super(relaxedSyntax);
+ fASTFactory = new ASTNodeFactory(relaxedSyntax);
+ fVariableMap = new HashMapexpression
(possibly after a new Variable
+ * assignment)
+ *
+ * @param Expression
+ * @return
+ * @throws SyntaxError
+ */
+ public BigFraction evaluate() {
+ if (fNode == null) {
+ throw new SyntaxError(0, 0, 0, " ", "No parser input defined", 1);
+ }
+ return evaluateNode(fNode);
+ }
+
+ /**
+ * Parse the given expression String
and evaluate it to a
+ * BigFraction value
+ *
+ * @param expression
+ * @return
+ * @throws SyntaxError
+ */
+ public BigFraction evaluate(String expression) {
+ Parser p;
+ if (fRelaxedSyntax) {
+ p = new Parser(ASTNodeFactory.RELAXED_STYLE_FACTORY, true);
+ } else {
+ p = new Parser(ASTNodeFactory.MMA_STYLE_FACTORY, false);
+ }
+ fNode = p.parse(expression);
+ if (fNode instanceof FunctionNode) {
+ fNode = optimizeFunction((FunctionNode) fNode);
+ }
+ return evaluateNode(fNode);
+ }
+
+ /**
+ * Evaluate an already parsed in FunctionNode
into a
+ * souble
number value.
+ *
+ * @param functionNode
+ * @return
+ *
+ * @throws ArithmeticMathException
+ * if the functionNode
cannot be evaluated.
+ */
+ public BigFraction evaluateFunction(final FunctionNode functionNode) {
+ if (functionNode.size() > 0 && functionNode.getNode(0) instanceof SymbolNode) {
+ String symbol = functionNode.getNode(0).toString();
+ if (symbol.equals("If") || (fRelaxedSyntax && symbol.equalsIgnoreCase("if"))) {
+ if (functionNode.size() == 3) {
+ if (evaluateNodeLogical(functionNode.getNode(1))) {
+ return evaluateNode(functionNode.getNode(2));
+ }
+ } else if (functionNode.size() == 4) {
+ if (evaluateNodeLogical(functionNode.getNode(1))) {
+ return evaluateNode(functionNode.getNode(2));
+ } else {
+ return evaluateNode(functionNode.getNode(3));
+ }
+ }
+ } else {
+ Object obj = FUNCTION_MAP.get(symbol);
+ if (obj instanceof IFieldElementFunctionNode) {
+ return ((IFieldElementFunctionNodeBigFraction
number value.
+ *
+ * @param node
+ * abstract syntax tree node
+ *
+ * @return the evaluated BigFraction number
+ *
+ * @throws ArithmeticMathException
+ * if the node
cannot be evaluated.
+ */
+ @Override
+ public BigFraction evaluateNode(final ASTNode node) {
+ if (node instanceof BigFractionNode) {
+ return ((BigFractionNode) node).getValue();
+ }
+ if (node instanceof FunctionNode) {
+ return evaluateFunction((FunctionNode) node);
+ }
+ if (node instanceof SymbolNode) {
+ FieldElementVariabletrue
us e function syntax like
+ * sin(x)
otherwise use Sin[x]
.
+ */
+ public void getVariables(String expression, SetSymbolNode
and test if the
+ * names are equal.
+ *
+ * @param symbol1
+ * @param symbol2Name
+ * @return
+ */
+ public boolean isSymbol(SymbolNode symbol1, String symbol2Name) {
+ if (fRelaxedSyntax) {
+ return symbol1.getString().equalsIgnoreCase(symbol2Name);
+ }
+ return symbol1.getString().equals(symbol2Name);
+ }
+
+ /**
+ * Check if the given symbol is a SymbolNode
and test if the
+ * names are equal.
+ *
+ * @param symbol1
+ * @param symbol2
+ * @return
+ */
+ public boolean isSymbol(SymbolNode symbol1, SymbolNode symbol2) {
+ if (fRelaxedSyntax) {
+ return symbol1.getString().equalsIgnoreCase(symbol2.getString());
+ }
+ return symbol1.equals(symbol2);
+ }
+
+ /**
+ * Optimize an already parsed in functionNode
into an
+ * ASTNode
.
+ *
+ * @param functionNode
+ * @return
+ *
+ */
+ @Override
+ public ASTNode optimizeFunction(final FunctionNode functionNode) {
+ // if (functionNode.size() > 0) {
+ // boolean dfpOnly = true;
+ // ASTNode node;
+ // for (int i = 1; i < functionNode.size(); i++) {
+ // node = functionNode.getNode(i);
+ // if (node instanceof NumberNode) {
+ // if (node instanceof FractionNode) {
+ // functionNode.set(i,
+ // new BigFractionNode(fDfpField.newDfp(((FractionNode)
+ // node).getNumerator().toString())
+ // .divide(fDfpField.newDfp(((FractionNode)
+ // node).getDenominator().toString()))));
+ // } else if (node instanceof IntegerNode) {
+ // String iStr = ((NumberNode) functionNode.getNode(i)).getString();
+ // if (iStr != null) {
+ // functionNode.set(i, new BigFractionNode(fDfpField.newDfp(iStr)));
+ // } else {
+ // functionNode.set(i, new BigFractionNode(
+ // fDfpField.newDfp(((IntegerNode)
+ // functionNode.getNode(i)).getIntValue())));
+ // }
+ // } else {
+ // functionNode.set(i, new BigFractionNode(
+ // fDfpField.newDfp(((NumberNode)
+ // functionNode.getNode(i)).getString())));
+ // }
+ // } else if (functionNode.getNode(i) instanceof FunctionNode) {
+ // ASTNode optNode = optimizeFunction((FunctionNode)
+ // functionNode.getNode(i));
+ // if (!(optNode instanceof BigFractionNode)) {
+ // dfpOnly = false;
+ // }
+ // functionNode.set(i, optNode);
+ // } else if (node instanceof SymbolNode) {
+ // BigFraction dbl = SYMBOL_MAP.get(node.toString());
+ // if (dbl != null) {
+ // functionNode.set(i, new BigFractionNode(dbl));
+ // } else {
+ // dfpOnly = false;
+ // }
+ // } else {
+ // dfpOnly = false;
+ // }
+ // }
+ // if (dfpOnly) {
+ // try {
+ // return new BigFractionNode(evaluateFunction(functionNode));
+ // } catch (Exception e) {
+ //
+ // }
+ // }
+ // }
+ return functionNode;
+ }
+
+ /**
+ * Parse the given expression String
and store the resulting
+ * ASTNode in this BigFractionEvaluator
+ *
+ * @param expression
+ * @return
+ * @throws SyntaxError
+ */
+ public ASTNode parse(String expression) {
+ Parser p;
+ if (fRelaxedSyntax) {
+ p = new Parser(ASTNodeFactory.RELAXED_STYLE_FACTORY, true);
+ } else {
+ p = new Parser(ASTNodeFactory.MMA_STYLE_FACTORY, false);
+ }
+ fNode = p.parse(expression);
+ if (fNode instanceof FunctionNode) {
+ fNode = optimizeFunction((FunctionNode) fNode);
+ }
+ return fNode;
+ }
+
+ @Override
+ public void setUp(BigFraction data) {
+ super.setUp(data);
+ }
+
+ public void setValue(FieldElementVariableString
representation of the given
+ * org.apache.commons.math3.fraction.BigFraction
number.
+ *
+ * @param c
+ * @return
+ *
+ */
+ public static String toString(BigFraction bf) {
+ return bf.toString();
+ }
+
+ public BigFractionEvaluator(IASTVisitor+Predefined evaluation engine BigFractionEvaluator for the org.apache.commons.math3.fraction.BigFraction class. +
+ + diff --git a/symja-parser/src/test/java/org/matheclipse/parser/test/eval/AllEvalTests.java b/symja-parser/src/test/java/org/matheclipse/parser/test/eval/AllEvalTests.java index d9a6079..076f32c 100644 --- a/symja-parser/src/test/java/org/matheclipse/parser/test/eval/AllEvalTests.java +++ b/symja-parser/src/test/java/org/matheclipse/parser/test/eval/AllEvalTests.java @@ -17,6 +17,7 @@ public static Test suite() { s.addTestSuite(EvalDoubleRelaxedTestCase.class); s.addTestSuite(EvalComplexRelaxedTestCase.class); s.addTestSuite(EvalDfpRelaxedTestCase.class); + s.addTestSuite(EvalBigFractionRelaxedTestCase.class); return s; } diff --git a/symja-parser/src/test/java/org/matheclipse/parser/test/eval/EvalBigFractionRelaxedTestCase.java b/symja-parser/src/test/java/org/matheclipse/parser/test/eval/EvalBigFractionRelaxedTestCase.java new file mode 100644 index 0000000..84deb66 --- /dev/null +++ b/symja-parser/src/test/java/org/matheclipse/parser/test/eval/EvalBigFractionRelaxedTestCase.java @@ -0,0 +1,112 @@ +package org.matheclipse.parser.test.eval; + +import org.apache.commons.math3.fraction.BigFraction; +import org.junit.Assert; +import org.matheclipse.parser.client.eval.BooleanVariable; +import org.matheclipse.parser.client.eval.bigfraction.BigFractionEvalVisitor; +import org.matheclipse.parser.client.eval.bigfraction.BigFractionEvaluator; +import org.matheclipse.parser.client.eval.bigfraction.BigFractionVariable; + +import junit.framework.TestCase; + +/** + * Tests evaluation inBigFraction
expression mode
+ *
+ * @see org.apache.commons.math3.fraction.BigFraction
+ */
+public class EvalBigFractionRelaxedTestCase extends TestCase {
+
+ public EvalBigFractionRelaxedTestCase(String name) {
+ super(name);
+ }
+
+ public void check(String in, String compareWith) {
+ try {
+ BigFractionEvalVisitor engine = new BigFractionEvalVisitor(true);
+ BigFraction bf = engine.evaluate(in);
+ String result = BigFractionEvaluator.toString(bf);
+ assertEquals(result, compareWith);
+ } catch (Exception e) {
+ e.printStackTrace();
+ assertEquals("", e.getMessage());
+ }
+ }
+
+ public void testEval001() {
+
+ check("42", "42");
+ check("1.5", "3 / 2");
+ check("-42", "-42");
+ check("+42", "42");
+ check("-42.1", "-5925048259759309 / 140737488355328");
+ check("+42.2", "2969561004297421 / 70368744177664");
+ check("-3/4", "-3 / 4");
+ check("+3/4", "3 / 4");
+ check("0^2", "0");
+ check("3^3", "27");
+ check("2^9", "512");
+ check("2^3^2", "512");
+ check("(2^3)^2", "64");
+ check("3+4*7", "31");
+ check("3+4*7*3", "87");
+ check("1+2+3+4*7*3", "90");
+ }
+
+ public void testEval003() {
+ try {
+ BigFractionVariable vc = new BigFractionVariable(new BigFraction(3));
+ BigFractionEvalVisitor engine = new BigFractionEvalVisitor(true);
+ engine.defineVariable("x", vc);
+ BigFraction bf = engine.evaluate("x^2+3*x^3");
+ String result = BigFractionEvaluator.toString(bf);
+ assertEquals(result, "90");
+
+ vc.setValue(new BigFraction(4));
+ bf = engine.evaluate();
+ result = BigFractionEvaluator.toString(bf);
+ assertEquals(result, "208");
+ } catch (Exception e) {
+ e.printStackTrace();
+ assertEquals("", e.getMessage());
+ }
+ }
+
+ public void testEval006() {
+ try {
+ BigFractionEvalVisitor engine = new BigFractionEvalVisitor(true);
+ BooleanVariable vb = new BooleanVariable(true);
+ engine.defineVariable("$1", vb);
+ BooleanVariable vb2 = new BooleanVariable(true);
+ engine.defineVariable("$2", vb2);
+ BigFraction bf = engine.evaluate("if($1 && $2, 1, 0)");
+ Assert.assertEquals(BigFractionEvaluator.toString(bf), "1");
+ vb.setValue(false);
+ bf = engine.evaluate();
+ Assert.assertEquals(BigFractionEvaluator.toString(bf), "0");
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.assertEquals("", e.getMessage());
+ }
+ }
+
+ public void testEval007() {
+ try {
+
+ BigFractionEvalVisitor engine = new BigFractionEvalVisitor(true);
+
+ BigFractionVariable vc = new BigFractionVariable(new BigFraction(3));
+ engine.defineVariable("$1", vc);
+
+ BigFractionVariable vc2 = new BigFractionVariable(new BigFraction(-4));
+ engine.defineVariable("$2", vc2);
+ BigFraction bf = engine.evaluate("$i = $1+$2; IF($i==0, 1, -1)");
+ Assert.assertEquals(BigFractionEvaluator.toString(bf), "-1");
+ vc2.setValue(-3);
+ bf = engine.evaluate();
+ Assert.assertEquals(BigFractionEvaluator.toString(bf), "1");
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.assertEquals("", e.getMessage());
+ }
+ }
+}
\ No newline at end of file