/* 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; i Parameter:
* 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:
* 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; i Parameters:
* 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:
* 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
node -- the node to be evaluated.
*
node -- the passed node.
*
ch -- the character.
*
node -- the node to be evaluated.
*