package edu.jsu.leathrum.mathlets.shared; import java.awt.event.KeyEvent; import java.io.StringReader; import java.awt.Color; import java.util.Stack; public abstract class AParserInputSet extends InputSet { private static StringReader collector = new StringReader("\n"); private static Parser parser = new Parser(collector); boolean dirty = true; boolean errorDetected = false; Stack parseReturn = new Stack(); public AParserInputSet(String namestr, int size, boolean chbox, Color c) { super(namestr, size, chbox, c); parser.ReInit(collector); } public AParserInputSet(String namestr, int size, boolean chbox) { super(namestr, size, chbox); parser.ReInit(collector); } public AParserInputSet(String namestr, int size) { super(namestr, size); parser.ReInit(collector); } public AParserInputSet(String namestr, int size, Color c) { super(namestr, size, c); parser.ReInit(collector); } public void setToDefault() { super.setToDefault(); setDirty(); } // overrides public void setField(String val) { super.setField(val); setDirty(); } // overrides private void evaluate(String expr) { StringReader collector = new StringReader(expr+"\n"); parser.ReInit(collector); parseReturn = parser.getStack(); } private double evaluateStack(Stack s) { int top = ((Integer) s.pop()).intValue(); double a, b, c, d; switch (top) { case Parser.DBL: try {return ((Double) s.pop()).doubleValue();} catch (ClassCastException e) { selectAll(); requestFocus(); errorDetected = true; return Double.NaN; } case Parser.PLUS: a = evaluateStack(s); b = evaluateStack(s); return a + b; case Parser.MINUS: a = evaluateStack(s); b = evaluateStack(s); return b - a; case Parser.MULT: a = evaluateStack(s); b = evaluateStack(s); return a * b; case Parser.DIV: a = evaluateStack(s); b = evaluateStack(s); return b / a; case Parser.POW: a = evaluateStack(s); b = evaluateStack(s); return Math.pow(b,a); case Parser.NEG: a = evaluateStack(s); return -a; case Parser.PI: return Math.PI; case Parser.E: return Math.E; case Parser.INFTY: return Double.POSITIVE_INFINITY; case Parser.VARX: case Parser.VARY: case Parser.VARZ: case Parser.VARU: case Parser.VARV: case Parser.VARR: case Parser.VARS: case Parser.VART: case Parser.VARN: case Parser.VARC: return getVar(top); case Parser.ABS: a = evaluateStack(s); return Math.abs(a); case Parser.SQRT: a = evaluateStack(s); return Math.sqrt(a); case Parser.NRT: a = evaluateStack(s); b = evaluateStack(s); return nrt(b,a); case Parser.SIN: a = evaluateStack(s); return Math.sin(a); case Parser.COS: a = evaluateStack(s); return Math.cos(a); case Parser.TAN: a = evaluateStack(s); return Math.tan(a); case Parser.SEC: a = evaluateStack(s); return 1/Math.cos(a); case Parser.CSC: a = evaluateStack(s); return 1/Math.sin(a); case Parser.COT: a = evaluateStack(s); return 1/Math.tan(a); case Parser.EXP: a = evaluateStack(s); return Math.exp(a); case Parser.LN: a = evaluateStack(s); return Math.log(a); case Parser.LOG: a = evaluateStack(s); return Math.log(a)/Math.log(10); case Parser.ASIN: a = evaluateStack(s); return Math.asin(a); case Parser.ACOS: a = evaluateStack(s); return Math.acos(a); case Parser.ATAN: a = evaluateStack(s); return Math.atan(a); case Parser.ASEC: a = evaluateStack(s); return Math.acos(1/a); case Parser.FACT: a = evaluateStack(s); return fact(a); case Parser.MAX: a = evaluateStack(s); b = evaluateStack(s); return Math.max(a,b); case Parser.MIN: a = evaluateStack(s); b = evaluateStack(s); return Math.min(a,b); case Parser.INT: a = evaluateStack(s); return Math.floor(a); case Parser.ALT: a = evaluateStack(s); if (((int) Math.floor(a)) % 2 == 0) return 1.0; else return -1.0; case Parser.COND: a = evaluateStack(s); b = evaluateStack(s); c = evaluateStack(s); return (c>0?b:a); case Parser.AND: c = evaluateStack(s); d = evaluateStack(s); return (((c>0) && (d>0))?1:0); case Parser.OR: c = evaluateStack(s); d = evaluateStack(s); return (((c>0) || (d>0))?1:0); case Parser.NOT: c = evaluateStack(s); return ((!(c>0))?1:0); case Parser.LESS: a = evaluateStack(s); b = evaluateStack(s); return ((b < a)?1:0); case Parser.GRT: a = evaluateStack(s); b = evaluateStack(s); return ((b > a)?1:0); case Parser.EQ: a = evaluateStack(s); b = evaluateStack(s); return ((b == a)?1:0); case Parser.ERROR: selectAll(); requestFocus(); errorDetected = true; return Double.NaN; default: return Double.NaN; } } public double evaluatef(double[] v) { if (errorDetected) return Double.NaN; else { setVars(v); if (dirty) { String expr = super.getInput(); if (expr.length() == 0) return Double.NaN; else evaluate(expr); dirty = false; } if (errorDetected) return Double.NaN; else return evaluateStack((Stack) parseReturn.clone()); } } public double evaluatef(double x, double y, double z, double w, double t) { double[] v = {x, y, z, w, t}; return evaluatef(v); } public double evaluatef(double x, double y, double z, double w) { double[] v = {x, y, z, w}; return evaluatef(v); } public double evaluatef(double x, double y, double z) { double[] v = {x, y, z}; return evaluatef(v); } public double evaluatef(double x, double y) { double[] v = {x, y}; return evaluatef(v); } public double evaluatef(double x) { double[] v = {x}; return evaluatef(v); } public double evaluatef() { double[] v = {}; return evaluatef(v); } private double fact(double x) { if (x<0 || x>57.0) return Double.NaN; // even long ints can't do more than 57! else return (double) ifact((long) Math.floor(x)); //use long instead of int } // longs added 4/16/03 and tested in seqser private long ifact(long n) { //use long instead of int if (n<0) return 0; else if (n==0) return 1; else return n*ifact(n-1); } private double nrt(double x, double y) { if (x<1) return Double.NaN; else return (double) inrt((int) Math.floor(x), y); } private double inrt(int n, double y) { if (n<1) return 0; else if (n==1) return y; else if ((y>0) || (n%2==0)) return Math.pow(y,1/((double) n)); else return -1*Math.pow(Math.abs(y),1/((double) n)); } public void setDirty() { dirty = true; errorDetected = false; } public boolean isKey(KeyEvent e) { boolean tmp = super.isKey(e); if (tmp) setDirty(); return tmp; } // overrides public void invalidVar() { errorDetected = true; selectAll(); requestFocus(); } // for use in getVar() if variable not recognized in that field protected abstract void setVars(double[] v); protected abstract double getVar(int id); }