/* Copyright @ 2004, The Institute for Genomic Research (TIGR). All rights reserved. */ /*************************************************************************** * Author: Jianwei(Jerry) Li. * Name: MathTree (Version 1.0) * Date: Created: 10/15/2004 and modified: 11/05/2004 * Descp: A Java class that evaluate a formula passed in. ***************************************************************************/ package org.tigr.util.formula; import java.awt.*; import java.util.Vector; import org.tigr.util.formula.node.EvaluateException; import org.tigr.util.formula.node.MathNode; public class MathTree implements Variant { private int gLastNodeId; private int gKey; private MathNode gRoot, gNode; private String[] gOperants; public MathTree() { gLastNodeId = 0; gNode = null; } /************************************************************************** * Description: * evaluate the tree to get the final result. *

Return: the result. *************************************************************************/ public float evaluate() throws EvaluateException { float res = 0; if(gRoot == null){ throw new EvaluateException("No Math Tree is set."); } res = processNode(gRoot); return res; } /************************************************************************** * Description: * evaluate the tree to get the final result. *

Parameter: *
vals -- the values to be evaluate based on the tree, representing * the formula. *

Return: the result. *************************************************************************/ public float evaluate(String[] vals) throws EvaluateException { float res = 0; setOperants(vals); reset(gRoot); if(gRoot == null){ throw new EvaluateException("No Math Tree is set."); } try{ res = evaluateNodeFor(gRoot); } catch (EvaluateException e){ throw e; } return res; } /**************************************************************************** * Description: * extends the nodes from the left end node. *

Parameter: *
nodeVals -- values of the nodes in the format: * left-operant, operator, right-operant *

Return: the id of the last node that is inserted. ****************************************************************************/ public int extendTree(String[] nodeVals, int offset){ int indx; MathNode left, right, current, children[]; indx = gLastNodeId; left = new MathNode(nodeVals[0]); right = new MathNode(nodeVals[2]); children = new MathNode[2]; children[0] = left; children[1] = right; if(gRoot == null){ gRoot = new MathNode(nodeVals[1]); gRoot.setIndex(++indx); gRoot.setChildren(children); } else { current = getNodeAt(offset); while(current.getChildren() != null){ current = current.getChildren()[0]; } current.setContent(nodeVals[1]); current.setChildren(children); } left.setIndex(++indx); right.setIndex(++indx); gLastNodeId = indx; return indx; } /**************************************************************************** * Description: * searches a node and return it. *

Parameter: *
index -- the id of the node to be searched. *

Return: the node if found. ****************************************************************************/ public MathNode getNodeAt(int indx){ gKey = indx; MathNode current = gRoot; // start at root if(current.getIndex() == indx){ return current; } else { current = searchSubTree(current); return current; } } /**************************************************************************** * Description: * checks if there are node that has formula as its value. *

Return: the formula and id of the node if found. ****************************************************************************/ public String[] findExpression(){ String temp[] = null; temp = hasFormulaAt(gRoot); return temp; } public MathNode getRootNode() { return gRoot; } /*************************************************************************** * Description: * sets the result to null for those nodes whose values is a number. **************************************************************************/ public void reset(MathNode node){ MathNode[] children = node.getChildren(); int addr; String val; if(children != null){ for(int i=0; iDescription: * processe the evaluation of the node that has two operants. The operants * are not the real values. They are the indices of the gOperants. *

Parameter: *
node -- the node to be evaluated. *

Return: the result. ****************************************************************************/ private float evaluateNodeFor(MathNode node) throws EvaluateException { float lVal, rVal, res; Float lf, rf; int addr; MathNode[] children = node.getChildren(); String lop, rop, operator; char op; res = 0; try{ if(children != null){ lf = children[0].getResult(); rf = children[1].getResult(); operator = node.getContent(); if(lf != null){ lop = children[0].getContent(); if(isOperator(lop.charAt(0))){ lVal = ((Float)children[0].getResult()).floatValue(); } else { addr = Integer.parseInt(children[0].getContent()); lVal = Float.parseFloat(gOperants[addr]); } } else { lVal = evaluateNodeFor(children[0]); } if(rf != null){ rop = children[1].getContent(); if(isOperator(rop.charAt(0))){ rVal = ((Float)children[1].getResult()).floatValue(); } else { addr = Integer.parseInt(children[1].getContent()); rVal = Float.parseFloat(gOperants[addr]); } } else { rVal = evaluateNodeFor(children[1]); } op = operator.charAt(0); if(op == OPERATORS[0]){ // '+' res = lVal + rVal; } else if (op == OPERATORS[1]){ // '-' res = lVal - rVal; } else if (op == OPERATORS[2]){ // '*' res = lVal * rVal; } else if (op == OPERATORS[3]){ // '/' res = lVal / rVal; } node.setResult(new Float(res)); //System.out.println("" + lVal + "" + op + "" + rVal + " = " + res); } } catch (Exception e){ throw new EvaluateException(e.getMessage()); } return res; } /*************************************************************************** * Description: * checks if the passed node has formula as its value. *

Parameters: *
node -- the passed node. *

Return: a string array whose first element is the formula and * the seconde one is the index of the node. **************************************************************************/ private String[] hasFormulaAt(MathNode node){ int addr; float res; MathNode[] children = node.getChildren(); String val; String[] fa = null; if(children != null){ for(int i=0; iDescription: * checks if the passed character is an operator. *

Parameters: *
ch -- the character. *

Return: true if it is; otherwise, false. **************************************************************************/ private boolean isOperator(char ch){ boolean yes = false; for(int i=0; i<4; i++){ if(ch == OPERATORS[i]){ yes = true; i = 4; } } return yes; } /**************************************************************************** * Description: * processe the evaluation of the node that has two operants. *

Parameter: *
node -- the node to be evaluated. *

Return: the result. ****************************************************************************/ private float processNode(MathNode node) throws EvaluateException { float lVal, rVal, res; MathNode[] children = node.getChildren(); String lop, rop, operator; char op; res = 0; try { if(children != null){ lop = children[0].getContent(); rop = children[1].getContent(); operator = node.getContent(); if(isOperator(lop.charAt(0))){ lVal = processNode(children[0]); } else { lVal = Float.parseFloat(lop); } if(isOperator(rop.charAt(0))){ rVal = processNode(children[1]); } else { rVal = Float.parseFloat(rop); } op = operator.charAt(0); if(op == OPERATORS[0]){ // '+' res = lVal + rVal; } else if (op == OPERATORS[1]){ // '-' res = lVal - rVal; } else if (op == OPERATORS[2]){ // '*' res = lVal * rVal; } else if (op == OPERATORS[3]){ // '/' res = lVal / rVal; } //System.out.println("" + lVal + "" + op + "" + rVal + " = " + res); node.setContent("" + res); } } catch (Exception e){ throw new EvaluateException(e.getMessage()); } return res; } private MathNode searchSubTree(MathNode parent){ MathNode[] children = parent.getChildren(); MathNode temp; int addr; String pName; if(children != null){ for(int i=0; i