package tools;
import java.util.Vector;
public class CaltechEval {
String expression;
String[] Operators;
int[] OperatorsArgs;
boolean[] OperatorsLeftRight;
int[] OperatorsPrecedence;
int NOPERATORS;
public static void main(String[] args) {
if ((args == null) || (args.length != 1)) {
System.exit(0);
}
CaltechEval m = new CaltechEval(args[0]);
FileoutputUtil.log(args[0].replace(" ", "") + " = " + m.evaluate());
}
public CaltechEval(String s) {
init();
this.expression = s.replace(" ", "");
}
private void init() {
this.NOPERATORS = 19;
this.Operators = new String[this.NOPERATORS];
this.OperatorsArgs = new int[this.NOPERATORS];
this.OperatorsLeftRight = new boolean[this.NOPERATORS];
this.OperatorsPrecedence = new int[this.NOPERATORS];
this.Operators[0] = "+";
this.OperatorsArgs[0] = 2;
this.OperatorsLeftRight[0] = true;
this.OperatorsPrecedence[0] = 2;
this.Operators[1] = "-";
this.OperatorsArgs[1] = 2;
this.OperatorsLeftRight[1] = true;
this.OperatorsPrecedence[1] = 2;
this.Operators[2] = "*";
this.OperatorsArgs[2] = 2;
this.OperatorsLeftRight[2] = true;
this.OperatorsPrecedence[2] = 3;
this.Operators[3] = "/";
this.OperatorsArgs[3] = 2;
this.OperatorsLeftRight[3] = true;
this.OperatorsPrecedence[3] = 3;
this.Operators[4] = "sin";
this.OperatorsArgs[4] = 1;
this.OperatorsLeftRight[4] = false;
this.OperatorsPrecedence[4] = 10;
this.Operators[5] = "cos";
this.OperatorsArgs[5] = 1;
this.OperatorsLeftRight[5] = false;
this.OperatorsPrecedence[5] = 10;
this.Operators[6] = "tan";
this.OperatorsArgs[6] = 1;
this.OperatorsLeftRight[6] = false;
this.OperatorsPrecedence[6] = 10;
this.Operators[7] = "exp";
this.OperatorsArgs[7] = 1;
this.OperatorsLeftRight[7] = false;
this.OperatorsPrecedence[7] = 10;
this.Operators[8] = "sqrt";
this.OperatorsArgs[8] = 1;
this.OperatorsLeftRight[8] = false;
this.OperatorsPrecedence[8] = 10;
this.Operators[9] = "asin";
this.OperatorsArgs[9] = 1;
this.OperatorsLeftRight[9] = false;
this.OperatorsPrecedence[9] = 10;
this.Operators[10] = "acos";
this.OperatorsArgs[10] = 1;
this.OperatorsLeftRight[10] = false;
this.OperatorsPrecedence[10] = 10;
this.Operators[11] = "atan";
this.OperatorsArgs[11] = 1;
this.OperatorsLeftRight[11] = false;
this.OperatorsPrecedence[11] = 10;
this.Operators[12] = "atan2";
this.OperatorsArgs[12] = 2;
this.OperatorsLeftRight[12] = false;
this.OperatorsPrecedence[12] = 10;
this.Operators[13] = "max";
this.OperatorsArgs[13] = 2;
this.OperatorsLeftRight[13] = false;
this.OperatorsPrecedence[13] = 10;
this.Operators[14] = "min";
this.OperatorsArgs[14] = 2;
this.OperatorsLeftRight[14] = false;
this.OperatorsPrecedence[14] = 10;
this.Operators[15] = ",";
this.OperatorsArgs[15] = 2;
this.OperatorsLeftRight[15] = true;
this.OperatorsPrecedence[15] = 1;
this.Operators[16] = "u";
this.OperatorsArgs[16] = 1;
this.OperatorsLeftRight[16] = false;
this.OperatorsPrecedence[16] = 4;
this.Operators[17] = "d";
this.OperatorsArgs[17] = 1;
this.OperatorsLeftRight[17] = false;
this.OperatorsPrecedence[17] = 4;
this.Operators[18] = "n";
this.OperatorsArgs[18] = 1;
this.OperatorsLeftRight[18] = false;
this.OperatorsPrecedence[18] = 11;
}
public double evaluate() {
return eval(this.expression);
}
private int getOperator(String op) {
for (int i = 0; i < this.NOPERATORS; i++) {
if ((op.equals(this.Operators[i])) && (op.length() == this.Operators[i].length())) {
return i;
}
}
return -1;
}
private double doOp(String op, double arg1, double arg2) {
if (op.equals("+")) {
return arg1 + arg2;
}
if (op.equals("-")) {
return arg1 - arg2;
}
if (op.equals("*")) {
return arg1 * arg2;
}
if (op.equals("/")) {
return arg1 / arg2;
}
if (op.equals("sin")) {
return Math.sin(arg1);
}
if (op.equals("cos")) {
return Math.cos(arg1);
}
if (op.equals("tan")) {
return Math.tan(arg1);
}
if (op.equals("exp")) {
return Math.exp(arg1);
}
if (op.equals("sqrt")) {
return Math.sqrt(arg1);
}
if (op.equals("asin")) {
return Math.asin(arg1);
}
if (op.equals("acos")) {
return Math.acos(arg1);
}
if (op.equals("atan")) {
return Math.atan(arg1);
}
if (op.equals("atan2")) {
return Math.atan2(arg1, arg2);
}
if (op.equals("max")) {
return Math.max(arg1, arg2);
}
if (op.equals("min")) {
return Math.min(arg1, arg2);
}
if (op.equals("u")) {
return Math.ceil(arg1);
}
if (op.equals("d")) {
return Math.floor(arg1);
}
if (op.equals("n")) {
return -arg1;
}
throw new RuntimeException("Invalid operator: " + op);
}
private boolean inOperand(char c) {
return ((c >= '0') && (c <= '9')) || (c == '.');
}
private Vector toTokens(String s) {
Vector tokenStrings = new Vector(1);
String operand = "";
String operator = "";
int nd = 0;
int nt = 0;
int i = 0;
while (i < s.length()) {
char c = s.charAt(i);
char cnext = ' ';
if (i < s.length() - 1) {
cnext = s.charAt(i + 1);
}
if ((nt > 0) && (operator.equals("atan")) && (c == '2')) {
tokenStrings.addElement("atan2");
operator = "";
nt = 0;
i++;
} else if (inOperand(c)) {
operand = operand + s.charAt(i);
nd++;
if (nt > 0) {
tokenStrings.addElement(operator);
}
nt = 0;
operator = "";
i++;
} else if ((c == 'e') && (nd > 0) && (i < s.length() - 2) && ((cnext == '+') || (cnext == '-') || (inOperand(cnext)))) {
operand = operand + c;
operand = operand + cnext;
nd += 2;
nt = 0;
i += 2;
} else if ((c == '(') || (c == ')')) {
if (nd > 0) {
tokenStrings.addElement(operand);
}
nd = 0;
operand = "";
if (nt > 0) {
tokenStrings.addElement(operator);
}
operator = "" + c;
tokenStrings.addElement(operator);
nt = 0;
operator = "";
i++;
} else {
if (nd > 0) {
tokenStrings.addElement(operand);
}
nd = 0;
operand = "";
operator = operator + c;
if ((operator.equals("+")) || (operator.equals("-")) || (operator.equals("*")) || (operator.equals("/")) || (operator.equals(","))) {
tokenStrings.addElement(operator);
nt = 0;
operator = "";
} else {
nt++;
}
i++;
}
}
if (nd > 0) {
tokenStrings.addElement(operand);
nt = 0;
}
if (nt > 0) {
tokenStrings.addElement(operator);
}
return tokenStrings;
}
private double eval(String s) {
Vector tokens = toTokens(s);
while (tokens.size() > 1) {
tokens = reduceTokens(tokens);
}
return Double.parseDouble((String) tokens.elementAt(0));
}
public Vector reduceTokens(Vector tokens) {
double leftValue = 0.0D;
while (tokens.indexOf("(") != -1) {
int ib = tokens.indexOf("(");
Vector bracketTokens = new Vector();
int brackets = 1;
for (int it = ib + 1; it < tokens.size(); it++) {
String st = (String) tokens.elementAt(it);
switch (st) {
case ")":
brackets--;
break;
case "(":
brackets++;
break;
}
if (brackets != 0) {
continue;
}
for (int i3 = ib + 1; i3 < it; i3++) {
bracketTokens.addElement(tokens.elementAt(i3));
}
int startsize = bracketTokens.size();
bracketTokens = reduceTokens(bracketTokens);
int endsize = bracketTokens.size();
int ip = ib;
for (int i3 = 0; i3 < bracketTokens.size(); i3++) {
tokens.setElementAt(bracketTokens.elementAt(i3), ip++);
}
for (int i = 0; i < startsize - endsize + 2; i++) {
tokens.removeElementAt(ip);
}
break;
}
}
while (tokens.size() > 1) {
int maxprec = 0;
int ipos = -1;
for (int it = 0; it < tokens.size(); it++) {
String st = (String) tokens.elementAt(it);
int iop = getOperator(st);
if (iop == -1) {
continue;
}
if (this.OperatorsPrecedence[iop] >= maxprec) {
maxprec = this.OperatorsPrecedence[iop];
ipos = it;
}
}
if (ipos == -1) {
return tokens;
}
int it = ipos;
String st = (String) tokens.elementAt(it);
int iop = getOperator(st);
if (this.OperatorsLeftRight[iop]) {
if (!st.equals(",")) {
int ipt = it - 1;
if (it > 0) {
String stleft = (String) tokens.elementAt(it - 1);
if (getOperator(stleft) != -1) {
ipt = it;
leftValue = 0.0D;
} else {
leftValue = Double.parseDouble(stleft);
}
} else {
ipt = 0;
leftValue = 0.0D;
}
String stright = (String) tokens.elementAt(it + 1);
double rightValue1 = Double.parseDouble(stright);
double value = doOp(st, leftValue, rightValue1);
stright = "" + value;
tokens.setElementAt(stright, ipt);
tokens.removeElementAt(ipt + 1);
if ((it > 0) && (ipt != it)) {
tokens.removeElementAt(ipt + 1);
continue;
}
}
tokens.removeElementAt(it);
continue;
}
int nargs = this.OperatorsArgs[iop];
String stright = (String) tokens.elementAt(it + 1);
double rightValue1 = Double.parseDouble(stright);
double rightValue2 = 0.0D;
if (nargs > 1) {
stright = (String) tokens.elementAt(it + 2);
rightValue2 = Double.parseDouble(stright);
}
double value = doOp(st, rightValue1, rightValue2);
stright = "" + value;
tokens.setElementAt(stright, it);
tokens.removeElementAt(it + 1);
if (nargs > 1) {
tokens.removeElementAt(it + 1);
}
}
return tokens;
}
}