jep-2.4.1-ext-1.1.1-gpl/0000755000000000000000000000000010615400352013000 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/0000755000000000000000000000000010615400352013567 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/0000755000000000000000000000000010615400352014356 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/0000755000000000000000000000000010615400352015331 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/0000755000000000000000000000000010615400352017752 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MatrixConsole.java0000644000000000000000000000333710615400352023412 0ustar rootroot/* @author rich * Created on 21-Mar-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.lsmp.djep.matrixJep.*; /** * @author Rich Morris * Created on 21-Mar-2005 */ public class MatrixConsole extends DJepConsole { private static final long serialVersionUID = -4768856862892634425L; public static void main(String[] args) { Console c = new MatrixConsole(); c.run(args); } public String getPrompt() { return "MatrixJep > "; } public void initialise() { j = new MatrixJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); ((MatrixJep) j).addStandardDiffRules(); } public void printHelp() { super.printHelp(); println("Dot product: [1,2,3].[4,5,6]"); println("Cross product: [1,2,3]^[4,5,6]"); println("Matrix Multiplication: [[1,2],[3,4]]*[[1,2],[3,4]]"); } public void printIntroText() { println("MatrixJep: advanced vector and matrix handling"); super.printStdHelp(); } public void processEquation(Node node) throws ParseException { MatrixJep mj = (MatrixJep) j; if(verbose) { print("Parsed:\t\t"); println(mj.toString(node)); } Node processed = mj.preprocess(node); if(verbose) { print("Processed:\t"); println(mj.toString(processed)); } Node simp = mj.simplify(processed); if(verbose) print("Simplified:\t"); println(mj.toString(simp)); Object val = mj.evaluate(simp); String s = mj.getPrintVisitor().formatValue(val); println("Value:\t\t"+s); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/package.html0000644000000000000000000000012610615400352022232 0ustar rootroot Various example applications illustrating the use of most features. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/PrintExample.java0000644000000000000000000000201610615400352023224 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; /** * @author Rich Morris * Created on 26-Feb-2004 */ public class PrintExample { public static void main(String[] args) { XJep j = new XJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); try { // parse expression Node node = j.parse("a*b+c*(d+sin(x))"); // print it j.println(node); // convert to string String str = j.toString(node); System.out.println("String is '"+str+"'"); j.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true); j.println(node); j.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,false); Node node2=j.parse("1*x^1+0"); j.println(node2); Node simp=j.simplify(node2); j.println(simp); } catch(ParseException e) { System.out.println("Parse error"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/XJepExample.java0000644000000000000000000000520210615400352022776 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; /** * Examples using differentation */ public class XJepExample { public static void main(String args[]) { /* initilisation */ XJep j = new XJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.setImplicitMul(true); try { Node node10 = j.parse("x=3"); Node node11 = j.preprocess(node10); System.out.println(j.evaluate(node11)); Node node12 = j.parse("y=x^2"); Node node13 = j.preprocess(node12); System.out.println(j.evaluate(node13)); Node node14 = j.parse("z=y+x"); Node node15 = j.simplify(j.preprocess(node14)); System.out.println(j.evaluate(node15)); // If a variable is changed then any expresion tree // it depends on needs to be re-evaluated to bring // values of other variables upto date j.setVarValue("x",new Double(4)); System.out.println(j.evaluate(node13)); System.out.println(j.evaluate(node15)); System.out.println("z: "+j.getVarValue("z").toString()); // the findVarValue method will automatically // re-calculate the value of variables specified by // equations if needed. However a lazy j.setVarValue("x",new Double(5)); System.out.println("j.setVarValue(\"x\",new Double(5));"); System.out.println("j.findVarValue(y): "+j.calcVarValue("y").toString()); System.out.println("j.findVarValue(z): "+j.calcVarValue("z").toString()); // if j.getSymbolTable().clearValues(); // is called before values of equations are set // then the values of intermediate equations // are automatically calculated, so you can jump // straight to the chase: no need to calculate // y explititly to find the value of z. j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(6)); System.out.println("j.setVarValue(\"x\",new Double(6));"); System.out.println("j.findVarValue(z): "+j.calcVarValue("z").toString()); j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(7)); System.out.println(j.evaluate(node15)); System.out.println("z: "+j.getVarValue("z").toString()); // now see if reentrancy works j.restartParser("x=1; // semi colon; in comment \ny=2; z=3;"); Node node21; while((node21 = j.continueParsing()) != null) j.println(node21); } catch(ParseException e) { System.out.println("Error with parsing"); } catch(Exception e) { System.out.println("Error with evaluation"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/XJepConsole.java0000644000000000000000000001132310615400352023006 0ustar rootroot/* @author rich * Created on 21-Mar-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import org.lsmp.djep.djep.DPrintVisitor; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; import java.text.NumberFormat; import java.util.Enumeration; /** * @author Rich Morris * Created on 21-Mar-2005 */ public class XJepConsole extends Console { private static final long serialVersionUID = -3239922790774093668L; protected NumberFormat format=null; protected boolean verbose = false; public static void main(String[] args) { Console c = new XJepConsole(); c.run(args); } public String getPrompt() { return "XJep > "; } public void initialise() { j = new XJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.setImplicitMul(true); } public void printHelp() { super.printHelp(); println("'setMaxLen 80'\tensures all lines and < 80 chars"); println("'setDP 3'\tonly prints 3 decimal places"); println("'setFullBrackets true'\tprints equations with full bracketing"); println("'setComplexI true'\tprint complex numbers in form x+iy"); println("'invalidate'\tmarks all variables as invalid, forcing reevaluation"); println("eg 'x=5','y=2*x' gives value 10, 'invalidate', 'x=6', 'y' gives value 12"); } public void printIntroText() { println("XJep Console"); super.printStdHelp(); } public void printOps() { println("Known operators"); Operator ops[] = j.getOperatorSet().getOperators(); int maxPrec = -1; for(int i=0;imaxPrec) maxPrec=((XOperator) ops[i]).getPrecedence(); for(int jj=-1;jj<=maxPrec;++jj) for(int i=0;i1 && words[1].equals("true")) xj.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true); else xj.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true); return false; } if(command.startsWith("setComplexI")) { String words[] = split(command); if(words.length>1 && words[1].equals("true")) xj.getPrintVisitor().setMode(PrintVisitor.COMPLEX_I,true); else xj.getPrintVisitor().setMode(PrintVisitor.COMPLEX_I,true); return false; } if(command.startsWith("verbose")) { String words[] = split(command); if(words.length<2) println("verbose should be on or off"); else if(words[1].equals("on")) verbose = true; else if(words[1].equals("off")) verbose = true; else println("verbose should be on or off"); return false; } return true; } public void processEquation(Node node) throws ParseException { XJep xj = (XJep) j; if(xj.getPrintVisitor().getMode(PrintVisitor.FULL_BRACKET)) { print("Node:\t"); xj.println(node); } Node processed = xj.preprocess(node); if(processed==null) return; if(xj.getPrintVisitor().getMode(PrintVisitor.FULL_BRACKET)) { print("Processed:\t"); xj.println(processed); } Node simp = xj.simplify(processed); print("Simplified:\t"); println(xj.toString(simp)); Object val = xj.evaluate(simp); String s = xj.getPrintVisitor().formatValue(val); println("Value:\t\t"+s); } public void printVars() { PrintVisitor pv = ((XJep) j).getPrintVisitor(); SymbolTable st = j.getSymbolTable(); pv.setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,!verbose); println("Variables:"); for(Enumeration loop = st.keys();loop.hasMoreElements();) { String s = (String) loop.nextElement(); XVariable var = (XVariable) st.getVar(s); println("\t"+var.toString(pv)); } pv.setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,true); } public void resetVars() { this.j.getSymbolTable().clearValues(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/GroupConsole.java0000644000000000000000000001224510615400352023240 0ustar rootroot/* @author rich * Created on 21-Mar-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.groups.*; import org.lsmp.djep.groupJep.interfaces.*; import org.lsmp.djep.groupJep.values.*; import org.nfunk.jep.type.Complex; import java.math.*; /** * Console application with handling for abstract groups * @author Rich Morris * Created on 21-Mar-2005 */ public class GroupConsole extends Console { private static final long serialVersionUID = -3097491397108691409L; public static void main(String args[]) { Console c = new GroupConsole(); c.run(args); } public String getPrompt() { return "GroupJep > "; } public void initialise() { j = new GroupJep(new Rationals()); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); j.addStandardConstants(); j.addStandardFunctions(); } public void initialise(Group g) { j = new GroupJep(g); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); j.addStandardConstants(); j.addStandardFunctions(); } public void printIntroText() { println("GroupJep: evaluation over abstract groups"); printGroup(); super.printStdHelp(); } public void printGroup() { println("Current Group: "+((GroupJep) j).getGroup().toString()); } public void processEquation(Node node) throws ParseException { Object value = j.evaluate(node); if(value instanceof HasComplexValueI) println(value.toString()+"=" +((HasComplexValueI) value).getComplexValue()); else println(value); } public boolean testSpecialCommands(String command) { GroupJep gj = (GroupJep) j; if(!super.testSpecialCommands(command)) return false; String words[] = split(command); if(words.length==0) return true; if(words[0].equals("group")) { if(words.length == 1) { } else if(words[1].equals("Z")) { initialise(new Integers()); } else if(words[1].equals("Q")) { initialise(new Rationals()); } else if(words[1].equals("R") && words.length == 3) { initialise(new BigReals( Integer.parseInt(words[2]), BigDecimal.ROUND_HALF_EVEN )); } else if(words[1].equals("R") && words.length == 2) { initialise(new Reals()); } else if(words[1].equals("P") && words.length == 3) { initialise(new PermutationGroup( Integer.parseInt(words[2])) ); } else if(words[1].equals("Zn") && words.length == 3) { initialise(new Zn(new BigInteger(words[2]))); } else if(words[1].equals("Qu")) { initialise(new Quaternions()); } else { println("invalid group spec "+command); return false; } printGroup(); return false; } if(words[0].equals("extend")) { RingI ring = (RingI) gj.getGroup(); if(words.length < 2) println("extend must have at least one argument"); else if(words.length == 2) /* Add a free variable */ { initialise(new ExtendedFreeGroup(ring, words[1])); } else /* extend by an algebraic number */ { int deg = words.length-3; Number coeffs[] = new Number[deg+1]; for(int i=0;i<=deg;++i) coeffs[i] = ring.valueOf(words[words.length-i-1]); Polynomial p1 = new Polynomial(ring,words[1],coeffs); initialise(new AlgebraicExtension(ring, p1)); } printGroup(); return false; } if(words[0].equals("setRootVal")) { String symbol = words[1]; Complex val = new Complex(Double.parseDouble(words[2]),Double.parseDouble(words[3])); GroupI g = gj.getGroup(); if(g instanceof FreeGroup) { boolean flag = ((FreeGroup) g).setRootVal(symbol,val); if(!flag) println("Failed to set root value, could not find symbol"); } return false; } return true; } public void printHelp() { super.printHelp(); println("'group'\tprints the current group"); println("'group G'\tchanges underlying group to G"); println("'group Z'\tintegers (arbitrary precision)"); println("'group Q'\trationals"); println("'group R'\treals, represented as Doubles."); println("'group R 3'\treals represented as BigDecimals with 3 decimal places"); println("'group P 3'\tpermutation group on three symbols"); println("\t[1,3,2]+[3,2,1] -> (3,1,2)"); println("'group Zn 5'\tintegers modulo 5"); println("'group Qu'\tQuarternions"); println("'extend x'\textends current group by adding symbol x, i.e. a free group"); println("\tsuch a group can be considered as the ring of polynomials"); println("\tsimplification happens automatically"); println("'extend t a b c'\talgebraic extensions generated by t"); println("\twhere t is a root of the polynomial a t^2 + b t +c=0"); println("\te.g group extend t 1 0 1 gives complex numbers, t^2+1=0."); println("\tfor these groups there is a natural mapping to complex numbers and complex result is also printed."); println("'setRootVal t re im'\tsets the value of free variable 't' in a free group to complex number re+i im"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/BlockStatments.java0000644000000000000000000000360310615400352023554 0ustar rootroot package org.lsmp.djepExamples; import org.nfunk.jep.*; /** * Example code illustrating how block control structures could be implemented. *

* Sample session *

* JEP > a=5
* 5.0
* JEP > a>4
* 1.0
* JEP > TrueBlock
* JEP > b=a^2
* 25.0
* JEP > c=a^3
* 125.0
* JEP > FalseBlock
* JEP > b=a^3
* JEP > c=a^2
* JEP > EndBlock
* JEP > b
* 25.0
*
*This code does not allow nesting on condition statements. **/ public class BlockStatments extends Console { private static final long serialVersionUID = 9035584745289937584L; /** Sets up three possible states */ private static final int NoState = 0; private static final int TrueState = 1; private static final int FalseState = 2; /** Indicates current state where in */ private int state = NoState; private int conditionValue = 0; /** * Catches macros which are not handled by JEP * * @return false - stops further processing of the line */ public boolean testSpecialCommands(String command) { if(command.equals("TrueBlock")) { state = TrueState; return false; } if(command.equals("FalseBlock")) { state = FalseState; return false; } if(command.equals("EndBlock")) { state = NoState; return false; } return true; } /** Evaluates a node, but only if the state corresponds to the conditionValue. * Also saves the result of evaluation in conditionValue for use in subsequent calls * * @param node Node representing expression * @throws ParseException if a Parse or evaluation error */ public void processEquation(Node node) throws ParseException { if(state==NoState || ( state==TrueState && conditionValue !=0 ) || ( state==FalseState && conditionValue ==0 ) ) { Object res = j.evaluate(node); println(res); if(state==NoState) conditionValue = ((Number) res).intValue(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/RpExample.java0000644000000000000000000000720410615400352022515 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.rpe.*; /** * Examples using vectors and matricies */ public class RpExample { static JEP j; public static void main(String args[]) { j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); // parse and evaluate each equation in turn doStuff("1*2*3+4*5*6+7*8*9"); doAll(new String[]{"x1=1","x2=2","x3=3","x4=4","x5=5","x6=6","x7=7","x8=8","x9=9", "x1*x2*x3+x4*x5*x6+x7*x8*x9"}); doAll(new String[]{"x=0.7","cos(x)^2+sin(x)^2"}); // vectors and matricies can be used with assignment // doStuff("x=[1,2,3]"); // Value: [1.0,2.0,3.0] // doStuff("x+x"); // Value: [2.0,4.0,6.0] // doStuff("x . x"); // Value: 14.0 // doStuff("x^x"); // Value: [0.0,0.0,0.0] // doStuff("y=[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] // doStuff("y * y"); // Value: [[7.0,10.0],[15.0,22.0]] // accessing the elements on an array or vector // doStuff("ele(x,2)"); // Value: 2.0 // doStuff("ele(y,[1,2])"); // Value: 2.0 // using differentation // doStuff("x=2"); // 2.0 // doStuff("y=[x^3,x^2,x]"); // [8.0,4.0,2.0] // doStuff("z=diff(y,x)"); // [12.0,4.0,1.0] // doStuff("diff([x^3,x^2,x],x)"); // System.out.println("dim(z) "+((MatrixVariableI) j.getVar("z")).getDimensions()); } public static void extendedPrint(RpCommandList list) throws ParseException { int num = list.getNumCommands(); for(int i=0;i * If you have some nice complicated examples, I'd love to * hear about them to see if we can tune things up. - rich */ public class RpSpeed { static JEP j; static int num_itts = 100000; // for normal use // static int num_itts = 1000; // for use with profiler public static void main(String args[]) { long t1 = System.currentTimeMillis(); initJep(); long t2 = System.currentTimeMillis(); System.out.println("Jep initialise "+(t2-t1)); doAll(new String[0],"1*2*3+4*5*6+7*8*9"); doAll(new String[]{"x1=1","x2=2","x3=3","x4=4","x5=5","x6=6","x7=7","x8=8","x9=9"}, "x1*x2*x3+x4*x5*x6+x7*x8*x9"); doAll(new String[]{"x=0.7"},"cos(x)^2+sin(x)^2"); } public static void doAll(String eqns[],String eqn2) { System.out.print("Testing speed for <"); for(int i=0;i and <"+eqn2+">"); doJep(eqns,eqn2); doRpe(eqns,eqn2); System.out.println(); } static void initJep() { j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); } static void doJep(String eqns[],String eqn2) { // System.out.println("vec init"+(t4-t3)); try { for(int i=0;i * Usage: java org.lsmp.djepExamples.Console [expression] * * If an argument is passed, it is interpreted as an expression * and evaluated. Otherwise, a prompt is printed, and the user can enter * expressions to be evaluated. * *

* This class has been designed to be sub classed to allow different * consol applications. * The methods *

* public void initialise()
* public void processEquation(Node node) throws Exception
* public boolean testSpecialCommands(String command)
* public void printPrompt()
* public void printIntroText()
* public void printHelp()
* 
* can all be overwritten. *

*

* Furthermore main should be overwritten. For example *

 
* 	public static void main(String args[]) {
*		Console c = new DJepConsole();
*		c.run(args);
*	}
*
*/ public class Console extends Applet implements KeyListener { private static final long serialVersionUID = 9035584745289937584L; /** Main JEP object */ protected JEP j; /** The input reader */ private BufferedReader br; /** Text area for user input in applets. */ protected TextArea ta = null; /** Constructor */ public Console() { br = new BufferedReader(new InputStreamReader(System.in)); } /** Applet initialization */ public void init() { initialise(); this.setLayout(new BorderLayout(1,1)); ta = new TextArea("",10,80,TextArea.SCROLLBARS_BOTH); ta.setEditable(true); ta.addKeyListener(this); add("Center",ta); printIntroText(); print(getPrompt()); } /** Creates a new Console object and calls run() */ public static void main(String args[]) { Console c = new Console(); c.run(args); } /** The main entry point with command line arguments */ public void run(String args[]) { initialise(); if (args.length>0) { for (int i=1; i *
  • Tests for exit, quit, and help.
  • *
  • Tests for any special commands used by sub classes. * {@link #testSpecialCommands(String)}
  • *
  • Parses the command.
  • *
  • Processes the node. {@link #processEquation(Node)}
  • *
  • Checks for errors. {@link #handleError(Exception)}
  • * * * @param command The line to be processed * @return false if un-recoverable error or 'quit' or 'exit' */ public boolean processCommand(String command) { if(command.equals("quit") || command.equals("exit")) return false; if(command.equals("help")) { printHelp(); return true; } if(command.equals("functions")) { printFuns(); return true; } if(command.equals("operators")) { printOps(); return true; } if(command.equals("variables")) { printVars(); return true; } if(!testSpecialCommands(command)) return true; try { Node n = j.parse(command); processEquation(n); } catch(Exception e) { return handleError(e); } return true; } /** sets up all the needed objects. */ public void initialise() { j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.setImplicitMul(true); } /** Performs the required operation on a node. * Typically evaluates the node and prints the value. * * @param node Node representing expression * @throws ParseException if a Parse or evaluation error */ public void processEquation(Node node) throws ParseException { Object res = j.evaluate(node); println(res); } /** * Get a command from the input. * @return null if an IO error or EOF occurs. */ protected String getCommand() { String s=null; if (br == null) return null; try { if ( (s = br.readLine()) == null) return null; } catch(IOException e) { println("IOError exiting"); return null; } return s; } /** Prints the prompt string. */ public String getPrompt() { return "JEP > "; } /** Prints a standard help message. * Type 'quit' or 'exit' to quit, 'help' for help. **/ public final void printStdHelp() { if(ta == null) println("Type 'quit' or 'exit' to quit, 'help' for help."); else println("Type 'help' for help."); } /** Print help message. */ public void printHelp() { printStdHelp(); println("'functions' lists defined functions"); println("'operators' lists defined operators"); println("'variables' lists variables and constants"); } /** Prints introductory text. */ public void printIntroText() { println("JEP Console."); printStdHelp(); } /** Prints a list of defined functions. */ public void printFuns() { FunctionTable ft = j.getFunctionTable(); println("Known functions:"); for(Enumeration loop = ft.keys();loop.hasMoreElements();) { String s = (String) loop.nextElement(); println("\t"+s); } } /** Prints a list of defined operators. */ public void printOps() { OperatorSet opset = j.getOperatorSet(); Operator ops[] = opset.getOperators(); println("Known operators:"); for(int i=0;iverbose on * This method can be used detected this input, * perform required actions and skip normal processing by returning true. * * @param command * @return true indicates normal processing should continue (default) false if the command is special and no further processing should be performed (parsing and evaluating) * @see #split(String) */ public boolean testSpecialCommands(String command) { return true; } /** * Handle an error in the parse and evaluate routines. * @param e * @return false if the error cannot be recovered and the program should exit */ public boolean handleError(Exception e) { if(e instanceof ParseException) { println("Parse Error: "+e.getMessage()); } else println("Error: "+e.getClass().getName()+" "+e.getMessage()); return true; } /** Splits a string on spaces. * * @param s the input string * @return an array of the tokens in the string */ public String[] split(String s) { StringTokenizer st = new StringTokenizer(s); int tokCount = st.countTokens(); String res[] = new String[tokCount]; int pos=0; while (st.hasMoreTokens()) { res[pos++]=st.nextToken(); } return res; } /** Prints a line of text no newline. * Subclasses should call this method rather than * System.out.print to allow for output to different places. * */ public void print(Object o) { String s=null; if(o == null) s = "null"; else s = o.toString(); if(ta != null) ta.append(s); else System.out.print(s); } /** Prints a line of text no newline. * Subclasses should call this method rather than * System.out.print to allow for output to different places. */ public void println(Object o) { String s=null; if(o == null) s = "null"; else s = o.toString(); if(ta != null) ta.append(s + "\n"); else System.out.println(s); } /** * Handles keyRelease events */ public void keyReleased(KeyEvent event) { int code = event.getKeyCode(); if(code == KeyEvent.VK_ENTER) { int cpos = ta.getCaretPosition(); String alltext = ta.getText(); String before = alltext.substring(0,cpos-1); int startOfLine = before.lastIndexOf('\n'); if(startOfLine > 0) before = before.substring(startOfLine+1); String prompt = getPrompt(); String line=null; if(before.startsWith(prompt)) { line = before.substring(prompt.length()); this.processCommand(line); } // System.out.println("line ("+line+")"); //if(!flag) this.exit(); this.print(getPrompt()); } } public void keyPressed(KeyEvent arg0) { } public void keyTyped(KeyEvent arg0) { } public String getAppletInfo() { return "Jep Console applet\n" + "R Morris Mar 2005\n" + "See http://www.singsurf.org/djep/"; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/DJepApplet.java0000644000000000000000000001000410615400352022600 0ustar rootroot/* * Created on 16-Jun-2003 by Rich webmaster@pfaf.org * www.comp.leeds.ac.uk/pfaf/lsmp * * Adapted from : */ /***************************************************************************** JEP - Java Math Expression Parser 2.24 December 30 2002 (c) Copyright 2002, Nathan Funk See LICENSE.txt for license information. *****************************************************************************/ /** * Console - JEP Example Applet * Copyright (c) 2000 Nathan Funk * * @author Nathan Funk */ package org.lsmp.djepExamples; import org.lsmp.djep.djep.*; import org.nfunk.jep.*; import java.applet.*; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; /** * This class implements a simple command line utility for evaluating * mathematical expressions. * * Usage: java org.lsmp.djep.DJepConsole [expression] * * If an argument is passed, it is interpreted as an expression * and evaluated. Otherwise, a prompt is printed, and the user can enter * expressions to be evaluated. To exit from the command prompt a 'q' must * be entered. * typing *
    diff(x^2,x)
    * will differentiate x^2 wrt 2. And *
    eval(x^2,x,3)
    * will calculate x^2 at x=3. * Expresions like *
    eval(diff(diff(x^2+y^3,x),y),x,3,y,4)
    * are also allowed. */ public class DJepApplet extends Applet implements ActionListener { /** * */ private static final long serialVersionUID = -2026659445630529741L; /** * */ /** Main JEP object */ DJep j; /** Input equation. */ TextField inputTF; /** variable to differentiate wrt respect to. */ TextField varTF; /** Output equation. */ TextField outputTF; /** Button to perform differentiation. */ Button but; /** Applet initialisation */ public void init() { initialise(); setLayout(new GridLayout(3,2)); inputTF = new TextField("sin(x^2)",50); outputTF = new TextField(50); outputTF.setEditable(false); varTF = new TextField("x",5); but = new Button("Calculate"); but.addActionListener(this); inputTF.addActionListener(this); Panel p1 = new Panel(); p1.add(new Label("Differentiate:")); p1.add(inputTF); add(p1); Panel p2 = new Panel(); p2.add(new Label("with respect to:")); p2.add(varTF); p2.add(but); add(p2); Panel p3 = new Panel(); p3.add(new Label("Result:")); p3.add(outputTF); add(p3); } /** Called when the Calculate button is pressed. * Firsts differentiates the expresion in inputTF wrt variable in * varTF, then simplifies it and puts results into outputTF. */ public void actionPerformed(ActionEvent e) { String command = inputTF.getText(); j.parseExpression(command); if (j.hasError()) { outputTF.setText(j.getErrorInfo()); } else { // expression is OK, get the value try { Node diff = j.differentiate(j.getTopNode(),varTF.getText()); Node simp = j.simplify(diff); if (j.hasError()) { outputTF.setText(j.getErrorInfo()); } else outputTF.setText(j.toString(simp)); } catch(ParseException e1) { outputTF.setText("Parse Error: "+e1.getMessage()); } catch(IllegalArgumentException e2) { outputTF.setText(e2.getMessage()); } catch(Exception e3) { outputTF.setText(e3.getMessage()); } // did error occur during evaluation? } } /** Creates a new Console object and calls run() */ public static void main(String args[]) { DJepApplet app = new DJepApplet(); app.init(); Frame mainFrame = new Frame("Wallpaper patterns"); mainFrame.setBounds(0,0,200,200); mainFrame.add(app); mainFrame.show(); } /** sets up all the needed objects. */ public void initialise() { j = new DJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.setImplicitMul(true); j.addStandardDiffRules(); //j.setTraverse(true); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/SJepConsole.java0000644000000000000000000000254410615400352023006 0ustar rootroot/* @author rich * Created on 22-Mar-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.lsmp.djep.xjep.XJep; import org.lsmp.djep.sjep.PolynomialCreator; /** * @author Rich Morris * Created on 22-Mar-2005 */ public class SJepConsole extends DJepConsole { private static final long serialVersionUID = -2796652887843007314L; PolynomialCreator pc = null; public static void main(String[] args) { Console c = new SJepConsole(); c.run(args); } public String getPrompt() { return "SJep > "; } public void initialise() { super.initialise(); pc = new PolynomialCreator((XJep) j); } public void printIntroText() { println("SJep: advanced simplification/expansion"); } public void processEquation(Node node) throws ParseException { XJep xj = (XJep) j; Node pre = xj.preprocess(node); Node proc = xj.simplify(pre); print("Old simp:\t"); println(xj.toString(proc)); Node simp = pc.simplify(proc); print("New simp:\t"); println(xj.toString(simp)); Node expand = pc.expand(proc); print("Expanded:\t"); println(xj.toString(expand)); Object val = xj.evaluate(simp); String s = xj.getPrintVisitor().formatValue(val); println("Value:\t\t"+s); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/AssignmentExample.java0000644000000000000000000000272410615400352024246 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; /** * Examples using assignment */ public class AssignmentExample { public static void main(String args[]) { // standard initilisation JEP j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); // swith assignment facilities on j.setAllowAssignment(true); // parse assignment equations j.parseExpression("x=3"); // evaluate it - no need to save the value returned j.getValueAsObject(); // parse a second equation j.parseExpression("y=2"); j.getValueAsObject(); // an equation involving above variables j.parseExpression("x^y"); Object val3 = j.getValueAsObject(); System.out.println("Value is "+val3); try { // Alternative syntax Node node1 = j.parse("z=i*pi"); j.evaluate(node1); Node node2 = j.parse("exp(z)"); Object val2 = j.evaluate(node2); System.out.println("Value: "+val2); // getting and setting variable values Node node3 = j.parse("z=x^y"); j.setVarValue("x",new Double(2)); j.setVarValue("y",new Double(3)); j.evaluate(node3); System.out.println(j.getVarValue("z")); // prints 8 } catch(ParseException e) { System.out.println("Error with parsing"); } catch(Exception e) { System.out.println("Error with evaluation"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/VectorConsole.java0000644000000000000000000000304710615400352023406 0ustar rootroot/* @author rich * Created on 21-Mar-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import org.lsmp.djep.vectorJep.*; /** * @author Rich Morris * Created on 21-Mar-2005 */ public class VectorConsole extends Console { private static final long serialVersionUID = -2335406063822614650L; public static void main(String[] args) { Console c = new VectorConsole(); c.run(args); } public String getPrompt() { return "VectorJep > "; } public void initialise() { j = new VectorJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); } public void printHelp() { super.printHelp(); println("Dot product: [1,2,3].[4,5,6]"); println("Cross product: [1,2,3]^^[4,5,6]"); println("Matrix Multiplication: [[1,2],[3,4]]*[[1,2],[3,4]]"); println("setEleMult: sets element by element mode for multiplication"); println("setMatrixMult: sets matrix multiplication"); } public void printIntroText() { println("VectorJep: matrix and vector calculations in Jep"); println("eg. [1,2,3].[4,5,6] [[1,2],[3,4]]*[1,0]"); printStdHelp(); } public boolean testSpecialCommands(String command) { if(command.equals("setEleMult")) { ((VectorJep)j).setElementMultiply(true); return false; } if(command.equals("setMatrixMult")) { ((VectorJep)j).setElementMultiply(true); return false; } return true; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/VectorPrint.java0000644000000000000000000000360410615400352023077 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.xjep.*; /** * Examples using vectors and matrices */ public class VectorPrint { static XJep j; // static PrintVisitor pv; public static void main(String args[]) { j = new XJep(new VectorJep()); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); // parse and evaluate each equation in turn doStuff("3^2"); doStuff("[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("[1,2,3].[4,5,6]"); // Value: 32.0 doStuff("[1,2,3]^^[4,5,6]"); // Value: [-3.0,6.0,-3.0] doStuff("[1,2,3]+[4,5,6]"); // Value: [5.0,7.0,9.0] doStuff("[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("[[1,2],[3,4]]*[1,0]"); // Value: [1.0,3.0] doStuff("[1,0]*[[1,2],[3,4]]"); // Value: [1.0,2.0] doStuff("x=[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("x+x"); // Value: [2.0,4.0,6.0] doStuff("x . x"); // Value: 14.0 doStuff("x^^x"); // Value: [0.0,0.0,0.0] doStuff("ele(x,2)"); // Value: 2.0 doStuff("y=[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("y * y"); // Value: [[7.0,10.0],[15.0,22.0]] doStuff("ele(y,[1,2])"); // Value: 2.0 } public static void doStuff(String str) { try { Node node = j.parse(str); Object value = j.evaluate(node); j.print(node); System.out.println("\tvalue " + value.toString()); } catch(ParseException e) { System.out.println("Parse error "+e.getMessage()); } catch(Exception e) { System.out.println("evaluation error "+e.getMessage()); e.printStackTrace(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MRpSurfExample.java0000644000000000000000000001277610615400352023504 0ustar rootroot/* @author rich * Created on 01-Apr-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import java.util.Enumeration; import java.util.Vector; import org.lsmp.djep.matrixJep.MatrixJep; import org.lsmp.djep.matrixJep.MatrixVariableI; import org.lsmp.djep.mrpe.MRpCommandList; import org.lsmp.djep.mrpe.MRpEval; import org.lsmp.djep.mrpe.MRpRes; import org.lsmp.djep.vectorJep.VectorJep; import org.lsmp.djep.vectorJep.values.MVector; import org.lsmp.djep.vectorJep.values.Scaler; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.nfunk.jep.Variable; /** * @author Rich Morris * Created on 01-Apr-2005 */ public class MRpSurfExample { MatrixJep mj; VectorJep vj; MRpEval mrpe=null; MRpCommandList allCommands[]; Node allEqns[]; Node vecEqns[]; // LVars psVars[]; MatrixVariableI xVar,yVar; Variable xVVar,yVVar; int xref,yref; double xmin = -1.0,xmax = 1.0,ymin=1.0,ymax=1.0; int xsteps = 1000,ysteps = 1000; public static void main(String args[]) { timePrint("\tStart"); MRpSurfExample surf = new MRpSurfExample(); timePrint("\tDone init"); try { surf.equationChanged("th=pi*x;phi=pi*y;f=[cos(th) cos(phi),sin(th) cos(phi),sin(phi)];"); surf.vecEquationChanged(new String[]{"th=pi*x;","phi=pi*y;","[cos(th) cos(phi),sin(th) cos(phi),sin(phi)];"}); timePrint("\tDone parse"); surf.calcMRPE(); surf.mrpe.cleanUp(); timePrint("\tDone mrpe"); surf.calcMJ(); timePrint("\tDone MJ"); surf.calcVJ(); timePrint("\tDone VJ"); } catch(Exception e) { System.out.println(e.getClass().getName()+": "+e.getMessage()); } } static long oldTime = 0; public static void timePrint(String msg) { long time = System.currentTimeMillis(); long timediff = time-oldTime; oldTime = time; System.out.println(""+timediff+"\t"+msg); } public MRpSurfExample() { vj = new VectorJep(); vj.setAllowAssignment(true); vj.setAllowUndeclared(true); vj.setImplicitMul(true); vj.addComplex(); vj.addStandardConstants(); vj.addStandardFunctions(); mj = new MatrixJep(); mj.setAllowAssignment(true); mj.setAllowUndeclared(true); mj.setImplicitMul(true); mj.addComplex(); mj.addStandardConstants(); mj.addStandardFunctions(); mj.addStandardDiffRules(); mrpe = new MRpEval(mj); } public void equationChanged(String text) { mj.restartParser(text); try { Vector coms = new Vector(); Vector eqns = new Vector(); Node n; while((n = mj.continueParsing())!=null) { Node n2 = mj.preprocess(n); MRpCommandList com = mrpe.compile(n2); coms.add(com); eqns.add(n2); } int i=0; allCommands = new MRpCommandList[coms.size()]; for(Enumeration en=coms.elements();en.hasMoreElements();++i) allCommands[i] = (MRpCommandList) en.nextElement(); i=0; allEqns = new Node[eqns.size()]; for(Enumeration en=eqns.elements();en.hasMoreElements();++i) allEqns[i] = (Node) en.nextElement(); xVar = (MatrixVariableI) mj.getVar("x"); yVar = (MatrixVariableI) mj.getVar("y"); xref = mrpe.getVarRef(xVar); yref = mrpe.getVarRef(yVar); } catch(ParseException e) {System.out.println(e.getMessage());} } public void vecEquationChanged(String lines[]) { try { vecEqns = new Node[lines.length]; for(int i=0;i["+topRes[0]+","+topRes[1]+","+topRes[2]+"]"); } } System.out.println("res "+topRes[0]+","+topRes[1]+","+topRes[2]); } public void calcMJ() throws ParseException { Object topRes[]=null; Scaler xVal = (Scaler) xVar.getMValue(); Scaler yVal = (Scaler) yVar.getMValue(); xVar.setValidValue(true); yVar.setValidValue(true); for(int i=0;i<=xsteps;++i) { double x = xmin + ((xmax - xmin)*i)/xsteps; xVal.setEle(0,new Double(x)); for(int j=0;j<=ysteps;++j) { double y = ymin + ((ymax - ymin)*j)/ysteps; yVal.setEle(0,new Double(y)); Object res=null; for(int k=0;k["+topRes[0]+","+topRes[1]+","+topRes[2]+"]"); } } System.out.println("res "+topRes[0]+","+topRes[1]+","+topRes[2]); } public void calcVJ() throws ParseException,Exception { Object topRes[]=null; for(int i=0;i<=xsteps;++i) { double x = xmin + ((xmax - xmin)*i)/xsteps; xVVar.setValue(new Double(x)); for(int j=0;j<=ysteps;++j) { double y = ymin + ((ymax - ymin)*j)/ysteps; yVVar.setValue(new Double(y)); Object res=null; for(int k=0;k["+topRes[0]+","+topRes[1]+","+topRes[2]+"]"); } } System.out.println("res "+topRes[0]+","+topRes[1]+","+topRes[2]); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/DiffExample.java0000644000000000000000000001030110615400352022774 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; import org.lsmp.djep.djep.*; /** * Examples using differentation */ public class DiffExample { public static void main(String args[]) { /* initilisation */ DJep j = new DJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.setImplicitMul(true); j.addStandardDiffRules(); try { // parse the string Node node = j.parse("sin(x^2)"); // differentiate wrt x Node diff = j.differentiate(node,"x"); // print j.println(diff); // simplify Node simp = j.simplify(diff); // print j.println(simp); // This time the differentation is specified by // the diff(eqn,var) function Node node2 = j.parse("diff(cos(x^3),x)"); // To actually make diff do its work the // equation needs to be preprocessed Node processed = j.preprocess(node2); j.println(processed); // finally simplify Node simp2 = j.simplify(processed); j.println(simp2); // Now combine assignment and differentation Node node3 = j.parse("y=x^5"); j.preprocess(node3); Node node4 = j.parse("diff(y^2+x,x)"); Node simp3 = j.simplify(j.preprocess(node4)); j.println(simp3); // default printing will be 2*y*5*x^4+1 PrintVisitor pv = j.getPrintVisitor(); pv.setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,false); j.println(simp3); // no expansion will be 2*y*dy/dx+1 pv.setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,true); pv.setMode(DPrintVisitor.PRINT_VARIABLE_EQNS,true); j.println(simp3); // full expansion: 2*x^5*5*x^4+1 pv.setMode(DPrintVisitor.PRINT_VARIABLE_EQNS,false); // Node node5 = j.parse("y"); // j.println(node5); // ((DPrintVisitor)j.getPrintVisitor()).setPrintVariableEquations(true); // j.println(node5); j.getSymbolTable().setVarValue("x",new Double(5)); System.out.println(j.evaluate(simp3)); j.evaluate(node3); System.out.println(j.getSymbolTable().getVar("y").getValue()); j.getSymbolTable().setVarValue("x",new Double(0)); System.out.println(j.evaluate(simp)); Node node10 = j.parse("x=3"); Node node11 = j.preprocess(node10); System.out.println(j.evaluate(node11)); Node node12 = j.parse("y=x^2"); Node node13 = j.preprocess(node12); System.out.println(j.evaluate(node13)); Node node14 = j.parse("z=diff(y,x)"); Node node15 = j.simplify(j.preprocess(node14)); System.out.println(j.evaluate(node15)); // If a variable is changed then any expresion tree // it depends on needs to be re-evaluated to bring // values of other variables upto date j.setVarValue("x",new Double(4)); System.out.println(j.evaluate(node13)); System.out.println(j.evaluate(node15)); System.out.println("z: "+j.getVarValue("z").toString()); // the findVarValue method will automatically // re-calculate the value of variables specified by // equations if needed. However a lazy j.setVarValue("x",new Double(5)); System.out.println("j.setVarValue(\"x\",new Double(5));"); System.out.println("j.findVarValue(y): "+j.calcVarValue("y").toString()); System.out.println("j.findVarValue(z): "+j.calcVarValue("z").toString()); // if j.getSymbolTable().clearValues(); // is called before values of equations are set // then the values of intermediate equations // are automatically calculated, so you can jump // straight to the chase: no need to calculate // y explititly to find the value of z. j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(6)); System.out.println("j.setVarValue(\"x\",new Double(6));"); System.out.println("j.findVarValue(z): "+j.calcVarValue("z").toString()); j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(7)); System.out.println(j.evaluate(node15)); System.out.println("z: "+j.getVarValue("z").toString()); } catch(ParseException e) { System.out.println("Error with parsing"); } catch(Exception e) { System.out.println("Error with evaluation"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MatrixExample.java0000644000000000000000000000467710615400352023413 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; /** * Examples using vectors and matricies */ public class MatrixExample { static MatrixJep j; public static void main(String args[]) { j = new MatrixJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); // parse and evaluate each equation in turn doStuff("[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("[1,2,3].[4,5,6]"); // Value: 32.0 doStuff("[1,2,3]^[4,5,6]"); // Value: [-3.0,6.0,-3.0] doStuff("[1,2,3]+[4,5,6]"); // Value: [5.0,7.0,9.0] doStuff("[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("[[1,2],[3,4]]*[1,0]"); // Value: [1.0,3.0] doStuff("[1,0]*[[1,2],[3,4]]"); // Value: [1.0,2.0] doStuff("[[1,2],[3,4]]*[[1,2],[3,4]]"); // Value: [[7.0,10.0],[15.0,22.0]] // vectors and matricies can be used with assignment doStuff("x=[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("x+x"); // Value: [2.0,4.0,6.0] doStuff("x . x"); // Value: 14.0 doStuff("x^x"); // Value: [0.0,0.0,0.0] doStuff("y=[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("y * y"); // Value: [[7.0,10.0],[15.0,22.0]] // accessing the elements on an array or vector doStuff("ele(x,2)"); // Value: 2.0 doStuff("ele(y,[1,2])"); // Value: 2.0 // using differentation doStuff("x=2"); // 2.0 doStuff("y=[x^3,x^2,x]"); // [8.0,4.0,2.0] doStuff("z=diff(y,x)"); // [12.0,4.0,1.0] doStuff("diff([x^3,x^2,x],x)"); System.out.println("dim(z) "+((MatrixVariableI) j.getVar("z")).getDimensions()); } public static void doStuff(String str) { try { Node node = j.parse(str); Node proc = j.preprocess(node); Node simp = j.simplify(proc); Object value = j.evaluate(simp); //j.println(proc); j.print(simp); System.out.print("\t dim "+((MatrixNodeI) simp).getDim()); System.out.println("\tvalue " + value.toString()); } catch(ParseException e) { System.out.println("Parse error "+e.getMessage()); } catch(Exception e) { System.out.println("evaluation error "+e.getMessage()); e.printStackTrace(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MRpDiffExample.java0000644000000000000000000001154710615400352023430 0ustar rootroot/* @author rich * Created on 01-Apr-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepExamples; import java.util.Enumeration; import java.util.Vector; import org.lsmp.djep.djep.DPrintVisitor; import org.lsmp.djep.matrixJep.MatrixJep; import org.lsmp.djep.matrixJep.MatrixVariableI; import org.lsmp.djep.mrpe.MRpCommandList; import org.lsmp.djep.mrpe.MRpEval; import org.lsmp.djep.mrpe.MRpRes; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /** * An example of using MRpEval with differentation. * * @author Rich Morris * Created on 01-Apr-2005 */ public class MRpDiffExample { MatrixJep mj; MRpEval mrpe=null; MRpCommandList allCommands[]; int xref,yref; double xmin = -1.0,xmax = 1.0,ymin=1.0,ymax=1.0; int xsteps = 100,ysteps = 100; public static void main(String args[]) { timePrint("\tStart"); MRpDiffExample surf = new MRpDiffExample(); timePrint("\tDone init"); try { surf.compile("th=pi*x;phi=pi*y;f=[cos(th) cos(phi),sin(th) cos(phi),sin(phi)];dx=diff(f,x);dy=diff(f,y);dx^dy;"); timePrint("\tDone parse"); surf.calcMRPE(); surf.mrpe.cleanUp(); timePrint("\tDone mrpe"); } catch(Exception e) { System.out.println(e.getClass().getName()+": "+e.getMessage()); } } static long oldTime = 0; public static void timePrint(String msg) { long time = System.currentTimeMillis(); long timediff = time-oldTime; oldTime = time; System.out.println(""+timediff+"\t"+msg); } public MRpDiffExample() { mj = new MatrixJep(); mj.setAllowAssignment(true); mj.setAllowUndeclared(true); mj.setImplicitMul(true); mj.addComplex(); mj.addStandardConstants(); mj.addStandardFunctions(); mj.addStandardDiffRules(); mrpe = new MRpEval(mj); //mj.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true); mj.getPrintVisitor().setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,false); } /** * Compile a sequence of equations. * * @param text */ public void compile(String text) { mj.restartParser(text); try { Vector eqns = new Vector(); Node n; while((n = mj.continueParsing())!=null) { Node n2 = mj.preprocess(n); Node n3 = mj.simplify(n2); eqns.add(n3); } // gets the top equation Node topEqn = (Node) eqns.get(eqns.size()-1); // differentiate it Node dx = mj.differentiate(topEqn,"x"); Node dy = mj.differentiate(topEqn,"y"); // create a list of all variables needed to // successfully evaluate topEqn, dx, and dy Vector deps = mj.recursiveGetVarsInEquation(topEqn,new Vector()); deps = mj.recursiveGetVarsInEquation(dx,deps); deps = mj.recursiveGetVarsInEquation(dy,deps); // Compile all equations needed for successful evaluation // of top, dx, dy Vector coms = new Vector(); for(Enumeration en=deps.elements();en.hasMoreElements();) { MatrixVariableI var = (MatrixVariableI) en.nextElement(); if(var.hasEquation()) { Node eqn = var.getEquation(); System.out.print("Compiling "+var.getName()+"="); mj.println(eqn); coms.add(mrpe.compile(var,eqn)); } else { // The variable has no equation System.out.println("Ignoring "+var.getName()); } } // compile the top equation and derivatives System.out.print("Compiling "); mj.println(topEqn); coms.add(mrpe.compile(topEqn)); System.out.print("Compiling "); mj.println(dx); coms.add(mrpe.compile(dx)); System.out.print("Compiling "); mj.println(dy); coms.add(mrpe.compile(dy)); // put into any array int i=0; allCommands = new MRpCommandList[coms.size()]; for(Enumeration en=coms.elements();en.hasMoreElements();++i) allCommands[i] = (MRpCommandList) en.nextElement(); // finds the references for two variables xref = mrpe.getVarRef(mj.getVar("x")); yref = mrpe.getVarRef(mj.getVar("y")); } catch(ParseException e) {e.getMessage();} } public void calcMRPE() { double topRes[]=null,dxRes[]=null,dyRes[]=null; for(int i=0;i<=xsteps;++i) { double x = xmin + ((xmax - xmin)*i)/xsteps; mrpe.setVarValue(xref,x); for(int j=0;j<=ysteps;++j) { double y = ymin + ((ymax - ymin)*j)/ysteps; mrpe.setVarValue(yref,y); MRpRes res=null; for(int k=0;khttp://math.nist.gov/javanumerics/jama/ */ public class JamaConsole extends VectorConsole { private static final long serialVersionUID = -4256036388099114905L; public static void main(String[] args) { Console c = new JamaConsole(); c.run(args); } public void initialise() { super.initialise(); JamaUtil.addStandardFunctions(j); } public void printHelp() { super.printHelp(); println("inverse([[1,2],[3,4]])"); println("rank([[1,2],[3,4]])"); println("z = solve(x,y) solves x*z = y"); } public void printIntroText() { super.printIntroText(); println("Adds Jama matrix ops: inverse, solve, rank"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MRpExample.java0000644000000000000000000000674510615400352022643 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.mrpe.MRpCommandList; import org.lsmp.djep.mrpe.MRpEval; import org.lsmp.djep.mrpe.MRpRes; import org.lsmp.djep.vectorJep.values.*; /** * Examples using fast reverse polish calculator with vectors and matrices */ public class MRpExample { static MatrixJep mj; static MRpEval rpe; public static void main(String args[]) { mj = new MatrixJep(); mj.addStandardConstants(); mj.addStandardFunctions(); mj.addComplex(); mj.setAllowUndeclared(true); mj.setImplicitMul(true); mj.setAllowAssignment(true); rpe = new MRpEval(mj); // parse and evaluate each equation in turn doStuff("[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("[1,2,3].[4,5,6]"); // Value: 32.0 doStuff("[1,2,3]^[4,5,6]"); // Value: [-3.0,6.0,-3.0] doStuff("[1,2,3]+[4,5,6]"); // Value: [5.0,7.0,9.0] doStuff("[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("[[1,2],[3,4]]*[1,0]"); // Value: [1.0,3.0] doStuff("[1,0]*[[1,2],[3,4]]"); // Value: [1.0,2.0] doStuff("[[1,2],[3,4]]*[[1,2],[3,4]]"); // Value: [[7.0,10.0],[15.0,22.0]] // vectors and matrices can be used with assignment doStuff("x=[1,2,3]"); // Value: [1.0,2.0,3.0] doStuff("x+x"); // Value: [2.0,4.0,6.0] doStuff("x . x"); // Value: 14.0 doStuff("x^x"); // Value: [0.0,0.0,0.0] doStuff("y=[[1,2],[3,4]]"); // Value: [[1.0,2.0],[3.0,4.0]] doStuff("y * y"); // Value: [[7.0,10.0],[15.0,22.0]] // accessing the elements on an array or vector // doStuff("ele(x,2)"); // Value: 2.0 // doStuff("ele(y,[1,2])"); // Value: 2.0 // using differentation // doStuff("x=2"); // 2.0 // doStuff("y=[x^3,x^2,x]"); // [8.0,4.0,2.0] // doStuff("z=diff(y,x)"); // [12.0,4.0,1.0] // doStuff("diff([x^3,x^2,x],x)"); // System.out.println("dim(z) "+((MatrixVariableI) mj.getVar("z")).getDimensions()); } public static void doStuff(String str) { try { Node node = mj.parse(str); Node proc = mj.preprocess(node); Node simp = mj.simplify(proc); MRpCommandList list = rpe.compile(simp); MRpRes res = rpe.evaluate(list); mj.print(node); // conversion to String System.out.println("\nres " + res.toString()); // conversion to MatrixValueI MatrixValueI mat = res.toVecMat(); System.out.println("matrix " + mat.toString()); // conversion to array if(res.getDims().is1D()) { double vecArray[] = (double []) res.toArray(); System.out.print("["); for(int i=0;i "; } public void processEquation(Node node) throws ParseException { DJep dj = (DJep) this.j; if(verbose) { print("Parsed:\t\t"); println(dj.toString(node)); } Node processed = dj.preprocess(node); if(verbose) { print("Processed:\t"); println(dj.toString(processed)); } Node simp = dj.simplify(processed); if(verbose) print("Simplified:\t"); println(dj.toString(simp)); if(verbose) { print("Full Brackets, no variable expansion:\n\t\t"); dj.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true); dj.getPrintVisitor().setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,false); println(dj.toString(simp)); dj.getPrintVisitor().setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,true); dj.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,false); } Object val = dj.evaluate(simp); String s = dj.getPrintVisitor().formatValue(val); println("Value:\t\t"+s); } /** Creates a new Console object and calls run() */ public static void main(String args[]) { Console c = new DJepConsole(); c.run(args); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepExamples/MRpSpeed.java0000644000000000000000000002202510615400352022275 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djepExamples; import org.nfunk.jep.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.mrpe.MRpCommandList; import org.lsmp.djep.mrpe.MRpEval; import org.lsmp.djep.vectorJep.*; /** * Compares the speed of matrix operations * using mrpe, vectorJep and matrixJep. */ public class MRpSpeed { static MatrixJep mj; static VectorJep vj; static int num_itts = 100000; // for normal use // static int num_itts = 1000; // for use with profiler public static void main(String args[]) { if(args.length>0) num_itts = Integer.parseInt(args[0]); System.out.println("VectorJep, MatrixJep, MRPEval Speed comparison"); System.out.println("Number of iterations: "+num_itts); long t1 = System.currentTimeMillis(); initVec(); long t2 = System.currentTimeMillis(); System.out.println("Vec initialise "+(t2-t1)); initMat(); long t3 = System.currentTimeMillis(); System.out.println("Mat initialise "+(t3-t2)); doRawAdd(); doObjAdd(); doRawMult(); doObjMult(); doAll(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*y"); doAll(new String[]{},"y=[[1,2,3],[4,5,6],[7,8,9]]"); doAll(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"z=y*y"); doAll(new String[0],"[[1,2,3],[4,5,6],[7,8,9]]*[[1,2,3],[4,5,6],[7,8,9]]"); doAll(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y+y"); doAll(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y-y"); doAll(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*y+y"); doAll(new String[]{"x=[1,2,3]","y=[[1,2,3],[4,5,6],[7,8,9]]"},"x*y"); doAll(new String[]{"x=[1,2,3]","y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*x"); doAll(new String[]{"y=[1,2,3]"},"y+y"); doAll(new String[]{"y=[1,2,3]"},"y . y"); doAll(new String[]{"y=[1,2,3]"},"y^^y"); doAll(new String[]{"y=[[1,2],[3,4]]"},"y*y"); doAll(new String[]{"y=[[1,2],[3,4]]"},"y+y"); doAll(new String[]{"y=[[1,2],[3,4]]"},"y-y"); doAll(new String[]{"y=[[1,2],[3,4]]"},"y*y+y"); doAll(new String[]{"x=[1,2]","y=[[1,2],[3,4]]"},"x*y"); doAll(new String[]{"x=[1,2]","y=[[1,2],[3,4]]"},"y*x"); doAll(new String[0],"1*2*3+4*5*6+7*8*9"); doAll(new String[]{"x1=1","x2=2","x3=3","x4=4","x5=5","x6=6","x7=7","x8=8","x9=9"}, "x1*x2*x3+x4*x5*x6+x7*x8*x9"); doAll(new String[]{"y=[1,2,3,4,5]"},"y+y"); doAll(new String[]{"y=[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]]"},"y*y"); doAll(new String[]{"x=0.7"},"cos(x)^2+sin(x)^2"); for(int scale=2;scale<=6;++scale) { StringBuffer sb = new StringBuffer("y=["); int k=1; for(int i=0;i0) sb.append(','); sb.append('['); for(int j=0;j0) sb.append(','); sb.append(k); ++k; } sb.append(']'); } sb.append(']'); doAll(new String[]{sb.toString()},"y*y"); } } public static void doAll(String eqns[],String eqn2) { System.out.println("Testing speed for <"+eqn2+"> Where "); for(int i=0;i and <"+eqn2+">"); doVec(eqn1,eqn2); doMat(eqn1,eqn2); } static void initVec() { vj = new VectorJep(); vj.addStandardConstants(); vj.addStandardFunctions(); vj.addComplex(); vj.setAllowUndeclared(true); vj.setImplicitMul(true); vj.setAllowAssignment(true); } static void doVec(String eqn1,String eqn2) { // System.out.println("vec init"+(t4-t3)); try { Node node1 = vj.parse(eqn1); vj.evaluate(node1); Node node = vj.parse(eqn2); long t1 = System.currentTimeMillis(); // System.out.println("vec parse"+(t1-t4)); for(int i=0;i Functions and operators for working with vectors and matricies.

    In the VectorJep package vectors are handled if a different fashion to standard Jep. The VList function converts a list of values [1,2,3] into one of the MatrixValueI types: Scaler, MVector, Matrix or Tensor.

    Functions which work with Vectors in this package should handle the above types.

    Furthermore if the MatrixJep package is going to be used, then classes should implement one of the interfaces either UnaryOperatorI BinaryOperatorI or NaryOperatorI interfaces. These use a more efficient method for evaluation through the calcValue methods, where an object to hold the results is provided. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/MAdd.java0000644000000000000000000000532210615400352023513 0ustar rootroot/* @author rich * Created on 27-Jul-2003 */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.*; import org.nfunk.jep.function.Add; /** * An extension of the Add command to allow it to add MVector's and Matrix's. * @author Rich Morris * Created on 27-Jul-2003 */ public class MAdd extends Add implements BinaryOperatorI { public Dimensions calcDim(Dimensions ldim,Dimensions rdim) { if(ldim.equals(rdim)) return ldim; return null; } /** calculates the value. * @param res - results will be stored in this object * @param lhs - lhs value * @param rhs - rhs value * @return res */ public MatrixValueI calcValue(MatrixValueI res,MatrixValueI lhs,MatrixValueI rhs) throws ParseException { int len = res.getNumEles(); for(int i=0;i matrix. * * @author Rich Morris * Created on 27-Jul-2003 * TODO add handeling of tensors * @since 2.3.2 Improved error reporting */ public class MMultiply extends Multiply implements BinaryOperatorI { protected Add add = new Add(); protected Subtract sub = new Subtract(); public MMultiply() { //add = (Add) Operator.OP_ADD.getPFMC(); //sub = (Subtract) Operator.OP_SUBTRACT.getPFMC(); numberOfParameters = 2; } /** * need to redo this as the standard jep version assumes commutivity. */ public void run(Stack stack) throws ParseException { checkStack(stack); // check the stack //if(this.curNumberOfParameters!=2) throw new ParseException("Multiply: should have two children its got "+stack.size()); Object param2 = stack.pop(); Object param1 = stack.pop(); Object product = mul(param1, param2); stack.push(product); return; } /** * Multiply two objects. */ public Object mul(Object param1, Object param2) throws ParseException { if(param1 instanceof MatrixValueI && param2 instanceof MatrixValueI) { return mul((MatrixValueI) param1,(MatrixValueI) param2); } else if(param1 instanceof MatrixValueI) { MatrixValueI l = (MatrixValueI) param1; MatrixValueI res = Tensor.getInstance(l.getDim()); for(int i=0;i Vector return l; case 1: // Vector * Vector -> Matrix return Dimensions.valueOf(l.getFirstDim(),r.getFirstDim()); case 2: // Vector * Matrix -> Vector if(l.getLastDim() == r.getFirstDim()) return Dimensions.valueOf(r.getLastDim()); break; default: // Tensor res throw new ParseException("Sorry I don't know how to multiply a vector by a tensor"); } break; case 2: // Matrix * ? switch(rrank) { case 0: // Matrix * Scaler -> Matrix return l; case 1: // Matrix * Vector -> Vector if(l.getLastDim() == r.getFirstDim()) return Dimensions.valueOf(l.getFirstDim()); break; case 2: // Matrix * Matrix -> Matrix if(l.getLastDim() == r.getFirstDim()) return Dimensions.valueOf(l.getFirstDim(),r.getLastDim()); break; default: // Tensor res //throw new ParseException("Sorry I don't know how to multiply a matrix by a tensor"); } break; default: // Tensor res switch(rrank) { case 0: // Scaler res return l; // case 1: // Vector res // throw new ParseException("Sorry I don't know how to multiply a tensor by a vector"); // case 2: // Matrix res // throw new ParseException("Sorry I don't know how to multiply a tensor by a matrix"); // default: // Tensor res // throw new ParseException("Sorry I don't know how to multiply a tensor by a tensor"); } } throw new ParseException("Dimensions for multiply do not match: "+l+" "+r); } public MatrixValueI calcValue(MatrixValueI res,MatrixValueI param1,MatrixValueI param2) throws ParseException { if(param1 instanceof Scaler) { if(param2 instanceof Scaler) { // Scaler * Scaler -> Scaler res.setEle(0,super.mul(param1.getEle(0),param2.getEle(0))); } else if(param2 instanceof MVector) { // Scaler * Vector -> Vector for(int i=0;i Matrix { Matrix r = (Matrix) param2; Matrix mres = (Matrix) res; for(int i=0;i Vector { for(int i=0;i Matrix { Matrix mat = (Matrix) res; for(int i=0;i Vector { MVector lhs = (MVector) param1; Matrix rhs = (Matrix) param2; if(lhs.getNumEles() != rhs.getNumRows()) throw new ParseException("Multiply Matrix , Vector: Miss match in sizes ("+lhs.getNumEles()+","+rhs.getNumRows()+")!"); for(int i=0;i Matrix { Matrix l = (Matrix) param1; Matrix mres = (Matrix) res; for(int i=0;i Vector { Matrix lhs = (Matrix) param1; MVector rhs = (MVector) param2; if(lhs.getNumCols() != rhs.getNumEles()) throw new ParseException("Mat * Vec: Miss match in sizes ("+lhs.getNumCols()+","+rhs.getNumEles()+") when trying to add vectors!"); for(int i=0;i Matrix { Matrix lhs = (Matrix) param1; Matrix rhs = (Matrix) param2; Matrix mres = (Matrix) res; if(lhs.getNumCols() != rhs.getNumRows()) throw new ParseException("Multiply matrix,matrix: Miss match in number of dims ("+lhs.getNumCols()+","+rhs.getNumRows()+")!"); int lnr = lhs.getNumRows(); int lnc = lhs.getNumCols(); int rnc = rhs.getNumCols(); Object ldata[][] = lhs.getEles(); Object rdata[][] = rhs.getEles(); Object resdata[][] = mres.getEles(); for(int i=0;i [[1,0,0],[0,1,0],[0,0,1]] * * @author Rich Morris * Created on 13-Feb-2005 */ public class Id extends PostfixMathCommand { public Id() { this.numberOfParameters = 1; } public void run(Stack s) throws ParseException { Object obj = s.pop(); int n = ((Number) obj).intValue(); Matrix mat = (Matrix) Matrix.getInstance(n,n); for(int i=0;i * size(7) -> 1 * size([1,2,3]) -> 3 * size([[1,2,3],[4,5,6]]) -> [2,3] * size([[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]) -> [2,3,2] * * @author Rich Morris * Created on 13-Feb-2005 */ public class Size extends PostfixMathCommand implements UnaryOperatorI { public Size() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { int rank = ldim.rank(); if(rank == 0) return Dimensions.ONE; return Dimensions.valueOf(rank); } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { Dimensions dims = lhs.getDim(); if(dims.is0D()) { res.setEle(0,new Integer(1)); return res; } for(int i=0;i * len(5) -> 1 * len([1,2,3]) -> 3 * len([[1,2],[3,4],[5,6]]) -> 6 * * @author Rich Morris * Created on 13-Feb-2005 */ public class Length extends PostfixMathCommand implements UnaryOperatorI { public Dimensions calcDim(Dimensions ldim) { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { int neles = lhs.getNumEles(); res.setEle(0,new Integer(neles)); return res; } public void run(Stack aStack) throws ParseException { Object obj = aStack.pop(); MatrixValueI res = null; if(obj instanceof MatrixValueI) { res = Scaler.getInstance(new Integer(((MatrixValueI) obj).getNumEles())); } else res = Scaler.getInstance(new Integer(1)); aStack.push(res); } public Length() { super(); this.numberOfParameters = 1; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/Transpose.java0000644000000000000000000000324310615400352024664 0ustar rootroot/* @author rich * Created on 13-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.vectorJep.function; import java.util.Stack; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; /** * Transpose a matrix. * trans([[1,2],[3,4]]) -> [[1,3],[2,4]] * * @author Rich Morris * Created on 13-Feb-2005 */ public class Transpose extends PostfixMathCommand implements UnaryOperatorI { public Transpose() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.valueOf(ldim.getLastDim(),ldim.getFirstDim()); } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(res instanceof Matrix)) throw new ParseException("transpose: result must be a matrix"); if(!(lhs instanceof Matrix)) throw new ParseException("transpose: argument must be a matrix"); Matrix resmat = (Matrix) res; Matrix mat = (Matrix) lhs; if( resmat.getNumCols() != mat.getNumRows() || resmat.getNumRows() != mat.getNumCols()) throw new ParseException("transpose, dimension of result is wrong res "+resmat.getDim()+" arg "+mat.getDim()); for(int i=0;i=0;--i) { Vector vec = (Vector) inStack.pop(); for(int j=0;j=0;--i) { MatrixValueI mat = (MatrixValueI) inStack.pop(); for(int j=0;j=0;--i) { Object param = inStack.pop(); res.setEle(i,param); } inStack.push(res); return; } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/UnaryOperatorI.java0000644000000000000000000000176510615400352025640 0ustar rootroot/* @author rich * Created on 02-Nov-2003 */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommandI; /** * A matrix enabled unary operator. * This interface is primarilary used in the matrixJep package * but is here for convienience. * * @author Rich Morris * Created on 02-Nov-2003 */ public interface UnaryOperatorI extends PostfixMathCommandI { /** Find the dimensions of this operator when applied to arguments with given dimensions. */ public Dimensions calcDim(Dimensions ldim); /** Calculates the value of this operator for given input with results stored in res. * res is returned. Using this method is slightly faster * than the standard run method as it eliminates the construction * of tempoary objects. */ public MatrixValueI calcValue( MatrixValueI res, MatrixValueI lhs) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/VPower.java0000644000000000000000000000367010615400352024134 0ustar rootroot/* @author rich * Created on 26-Nov-2003 */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.*; import java.util.*; /** * An overloaded power function, if both arguments are vectors returns * the exteriour product, else return standard power. * @author Rich Morris * Created on 26-Nov-2003 */ public class VPower extends PostfixMathCommand implements BinaryOperatorI { private static Power pow = new Power(); private static ExteriorProduct cross = new ExteriorProduct(); public VPower() { super(); this.numberOfParameters = 2; } public Dimensions calcDim(Dimensions ldim,Dimensions rdim) throws ParseException { if(ldim.equals(Dimensions.ONE) && rdim.equals(Dimensions.ONE)) return Dimensions.ONE; if(ldim.equals(Dimensions.THREE) && rdim.equals(Dimensions.THREE)) return Dimensions.THREE; throw new ParseException("Power: both sides must be either 0 dimensional or 3D vectors"); } public MatrixValueI calcValue( MatrixValueI res, MatrixValueI lhs, MatrixValueI rhs) throws ParseException { if(lhs.getDim().equals(Dimensions.ONE) && rhs.getDim().equals(Dimensions.ONE)) { res.setEle(0,pow.power(lhs.getEle(0),rhs.getEle(0))); return res; } if(lhs.getDim().equals(Dimensions.THREE) && rhs.getDim().equals(Dimensions.THREE)) { return cross.calcValue(res,lhs,rhs); } throw new ParseException("Power: both sides must be either 0 dimensional or 3D vectors"); } public void run(Stack inStack) throws ParseException { checkStack(inStack); // check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if(param1 instanceof MVector && param2 instanceof MVector) inStack.push(cross.crosspower(param1, param2)); else inStack.push(pow.power(param1,param2)); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/ArrayAccess.java0000644000000000000000000000625310615400352025112 0ustar rootroot/* Created 16-May-2006 - Richard Morris */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.MVector; import org.lsmp.djep.vectorJep.values.Matrix; import org.lsmp.djep.vectorJep.values.MatrixValueI; import org.lsmp.djep.vectorJep.values.Tensor; import org.nfunk.jep.ASTVarNode; import org.nfunk.jep.EvaluatorI; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.nfunk.jep.Variable; import org.nfunk.jep.function.LValueI; /** * A postfix MathCommand which facilitates the getting and setting of vector and matrix elements. * The class implements the set method of LValueI., read access is handled by parent VEle class. * For examples * * a=[1,2,3]; * a[2]=4; * b=[[1,2],[3,4]]; * b[2,1]=5; * * @author Richard Morris * TODO implement setting slices a[3:5]=[3,4,5] a[1,]=[1,3] */ public class ArrayAccess extends VEle implements LValueI { public ArrayAccess() { super(); // TODO Auto-generated constructor stub } /** * Sets the LValue. For the equation a[2]=5 */ public void set(EvaluatorI pv,Node node, Object value) throws ParseException { Node lhs = node.jjtGetChild(0); // TODO Auto-generated method stub if(! (lhs instanceof ASTVarNode)) throw new ParseException("ArrayAccess: lhs of operator must be a Variable"); Variable var = ((ASTVarNode) lhs).getVar(); MatrixValueI varVal = (MatrixValueI) var.getValue(); Object indicies = pv.eval(node.jjtGetChild(1)); if(varVal instanceof MVector) { if(indicies instanceof Number) { ((MVector) varVal).setEle(((Number) indicies).intValue()-1,value); return; } else if(indicies instanceof MVector) { MVector vec = (MVector) indicies; if(vec.getDim().equals(Dimensions.ONE)) { int d1 = ((Number) vec.getEle(0)).intValue(); if(d1<1 || d1 > ((MVector) varVal).getNumEles()) throw new ParseException("ArrayAccess: array index "+d1+" out of range 1.."+varVal.getDim()); ((MVector) varVal).setEle(d1-1,value); return; } } throw new ParseException("ArrayAccess: Bad second argument expecting a double "+indicies.toString()); } else if(varVal instanceof Matrix) { if(indicies instanceof MVector) { MVector vec = (MVector) indicies; if(vec.getDim().equals(Dimensions.TWO)) { int d1 = ((Number) vec.getEle(0)).intValue(); int d2 = ((Number) vec.getEle(1)).intValue(); if( d1<1 || d1 > ((Matrix) varVal).getNumRows() || d2<1 || d2 > ((Matrix) varVal).getNumCols() ) throw new ParseException("ArrayAccess: array indices "+d1+", "+d2+" out of range 1.."+varVal.getDim()); ((Matrix) varVal).setEle(d1-1,d2-1,value); return; } } else throw new ParseException("ArrayAccess:Bad second argument, expecting [i,j] "+indicies.toString()); } else if(indicies instanceof Tensor) { throw new ParseException("ArrayAccess: Sorry don't know how to set an elements for a tensor"); } throw new ParseException("ArrayAccess: requires a vector matrix or tensor for first argument it has "+varVal.toString()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/NaryOperatorI.java0000644000000000000000000000162710615400352025450 0ustar rootroot/* @author rich * Created on 02-Nov-2003 */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommandI; /** * A matrix enabled operator with N arguments. * This interface is primarilary used in the matrixJep package * but is here for convienience. * * @author Rich Morris * Created on 02-Nov-2003 */ public interface NaryOperatorI extends PostfixMathCommandI { /** Find the dimensions of this operator when applied to arguments with given dimensions. */ public Dimensions calcDim(Dimensions dims[]) throws ParseException; /** Calculates the value of this operator for given input with results stored in res. * res is returned. */ public MatrixValueI calcValue(MatrixValueI res, MatrixValueI inputs[]) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/Diagonal.java0000644000000000000000000000245410615400352024427 0ustar rootroot/* @author rich * Created on 13-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.vectorJep.function; import java.util.Stack; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; /** * Creates a diagonal matrix, with a given vector as diagonals elements. * diag([1,2,3]) -> [[1,0,0],[0,2,0],[0,0,3]] * * @author Rich Morris * Created on 13-Feb-2005 */ public class Diagonal extends PostfixMathCommand implements UnaryOperatorI { public Diagonal() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.valueOf(ldim.numEles(),ldim.numEles()); } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { Matrix mat = (Matrix) res; int n = lhs.getNumEles(); for(int i=0;i 1*4-2*3 = -2 * * @author Rich Morris * Created on 13-Feb-2005 */ public class Determinant extends PostfixMathCommand implements UnaryOperatorI { Add add = new Add(); Subtract sub = new Subtract(); Multiply mul = new Multiply(); public Determinant() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(res instanceof Scaler)) throw new ParseException("det: result must be a scaler"); if(!(lhs instanceof Matrix)) throw new ParseException("det: argument must be a matrix"); Matrix mat = (Matrix) lhs; if( mat.getNumRows()!= mat.getNumCols()) throw new ParseException("det: argument must be a square matrix "+mat); if(mat.getNumRows() == 2) { res.setEle(0,sub.sub( mul.mul(mat.getEle(0,0),mat.getEle(1,1)), mul.mul(mat.getEle(1,0),mat.getEle(0,1)))); } else if(mat.getNumRows() == 3) { // | a b c | // | d e f | -> a e j + b f g + c d h - a f h - b d i - c e g // | g h i | Object r1 = mul.mul(mat.getEle(0,0),mul.mul(mat.getEle(1,1),mat.getEle(2,2))); Object r2 = mul.mul(mat.getEle(0,1),mul.mul(mat.getEle(1,2),mat.getEle(2,0))); Object r3 = mul.mul(mat.getEle(0,2),mul.mul(mat.getEle(1,0),mat.getEle(2,1))); Object r4 = mul.mul(mat.getEle(0,0),mul.mul(mat.getEle(1,2),mat.getEle(2,1))); Object r5 = mul.mul(mat.getEle(0,1),mul.mul(mat.getEle(1,0),mat.getEle(2,2))); Object r6 = mul.mul(mat.getEle(0,2),mul.mul(mat.getEle(1,1),mat.getEle(2,0))); Object r7 = add.add(r1,add.add(r2,r3)); Object r8 = add.add(r4,add.add(r5,r6)); res.setEle(0,sub.sub(r7,r8)); } else { Object[][] m = mat.getEles(); res.setEle(0,det(m)); } // throw new ParseException("Sorry can only calculate determinants for 2 by 2 and 3 by 3 matricies"); return res; } /** returns a matrix excluding the specifyed row and column */ public static Object[][] dropRowCol(Object[][] mat,int xrow,int xcol) { int nrows = mat.length; int ncols = mat[0].length; Object res[][] = new Object[nrows-1][ncols-1]; int currow = 0; for(int i=0;i 6 * vsum([[1,2],[3,4]]) -> 10 * * @author Rich Morris * Created on 13-Feb-2005 */ public class VSum extends PostfixMathCommand implements UnaryOperatorI { Add add = new Add(); public VSum() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(res instanceof Scaler)) throw new ParseException("vsum: result must be a scaler"); Object val = lhs.getEle(0); for(int i=1;i * GenMat(3,1) -> [1,1,1] * GenMat(3,ii,ii) -> [1,2,3] * GenMat(3,rand()) -> [0.343,0.974,0.567] * GenMat([2,2],ii+jj,[ii,jj]) -> [[2,3],[3,4]] * * Note the free variables should not be the same name as variables already * in use, in particular i is often set to be the complex root of unity, and should be avoided. * * @author Rich Morris * Created on 14-Feb-2005 */ public class GenMat extends PostfixMathCommand implements CallbackEvaluationI { public GenMat() { super(); this.numberOfParameters = -1; } public boolean checkNumberOfParameters(int n) { return (n == 2 || n == 3); } public Object evaluate( Node node, EvaluatorI pv) throws ParseException { Object sizeObj = pv.eval(node.jjtGetChild(0)); int sizes[] = null; if( sizeObj instanceof Scaler) { sizes = new int[1]; sizes[0] = ((Number) sizeObj).intValue(); } else if( sizeObj instanceof MVector) { MVector vec = (MVector) sizeObj; int n = vec.getNumEles(); sizes = new int[n]; for(int i=0;i 1+4 = 5 * * @author Rich Morris * Created on 13-Feb-2005 */ public class Trace extends PostfixMathCommand implements UnaryOperatorI { Add add = new Add(); Multiply mul = new Multiply(); public Trace() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(res instanceof Scaler)) throw new ParseException("trace: result must be a scaler"); if(!(lhs instanceof Matrix)) throw new ParseException("trace: argument must be a matrix"); Matrix mat = (Matrix) lhs; if( mat.getNumRows()!= mat.getNumCols()) throw new ParseException("trace: argument must be a square matrix "+mat); if(mat.getNumRows() == 2) { res.setEle(0,add.add(mat.getEle(0,0),mat.getEle(1,1))); } else if(mat.getNumRows() == 3) { res.setEle(0,add.add(mat.getEle(0,0),add.add(mat.getEle(1,1),mat.getEle(2,2)))); } else { Object val = mat.getEle(0,0); for(int i=1;i * a = [1,2,3,4]; * ele(a,1); // returns 1 * m = [[1,2],[3,4]]; * ele(m,[2,2]); // return 4 * * * New parser feature allow a[] notation to be used. * * a=[1,2,3,4]; * a[3]; // returns 3 * b=[[1,2],[3,4]]; * b[1,2]; // returns 2 * * * @author Rich Morris * Created on 15-Nov-2003 */ public class VEle extends PostfixMathCommand implements BinaryOperatorI { public VEle() { super(); numberOfParameters = 2; } public Dimensions calcDim(Dimensions ldim, Dimensions rdim) throws ParseException { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI param1,MatrixValueI param2) throws ParseException { // Number num = (Number) rhs.getEle(0); // res.setEle(0,lhs.getEle(num.intValue()-1)); if(param1 instanceof MVector) { if(param2 instanceof Scaler) { int index = ((Number) param2.getEle(0)).intValue()-1; Object val = ((MVector) param1).getEle(index); res.setEle(0,val); } else if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.ONE)) { int d1 = ((Number) vec.getEle(0)).intValue(); if( d1<1 || d1 > ((MVector) param1).getNumEles()) throw new ParseException("ArrayAccess: array indices "+d1+" out of range 1.."+param1.getDim()); Object val = ((MVector) param1).getEle(d1-1); res.setEle(0,val); } } else throw new ParseException("Bad second argument to ele, expecting a double "+param2.toString()); } else if(param1 instanceof Matrix) { if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.TWO)) { int d1 = ((Number) vec.getEle(0)).intValue(); int d2 = ((Number) vec.getEle(1)).intValue(); if( d1<1 || d1 > ((Matrix) param1).getNumRows() || d2<1 || d2 > ((Matrix) param1).getNumCols() ) throw new ParseException("ArrayAccess: array indices "+d1+", "+d2+" out of range 1.."+param1.getDim()); Object val = ((Matrix) param1).getEle(d1-1,d2-1); res.setEle(0,val); } } else throw new ParseException("Bad second argument to ele, expecting [i,j] "+param2.toString()); } else if(param1 instanceof Tensor) { throw new ParseException("Sorry don't know how to find elements for a tensor"); } else throw new ParseException("ele requires a vector matrix or tensor for first argument it has "+param1.toString()); return res; } public void run(Stack stack) throws ParseException { checkStack(stack); // check the stack Object param1,param2; // get the parameter from the stack param2 = stack.pop(); param1 = stack.pop(); if(param1 instanceof MVector) { if(param2 instanceof Number) { Object val = ((MVector) param1).getEle(((Number) param2).intValue()-1); stack.push(val); return; } else if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.ONE)) { int d1 = ((Number) vec.getEle(0)).intValue(); if( d1<1 || d1 > ((MVector) param1).getNumEles()) throw new ParseException("ArrayAccess: array indices "+d1+" out of range 1.."+((MVector) param1).getDim()); Object val = ((MVector) param1).getEle(d1-1); stack.push(val); return; } } throw new ParseException("Bad second argument to ele, expecting a double "+param2.toString()); } else if(param1 instanceof Matrix) { if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.TWO)) { int d1 = ((Number) vec.getEle(0)).intValue(); int d2 = ((Number) vec.getEle(1)).intValue(); if( d1<1 || d1 > ((Matrix) param1).getNumRows() || d2<1 || d2 > ((Matrix) param1).getNumCols() ) throw new ParseException("ArrayAccess: array indices "+d1+", "+d2+" out of range 1.."+((Matrix) param1).getDim()); Object val = ((Matrix) param1).getEle(d1-1,d2-1); stack.push(val); return; } } else throw new ParseException("Bad second argument to ele, expecting [i,j] "+param2.toString()); } else if(param1 instanceof Tensor) { throw new ParseException("Sorry don't know how to find elements for a tensor"); } throw new ParseException("ele requires a vector matrix or tensor for first argument it has "+param1.toString()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/BinaryOperatorI.java0000644000000000000000000000206410615400352025757 0ustar rootroot/* @author rich * Created on 02-Nov-2003 */ package org.lsmp.djep.vectorJep.function; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommandI; /** * A matrix enabled binary operator. * This interface is primarilary used in the matrixJep package * but is here for convienience. * * @author Rich Morris * Created on 02-Nov-2003 */ public interface BinaryOperatorI extends PostfixMathCommandI { /** Find the dimensions of this operator when applied to arguments with given dimensions. */ public Dimensions calcDim(Dimensions ldim,Dimensions rdim) throws ParseException; /** Calculates the value of this operator for given input with results stored in res. * res is returned. Using this method is slightly faster * than the standard run method as it eliminates the construction * of tempoary objects. */ public MatrixValueI calcValue( MatrixValueI res, MatrixValueI lhs, MatrixValueI rhs) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/ElementComparative.java0000644000000000000000000000421310615400352026470 0ustar rootroot/* @author rich * Created on 10-Dec-2004 */ package org.lsmp.djep.vectorJep.function; import java.util.Stack; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * Multiplies any number of Vectors or Matrices element by element. * TODO could be much more efficient when called through run. * * @author Rich Morris * Created on 10-Dec-2004 */ public class ElementComparative extends Comparative implements BinaryOperatorI { public ElementComparative(int index) {super(index);} public Dimensions calcDim(Dimensions ldim,Dimensions rdim) { if(ldim.equals(rdim)) return ldim; return null; } /** * Multiply the inputs element by element putting the results in res. */ public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs,MatrixValueI rhs) throws ParseException { int len = res.getNumEles(); for(int i=0;i [1,4,9] * Map(x^y,[x,y],[1,2,3],[1,2,3]) -> [1,4,27] * First argument is a equation, second argument is the name or names of variables. * Third and subsequent arguments are vectors or matrices, they must have the same dimensions * and the number of subsequent arguments must match the number of variables specified in the second argument. * * @author Rich Morris * Created on 14-Feb-2005 */ public class VMap extends PostfixMathCommand implements NaryOperatorI, CallbackEvaluationI { /** * */ public VMap() { super(); this.numberOfParameters = -1; } public Dimensions calcDim(Dimensions[] dims) throws ParseException { return dims[2]; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI[] inputs) throws ParseException { return null; } public static Variable[] getVars(Node varsNode) throws ParseException { Variable vars[]=null; if(varsNode instanceof ASTFunNode && ((ASTFunNode) varsNode).getPFMC() instanceof VList ) { int nVars = varsNode.jjtGetNumChildren(); vars = new Variable[nVars]; for(int i=0;i= 3); } public Object evaluate( Node node, EvaluatorI pv) throws ParseException { int nChild = node.jjtGetNumChildren(); if(nChild <3) throw new ParseException("Map must have three or more arguments"); // First find the variables Variable vars[] = getVars(node.jjtGetChild(1)); if(nChild != vars.length + 2) throw new ParseException("Map: number of arguments should match number of variables + 2"); // Now evaluate third and subsequent arguments MatrixValueI inputs[] = new MatrixValueI[nChild-2]; Dimensions dim=null; for(int i=0;i * a = [1,2,3,4]; * ele(a,1); // returns 1 * m = [[1,2],[3,4]]; * ele(m,[2,2]); // return 4 * * * New parser feature allow a[] notation to be used. * * a=[1,2,3,4]; * a[3]; // returns 3 * b=[[1,2],[3,4]]; * b[1,2]; // returns 2 * * * @author Rich Morris * Created on 15-Nov-2003 */ public class Ele extends PostfixMathCommand implements BinaryOperatorI { public Ele() { super(); numberOfParameters = 2; } public Dimensions calcDim(Dimensions ldim, Dimensions rdim) throws ParseException { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI param1,MatrixValueI param2) throws ParseException { // Number num = (Number) rhs.getEle(0); // res.setEle(0,lhs.getEle(num.intValue()-1)); if(param1 instanceof MVector) { if(param2 instanceof Scaler) { int index = ((Number) param2.getEle(0)).intValue()-1; Object val = ((MVector) param1).getEle(index); res.setEle(0,val); } else if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.ONE)) { int d1 = ((Number) vec.getEle(0)).intValue(); if( d1<1 || d1 > ((MVector) param1).getNumEles()) throw new ParseException("ArrayAccess: array indices "+d1+" out of range 1.."+param1.getDim()); Object val = ((MVector) param1).getEle(d1-1); res.setEle(0,val); } } else throw new ParseException("Bad second argument to ele, expecting a double "+param2.toString()); } else if(param1 instanceof Matrix) { if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.TWO)) { int d1 = ((Number) vec.getEle(0)).intValue(); int d2 = ((Number) vec.getEle(1)).intValue(); if( d1<1 || d1 > ((Matrix) param1).getNumRows() || d2<1 || d2 > ((Matrix) param1).getNumCols() ) throw new ParseException("ArrayAccess: array indices "+d1+", "+d2+" out of range 1.."+param1.getDim()); Object val = ((Matrix) param1).getEle(d1-1,d2-1); res.setEle(0,val); } } else throw new ParseException("Bad second argument to ele, expecting [i,j] "+param2.toString()); } else if(param1 instanceof Tensor) { throw new ParseException("Sorry don't know how to find elements for a tensor"); } else throw new ParseException("ele requires a vector matrix or tensor for first argument it has "+param1.toString()); return res; } public void run(Stack stack) throws ParseException { checkStack(stack); // check the stack Object param1,param2; // get the parameter from the stack param2 = stack.pop(); param1 = stack.pop(); if(param1 instanceof MVector) { if(param2 instanceof Number) { Object val = ((MVector) param1).getEle(((Number) param2).intValue()-1); stack.push(val); return; } else if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.ONE)) { int d1 = ((Number) vec.getEle(0)).intValue(); if( d1<1 || d1 > ((MVector) param1).getNumEles()) throw new ParseException("ArrayAccess: array indices "+d1+" out of range 1.."+((MVector) param1).getDim()); Object val = ((MVector) param1).getEle(d1-1); stack.push(val); return; } } throw new ParseException("Bad second argument to ele, expecting a double "+param2.toString()); } else if(param1 instanceof Matrix) { if(param2 instanceof MVector) { MVector vec = (MVector) param2; if(vec.getDim().equals(Dimensions.TWO)) { int d1 = ((Number) vec.getEle(0)).intValue(); int d2 = ((Number) vec.getEle(1)).intValue(); if( d1<1 || d1 > ((Matrix) param1).getNumRows() || d2<1 || d2 > ((Matrix) param1).getNumCols() ) throw new ParseException("ArrayAccess: array indices "+d1+", "+d2+" out of range 1.."+((Matrix) param1).getDim()); Object val = ((Matrix) param1).getEle(d1-1,d2-1); stack.push(val); return; } } else throw new ParseException("Bad second argument to ele, expecting [i,j] "+param2.toString()); } else if(param1 instanceof Tensor) { throw new ParseException("Sorry don't know how to find elements for a tensor"); } throw new ParseException("ele requires a vector matrix or tensor for first argument it has "+param1.toString()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/ExteriorProduct.java0000644000000000000000000000506010615400352026047 0ustar rootroot/***************************************************************************** JEP - Java Math Expression Parser 2.24 December 30 2002 (c) Copyright 2002, Nathan Funk See LICENSE.txt for license information. *****************************************************************************/ package org.lsmp.djep.vectorJep.function; import java.util.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * An overloaded operator, either cross product or power. * If the arguments are 3D vectors then treat as cross product. * Otherwise treet as power. * @author Rich Morris * Created on 27-Jul-2003 */ public class ExteriorProduct extends PostfixMathCommand implements BinaryOperatorI { private Subtract sub = new Subtract(); private Multiply mul = new Multiply(); public ExteriorProduct() { numberOfParameters = 2; } public Dimensions calcDim(Dimensions ldim,Dimensions rdim) throws ParseException { if(ldim.equals(Dimensions.THREE)&&rdim.equals(Dimensions.THREE)) return Dimensions.THREE; throw new ParseException("^ only implemented for three dimensions vectors"); } public MatrixValueI calcValue( MatrixValueI res, MatrixValueI lhs, MatrixValueI rhs) throws ParseException { res.setEle(0,sub.sub( mul.mul(lhs.getEle(1),rhs.getEle(2)), mul.mul(lhs.getEle(2),rhs.getEle(1)))); res.setEle(1,sub.sub( mul.mul(lhs.getEle(2),rhs.getEle(0)), mul.mul(lhs.getEle(0),rhs.getEle(2)))); res.setEle(2,sub.sub( mul.mul(lhs.getEle(0),rhs.getEle(1)), mul.mul(lhs.getEle(1),rhs.getEle(0)))); return res; } public void run(Stack inStack) throws ParseException { checkStack(inStack); // check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); inStack.push(crosspower(param1, param2)); } public Object crosspower(Object param1, Object param2) throws ParseException { if(param1 instanceof MVector && param2 instanceof MVector) return exteriorProduct((MVector) param1,(MVector) param2); throw new ParseException("Sorry: can currently only do cross product on 3D vectors"); } public Object exteriorProduct(MVector lhs, MVector rhs) throws ParseException { if(!lhs.getDim().equals(Dimensions.THREE) || !lhs.getDim().equals(Dimensions.THREE) ) throw new ParseException("Cross: Miss match in sizes ("+lhs.getDim()+","+rhs.getDim()+")"); MVector res = new MVector(3); return calcValue(res,lhs,rhs); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/function/GetDiagonal.java0000644000000000000000000000257310615400352025071 0ustar rootroot/* @author rich * Created on 13-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.vectorJep.function; import java.util.Stack; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; /** * Extracts diagonal from a square matrix. * getDiag([[1,0,0],[0,2,0],[0,0,3]]) -> [1,2,3] * * @author Rich Morris * Created on 13-Feb-2005 */ public class GetDiagonal extends PostfixMathCommand implements UnaryOperatorI { public GetDiagonal() { super(); this.numberOfParameters = 1; } public Dimensions calcDim(Dimensions ldim) { return Dimensions.valueOf(ldim.getFirstDim()); } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { MVector vec = (MVector) res; Matrix mat = (Matrix) lhs; if( vec.getNumEles() != mat.getNumRows() || vec.getNumEles() != mat.getNumCols()) throw new ParseException("getDiag requires a square matrix"); for(int i=0;i Basic handeling of Vectors and Matricies. This is a smaller and simpler version than {link org.lsmp.djep.matrixJep matrixJep}. For most applications this package will suffice, however if differentation or overloading ^ to be the cross product operator then matrixJep should be used.

    Sub-packages
    org.lsmp.djep.vectorJep.function Functions for vector and matrix operations
    org.lsmp.djep.vectorJep.values Values representing Vectors and Matricies.
    @see VectorJep documentation jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/VectorEvaluator.java0000644000000000000000000000670010615400352024207 0ustar rootroot/* @author rich * Created on 10-Dec-2004 */ package org.lsmp.djep.vectorJep; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.vectorJep.function.*; import org.lsmp.djep.vectorJep.values.*; /** * @author Rich Morris * Created on 10-Dec-2004 */ public class VectorEvaluator extends EvaluatorVisitor { /** * Visit a function node. The values of the child nodes * are first pushed onto the stack. Then the function class associated * with the node is used to evaluate the function. *

    * If a function implements SpecialEvaluationI then the * evaluate method of PFMC is called. */ public Object visit(ASTFunNode node, Object data) throws ParseException { if (node == null) return null; PostfixMathCommandI pfmc = node.getPFMC(); // check if the function class is set if (pfmc == null) throw new ParseException( "No function class associated with " + node.getName()); int numChild = node.jjtGetNumChildren(); // Some operators (=) need a special method for evaluation // as the pfmc.run method does not have enough information // in such cases we call the evaluate method which passes // all available info. Note evaluating the children is // the responsibility of the evaluate method. if (pfmc instanceof SpecialEvaluationI) { return ((SpecialEvaluationI) node.getPFMC()).evaluate( node,data,this,stack,this.symTab); } if(pfmc instanceof CallbackEvaluationI) { Object value = ((CallbackEvaluationI) pfmc).evaluate(node,this); stack.push(value); return value; } if (debug == true) { System.out.println( "Stack size before childrenAccept: " + stack.size()); } // evaluate all children (each leaves their result on the stack) data = node.childrenAccept(this, data); if (debug == true) { System.out.println( "Stack size after childrenAccept: " + stack.size()); } if (pfmc.getNumberOfParameters() == -1) { // need to tell the class how many parameters it can take off // the stack because it accepts a variable number of params pfmc.setCurNumberOfParameters(numChild); } // try to run the function if(pfmc instanceof UnaryOperatorI || pfmc instanceof BinaryOperatorI || pfmc instanceof NaryOperatorI || pfmc instanceof Comparative) pfmc.run(stack); else if(numChild == 0) { pfmc.run(stack); } else /* perform operations element by element */ { if(stack.peek() instanceof MatrixValueI) { MatrixValueI args[] = new MatrixValueI[node.jjtGetNumChildren()]; args[numChild-1] = (MatrixValueI) stack.pop(); Dimensions lastDim = args[numChild-1].getDim(); for(int i=numChild-2;i>=0;--i) { Object val = stack.pop(); if(!(val instanceof MatrixValueI)) throw new ParseException("All arguments of function must be same dimension"); args[i]=(MatrixValueI) val; if(!lastDim.equals(args[i].getDim())) throw new ParseException("All arguments of function must be same dimension"); } MatrixValueI res = Tensor.getInstance(lastDim); for(int i=0;i0) sb.append(','); sb.append(data[i]); } sb.append(']'); return sb.toString(); } public Dimensions getDim() { return dim; } public int getNumEles() { return data.length; } public void setEle(int i,Object value) { data[i] = value; } public Object getEle(int i) { return data[i]; } /** sets the elements to those of the arguments. */ public void setEles(MatrixValueI val) { if(!dim.equals(val.getDim())) return; System.arraycopy(((MVector) val).data,0,data,0,getNumEles()); } public Object[] getEles() { return data; } /** value of constant ele(1). */ //public int intValue() {return ((Number) data[0]).intValue(); } /** value of constant ele(1). */ //public long longValue() {return ((Number) data[0]).longValue(); } /** value of constant ele(1). */ //public float floatValue() { return ((Number) data[0]).floatValue(); } /** value of constant ele(1). */ //public double doubleValue() {return ((Number) data[0]).doubleValue(); } public boolean equals(Object obj) { if(!(obj instanceof MVector)) return false; MVector vec = (MVector) obj; if(!vec.getDim().equals(getDim())) return false; for(int i=0;i Objects representing the values of Scalers, Vectors, Matricies and Tensors. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/vectorJep/values/Tensor.java0000644000000000000000000000756310615400352023643 0ustar rootroot/* @author rich * Created on 07-Jul-2003 */ package org.lsmp.djep.vectorJep.values; import org.lsmp.djep.vectorJep.*; /** * Represents tensor (generalisation of Matrix/Vector). * @author Rich Morris * Created on 07-Jul-2003 * @version 1.3.0.2 now extends number */ public class Tensor implements MatrixValueI { private Object values[]=null; private Dimensions dims; //DoubleMatrix jsciMat; private Tensor() {} /** Creates a Tensor with the given dimension. **/ public Tensor(Dimensions dims) { values = new Object[dims.numEles()]; this.dims = dims; } /** Creates a Tensor with same dimension as the arguments. **/ public Tensor(Tensor t) { values = new Object[t.getDim().numEles()]; this.dims = t.getDim(); } public MatrixValueI copy() { Tensor tmp = new Tensor(this); tmp.setEles(tmp); return tmp; } /** Creates a tensor with dimensions [len,dims[0],...,dims[n]] **/ public Tensor(int len,Dimensions dims) { values = new Object[len*dims.numEles()]; this.dims = Dimensions.valueOf(len,dims); } public Dimensions getDim() { return dims; } public int getNumEles() { return values.length; } public void setEle(int i,Object value) { values[i]=value; } public Object getEle(int i) { return values[i]; } /** sets the elements to those of the arguments. */ public void setEles(MatrixValueI val) { if(!dims.equals(val.getDim())) return; System.arraycopy(((Tensor) val).values,0,values,0,getNumEles()); } /** Factory method to return a new Vector, Matrix or Tensor * with the given dimensions. */ public static MatrixValueI getInstance(Dimensions dims) { switch(dims.rank()) { case 0: return new Scaler(); case 1: return new MVector(dims.getFirstDim()); case 2: return new Matrix(dims.getFirstDim(),dims.getLastDim()); default: return new Tensor(dims); } } private static MatrixValueI getInstance(int rows,Dimensions dims) { switch(dims.rank()) { case 0: return new MVector(rows); case 1: return new Matrix(rows,dims.getFirstDim()); default: return new Tensor(Dimensions.valueOf(rows,dims)); } } private int curEle =0; /** Recursive procedure to print the tensor with lots of brackets. **/ protected void bufferAppend(StringBuffer sb,int currank) { sb.append("["); if(currank+1 >= dims.rank()) { // bottom of tree for(int i=0;i0) sb.append(','); sb.append('['); for(int j=0;j0)sb.append(','); sb.append(data[i][j]); } sb.append(']'); } sb.append(']'); return sb.toString(); } public Dimensions getDim() { return dims; } public int getNumEles() { return rows*cols; } public int getNumRows() { return rows; } public int getNumCols() { return cols; } public void setEle(int n,Object value) { int i = n / cols; int j = n % cols; data[i][j] = value; } public void setEle(int i,int j,Object value) { data[i][j] = value; } public Object getEle(int n) { int i = n / cols; int j = n % cols; return data[i][j]; } public Object getEle(int i,int j) { return data[i][j]; } public Object[][] getEles() { return data; } /** sets the elements to those of the arguments. */ public void setEles(MatrixValueI val) { if(!dims.equals(val.getDim())) return; for(int i=0;i>32)); // int yi = (int)(yl^(yl>>32)); for(int i=0;i Differentiation and Matricies in JEP. Main JEP documentation. Main DJep documentation. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/0000755000000000000000000000000010615400352017214 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/PVariable.java0000644000000000000000000000170510615400352021727 0ustar rootroot/* @author rich * Created on 14-Dec-2004 */ package org.lsmp.djep.sjep; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; /** * Represents a variable. * * @author Rich Morris * Created on 14-Dec-2004 */ public class PVariable extends AbstractPNode { XVariable variable; /** * */ public PVariable(PolynomialCreator pc,XVariable var) { super(pc); this.variable = var; } public boolean equals(PNodeI node) { if(node instanceof PVariable) if(variable.equals(((PVariable)node).variable)) return true; return false; } /** this < arg ---> -1 this > arg ---> 1 */ public int compareTo(PVariable vf) { return variable.getName().compareTo(vf.variable.getName()); } public String toString() { return variable.getName(); } public Node toNode() throws ParseException { return pc.nf.buildVariableNode(variable); } public PNodeI expand() { return this; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/Polynomial.java0000644000000000000000000001120110615400352022175 0ustar rootroot/* @author rich * Created on 14-Dec-2004 */ package org.lsmp.djep.sjep; import org.nfunk.jep.*; /** * Represents a polynomial. * i.e. a sum of terms which are typically * {@link Monomial}s, but can be any {@link AbstractPNode}. The order of the terms is specified by the total ordering. * * @author Rich Morris * Created on 14-Dec-2004 */ public class Polynomial extends AbstractPNode { PNodeI terms[]; /** * */ Polynomial(PolynomialCreator pc,PNodeI terms[]) { super(pc); this.terms = terms; } MutiablePolynomial toMutiablePolynomial() { PNodeI newTerms[] = new PNodeI[terms.length]; for(int i=0;i -1 this > arg ---> 1 */ public int compareTo(PNodeI node) { if(node instanceof Polynomial) return this.compareTo((Polynomial) node); int res = terms[0].compareTo(node); if(res != 0) return res; if(terms.length == 1) return 0; return 1; } public int compareTo(Polynomial p) { for(int i=0;i= p.terms.length) return 1; int res = terms[i].compareTo(p.terms[i]); if(res != 0) return res; } if(terms.length < p.terms.length) return -1; return 0; } private boolean isNegative(PNodeI node) { if(node instanceof PConstant) return ((PConstant) node).isNegative(); if(node instanceof Monomial) return ((Monomial) node).negativeCoefficient(); return false; } public String toString() { if(terms.length==0) return "0"; StringBuffer sb = new StringBuffer(); for(int i=0;i0 && !isNegative(terms[i])) sb.append('+'); sb.append(terms[i].toString()); } return sb.toString(); } public Node toNode() throws ParseException { if(terms.length==0) return pc.nf.buildConstantNode(pc.zero); Node args[] = new Node[terms.length]; for(int i=0;i

    An advanced simplification/expansion/comparison algorithm. To use

    PolynomialCreator pc = new PolynomialCreator(jep);
    Node simp = pc.simplify(node);
    Node expand = pc.expand(node);
    boolean flag = pc.equals(node1,node2);
    int res = pc.compare(node1,node2);
    PNodeI poly = pc.createPoly(node);
    

    How it works

    The basic idea is to reduce each equation to a canonical form based on a total ordering of the terms. For example a polynomial in x will always be in the form a+b x+c x^2+d x^3. This makes comparison of two polynomials easy as it is just necessary to compare term by term, whereas it is difficult to compare x^2-1 with (x+1)*(x-1) without any simplification or reordering.

    The precise total ordering is intentionally not defined as it may be later modified. As an illustration some of the rules for the ordering are 0<1<2, 5<x, x<x^2<x^3, x<y.

    A polynomial is constructed from a set of monomials by arranging the monomials in order. Likewise a monomial is constructed from a set of variables by arranging the variables in name order.

    The algorithm can also work with non-polynomial equations. Functions are order by the name of the function and the ordering of their arguments. Hence cos(x)<sin(x)<sin(y).

    jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/PolynomialCreator.java0000644000000000000000000002345710615400352023535 0ustar rootroot/* @author rich * Created on 14-Dec-2004 */ package org.lsmp.djep.sjep; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.nfunk.jep.function.*; /** * Main entry point for simplification routines. * *

    Uses a complete reworking of the ways equations are represented. A tree structure is built from Polynomials, Monomials, PVariable etc. An equation like

    1+2 x^2+3 x y+4 x sin(y)
    is represented as
    Polynomial([
      Monomial(2.0,[PVariable(x)],[2])]),
      Monomial(3.0,[x,y],[1,1]),
      Monomial(4.0,[x,Function(sin,arg)],[1,1])
    ])
    

    A total ordering of all expressions is used. As the representation is constructed the total ordering of terms is maintained. This helps ensure that polynomials are always in their simplest form and also allows comparison of equations.

    The following sequence illustrates current ordering. This ordering may change without warning.

    • -1 numbers sorted by values
    • 0
    • 1 numbers before monomials
    • a^-2 powers in increasing order
    • a^-1
    • a
    • a^2
    • a^3
    • a^x numeric powers before symbolic powers
    • a b single variable monomials before multiple variables
    • a^2 b
    • b variables sorted alphabetically
    • cos(a) monomials before functions
    • sin(a) function names sorted alphabetically
    • a+b functions before polynomials
    • a+b+c
    * @author Rich Morris * Created on 14-Dec-2004 */ public class PolynomialCreator extends DoNothingVisitor { private XJep jep; Object zero,one,minusOne,infinity,nan,two; PConstant zeroConstant,oneConstant,minusOneConstant,infConstant,nanConstant,twoConstant; Monomial zeroMonomial,unitMonomial,infMonomial,nanMonomial; Polynomial zeroPolynomial,unitPolynomial,infPolynomial,nanPolynomial; NumberFactory numf; OperatorSet os; NodeFactory nf; //boolean expand=false; private PolynomialCreator() {} public PolynomialCreator(XJep j) { jep = j; numf = j.getNumberFactory(); os = j.getOperatorSet(); nf = j.getNodeFactory(); zero = j.getNumberFactory().getZero(); one = j.getNumberFactory().getOne(); minusOne = j.getNumberFactory().getMinusOne(); two = j.getNumberFactory().getTwo(); try { infinity = div(one,zero); nan = div(zero,zero); } catch(ParseException e) { infinity = new Double(Double.POSITIVE_INFINITY); nan = new Double(Double.NaN); } zeroConstant = new PConstant(this,zero); oneConstant = new PConstant(this,one); twoConstant = new PConstant(this,two); minusOneConstant = new PConstant(this,minusOne); infConstant = new PConstant(this,infinity); nanConstant = new PConstant(this,nan); } /** * Converts an expression into the polynomial representation. * @param node top node of expression * @return top node of polynomial form of expression * @throws ParseException if expression cannot be converted. */ public PNodeI createPoly(Node node) throws ParseException { return (PNodeI) node.jjtAccept(this,null); } /** * Simplifies an expression. * * @param node top node to expression to be simplified. * @return a simplified expression * @throws ParseException */ public Node simplify(Node node) throws ParseException { PNodeI poly = createPoly(node); return poly.toNode(); } /** * Expands an expression. * Will always expand brackets for multiplication and simple powers. * For instance * (1+x)^3 -> 1+3x+3x^2+x^3 * * @param node top node to expression to be simplified. * @return a simplified expression * @throws ParseException */ public Node expand(Node node) throws ParseException { PNodeI poly = createPoly(node); PNodeI expand = poly.expand(); return expand.toNode(); } /** * Compares two nodes. * Uses a total ordering of expressions. * Expands equations before comparison. * * @param node1 * @param node2 * @return -1 if node1node2 * @throws ParseException */ public int compare(Node node1,Node node2) throws ParseException { PNodeI poly1 = createPoly(node1); PNodeI exp1 = poly1.expand(); PNodeI poly2 = createPoly(node2); PNodeI exp2 = poly2.expand(); return exp1.compareTo(exp2); } /** * Compares two nodes. * Uses a total ordering of expressions. * May give some false negatives is simplification cannot reduce * two equal expressions to the same canonical form. * Expands equations before comparison. * * @param node1 * @param node2 * @return true if two nodes represents same expression. * @throws ParseException */ public boolean equals(Node node1,Node node2) throws ParseException { PNodeI poly1 = createPoly(node1); PNodeI exp1 = poly1.expand(); PNodeI poly2 = createPoly(node2); PNodeI exp2 = poly2.expand(); return exp1.equals(exp2); } public Object visit(ASTConstant node, Object data) throws ParseException { return new PConstant(this,node.getValue()); } public Object visit(ASTVarNode node, Object data) throws ParseException { return new PVariable(this,(XVariable) node.getVar()); } public Object visit(ASTFunNode node, Object data) throws ParseException { int nChild = node.jjtGetNumChildren(); PNodeI args[] = new PNodeI[nChild]; for(int i=0;i 0) { newTerms[pos] = term; ++pos; done = true; } newTerms[pos] = terms[i]; ++pos; } if(!done) { newTerms[pos] = term; ++pos; } terms = newTerms; } /** * Multiplies this by a polynomial and expands the results. * (1+x)*(1+x) --> 1+2*x+x^2 * @param p the polynomial to multiply by * @throws ParseException */ void expandMul(Polynomial p) throws ParseException { PNodeI newTerms[][] = new PNodeI[terms.length][p.terms.length]; for(int i=0;i 1+2*x+x^2 * @param node * @throws ParseException */ void expandMul(PNodeI node) throws ParseException { if(node instanceof Polynomial) { expandMul((Polynomial) node); return; } PNodeI newTerms[] = new PNodeI[terms.length]; for(int i=0;i 1 else if(terms[i] instanceof PConstant) {} else { newTerms[pos] = terms[i]; ++pos; } } terms = newTerms; } PNodeI toPNode() throws ParseException { reduce(); if(terms.length ==0) return pc.zeroConstant; if(terms.length == 1) return terms[0]; return new Polynomial(pc,terms); } public String toString() { StringBuffer sb = new StringBuffer(); for(int i=0;i0) sb.append('+'); sb.append(terms[i].toString()); } return sb.toString(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/PNodeI.java0000644000000000000000000000333610615400352021202 0ustar rootroot/* @author rich * Created on 17-Dec-2004 */ package org.lsmp.djep.sjep; import org.nfunk.jep.*; /** * An element in a polynomial representation of an expression. * Provides the main routines for creating, comparing and manipulating polynomials. * * @author Rich Morris * Created on 17-Dec-2004 */ public interface PNodeI { /** Adds a node to this one. **/ public PNodeI add(PNodeI node) throws ParseException; /** Subtracts the argument from this. **/ public PNodeI sub(PNodeI node) throws ParseException; /** negates node i.e. -x */ public PNodeI negate() throws ParseException; /** Multiplies this by the argument. **/ public PNodeI mul(PNodeI node) throws ParseException; /** Divides this by the argument. **/ public PNodeI div(PNodeI node) throws ParseException; /** Raise this to the argument. **/ public PNodeI pow(PNodeI node) throws ParseException; /** inverts node i.e. 1/x */ public PNodeI invert() throws ParseException; /** True is nodes represent the same parse trees */ public boolean equals(PNodeI node); /** True is nodes represent the same parse trees */ public boolean equals(Object o); /** Compares this expression to argument. Uses a total ordering of expressions. Returns positive if this node comes after the argument. */ public int compareTo(PNodeI fun); /** Converts the node to standard JEP format. */ public Node toNode() throws ParseException; /** Produces a string representation of the argument. */ public String toString(); /** True if node represents zero */ public boolean isZero(); /** True if node represents one */ public boolean isOne(); /** complete expansion. (1+x)^2 --> 1+2*x+x^2 */ public PNodeI expand() throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/MutiableMonomial.java0000644000000000000000000000642110615400352023320 0ustar rootroot/* @author rich * Created on 23-Dec-2004 * * See LICENSE.txt for license information. */ package org.lsmp.djep.sjep; import org.nfunk.jep.*; /** * A mutable monomial representing a * x^i * y^j * ... * z^k. * There are no requirements that this is in a reduced form * so some powers can be zero. * * @author Rich Morris * Created on 23-Dec-2004 */ public class MutiableMonomial { PolynomialCreator pc; PConstant coeff; int length; PNodeI terms[]; PNodeI powers[]; /** * Note arrays parsed may be modified. */ public MutiableMonomial(PolynomialCreator pc,PConstant coeff,PNodeI nodes[],PNodeI pows[]) { this.pc = pc; this.coeff = coeff; length = nodes.length; terms = nodes; powers = pows; } public void mul(PConstant c) throws ParseException { coeff = (PConstant) coeff.mul(c); } public void div(PConstant c) throws ParseException { coeff = (PConstant) coeff.div(c); } public void mul(PNodeI term,PNodeI power) throws ParseException { for(int i=0;i 0) { newTerms[pos] = term; newPowers[pos] = power; ++pos; done = true; } newTerms[pos] = terms[i]; newPowers[pos] = powers[i]; ++pos; } if(!done) { newTerms[pos] = term; newPowers[pos] = power; ++pos; } length = length+1; terms = newTerms; powers = newPowers; } void power(PConstant c) throws ParseException { coeff = (PConstant) coeff.pow(c); for(int i=0;i 1 else if(terms[i].isOne()) {} // 1^x --> 1 else if(terms[i] instanceof PConstant && powers[i] instanceof PConstant) { coeff = (PConstant) coeff.mul(terms[i].pow(powers[i])); } else { newTerms[pos] = terms[i]; newPowers[pos] = powers[i]; ++pos; } } length = newLen; terms = newTerms; powers = newPowers; } PNodeI toPNode() throws ParseException { reduce(); if(length ==0) return coeff; if(coeff.isZero()) return pc.zeroConstant; return new Monomial(pc,coeff,terms,powers); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(coeff.toString()); for(int i=0;i -1 this > arg ---> 1 */ public int compareTo(POperator fun) { int res = op.getName().compareTo(op.getName()); if(res != 0) return res; if(args.length < fun.args.length) return -1; if(args.length > fun.args.length) return 1; for(int i=0;i -1, this > arg ---> 1 */ public int compareTo(PNodeI node) { if(node instanceof PConstant) return 1; if(node instanceof Monomial) { Monomial mon = (Monomial) node; for(int i=0;i=mon.vars.length) return 1; int res = vars[i].compareTo(mon.vars[i]); if(res!=0) return res; res = powers[i].compareTo(mon.powers[i]); if(res!=0) return res; } if(vars.length > mon.vars.length) return 1; if(vars.length < mon.vars.length) return -1; return coeff.compareTo(mon.coeff); } // compare with first term int res = vars[0].compareTo(node); if(res==0) res = powers[0].compareTo(pc.oneConstant); return res; } private boolean negativePower(PNodeI pow) { return( pow instanceof PConstant && ((PConstant) pow).isNegative()); } private void printPower(StringBuffer sb,PNodeI pow) { if(pow.isOne()) return; if(pow instanceof PConstant || pow instanceof PVariable || pow instanceof PFunction) { sb.append('^'); sb.append(pow.toString()); } else { sb.append("^("); sb.append(pow.toString()); sb.append(")"); } } public String toString() { StringBuffer sb = new StringBuffer(); boolean flag = false; if( coeff.isMinusOne()) sb.append('-'); else if( coeff.isOne()) { } else { sb.append(coeff.toString()); flag = true; } // first print positive and complicated powers int numNeg = 0; for(int i=0;i0) { if(!flag) sb.append('1'); if(numNeg > 1) sb.append("/("); else sb.append("/"); flag = false; for(int i=0;i 1) sb.append(")"); } return sb.toString(); } public Node toNode() throws ParseException { int nCoeff = coeff.isOne() ? 0 : 1; int numDivisors = 0; for(int i=0;i0) args[pos++]=coeff.toNode(); for(int i=0;i0) { PNodeI res = vars[i].expand(); for(int j=1;j<=intpow;++j) mp.expandMul(res); } else mp.expandMul(new Monomial(pc,pc.oneConstant,vars[i].expand(),powers[i])); } } else mp.expandMul(new Monomial(pc,pc.oneConstant,vars[i].expand(),powers[i])); } return mp.toPNode(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/PFunction.java0000644000000000000000000000400510615400352021763 0ustar rootroot/* @author rich * Created on 15-Dec-2004 */ package org.lsmp.djep.sjep; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.xjep.*; /** * Represents a function. * * @author Rich Morris * Created on 15-Dec-2004 */ public class PFunction extends AbstractPNode { String name; PostfixMathCommandI pfmc; XOperator op=null; PNodeI args[]; /** * */ public PFunction(PolynomialCreator pc,String name,PostfixMathCommandI pfmc,PNodeI args[]) { super(pc); this.name = name; this.pfmc = pfmc; this.args = args; } public boolean equals(PNodeI node) { if(!(node instanceof PFunction)) return false; PFunction fun = (PFunction) node; if(!name.equals(fun.name)) return false; if(args.length != fun.args.length) return false; for(int i=0;i -1 this > arg ---> 1 */ public int compareTo(PFunction fun) { int res = name.compareTo(fun.name); if(res != 0) return res; if(args.length < fun.args.length) return -1; if(args.length > fun.args.length) return 1; for(int i=0;i0) sb.append(','); sb.append(args[i].toString()); } sb.append(')'); return sb.toString(); } public Node toNode() throws ParseException { Node funargs[] = new Node[args.length]; for(int i=0;i 0; } catch(Exception e) { return false; } } public boolean isNegative() { try { return ((Double) value).compareTo((Double) pc.zero) < 0; } catch(Exception e) { return false; } } public boolean isInteger() { try { double val = ((Double) value).doubleValue(); return val == Math.floor(val); } catch(Exception e) { return false; } } public int intValue() { return ((Number) value).intValue(); } public Node toNode() throws ParseException { return pc.nf.buildConstantNode(value); } public int compareTo(PConstant c) { return ((Comparable) value).compareTo(c.value); } public boolean equals(PNodeI node) { if(node instanceof PConstant) return value.equals(((PConstant)node).value); return false; } public PNodeI expand() { return this; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/sjep/AbstractPNode.java0000644000000000000000000001164110615400352022553 0ustar rootroot/* @author rich * Created on 22-Dec-2004 * * See LICENSE.txt for license information. */ package org.lsmp.djep.sjep; import org.nfunk.jep.ParseException; /** * Default methods, when more specific methods do not work. * * @author Rich Morris * Created on 22-Dec-2004 */ public abstract class AbstractPNode implements PNodeI { /** A reference to the PolynomialCreator instance. */ protected PolynomialCreator pc; private AbstractPNode() {} public AbstractPNode(PolynomialCreator pc) { this.pc = pc; } /** * */ public PNodeI add(PNodeI node) throws ParseException { if(node.isZero()) return this; if(this.isZero()) return node; if(this.equals(node)) return new Monomial(pc,pc.twoConstant,this); if(node instanceof Polynomial) return node.add(this); if(this.compareTo(node) < 0) return new Polynomial(pc,new PNodeI[]{this,node}); // x+y return new Polynomial(pc,new PNodeI[]{node,this}); // x+y } public PNodeI sub(PNodeI node) throws ParseException { if(node.isZero()) return this; if(this.isZero()) return node.negate(); if(this.equals(node)) return pc.zeroConstant; if(node instanceof Polynomial) return node.negate().add(this); if(node instanceof PConstant) return this.add(node.negate()); return new Polynomial(pc,new PNodeI[]{this, new Monomial(pc,pc.minusOneConstant,node)}); // x-y } public PNodeI negate() throws ParseException { return new Monomial(pc,pc.minusOneConstant,this); } public PNodeI mul(PNodeI node) throws ParseException { if(node.isZero()) return pc.zeroConstant; if(node.isOne()) return this; if(this.equals(node)) return new Monomial(pc,pc.oneConstant,this,pc.twoConstant); if(node instanceof PConstant) return new Monomial(pc,(PConstant) node,this); if(node instanceof Monomial) return ((Monomial) node).mul(this); if(this instanceof PConstant) { // if(node instanceof Polynomial) // return ((Polynomial) node).mul((Constant) this); return new Monomial(pc,(PConstant) this,node); } if(this.compareTo(node) < 0) return new Monomial(pc, pc.oneConstant, new PNodeI[]{this,node}, new PNodeI[]{pc.oneConstant,pc.oneConstant}); return new Monomial(pc, pc.oneConstant, new PNodeI[]{node,this}, new PNodeI[]{pc.oneConstant,pc.oneConstant}); } public PNodeI div(PNodeI node) throws ParseException { if(this.equals(node)) return pc.oneConstant; if(node.isZero()) return pc.infConstant; if(node.isOne()) return this; if(node instanceof Monomial) return ((Monomial) node).invert().mul(this); if(this instanceof PConstant) return new Monomial(pc,(PConstant) this,node,pc.minusOneConstant); if(node instanceof PConstant) return new Monomial(pc,(PConstant) node.invert(),this); return new Monomial(pc, pc.oneConstant, new PNodeI[]{this,node}, new PNodeI[]{pc.oneConstant,pc.minusOneConstant}); } public PNodeI invert() throws ParseException { return pow(pc.minusOneConstant); // x^-1 } public PNodeI pow(PNodeI node) throws ParseException { if(node.isZero()) return pc.oneConstant; if(node.isOne()) return this; return new Monomial(pc, pc.oneConstant,this,node); } public boolean equals(PNodeI node) {return false; } public boolean isZero() {return false; } public boolean isOne() {return false; } /** this < arg ---> -1 this > arg ---> 1 */ public int compareTo(PNodeI node) { if(this instanceof PConstant) { if(node instanceof PConstant) return ((PConstant) this).compareTo((PConstant) node); return -1; } if(this instanceof PVariable) { if(node instanceof PConstant) return 1; if(node instanceof PVariable) return ((PVariable) this).compareTo((PVariable) node); if( node instanceof PFunction || node instanceof POperator) return -1; } if(this instanceof POperator) { if( node instanceof PConstant || node instanceof PVariable) return 1; if( node instanceof POperator) return ((POperator) this).compareTo((POperator) node); if( node instanceof PFunction) return -1; } if(this instanceof PFunction) { if( node instanceof PConstant || node instanceof PVariable || node instanceof PFunction) return 1; if( node instanceof PFunction) return ((PFunction) this).compareTo((PFunction) node); } if( this instanceof Monomial || this instanceof Polynomial) throw new IllegalStateException("Comparison failed "+this.getClass().getName()+" "+node.getClass().getName()); if(node instanceof Monomial) return -((Monomial) node).compareTo(this); if(node instanceof Polynomial) return -((Polynomial) node).compareTo(this); throw new IllegalArgumentException("Comparison failed "+this.getClass().getName()+" "+node.getClass().getName()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/jama/0000755000000000000000000000000010615400352017163 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/jama/package.html0000644000000000000000000000102510615400352021442 0ustar rootroot Wrapper for JAMA matrix operations for use in vectorJep and matrixJep. To add these functions to a VectorJep or MatrixJep instance use
    VectorJep j = new VectorJep();
    j.addStandardFunctions();
    ...
    JamaUtil.addStandardFunctions(j);
    
    This will add a rank, inverse and solve function. z = solve(x,y) solves x*z = y. @see org.lsmp.djep.vectorJep @see org.lsmp.djep.matrixJep @see http://math.nist.gov/javanumerics/jama/ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/jama/JamaUtil.java0000644000000000000000000000544010615400352021537 0ustar rootroot/* @author rich * Created on 15-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.jama; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.*; /** * Utility functions for adding Jama matrix functions. * To add these functions to a VectorJep or MatrixJep instance use *
     * VectorJep j = new VectorJep();
     * j.addStandardFunctions();
     * ...
     * JamaUtil.addStandardFunctions(j);
     * 
    * * @author Rich Morris * Created on 15-Feb-2005 * @see http://math.nist.gov/javanumerics/jama/ */ public final class JamaUtil { public static Jama.Matrix toJama(Matrix m) throws ParseException { int rows = m.getNumRows(); int cols = m.getNumCols(); Object data[][] = m.getEles(); double A[][] = new double[rows][cols]; for(int i=0;ihttp://math.nist.gov/javanumerics/jama/ * * @author Rich Morris * Created on 15-Feb-2005 */ public class Rank extends PostfixMathCommand implements UnaryOperatorI { public Rank() { this.numberOfParameters = 1; } public void run(Stack s) throws ParseException { Object o = s.pop(); if(!(o instanceof Matrix)) throw new ParseException("inverse: can only be applied to a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) o); int rank = m.rank(); s.push(new Integer(rank)); } public Dimensions calcDim(Dimensions ldim) { return Dimensions.ONE; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(lhs instanceof Matrix)) throw new ParseException("inverse: can only be applied to a matrix"); if(!(res instanceof Matrix)) throw new ParseException("inverse: result should be a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) lhs); int rank = m.rank(); res.setEle(0,new Integer(rank)); return res; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/jama/Inverse.java0000644000000000000000000000343610615400352021447 0ustar rootroot/* @author rich * Created on 15-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.jama; import java.util.Stack; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.vectorJep.function.*; /** * Find the inverses of a matrix. * Serves a wrapper around the Jama linear algebra function. * @see http://math.nist.gov/javanumerics/jama/ * * @author Rich Morris * Created on 15-Feb-2005 */ public class Inverse extends PostfixMathCommand implements UnaryOperatorI { public Inverse() { this.numberOfParameters = 1; } public void run(Stack s) throws ParseException { Object o = s.pop(); if(!(o instanceof Matrix)) throw new ParseException("inverse: can only be applied to a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) o); Jama.Matrix inv = m.inverse(); Matrix res = JamaUtil.fromJama(inv); s.push(res); } public Dimensions calcDim(Dimensions ldim) { int rows = ldim.getFirstDim(); int cols = ldim.getLastDim(); if(rows < cols) return Dimensions.valueOf(rows,rows); else if(rows > cols) return Dimensions.valueOf(cols,cols); else return ldim; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs) throws ParseException { if(!(lhs instanceof Matrix)) throw new ParseException("inverse: can only be applied to a matrix"); if(!(res instanceof Matrix)) throw new ParseException("inverse: result should be a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) lhs); Jama.Matrix inv = m.inverse(); JamaUtil.fromJama(inv,(Matrix) res); return res; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/jama/Solve.java0000644000000000000000000000373010615400352021121 0ustar rootroot/* @author rich * Created on 15-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.jama; import java.util.Stack; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.vectorJep.function.*; /** * z = solve(x,y) solves x*z = y where x,y,z are real matricies. * Serves a wrapper around the Jama linear algebra function. * @see http://math.nist.gov/javanumerics/jama/ * * @author Rich Morris * Created on 15-Feb-2005 */ public class Solve extends PostfixMathCommand implements BinaryOperatorI { public Solve() { this.numberOfParameters = 2; } public void run(Stack s) throws ParseException { Object r = s.pop(); if(!(r instanceof Matrix)) throw new ParseException("solve: can only be applied to a matrix"); Object l = s.pop(); if(!(l instanceof Matrix)) throw new ParseException("solve: can only be applied to a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) l); Jama.Matrix b = JamaUtil.toJama((Matrix) r); Jama.Matrix solve = m.solve(b); Matrix res = JamaUtil.fromJama(solve); s.push(res); } public Dimensions calcDim(Dimensions ldim,Dimensions rdim) { int rows = ldim.getLastDim(); int cols = rdim.getLastDim(); return Dimensions.valueOf(rows,cols); } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI lhs,MatrixValueI rhs) throws ParseException { if(!(lhs instanceof Matrix)) throw new ParseException("solve: can only be applied to a matrix"); if(!(res instanceof Matrix)) throw new ParseException("inverse: result should be a matrix"); Jama.Matrix m = JamaUtil.toJama((Matrix) lhs); Jama.Matrix b = JamaUtil.toJama((Matrix) rhs); Jama.Matrix solve = m.solve(b); JamaUtil.fromJama(solve,(Matrix) res); return res; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/0000755000000000000000000000000010615400352017221 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/DoNothingVisitor.java0000644000000000000000000000417110615400352023340 0ustar rootroot/* @author rich * Created on 16-Nov-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; /** * A Visitor which visits each node of a expression tree. * It returns the top node. * This visitor should be extended by Visitors which modify trees in place. * * @author Rich Morris * Created on 16-Nov-2003 */ public abstract class DoNothingVisitor implements ParserVisitor { /* * The following methods was used to facilitate * using visitors which implemented a interface * which subclassed ParserVisitor. * * If subclassed to extend to implement a different visitor * this method should be overwritten to ensure the correct * accept method is called. * This method simply calls the jjtAccept(ParserVisitor this,Object data) of node. * * We no longer need this as we use ParseVisitor everywhere, * but kept for future reference. * private Object nodeAccept(Node node, Object data) throws ParseException { return node.jjtAccept(this,data); } */ /** * Gets the result of visiting children of a array of nodes. */ protected Node[] acceptChildrenAsArray(Node node,Object data) throws ParseException { int n = node.jjtGetNumChildren(); Node children[] = new Node[n]; for(int i=0;i * XJep > Define("half",1,"x/2") * XJep > half(5) * *

    * Currently the Define function is handled in the preprocessing step *

     * Node n = xj.parse("Define(\"sumToX\",1,\"x*(x+1)/2\")");
     * Node preproc = xj.preprocess(n);
     * 
    * and preproc will be null if a Define statement is encountered. * This is probably a bug. * * TODO improve syntax. So can have Define("half(x)",x/2) * TODO work out how to simplify and evaluate Define statements which don't really have a value. * TODO fix parser so can do half(x) = x/2 * * @author Rich Morris * Created on 21-Jul-2005 */ public class Define extends PostfixMathCommand implements CommandVisitorI { private XJep xj; public Define(XJep xj) { this.numberOfParameters = -1; this.xj = xj; } /** * */ public Node process(Node node, Node[] children, XJep xjep) throws ParseException { String funName = null; int nArgs=-1; String def = null; if(children[0] instanceof ASTConstant) { Object val = ((ASTConstant) children[0]).getValue(); if(val instanceof String) { funName = (String) val; } else throw new ParseException("First argument to Define must be a string"); } if(children[1] instanceof ASTConstant) { Object val = ((ASTConstant) children[1]).getValue(); if(val instanceof Number) { nArgs = ((Number) val).intValue(); } else throw new ParseException("Second argument to Define must be a integer"); } if(children[2] instanceof ASTConstant) { Object val = ((ASTConstant) children[2]).getValue(); if(val instanceof String) { def = (String) val; } else throw new ParseException("Third argument to Define must be a string"); } MacroFunction mf = new MacroFunction(funName,nArgs,def,xj); xj.addFunction(funName,mf); return null; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/Min.java0000644000000000000000000000125110615400352022433 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.lsmp.djep.xjep.function; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * A min function Min(x^2,x,1,10) finds the min of x^2 with x running from 1 to 10. * * @author Rich Morris * Created on 10-Sept-2004 */ public class Min extends SumType { static Comparative comp = new Comparative(Comparative.LE); public Min() { super("Min"); } public Object evaluate(Object elements[]) throws ParseException { Object ret; ret = elements[0]; for(int i=1;i Functions for use in XJep. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/SumType.java0000644000000000000000000001065510615400352023326 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.lsmp.djep.xjep.function; import java.util.Stack; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * Base class for functions like Sum(x^2,x,1,10) which finds the sum of x^2 with x running from 1 to 10. * The first argument should be an equation, the second argument is a variable name, * the third argument is the min value, the forth is the max value and the * fifth argument (if present, default 1) is the increment to use. * Sub classes should implement the *
    public abstract Object evaluate(Object elements[]) throws ParseException;
    * method, which is passed an array of the value * @author Rich Morris * Created on 10-Sept-2004 */ public abstract class SumType extends PostfixMathCommand implements CallbackEvaluationI { /** The name of the function, use in error reporting. */ protected String name; public SumType(String funName) { numberOfParameters = -1; name = funName; } public SumType() { numberOfParameters = -1; } public boolean checkNumberOfParameters(int n) { return (n==4||n==5); } /** * Evaluates the operator in given context. * Typically does not need to be sub-classed as the other evaluate methods are more useful. This method just checks the arguments. */ public Object evaluate(Node node,EvaluatorI pv) throws ParseException { int numParams = node.jjtGetNumChildren(); if(!checkNumberOfParameters(numParams)) throw new ParseException(name+": called with invalid number of parameters: "+numParams+" it should be either 4 or 5."); Node varNode = node.jjtGetChild(1); Variable var=null; if(varNode instanceof ASTVarNode) var = ((ASTVarNode) varNode).getVar(); else throw new ParseException(name+": second argument should be a variable"); Object minObj = pv.eval(node.jjtGetChild(2)); double min; if(minObj instanceof Number) min = ((Number ) minObj).doubleValue(); else throw new ParseException(name+": third argument (min) should evaluate to a number it is "+minObj.toString()); Object maxObj = pv.eval(node.jjtGetChild(3)); double max; if(maxObj instanceof Number) max = ((Number ) maxObj).doubleValue(); else throw new ParseException(name+": forth argument (max) should evaluate to a number it is "+minObj.toString()); if(min>max) throw new ParseException(name+": min value should be smaller than max value they are "+min+" and "+max+"."); if(numParams == 5) { //node.jjtGetChild(3).jjtAccept(pv,data); //checkStack(stack); // check the stack //Object incObj = stack.pop(); Object incObj = pv.eval(node.jjtGetChild(4)); double inc; if(incObj instanceof Number) inc = ((Number ) incObj).doubleValue(); else throw new ParseException(name+": fifth argument (steps) should evaluate to a number it is "+minObj.toString()); return evaluate(node.jjtGetChild(0),var,min,max,inc,pv); } return evaluate(node.jjtGetChild(0),var,min,max,1.0,pv); } /** Evaluates the node by repeatibly setting the value of the variable from min to max, and calculating the value of the first argument. * Sub classes generally do not need to implement this method as * {@link #evaluate(Object[])} * is more useful. If they do they should follow the pattern used here. * * @param node * @param var * @param min * @param max * @param inc * @param pv * @return the result of evaluation * @throws ParseException */ public Object evaluate( Node node, Variable var, double min, double max, double inc, EvaluatorI pv) throws ParseException { int i=0; double val; Object[] res=new Object[(int) ((max-min)/inc)+1]; for(i=0,val=min;val<=max;++i,val=min+i*inc) { var.setValue(new Double(val)); res[i] = pv.eval(node); } Object ret = evaluate(res); return ret; } /** Evaluates the function given the set of y values. * For example for Sum(x^2,x,1,5) the function will be passed the array [1,4,9,16,25]. * * @param elements the y values * @return the result of the function * @throws ParseException */ public abstract Object evaluate(Object elements[]) throws ParseException; /** * run method. Should not be called. */ public void run(Stack s) throws ParseException { throw new ParseException(name+": run method called should not normally happen."); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/XAssign.java0000644000000000000000000000314310615400352023266 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.lsmp.djep.xjep.function; import org.lsmp.djep.xjep.CommandVisitorI; import org.lsmp.djep.xjep.TreeUtils; import org.lsmp.djep.xjep.XJep; import org.lsmp.djep.xjep.XVariable; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * An assignment operator so we can do * x=3+4. * This function implements the SpecialEvaluationI interface * so that it handles seting the value of a variable. * @author Rich Morris * Created on 18-Nov-2003 */ public class XAssign extends Assign implements CommandVisitorI { public XAssign() {} { numberOfParameters = 2; } /** * In the pre-process stage, set the equation of the lhs variable to the rhs equation. */ public Node process(Node node,Node children[],XJep xjep) throws ParseException { if(node.jjtGetNumChildren()!=2) throw new ParseException("Assignment opperator must have 2 operators."); // evaluate the value of the righthand side. Left on top of stack // Set the value of the variable on the lhs. Node lhsNode = children[0]; if(lhsNode instanceof ASTVarNode) { ASTVarNode vn = (ASTVarNode) lhsNode; XVariable var = (XVariable) vn.getVar(); var.setEquation(xjep.deepCopy(children[1])); TreeUtils.copyChildrenIfNeeded(node,children); return node; } else if(lhsNode instanceof ASTFunNode && ((ASTFunNode) lhsNode).getPFMC() instanceof LValueI) { //TODO TreeUtils.copyChildrenIfNeeded(node,children); return node; } throw new ParseException("Assignment should have a variable for the lhs."); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/MinArg.java0000644000000000000000000000214210615400352023065 0ustar rootroot/* @author rich * Created on 10-Sep-2004 */ package org.lsmp.djep.xjep.function; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * @author Rich Morris * Created on 10-Sep-2004 */ public class MinArg extends SumType { static Comparative comp = new Comparative(Comparative.LE); public MinArg() { super("MinArg"); } public Object evaluate(Object[] elements) throws ParseException { throw new ParseException("MinArg: call to evaluate(Object[] elements) should not have happened."); } public Object evaluate( Node node, Variable var, double min, double max, double inc, EvaluatorI pv) throws ParseException { int i=0; double val; Object minVal=null; Object minArg=null; for(i=0,val=min;val<=max;++i,val=min+i*inc) { Object curArg = new Double(val); var.setValue(curArg); Object res = pv.eval(node); if(i==0) { minVal = res; minArg = curArg; } else if(comp.lt(res,minVal)) { minVal = res; minArg = curArg; } } return minArg; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/ToBase.java0000644000000000000000000001312010615400352023063 0ustar rootroot/* @author rich * Created on 02-May-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.xjep.function; import java.util.Stack; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommand; /** * Convert a number to a string in a given base. * toBase(val,12) converts to base 12 numbers. * toBase(val,16,3) converts to base 12 with 3 hex digits after decimal place. * toHex(val) converts to base 16 * toHex(val,3) converts to base 16 with 3 hex digits after decimal place. * A prefix can be specified in the constructor. If set * this will be appended to the number (after minus sign for negative values). * * @author Rich Morris * Created on 02-May-2005 * @see java.lang.Long#toString(long, int) */ public class ToBase extends PostfixMathCommand { int globalBase=-1; String prefix=""; /** * Constructor where base is specified as a function argument. */ public ToBase() { super(); this.numberOfParameters = -1; } /** * Constructor with specified base. * @param base the base to use * @throws IllegalArgumentException if base is < 2 or > 36 */ public ToBase(int base) { if(base < Character.MIN_RADIX || base > Character.MAX_RADIX) throw new IllegalArgumentException("base must be between "+Character.MIN_RADIX+" and "+Character.MIN_RADIX); globalBase = base; numberOfParameters = -1; } /** * Constructor with specified base and a given prefix. * For example 0x to proceed hexadecimal numbers. * @param base the base to use * @param prefix the string to prefix numbers with. * @throws IllegalArgumentException if base is < 2 or > 36 */ public ToBase(int base,String prefix) { if(base < Character.MIN_RADIX || base > Character.MAX_RADIX) throw new IllegalArgumentException("base must be between "+Character.MIN_RADIX+" and "+Character.MIN_RADIX); globalBase = base; numberOfParameters = -1; this.prefix = prefix; } public boolean checkNumberOfParameters(int n) { if(globalBase == -1) { return (n==2||n==3); } else {return (n==1||n==2); } } public void run(Stack s) throws ParseException { int narg = curNumberOfParameters; int digits=0; int base = 0; if(!checkNumberOfParameters(narg)) throw new ParseException("toBase: can only have 1,2 or 3 arguments"); if(narg==3 || (globalBase != -1 && narg==2)) { try { digits = ((Number) s.pop()).intValue(); } catch(ClassCastException e) { throw new ParseException("toBase: last argument should be an integer"); } } if(globalBase == -1) { Object rhs = s.pop(); if(rhs instanceof Number) base = ((Number) rhs).intValue(); else throw new ParseException("toBase: second argument should be an integer"); } else { base = globalBase; } if(base < Character.MIN_RADIX || base > Character.MAX_RADIX) throw new ParseException("base must be between "+Character.MIN_RADIX+" and "+Character.MIN_RADIX); Object lhs = s.pop(); String res=null; if(lhs instanceof Integer || lhs instanceof Short || lhs instanceof Long) res = toBase(((Number) lhs).longValue(),base); else if(lhs instanceof Float || lhs instanceof Double || lhs instanceof Number) res = toBase(((Number) lhs).doubleValue(),base,digits); else throw new ParseException("toBase: Cannot convert object of type "+lhs.getClass().getName()); s.push(res); } /** * Converts a number to a give base. * @param num number to convert * @param base base to use * @return String representation * @throws IllegalArgumentException if base is < 2 or > 36 */ public String toBase(long num,int base) { if(base < Character.MIN_RADIX || base > Character.MAX_RADIX) throw new IllegalArgumentException("base must be between "+Character.MIN_RADIX+" and "+Character.MIN_RADIX); if(num<0) return '-' + prefix + Long.toString(num,base); return prefix + Long.toString(num,base); } /** * Converts a number to a give base. * @param val number to convert * @param base base to use * @param digits number of digits after decimal place * @return String representation * @throws IllegalArgumentException if base is < 2 or > 36 */ public String toBase(double val,int base,int digits) { if(base < Character.MIN_RADIX || base > Character.MAX_RADIX) throw new IllegalArgumentException("base must be between "+Character.MIN_RADIX+" and "+Character.MIN_RADIX); StringBuffer sb = new StringBuffer(); if(val<0.0) { val = -val; sb.append('-'); } sb.append(prefix); val = val * Math.pow(base,digits); long round = Math.round(val); String s = Long.toString(round,base); if(s.length()<=digits) { sb.append("0."); for(int i=0;i0) { sb.append(s); sb.insert(sb.length()-digits,'.'); } else sb.append(s); return sb.toString(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/MaxArg.java0000644000000000000000000000214010615400352023065 0ustar rootroot/* @author rich * Created on 10-Sep-2004 */ package org.lsmp.djep.xjep.function; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * @author Rich Morris * Created on 10-Sep-2004 */ public class MaxArg extends SumType { static Comparative comp = new Comparative(Comparative.LE); public MaxArg() { super("MaxArg"); } public Object evaluate(Object[] elements) throws ParseException { throw new ParseException("MaxArg: call to evaluate(Object[] elements) should not have happened."); } public Object evaluate( Node node, Variable var, double min, double max, double inc, EvaluatorI pv) throws ParseException { int i=0; double val; Object maxVal=null; Object maxArg=null; for(i=0,val=min;val<=max;++i,val=min+i*inc) { Object curArg = new Double(val); var.setValue(curArg); Object res = pv.eval(node); if(i==0) { maxVal = res; maxArg = curArg; } else if(comp.gt(res,maxVal)) { maxVal = res; maxArg = curArg; } } return maxArg; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/function/Simpson.java0000644000000000000000000000214110615400352023337 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.lsmp.djep.xjep.function; import org.nfunk.jep.*; /** * The Simpson rule for approximation to a definite integral. * h * (y0 + yn + 4(y1+y3+...+y_(n-1)) + 2(y2+y4+...+y_(n-2)) ) /3 * where h = (xn-x0)/n, yi = f(xi) * Simpson(x^2,x,0,10,0.5) * finds an approximation for int(x^2) where x runs from 0 to 10 in steps of * h=0.5. * * @author Rich Morris * Created on 10-Sept-2004 */ public class Simpson extends Trapezium { public Simpson() { super("Simpson"); } public Object evaluate(Object elements[]) throws ParseException { if(elements.length % 2 != 1 || elements.length <2) throw new ParseException("Simpson: there should be an odd number of ordinates, its"+elements.length); Object ret = add.add(elements[0],elements[elements.length-1]); for(int i=1;i Simplification, deep copying, printing and various utilities. @see XJep documentation jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/XOperator.java0000644000000000000000000002141710615400352022014 0ustar rootroot/* @author rich * Created on 03-Aug-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.function.PostfixMathCommandI; import org.nfunk.jep.*; /** * An Operator with additional information about its commutativity etc. *

    * Operators have a number of properties: *

      *
    • A symbol or name of the operator "+". *
    • The number of arguments NO_ARGS 0, UNARY 1 (eg UMINUS -x), * BINARY 2 (eq x+y), and NARY either 3 ( a>b ? a : b) or * unspecified like a list [x,y,z,w]. *
    • The binging of the operator, LEFT 1+2+3 -> (1+2)+3 or RIGHT 1=2=3 -> 1=(2=3). *
    • Whether the operator is ASSOCIATIVE or COMMUTATIVE. *
    • The precedence of the operators + has a higher precedence than *. *
    • For unary opperators they can either be PREFIX like -x or SUFIX like x%. *
    • Comparative operators can be REFLEXIVE, SYMMETRIC, TRANSITIVE or EQUIVILENCE which has all three properties. *
    • A reference to a PostfixtMathCommandI object which is used to evaluate an equation containing the operator. *
    * various is... and get... methods are provided to query the properties of the opperator. * * @author Rich Morris * Created on 19-Oct-2003 */ public class XOperator extends Operator { /** No arguments to operator */ public static final int NO_ARGS=0; /** Unary operators, such as -x !x ~x */ public static final int UNARY=1; /** Binary operators, such as x+y, x>y */ public static final int BINARY=2; /** Trinary ops such as ?: and or higher like [x,y,z,w] */ public static final int NARY=3; /** Left binding like +: 1+2+3 -> (1+2)+3 */ public static final int LEFT=4; /** Right binding like =: 1=2=3 -> 1=(2=3) */ public static final int RIGHT=8; /** Associative operators x*(y*z) == (x*y)*z . */ public static final int ASSOCIATIVE=16; /** Commutative operators x*y = y*x. */ public static final int COMMUTATIVE=32; /** Reflecive relations x=x for all x. */ public static final int REFLEXIVE=64; /** Symmetric relation x=y implies y=x. */ public static final int SYMMETRIC=128; /** Transative relations x=y and y=z implies x=z */ public static final int TRANSITIVE=256; /** Equivilence relations = reflexive, transative and symetric. */ public static final int EQUIVILENCE=TRANSITIVE+REFLEXIVE+SYMMETRIC; /** prefix operators -x **/ public static final int PREFIX=512; /** postfix operators x%, if neiter prefix and postif then infix, if both trifix like x?y:z **/ public static final int SUFIX=1024; /** self inverse operators like -(-x) !(!x) **/ public static final int SELF_INVERSE=2048; /** composite operators, like a-b which is a+(-b) **/ public static final int COMPOSITE=4096; /** For non commutative operators printing can be determined by the left or right binding. * For example (a-b)-c is printed as a-b-c. * But a/b/c could be ambiguous so (a/b)/c is printed with brackets. */ public static final int USE_BINDING_FOR_PRINT=8192; /** flags for type of operator */ private int flags; /** construct a new operator. * * @param name printable name of operator * @param pfmc postfix math command for opperator * @param flags set of flags defining the porperties of the operator. */ public XOperator(String name,PostfixMathCommandI pfmc,int flags) { super(name,pfmc); this.flags = flags; } /** * Allows a given precedent to be set. * @param name * @param pfmc * @param flags * @param precedence */ public XOperator(String name,PostfixMathCommandI pfmc,int flags,int precedence) { this(name,pfmc,flags); this.precedence=precedence; } /** construct a new operator, with a different name and symbol * * @param name name of operator, must be unique, used when describing operator * @param symbol printable name of operator, used for printing equations * @param pfmc postfix math command for opperator * @param flags set of flags defining the porperties of the operator. */ public XOperator(String name,String symbol,PostfixMathCommandI pfmc,int flags) { super(name,symbol,pfmc); this.flags = flags; } /** * Allows a given precedent to be set. * @param name * @param pfmc * @param flags * @param precedence */ public XOperator(String name,String symbol,PostfixMathCommandI pfmc,int flags,int precedence) { super(name,symbol,pfmc); this.precedence=precedence; this.flags=flags; } public XOperator(Operator op,int flags,int precedence) { this(op.getName(),op.getSymbol(),op.getPFMC(),flags,precedence); } public XOperator(Operator op,int flags) { this(op.getName(),op.getSymbol(),op.getPFMC(),flags); } /** Creates a new XOperators with same flags and precedance as argument. */ // public XOperator(XOperator op,PostfixMathCommandI pfmc) // { // this(op.getName(),op.getSymbol(),op.getPFMC(),op.flags,op.precedence); // } /** precedence of operator, 0 is most tightly bound, so prec("*") < prec("+"). */ private int precedence = -1; public final int getPrecedence() {return precedence;} protected final void setPrecedence(int i) {precedence = i;} /** Operators this is distributative over **/ private Operator distribOver[] = new Operator[0]; protected final void setDistributiveOver(Operator op) { int len = distribOver.length; Operator temp[] = new Operator[len+1]; for(int i=0;i (x+y)+z or * Operator.RIGHT x=y=z -> x=(y=z). */ public final int getBinding() { return (flags & (LEFT | RIGHT)); } public final boolean isAssociative() {return ((flags & ASSOCIATIVE) == ASSOCIATIVE);} public final boolean isCommutative() { return ((flags & COMMUTATIVE) == COMMUTATIVE);} public final boolean isBinary() { return ((flags & 3) == BINARY); } public final boolean isUnary() { return ((flags & 3) == UNARY); } public final boolean isNary() { return ((flags & 3) == NARY); } public final int numArgs() { return (flags & 3); } public final boolean isTransitive() { return ((flags & TRANSITIVE) == TRANSITIVE); } public final boolean isSymmetric() { return ((flags & SYMMETRIC) == SYMMETRIC); } public final boolean isReflexive() { return ((flags & REFLEXIVE) == REFLEXIVE); } public final boolean isEquivilence() {return ((flags & EQUIVILENCE) == EQUIVILENCE); } public final boolean isPrefix() {return ((flags & PREFIX) == PREFIX); } public final boolean isSufix() {return ((flags & SUFIX) == SUFIX); } public final boolean isComposite() {return ((flags & COMPOSITE) == COMPOSITE); } public final boolean isSelfInverse() {return ((flags & SELF_INVERSE) == SELF_INVERSE); } public final boolean useBindingForPrint() {return ((flags & USE_BINDING_FOR_PRINT) == USE_BINDING_FOR_PRINT); } /** returns a verbose representation of the operator and all its properties. **/ public String toFullString() { StringBuffer sb = new StringBuffer(); sb.append("Operator: \""+getSymbol()+"\""); if(!getName().equals(getSymbol())) sb.append(" "+getName()); switch(numArgs()){ case 0: sb.append(" no arguments,"); break; case 1: sb.append(" unary,"); break; case 2: sb.append(" binary,"); break; case 3: sb.append(" variable number of arguments,"); break; } if(isPrefix() && isSufix()) sb.append(" trifix,"); else if(isPrefix()) sb.append(" prefix,"); else if(isSufix()) sb.append(" sufix,"); else sb.append(" infix,"); if(getBinding()==LEFT) sb.append(" left binding,"); else if(getBinding()==RIGHT) sb.append(" right binding,"); if(isAssociative()) sb.append(" associative,"); if(isCommutative()) sb.append(" commutative,"); sb.append(" precedence "+getPrecedence()+","); if(isEquivilence()) sb.append(" equivilence relation,"); else { if(isReflexive()) sb.append(" reflexive,"); if(isSymmetric()) sb.append(" symmetric,"); if(isTransitive()) sb.append(" transitive,"); } sb.setCharAt(sb.length()-1,'.'); return sb.toString(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/NodeFactory.java0000644000000000000000000001410710615400352022304 0ustar rootroot/* @author rich * Created on 16-Nov-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * This class is used to create nodes of specified types. * It can be sub-classed to change the nature of how nodes * are constructed. Generally there are two methods for creating * nodes, methods which take an existing node and methods which * take the components. * * @author Rich Morris * Created on 16-Nov-2003 */ public class NodeFactory { private XJep xj; public NodeFactory(XJep xj) {this.xj=xj;} private NodeFactory() {} /** * Sets the children of node to be those specified in array. * @param node the node whose children will be set. * @param children an array of nodes which will be the children of the node. */ public void copyChildren(Node node,Node children[]) { int nchild = children.length; node.jjtOpen(); for(int i=0;i * JEP j = ...; Node in = ...; * SimplificationVisitor sv = new SimplificationVisitor(tu); * Node out = sv.simplify(in); * * *

    * Its intended to completly rewrite this class to that simplification * rules can be specified by strings in a way similar to DiffRulesI. * It also would be nice to change the rules depending on the type of * arguments, for example matrix multiplication is not commutative. * But some of the in built rules exploit commutativity. * * @author Rich Morris * Created on 20-Jun-2003 * TODO cope with 'a - (-1) * b' * TODO cope with '0 - uminus(b)' * TODO cope with simplifying complex numbers */ public class SimplificationVisitor extends DoNothingVisitor { private NodeFactory nf; private OperatorSet opSet; private TreeUtils tu; public SimplificationVisitor() { } /** must be implemented for subclasses. **/ public Node simplify(Node node,XJep xjep) throws ParseException,IllegalArgumentException { nf = xjep.getNodeFactory(); opSet = xjep.getOperatorSet(); tu = xjep.getTreeUtils(); if (node == null) return null; // throw new IllegalArgumentException( // "topNode parameter is null"); Node res = (Node) node.jjtAccept(this,null); return res; } /** First create a new node and then simplify it. */ public Node simplifyBuiltOperatorNode(Operator op,Node lhs,Node rhs) throws ParseException { ASTFunNode res = nf.buildOperatorNode(op,lhs,rhs); Node res2 = simplifyOp(res,new Node[]{lhs,rhs}); return res2; } /** * Simplifies expressions like 2+(3+x) or (2+x)+3 * * @param op the root operator * @param lhs the left hand side node * @param rhs the right hand side node * @return null if no rewrite happens or top node or top node of new tree. * @throws ParseException */ public Node simplifyTripple(XOperator op,Node lhs,Node rhs) throws ParseException { XOperator rootOp; if(op.isComposite()) rootOp = (XOperator) op.getRootOp(); else rootOp = op; if(op.isCommutative() && tu.isConstant(rhs)) { return simplifyBuiltOperatorNode(op,rhs,lhs); } if(tu.isConstant(lhs) && tu.isBinaryOperator(rhs)) { Node rhsChild1 = rhs.jjtGetChild(0); Node rhsChild2 = rhs.jjtGetChild(1); XOperator rhsOp = (XOperator) ((ASTFunNode) rhs).getOperator(); XOperator rhsRoot; if(rhsOp.isComposite()) rhsRoot = (XOperator) rhsOp.getRootOp(); else rhsRoot = rhsOp; if(tu.isConstant(rhsChild1)) { XOperator op2 = rootOp; if(op == rhsOp) op2 = rootOp; else op2 = (XOperator) rootOp.getBinaryInverseOp(); // 2 + ~( 3 + ~x ) -> (2+~3) + ~~x if(rootOp == rhsRoot && rootOp.isAssociative()) { Node newnode = simplifyBuiltOperatorNode(op2, nf.buildConstantNode(op,lhs,rhsChild1),rhsChild2); return newnode; } if(op.isDistributiveOver(rhsRoot)) // 2 * (3 + ~x) -> (2 * 3) + ~(2 @ x) { Node newnode = simplifyBuiltOperatorNode(rhsOp, nf.buildConstantNode(op,lhs,rhsChild1), simplifyBuiltOperatorNode(op,lhs,rhsChild2)); return newnode; } } if(tu.isConstant(rhsChild2)) { // 2 + ~( x + ~3 ) -> (2 + ~~3) + ~x Operator op2 = rootOp; if(op == rhsOp) op2 = rootOp; else op2 = rootOp.getBinaryInverseOp(); if(rootOp == rhsRoot && rootOp.isCommutative() && rootOp.isAssociative()) { Node newnode = simplifyBuiltOperatorNode(op, nf.buildConstantNode(op2,lhs,rhsChild2),rhsChild1); return newnode; } if(op.isDistributiveOver(rhsRoot)) // 2 * (x + ~3) -> (2 * x) + ~(2 * 3) { Node newnode = simplifyBuiltOperatorNode(rhsOp, simplifyBuiltOperatorNode(op,lhs,rhsChild1), nf.buildConstantNode(op,lhs,rhsChild2)); return newnode; } } } if(tu.isBinaryOperator(lhs) && tu.isConstant(rhs)) { Node lhsChild1 = lhs.jjtGetChild(0); Node lhsChild2 = lhs.jjtGetChild(1); XOperator lhsOp = (XOperator) ((ASTFunNode) lhs).getOperator(); XOperator lhsRoot; if(lhsOp.isComposite()) lhsRoot = (XOperator) lhsOp.getRootOp(); else lhsRoot = lhsOp; if(tu.isConstant(lhsChild1)) { // (2 + ~x) + ~3 -> (2 + ~3) + ~x if(rootOp == lhsRoot && rootOp.isAssociative() && rootOp.isCommutative()) { Node newnode = simplifyBuiltOperatorNode(lhsOp, nf.buildConstantNode(op,lhsChild1,rhs), lhsChild2); return newnode; } // (2 + ~x) * 3 --> (2*3) +~ (x*3) if(op.isDistributiveOver(lhsRoot)) { Node newnode = simplifyBuiltOperatorNode(lhsOp, nf.buildConstantNode(op,lhsChild1,rhs), simplifyBuiltOperatorNode(op,lhsChild2,rhs)); return newnode; } } if(tu.isConstant(lhsChild2)) { // (x + ~2) + !3 -> x + (~2 + !3) -> x + ~(2+~!3) // (x*2)*3 -> x*(2*3), (x/2)*3 -> x/(2/3) // (x*2)/3 -> x*(2/3), (x/2)/3 -> x/(2*3) if(rootOp == lhsRoot && rootOp.isAssociative()) { Operator op2 = rootOp; if(op == lhsOp) op2 = rootOp; else op2 = rootOp.getBinaryInverseOp(); Node newnode = simplifyBuiltOperatorNode(lhsOp, lhsChild1, nf.buildConstantNode(op2,lhsChild2,rhs)); return newnode; } // (x + ~2) * 3 -> (x*3) + ~(2*3) if(op.isDistributiveOver(lhsRoot)) { Node newnode = simplifyBuiltOperatorNode(lhsOp, simplifyBuiltOperatorNode(op,lhsChild1,rhs), nf.buildConstantNode(op,lhsChild2,rhs)); return newnode; } } } return null; } /** * Simplifies an addition. Performs the following rules *

       * 0+x -> x
       * x+0 -> x
       * m+n -> (m+n) where m,n are numbers
       * x - (-2) -> x + 2 for any negative number -2
       * x + (-2) -> x - 2 for any negative number -2
       * 2 +/- ( 3 +/- x ) ->  (2 +/- 3 ) +/- x and similar
       * 
    */ public Node simplifyAdd(Node lhs,Node rhs) throws ParseException { if(tu.isInfinity(lhs)) { // Inf + Inf -> NaN TODO not correct for signed infinity if(tu.isInfinity(rhs)) return nf.buildConstantNode(tu.getNAN()); // Inf + x -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); } if(tu.isInfinity(rhs)) // x + Inf -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); if(tu.isZero(lhs)) // 0+x -> x return rhs; if(tu.isZero(rhs)) // x + 0 -> x return lhs; if(tu.isNegative(lhs)) // -3 + x -> x - 3 { Node newnode = nf.buildOperatorNode(opSet.getSubtract(), rhs, nf.buildConstantNode(opSet.getUMinus(),lhs)); return newnode; } if(tu.isNegative(rhs)) // x + -3 -> x - 3 { Node newnode = nf.buildOperatorNode(opSet.getSubtract(), lhs, nf.buildConstantNode(opSet.getUMinus(),rhs)); return newnode; } return null; // return nf.buildOperatorNode(node.getOperator(),lhs,dimKids[1]); // return opSet.buildAddNode(lhs,dimKids[1]); } /** * Simplifies a subtraction. Performs the following rules *
       * 0-x -> 0-x
       * x-0 -> x
       * m-n -> (m-n) where m,n are numbers
       * x - (-2) -> x + 2 for any negative number -2
       * x + (-2) -> x - 2 for any negative number -2
       * 2 +/- ( 3 +/- x ) ->  (2 +/- 3 ) +/- x and similar
       * 
    * @param lhs the left hand side * @param rhs the right hand side */ public Node simplifySubtract(Node lhs,Node rhs) throws ParseException { if(tu.isInfinity(lhs)) { // Inf + Inf -> NaN TODO not correct for signed infinity if(tu.isInfinity(rhs)) return nf.buildConstantNode(tu.getNAN()); // Inf + x -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); } if(tu.isInfinity(rhs)) // x + Inf -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); if(tu.isZero(rhs)) // x - 0 -> x return lhs; // TODO implement 0 - x -> -(x) if(tu.isNegative(rhs)) // x - (-2) -> x + 2 { Node newnode = simplifyBuiltOperatorNode(opSet.getAdd(), lhs, nf.buildConstantNode(opSet.getUMinus(),rhs)); return newnode; } if(tu.getOperator(rhs)==opSet.getUMinus()) { Node newnode = simplifyBuiltOperatorNode(opSet.getAdd(), lhs, rhs.jjtGetChild(0)); return newnode; } /* if(tu.getOperator(rhs)==opSet.getMultiply()) { if(tu.isNegative(rhs.jjtGetChild(0))) // a - (-2) * b -> a + 2 * b { Node newnode = simplifyBuiltOperatorNode( opSet.getAdd(), lhs, nf.buildOperatorNode( opSet.getMultiply(), nf.buildConstantNode( opSet.getUMinus(),rhs.jjtGetChild(0)), rhs.jjtGetChild(1))); return newnode; } } */ return null; // return nf.buildOperatorNode(((ASTOpNode) node).getOperator(),lhs,rhs); // return tu.buildSubtract(lhs,rhs); } /** * Simplifies a multiplication. *
       * 0 * Inf -> NaN
       * 0 * x -> 0
       * x * 0 -> 0
       * 1 * x -> x
       * x * 1 -> x
       * Inf * x -> Inf
       * x * Inf -> Inf
       * 2 * ( 3 * x) -> (2*3) * x
       * and similar.
       * 
    */ public Node simplifyMultiply(Node child1,Node child2) throws ParseException { if(tu.isZero(child1)) { // 0*Inf -> NaN if(tu.isInfinity(child2)) return nf.buildConstantNode(tu.getNAN()); // 0*x -> 0 return nf.buildConstantNode(tu.getZERO()); } if(tu.isZero(child2)) { // Inf*0 -> NaN if(tu.isInfinity(child1)) return nf.buildConstantNode(tu.getNAN()); // 0 * x -> 0 return nf.buildConstantNode(tu.getZERO()); } if(tu.isInfinity(child1)) // Inf * x -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); if(tu.isInfinity(child2)) // x * Inf -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); if(tu.isOne(child1)) // 1*x -> x return child2; if(tu.isOne(child2)) // x*1 -> x return child1; if(tu.isMinusOne(child1)) // -1*x -> -x { Node newnode = nf.buildOperatorNode(opSet.getUMinus(),child2); return newnode; } if(tu.isMinusOne(child2)) // x*-1 -> -x { Node newnode = nf.buildOperatorNode(opSet.getUMinus(),child1); return newnode; } return null; // return nf.buildOperatorNode(((ASTOpNode) node).getOperator(),child1,child2); // return tu.buildMultiply(child1,child2); } /** * Simplifies a division. *
    	 * 0/0 -> NaN
    	 * 0/Inf -> Inf
    	 * 0/x -> Inf
    	 * x/0 -> Inf
    	 * x/1 -> x
    	 * Inf / x -> Inf
    	 * x / Inf -> 0
    	 * 2 / ( 3 * x) -> (2/3) / x
    	 * 2 / ( x * 3) -> (2/3) / x
    	 * 2 / ( 3 / x) -> (2/3) * x
    	 * 2 / ( x / 3) -> (2*3) / x
    	 * (2 * x) / 3 -> (2/3) * x
    	 * (x * 2) / 3 -> x * (2/3)
    	 * (2 / x) / 3 -> (2/3) / x
    	 * (x / 2) / 3 -> x / (2*3)
    	 * 
    */ public Node simplifyDivide(Node child1,Node child2) throws ParseException { if(tu.isZero(child2)) { if(tu.isZero(child1)) // 0/0 -> NaN return nf.buildConstantNode(tu.getNAN()); // x/0 -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); } if(tu.isZero(child1)) { // 0/x -> 0 return child1; } //if(tu.isOne(child1)) // 1/x -> 1/x // return child2; if(tu.isOne(child2)) // x/1 -> x return child1; if(tu.isInfinity(child1)) // Inf / x -> Inf return nf.buildConstantNode(tu.getPositiveInfinity()); if(tu.isInfinity(child2)) // x / Inf -> 0 return nf.buildConstantNode(tu.getZERO()); return null; // return nf.buildOperatorNode(((ASTOpNode) node).getOperator(),child1,child2); // return opSet.buildDivideNode(child1,child2); } /** Simplify a power. *
    	 * x^0 -> 1
    	 * x^1 -> x
    	 * 0^0 -> NaN
    	 * 0^x -> 0
    	 * 1^x -> 1
    	 * 
    */ public Node simplifyPower(Node child1,Node child2) throws ParseException { if(tu.isZero(child1)) { if(tu.isZero(child2)) // 0^0 -> NaN return nf.buildConstantNode(tu.getNAN()); // 0^x -> 0 return nf.buildConstantNode(tu.getZERO()); } if(tu.isZero(child2)) // x^0 -> 1 return nf.buildConstantNode(tu.getONE()); if(tu.isOne(child1)) // 1^x -> 1 return nf.buildConstantNode(tu.getONE()); if(tu.isOne(child2)) // x^1 -> x return child1; if(tu.isConstant(child2) && tu.getOperator(child1) == opSet.getPower()) { if(tu.isConstant(child1.jjtGetChild(1))) { /* (x^3)^4 -> x^(3*4) */ return nf.buildOperatorNode( opSet.getPower(), child1.jjtGetChild(0), nf.buildConstantNode( opSet.getMultiply(), child1.jjtGetChild(1), child2)); } } return null; // return nf.buildOperatorNode(((ASTOpNode) node).getOperator(),child1,child2); // return tu.buildPower(child1,child2); } /** simplifies operators, does not descend into children */ public Node simplifyOp(ASTFunNode node,Node children[]) throws ParseException { boolean allConst=true; XOperator op= (XOperator) node.getOperator(); // TODO a bit of a hack to prevent lists of constants being converted // what happens is that for [[1,2],[3,4]] the dimension is not passed // into buildConstantNode so list is treated as [1,2,3,4] // Ideally there would be a special simplification rule for List if(op.getPFMC() instanceof org.nfunk.jep.function.List) return node; int nchild=children.length; for(int i=0;i>32)); int yi = (int)(b^(b>>32)); result = 37*result+xi; result = 37*result+yi; return result; } public String toString() { return "("+a+","+b+")"; } } static Hashtable pascal = new Hashtable(); public static long binomial(long n,long i) { if(i==0 || n==i) return 1; if(i==1 || n==i-1 ) return n; return binomial(new LongPair(n,i)); } public static long binomial(LongPair pair) { Object find = pascal.get(pair); if(find == null) { long l = binomial(pair.x()-1,pair.y()-1); long r = binomial(pair.x()-1,pair.y()); pascal.put(pair,new Long(l+r)); return l+r; } return ((Long) find).longValue(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/XOperatorSet.java0000644000000000000000000001310610615400352022464 0ustar rootroot/* @author rich * Created on 26-Jul-2003 */ package org.lsmp.djep.xjep; import org.lsmp.djep.xjep.function.*; import org.nfunk.jep.*; /** * An OperatorSet where the operators have information about their commutativity etc. * * @see XOperator * @author Rich Morris * Created on 26-Jul-2003 */ public class XOperatorSet extends OperatorSet { private void annotateOperators(OperatorSet o) { OP_GT = new XOperator(o.getGT(),XOperator.BINARY+XOperator.LEFT+XOperator.TRANSITIVE); OP_LT = new XOperator(o.getLT(),XOperator.BINARY+XOperator.LEFT+XOperator.TRANSITIVE); OP_EQ = new XOperator(o.getEQ(),XOperator.BINARY+XOperator.LEFT+XOperator.EQUIVILENCE); OP_LE = new XOperator(o.getLE(),XOperator.BINARY+XOperator.LEFT+XOperator.REFLEXIVE+XOperator.TRANSITIVE); OP_GE = new XOperator(o.getGE(),XOperator.BINARY+XOperator.LEFT+XOperator.REFLEXIVE+XOperator.TRANSITIVE); OP_NE = new XOperator(o.getNE(),XOperator.BINARY+XOperator.LEFT+XOperator.SYMMETRIC); OP_AND = new XOperator(o.getAnd(),XOperator.BINARY+XOperator.LEFT+XOperator.COMMUTATIVE+XOperator.ASSOCIATIVE+XOperator.USE_BINDING_FOR_PRINT); OP_OR = new XOperator(o.getOr(),XOperator.BINARY+XOperator.LEFT+XOperator.COMMUTATIVE+XOperator.ASSOCIATIVE); OP_NOT = new XOperator(o.getNot(),XOperator.UNARY+XOperator.RIGHT+XOperator.PREFIX+XOperator.SELF_INVERSE); OP_ADD = new XOperator(o.getAdd(),XOperator.BINARY+XOperator.LEFT+XOperator.COMMUTATIVE+XOperator.ASSOCIATIVE); OP_SUBTRACT = new XOperator(o.getSubtract(),XOperator.BINARY+XOperator.LEFT+XOperator.COMPOSITE+XOperator.USE_BINDING_FOR_PRINT); OP_UMINUS = new XOperator(o.getUMinus(),XOperator.UNARY+XOperator.RIGHT+XOperator.PREFIX+XOperator.SELF_INVERSE); OP_MULTIPLY = new XOperator(o.getMultiply(),XOperator.BINARY+XOperator.LEFT+XOperator.COMMUTATIVE+XOperator.ASSOCIATIVE); OP_DIVIDE = new XOperator(o.getDivide(),XOperator.BINARY+XOperator.LEFT+XOperator.COMPOSITE); OP_MOD = new XOperator(o.getMod(),XOperator.BINARY+XOperator.LEFT); /** unary division i.e. 1/x or x^(-1) **/ OP_UDIVIDE = new XOperator("UDivide","^-1",null,XOperator.UNARY+XOperator.RIGHT+XOperator.PREFIX+XOperator.SELF_INVERSE); OP_POWER = new XOperator(o.getPower(),XOperator.BINARY+XOperator.LEFT); OP_ASSIGN = new XOperator("=",new XAssign(),XOperator.BINARY+XOperator.RIGHT); // OP_DOT = new XOperator(o.getDot(),XOperator.BINARY+XOperator.LEFT); // OP_CROSS = new XOperator(o.getCross(),XOperator.BINARY+XOperator.LEFT); // OP_LIST = new XOperator(o.getList(),XOperator.NARY+XOperator.RIGHT); // OP_ELEMENT = new XOperator(o.getElement(),XOperator.NARY+XOperator.RIGHT); // // OP_RANGE = new XOperator(o.getRange(),XOperator.NARY+XOperator.RIGHT); // setPrecedenceTable(new Operator[][] { {OP_UMINUS}, {OP_NOT}, {OP_POWER}, {OP_MULTIPLY,OP_DIVIDE,OP_MOD,OP_DOT,OP_CROSS}, {OP_ADD,OP_SUBTRACT}, {OP_LT,OP_LE}, {OP_GT,OP_GE}, {OP_EQ}, {OP_NE}, {OP_AND}, {OP_OR}, {OP_ASSIGN}, }); //printOperators(); // ((XOperator) OP_ADD).setInverseOp(OP_UMINUS); ((XOperator) OP_ADD).setBinaryInverseOp(OP_SUBTRACT); ((XOperator) OP_SUBTRACT).setRootOp(OP_ADD); ((XOperator) OP_SUBTRACT).setInverseOp(OP_UMINUS); ((XOperator) OP_UMINUS).setRootOp(OP_ADD); ((XOperator) OP_UMINUS).setBinaryInverseOp(OP_SUBTRACT); ((XOperator) OP_MULTIPLY).setInverseOp(OP_UDIVIDE); ((XOperator) OP_MULTIPLY).setBinaryInverseOp(OP_DIVIDE); ((XOperator) OP_DIVIDE).setRootOp(OP_MULTIPLY); ((XOperator) OP_DIVIDE).setInverseOp(OP_UDIVIDE); ((XOperator) OP_UDIVIDE).setRootOp(OP_MULTIPLY); ((XOperator) OP_UDIVIDE).setBinaryInverseOp(OP_DIVIDE); // Set distributive over ((XOperator) OP_UMINUS).setDistributiveOver(OP_ADD); // -(a+b) -> (-a) + (-b) ((XOperator) OP_UMINUS).setDistributiveOver(OP_SUBTRACT); // -(a-b) -> (-a) - (-b) ((XOperator) OP_MULTIPLY).setDistributiveOver(OP_ADD); // a*(b+c) -> a*b + a*c ((XOperator) OP_MULTIPLY).setDistributiveOver(OP_SUBTRACT); // a*(b-c) -> a*b - a*c ((XOperator) OP_MULTIPLY).setDistributiveOver(OP_UMINUS); // a*(-b) -> -(a*b) } /** Creates the operator set from a given set. Will * use the names and pfmc's but adds info about the operators properties. * Note changes pfmc for = from Assign to XAssign */ public XOperatorSet(OperatorSet opSet) { annotateOperators(opSet); } /** Create the standard set of operators. */ public XOperatorSet() { annotateOperators(this); } /** * Sets the precedences of the operators according to order in the supplied array. * For example *
    	 * 		setPrecedenceTable(new Operator[][] 
    	 *		{	{OP_UMINUS},
    	 *			{OP_NOT},
    	 *			{OP_MUL,OP_DIV,OP_MOD},
    	 *			{OP_PLUS,OP_MINUS},
    	 *			{OP_LT,OP_LE},
    	 *			{OP_GT,OP_GE},
    	 *			{OP_EQ},
    	 *			{OP_NE},
    	 *			{OP_AND},
    	 *			{OP_OR},
    	 *			});
    	 * 
    */ public static final void setPrecedenceTable(Operator[][] precArray) { for(int i=0;imaxPrec) maxPrec=((XOperator) ops[i]).getPrecedence(); for(int j=-1;j<=maxPrec;++j) for(int i=0;ieval(diff(x^3,x),x,2) * to differentiate x^3 and then substitute x=2 to get the value 12. * To use do *
     * JEP j = ...; Node in = ...;
     * TreeUtils tu = new TreeUtils(j);
     * CommandVisitor cv = new CommandVisitor(tu);
     * Node out = cv.process(in);
     * 
    * Commands to be executed must implement * {@link org.lsmp.djep.xjep.CommandVisitorI CommandVisitorI} and {@link org.nfunk.jep.function.PostfixMathCommandI PostfixMathCommandI}. * See {@link org.lsmp.djep.xjep.Eval Eval} for an example of this. * See {@link org.nfunk.jep.ParserVisitor ParserVisitor} for details on the VisitorPattern. * @author R Morris * Created on 19-Jun-2003 */ public class CommandVisitor extends DoNothingVisitor { private XJep xjep; /** private default constructor to prevent init without a tree utils */ public CommandVisitor() { } /** * Descends the tree processing all diff, eval and simplify options */ public Node process(Node node,XJep xj) throws ParseException { this.xjep=xj; Node res = (Node) node.jjtAccept(this,null); return res; } public Object visit(ASTFunNode node, Object data) throws ParseException { Node children[] = acceptChildrenAsArray(node,data); PostfixMathCommandI pfmc = node.getPFMC(); if(pfmc instanceof CommandVisitorI ) { CommandVisitorI com = (CommandVisitorI) pfmc; return com.process(node,children,xjep); } TreeUtils.copyChildrenIfNeeded(node,children); return node; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/MacroFunction.java0000644000000000000000000000626010615400352022637 0ustar rootroot/* @author rich * Created on 18-Jun-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.function.PostfixMathCommand; import org.nfunk.jep.*; import java.util.*; /** * A function specified by a string. * For example *
     * XJepI jep = new XJep();
     * j.addFunction("zap",new MacroFunction("zap",1,"x*(x-1)/2",j));
     * Node node = j.parse("zap(10)");
     * System.out.println(j.evaluate(node)); // print 45
     * 
    * The names of the variables used inside the function depends on the number of arguments: *
      *
    • One argument variable must be x: new MacroFunction("sec",1,"1/cos(x)",j)
    • *
    • Two arguments variables must be x or y: new MacroFunction("myPower",2,"x^y",j)
    • *
    • Three or more arguments variables must be x1, x2, x3,...: new MacroFunction("add3",3,"x1+x2+x3",j)
    • *
    * @author R Morris. * Created on 18-Jun-2003 */ public class MacroFunction extends PostfixMathCommand { private String name; private Node topNode; private EvaluatorVisitor ev = new EvaluatorVisitor(); // private XJep localJep; private XSymbolTable mySymTab; private Variable vars[]; public String getName() { return name; } public Node getTopNode() { return topNode; } /** * Create a function specified by a string. * For example new MacroFunction("sec",1,"1/cos(x)",tu) creates the function for sec. * Variable names must be x,y for 1 or 2 variables or x1,x2,x3,.. for 3 or more variables. * @param inName name of function * @param nargs number of arguments * @param expression a string representing the expression. * @param jep a reference to main XJep object. */ public MacroFunction(String inName,int nargs,String expression,XJep jep) throws IllegalArgumentException,ParseException { super(); name = inName; XSymbolTable jepSymTab = (XSymbolTable) jep.getSymbolTable(); mySymTab = (XSymbolTable) jepSymTab.newInstance(); mySymTab.copyConstants(jepSymTab); XJep localJep = jep.newInstance(mySymTab); numberOfParameters = nargs; if(numberOfParameters == 0) {} else if(numberOfParameters == 1) vars = new Variable[]{mySymTab.addVariable("x",null)}; else if(numberOfParameters == 2) { vars = new Variable[]{ mySymTab.addVariable("x",null), mySymTab.addVariable("y",null)}; } else { vars = new Variable[numberOfParameters]; for(int i=numberOfParameters-1;i>0;) vars[i] = mySymTab.addVariable("x"+String.valueOf(i),null); } topNode = localJep.parse(expression); } /** * Calculates the value of the expression. * @throws ParseException if run. */ public void run(Stack stack) throws ParseException { if(numberOfParameters == 0) {} else if(numberOfParameters == 1) vars[0].setValue(stack.pop()); else if(numberOfParameters == 2) { vars[1].setValue(stack.pop()); vars[0].setValue(stack.pop()); } else { for(int i=numberOfParameters-1;i>0;) vars[i].setValue(stack.pop()); } try { Object res = ev.getValue(topNode,mySymTab); stack.push(res); } catch(Exception e1) { throw new ParseException("MacroFunction eval: "+e1.getMessage()); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/DeepCopyVisitor.java0000644000000000000000000000213010615400352023150 0ustar rootroot/* @author rich * Created on 16-Nov-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; /** * A Visitor which returns an exact copy of the tree. * This class should be extended by visitors which * modify trees and creates a new tree. * * @author Rich Morris * Created on 16-Nov-2003 */ public class DeepCopyVisitor extends DoNothingVisitor implements ParserVisitor { private XJep xjep; /** Creates a deepCopy of a Node **/ public Node deepCopy(Node node,XJep xj) throws ParseException { this.xjep = xj; Node res = (Node) node.jjtAccept(this,null); return res; } public Object visit(ASTConstant node, Object data) throws ParseException { return xjep.getNodeFactory().buildConstantNode(node); } public Object visit(ASTVarNode node, Object data) throws ParseException { return xjep.getNodeFactory().buildVariableNode(node); } public Object visit(ASTFunNode node, Object data) throws ParseException { Node children[]=acceptChildrenAsArray(node,data); return xjep.getNodeFactory().buildFunctionNode(node,children); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/ErrorCatchingVisitor.java0000644000000000000000000000275510615400352024207 0ustar rootroot/* @author Rich Morris * Created on 19-Jun-2003 */ package org.lsmp.djep.xjep; //import org.lsmp.djep.matrixParser.*; import org.nfunk.jep.*; /** * An abstract ParserVisitor * which adds some useful error handling facilities. * Visitors which require these facilities should extend this class. * General format should be *
      
     * 	clearErrors();
     *	Object res = (Node) node.jjtAccept(this,data);
     *	if(hasErrors())
     *		throw new ParseException(getErrors());
     *
    * @author Rich Morris * Created on 19-Jun-2003 */ abstract public class ErrorCatchingVisitor extends DoNothingVisitor { /** The current error list. */ private Exception error=null; /** calls jjtAccept inside a try catch block, adding the error if necessary */ public Object acceptCatchingErrors(Node node,Object data) { Object res=null; clearErrors(); try { res = node.jjtAccept(this,data); } catch (ParseException e) { addError(e); } return res; } /** Reset the list of errors. */ public void clearErrors() { error = null; } /** Are their any errors? */ public boolean hasErrors() { return error != null; } /** Adds an error message to the list of errors. */ public void addError(Exception e) {error = e; } /** Returns the error messages. */ public String getErrorsMessage() { if(error==null) return null; return error.getMessage(); } /** Returns the Exception or null if no error. */ public Exception getError() { return error; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/TreeUtils.java0000644000000000000000000002354310615400352022013 0ustar rootroot/* * Created on 16-Jun-2003 by Rich webmaster@pfaf.org * www.singsurf.org */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * A set of Utility functions for working with JEP expression trees. * Main methods are *
      *
    • {@link #isConstant isConstant} test if its a constant. Many other is... methods. *
    • {@link #getValue getValue} extracts the value from a node without needing to cast and check types. *
    * @author rich */ public class TreeUtils { /** Real zero. Note that this is a Double, if a different number * format is needed then this class should be sub-classed. */ protected static Double ZERO = new Double(0.0); /** Real One */ protected static Double ONE = new Double(1.0); /** Real Minus One */ protected static Double MINUSONE = new Double(-1.0); /** Complex Zero **/ protected static Complex CZERO = new Complex(0.0,0.0); /** Complex One **/ protected static Complex CONE = new Complex(1.0,0.0); /** Complex i **/ protected static Complex CI = new Complex(0.0,1.0); /** Complex Minus One **/ protected static Complex CMINUSONE = new Complex(-1.0,0.0); /** Complex Minus i **/ protected static Complex CMINUSI = new Complex(0.0,-1.0); /** Real NaN */ protected static Double NAN = new Double(Double.NaN); /** Real positive infinity */ protected static Double PosInf = new Double(Double.POSITIVE_INFINITY); /** Real NaN */ protected static Double NegInf = new Double(Double.NEGATIVE_INFINITY); /** * Default constructor. * TODO Should use the NumberFactory to create numbers! */ public TreeUtils() {} //public static TreeUtils getInstance() { return INSTANCE; } /** * Returns the value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant */ public String getName(Node node) throws IllegalArgumentException { if(isVariable(node)) return ((ASTVarNode) node).getName(); if(isFunction(node)) return ((ASTFunNode) node).getName(); throw new IllegalArgumentException("Tried to find the name of constant node"); } /** gets the PostfixMathCommand with a given name. */ /* public PostfixMathCommandI getPfmc(String name) { return (PostfixMathCommandI) myFunTab.get(name); } */ /** * Returns the value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant */ public Object getValue(Node node) throws IllegalArgumentException { if(!isConstant(node)) throw new IllegalArgumentException("Tried to find the value of a non constant node"); return ((ASTConstant) node).getValue(); } /** * Returns the double value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant with a Double value */ public double doubleValue(Node node) throws IllegalArgumentException { return ((Double) getValue(node)).doubleValue(); } /** * Returns the long value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant with a Double value */ public long longValue(Node node) throws IllegalArgumentException { return ((Number) getValue(node)).longValue(); } /** * Returns the int value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant with a Double value */ public int intValue(Node node) throws IllegalArgumentException { return ((Number) getValue(node)).intValue(); } /** * Returns the Complex value represented by node * @throws IllegalArgumentException if given something which is not an ASTConstant with a Complex value */ public Complex complexValue(Node node) throws IllegalArgumentException { return ((Complex) getValue(node)); } /** * returns true if node is a ASTConstant */ public boolean isConstant(Node node) { return (node instanceof ASTConstant); } /** * returns true if node is a ASTConstant with Double value */ public boolean isReal(Node node) { return (node instanceof ASTConstant) && ( ((ASTConstant) node).getValue() instanceof Double ); } /** * returns true if node is a ASTConstant with Double value representing an integer. */ public boolean isInteger(Node node) { if(isReal(node)) { Number val = (Number) ((ASTConstant) node).getValue(); double x = val.doubleValue(); double xInt = Math.rint(x); return x == xInt; } return false; } /** * returns true if node is a ASTConstant with value Double(0) or Complex(0,0) */ public boolean isZero(Node node) { return ( isReal(node) && ( ((ASTConstant) node).getValue().equals(ZERO)) ) ||( isComplex(node) && ( ((Complex) ((ASTConstant) node).getValue()).equals(CZERO,0.0) ) ); } /** * returns true if node is a ASTConstant with value Double(0) or Complex(0,0) * @param tol tolerance for testing for zero */ public boolean isZero(Node node,double tol) { return ( isReal(node) && ( (((ASTConstant) node).getValue().equals(ZERO)) ) || Math.abs(doubleValue(node)) < tol ) ||( isComplex(node) && ( ((Complex) ((ASTConstant) node).getValue()).equals(CZERO,tol) ) ); } /** * returns true if node is a ASTConstant with value Double(1) or Complex(1,0) */ public boolean isOne(Node node) { return ( isReal(node) && ( ((ASTConstant) node).getValue().equals(ONE)) ) ||( isComplex(node) && ( ((Complex) ((ASTConstant) node).getValue()).equals(CONE,0.0) ) ); } /** * returns true if node is a ASTConstant with value Double(-1) or Complex(-1,0) */ public boolean isMinusOne(Node node) { return ( isReal(node) && ( ((ASTConstant) node).getValue().equals(MINUSONE)) ) ||( isComplex(node) && ( ((Complex) ((ASTConstant) node).getValue()).equals(CMINUSONE,0.0) ) ); } /** * returns true if node is a ASTConstant with a Infinite component * TODO do proper treatment of signed infinity */ public boolean isInfinity(Node node) { if(isReal(node)) { Double dub = (Double) ((ASTConstant) node).getValue(); return dub.isInfinite(); } if(isComplex(node)) { Complex z = (Complex) ((ASTConstant) node).getValue(); return Double.isInfinite(z.re()) || Double.isInfinite(z.im()); } return false; } /** * returns true if node is a ASTConstant with a NaN component */ public boolean isNaN(Node node) { if(isReal(node)) { Double dub = (Double) ((ASTConstant) node).getValue(); return dub.isNaN(); } if(isComplex(node)) { Complex z = (Complex) ((ASTConstant) node).getValue(); return Double.isNaN(z.re()) || Double.isNaN(z.im()); } return false; } /** * returns true if node is an ASTConstant with a negative Double value */ public boolean isNegative(Node node) { return isReal(node) && ( ((Double) ((ASTConstant) node).getValue()).doubleValue() < 0.0 ); } /** * returns true if node is an ASTConstant with a positive Double value */ public boolean isPositive(Node node) { return isReal(node) && ( ((Double) ((ASTConstant) node).getValue()).doubleValue() > 0.0 ); } /** * returns true if node is an ASTConstant of type Complex */ public boolean isComplex(Node node) { return isConstant(node) && ( ((ASTConstant) node).getValue() instanceof Complex ); } /** * returns true if node is an ASTVarNode */ public boolean isVariable(Node node) { return (node instanceof ASTVarNode); } /** * returns true if node is an ASTOpNode */ public boolean isOperator(Node node) { return (node instanceof ASTFunNode) && ((ASTFunNode) node).isOperator(); } public boolean isBinaryOperator(Node node) { if(isOperator(node)) { return ((XOperator) ((ASTFunNode) node).getOperator()).isBinary(); } return false; } public boolean isUnaryOperator(Node node) { if(isOperator(node)) { return ((XOperator) ((ASTFunNode) node).getOperator()).isUnary(); } return false; } /** * returns the operator for a node or null if it is not an operator node. */ public Operator getOperator(Node node) { if(isOperator(node)) return ((ASTFunNode) node).getOperator(); return null; } /** * returns true if node is an ASTFunNode */ public boolean isFunction(Node node) { return (node instanceof ASTFunNode); } /** * Sets the children of a node if they have changed for it current children. */ public static Node copyChildrenIfNeeded(Node node,Node children[]) throws ParseException { int n=node.jjtGetNumChildren(); if(n!=children.length) throw new ParseException("copyChildrenIfNeeded: umber of children of node not the same as supplied children"); for(int i=0;i * Function nodes are evaluated by first evaluating all the children nodes, * then applying the function class associated with the node. Variable and * constant nodes are evaluated by pushing their value onto the stack. *

    * Some changes implemented by rjm. Nov 03. * Added hook to SpecialEvaluationI. * Clears stack before evaluation. * Simplifies error handling by making visit methods throw ParseException. * Changed visit(ASTVarNode node) so messages not calculated every time. */ public class XEvaluatorVisitor extends EvaluatorVisitor { /** * Visit a variable node. The value of the variable is obtained from the * symbol table (symTab) and pushed onto the stack. */ public Object visit(ASTVarNode node, Object data) throws ParseException { Variable var = node.getVar(); if (var == null) { String message = "Could not evaluate " + node.getName() + ": "; throw new ParseException(message + " variable not set"); } Object val = null; if(var.hasValidValue()) { val = var.getValue(); if (trapNullValues && val == null) { String message = "Could not evaluate " + node.getName() + ": null value"; throw new ParseException(message); } stack.push(val); } else if(var instanceof XVariable) { Node equation = ((XVariable) var).getEquation(); if(equation==null) throw new ParseException("Cannot find value of "+var.getName()+" no equation."); // TODO causes stack overflow if recursive eqn with undefined value is used: recurse = recurse+1 equation.jjtAccept(this,data); val = stack.peek(); if (trapNullValues && val == null) { String message = "Could not evaluate " + node.getName() + ": null value"; throw new ParseException(message); } } else { throw new ParseException("Could not evaluate " + node.getName() + ": value not set"); } return data; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/PrintVisitor.java0000644000000000000000000002671610615400352022554 0ustar rootroot/* @author rich * Created on 18-Jun-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import java.io.PrintStream; import java.util.Hashtable; import java.text.NumberFormat; import java.text.FieldPosition; /** * Prints an expression. * Prints the expression with lots of brackets. * ((-1.0)/sqrt((1.0-(x^2.0)))). * To use *

     * XJep j = ...; Node in = ...;
     * j.print(in,"x");
     * 
    * @author Rich Morris * Created on 20-Jun-2003 * @since Dec 04 and NumberFormat object can be supplied to modify printing of numbers. * @since 21 Dec 04 PrintVisitor can now cope with 3 or more arguments to + and *. * @see XJep#print(Node) * @see XJep#print(Node, PrintStream) * @see XJep#println(Node) * @see XJep#println(Node, PrintStream) * @see XJep#toString(Node) */ public class PrintVisitor extends ErrorCatchingVisitor { /** All brackets are printed. Removes all ambiguity. */ public static final int FULL_BRACKET = 1; /** Print Complex as 3+2 i */ public static final int COMPLEX_I = 2; private int maxLen = -1; protected StringBuffer sb; /** The current mode for printing. */ // protected boolean fullBrackets=false; protected int mode=0; private Hashtable specialRules = new Hashtable(); /** Creates a visitor to create and print string representations of an expression tree. **/ public PrintVisitor() { } /** Prints the tree descending from node with lots of brackets * or specified stream. * @see XJep#println(Node, PrintStream) **/ public void print(Node node,PrintStream out) { sb = new StringBuffer(); acceptCatchingErrors(node,null); if(maxLen == -1) out.print(sb); else { while(true) { if(sb.length() < maxLen) { out.print(sb); return; } int pos = maxLen-2; for(int i=maxLen-2;i>=0;--i) { char c = sb.charAt(i); if(c == '+' || c == '-' || c == '*' || c == '/'){ pos = i; break; } } //out.println("<"+sb.substring(0,pos+10)+">"); out.println(sb.substring(0,pos+1)); sb.delete(0,pos+1); } } } /** Prints on System.out. */ public void print(Node node) { print(node,System.out); } /** Prints the tree descending from node with a newline at end. **/ public void println(Node node,PrintStream out) { print(node,out); out.println(""); } /** Prints on System.out. */ public void println(Node node) { println(node,System.out); } /** returns a String representation of the equation. */ public String toString(Node node) { sb = new StringBuffer(); acceptCatchingErrors(node,null); return sb.toString(); } /** * This interface specifies the method needed to implement a special print rule. * A special rule must implement the append method, which should * call pv.append to add data to the output. For example *
    	 * 	pv.addSpecialRule(Operator.OP_LIST,new PrintVisitor.PrintRulesI()
    	 *	{
    	 *  	public void append(Node node,PrintVisitor pv) throws ParseException
    	 *		{
    	 *			pv.append("[");
    	 *			for(int i=0;i0) pv.append(",");
    	 *				node.jjtGetChild(i).jjtAccept(pv, null);
    	 *			}
    	 *			pv.append("]");
    	 *		}});
     	 * 
    * @author Rich Morris * Created on 21-Feb-2004 */ public interface PrintRulesI { /** The method called to append data for the rule. **/ public void append(Node node,PrintVisitor pv) throws ParseException; } /** Add a string to buffer. Classes implementing PrintRulesI * should call this add the */ public void append(String s) { sb.append(s); } /** Adds a special print rule to be added for a given operator. * TODO Allow special rules for other functions, i.e. not operators. */ public void addSpecialRule(Operator op,PrintRulesI rules) { specialRules.put(op,rules); } /***************** visitor methods ********************************/ /** print the node with no brackets. */ private void printNoBrackets(Node node) throws ParseException { node.jjtAccept(this,null); } /** print a node surrounded by brackets. */ private void printBrackets(Node node) throws ParseException { sb.append("("); printNoBrackets(node); sb.append(")"); } /** print a unary operator. */ private Object visitUnary(ASTFunNode node, Object data) throws ParseException { Node rhs = node.jjtGetChild(0); // now print the node sb.append(node.getOperator().getSymbol()); // now the rhs if(rhs instanceof ASTFunNode && ((ASTFunNode) rhs).isOperator()) printBrackets(rhs); // -(-3) -(1+2) or !(-3) else printNoBrackets(rhs); return data; } private boolean testLeft(XOperator top,Node lhs) { if((mode & FULL_BRACKET)!= 0) { return true; } else if(lhs instanceof ASTFunNode && ((ASTFunNode) lhs).isOperator()) { XOperator lhsop = (XOperator) ((ASTFunNode) lhs).getOperator(); if(top == lhsop) { if(top.getBinding() == XOperator.LEFT // (1-2)-3 -> 1-2-3 && top.isAssociative() ) return false; else if(top.useBindingForPrint()) return false; else return true; // (1=2)=3 -> (1=2)=3 } else if(top.getPrecedence() == lhsop.getPrecedence()) { if(lhsop.getBinding() == XOperator.LEFT && lhsop.isAssociative()) return false; else if(lhsop.useBindingForPrint()) return false; else return true; } // (1=2)=3 -> (1=2)=3 else if(top.getPrecedence() > lhsop.getPrecedence()) // (1*2)+3 return false; else return true; } else return false; } private boolean testMid(XOperator top,Node rhs) { if((mode & FULL_BRACKET)!= 0) { return true; } else if(rhs instanceof ASTFunNode && ((ASTFunNode) rhs).isOperator()) { XOperator rhsop = (XOperator) ((ASTFunNode) rhs).getOperator(); if(top == rhsop) { return false; } else if(top.getPrecedence() == rhsop.getPrecedence()) { return false; // a+(b-c) -> a+b-c } else if(top.getPrecedence() > rhsop.getPrecedence()) // 1+(2*3) -> 1+2*3 return false; else return true; } else return false; } private boolean testRight(XOperator top,Node rhs) { if((mode & FULL_BRACKET)!= 0) { return true; } else if(rhs instanceof ASTFunNode && ((ASTFunNode) rhs).isOperator()) { XOperator rhsop = (XOperator) ((ASTFunNode) rhs).getOperator(); if(top == rhsop) { if(top.getBinding() == XOperator.RIGHT // 1=(2=3) -> 1=2=3 || top.isAssociative() ) // 1+(2-3) -> 1+2-3 return false; return true; // 1-(2+3) -> 1-(2-3) } else if(top.getPrecedence() == rhsop.getPrecedence()) { if(top.getBinding() == XOperator.LEFT && top.isAssociative() ) // 1+(2-3) -> 1+2-3) return false; // a+(b-c) -> a+b-c return true; // a-(b+c) -> a-(b+c) } else if(top.getPrecedence() > rhsop.getPrecedence()) // 1+(2*3) -> 1+2*3 return false; else return true; } else return false; } private Object visitNaryBinary(ASTFunNode node,XOperator op) throws ParseException { int n = node.jjtGetNumChildren(); for(int i=0;i0) sb.append(op.getSymbol()); Node arg = node.jjtGetChild(i); if(testMid(op,arg)) printBrackets(arg); else printNoBrackets(arg); } return null; } public Object visit(ASTFunNode node, Object data) throws ParseException { if(!node.isOperator()) return visitFun(node); if(node instanceof PrintRulesI) { ((PrintRulesI) node).append(node,this); return null; } if(node.getOperator()==null) { throw new ParseException("Null operator in print for "+node); } if(specialRules.containsKey(node.getOperator())) { ((PrintRulesI) specialRules.get(node.getOperator())).append(node,this); return null; } if(node.getPFMC() instanceof org.nfunk.jep.function.List) { append("["); for(int i=0;i0) append(","); node.jjtGetChild(i).jjtAccept(this, null); } append("]"); return null; } if(((XOperator) node.getOperator()).isUnary()) return visitUnary(node,data); if(((XOperator) node.getOperator()).isBinary()) { XOperator top = (XOperator) node.getOperator(); if(node.jjtGetNumChildren()!=2) return visitNaryBinary(node,top); Node lhs = node.jjtGetChild(0); Node rhs = node.jjtGetChild(1); if(testLeft(top,lhs)) printBrackets(lhs); else printNoBrackets(lhs); // now print the node sb.append(node.getOperator().getSymbol()); // now the rhs if(testRight(top,rhs)) printBrackets(rhs); else printNoBrackets(rhs); } return null; } /** prints a standard function: fun(arg,arg) */ private Object visitFun(ASTFunNode node) throws ParseException { sb.append(node.getName()+"("); for(int i=0;i0) sb.append(","); node.jjtGetChild(i).jjtAccept(this, null); } sb.append(")"); return null; } public Object visit(ASTVarNode node, Object data) throws ParseException { sb.append(node.getName()); return data; } public Object visit(ASTConstant node, Object data) { Object val = node.getValue(); formatValue(val,sb); return data; } private FieldPosition fp = new FieldPosition(NumberFormat.FRACTION_FIELD); /** Appends a formatted versions of val to the string buffer. * * @param val The value to format * @param sb1 The StingBuffer to append to */ public void formatValue(Object val,StringBuffer sb1) { if(format != null) { if(val instanceof Number) format.format(val,sb1,fp); else if(val instanceof Complex) { if((mode | COMPLEX_I) == COMPLEX_I) sb1.append(((Complex) val).toString(format,true)); else sb1.append(((Complex) val).toString(format)); } else sb1.append(val); } else sb1.append(val); } /** Returns a formated version of the value. */ public String formatValue(Object val) { StringBuffer sb2 = new StringBuffer(); formatValue(val,sb2); return sb2.toString(); } /** * Return the current print mode. */ public int getMode() { return mode; } public boolean getMode(int testmode) { return( (this.mode | testmode ) == testmode); } /** * Set printing mode. * In full bracket mode the brackets each element in the tree will be surrounded * by brackets to indicate the tree structure. * In the default mode, (full bracket off) the number of brackets is * minimised so (x+y)+z will be printed as x+y+z. * @param mode which flags to change, typically FULL_BRACKET * @param flag whether to switch this mode on or off */ public void setMode(int mode,boolean flag) { if(flag) this.mode |= mode; else this.mode ^= mode; } /** The NumberFormat object used to print numbers. */ protected NumberFormat format; public void setNumberFormat(NumberFormat format) { this.format = format; } /** * Sets the maximum length printed per line. * If the value is not -1 then the string will be broken into chunks * each of which is less than the max length. * @param i the maximum length */ public void setMaxLen(int i) { maxLen = i; } /** * @return the maximum length printed per line */ public int getMaxLen() { return maxLen; } } /*end*/ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/BaseFormat.java0000644000000000000000000000473410615400352022117 0ustar rootroot/* @author rich * Created on 02-May-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.xjep; import java.text.FieldPosition; import java.text.NumberFormat; import java.text.ParsePosition; import org.lsmp.djep.xjep.function.FromBase; import org.lsmp.djep.xjep.function.ToBase; /** * A Number format object which prints results in a specified base. * TODO Do something with the FieldPosition arguments. * * @author Rich Morris * Created on 02-May-2005 */ public class BaseFormat extends NumberFormat { /** * */ private static final long serialVersionUID = 1805136353312272410L; int base; ToBase tb=null; FromBase fb=null; /** * */ private BaseFormat() { super(); tb = new ToBase(); fb = new FromBase(); } /** * Create a new base format object * @param base the base of number to use * @throws IllegalArgumentException if base is < 2 or > 36 */ public BaseFormat(int base) { super(); this.base = base; tb = new ToBase(base); fb = new FromBase(base); } /** * Create a new base format object * @param base the base of number to use * @param prefix prefix to appear before number * @throws IllegalArgumentException if base is < 2 or > 36 */ public BaseFormat(int base,String prefix) { super(); this.base = base; tb = new ToBase(base,prefix); fb = new FromBase(base,prefix); } /** * Format a double value in specific base. * @param val the number to format * @param sb the buffer to append to * @param fp not used * @return the string buffer */ public StringBuffer format(double val, StringBuffer sb, FieldPosition fp) { sb.append(tb.toBase(val,base,this.getMaximumFractionDigits())); return sb; } /** * Format a double value in specific base. * @param val the number to format * @param sb the buffer to append to * @param fp not used * @return the string buffer */ public StringBuffer format(long val, StringBuffer sb, FieldPosition fp) { sb.append(tb.toBase(val,base)); return sb; } /** * Not implemented */ public Number parse(String arg0, ParsePosition arg1) { // TODO Auto-generated method stub return null; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/xjep/SubstitutionVisitor.java0000644000000000000000000000470510615400352024166 0ustar rootroot/* @author rich * Created on 16-Nov-2003 */ package org.lsmp.djep.xjep; import org.nfunk.jep.*; /** * Allows substitution of a given variable with an expression tree. * Substitution is best done using the * {@link XJep#substitute(Node,String,Node) XJep.substitute} method. * For example *
     * XJepI xjep = ...;
     * Node node = xjep.parse("x^2+x");
     * Node sub = xjep.parse("sin(y)");
     * Node res = xjep.substitute(node,"x",sub,xjep);
     * 
    * Will give the expression "(sin(y))^2+sin(y)". * * @author Rich Morris * Created on 16-Nov-2003 */ public class SubstitutionVisitor extends DoNothingVisitor { private String names[]; private Node replacements[]; private XJep xjep; public SubstitutionVisitor() {} /** * Substitutes all occurrences of variable var with replacement. * Does not do a DeepCopy. * @param orig the expression we wish to perform the substitution on * @param name the name of the variable * @param replacement the expression var is substituted for * @return the tree with variable replace (does not do a DeepCopy) * @throws ParseException */ public Node substitute(Node orig,String name,Node replacement,XJep xj) throws ParseException { this.names = new String[]{name}; this.replacements = new Node[]{replacement}; this.xjep=xj; Node res = (Node) orig.jjtAccept(this,null); return res; } /** * Substitutes all occurrences of a set of variable var with a set of replacements. * Does not do a DeepCopy. * @param orig the expression we wish to perform the substitution on * @param names the names of the variable * @param replacements the expression var is substituted for * @return the tree with variable replace (does not do a DeepCopy) * @throws ParseException */ public Node substitute(Node orig,String names[],Node replacements[],XJep xj) throws ParseException { this.names = names; this.replacements = replacements; this.xjep=xj; Node res = (Node) orig.jjtAccept(this,null); return res; } public Object visit(ASTVarNode node, Object data) throws ParseException { for(int i=0;i * XJep j = new XJep(); * j.restartParser("x=1;y=2; z=3;"); * Node node; * try { * while((node = j.continueParsing())!=null) { * j.println(node); * } }catch(ParseException e) {} * * @return top node of equation parsed to date or null if empty equation * @throws ParseException * @see #restartParser(String) */ public Node continueParsing() throws ParseException { return parser.continueParse(); } /** * Restarts the parser with the given string. * @param str String containing a sequence of equations separated by semi-colons. * @see #continueParsing */ public void restartParser(String str) { parser.restart(new java.io.StringReader(str), this); } /** * Restarts the parser with the given Reader. * @param reader Reader from which equations separated by semi-colons will be read. * @see #continueParsing */ public void restartParser(Reader reader) { parser.restart(reader, this); } /** * Finds all the variables in an equation. * * @param n the top node of the expression * @param v a vector to store the list of variables (new variables will be added on end) * @return v */ public Vector getVarsInEquation(Node n,Vector v) { if(n instanceof ASTVarNode) { Variable var = ((ASTVarNode) n).getVar(); if(!v.contains(var)) v.add(var); } else if(n instanceof ASTFunNode) { for(int i=0;i * For example if the equation is a+b and * a=c+d, b=c+e then the * result will be the sequence (c,d,a,e,b) * * @param n top node * @param v vector for storing results, new variables will be added on the end. * @return v, the ordered sequence of variables * @throws ParseException if equation is recursive i.e. x=y; y=x+1; */ public Vector recursiveGetVarsInEquation(Node n,Vector v) throws ParseException { if(n instanceof ASTVarNode) { XVariable var = (XVariable) (((ASTVarNode) n).getVar()); if(!v.contains(var)) { if(var.hasEquation()) recursiveGetVarsInEquation(var.getEquation(),v); if(v.contains(var)) throw new ParseException("Recursive definition for "+var.getName()); v.add(var); } } else if(n instanceof ASTFunNode) { for(int i=0;i=0;--i) { res[i] = (Number) stack.pop(); } stack.push(((HasListI) group).list(res)); return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/package.html0000644000000000000000000000011410615400352024150 0ustar rootroot PostfixMathCommands which implement the group operations. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GPower.java0000644000000000000000000000255110615400352023744 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.interfaces.*; import java.util.*; import org.nfunk.jep.*; /** * Power operator for a group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GPower extends PostfixMathCommand { /** null if power not implemented */ private HasPowerI group=null; /** * */ private GPower() { } public GPower(GroupI group) { numberOfParameters = 2; if(group instanceof HasPowerI) this.group = (HasPowerI) group; } /** * Calculates the result of applying the "+" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object exponant = stack.pop(); Object param = stack.pop(); Object res = pow(param, exponant); stack.push(res); return; } public Object pow(Object param1, Object param2) throws ParseException { if(group==null) throw new ParseException("Power not implemented for this group."); if (param1 instanceof Number) { if (param2 instanceof Number) { return group.pow((Number)param1, (Number)param2); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GUMinus.java0000644000000000000000000000201210615400352024060 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import java.util.*; import org.nfunk.jep.*; /** * Unitary division for a group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GUMinus extends PostfixMathCommand { private GroupI group; /** * */ private GUMinus() { } public GUMinus(GroupI group) { numberOfParameters = 1; this.group = group; } /** * Calculates the result of applying the "+" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object sum = stack.pop(); stack.push(uminus(sum)); return; } public Object uminus(Object param1) throws ParseException { if (param1 instanceof Number) { return group.getInverse((Number)param1); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GNot.java0000644000000000000000000000213510615400352023406 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import java.util.*; import org.nfunk.jep.*; /** * Not function for use with arbitary groups. * Expects Boolean arguments. * * @author Rich Morris * Created on 13-Dec-2004 */ public class GNot extends PostfixMathCommand { public GNot() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); if (param instanceof Boolean) { boolean a = ((Boolean)param).booleanValue(); inStack.push(a ? Boolean.FALSE : Boolean.TRUE);//push the result on the inStack } else { throw new ParseException("Invalid parameter type"); } return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GMod.java0000644000000000000000000000246110615400352023367 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.interfaces.*; import java.util.*; import org.nfunk.jep.*; /** * Modulus operator for group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GMod extends PostfixMathCommand { private HasModI group=null; /** * */ private GMod() { } public GMod(GroupI group) { numberOfParameters = 2; if(group instanceof HasModI) this.group = (HasModI) group; } /** * Calculates the result of applying the "+" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object sum = stack.pop(); Object param; param = stack.pop(); sum = mod(param, sum); stack.push(sum); return; } public Object mod(Object param1, Object param2) throws ParseException { if(group==null) throw new ParseException("Modulus not implemented for this group."); if (param1 instanceof Number) { if (param2 instanceof Number) { return group.mod((Number)param1, (Number)param2); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GLogical.java0000644000000000000000000000311210615400352024214 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import java.util.*; import org.nfunk.jep.*; /** * Implements logical operators for a group. * * @author Rich Morris * Created on 13-Dec-2004 */ public class GLogical extends PostfixMathCommand { int id; /** * Constructs * @param id should be Logical.AND or Logical.OR * @see org.nfunk.jep.function.Logical **/ public GLogical(int id) { this.id = id; numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if ((param1 instanceof Boolean) && (param2 instanceof Boolean)) { boolean a = ((Boolean)param1).booleanValue(); boolean b = ((Boolean)param2).booleanValue(); boolean flag=false; switch (id) { case Logical.AND: flag = a && b; break; case Logical.OR: flag = a || b; break; default: throw new ParseException("Illegal logical operator"); } inStack.push(flag ? Boolean.TRUE : Boolean.FALSE);//push the result on the inStack } else { throw new ParseException("Invalid parameter type"); } return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GDivide.java0000644000000000000000000000256610615400352024062 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.interfaces.*; import java.util.*; import org.nfunk.jep.*; /** * Divide function for use with arbitary groups. * Actual behaviour defined by the Group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GDivide extends PostfixMathCommand { private HasDivI group=null; /** * */ private GDivide() { } public GDivide(GroupI group) { numberOfParameters = 2; if(group instanceof HasDivI) this.group = (HasDivI) group; } /** * Calculates the result of applying the "/" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object sum = stack.pop(); Object param; param = stack.pop(); sum = div(param, sum); stack.push(sum); return; } public Object div(Object param1, Object param2) throws ParseException { if(group==null) throw new ParseException("Divide not implemented for this group."); if (param1 instanceof Number) { if (param2 instanceof Number) { return group.div((Number)param1, (Number)param2); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GComparative.java0000644000000000000000000000571710615400352025131 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.lsmp.djep.groupJep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.interfaces.*; /** * Implements logical operations on a group. * Will always return Boolean results. * * @author Rich Morris * Created on 06-Mar-2004 */ public class GComparative extends PostfixMathCommand { int id; GroupI group; /** * Constructor. For inequalities the group should implement OrderedSetI. * * @param id should be Comparative.LT or GT, LE, GE, NE EQ * @see org.nfunk.jep.function.Comparative */ public GComparative(GroupI group,int id) { this.id = id; numberOfParameters = 2; this.group = group; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if ((param1 instanceof Number) && (param2 instanceof Number)) { Number num1 = (Number)param1; Number num2 = (Number)param2; boolean flag; if(group instanceof OrderedSetI) { int comp = ((OrderedSetI) group).compare(num1,num2); switch (id) { case Comparative.LT: flag = comp < 0; break; case Comparative.GT: flag = comp > 0; break; case Comparative.LE: flag = comp <= 0; break; case Comparative.GE: flag = comp >= 0; break; case Comparative.NE: flag = comp != 0; break; case Comparative.EQ: flag = comp == 0; break; default: throw new ParseException("Unknown relational operator"); } } else { switch (id) { case Comparative.NE: flag = !group.equals(num1,num2); break; case Comparative.EQ: flag = group.equals(num1,num2); break; default: throw new ParseException("Unknown relational operator"); } } inStack.push(flag ? Boolean.TRUE : Boolean.FALSE);//push the result on the inStack } else if ((param1 instanceof Boolean) && (param2 instanceof Boolean)) { boolean num1 = ((Boolean)param1).booleanValue(); boolean num2 = ((Boolean)param2).booleanValue(); boolean flag; switch (id) { case Comparative.NE: flag = num1 != num2; break; case Comparative.EQ: flag = num1 == num2; break; default: throw new ParseException("Unknown relational operator"); } inStack.push(flag ? Boolean.TRUE : Boolean.FALSE);//push the result on the inStack } else throw new ParseException("Invalid parameters for comparitive op"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GMultiply.java0000644000000000000000000000310210615400352024460 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.interfaces.*; import java.util.*; import org.nfunk.jep.*; /** * Multiplication operator for a group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GMultiply extends PostfixMathCommand { private RingI group = null; /** * */ private GMultiply() { } public GMultiply(GroupI group) { numberOfParameters = -1; if(group instanceof RingI) this.group = (RingI) group; } /** * Calculates the result of applying the "*" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { if(group==null) throw new ParseException("Multiply not implemented for this group."); checkStack(stack);// check the stack Object sum = stack.pop(); Object param; int i = 1; // repeat summation for each one of the current parameters while (i < curNumberOfParameters) { // get the parameter from the stack param = stack.pop(); // add it to the sum (order is important for String arguments) sum = mul(param, sum); i++; } stack.push(sum); return; } public Object mul(Object param1, Object param2) throws ParseException { if (param1 instanceof Number) { if (param2 instanceof Number) { return group.mul((Number)param1, (Number)param2); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/function/GAdd.java0000644000000000000000000000266410615400352023345 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.groupJep.*; import java.util.*; import org.nfunk.jep.*; /** * Add function for use with arbitary groups. * Actual behaviour defined by the Group. * * @author Rich Morris * Created on 05-Mar-2004 */ public class GAdd extends PostfixMathCommand { private GroupI group; /** * */ private GAdd() { } public GAdd(GroupI group) { numberOfParameters = -1; this.group = group; } /** * Calculates the result of applying the "+" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object sum = stack.pop(); Object param; int i = 1; // repeat summation for each one of the current parameters while (i < curNumberOfParameters) { // get the parameter from the stack param = stack.pop(); // add it to the sum (order is important for String arguments) sum = add(param, sum); i++; } stack.push(sum); return; } public Object add(Object param1, Object param2) throws ParseException { if (param1 instanceof Number) { if (param2 instanceof Number) { return group.add((Number)param1, (Number)param2); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/package.html0000644000000000000000000000363310615400352022334 0ustar rootroot A version of JEP which can work over an arbitary group. This version of jep changes the behaviour of the arithmetic and the comparative operations according to the group operations. These group operations are specified by objects which implement GroupI or one of its decendants like RingI or HasPowerI. There are various example groups which can be used: arbitrary-precision integers, arbitrary-precision rationals, integers mod n, reals with a fixed precision.

    Typically it is used like

    import org.lsmp.djep.rationalJep.*;
    import org.lsmp.djep.rationalJep.groups.*;
    ....
    GroupI group = new Rationals();
    JEP j = new GroupJep(group);
    ....
    
    See the groups package for the different types of group which can be used.

    Sub-packages
    org.lsmp.djep.groupJep.function Functions for basic operators +,-,* in GroupJep
    org.lsmp.djep.groupJep.groups Various pre-defined groups.
    org.lsmp.djep.groupJep.interfaces Interfaces defining ring, field and other group structures.
    org.lsmp.djep.groupJep.values Objects representing elements of groups.
    @see GroupJep documentation jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/GOperatorSet.java0000644000000000000000000000260010615400352023265 0ustar rootroot/* @author rich * Created on 07-Mar-2004 */ package org.lsmp.djep.groupJep; import org.nfunk.jep.*; import org.lsmp.djep.groupJep.function.*; import org.nfunk.jep.function.*; /** * The set of operators used in the parser. * Actual function and suported operators are * defined by the group and the interfaces it supports. * * @author Rich Morris * Created on 07-Mar-2004 */ public class GOperatorSet extends OperatorSet { /** * TODO Should really change the properties of operators, might muck up simplification. */ public GOperatorSet(GroupI group) { super(); OP_ADD.setPFMC(new GAdd(group)); OP_SUBTRACT.setPFMC(new GSubtract(group)); OP_MULTIPLY.setPFMC(new GMultiply(group)); OP_DIVIDE.setPFMC(new GDivide(group)); OP_MOD.setPFMC(new GMod(group)); OP_POWER.setPFMC(new GPower(group)); OP_UMINUS.setPFMC(new GUMinus(group)); OP_LT.setPFMC(new GComparative(group,Comparative.LT)); OP_GT.setPFMC(new GComparative(group,Comparative.GT)); OP_LE.setPFMC(new GComparative(group,Comparative.LE)); OP_GE.setPFMC(new GComparative(group,Comparative.GE)); OP_NE.setPFMC(new GComparative(group,Comparative.NE)); OP_EQ.setPFMC(new GComparative(group,Comparative.EQ)); OP_AND.setPFMC(new GLogical(Logical.AND)); OP_AND.setPFMC(new GLogical(Logical.OR)); OP_OR.setPFMC(new GNot()); OP_LIST.setPFMC(new GList(group)); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/GroupI.java0000644000000000000000000000253610615400352022124 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep; import org.nfunk.jep.type.*; import org.nfunk.jep.*; /** * Represents a group with an identity, and addition operator. * * @author Rich Morris * Created on 05-Mar-2004 */ public interface GroupI { /** Returns the identity element under + */ public Number getZERO(); /** Get Inverse of a number */ public Number getInverse(Number num); /** Get sum of the numbers */ public Number add(Number a,Number b); /** Get the difference of the numbers. * i.e. a + (-b) */ public Number sub(Number a,Number b); /** whether two numbers are equal */ public boolean equals(Number a,Number b); /** returns number given by the string */ public Number valueOf(String s); /** returns a number factory for creating group elements from strings. * Most groups which are subclasses of {@link org.lsmp.djep.groupJep.groups.Group Group} do not need to * implement this method. */ public NumberFactory getNumberFactory(); /** adds the standard constants for this group */ public void addStandardConstants(JEP j); /** adds the standard function for this group */ public void addStandardFunctions(JEP j); /** For groups like rings of polynomials this determins if a given element is a constant polynomial. */ public boolean isConstantPoly(Number a); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/0000755000000000000000000000000010615400352021365 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Group.java0000644000000000000000000000540110615400352023324 0ustar rootroot/* @author rich * Created on 06-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import org.lsmp.djep.groupJep.*; import org.nfunk.jep.type.*; import org.nfunk.jep.*; /** * Base abstract class for all groups. * * @author Rich Morris * Created on 06-Mar-2004 */ public abstract class Group implements GroupI { /** * Creates a default NumberFactory which calls * the {@link org.lsmp.djep.groupJep.GroupI#valueOf} method of the subclass * to create strings from numbers. */ private NumberFactory NumFac = new NumberFactory() { public Object createNumber(String s) { return valueOf(s); } /** Return an object representing ZERO the additive identity. */ public Object getZero() { return getZERO() ; } public Object createNumber(double value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(int value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(short value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(float value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(boolean value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(Number value) throws ParseException { // TODO Auto-generated method stub return null; } public Object createNumber(Complex value) throws ParseException { // TODO Auto-generated method stub return null; } public Object getOne() { // TODO Auto-generated method stub return null; } public Object getMinusOne() { // TODO Auto-generated method stub return null; } public Object getTwo() { // TODO Auto-generated method stub return null; } }; /** returns a number factory for creating group elements from strings */ public NumberFactory getNumberFactory() { return NumFac; } /** adds the standard constants for this group. * By default does nothing. */ public void addStandardConstants(JEP j) {} /** adds the standard function for this group * By default does nothing. */ public void addStandardFunctions(JEP j) {} public String toString() { return "general group"; } /** Default implementation. * Returns true. */ public boolean isConstantPoly(Number a) { return true; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/package.html0000644000000000000000000000005210615400352023643 0ustar rootroot Some predefined groups. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Zn.java0000644000000000000000000000502210615400352022616 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import org.lsmp.djep.groupJep.interfaces.*; import java.math.*; /** * The group of integers mod n. * For prime values of n this is a field, with some * nice division tables. i.e. for Z5 *
    * | 1 2 3 4
     * ------------
     * 1 | 1 2 3 4
     * 2 | 2 4 1 3
     * 3 | 3 1 4 2
     * 4 | 4 3 2 1
     * 
    *
    / | 1 2 3 4
     * ------------
     * 1 | 1 2 3 4
     * 2 | 3 1 4 2
     * 3 | 2 4 1 3
     * 4 | 4 3 2 1
     * 
    * * @author Rich Morris * Created on 05-Mar-2004 */ public class Zn extends Group implements FieldI, OrderedSetI,HasModI,HasPowerI { BigInteger modulus; /** * Operations on the reals (Implemented as BigInteger). */ private Zn() {} public Zn(BigInteger modulus) { this.modulus = modulus; } public Number getZERO() { return BigInteger.ZERO; } public Number getONE() { return BigInteger.ONE; } public Number getInverse(Number num) { BigInteger a = (BigInteger) num; return a.negate().mod(modulus); } public Number getMulInverse(Number num) { BigInteger a = (BigInteger) num; return a.modInverse(modulus); } public Number add(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.add(b).mod(modulus); } public Number sub(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.subtract(b).mod(modulus); } public Number mul(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.multiply(b).mod(modulus); } public Number div(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.multiply(b.modInverse(modulus)).mod(modulus); } public Number mod(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.mod(b).mod(modulus); } public Number pow(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.modPow(b,modulus); } public boolean equals(Number a,Number b) { return ((Integer) a).compareTo((Integer) b) == 0; } public int compare(Number a,Number b) { return ((Integer) a).compareTo((Integer) b); } public Number valueOf(String str) { BigInteger in = new BigInteger(str); return in.mod(modulus); } public String toString() { return "Integers mod "+this.modulus; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/BigReals.java0000644000000000000000000000470110615400352023722 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import java.math.*; import org.lsmp.djep.groupJep.interfaces.*; /** * The field of Reals represented by BigDecimals. * TODO Sorry power is not implemented. * @see BigDecimal * * @author Rich Morris * Created on 05-Mar-2004 */ public class BigReals extends Group implements FieldI,OrderedSetI { private BigDecimal ZERO = BigDecimal.valueOf(0); private BigDecimal ONE = BigDecimal.valueOf(1); private int roundMode; private int scale; /** private constructor as a scale must be specified. */ private BigReals() {} /** Create a field of BigIntegers. * The round mode and scale are used during the div * method which calls {@link java.math.BigDecimal#divide(BigDecimal,int,int)}. * if scale is negative then the * {@link java.math.BigDecimal#divide(BigDecimal,int)}. is called instead. */ public BigReals(int scale,int roundMode) { this.roundMode = roundMode; this.scale = scale; } /** Create a BigReals group with round mode set to * BigDecimal.ROUND_HALF_DOWN. * * @param scale */ public BigReals(int scale) { this.roundMode = BigDecimal.ROUND_HALF_DOWN; this.scale = scale; } public Number getZERO() { return ZERO; } public Number getONE() { return ONE; } public Number getInverse(Number num) { BigDecimal a = (BigDecimal) num; return a.negate(); } public Number getMulInverse(Number num) { return div(ONE,num); } public Number add(Number num1, Number num2) { BigDecimal a = (BigDecimal) num1; BigDecimal b = (BigDecimal) num2; return a.add(b); } public Number sub(Number num1, Number num2) { BigDecimal a = (BigDecimal) num1; BigDecimal b = (BigDecimal) num2; return a.subtract(b); } public Number mul(Number num1, Number num2) { BigDecimal a = (BigDecimal) num1; BigDecimal b = (BigDecimal) num2; return a.multiply(b); } public Number div(Number num1, Number num2) { BigDecimal a = (BigDecimal) num1; BigDecimal b = (BigDecimal) num2; if(scale>0) return a.divide(b,scale,roundMode); return a.divide(b,roundMode); } public boolean equals(Number a,Number b) { return ((BigDecimal) a).compareTo((BigDecimal) b) == 0; } public int compare(Number a,Number b) { return ((BigDecimal) a).compareTo((BigDecimal) b); } public Number valueOf(String str) { return new BigDecimal(str); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/ExtendedFreeGroup.java0000644000000000000000000000345510615400352025616 0ustar rootroot/* @author rich * Created on 07-Dec-2004 */ package org.lsmp.djep.groupJep.groups; import org.lsmp.djep.groupJep.interfaces.*; import org.lsmp.djep.groupJep.values.*; import org.nfunk.jep.type.*; /** * An extended version of a Free Group, limted seport for powers and division. * Positive integer powers are allowed and division by constants. * TODO implement polynomial division and remainder (mod). * * @author Rich Morris * Created on 07-Dec-2004 */ public class ExtendedFreeGroup extends FreeGroup implements HasPowerI, HasDivI { public ExtendedFreeGroup(RingI K, String symbol) { super(K, symbol); } /** Limited implementation of power, only works with integer powers. * Second argument should be an Integer. */ public Number pow(Number a, Number b) { FreeGroupElement exp = (FreeGroupElement) b; if(!isConstantPoly(exp)) throw new IllegalArgumentException("Powers only supported for integer exponant. Current exponant is "+exp.toString()); Complex c = exp.getComplexValue(); if(c.im() != 0.0) throw new IllegalArgumentException("Powers only supported for integer exponant. Current exponant is "+exp.toString()); double re = c.re(); if(Math.floor(re) != re) throw new IllegalArgumentException("Powers only supported for integer exponant. Current exponant is "+exp.toString()); return ((FreeGroupElement) a).pow((int) re); } /** Currently just division by constants. Polynomial division to come. * */ public Number div(Number a, Number b) { return ((FreeGroupElement) a).div((FreeGroupElement) b); } /** Division of Polynomials, discards remainder. * Not yet implemented. */ // public Number mod(Number a, Number b) { // return null; // //return ((FreeGroupElement) a).mod((FreeGroupElement) b); // } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Rationals.java0000644000000000000000000000304710615400352024170 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import java.math.*; import org.lsmp.djep.groupJep.interfaces.*; import org.lsmp.djep.groupJep.values.*; /** * The Field of rational numbers. * * @author Rich Morris * Created on 05-Mar-2004 */ public class Rationals extends Group implements FieldI,OrderedSetI,HasPowerI { private Rational ZERO = new Rational(BigInteger.valueOf(0)); private Rational ONE = new Rational(BigInteger.valueOf(1)); public Rationals() {} public Number getZERO() { return ZERO; } public Number getONE() { return ONE; } public Number getInverse(Number num) { return ((Rational) num).negate(); } public Number getMulInverse(Number num) { return ((Rational) num).inverse(); } public Number add(Number a, Number b) { return ((Rational) a).add((Rational) b); } public Number sub(Number a, Number b) { return ((Rational) a).sub((Rational) b); } public Number mul(Number a, Number b) { return ((Rational) a).mul((Rational) b); } public Number div(Number a, Number b) { return ((Rational) a).div((Rational) b); } public Number pow(Number a, Number b) { return ((Rational) a).pow((Rational) b); } public boolean equals(Number a,Number b) { return ((Rational) a).compareTo(b) == 0; } public int compare(Number a,Number b) { return ((Rational) a).compareTo(b); } public Number valueOf(String s) { return Rational.valueOf(s); } public String toString() { return "Q"; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Integers.java0000644000000000000000000000404410615400352024012 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import java.math.*; import org.lsmp.djep.groupJep.interfaces.*; /** * The group of integers, implemented as a BigInteger. * @see java.math.BigInteger * @author Rich Morris * Created on 05-Mar-2004 */ public class Integers extends Group implements IntegralDomainI,HasDivI, OrderedSetI,HasModI,HasPowerI { /** * Operations on the reals (Implemented as BigInteger). */ public Integers() { } public Number getZERO() { return BigInteger.ZERO; } public Number getONE() { return BigInteger.ONE; } public Number getInverse(Number num) { BigInteger a = (BigInteger) num; return a.negate(); } public Number add(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.add(b); } public Number sub(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.subtract(b); } public Number mul(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.multiply(b); } public Number div(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.divide(b); } /* note -3 mod 2 is 1 rather than -1 as for % in java language specifications. */ public Number mod(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.remainder(b); } public Number pow(Number num1, Number num2) { BigInteger a = (BigInteger) num1; BigInteger b = (BigInteger) num2; return a.pow(b.intValue()); } public boolean equals(Number a,Number b) { return ((BigInteger) a).compareTo((BigInteger) b) == 0; } public int compare(Number a,Number b) { return ((BigInteger) a).compareTo((BigInteger) b); } public Number valueOf(String str) { return new BigInteger(str); } public String toString() { return "Z: integers"; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Reals.java0000644000000000000000000000324110615400352023276 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import org.lsmp.djep.groupJep.interfaces.*; /** * A representation of the Reals where elements are represented as Doubles. * * @author Rich Morris * Created on 05-Mar-2004 */ public class Reals extends Group implements FieldI,OrderedSetI,HasPowerI { private Double ZERO = new Double(0.0); private Double ONE = new Double(1.0); /** * Operations on the reals (Implemented as Doubles). */ public Reals() { } public Number getZERO() { return ZERO; } public Number getONE() { return ONE; } public Number getInverse(Number num) { return new Double(1.0/num.doubleValue()); } public Number getMulInverse(Number num) { return new Double(1.0 / num.doubleValue()); } public Number add(Number a, Number b) { return new Double(a.doubleValue()+b.doubleValue()); } public Number sub(Number a, Number b) { return new Double(a.doubleValue()-b.doubleValue()); } public Number mul(Number a, Number b) { return new Double(a.doubleValue()*b.doubleValue()); } public Number div(Number a, Number b) { return new Double(a.doubleValue()/b.doubleValue()); } public Number pow(Number a, Number b) { return new Double(Math.pow(a.doubleValue(),b.doubleValue())); } public Number valueOf(String str) { return new Double(str); } public boolean equals(Number a,Number b) { return ((Double) a).compareTo((Double) b) == 0; } public int compare(Number a,Number b) { return ((Double) a).compareTo((Double) b); } public String toString() { return "Reals (represented as Doubles)"; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/Quaternions.java0000644000000000000000000000621310615400352024542 0ustar rootroot/* @author rich * Created on 16-May-2004 */ package org.lsmp.djep.groupJep.groups; import org.nfunk.jep.JEP; import org.lsmp.djep.groupJep.interfaces.*; /** * Possibly the Quaternions, completely untested. * * @author Rich Morris * Created on 16-May-2004 */ public class Quaternions extends Group implements RingI { public static class Quaternion extends Number { double x,y,z,w; public Quaternion(double x,double y,double z,double w){ this.w = x; this.y = y; this.z=z; this.w=w; } public double doubleValue() {return x;} public float floatValue() {return (float) x;} public int intValue() {return (int) x;} public long longValue() {return (long) x;} // TODO pretty print so 0 + 0 i + 0 j + 1 k printed as k public String toString() {//return ""+x+"+"+y+" i +"+z+" j +"+w+" k"; StringBuffer sb = new StringBuffer(); boolean flag=false; if(x!=0.0) { sb.append(x); flag = true; } if(y!=0.0) { if(flag && y>0.0) sb.append("+"); if(y==1.0) {} else if(y==-1.0) { sb.append("-"); } else sb.append(y); sb.append("i"); flag=true; } if(z!=0.0) { if(flag && z>0.0) sb.append("+"); if(z==1.0) {} else if(z==-1.0) { sb.append("-"); } else sb.append(z); sb.append("j"); flag=true; } if(w!=0.0) { if(flag && w>0.0) sb.append("+"); if(w==1.0) {} else if(w==-1.0) { sb.append("-"); } else sb.append(w); sb.append("k"); flag=true; } if(!flag) sb.append("0"); return sb.toString(); } } private Quaternion ZERO = new Quaternion(0,0,0,0); private Quaternion ONE = new Quaternion(1,0,0,0); private Quaternion I = new Quaternion(0,1,0,0); private Quaternion J = new Quaternion(0,0,1,0); private Quaternion K = new Quaternion(0,0,0,1); public Number getZERO() {return ZERO;} public Number getONE() {return ONE; } public Number getInverse(Number num) { Quaternion q = (Quaternion) num; return new Quaternion(-q.x,-q.y,-q.z,-q.w); } public Number add(Number a, Number b) { Quaternion p = (Quaternion) a; Quaternion q = (Quaternion) b; return new Quaternion(p.x+q.x,p.y+q.y,p.z+q.z,p.w+q.w); } public Number sub(Number a, Number b) { Quaternion p = (Quaternion) a; Quaternion q = (Quaternion) b; return new Quaternion(p.x-q.x,p.y-q.y,p.z-q.z,p.w-q.w); } public Number mul(Number a, Number b) { Quaternion p = (Quaternion) a; Quaternion q = (Quaternion) b; return new Quaternion( p.x*q.x - p.y*q.y - p.z*q.z - p.w*q.w, p.x*q.y - p.y*q.x + p.z*q.w - p.w*q.z, p.x*q.z - p.y*q.w + p.z*q.x + p.w*q.y, p.x*q.w - p.y*q.z - p.z*q.y + p.w*q.x ); } public boolean equals(Number a, Number b) { Quaternion p = (Quaternion) a; Quaternion q = (Quaternion) b; return (p.x==q.x)&&(p.y==q.y)&&(p.z==q.z)&&(p.w==q.w); } public Number valueOf(String s) { return new Quaternion(Double.parseDouble(s),0,0,0); } public void addStandardConstants(JEP j) { super.addStandardConstants(j); j.addConstant("i",I); j.addConstant("j",J); j.addConstant("k",K); } public String toString() {return "Quaternions";} } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/groups/AlgebraicExtension.java0000644000000000000000000000625510615400352026006 0ustar rootroot/* @author rich * Created on 09-Mar-2004 */ package org.lsmp.djep.groupJep.groups; import org.lsmp.djep.groupJep.interfaces.*; import org.lsmp.djep.groupJep.values.*; import org.nfunk.jep.type.*; /** * An Algebraic Extension of a Ring. * The ring generated by {1,t,...,t^n-1} where t is an algebraic number * i.e t is be a root of a monic polynomial equation. * * @see AlgebraicExtensionElement * @author Rich Morris * Created on 09-Mar-2004 */ public class AlgebraicExtension extends ExtendedFreeGroup implements RingI { private Polynomial poly; private Polynomial poly2; /** * Create the ring K(t) where t is a solution of the monic polynomial p. * * @param K the Ring this is an extension of. * @param poly A monic polynomial whose solution gives an algebraic number which is used to generate this group. * @throws IllegalArgumentException if the base ring of the poly is not the same. * @throws IllegalArgumentException if the polynomial is not monic. */ public AlgebraicExtension(RingI K, Polynomial poly) { super(K,poly.getSymbol()); this.poly = poly; if(baseRing != poly.getBaseRing()) throw new IllegalArgumentException("The polynomial should be specified over the same base ring"); // test for monic if(!baseRing.equals( poly.getCoeffs()[poly.getDegree()], baseRing.getONE())) throw new IllegalArgumentException("poly "+poly.toString()+" should be monic"); // construct q = t^n - poly (deg n-1) Number coeffs[] = new Number[poly.getDegree()]; for(int i=0;i0;--i) if(!baseRing.equals(coeffs[i],baseRing.getZERO())) { deg=i; break; } if(deg == coeffs.length-1) this.coeffs = coeffs; else { this.coeffs = new Number[deg+1]; System.arraycopy(coeffs,0,this.coeffs,0,deg+1); } this.degree = deg; } /** Sub classes can change the coefficients. Other methods * should treat polynomials as imutable. */ protected void setCoeffs(Number coeffs[]) { this.coeffs = coeffs; this.degree = coeffs.length-1; } /** Factory method to create a polynomial with the given coefficients. * Sub classes should overwrite this method to costruct objects of the correct type. */ protected Polynomial valueOf(Number lcoeffs[]) { Polynomial p = new Polynomial(baseRing,symbol,lcoeffs); return p; } public Polynomial add(Polynomial poly) { int deg = degree > poly.degree ? degree : poly.degree; Number lcoeffs[] = new Number[deg+1]; for(int i=0;i<=deg;++i) { if(i<=degree && i <= poly.degree) lcoeffs[i] = baseRing.add(coeffs[i],poly.coeffs[i]); else if(i<=degree) lcoeffs[i] = coeffs[i]; else lcoeffs[i] = poly.coeffs[i]; } return valueOf(lcoeffs); } public Polynomial sub(Polynomial poly) { int deg = degree > poly.degree ? degree : poly.degree; Number lcoeffs[] = new Number[deg+1]; for(int i=0;i<=deg;++i) { if(i<=degree && i <= poly.degree) lcoeffs[i] = baseRing.sub(coeffs[i],poly.coeffs[i]); else if(i<=degree) lcoeffs[i] = coeffs[i]; else lcoeffs[i] = baseRing.getInverse(poly.coeffs[i]); } return valueOf(lcoeffs); } public Polynomial mul(Polynomial poly) { int deg = degree + poly.degree; Number lcoeffs[] = new Number[deg+1]; for(int i=0;i<=deg;++i) lcoeffs[i] = baseRing.getZERO(); for(int i=0;i<=degree;++i) for(int j=0;j<=poly.degree;++j) { lcoeffs[i+j] = baseRing.add(lcoeffs[i+j], baseRing.mul(coeffs[i],poly.coeffs[j])); } return valueOf(lcoeffs); } public Polynomial div(Polynomial poly) { if(!poly.isConstantPoly()) throw new IllegalArgumentException("Can currently only divide by numbers and not polynomials"); int deg = coeffs.length-1; Number lcoeffs[] = new Number[deg+1]; for(int i=0;i>= 1; if(exp == 0) break; currentPower = currentPower.mul(currentPower); } return res; } private boolean needsBrackets(String s) { int i1 = s.indexOf('+'); int i2 = s.lastIndexOf('-'); return ( (i1 !=-1) || (i2>0) ); } public String toString() { if(degree==0) return coeffs[0].toString(); StringBuffer sb = new StringBuffer(""); for(int i=degree;i>=0;--i) { String s = coeffs[i].toString(); // don't bother if a zero coeff if(s.equals("0") || this.baseRing.equals(coeffs[i],baseRing.getZERO())) continue; // apart from first add a + sign if positive if(i!=degree && !s.startsWith("-")) sb.append("+"); // always print the final coeff (if non zero) if( i==0 ) { String s1 = coeffs[i].toString(); sb.append(s1); //if(s1.startsWith("(") && s1.endsWith(")")) //{ // sb.append(s1.substring(1,s1.length()-1)); //} //else sb.append(s1); break; } // if its -1 t^i just print - if(s.equals("-1")) sb.append("-"); else if(s.equals("1") || this.baseRing.equals( coeffs[i], baseRing.getONE())) {} // don't print 1 else { if(needsBrackets(coeffs[i].toString())) { sb.append("("); sb.append(coeffs[i].toString()); sb.append(")"); } else sb.append(coeffs[i].toString()); //sb.append(stripBrackets(coeffs[i])); sb.append(" "); } if(i>=2) sb.append(symbol+"^"+i); else if(i==1) sb.append(symbol); } sb.append(""); return sb.toString(); } public int getDegree() { return degree; } public String getSymbol() { return symbol; } /** Returns the coefficients of polynomial. * TODO use defensive copying * @return the array of coefficients, constant coefficient is element 0. */ public Number[] getCoeffs() { return coeffs; } public Number getCoeff(int i) { return coeffs[i]; } public RingI getBaseRing() { return baseRing; } /** value of constant coeff. */ public int intValue() {return coeffs[0].intValue(); } /** value of constant coeff. */ public long longValue() {return coeffs[0].longValue(); } /** value of constant coeff. */ public float floatValue() { return coeffs[0].floatValue(); } /** value of constant coeff. */ public double doubleValue() {return coeffs[0].doubleValue(); } /** Is this a constant polynomial? **/ public boolean isConstantPoly() { if( coeffs.length > 1) return false; return baseRing.isConstantPoly(coeffs[0]); } public boolean equals(Polynomial n) { if(this.getDegree()!=n.getDegree()) return false; for(int i=0;i<=this.getDegree();++i) if(!baseRing.equals(this.getCoeff(i),n.getCoeff(i))) return false; return true; } /** returns the complex value of this polynomial. * Where the value of the symbol is replaced by rootVal. */ public Complex calculateComplexValue(Complex rootVal) { Number val = coeffs[this.getDegree()]; Complex cval = GroupJep.complexValueOf(val); for(int i=this.getDegree()-1;i>=0;--i) { Number val2 = coeffs[i]; Complex cval2 = GroupJep.complexValueOf(val2); Complex prod = cval.mul(rootVal); cval = prod.add(cval2); } return cval; } public Number calculateValue(Number rootVal) { Number val = coeffs[this.getDegree()]; for(int i=this.getDegree()-1;i>=0;--i) { Number val2 = coeffs[i]; Number prod = baseRing.mul(val,rootVal); val = baseRing.add(prod,val2); } return val; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/Rational.java0000644000000000000000000001157610615400352023773 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.values; import java.math.*; /** * A Rational number with full precision. Represented as quotien of two * numbers (always in most reduced form with posative denominator). * * @author Rich Morris * Created on 05-Mar-2004 */ public class Rational extends Number implements Comparable { private BigInteger numerator; private BigInteger denominator; /** */ private Rational() { } public Rational(BigInteger num) { numerator = num; denominator = BigInteger.ONE; } /** Rationals will always be represented in most reduced * form with a positive denominator. */ public Rational(BigInteger num,BigInteger den) { BigInteger gcd = num.gcd(den); if(gcd.equals(BigInteger.ZERO)) { numerator = denominator = BigInteger.ZERO; } else if(den.signum() > 0){ numerator = num.divide(gcd); denominator = den.divide(gcd); } else { numerator = num.divide(gcd).negate(); denominator = den.divide(gcd).negate(); } } public int intValue() { if(denominator.equals(BigInteger.ZERO)) { int sign = numerator.signum(); if(sign == 0) return Integer.MAX_VALUE; else if(sign > 0 ) return Integer.MAX_VALUE; else return Integer.MIN_VALUE; } return numerator.divide(denominator).intValue(); } public long longValue() { return numerator.divide(denominator).longValue(); } public float floatValue() { if(denominator.equals(BigInteger.ZERO)) { int sign = numerator.signum(); if(sign == 0) return Float.NaN; else if(sign > 0 ) return Float.POSITIVE_INFINITY; else return Float.NEGATIVE_INFINITY; } return numerator.divide(denominator).floatValue(); } public double doubleValue() { if(denominator.equals(BigInteger.ZERO)) { int sign = numerator.signum(); if(sign == 0) return Double.NaN; else if(sign > 0 ) return Double.POSITIVE_INFINITY; else return Double.NEGATIVE_INFINITY; } return numerator.divide(denominator).doubleValue(); } public Rational add(Rational arg) { BigInteger ad = this.numerator.multiply(arg.denominator); BigInteger bc = this.denominator.multiply(arg.numerator); BigInteger bd = this.denominator.multiply(arg.denominator); BigInteger top = ad.add(bc); return new Rational(top,bd); } public Rational sub(Rational arg) { BigInteger ad = this.numerator.multiply(arg.denominator); BigInteger bc = this.denominator.multiply(arg.numerator); BigInteger bd = this.denominator.multiply(arg.denominator); BigInteger top = ad.subtract(bc); return new Rational(top,bd); } public Rational mul(Rational arg) { BigInteger ac = this.numerator.multiply(arg.numerator); BigInteger bd = this.denominator.multiply(arg.denominator); return new Rational(ac,bd); } public Rational div(Rational arg) { BigInteger ad = this.numerator.multiply(arg.denominator); BigInteger bc = this.denominator.multiply(arg.numerator); return new Rational(ad,bc); } public Rational pow(Rational arg) { if(!arg.denominator.equals(BigInteger.ONE)) throw new ArithmeticException("Can only raise rationals to integer powers"); int exponant = arg.numerator.intValue(); if(exponant == 0) return new Rational(BigInteger.ONE); else if(exponant > 0) { BigInteger top = this.numerator.pow(exponant); BigInteger bot = this.denominator.pow(exponant); return new Rational(top,bot); } else { // (a/b)^(-c) -> (b/a)^c -> (b^c/a^c) BigInteger top = this.numerator.pow(-exponant); BigInteger bot = this.denominator.pow(-exponant); return new Rational(bot,top); } } public Rational negate() { return new Rational(numerator.negate(),denominator); } public Rational inverse() { return new Rational(denominator,numerator); } public static Number valueOf(String s) { int pos = s.indexOf('/'); if(pos==-1) return new Rational(new BigInteger(s)); return new Rational( new BigInteger(s.substring(pos-1)), new BigInteger(s.substring(pos+1,-1))); } /** * * Returns the bottom half of the rational. */ public BigInteger getDenominator() { return denominator; } /** * Returns the top half of the rational. */ public BigInteger getNumerator() { return numerator; } public String toString() { if(denominator.equals(BigInteger.ONE)) return numerator.toString(); return numerator.toString() +"/" + denominator.toString(); } public int compareTo(Object arg) { Rational num = (Rational) arg; if(this.denominator.compareTo(num.denominator) == 0) { return this.numerator.compareTo(num.numerator); } BigInteger ad = this.numerator.multiply(num.denominator); BigInteger bc = this.denominator.multiply(num.numerator); return ad.compareTo(bc); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/AlgebraicExtensionElement.java0000644000000000000000000000406210615400352027272 0ustar rootroot/* @author rich * Created on 09-Mar-2004 */ package org.lsmp.djep.groupJep.values; import org.lsmp.djep.groupJep.groups.AlgebraicExtension; /** * An element of the algrabraic extension K(t). * a0 + a1 t + a(n-1) t^(n-1) * where t is defined to be the the solution of a polynomial equation. * * @see AlgebraicExtension * @author Rich Morris * Created on 09-Mar-2004 */ public class AlgebraicExtensionElement extends FreeGroupElement { AlgebraicExtension ae; /** * An element of the algebraic extension K(t). * a0 + a1 t + a(n-1) t^(n-1) * where t is defined to be the the solution of a polynomial equation. * If the degree of the polynomial specified by coeffs is greater * than n then the polynomial will be reduced by using * the equation t^n = ..... * @param K the algebraic extension. * @param coeffs array of coefficients for this algebraic number. c0 + c1 t + ... + cn t^n */ public AlgebraicExtensionElement(AlgebraicExtension K, Number coeffs[]) { super(K,coeffs); this.ae = K; int deg_p = ae.getPoly().getDegree(); while(this.getCoeffs().length > deg_p) { Polynomial poly2 = ae.getSubsPoly(); int deg_c = this.getCoeffs().length-1; // coeffs = (a_m s^(m-n)+...+a_n) s^n + (a_(n-1) s^(n-1)+...+a_0) // = p1 * s^n + p2; // = p2 - p1 * q; Number p1Coeffs[] = new Number[deg_c-deg_p+1]; Number p2Coeffs[] = new Number[deg_p]; System.arraycopy(this.getCoeffs(),deg_p,p1Coeffs,0,deg_c-deg_p+1); System.arraycopy(this.getCoeffs(),0,p2Coeffs,0,deg_p); Polynomial p1 = new Polynomial(ae.getBaseRing(),ae.getPoly().getSymbol(),p1Coeffs); Polynomial p2 = new Polynomial(ae.getBaseRing(),ae.getPoly().getSymbol(),p2Coeffs); Polynomial p3 = p1.mul(poly2); Polynomial p4 = p3.add(p2); super.setCoeffs(p4.getCoeffs()); } } /** sub classes should overwrite this to make the correct type. */ protected Polynomial valueOf(Number lcoeffs[]) { AlgebraicExtensionElement g = new AlgebraicExtensionElement(ae,lcoeffs); return g; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/package.html0000644000000000000000000000055310615400352023631 0ustar rootroot Objects representing the elements of a group. All group elements should extend {@link java.lang.Number} and some groups elements may be standard Number types such as {@link java.math.BigInteger}. If the element has a natural conversion to the complex numbers then it should implement {@link org.lsmp.djep.groupJep.values.HasComplexValueI}. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/Permutation.java0000644000000000000000000000351510615400352024523 0ustar rootroot/* @author rich * Created on 15-Mar-2004 */ package org.lsmp.djep.groupJep.values; import org.lsmp.djep.groupJep.*; /** * @author Rich Morris * Created on 15-Mar-2004 */ public class Permutation extends Number { protected GroupI group; protected Integer perm[]; protected int len; /** * */ public Permutation(GroupI group,Integer perm[]) { super(); this.group = group; this.perm = perm; this.len = perm.length; } public Permutation add(Permutation p1) { Integer res[] = new Integer[p1.perm.length]; for(int i=0;i0) sb.append(","); sb.append(this.perm[i].toString()); } sb.append("]"); return sb.toString(); } /** Just returns 0. Minimal implematation for compatability with Number. */ public double doubleValue() {return 0; } public float floatValue() {return 0; } public int intValue() { return 0; } public long longValue() {return 0; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/FreeGroupElement.java0000644000000000000000000000306010615400352025417 0ustar rootroot/* @author rich * Created on 09-Mar-2004 */ package org.lsmp.djep.groupJep.values; import org.lsmp.djep.groupJep.groups.FreeGroup; import org.nfunk.jep.type.*; /** * An element of a free group with one generator. * * @see org.lsmp.djep.groupJep.groups.FreeGroup * @author Rich Morris * Created on 09-Mar-2004 */ public class FreeGroupElement extends Polynomial implements HasComplexValueI { FreeGroup group; /** * An element of a free group with one generator. * @param K the free group. * @param coeffs array of coefficients for this element c0 + c1 t + ... + cn t^n */ public FreeGroupElement(FreeGroup K, Number coeffs[]) { super(K.getBaseRing(),K.getSymbol(),coeffs); this.group = K; } // public AlgebraicNumber(RingI baseRing,Polynomial poly,Number coeffs[]) { // this(new AlgebraicExtension(baseRing,poly),coeffs); // } /** sub classes should overwrite this to make the correct type. */ protected Polynomial valueOf(Number lcoeffs[]) { FreeGroupElement g = new FreeGroupElement(group,lcoeffs); return g; } /** Returns an approximation to the complex number representing this algebraic number. * This only gives meaningful results if setRootValue has been called * or if it is a quadratic extension (t^2+b t+c) or if it is a simple n-th root (t^n+a). * In the last two cases the root value is calculated automatically. * @return Complex(Nan) if currently unable to calculate it. */ public Complex getComplexValue() { return calculateComplexValue(group.getRootVal()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/values/HasComplexValueI.java0000644000000000000000000000051610615400352025363 0ustar rootroot/* @author rich * Created on 11-Mar-2004 */ package org.lsmp.djep.groupJep.values; import org.nfunk.jep.type.*; /** * Group elements which have a natural conversion to complex numbers. * * @author Rich Morris * Created on 11-Mar-2004 */ public interface HasComplexValueI { public Complex getComplexValue(); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/0000755000000000000000000000000010615400352022171 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/OrderedSetI.java0000644000000000000000000000063510615400352025211 0ustar rootroot/* @author rich * Created on 06-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Groups which have a total ordering, i.e <, >= make sense. * @see java.lang.Comparable * @author Rich Morris * Created on 06-Mar-2004 */ public interface OrderedSetI { /** Returns -1,0,1 depending on whether a is less than, equal to or greater than b. */ public int compare(Number a,Number b); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/package.html0000644000000000000000000000032510615400352024452 0ustar rootroot Interfaces defining behavious a group implements. The main hiearachy is GroupI -> AbelianGroupI -> RingI -> IntegralDomainI -> FieldI the other interfaces here add additional functionality. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/HasListI.java0000644000000000000000000000041710615400352024516 0ustar rootroot/* @author rich * Created on 15-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Group implements a List function [a,b,c]. * @author Rich Morris * Created on 15-Mar-2004 */ public interface HasListI { public Number list(Number eles[]); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/FieldI.java0000644000000000000000000000062210615400352024170 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Represents a field. * Abelian group for + with inverse 0. * Elements excluding 0 form a abelian group. * * @author Rich Morris * Created on 05-Mar-2004 */ public interface FieldI extends IntegralDomainI,HasDivI { /** get mul inverse */ public Number getMulInverse(Number num); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/HasPowerI.java0000644000000000000000000000042010615400352024671 0ustar rootroot/* @author rich * Created on 06-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Group has a power operator a ^ b. * * @author Rich Morris * Created on 06-Mar-2004 */ public interface HasPowerI { public Number pow(Number a,Number b); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/HasModI.java0000644000000000000000000000041410615400352024317 0ustar rootroot/* @author rich * Created on 06-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Group has a mod operator a % b. * * @author Rich Morris * Created on 06-Mar-2004 */ public interface HasModI { public Number mod(Number a,Number b); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/AbelianGroupI.java0000644000000000000000000000044710615400352025522 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; import org.lsmp.djep.groupJep.*; /** * Represents a abelian (commutative) group. * * @author Rich Morris * Created on 05-Mar-2004 */ public interface AbelianGroupI extends GroupI { } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/IntegralDomainI.java0000644000000000000000000000065510615400352026050 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * A RingI which has a multiplicative indentity. * Does not add any functionality as RingI defines the * public Number getMulIdentity(); * * @author Rich Morris * Created on 05-Mar-2004 */ public interface IntegralDomainI extends RingI { /** get multiplicative identity */ //public Number getMulIdentity(); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/RingI.java0000644000000000000000000000117710615400352024052 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * Defines the operations on a ring, i.e. an abelian group * under + with a closed * operator and * distributitive over +. * * @author Rich Morris * Created on 05-Mar-2004 */ public interface RingI extends AbelianGroupI { /** Returns the product of two numbers, a*b */ public Number mul(Number a,Number b); /** Get multiplicative identity i.e. 1. * Strictly speaking a ring need not have a mul indentity. * However most useful ones do, and they are not * all integral domains. */ public Number getONE(); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/interfaces/HasDivI.java0000644000000000000000000000065410615400352024330 0ustar rootroot/* @author rich * Created on 05-Mar-2004 */ package org.lsmp.djep.groupJep.interfaces; /** * An IntergralDomainI which also has a notion of division, * which is not necessarily closed i.e. the integers. * * @author Rich Morris * Created on 05-Mar-2004 */ public interface HasDivI { /** get division of two numbers. i.e. a * ( b^-1). * Strictly speeking */ public Number div(Number a,Number b); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/groupJep/PolynomialVisitor.java0000644000000000000000000000436210615400352024421 0ustar rootroot/* @author rich * Created on 05-Oct-2004 */ package org.lsmp.djep.groupJep; import org.nfunk.jep.*; import org.lsmp.djep.groupJep.values.*; import org.lsmp.djep.groupJep.groups.*; import org.lsmp.djep.xjep.*; /** * Constructs a polynomial from a JEP equation. * * @author Rich Morris * Created on 05-Oct-2004 */ public class PolynomialVisitor extends DoNothingVisitor { private OperatorSet opSet; private FreeGroup fg; /** * */ public PolynomialVisitor(JEP j) { super(); opSet = j.getOperatorSet(); } /** * calculates a polynomial representing the node. * @param node The top node of the expression * @param fg The group the polynomial is an element of. * @return the polynomial representing the equation * @throws ParseException if the node cannot be converted to a Polynomial */ public Polynomial calcPolynomial(Node node,FreeGroup fg) throws ParseException { this.fg = fg; return (Polynomial) node.jjtAccept(this,null); } public Object visit(ASTFunNode node, Object data) throws ParseException { int nchild = node.jjtGetNumChildren(); Polynomial children[] = new Polynomial[nchild]; for(int i=0;i

    Classes to perform differentiation of equations and various utility classes. The main class is {@link org.lsmp.djep.djep.DifferentiationVisitor DifferentiationVisitor} which performs the differentation by repeated applications of the chain, product and quotient rules. Typically the result of differentation should be simplified to remove occurences of redundant expressions (for example diff(x^2.0,x) is 2.0*x^1.0*1.0 which is simplified to 2.0*x).

    For each function, a rule is used to specify how to differentiate it. For example, the differative of sin is specified using

    addDiffRule(new MacroDiffRules(Jep,"sin","cos(x)"))
    There are various classes of differentiation rules which all implement {@link org.lsmp.djep.djep.DiffRulesI DiffRulesI} and have special behaviours.

    Variables can also be differentiated, and the derivative of y with respect to x will be represented by the {@link org.lsmp.djep.djep.PartialDerivative PartialDerivative} dy/dx. To allow this, the {@link org.lsmp.djep.djep.DVariable DVariable} is used to represent variable and {@link org.lsmp.djep.djep.DSymbolTable DSymbolTable} and {@link org.lsmp.djep.djep.DVariableFactory DVariableFactory} are used to control the look up of variables and the creation of new variables.

    Sub-packages
    org.lsmp.djep.djep.diffRules Classes defining how to perform differentation of given functions.
    @see DJep documentation jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/DifferentiationVisitor.java0000644000000000000000000001573210615400352024542 0ustar rootroot/* @author rich * Created on 18-Jun-2003 */ package org.lsmp.djep.djep; import org.lsmp.djep.djep.diffRules.*; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import java.util.Hashtable; import java.util.Enumeration; import java.io.PrintStream; /** * A class for performing differentation of an expression. * To use do *
     * JEP j = ...; Node in = ...;
     * DifferentiationVisitor dv = new DifferentiationVisitor(jep);
     * dv.addStandardDiffRules();
     * Node out = dv.differentiate(in,"x");
     * 
    * The class follows the visitor pattern described in * {@link org.nfunk.jep.ParserVisitor ParserVisitor}. * The rules for differentiating specific functions are contained in * object which implement * {@link DiffRulesI DiffRulesI} * A number of inner classes which use this interface are defined for specific * function types. * In particular * {@link MacroDiffRules MacroDiffRules} * allow the rule for differentiation to be specified by strings. * New rules can be added using * {@link DJep#addDiffRule} method. * @author R Morris * Created on 19-Jun-2003 */ public class DifferentiationVisitor extends DeepCopyVisitor { private static final boolean DEBUG = false; private DJep localDJep; private DJep globalDJep; private NodeFactory nf; private TreeUtils tu; // private OperatorSet opSet; /** * Construction with a given set of tree utilities */ public DifferentiationVisitor(DJep jep) { this.globalDJep = jep; } /** The set of all differentation rules indexed by name of function. */ Hashtable diffRules = new Hashtable(); /** Adds the rules for a given function. */ void addDiffRule(DiffRulesI rule) { diffRules.put(rule.getName(),rule); if(DEBUG) System.out.println("Adding rule for "+rule.getName()); } /** finds the rule for function with given name. */ DiffRulesI getDiffRule(String name) { return (DiffRulesI) diffRules.get(name); } /** * Prints all the differentation rules for all functions on System.out. */ public void printDiffRules() { printDiffRules(System.out); } /** * Prints all the differentation rules for all functions on specified stream. */ public void printDiffRules(PrintStream out) { out.println("Standard Functions and their derivatives"); for(Enumeration en = globalDJep.getFunctionTable().keys(); en.hasMoreElements();) { String key = (String) en.nextElement(); PostfixMathCommandI value = globalDJep.getFunctionTable().get(key); DiffRulesI rule = (DiffRulesI) diffRules.get(key); if(rule==null) out.print(key+" No diff rules specified ("+value.getNumberOfParameters()+" arguments)."); else out.print(rule.toString()); out.println(); } for(Enumeration en = diffRules.keys(); en.hasMoreElements();) { String key = (String) en.nextElement(); DiffRulesI rule = (DiffRulesI) diffRules.get(key); if(!globalDJep.getFunctionTable().containsKey(key)) { out.print(rule.toString()); out.println("\tnot in JEP function list"); } } } /** * Differentiates an expression tree wrt a variable var. * @param node the top node of the expression tree * @param var the variable to differentiate wrt * @return the top node of the differentiated expression * @throws ParseException if some error occurred while trying to differentiate, for instance of no rule supplied for given function. * @throws IllegalArgumentException */ public Node differentiate(Node node,String var,DJep djep) throws ParseException,IllegalArgumentException { this.localDJep = djep; this.nf=djep.getNodeFactory(); this.tu=djep.getTreeUtils(); //this.opSet=djep.getOperatorSet(); if (node == null) throw new IllegalArgumentException("node parameter is null"); if (var == null) throw new IllegalArgumentException("var parameter is null"); Node res = (Node) node.jjtAccept(this,var); return res; } /********** Now the recursive calls to differentiate the tree ************/ /** * Applies differentiation to a function. * Used the rules specified by objects of type {@link DiffRulesI}. * @param node The node of the function. * @param data The variable to differentiate wrt. **/ public Object visit(ASTFunNode node, Object data) throws ParseException { String name = node.getName(); //System.out.println("FUN: "+ node + " nchild "+nchild); Node children[] = TreeUtils.getChildrenAsArray(node); Node dchildren[] = acceptChildrenAsArray(node,data); if(node.getPFMC() instanceof DiffRulesI) { return ((DiffRulesI) node.getPFMC()).differentiate(node,(String) data,children,dchildren,localDJep); } DiffRulesI rules = (DiffRulesI) diffRules.get(name); if(rules != null) return rules.differentiate(node,(String) data,children,dchildren,localDJep); throw new ParseException("Sorry I don't know how to differentiate "+node+"\n"); } public boolean isConstantVar(XVariable var) { if(!var.hasEquation()) return true; Node eqn = var.getEquation(); if(eqn instanceof ASTConstant) return true; /* So why would we want a=x to be treated as a constant? */ // if(eqn instanceof ASTVarNode) { // return isConstantVar((XVariable)((ASTVarNode) eqn).getVar()); // } return false; } /** * Differentiates a variable. * May want to alter behaviour when using multi equation as diff(f,x) * might not be zero. * @return 1 if the variable has the same name as data, 0 if the variable has a different name. */ public Object visit(ASTVarNode node, Object data) throws ParseException { String varName = (String) data; XVariable var = (XVariable) node.getVar(); PartialDerivative deriv=null; if(var instanceof DVariable) { DVariable difvar = (DVariable) var; if(varName.equals(var.getName())) return nf.buildConstantNode(tu.getONE()); else if(isConstantVar(var)) return nf.buildConstantNode(tu.getZERO()); deriv = difvar.findDerivative(varName,localDJep); } else if(var instanceof PartialDerivative) { if(isConstantVar(var)) return nf.buildConstantNode(tu.getZERO()); PartialDerivative pvar = (PartialDerivative) var; DVariable dvar = pvar.getRoot(); deriv = dvar.findDerivative(pvar,varName,localDJep); } else throw new ParseException("Encountered non differentiable variable"); Node eqn = deriv.getEquation(); if(eqn instanceof ASTVarNode) return nf.buildVariableNode(((ASTVarNode) eqn).getVar()); if(eqn instanceof ASTConstant) return nf.buildConstantNode(((ASTConstant)eqn).getValue()); return nf.buildVariableNode(deriv); } /** * Differentiates a constant. * @return 0 derivatives of constants are always zero. */ public Object visit(ASTConstant node, Object data) throws ParseException { return nf.buildConstantNode(tu.getZERO()); } } /*end*/ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/0000755000000000000000000000000010615400352021120 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/MacroDiffRules.java0000644000000000000000000002044610615400352024636 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.nfunk.jep.*; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.xjep.*; import org.nfunk.jep.function.PostfixMathCommandI; /** * Rules are specfied by a set of strings or trees of nodes. * The standard chain rule is applied *
    diff(f(g(x),h(x)),x) -> df/dg dg/dx + df/dh dh/dx
    * for example *
       * DifferentiationVisitor dv = new DifferentiationVisitor(new TreeUtils(jep));
       * DiffRulesI rule = new MacroDiffRules(dv,"sin","cos(x)");
       * 
    **/ public class MacroDiffRules extends ChainRuleDiffRules { /** * Create a differention rule for function with 1 argument * @param inName name of function * @param node a tree represention differation of function wrt "x" * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,Node node) throws ParseException { name = inName; pfmc = djep.getFunctionTable().get(inName); if(pfmc!=null) { int nParam = pfmc.getNumberOfParameters(); if(nParam != 1) throw new ParseException("Number of rules must match number of parameters for "+inName+" which is "+nParam); } rules = new Node[1]; rules[0] = node; //fixVarNames(); } /** * Create a differention rule for function with 1 argument * @param inName name of function * @param rule a string represention differation of a function wrt "x" * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,String rule) throws ParseException { this(djep,inName,djep.getFunctionTable().get(inName),rule); } /** * Create a differention rule for function with 1 argument * @param inName name of function * @param inPfmc PostfixMathCommandI for function * @param rule a string represention differation of function wrt "x" * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,PostfixMathCommandI inPfmc,String rule) throws ParseException { //super(dv); name = inName; pfmc = inPfmc; if(pfmc!=null) { int nParam = pfmc.getNumberOfParameters(); if(nParam != 1) throw new ParseException("Number of rules must match number of parameters for "+inName+" which is "+nParam); } XSymbolTable localSymTab = (XSymbolTable) ((XSymbolTable) djep.getSymbolTable()).newInstance(); //new SymbolTable(); localSymTab.copyConstants(djep.getSymbolTable()); XJep localJep = djep.newInstance(localSymTab); Node node = localJep.parse(rule); rules = new Node[1]; rules[0] = node; //fixVarNames(); } /** * Create a differention rule for function with 2 arguments. * The rules must be in terms of "x" and "y" * @param inName name of function * @param inPfmc PostfixMathCommandI for function * @param rule1 a string represention differation of function wrt "x" * @param rule2 a string represention differation of function wrt "y" * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,PostfixMathCommandI inPfmc,String rule1,String rule2) throws ParseException { //super(dv); name = inName; pfmc = inPfmc; if(pfmc!=null) { int nParam = pfmc.getNumberOfParameters(); if(nParam != 2) throw new ParseException("Number of rules must match number of parameters for "+inName+" which is "+nParam); } XSymbolTable localSymTab = (XSymbolTable) ((XSymbolTable) djep.getSymbolTable()).newInstance(); //new SymbolTable(); localSymTab.copyConstants(djep.getSymbolTable()); XJep localJep = djep.newInstance(localSymTab); Node node1 = localJep.parse(rule1); Node node2 = localJep.parse(rule2); rules = new Node[2]; rules[0] = node1; rules[1] = node2; //fixVarNames(); } /** * Create a differention rule for function with 2 arguments. * The rules must be in terms of "x" and "y" * @param inName name of function * @param rule1 a string represention differation of function wrt "x" * @param rule2 a string represention differation of function wrt "y" * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,String rule1,String rule2) throws ParseException { this(djep,inName,djep.getFunctionTable().get(inName),rule1,rule2); } /** * Create a differention rule for function with 2 arguments. * The rules must be in terms of "x" and "y" * @param inName name of function * @param inPfmc PostfixMathCommandI for function * @param node1 a expression tree represention differation of function wrt "x" * @param node2 a expression tree represention differation of function wrt "y" * @throws ParseException */ /* public MacroDiffRules(DJep djep,String inName,PostfixMathCommandI inPfmc,Node node1,Node node2) throws ParseException { //super(dv); name = inName; pfmc = inPfmc; if(pfmc!=null) { int nParam = pfmc.getNumberOfParameters(); if(nParam != 2) throw new ParseException("Number of rules must match number of parameters for "+inName+" which is "+nParam); } rules = new Node[2]; rules[0] = node1; rules[1] = node2; //fixVarNames(); } */ /** * Create a differention rule for function with 2 arguments. * The rules must be in terms of "x" and "y" * @param inName name of function * @param node1 a expression tree represention differation of function wrt "x" * @param node2 a expression tree represention differation of function wrt "y" * @throws ParseException */ /* public MacroDiffRules(DJep djep,String inName,Node node1,Node node2) throws ParseException { this(djep,inName,djep.getFunctionTable().get(inName),node1,node2); } */ /** * Create a differentation rule for function with n arguments. * The rules must be in terms of "x1", "x2", ... "xn" * @param inName name of function * @param inPfmc PostfixMathCommandI for function * @throws ParseException */ public MacroDiffRules(DJep djep,String inName,PostfixMathCommandI inPfmc,String[] inRules) throws ParseException { name = inName; pfmc = inPfmc; if(pfmc!=null) { int nParam = pfmc.getNumberOfParameters(); if(nParam != inRules.length) throw new ParseException("Number of rules must match number of parameters for "+inName+" which is "+nParam); } XSymbolTable localSymTab = (XSymbolTable) ((XSymbolTable) djep.getSymbolTable()).newInstance(); //new SymbolTable(); localSymTab.copyConstants(djep.getSymbolTable()); XJep localJep = djep.newInstance(localSymTab); rules = new Node[inRules.length]; for(int i=0;i Rules specifying how to differentiate functions. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/MacroFunctionDiffRules.java0000644000000000000000000000266110615400352026343 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; /** * If your really lazy, you don't even need to workout the derivatives * of a function defined by a macro yourself. * This class will automatically calculate the rules for you. */ public class MacroFunctionDiffRules extends ChainRuleDiffRules { /** * Calculates the rules for the given function. */ public MacroFunctionDiffRules(DJep djep,MacroFunction fun) throws ParseException { name = fun.getName(); pfmc = fun; XSymbolTable localSymTab = (XSymbolTable) ((XSymbolTable) djep.getSymbolTable()).newInstance(); //new SymbolTable(); localSymTab.copyConstants(djep.getSymbolTable()); DJep localJep = (DJep) djep.newInstance(localSymTab); int nargs = fun.getNumberOfParameters(); rules = new Node[nargs]; if(nargs == 1) rules[0] = localJep.differentiate(fun.getTopNode(),"x"); else if(nargs == 2) { rules[0] = localJep.differentiate(fun.getTopNode(),"x"); rules[1] = localJep.differentiate(fun.getTopNode(),"y"); } else { for(int i=0;i df/dg * dg/dx + df/dh * dh/dx * Variable names MUST be x,y for 1 to 2 variables or * x1,x2,x3 for 3 for more variables. */ public abstract class ChainRuleDiffRules implements DiffRulesI { protected String name; protected PostfixMathCommandI pfmc; protected Node rules[]=null; // protected DifferentationVisitor dv; // protected OperatorSet opSet; // protected NodeFactory nf; /** Cannot construct outside the context of a differentation visitor. */ public ChainRuleDiffRules() {} /** returns the name of the function */ public String getName() { return name; } /** returns the PostfixMathCommandI for the function. */ public PostfixMathCommandI getPfmc() { return pfmc; } /** Returns the number of rules which should be number of arguments of function */ public int getNumRules() { return rules.length; } /** returns the i-th rule as an expression tree. */ public Node getRule(int i) { return rules[i]; } /** * Use the chain rule to differentiate. * df(g(x),h(x))/dx -> df/dg * dg/dx + df/dh * dh/dx */ public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { XOperatorSet opSet= (XOperatorSet) djep.getOperatorSet(); NodeFactory nf=djep.getNodeFactory(); FunctionTable funTab = djep.getFunctionTable(); int nRules = rules.length; if(nRules != children.length) throw new ParseException("Error differentiating "+name+" number of rules "+nRules+" != number of arguments "+children.length); if(nRules ==1) { // df(g(x))/dx -> f'(g(x)) * g'(x) Node fprime = djep.deepCopy(rules[0]); Node g = children[0]; Node fprimesub = djep.substitute(fprime,"x",g); Node gprime = dchildren[0]; return nf.buildOperatorNode(opSet.getMultiply(),fprimesub,gprime); } else if(nRules == 2) { // df(g(x),h(x))/dx -> df/dg * dg/dx + df/dh * dh/dx Node df_dg = djep.deepCopy(rules[0]); Node df_dh = djep.deepCopy(rules[1]); //Node replacements[] = new Node[]{children[0],children[1]}; Node gprime = dchildren[0]; Node hprime = dchildren[1]; df_dg = djep.substitute(df_dg,new String[]{"x","y"},children); df_dh = djep.substitute(df_dh,new String[]{"x","y"},children); // df_dg = dv.djep.substitute(df_dg,"@2",h); // df_dh = dv.djep.substitute(df_dh,"@1",g); // df_dh = dv.djep.substitute(df_dh,"@2",h); return nf.buildOperatorNode(opSet.getAdd(), nf.buildOperatorNode(opSet.getMultiply(),df_dg,gprime), nf.buildOperatorNode(opSet.getMultiply(),df_dh,hprime)); } else if(nRules < 1) { throw new ParseException("Error differentiating "+name+" zero differention rules!"); } else { String names[]=new String[nRules]; Node[] df_dg = new Node[nRules]; Node[] products = new Node[nRules]; for(int i=0;i diff(y,x)*z+y*diff(z,x) * @since 28/1/05 now works when multiply has more than two arguments. */ public class MultiplyDiffRule implements DiffRulesI { private String name; //private DifferentationVisitor dv; private MultiplyDiffRule() {} public MultiplyDiffRule(String inName) { //dv = inDv; name = inName; } Operator mulOp=null; public MultiplyDiffRule(String inName,Operator op) { //dv = inDv; name = inName; mulOp = op; } public String toString() { return name + " \t\tdiff(f*g,x) -> diff(f,x)*g+f*diff(g,x)"; } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { OperatorSet opset = djep.getOperatorSet(); NodeFactory nf = djep.getNodeFactory(); Operator op = opset.getMultiply(); if(mulOp!=null) op = mulOp; int nchild = node.jjtGetNumChildren(); if(nchild==2) return nf.buildOperatorNode(opset.getAdd(), nf.buildOperatorNode(op, dchildren[0], djep.deepCopy(children[1])), nf.buildOperatorNode(op, djep.deepCopy(children[0]), dchildren[1])); Node sums[] = new Node[nchild]; for(int i=0;i m * y^(m-1) * otherwise * diff(y^z,x) -> z * y^(z-1) * diff(y,x) + y^z * ln(z) * diff(z,x) */ public class PowerDiffRule implements DiffRulesI { private String name; private PowerDiffRule() {} public PowerDiffRule(String inName) { name = inName; } public String toString() { return name + " \t\tdiff(f*g,x) -> diff(f,x)*g+f*diff(g,x)"; } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { OperatorSet op = djep.getOperatorSet(); NodeFactory nf = djep.getNodeFactory(); TreeUtils tu = djep.getTreeUtils(); FunctionTable funTab = djep.getFunctionTable(); int nchild = node.jjtGetNumChildren(); if(nchild!=2) throw new ParseException("Too many children "+nchild+" for "+node+"\n"); // x^y -> n*(pow(x,y-1)) x' + ln(y) pow(x,y) y' if(tu.isConstant(children[1])) { ASTConstant c = (ASTConstant) children[1]; Object value = c.getValue(); if(value instanceof Double) { // x^m -> m * x^(m-1) * x' // Node a = TreeUtils.deepCopy(children[1]); // Node b = TreeUtils.deepCopy(children[0]); // Node cc = TreeUtils.createConstant( ((Double) value).doubleValue()-1.0); // Node d = opSet.buildPowerNode(b,cc); // Node e = opSet.buildMultiplyNode(a,d); return nf.buildOperatorNode(op.getMultiply(), djep.deepCopy(children[1]), nf.buildOperatorNode(op.getMultiply(), nf.buildOperatorNode(op.getPower(), djep.deepCopy(children[0]), nf.buildConstantNode( tu.getNumber(((Double) value).doubleValue()-1.0))), dchildren[0])); } return nf.buildOperatorNode(op.getMultiply(), djep.deepCopy(children[1]), nf.buildOperatorNode(op.getMultiply(), nf.buildOperatorNode(op.getPower(), djep.deepCopy(children[0]), nf.buildOperatorNode(op.getSubtract(), djep.deepCopy(children[1]), nf.buildConstantNode(tu.getONE()))), dchildren[0])); } // z * y^(z-1) * diff(y,x) + y^z * ln(z) * diff(z,x) { return nf.buildOperatorNode(op.getAdd(), nf.buildOperatorNode(op.getMultiply(), // z * y^(z-1) * diff(y,x) nf.buildOperatorNode(op.getMultiply(), // z * y^(z-1) djep.deepCopy(children[1]), // z nf.buildOperatorNode(op.getPower(), // y^(z-1) djep.deepCopy(children[0]), // y nf.buildOperatorNode(op.getSubtract(), // z-1 djep.deepCopy(children[1]), // z djep.getNodeFactory().buildConstantNode(tu.getONE()) ))), dchildren[0]), // diff(y,x) nf.buildOperatorNode(op.getMultiply(), // + y^z * ln(z) * diff(z,x) nf.buildOperatorNode(op.getMultiply(), nf.buildOperatorNode(op.getPower(), // y^z djep.deepCopy(children[0]), djep.deepCopy(children[1])), djep.getNodeFactory().buildFunctionNode("ln",funTab.get("ln"), // ln(z) new Node[]{djep.deepCopy(children[0])})), dchildren[1])); // TODO will NaturalLog always have the name "ln" } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/PassThroughDiffRule.java0000644000000000000000000000305410615400352025655 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.djep.DiffRulesI; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.PostfixMathCommandI; /** * Rules like Sum where diff(sum(a,b,c),x) -> sum(da/dx,db/dx,dc/dx) are instance of this class. **/ public class PassThroughDiffRule implements DiffRulesI { private String name; private PostfixMathCommandI pfmc; private PassThroughDiffRule() {} public PassThroughDiffRule(DJep djep,String inName) { name = inName; pfmc = djep.getFunctionTable().get(name); } public PassThroughDiffRule(String inName,PostfixMathCommandI inPfmc) { name = inName; pfmc = inPfmc; } public String toString() { if(pfmc==null) { return "" + name +"\t\tPassthrough but no math command!"; } switch(pfmc.getNumberOfParameters()) { case 0: return name + " \t\tdiff("+name+",x) -> "+name; case 1: return name + " \tdiff("+name+"(a),x) -> "+name+"(da/dx)"; case 2: return name + " \tdiff("+name+"(a,b),x) -> "+name+"(da/dx,db/dx)"; default: return name + " \tdiff("+name+"(a,b,...),x) -> "+name+"(da/dx,db/dx,...)"; } } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { return djep.getNodeFactory().buildFunctionNode(node,dchildren); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/AdditionDiffRule.java0000644000000000000000000000224110615400352025136 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.djep.DiffRulesI; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /** * Differentiates a addition with respect to var. * diff(y+z,x) -> diff(y,x)+diff(z,x) */ public class AdditionDiffRule implements DiffRulesI { private String name; /** private default constructor, a name must always be specified. */ private AdditionDiffRule() { /* nothing happening */ } public AdditionDiffRule(String inName) { name = inName; } public String toString() { return name + " \t\tdiff(f+g,x) -> diff(f,x)+diff(g,x)"; } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { int nchild = node.jjtGetNumChildren(); if(nchild!=2) throw new ParseException("Too many children "+nchild+" for "+node+"\n"); return djep.getNodeFactory().buildOperatorNode(djep.getOperatorSet().getAdd(),dchildren[0],dchildren[1]); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/DivideDiffRule.java0000644000000000000000000000304610615400352024613 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.djep.DiffRulesI; import org.lsmp.djep.xjep.*; /** * Differentiates a division with respect to var. * diff(y/z,x) -> (diff(y,x)*z-y*diff(z,x))/(z*z) */ public class DivideDiffRule implements DiffRulesI { private String name; private DivideDiffRule() {} public DivideDiffRule(String inName) { name = inName; } public String toString() { return name + " \t\tdiff(f/g,x) -> (diff(f,x)*g-f*diff(g,x))/(g*g)"; } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { XOperatorSet op = (XOperatorSet) djep.getOperatorSet(); NodeFactory nf = djep.getNodeFactory(); int nchild = node.jjtGetNumChildren(); if(nchild==2) return nf.buildOperatorNode(op.getDivide(), nf.buildOperatorNode(op.getSubtract(), nf.buildOperatorNode(op.getMultiply(), dchildren[0], djep.deepCopy(children[1])), nf.buildOperatorNode(op.getMultiply(), djep.deepCopy(children[0]), dchildren[1])), nf.buildOperatorNode(op.getMultiply(), djep.deepCopy(children[1]), djep.deepCopy(children[1]))); throw new ParseException("Too many children "+nchild+" for "+node+"\n"); } } /* end DivideDiffRule */ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/diffRules/SubtractDiffRule.java0000644000000000000000000000234610615400352025200 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep.diffRules; import org.lsmp.djep.djep.DJep; import org.lsmp.djep.djep.DiffRulesI; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /** * Diffrentiates a subtaction with respect to var. * diff(y-z,x) -> diff(y,x)-diff(z,x) */ public class SubtractDiffRule implements DiffRulesI { private String name; private SubtractDiffRule() {} public SubtractDiffRule(String inName) { name = inName; } public String toString() { return name + " \t\tdiff(f-g,x) -> diff(f,x)-diff(g,x)"; } public String getName() { return name; } public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException { int nchild = node.jjtGetNumChildren(); if(nchild==2) return djep.getNodeFactory().buildOperatorNode(djep.getOperatorSet().getSubtract(),dchildren[0],dchildren[1]); else if(nchild==1) return djep.getNodeFactory().buildOperatorNode(djep.getOperatorSet().getUMinus(),dchildren[0]); else throw new ParseException("Too many children "+nchild+" for "+node+"\n"); } } /* end SubtractDiffRule */ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/DiffRulesI.java0000644000000000000000000000255710615400352022045 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /****** Classes to implement the differentation rules **********/ /** * Holds a set of rules describing how to differentiate a function. * Each function to be differentiated should have a object which implements * this interface. * @author R Morris * Created on 18-Jun-2003 */ public interface DiffRulesI { /** * Returns the top node of of the derivative of this function * wrt to variable var. * @param var The name of variable to differentiate wrt to. * @param children the arguments of the function * @param dchildren the derivatives of each argument of the function. * @return top node of and expression tree for the derivative. * @throws ParseException if there is some problem in compiling the derivative. */ public Node differentiate(ASTFunNode node,String var,Node [] children,Node [] dchildren,DJep djep) throws ParseException; /** * Returns a string representation of the rule. */ public String toString(); /** * Returns the name of the function. * Used as index in hashtable and as way of linking with standard JEP functions. * You probably want to specify the in the constructors. */ public String getName(); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/DPrintVisitor.java0000644000000000000000000000330310615400352022617 0ustar rootroot/* @author rich * Created on 26-Feb-2004 */ package org.lsmp.djep.djep; import org.nfunk.jep.*; import org.lsmp.djep.xjep.PrintVisitor; /** * An extension of PrintVisitor which will print the equations of a variable if required. * The behaviours of this class is determined by two modes * PRINT_PARTIAL_EQNS and PRINT_VARIABLE_EQNS. * When a variable or partial derivative is encountered then * its equation may be printed. * By default equations for PartialDerivatives are printed * but equations for normal derivatives are not. * TODO might want to print eqn for y=sin(x) but not x=3 * * @author Rich Morris * Created on 26-Feb-2004 */ public class DPrintVisitor extends PrintVisitor { public static final int PRINT_PARTIAL_EQNS = 16; public static final int PRINT_VARIABLE_EQNS = 32; /** * */ public DPrintVisitor() { super(); setMode(PRINT_PARTIAL_EQNS,true); } /** Prints the variable or its equation. * Depends on the state of the flags and whether the variable has an equation. */ public Object visit(ASTVarNode node, Object data) throws ParseException { Variable var = node.getVar(); if(var instanceof PartialDerivative) { PartialDerivative deriv = (PartialDerivative) var; if(((mode & PRINT_PARTIAL_EQNS)!=0) && deriv.hasEquation()) deriv.getEquation().jjtAccept(this,null); else sb.append(node.getName()); } else if(var instanceof DVariable) { DVariable dvar = (DVariable) var; if(((mode & PRINT_VARIABLE_EQNS)!=0) && dvar.hasEquation()) dvar.getEquation().jjtAccept(this,null); else sb.append(node.getName()); } else sb.append(node.getName()); return data; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/Diff.java0000644000000000000000000000257610615400352020722 0ustar rootroot/* @author rich * Created on 04-Jul-2003 */ package org.lsmp.djep.djep; import java.util.Stack; import org.lsmp.djep.xjep.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * The diff(f,x) operator. */ public class Diff extends PostfixMathCommand implements CommandVisitorI { public Diff() { super(); super.numberOfParameters = 2; } /** * Should never be evaluated! * @throws ParseException if called by evaluator. */ public void run(Stack inStack) throws ParseException { throw new ParseException("Cannot evaluate the diff function. "); } /** * Process the differentiation specified by node. * Defines process in * @see CommandVisitorI */ public Node process(Node node,Node children[],XJep xjep) throws ParseException { Node lhs = children[0]; Node rhs = children[1]; if(!xjep.getTreeUtils().isVariable(rhs) ) { throw new ParseException("Format should be diff(f,x) where x is a variables and 1,2 are constants"); } ASTVarNode var; try { // lhs = (Node) node.jjtGetChild(0); var = (ASTVarNode) rhs; } catch(ClassCastException e) { throw new ParseException("Format should be diff(f,x) where x is a variables and 1,2 are constants"); } return ((DJep) xjep).differentiate(lhs,var.getName()); } } /* end class Diff */ jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/DVariable.java0000644000000000000000000001536110615400352021677 0ustar rootroot/* @author rich * Created on 26-Oct-2003 */ package org.lsmp.djep.djep; import java.util.*; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; /** * Holds all info about a variable. * Has a name, an equation, a dimension (or sent of dimensions if matrix or tensor) * and also a set of {@link PartialDerivative PartialDerivative}. * The derivatives are stored in a hashtable index by * the sorted names of derivatives. * i.e. d^2f/dxdy, and d^2f/dydx will both be indexed by {"x","y"}. * df/dx is indexed by {"x"}, d^2f/dx^2 is index by {"x","x"}. * Partial derivatives are calculated as required by the * findDerivative method. * @author Rich Morris * Created on 26-Oct-2003 */ public class DVariable extends XVariable { protected Hashtable derivatives = new Hashtable(); protected PartialDerivative createDerivative(String derivnames[],Node eqn) { return new PartialDerivative(this,derivnames,eqn); } /** * The constructor is package private. Variables should be created * using the VariableTable.find(Sting name) method. */ protected DVariable(String name) { super(name); } protected DVariable(String name,Object value) { super(name,value); } /** sets the equation */ public void setEquation(Node eqn) { super.setEquation(eqn); derivatives.clear(); } /** makes value and values of all derivatives invalid. **/ public void invalidateAll() { if(isConstant()) return; setValidValue(false); for(Enumeration e = derivatives.elements(); e.hasMoreElements(); ) { PartialDerivative deriv = (PartialDerivative) e.nextElement(); deriv.setValidValue(false); } } /** Produces a string to represent the derivative. * The string will be of the form "dx^2/dxdy". * This string is used to index the derivatives of a variable. * @param rootname name of the variable we are calculating the derivative of. * @param dnames An array of the names of each of the partial derivatives. * @return the string representation */ public static String makeDerivString(String rootname,String dnames[]) { StringBuffer sb = new StringBuffer(); sb.append('d'); if( dnames.length!= 1) sb.append("^" + dnames.length); sb.append(rootname); sb.append('/'); // TODO print d^2f/dxdx as d^2f/dx^2 for(int i=0;i * DJep j = new DJep(); * j.addStandardDiffRules(); * .... * Node node = j.parse("x^3"); * Node diff = j.differentiate(node,"x"); * Node simp = j.simplify(diff); * j.println(simp); * Node node2 = j.parse("diff(x^4,x)"); * Node proc = j.preprocess(node2); * Node simp2 = j.simplify(proc); * j.println(simp2); * * @author Rich Morris * Created on 16-Nov-2003 */ public class DJep extends XJep { protected DifferentiationVisitor dv = new DifferentiationVisitor(this); /** * Standard constructor. * Use this instead of JEP or XJep if differentation facilities are required. */ public DJep() { this.pv = new DPrintVisitor(); // this.vf = ; this.symTab = new DSymbolTable(new DVariableFactory()); addFunction("diff",new Diff()); //addDiffRule(new AdditionDiffRule("+")); addDiffRule(new PassThroughDiffRule("+",this.getOperatorSet().getAdd().getPFMC())); addDiffRule(new SubtractDiffRule("-")); addDiffRule(new MultiplyDiffRule("*")); addDiffRule(new DivideDiffRule("/")); addDiffRule(new PowerDiffRule("^")); addDiffRule(new PassThroughDiffRule("UMinus",this.getOperatorSet().getUMinus().getPFMC())); } /** * Differentiate an equation with respect to a variable. * @param node top node of the expression tree to differentiate. * @param name differentiate with respect to this variable. * @return the top node of a new parse tree representing the derivative. * @throws ParseException if for some reason equation cannot be differentiated, * usually if it has not been taught how to differentiate a particular function. */ public Node differentiate(Node node,String name) throws ParseException { return dv.differentiate(node,name,this); } protected DJep(DJep j) { super(j); this.dv=j.dv; } public XJep newInstance() { DJep newJep = new DJep(this); return newJep; } public XJep newInstance(SymbolTable st) { DJep newJep = new DJep(this); newJep.symTab = st; return newJep; } /** * Returns the visitor used for differentiation. Allows more advanced functions. */ public DifferentiationVisitor getDifferentationVisitor() { return dv; } /** * Adds the standard set of differentation rules. * Corresponds to all standard functions in the JEP plus a few more. *
    	   * sin,cos,tan,asin,acos,atan,sinh,cosh,tanh,asinh,acosh,atanh
    	   * sqrt,log,ln,abs,angle
    	   * sum,im,re are handled separately.
    	   * rand and mod currently un-handled
    	   * 
    	   * Also adds rules for functions not in JEP function list:
    	   * 	sec,cosec,cot,exp,pow,sgn 
    	   * 
    	   * TODO include if, min, max, sgn
    	   * 
    * @return false on error */ public boolean addStandardDiffRules() { try { addDiffRule(new MacroDiffRules(this,"sin","cos(x)")); addDiffRule(new MacroDiffRules(this,"cos","-sin(x)")); addDiffRule(new MacroDiffRules(this,"tan","1/((cos(x))^2)")); addDiffRule(new MacroDiffRules(this,"sec","sec(x) * tan(x)")); addDiffRule(new MacroDiffRules(this,"cosec","-cosec(x) * cot(x)")); addDiffRule(new MacroDiffRules(this,"cot","-(cosec(x))^2")); addDiffRule(new MacroDiffRules(this,"asin","1/(sqrt(1-x^2))")); addDiffRule(new MacroDiffRules(this,"acos","-1/(sqrt(1-x^2))")); addDiffRule(new MacroDiffRules(this,"atan","1/(1+x^2)")); addDiffRule(new MacroDiffRules(this,"sinh","cosh(x)")); addDiffRule(new MacroDiffRules(this,"cosh","sinh(x)")); addDiffRule(new MacroDiffRules(this,"tanh","1-(tanh(x))^2")); addDiffRule(new MacroDiffRules(this,"asinh","1/(sqrt(1+x^2))")); addDiffRule(new MacroDiffRules(this,"acosh","1/(sqrt(x^2-1))")); addDiffRule(new MacroDiffRules(this,"atanh","1/(1-x^2)")); addDiffRule(new MacroDiffRules(this,"sqrt","1/(2 (sqrt(x)))")); addDiffRule(new MacroDiffRules(this,"exp","exp(x)")); // this.addFunction("pow",new Pow()); // addDiffRule(new MacroDiffRules(this,"pow","y*(pow(x,y-1))","(ln(x)) (pow(x,y))")); addDiffRule(new MacroDiffRules(this,"ln","1/x")); addDiffRule(new MacroDiffRules(this,"log", // -> (1/ln(10)) /x = log(e) / x but don't know if e exists this.getNodeFactory().buildOperatorNode(this.getOperatorSet().getDivide(), this.getNodeFactory().buildConstantNode( this.getTreeUtils().getNumber(1/Math.log(10.0))), this.getNodeFactory().buildVariableNode(this.getSymbolTable().makeVarIfNeeded("x"))))); // TODO problems here with using a global variable (x) in an essentially local context addDiffRule(new MacroDiffRules(this,"abs","abs(x)/x")); addDiffRule(new MacroDiffRules(this,"atan2","-y/(x^2+y^2)","x/(x^2+y^2)")); addDiffRule(new MacroDiffRules(this,"mod","1","0")); addDiffRule(new PassThroughDiffRule(this,"sum")); addDiffRule(new PassThroughDiffRule(this,"re")); addDiffRule(new PassThroughDiffRule(this,"im")); addDiffRule(new PassThroughDiffRule(this,"rand")); MacroFunction cmplx = (MacroFunction) this.getFunctionTable().get("macrocomplex"); if(cmplx!=null) addDiffRule(new MacroFunctionDiffRules(this,cmplx)); /* addDiffRule(new PassThroughDiffRule("\"<\"",this.getOperatorSet().getLT().getPFMC())); addDiffRule(new PassThroughDiffRule("\">\"",new Comparative(1))); addDiffRule(new PassThroughDiffRule("\"<=\"",new Comparative(2))); addDiffRule(new PassThroughDiffRule("\">=\"",new Comparative(3))); addDiffRule(new PassThroughDiffRule("\"!=\"",new Comparative(4))); addDiffRule(new PassThroughDiffRule("\"==\"",new Comparative(5))); */ // addDiffRule(new DiffDiffRule(this,"diff")); // TODO do we want to add eval here? // addDiffRule(new EvalDiffRule(this,"eval",eval)); //addDiffRule(new PassThroughDiffRule("\"&&\"")); //addDiffRule(new PassThroughDiffRule("\"||\"")); //addDiffRule(new PassThroughDiffRule("\"!\"")); // also consider if, min, max, sgn, dot, cross, //addDiffRule(new MacroDiffRules(this,"sgn","0")); return true; } catch(ParseException e) { System.err.println(e.getMessage()); return false; } } /** * Adds a rule with instruction on how to differentiate a function. * @param rule */ public void addDiffRule(DiffRulesI rule) { dv.addDiffRule(rule); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/DSymbolTable.java0000644000000000000000000000210310615400352022355 0ustar rootroot/* @author rich * Created on 23-Nov-2003 */ package org.lsmp.djep.djep; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; import java.util.*; /** * A SymbolTable which works with partial derivatives of variables. * Closely linked with * {@link DVariableFactory DVariableFactory} * * @author Rich Morris * Created on 23-Nov-2003 */ public class DSymbolTable extends XSymbolTable { private static final long serialVersionUID = 6350706295032274871L; public DSymbolTable(VariableFactory varFac) { super(varFac); } /** Creates a new SymbolTable with the same variable factory as this. */ public SymbolTable newInstance() { return new DSymbolTable(this.getVariableFactory()); } public PartialDerivative getPartialDeriv(String name,String dnames[]) { DVariable var = (DVariable) getVar(name); return var.getDerivative(dnames); } public void clearValues() { for(Enumeration e = this.elements(); e.hasMoreElements(); ) { DVariable var = (DVariable) e.nextElement(); var.invalidateAll(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/djep/PartialDerivative.java0000644000000000000000000000426410615400352023465 0ustar rootroot/* @author rich * Created on 29-Oct-2003 */ package org.lsmp.djep.djep; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; import java.util.Observable; import java.util.Observer; /** * Contains infomation about a PartialDerivative of a variable. * Should * @author Rich Morris * Created on 29-Oct-2003 */ public class PartialDerivative extends XVariable implements Observer { private DVariable root; private String dnames[] = null; private String printString; /** * Protected constructor, should only be constructed * through the findDerivative method in {@link DVariable DVariable}. **/ protected PartialDerivative(DVariable var, String derivnames[]) { super(var.getName()); root = var; dnames = derivnames; printString = DVariable.makeDerivString(root.getName(),derivnames); root.addObserver(this); } protected PartialDerivative(DVariable var, String derivnames[],Node deriv) { this(var,derivnames); /*TODO could be a little cleverer just have a * partial derivative which is a constant dy/dx = 1 * don't use an equation, instead use a value. * if(deriv instanceof ASTConstant) { System.out.println("Warning constant derivative "+printString+"="+((ASTConstant) deriv).getValue()); this.setValue(((ASTConstant) deriv).getValue()); } else */ setEquation(deriv); } public String getName() { return printString; } /** * Every partial derivative has a root variable * for instance the root variable of dy/dx is y. * This method returns than variable. */ public DVariable getRoot() { return root; } public String[] getDnames() { return dnames; } public String toString() { return printString; } public PartialDerivative findDerivative(String dname,DJep jep) throws ParseException { return root.findDerivative(this,dname,jep); } /** * When the value of the root object is changed * makes the value of this partial derivative invalid. * * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void update(Observable arg0, Object arg1) { if(root.equals(arg0)) { setValidValue(false); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/0000755000000000000000000000000010615400352020216 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/0000755000000000000000000000000010615400352022043 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MMap.java0000644000000000000000000000475210615400352023550 0ustar rootroot/* @author rich * Created on 14-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.matrixJep.function; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.function.VMap; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.vectorJep.Dimensions; import org.nfunk.jep.*; /** * @author Rich Morris * Created on 14-Feb-2005 */ public class MMap extends VMap implements SpecialPreProcessorI,MatrixSpecialEvaluationI { public MatrixNodeI preprocess( ASTFunNode node, MatrixPreprocessor visitor, MatrixJep jep, MatrixNodeFactory nf) throws ParseException { Variable vars[] = getVars(node.jjtGetChild(1)); for(int i=0;i A few functions necessary for advanced matrix operations. Most matrix functions are found in {@link org.lsmp.djep.vectorJep.function} jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MPower.java0000644000000000000000000000267710615400352024133 0ustar rootroot/* @author rich * Created on 14-Feb-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.matrixJep.function; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.function.*; import org.nfunk.jep.*; /** * An overloaded Power function compatible with MatrixJep. * * @author Rich Morris * Created on 14-Feb-2005 */ public class MPower extends VPower implements SpecialPreProcessorI { /** During preprocessing sets the function to the Cross function if necessary. */ public MatrixNodeI preprocess( ASTFunNode node, MatrixPreprocessor visitor, MatrixJep jep, MatrixNodeFactory nf) throws ParseException { MatrixNodeI children[] = visitor.visitChildrenAsArray(node,null); if(node.jjtGetNumChildren()!=2) throw new ParseException("Operator "+node.getOperator().getName()+" must have two elements, it has "+children.length); Dimensions lhsDim = children[0].getDim(); Dimensions rhsDim = children[1].getDim(); if(rhsDim.equals(Dimensions.ONE)) { Dimensions dim = lhsDim; return (ASTMFunNode) nf.buildOperatorNode( node.getOperator(),children,dim); } Operator op = jep.getOperatorSet().getCross(); BinaryOperatorI bin = (BinaryOperatorI) op.getPFMC(); Dimensions dim = bin.calcDim(lhsDim,rhsDim); return (ASTMFunNode) nf.buildOperatorNode(op,children,dim); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MAssign.java0000644000000000000000000000550010615400352024247 0ustar rootrootpackage org.lsmp.djep.matrixJep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.vectorJep.*; /** * A matrix enabled assignment function. * The lhs of an assignment must be a variable. * * @author Rich Morris * Created on 23-Feb-2004 */ public class MAssign extends Assign implements MatrixSpecialEvaluationI,SpecialPreProcessorI { public MAssign() { numberOfParameters = 2; } /** The run method should not be called. * Use {@link #evaluate} instead. */ public void run(Stack s) throws ParseException { throw new ParseException("Eval should not be called by Evaluator"); } /** * A special methods for evaluating an assignment. * When an assignment is encountered, first * evaluate the rhs. Then set the value * of the lhs to the result. */ public MatrixValueI evaluate(MatrixNodeI node,MatrixEvaluator visitor,MatrixJep j) throws ParseException { if(node.jjtGetNumChildren()!=2) throw new ParseException("Assignment operator must have 2 operators."); // evaluate the value of the right-hand side. Left on top of stack MatrixValueI rhsVal = (MatrixValueI) node.jjtGetChild(1).jjtAccept(visitor,null); // Set the value of the variable on the lhs. Node lhsNode = node.jjtGetChild(0); if(lhsNode instanceof ASTMVarNode) { ASTMVarNode vn = (ASTMVarNode) lhsNode; MatrixVariableI var = (MatrixVariableI) vn.getVar(); var.setMValue(rhsVal); return rhsVal; } else if(lhsNode instanceof ASTMFunNode && ((ASTMFunNode) lhsNode).getPFMC() instanceof LValueI) { ((LValueI) ((ASTMFunNode) lhsNode).getPFMC()).set(visitor,lhsNode,rhsVal); return rhsVal; } throw new ParseException("Assignment should have a variable for the lhs."); } public MatrixNodeI preprocess( ASTFunNode node, MatrixPreprocessor visitor, MatrixJep mjep, MatrixNodeFactory nf) throws ParseException { MatrixNodeI children[] = visitor.visitChildrenAsArray(node,null); if(node.jjtGetNumChildren()!=2) throw new ParseException("Operator "+node.getOperator().getName()+" must have two elements, it has "+children.length); Dimensions rhsDim = children[1].getDim(); if(children[0] instanceof ASTVarNode) { MatrixVariable var = (MatrixVariable) ((ASTVarNode) children[0]).getVar(); var.setDimensions(rhsDim); Node copy =mjep.deepCopy(children[1]); Node simp = mjep.simplify(copy); //Node preproc = (Node) simp.jjtAccept(this,data); var.setEquation(simp); } //TODO cope with ArrayAccess. Should really set the array access equations return (ASTMFunNode) nf.buildOperatorNode(node.getOperator(),children,rhsDim); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MSum.java0000644000000000000000000000154010615400352023567 0ustar rootroot/* @author rich * Created on 24-Apr-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djep.matrixJep.function; import org.lsmp.djep.vectorJep.Dimensions; import org.lsmp.djep.vectorJep.function.NaryOperatorI; import org.lsmp.djep.vectorJep.values.MatrixValueI; import org.lsmp.djep.xjep.function.Sum; import org.nfunk.jep.JEP; import org.nfunk.jep.ParseException; /** * @author Rich Morris * Created on 24-Apr-2005 */ public class MSum extends Sum implements NaryOperatorI { /** * @param j */ public MSum(JEP j) { super(j); } public Dimensions calcDim(Dimensions[] dims) throws ParseException { return dims[0]; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI[] inputs) throws ParseException { throw new ParseException("calcValue method for MSum called"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MArrayAccess.java0000644000000000000000000000122210615400352025220 0ustar rootroot/* Created 17-May-2006 - Richard Morris */ package org.lsmp.djep.matrixJep.function; import org.lsmp.djep.xjep.PrintVisitor; import org.lsmp.djep.vectorJep.function.ArrayAccess; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; public class MArrayAccess extends ArrayAccess implements PrintVisitor.PrintRulesI{ public void append(Node node, PrintVisitor pv) throws ParseException { // TODO Auto-generated method stub //pv.append("["); node.jjtGetChild(0).jjtAccept(pv, null); node.jjtGetChild(1).jjtAccept(pv, null); } public MArrayAccess() { super(); // TODO Auto-generated constructor stub } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MIf.java0000644000000000000000000000607110615400352023365 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.lsmp.djep.matrixJep.function; import org.nfunk.jep.function.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.function.NaryOperatorI; import org.lsmp.djep.vectorJep.values.*; import org.nfunk.jep.*; /** * The if(condExpr,posExpr,negExpr) function. * The value of trueExpr will be returned if condExpr is >0 (true) * and value of negExpr will be returned if condExpr is <= 0 (false). *

    * This function performs lazy evaluation so that * only posExpr or negExpr will be evaluated. * For Complex numbers only the real part is used. *

    * An alternate form if(condExpr,posExpr,negExpr,zeroExpr) * is also available. Note most computations * are carried out over floating point doubles so * testing for zero can be dangerous. *

    * This function implements the SpecialEvaluationI interface * so that it handles setting the value of a variable. * @author Rich Morris * Created on 18-Nov-2003 */ public class MIf extends PostfixMathCommand implements NaryOperatorI, MatrixSpecialEvaluationI { public MIf() { super(); numberOfParameters = -1; } /** Find the dimension of this node. */ public Dimensions calcDim(Dimensions dims[]) throws ParseException { int num =dims.length; if( num < 3 || num > 4) throw new ParseException("If operator must have 3 or 4 arguments."); Dimensions condDim = dims[0]; if(!condDim.equals(Dimensions.ONE)) throw new ParseException("First argument of if opperator must be 0 dimensional"); Dimensions posDim = dims[1]; for(int i=2;i 4) throw new ParseException("If operator must have 3 or 4 arguments."); // get value of argument Scaler cond = (Scaler) node.jjtGetChild(0).jjtAccept(visitor,null); // Object condVal = cond.getEle(0); // convert to double double val = cond.doubleValue(); MatrixValueI res; if(val>0.0) { res = (MatrixValueI) node.jjtGetChild(1).jjtAccept(visitor,null); } else if(num ==3 || val <0.0) { res = (MatrixValueI) node.jjtGetChild(2).jjtAccept(visitor,null); } else { res = (MatrixValueI) node.jjtGetChild(3).jjtAccept(visitor,null); } MatrixValueI mvalue = node.getMValue(); mvalue.setEles(res); return mvalue; } public boolean checkNumberOfParameters(int n) { return (n == 3 || n == 4); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/function/MList.java0000644000000000000000000000706310615400352023744 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.lsmp.djep.matrixJep.function; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.vectorJep.function.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.xjep.*; //import org.lsmp.djep.matrixJep.nodeTypes.*; /** * A enhanced version of list, allows matrices and tensors. * * @author Rich Morris * Created on 27-Nov-2003 */ public class MList extends VList implements PrintVisitor.PrintRulesI,NaryOperatorI,SpecialPreProcessorI { public MList() { numberOfParameters = -1; } public MatrixValueI calcValue(MatrixValueI res, MatrixValueI inputs[]) throws ParseException { int eleSize = inputs[0].getNumEles(); for(int i=0;i= node.getDim().rank()) { // bottom of tree for(int i=0;i Advanced vector and matrix handeling. For a simplier and smaller vector and matrix handeling see {@link org.lsmp.djep.vectorJep vectorJep}. This package adds:

    • ability to differentiate equations with vectors and matricies
    • overloaded ^ operator which can be either cross product or power
    • slightly faster evaluation
    Sub-packages
    org.lsmp.djep.matrixJep.function Some functions for use with MatrixJep
    org.lsmp.djep.matrixJep.nodeTypes The types of Node's used by MatrixJep.
    @see MatrixJep documentation jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/MatrixSpecialEvaluationI.java0000644000000000000000000000232710615400352025773 0ustar rootroot/* @author rich * Created on 26-Nov-2003 */ package org.lsmp.djep.matrixJep; import org.nfunk.jep.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.values.*; /** * If a function requires a special form of evaluation it should * implement this interface. * * @author Rich Morris * Created on 26-Nov-2003 */ public interface MatrixSpecialEvaluationI { /** * Returns the result of evaluating this node and the tree below. * This method has the responsibility for evaluating the children of the node * and it should generally call *
    	 * MatrixValueI val = (MatrixValueI) node.jjtGetChild(i).jjtAccept(visitor,null);	
    	 * 
    * for each child. * *

    * The final results should be copied into the mvalue field of the node using *

    	 * MatrixValueI mvalue = node.getMValue();
    	 * mvalue.setEles(res);
    	 * return mvalue;
    	 * 
    * * @param node The top node. * @param visitor The parser visitor * @param jep The current MatrixJep instance. * @return Value after evaluation. * @throws ParseException */ public MatrixValueI evaluate(MatrixNodeI node,MatrixEvaluator visitor,MatrixJep jep) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/MatrixPartialDerivative.java0000644000000000000000000000340310615400352025665 0ustar rootroot/* @author rich * Created on 29-Oct-2003 */ package org.lsmp.djep.matrixJep; import org.nfunk.jep.*; import org.lsmp.djep.djep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; /** * Contains information about a PartialDerivative of a variable. * * @author Rich Morris * Created on 29-Oct-2003 * TODO Should setValue be overwritten? */ public class MatrixPartialDerivative extends PartialDerivative implements MatrixVariableI { private MatrixValueI mvalue = null; /** * Protected constructor, should only be constructed * through the findDerivative method in {@link MatrixVariable}. **/ protected MatrixPartialDerivative(MatrixVariable var, String derivnames[],Node deriv) { super(var,derivnames); /*TODO could be a little cleverer just have a * partial derivative which is a constant dy/dx = 1 * don't use an equation, instead use a value. * if(deriv instanceof ASTMConstant) { MatrixValueI val = ((ASTMConstant) deriv).getMValue(); System.out.println("Warning constant derivative "+getName()+"="+val); mvalue = (Scaler) Scaler.getInstance(val); } else { */ setEquation(deriv); setValidValue(false); mvalue=Tensor.getInstance(var.getDimensions()); } public Dimensions getDimensions() { MatrixVariableI root = (MatrixVariableI) getRoot(); return root.getDimensions(); } public void setDimensions(Dimensions dims) {} public MatrixValueI getMValue() { return mvalue; } public void setMValue(MatrixValueI val) { if(this.isConstant()) return; mvalue.setEles(val); setValidValue(true); setChanged(); notifyObservers(); } // public void setMValue(VectorMatrixTensorI value) // { this.mvalue = value; setValidValue(true); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/0000755000000000000000000000000010615400352022170 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/package.html0000644000000000000000000000011710615400352024450 0ustar rootroot Subclasses the AST nodes to work with vectors and matricies. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/ASTMConstant.java0000644000000000000000000000140510615400352025311 0ustar rootroot/* @author rich * Created on 01-Feb-2004 */ package org.lsmp.djep.matrixJep.nodeTypes; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; /** * Holds a single constant number. * @author Rich Morris * Created on 01-Feb-2004 */ public class ASTMConstant extends ASTConstant implements MatrixNodeI { private Scaler scalerval; public ASTMConstant(int i) { super(i); scalerval = (Scaler) Scaler.getInstance(new Double(0.0)); } public Dimensions getDim() { return Dimensions.ONE; } public MatrixValueI getMValue() { return scalerval; } public Object getValue() { return scalerval.getEle(0); } public void setValue(Object val) { scalerval.setEle(0,val); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/ASTMVarNode.java0000644000000000000000000000123210615400352025054 0ustar rootroot/* @author rich * Created on 01-Feb-2004 */ package org.lsmp.djep.matrixJep.nodeTypes; import org.nfunk.jep.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; /** * @author Rich Morris * Created on 01-Feb-2004 */ public class ASTMVarNode extends ASTVarNode implements MatrixNodeI { private MatrixVariableI mvar=null; public ASTMVarNode(int i) {super(i);} public Dimensions getDim() {return mvar.getDimensions();} public void setVar(Variable var) { mvar = (MatrixVariableI) var; super.setVar(var); } public MatrixValueI getMValue() {return mvar.getMValue();} } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/ASTMFunNode.java0000644000000000000000000000113010615400352025051 0ustar rootroot/* @author rich * Created on 01-Feb-2004 */ package org.lsmp.djep.matrixJep.nodeTypes; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; /** * @author Rich Morris * Created on 01-Feb-2004 */ public class ASTMFunNode extends ASTFunNode implements MatrixNodeI { private MatrixValueI mvar=null; public ASTMFunNode(int i) { super(i);} public Dimensions getDim() {return mvar.getDim(); } public void setDim(Dimensions dim) { mvar = Tensor.getInstance(dim); } public MatrixValueI getMValue() {return mvar;} } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/nodeTypes/MatrixNodeI.java0000644000000000000000000000071610615400352025222 0ustar rootroot/* @author rich * Created on 01-Feb-2004 */ package org.lsmp.djep.matrixJep.nodeTypes; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; /** * @author Rich Morris * Created on 01-Feb-2004 */ public interface MatrixNodeI extends Node { public Dimensions getDim(); // public void setDim(Dimensions dim); public MatrixValueI getMValue(); //public void setMValue(VectorMatrixTensorI val); } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/MatrixNodeFactory.java0000644000000000000000000001410710615400352024466 0ustar rootroot/* @author rich * Created on 16-Nov-2003 */ package org.lsmp.djep.matrixJep; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.function.*; import org.lsmp.djep.xjep.*; /** * This class is used to create nodes of specified types. * It can be sub-classed to change the nature of how nodes * are constructed. Generally there are two methods for creating * nodes, methods which take an existing node and methods which * take the components. * * @author Rich Morris * Created on 16-Nov-2003 */ public class MatrixNodeFactory extends NodeFactory { public MatrixNodeFactory(XJep xj) { super(xj); } /** Creates an ASTConstant node with specified value. **/ public ASTConstant buildConstantNode(Object value) throws ParseException { ASTMConstant node = new ASTMConstant(ParserTreeConstants.JJTCONSTANT); node.setValue(value); return node; } /** Creates a ASTVariable node with specified value. **/ public ASTVarNode buildVariableNode(Variable var) throws ParseException { ASTMVarNode node = new ASTMVarNode(ParserTreeConstants.JJTVARNODE); node.setVar(var); return node; } /** * Builds a function with n arguments * @param name of function. * @param pfmc PostfixMathCommand for function. * @param arguments the arguments to the function. * @return top Node of expression */ public ASTFunNode buildFunctionNode(String name,PostfixMathCommandI pfmc,Node[] arguments) throws ParseException { ASTMFunNode res = new ASTMFunNode(ParserTreeConstants.JJTFUNNODE); res.setFunction(name,pfmc); copyChildren(res,arguments); res.setDim(calcDim(name,pfmc,arguments)); return res; } /** Calculates the dimension of node using the dimensions * of the children. Does not recurse down the tree. */ public Dimensions calcDim(String name,PostfixMathCommandI pfmc,Node arguments[]) throws ParseException { MatrixNodeI children[] = new MatrixNodeI[arguments.length]; for(int i=0;i *
  • Sets the dimension of each node. *
  • For assignment equations it adds an entry in the VariableTable *
  • For diff opperator it calculates the derivative. *
  • For the List opperator it finds the dimensions and * returns a ASTTensor. *
  • For the Hat opperator it finds the dimension and returns * a Power or Wedge opperator. * * The visitor will return a new Tree. * * @author Rich Morris * Created on 30-Oct-2003 */ public class MatrixPreprocessor implements ParserVisitor { private MatrixJep mjep; private MatrixNodeFactory nf; private DSymbolTable vt; public MatrixPreprocessor() {} /** * Main entry point: pre-process a node. * @param node Top node of tree. * @param mdjep Reference to MatrixJep instance * @return A new tree with all preprocessing carried out. * @throws ParseException */ public MatrixNodeI preprocess(Node node,MatrixJep mdjep) throws ParseException { this.mjep=mdjep; this.nf=(MatrixNodeFactory) mdjep.getNodeFactory(); this.vt=(DSymbolTable) mdjep.getSymbolTable(); return (MatrixNodeI) node.jjtAccept(this,null); } /** * Returns an array of matrix nodes which are the results of visiting each child. */ public MatrixNodeI[] visitChildrenAsArray(Node node,Object data) throws ParseException { int nchild = node.jjtGetNumChildren(); MatrixNodeI children[] = new MatrixNodeI[nchild]; for(int i=0;i *
  • Converts each node into one of the subtypes of MatrixNodeI
  • *
  • Calculate the dimensions for the results
  • *
  • Performs any special symbolic operations such as differentation
  • * * In general the first step in preprocessing is to run the preprocessor on the children of the node. * This can be done using *
    	 * MatrixNodeI children[] = visitor.visitChildrenAsArray(node,null);
    	 * 
    * The final step is to construct a node of the correct type. The MatrixNodeFactory * argument has a number of methods to do this. For example *
    	 * return (ASTMFunNode) nf.buildOperatorNode(node.getOperator(),children,rhsDim);
    	 * 
    * Note how the dimension is specified. * * @param node the top node of the tree representing the function and its arguments. * @param visitor A reference to the preprocessing visitor. * @param jep A reference of the MatrixJep instance. * @param nf A reference to the node factory object. * @return A new MatrixNodeI representing the converted function. * @throws ParseException if some error occurs. */ public MatrixNodeI preprocess( ASTFunNode node, MatrixPreprocessor visitor, MatrixJep jep, MatrixNodeFactory nf) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/matrixJep/MatrixVariable.java0000644000000000000000000000745610615400352024007 0ustar rootroot/* @author rich * Created on 26-Oct-2003 */ package org.lsmp.djep.matrixJep; import org.nfunk.jep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.xjep.*; import org.lsmp.djep.djep.*; /** * Holds all info about a variable. * Has a name, an equation, a dimension (or sent of dimensions if matrix or tensor) * and also a set of {@link MatrixPartialDerivative MatrixPartialDerivative}. * The derivatives are stored in a hashtable index by * the sorted names of derivatives. * i.e. d^2f/dxdy, and d^2f/dydx will both be indexed by {"x","y"}. * df/dx is indexed by {"x"}, d^2f/dx^2 is index by {"x","x"}. * Partial derivatives are calculated as required by the * findDerivative method. * @author Rich Morris * Created on 26-Oct-2003 * @since 2.3.2 Added a setValue method overriding */ public class MatrixVariable extends DVariable implements MatrixVariableI { private Dimensions dims; private MatrixValueI mvalue = null; protected PartialDerivative createDerivative(String derivnames[],Node eqn) { return new MatrixPartialDerivative(this,derivnames,eqn); } /** * The constructor is package private. Variables should be created * using the VariableTable.find(Sting name) method. */ MatrixVariable(String name) { super(name); this.dims = Dimensions.ONE; this.mvalue = Scaler.getInstance(new Double(0.0)); setValidValue(false); } MatrixVariable(String name,Object value) { super(name); if(value == null) this.mvalue = Scaler.getInstance(new Double(0.0)); else if(value instanceof MatrixValueI) this.mvalue = (MatrixValueI) value; else this.mvalue = Scaler.getInstance(value); this.dims = mvalue.getDim(); setValidValue(true); } public Dimensions getDimensions() { return dims; } public void setDimensions(Dimensions dims) { this.dims = dims; this.mvalue=Tensor.getInstance(dims); this.invalidateAll(); } /** returns the value, uses the Scaler type. */ public MatrixValueI getMValue() { return mvalue; } /** returns the value, unpacks Scalers so they just return its elements. */ public Object getValue() { if(mvalue instanceof Scaler) return mvalue.getEle(0); return mvalue; } /** * Sets the value of this variable. * Needed when using macro functions in matrix calculations. * TODO might be better to change macro function behaviour. */ protected boolean setValueRaw(Object val) { if(val instanceof MatrixValueI) { mvalue = (MatrixValueI) val; this.dims = mvalue.getDim(); } else mvalue.setEle(0,val); this.setValidValue(true); return true; } public void setMValue(MatrixValueI val) { if(this.isConstant()) return; mvalue.setEles(val); setValidValue(true); setChanged(); notifyObservers(val); } // public void setMValue(VectorMatrixTensorI value) // { this.mvalue = value; this.invalidateAll(); } public void print(PrintVisitor bpv) { StringBuffer sb = new StringBuffer(name); sb.append(": "); if(dims!=null) sb.append("dim "+dims.toString()); if(hasValidValue() && mvalue != null) sb.append(" val "+getMValue() ); else sb.append(" null value"); sb.append(" "); if(this.getEquation()!=null) sb.append("eqn "+bpv.toString(this.getEquation())); else sb.append("no equation"); sb.append("\n"); for(java.util.Enumeration e = this.derivatives.elements(); e.hasMoreElements(); ) { MatrixPartialDerivative var = (MatrixPartialDerivative) e.nextElement(); sb.append("\t"+var.toString()+": "); if(var.hasValidValue()) sb.append(" val "+var.getMValue() ); else sb.append(" null value"); sb.append(" "); sb.append(bpv.toString(var.getEquation())); sb.append("\n"); } System.out.print(sb.toString()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/mrpe/0000755000000000000000000000000010615400352017216 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/mrpe/package.html0000644000000000000000000000031610615400352021477 0ustar rootroot Experimental fast evaluation routines for vectors and matrices. Can give a ten fold speed improvement for matrix operations. Optimised for 2, 3 and 4 dimensions. @see org.lsmp.djep.rpe jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/mrpe/MRpEval.java0000644000000000000000000041634710615400352021406 0ustar rootroot/* @author rich * Created on 14-Apr-2004 */ package org.lsmp.djep.mrpe; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import org.lsmp.djep.matrixJep.nodeTypes.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.vectorJep.*; import org.lsmp.djep.vectorJep.values.*; import org.lsmp.djep.xjep.*; import java.util.*; /** * A fast evaluation algorithm for equations using Vectors and Matrix over the Doubles. * This is based around reverse polish notation (hence the name M Rp Eval) * and is optimised for speed at every opportunity. *

    * To use do *

     * MatrixJep j = ...;
     * Node node = ...; 
     * MRpEval rpe = new MRpEval(j);
     * MRpCommandList list = rpe.compile(node);
     * MRpRes rpRes = rpe.evaluate(list);
     * System.out.println(rpRes.toString());
     * MatrixValueI mat = rpRes.toVecMat();
     * rpe.cleanUp();
     * 
    * *

    * The real use of this class is when an equation (or set of equations) * need to be repeatedly evaluated with different values for the variables. * MRpEval use an internal store for variable values different from those * used in the main Jep classes. Changes in the Jep variable values, * say by calling {@link org.nfunk.jep.JEP#setVarValue JEP.setVarValue}, * are reflected * in changes in MRpEval variables, (the converse does not hold). * A more efficient way is to use int ref=getVarRef(var) * to return an index number of the variable and then calling * setVarVal(ref,value) to set its value. * For example *

     * MRpCommandList list = rpe.compile(node);
     * int ref = rpe.getVarRef(j.getVar("x"));
     * for(double x=-1.;x<1.001;x+=0.1) {
     *      rpe.setVarVal(ref,x);
     *      rpe.evaluate(list);
     * }
     * 
    * *

    * Combining mrpe with differentation requires special techniques * to cope with that fact that internal equations are used *

    * The compile methods converts the expression represented by node * into a string of commands. For example the expression "1+2*3" will * be converted into the sequence of commands *

     * Constant no 1 (pushes constant onto stack)
     * Constant no 2
     * Constant no 3
     * Multiply scalers (multiplies last two entries on stack)
     * Add scalers (adds last two entries on stack)
     * 
    * The evaluate method executes these methods sequentially * using a stack (actually a set of stacks) * and returns the last object on the stack. *

    * A few cautionary notes: the values returned by evaluate * are references to internal variables, their values will change * at the next call to compile or evaluate. * Its very unlikely to be thread safe. It only works over doubles; * expressions with complex numbers or strings will cause problems. * It is tuned to work best for expressions involving scalers and 2, 3 and 4 dimensional vectors and matricies, * larger vectors and matrices will be noticeably slower. * The cleanUp function should be used when you no longer need * the evaluator, this stops the evaluator listening to Variable * through the java.util.Observer interface. *

    * Implementation notes * A lot of things have been done to make it as fast as possible: *

      *
    • Everything is final which maximises the possibility for in-lining.
    • *
    • All object creation happens during compile.
    • *
    • All calculations done using double values.
    • *
    • Vectors and Matrices are instances of VecObj and MatObj optimised for speed. * For instance a 2 by 2 matrix is an instance of Mat22Obj whose elements * are represented by the fields a,b,c,d. This eliminates bound checking on arrays. *
    • *
    • Each possible vector and matrix operation has been hand coded, and there are * a lot of methods (27 just for matrix multiplication!).
    • *
    • The values of variables are kept on local arrays for fast access. * These values are kept in sync with the main Jep Variables by using * the java.util.Observer interface.
    • *
    * *

    * For each type of vector or matrix (i.e. 2D vecs, 3D vecs, 4D vecs, 2 by 2 matrices ... 4 by 4 matrices. * there is a corresponding class V2Obj, M22Obj etc. * which stores the values and another class V2Store, M22Store etc. * Each Store class contains a stack, a heap and a array of variable values. * During evaluation objects are pushed and popped from the stack * when a new object is needed it is taken from the heap. * The operation is illustrated by the add method for 2 by 2 matrices. *

     * private final class M22Store
     * {
     *  ....
     *  final void add(){
     *   M22Obj r = stack[--sp]; // pop from stack
     *   M22Obj l = stack[--sp]; // pop from stack
     *	 M22Obj res = heap[hp++]; // result is next entry in heap
     *	 res.a = l.a+r.a;	// add each componant
     *	 res.b = l.b+r.b;
     *	 res.c = l.c+r.c;
     *	 res.d = l.d+r.d;
     *	 stack[sp++]=res;	// push result onto stack
     *  }
     * }
     * 
    * * @author Rich Morris * Created on 14-Apr-2004 */ public final class MRpEval implements ParserVisitor { private MatrixOperatorSet opSet; public MRpEval(MatrixJep mjep) { this.opSet = (MatrixOperatorSet) mjep.getOperatorSet(); } private MRpEval() {} /** compile an expression of the type var = node. */ public final MRpCommandList compile(MatrixVariableI var,Node node) throws ParseException { MRpCommandList list = compile(node); ObjStore store = getStoreByDim(var.getDimensions()); short vRef = (short) store.addVar(var); store.decStack(); list.addCommand(ASSIGN,getDimType(var.getDimensions()),vRef); return list; } /** * Compile the expressions to produce a set of commands in reverse Polish notation. */ public final MRpCommandList compile(Node node) throws ParseException { curCommandList = new MRpCommandList(); node.jjtAccept(this,null); scalerStore.alloc(); v2Store.alloc(); v3Store.alloc(); v4Store.alloc(); vnStore.alloc(); m22Store.alloc(); m23Store.alloc(); m24Store.alloc(); m32Store.alloc(); m33Store.alloc(); m34Store.alloc(); m42Store.alloc(); m43Store.alloc(); m44Store.alloc(); mnnStore.alloc(); Dimensions dims = ((MatrixNodeI) node).getDim(); curCommandList.setFinalType(getDimType(dims)); // returnObj = Tensor.getInstance(dims); // if(dims.is2D()) // returnMat = (Matrix) returnObj; return curCommandList; } /** Index for each command */ static final short CONST = 0; static final short VAR = 1; static final short ADD = 2; static final short SUB = 3; static final short MUL = 4; static final short DIV = 5; static final short MOD = 6; static final short POW = 7; static final short AND = 8; static final short OR = 9; static final short NOT = 10; static final short LT = 11; static final short LE = 12; static final short GT = 13; static final short GE = 14; static final short NE = 15; static final short EQ = 16; static final short LIST = 17; static final short DOT = 18; static final short CROSS = 19; static final short ASSIGN = 20; static final short VLIST = 21; static final short MLIST = 22; static final short FUN = 23; static final short UMINUS = 24; /** Constant type scalers - used in the aux field of RpCommand */ private static final short SCALER = 0; // Scalers private static final short V2 = 2; // 2D vect private static final short V3 = 3; private static final short V4 = 4; private static final short Vn = 5; // n D vec private static final short M22 = 6; // 2 by 2 mat private static final short M23 = 7; // 2 by 3 mat private static final short M24 = 8; private static final short M32 = 9; private static final short M33 = 10; private static final short M34 = 11; private static final short M42 = 12; private static final short M43 = 13; private static final short M44 = 14; private static final short Mnn = 15; // other mats private static final short Dtens = 16; // tensors /** Standard functions **/ private static final short SIN = 1; private static final short COS = 2; private static final short TAN = 3; private static final short ASIN = 4; private static final short ACOS = 5; private static final short ATAN = 6; private static final short SINH = 7; private static final short COSH = 8; private static final short TANH = 9; private static final short ASINH = 10; private static final short ACOSH = 11; private static final short ATANH = 12; private static final short ABS = 13; private static final short EXP = 14; private static final short LOG = 15; private static final short LN = 16; private static final short SQRT = 17; private static final short SEC = 18; private static final short COSEC = 19; private static final short COT = 20; // 2 argument functions // private static final short ANGLE = 21; // private static final short MODULUS = 22; /** Hashtable for function name lookup **/ private static final Hashtable functionHash = new Hashtable(); { functionHash.put("sin",new Short(SIN)); functionHash.put("cos",new Short(COS)); functionHash.put("tan",new Short(TAN)); functionHash.put("asin",new Short(ASIN)); functionHash.put("acos",new Short(ACOS)); functionHash.put("atan",new Short(ATAN)); functionHash.put("sinh",new Short(SINH)); functionHash.put("cosh",new Short(COSH)); functionHash.put("tanh",new Short(TANH)); functionHash.put("asinh",new Short(ASINH)); functionHash.put("acosh",new Short(ACOSH)); functionHash.put("atanh",new Short(ATANH)); functionHash.put("abs",new Short(ABS)); functionHash.put("exp",new Short(EXP)); functionHash.put("log",new Short(LOG)); functionHash.put("ln",new Short(LN)); functionHash.put("sqrt",new Short(SQRT)); functionHash.put("sec",new Short(SEC)); functionHash.put("cosec",new Short(COSEC)); functionHash.put("cot",new Short(COT)); } /** Contains the constant values **/ private double constVals[] = new double[0]; /** * Finds the reference number used for this variable. * @param var * @return an index used to refer to the variable * @throws ParseException */ public int getVarRef(Variable var) throws ParseException { Dimensions dims = ((MatrixVariableI)var).getDimensions(); ObjStore store = getStoreByDim(dims); int ref = store.addVar((MatrixVariableI) var); return ref; } /** * Finds the reference number used for this variable. * @param var * @return an index used to refer to the variable * @throws ParseException */ public int getVarRef(MatrixVariableI var) throws ParseException { Dimensions dims = var.getDimensions(); ObjStore store = getStoreByDim(dims); int ref = store.addVar(var); return ref; } /** * Sets value of rpe variable. * * @param ref the reference number for the variable * (found using {@link #getVarRef(org.lsmp.djep.matrixJep.MatrixVariableI)}) * @param val * @throws ParseException */ public final void setVarValue(int ref,MatrixValueI val) throws ParseException { ObjStore store = getStoreByDim(val.getDim()); store.setVarValue(ref,val); } /** * Sets value of rpe variable. * Only applies to scaler (double variables). * * @param ref the reference number for the variable * (found using {@link #getVarRef(org.lsmp.djep.matrixJep.MatrixVariableI)}) * @param val the value */ public final void setVarValue(int ref,double val) { scalerStore.setVarValue(ref,val); } private final static class ScalerObj extends MRpRes { double a; private ScalerObj(double val) {a =val; } public final Dimensions getDims() { return Dimensions.ONE; } public final void copyToVecMat(MatrixValueI res) throws ParseException { if(! res.getDim().is0D()) throw new ParseException("CopyToVecMat: dimension of argument "+res.getDim()+" is not equal to dimension of object "+getDims()); res.setEle(0,new Double(a)); } public final String toString() { return String.valueOf(a); } public Object toArray() { return new double[]{a}; } } private ScalerObj scalerRes = new ScalerObj(0.0); private abstract static class VecObj extends MRpRes { public final void copyToVecMat(MatrixValueI res) throws ParseException { if(! getDims().equals(res.getDim())) throw new ParseException("CopyToVecMat: dimension of argument "+res.getDim()+" is not equal to dimension of object "+getDims()); copyToVec((MVector) res); } public abstract void copyToVec(MVector res); abstract double[] toArrayVec(); public Object toArray() { return toArrayVec(); } /** * Sets the value of th vector frm an array. */ // public abstract void fromArray(double array[]); } private abstract static class MatObj extends MRpRes { public final void copyToVecMat(MatrixValueI res) throws ParseException { if(! getDims().equals(res.getDim())) throw new ParseException("CopyToVecMat: dimension of argument "+res.getDim()+" is not equal to dimension of object "+getDims()); copyToMat((Matrix) res); } public abstract void copyToMat(Matrix res); abstract double[][] toArrayMat(); public Object toArray() { return toArrayMat(); } } /** * Base class for storage for each type of data. * Each subclass should define *
    	 * private Obj stack[];
    	 * private Obj heap[];
    	 * private Obj vars[]= new Obj[0];
    	 * 
    * where Obj is an Object of the specific type, eg V2Obj. * Memory for the data is allocated from the heap * and the stack is the current data used for calculations. * Data for Variables is stored in vars and references to the Variables * in varRefs. */ private abstract static class ObjStore implements Observer { /** Contains references to Variables of this type */ Hashtable varRefs = new Hashtable(); /** The stack pointer */ int sp=0; /** Maximum size of stack */ int stackMax=0; /** The heap pointer */ int hp=0; final void incStack() {sp++; if(sp > stackMax) stackMax = sp; } final void incHeap() {hp++;} final void decStack() throws ParseException {--sp; if(sp <0 ) throw new ParseException("RPEval: stack error");} /** call this to reset pointers as first step in evaluation */ final void reset() { sp = 0; hp = 0; } /** Add a reference to this variable. * @return the index of variable in table */ final int addVar(MatrixVariableI var){ Object index = varRefs.get(var); if(index==null) { int size = varRefs.size(); expandVarArray(var); varRefs.put(var,new Integer(size)); copyFromVar(var,size); ((Variable) var).addObserver(this); return size; } return ((Integer) index).intValue(); } /** Callback function for Observable Variables. * Called whenever the value of a variable is changed * so the private list of variables is kept in sync. */ final public void update(Observable obs, Object arg1) { MatrixVariableI var = (MatrixVariableI) obs; Object index = varRefs.get(var); copyFromVar(var,((Integer) index).intValue()); } abstract public void setVarValue(int ref,MatrixValueI val); /** allocates space needed */ abstract void alloc(); /** removed store from list of listeners. */ final void cleanUp() { for(Enumeration e=varRefs.keys();e.hasMoreElements();) { Variable var = (Variable) e.nextElement(); var.deleteObserver(this); } varRefs.clear(); } /** Copy variable values into into private storage */ abstract void copyFromVar(MatrixVariableI var,int i); /** Copy values from private storage into JEP variables */ // abstract void copyToVar(MatrixVariableI var,int i); /** expand size of array used to hold variable values. */ abstract void expandVarArray(MatrixVariableI var); /** add two objects of same type */ abstract void add(); /** subtract two objects of same type */ abstract void sub(); /** subtract two objects of same type */ abstract void uminus(); /** multiply by a scaler either of left or right */ abstract void mulS(); /** convert a set of scaler values into object of this type */ abstract void makeList(); /** assign a variable to stack value * @param i index of variable */ abstract void assign(int i); } private final class ScalerStore extends ObjStore { double stack[]=new double[0]; double vars[]= new double[0]; final void alloc() { stack = new double[stackMax]; } final void expandVarArray(MatrixVariableI var) { double newvars[] = new double[vars.length+1]; System.arraycopy(vars,0,newvars,0,vars.length); vars = newvars; } final void copyFromVar(MatrixVariableI var,int i) { if(var.hasValidValue()) { Scaler val = (Scaler) var.getMValue(); vars[i]=val.doubleValue(); } } public void setVarValue(int ref, double val) { vars[ref] = val; } public final void setVarValue(int ref,MatrixValueI val) { vars[ref]=((Scaler) val).doubleValue(); } final void add(){ double r = stack[--sp]; stack[sp-1] += r; } final void sub(){ double r = stack[--sp]; stack[sp-1] -= r; } final void uminus(){ double r = stack[--sp]; stack[sp++] = -r; } final void mulS(){ double r = stack[--sp]; stack[sp-1] *= r; } final void divS(){ double r = stack[--sp]; stack[sp-1] /= r; } final void mod(){ double r = stack[--sp]; stack[sp-1] %= r; } final void pow(){ double r = stack[--sp]; double l = stack[--sp]; stack[sp++] = Math.pow(l,r); } final void powN(int n){ double r = stack[--sp]; switch(n){ case 0: r = 1.0; break; case 1: break; case 2: r *= r; break; case 3: r *= r*r; break; case 4: r *= r*r*r; break; case 5: r *= r*r*r*r; break; default: r = Math.pow(r,n); break; } stack[sp++] = r; } final void makeList() { } final void assign(int i) { vars[i] = stack[--sp]; ++sp; } final void and(){ double r = stack[--sp]; double l = stack[--sp]; if((l != 0.0) && (r != 0.0)) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void or(){ double r = stack[--sp]; double l = stack[--sp]; if((l != 0.0) || (r != 0.0)) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void not(){ double r = stack[--sp]; if(r == 0.0) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void lt(){ double r = stack[--sp]; double l = stack[--sp]; if(l < r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void gt(){ double r = stack[--sp]; double l = stack[--sp]; if(l > r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void le(){ double r = stack[--sp]; double l = stack[--sp]; if(l <= r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void ge(){ double r = stack[--sp]; double l = stack[--sp]; if(l >= r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void eq(){ double r = stack[--sp]; double l = stack[--sp]; if(l == r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void neq(){ double r = stack[--sp]; double l = stack[--sp]; if(l != r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } } ScalerStore scalerStore = new ScalerStore(); /** Base class for vector type storage */ private abstract class VecStore extends ObjStore { abstract void copyVar(int i,MVector val); final void copyFromVar(MatrixVariableI var,int i) { if(var.hasValidValue()) { MVector val = (MVector) ((MatrixVariable) var).getMValue(); copyVar(i,val); } } public final void setVarValue(int ref, MatrixValueI val) { copyVar(ref,(MVector) val); } } private static final class V2Obj extends VecObj { double a,b; private static Dimensions dims = Dimensions.TWO; public Dimensions getDims() { return dims; } public String toString() { return "["+a+","+b+"]"; } public void fromVec(MVector val){ a = ((Double) val.getEle(0)).doubleValue(); b = ((Double) val.getEle(1)).doubleValue(); } public void copyToVec(MVector val){ val.setEle(0,new Double(a)); val.setEle(1,new Double(b)); } public double[] toArrayVec() { return new double[]{a,b}; } } private final class V2Store extends VecStore { V2Obj stack[]; V2Obj heap[]; V2Obj vars[]= new V2Obj[0]; final void alloc() { heap = new V2Obj[hp]; for(int i=0;i0) sb.append(","); sb.append(data[i]); } sb.append("]"); return sb.toString(); } public void fromVec(MVector val){ for(int i=0;i=0;--i) res.data[i] = scalerStore.stack[--scalerStore.sp]; stack[sp++]=res; } final void makeList() { throw new UnsupportedOperationException("VnObj: makeList cannot be called with no arguments"); } final void assign(int j) { VnObj r = stack[sp-1]; VnObj res = vars[j]; for(int i=0;i0) sb.append(','); sb.append('['); for(int j=0;j0) sb.append(','); sb.append(data[i][j]); } sb.append(']'); } sb.append(']'); return sb.toString(); } public void fromMat(Matrix val){ for(int i=0;i=0;--i) for(int j=cols-1;j>=0;--j) res.data[i][j]= scalerStore.stack[--scalerStore.sp]; stack[sp++]=res; } final void makeList() { throw new UnsupportedOperationException("VnObj: makeList cannot be called with no arguments"); } final void assign(int k) { MnnObj r = stack[sp-1]; MnnObj res = vars[k]; for(int i=0;i=1) { leftnode = (MatrixNodeI) node.jjtGetChild(0); ldims = leftnode.getDim(); } if(nChild>=2) { rightnode = (MatrixNodeI) node.jjtGetChild(1); rdims = rightnode.getDim(); } if(mnode.isOperator()) { XOperator op = (XOperator) mnode.getOperator(); if(op.isBinary()) if(nChild!=2) throw new ParseException("RpeEval: binary operator must have two children, but it has "+nChild); if(op.isUnary()) if(nChild!=1) throw new ParseException("RpeEval: unary operator must have one child, but it has "+nChild); if(op == opSet.getAdd()) { if(!dims.equals(ldims) || !dims.equals(rdims)) throw new ParseException("RpeEval: dims for add must be equal"); curCommandList.addCommand(ADD,getDimType(dims)); decByDim(dims); incheapByDim(dims); return null; } else if(op == opSet.getSubtract()) { if(!dims.equals(ldims) || !dims.equals(rdims)) throw new ParseException("RpeEval: dims for add must be equal"); curCommandList.addCommand(SUB,getDimType(dims)); decByDim(dims); incheapByDim(dims); return null; } else if(op == opSet.getUMinus()) { curCommandList.addCommand(UMINUS,getDimType(dims)); incheapByDim(dims); return null; } else if(op == opSet.getMultiply()) { decByDim(rdims); decByDim(ldims); incByDim(dims); incheapByDim(dims); curCommandList.addCommand(MUL,getDimType(ldims),getDimType(rdims)); return null; } else if(op == opSet.getMList()) { incByDim(dims); incheapByDim(dims); for(int j=0;j operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(GT,SCALER); return null; } else if(op == opSet.getLE()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for <= operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(LE,SCALER); return null; } else if(op == opSet.getGE()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for >= operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(GE,SCALER); return null; } else if(op == opSet.getAnd()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for && operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(AND,SCALER); return null; } else if(op == opSet.getOr()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for || operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(OR,SCALER); return null; } else if(op == opSet.getNot()) { if(!ldims.is0D())throw new ParseException("Dimension of operand for not operator must be one"); scalerStore.incStack(); decByDim(rdims); curCommandList.addCommand(NOT,SCALER); return null; } else if(op == opSet.getDivide()) { if(!rdims.is0D())throw new ParseException("RHS operands of / operator must be a Scaler"); decByDim(rdims); decByDim(ldims); incByDim(dims); incheapByDim(dims); curCommandList.addCommand(DIV,getDimType(ldims),getDimType(rdims)); return null; } else if(op == opSet.getMod()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for || operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(MOD,SCALER); return null; } else if(op == opSet.getPower()) { if(!ldims.is0D() || !rdims.is0D())throw new ParseException("Dimensions of operands for || operator must both be one"); scalerStore.incStack(); decByDim(ldims); decByDim(rdims); curCommandList.addCommand(POW,SCALER); return null; } throw new ParseException("RpeEval: Sorry unsupported operator/function: "+ mnode.getName()); } // other functions Short val = (Short) functionHash.get(mnode.getName()); if(val == null) throw new ParseException("RpeEval: Sorry unsupported operator/function: "+ mnode.getName()); if(mnode.getPFMC().getNumberOfParameters() == 1 && nChild == 1) { scalerStore.incStack(); decByDim(ldims); curCommandList.addCommand(FUN,val.shortValue()); return null; } throw new ParseException("RpeEval: Sorry unsupported operator/function: "+ mnode.getName()); } /***************************** evaluation *****************************/ /** Evaluate the expression. * * @return the value after evaluation */ public final MRpRes evaluate(MRpCommandList comList) { scalerStore.reset(); v2Store.reset(); v3Store.reset(); v4Store.reset(); vnStore.reset(); m22Store.reset(); m23Store.reset(); m24Store.reset(); m32Store.reset(); m33Store.reset(); m34Store.reset(); m42Store.reset(); m43Store.reset(); m44Store.reset(); mnnStore.reset(); // Now actually process the commands int num = comList.getNumCommands(); for(short commandNum=0;commandNum

    Experimental functions for tree manipulation, package may be dropped.

    Why this needs improving. To ensure correctness the current algorithm will after rewriting a node, check all of its children again for jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rewrite/AbstractRewrite.java0000644000000000000000000000171610615400352023711 0ustar rootroot/* @author rich * Created on 01-Oct-2004 */ package org.lsmp.djep.rewrite; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; /** * Basic implementation for a RewriteRule. * Subclasses can have access to NodeFactory,OperatorSet,TreeUtilsand XJep objects. * @author Rich Morris * Created on 01-Oct-2004 */ public abstract class AbstractRewrite implements RewriteRuleI { /** A NodeFactory used for construction nodes. */ protected NodeFactory nf; /** An OperatorSet used for finding operators. */ protected OperatorSet opSet; /** TreeUtils for testing types of nodes. */ protected TreeUtils tu; /** A reference to main XJep opbject. */ protected XJep xj; /** * Constructor with reference to XJep object. */ public AbstractRewrite(XJep xj) { opSet = xj.getOperatorSet(); tu = xj.getTreeUtils(); nf = xj.getNodeFactory(); this.xj = xj; } /** Private default constructor. */ private AbstractRewrite() {} } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rewrite/ExpandBrackets.java0000644000000000000000000000426010615400352023477 0ustar rootroot/* @author rich * Created on 01-Oct-2004 */ package org.lsmp.djep.rewrite; //import org.lsmp.djep.xjep.RewriteRuleI; import org.nfunk.jep.*; import org.lsmp.djep.xjep.*; /** * @author Rich Morris * Created on 01-Oct-2004 */ public class ExpandBrackets extends AbstractRewrite { /** * TODO cope with a * uminus(x+x) */ public ExpandBrackets(XJep xj) { super(xj); } /* (non-Javadoc) * @see org.lsmp.djep.xjep.RewriteRuleI#test(org.nfunk.jep.Node, org.nfunk.jep.Node[]) */ public boolean test(ASTFunNode node, Node[] children) { if(!node.isOperator()) return false; XOperator op= (XOperator) node.getOperator(); if(opSet.getMultiply() == op) { if(tu.getOperator(children[0]) == opSet.getAdd()) return true; if(tu.getOperator(children[0]) == opSet.getSubtract()) return true; if(tu.getOperator(children[1]) == opSet.getAdd()) return true; if(tu.getOperator(children[1]) == opSet.getSubtract()) return true; } return false; } /* (non-Javadoc) * @see org.lsmp.djep.xjep.RewriteRuleI#apply(org.nfunk.jep.Node, org.nfunk.jep.Node[]) */ public Node apply(ASTFunNode node, Node[] children) throws ParseException { Operator lhsOp = tu.getOperator(children[0]); Operator rhsOp = tu.getOperator(children[1]); if(lhsOp == opSet.getAdd() || lhsOp == opSet.getSubtract()) { /* (a+b)*c --> (a*c)+(b*c) */ return nf.buildOperatorNode( lhsOp, nf.buildOperatorNode( opSet.getMultiply(), children[0].jjtGetChild(0), xj.deepCopy(children[1])), nf.buildOperatorNode( opSet.getMultiply(), children[0].jjtGetChild(1), xj.deepCopy(children[1])) ); } if(rhsOp == opSet.getAdd() || rhsOp == opSet.getSubtract()) { /* a*(b+c) -> (a*b)+(a*c) */ return nf.buildOperatorNode( rhsOp, nf.buildOperatorNode( opSet.getMultiply(), xj.deepCopy(children[0]), children[1].jjtGetChild(0)), nf.buildOperatorNode( opSet.getMultiply(), xj.deepCopy(children[0]), children[1].jjtGetChild(1)) ); } throw new ParseException("ExpandBrackets at least one child must be + or -"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rewrite/CollectPowers.java0000644000000000000000000000571110615400352023370 0ustar rootroot/* @author rich * Created on 06-Oct-2004 */ package org.lsmp.djep.rewrite; import org.lsmp.djep.xjep.*; import org.nfunk.jep.ASTFunNode; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /** * Collect powers together so that x*x -> x^2 and x^n*x -> x^(n+1). * @author Rich Morris * Created on 06-Oct-2004 */ public class CollectPowers extends AbstractRewrite { /** * */ public CollectPowers(XJep xj) { super(xj); } /* (non-Javadoc) * @see org.lsmp.djep.xjep.RewriteRuleI#test(org.nfunk.jep.ASTFunNode, org.nfunk.jep.Node[]) */ public boolean test(ASTFunNode node, Node[] children) { if(node.getOperator()==opSet.getMultiply()) { // x * x -> true if(tu.isVariable(children[0]) && tu.isVariable(children[1])) { if(tu.getName(children[0]).equals(tu.getName(children[1]))) return true; return false; } // x^n * x if(tu.getOperator(children[0]) == opSet.getPower() && tu.isVariable(children[0].jjtGetChild(0)) && tu.isVariable(children[1])) { if(tu.getName(children[0].jjtGetChild(0)).equals(tu.getName(children[1]))) return true; return false; } if(tu.isVariable(children[0]) && tu.getOperator(children[1]) == opSet.getPower() && tu.isVariable(children[1].jjtGetChild(0))) { if(tu.getName(children[0]).equals(tu.getName(children[1].jjtGetChild(0)))) return true; return false; } } return false; } /* (non-Javadoc) * @see org.lsmp.djep.xjep.RewriteRuleI#apply(org.nfunk.jep.ASTFunNode, org.nfunk.jep.Node[]) */ public Node apply(ASTFunNode node, Node[] children) throws ParseException { if(node.getOperator()==opSet.getMultiply()) { if(tu.isVariable(children[0]) && tu.isVariable(children[1])) { if(tu.getName(children[0]).equals(tu.getName(children[1]))) { return nf.buildOperatorNode( opSet.getPower(), children[0], nf.buildConstantNode(new Double(2.0)) ); } } if(tu.getOperator(children[0]) == opSet.getPower() && tu.isVariable(children[0].jjtGetChild(0)) && tu.isVariable(children[1])) { if(tu.getName(children[0].jjtGetChild(0)).equals(tu.getName(children[1]))) { return nf.buildOperatorNode( opSet.getPower(), children[1], nf.buildOperatorNode( opSet.getAdd(), children[0].jjtGetChild(1), nf.buildConstantNode(tu.getONE()) )); } } if(tu.isVariable(children[0]) && tu.getOperator(children[1]) == opSet.getPower() && tu.isVariable(children[1].jjtGetChild(0))) { if(tu.getName(children[0]).equals(tu.getName(children[1].jjtGetChild(0)))) { return nf.buildOperatorNode( opSet.getPower(), children[0], nf.buildOperatorNode( opSet.getAdd(), children[1].jjtGetChild(1), nf.buildConstantNode(tu.getONE()) )); } } } return null; } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rewrite/RewriteVisitor.java0000644000000000000000000000356510615400352023611 0ustar rootroot package org.lsmp.djep.rewrite; //import org.lsmp.djep.matrixParser.*; import org.lsmp.djep.xjep.DoNothingVisitor; import org.lsmp.djep.xjep.TreeUtils; import org.lsmp.djep.xjep.XJep; import org.nfunk.jep.*; /** * Simplifies an expression. * To use *

     * JEP j = ...; Node in = ...;
     * SimplificationVisitor sv = new SimplificationVisitor(tu);
     * Node out = sv.simplify(in);
     * 
    * *

    * Its intended to completely rewrite this class to that simplification * rules can be specified by strings in a way similar to DiffRulesI. * It also would be nice to change the rules depending on the type of * arguments, for example matrix multiplication is not commutative. * But some of the in built rules exploit commutativity. * * @author Rich Morris * Created on 20-Jun-2003 */ public class RewriteVisitor extends DoNothingVisitor { private XJep xj; private RewriteRuleI rules[]; private boolean simp=false; public RewriteVisitor() { } /** must be implemented for subclasses. **/ public Node rewrite(Node node,XJep xjep,RewriteRuleI inrules[],boolean simplify) throws ParseException,IllegalArgumentException { xj = xjep; this.rules = inrules; this.simp = simplify; if(this.rules.length==0) return node; if (node == null) throw new IllegalArgumentException( "topNode parameter is null"); Node res = (Node) node.jjtAccept(this,null); return res; } public Object visit(ASTFunNode node, Object data) throws ParseException { Node children[] = acceptChildrenAsArray(node,data); TreeUtils.copyChildrenIfNeeded(node,children); for(int i=0;i (a^n+nC1 a^(n-1) b + ....) */ if(n == 0) return nf.buildConstantNode(new Double(1)); if(n == 1) return children[0]; Node vals[] = new Node[n+1]; /* a^n */ vals[0] = nf.buildOperatorNode( opSet.getPower(), xj.deepCopy(sub1), nf.buildConstantNode(new Double(n)) ); if(n==2) { vals[1]=nf.buildOperatorNode( opSet.getMultiply(), nf.buildConstantNode(new Double(2)), nf.buildOperatorNode( opSet.getMultiply(), xj.deepCopy(sub1), xj.deepCopy(sub2))); } else { /* n * a^(n-1) * b */ vals[1]=nf.buildOperatorNode( opSet.getMultiply(), nf.buildConstantNode(new Double(n)), nf.buildOperatorNode( opSet.getMultiply(), nf.buildOperatorNode( opSet.getPower(), xj.deepCopy(sub1), nf.buildConstantNode(new Double(n-1))), xj.deepCopy(sub2))); } /* n * a * b^(n-1) */ if(n>=3) { vals[n-1] = nf.buildOperatorNode( opSet.getMultiply(), nf.buildConstantNode(new Double(n)), nf.buildOperatorNode( opSet.getMultiply(), xj.deepCopy(sub1), nf.buildOperatorNode( opSet.getPower(), xj.deepCopy(sub2), nf.buildConstantNode(new Double(n-1))))); } /* a^n */ vals[n] = nf.buildOperatorNode( opSet.getPower(), xj.deepCopy(sub2), nf.buildConstantNode(new Double(n)) ); for(int i=2;i=0;--i) { sums[i] = nf.buildOperatorNode( lhsOp, vals[i], sums[i+1]); } return sums[0]; } throw new ParseException("ExpandBrackets at least one child must be + or -"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rewrite/RewriteRuleI.java0000644000000000000000000000067210615400352023166 0ustar rootroot/* @author rich * Created on 01-Oct-2004 */ package org.lsmp.djep.rewrite; import org.nfunk.jep.*; /** * @author Rich Morris * Created on 01-Oct-2004 */ public interface RewriteRuleI { /** Returns true if node needs to be rewritten, according to this rule. */ public boolean test(ASTFunNode node,Node children[]); /** Rewrites the node */ public Node apply(ASTFunNode node,Node children[]) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rpe/0000755000000000000000000000000010615400352017041 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rpe/RpCommandList.java0000644000000000000000000000306010615400352022417 0ustar rootroot/* @author rich * Created on 04-May-2004 */ package org.lsmp.djep.rpe; /** A list of commands */ public final class RpCommandList { /** Incremental size for list of commands **/ private static final int STACK_INC=10; /** List of commands **/ RpCommand commands[] = new RpCommand[STACK_INC]; /** Current position in the command Stack. **/ private short commandPos; private RpEval rpe; /** Package private constructor */ private RpCommandList() {} RpCommandList(RpEval rpe) {this.rpe = rpe;} /** Adds a command to the list */ final void addCommand(short command,short aux) { if(commandPos == commands.length) { RpCommand newCommands[] = new RpCommand[commands.length+STACK_INC]; System.arraycopy(commands,0,newCommands,0,commands.length); commands = newCommands; } commands[commandPos]=new RpCommand(rpe,command,aux); ++commandPos; // ++maxCommands; } final void addCommand(short command) { if(commandPos == commands.length) { RpCommand newCommands[] = new RpCommand[commands.length+STACK_INC]; System.arraycopy(commands,0,newCommands,0,commands.length); commands = newCommands; } commands[commandPos]=new RpCommand(rpe,command); ++commandPos; // ++maxCommands; } public int getNumCommands() { return commandPos;} public RpCommand getCommand(int i) { return commands[i]; } public String toString() { StringBuffer sb = new StringBuffer(); for(int i=0;i Experimental fast evaluation routines. Can give a ten fold speed improvment for matrix operations. @see org.lsmp.djep.mrpe jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djep/rpe/RpEval.java0000644000000000000000000004544310615400352021107 0ustar rootroot/* @author rich * Created on 14-Apr-2004 */ package org.lsmp.djep.rpe; import org.nfunk.jep.*; import org.nfunk.jep.function.*; import java.util.*; /** * A fast evaluation algorithm for equations over Doubles, does not work with vectors or matricies. * This is based around reverse polish notation * and is optimised for speed at every opportunity. *

    * To use do *

     * JEP j = ...;
     * Node node = ...; 
     * RpEval rpe = new RpEval(j);
     * RpCommandList list = rpe.compile(node);
     * double val = rpe.evaluate(list);
     * System.out.println(val);
     * rpe.cleanUp();
     * 
    * The compile methods converts the expression represented by node * into a string of commands. For example the expression "1+2*3" will * be converted into the sequence of commands *
     * Constant no 1 (pushes constant onto stack)
     * Constant no 2
     * Constant no 3
     * Multiply scalers (multiplies last two entries on stack)
     * Add scalers (adds last two entries on stack)
     * 
    * The evaluate method executes these methods sequentially * using a stack * and returns the last object on the stack. *

    * A few cautionary notes: * Its very unlikely to be thread safe. It only works over doubles * expressions with complex numbers or strings will cause problems. * It only works for expressions involving scalers. *

    * Implementation notes * A lot of things have been done to make it as fast as possible: *

      *
    • Everything is final which maximises the possibility for in-lining.
    • *
    • All object creation happens during compile.
    • *
    • All calculations done using double values.
    • *
    • Each operator/function is hand coded. To extend functionality you will have to modify the source.
    • *
    * * @author Rich Morris * Created on 14-Apr-2004 */ public final class RpEval implements ParserVisitor { private OperatorSet opSet; private ScalerStore scalerStore = new ScalerStore(); /** Contains the constant values **/ double constVals[] = new double[0]; /** Temporary holder for command list used during compilation */ private RpCommandList curCommandList; public RpEval(JEP jep) { this.opSet = jep.getOperatorSet(); } private RpEval() {} /** Index for each command */ public static final short CONST = 0; public static final short VAR = 1; public static final short ADD = 2; public static final short SUB = 3; public static final short MUL = 4; public static final short DIV = 5; public static final short MOD = 6; public static final short POW = 7; public static final short AND = 8; public static final short OR = 9; public static final short NOT = 10; public static final short LT = 11; public static final short LE = 12; public static final short GT = 13; public static final short GE = 14; public static final short NE = 15; public static final short EQ = 16; public static final short LIST = 17; public static final short DOT = 18; public static final short CROSS = 19; public static final short ASSIGN = 20; public static final short VLIST = 21; public static final short MLIST = 22; public static final short FUN = 23; public static final short UMINUS = 24; /** Standard functions **/ private static final short SIN = 1; private static final short COS = 2; private static final short TAN = 3; private static final short ASIN = 4; private static final short ACOS = 5; private static final short ATAN = 6; private static final short SINH = 7; private static final short COSH = 8; private static final short TANH = 9; private static final short ASINH = 10; private static final short ACOSH = 11; private static final short ATANH = 12; private static final short ABS = 13; private static final short EXP = 14; private static final short LOG = 15; private static final short LN = 16; private static final short SQRT = 17; private static final short SEC = 18; private static final short COSEC = 19; private static final short COT = 20; // 2 argument functions // private static final short ANGLE = 21; // private static final short MODULUS = 22; /** Hashtable for function name lookup **/ private static final Hashtable functionHash = new Hashtable(); { functionHash.put("sin",new Short(SIN)); functionHash.put("cos",new Short(COS)); functionHash.put("tan",new Short(TAN)); functionHash.put("asin",new Short(ASIN)); functionHash.put("acos",new Short(ACOS)); functionHash.put("atan",new Short(ATAN)); functionHash.put("sinh",new Short(SINH)); functionHash.put("cosh",new Short(COSH)); functionHash.put("tanh",new Short(TANH)); functionHash.put("asinh",new Short(ASINH)); functionHash.put("acosh",new Short(ACOSH)); functionHash.put("atanh",new Short(ATANH)); functionHash.put("abs",new Short(ABS)); functionHash.put("exp",new Short(EXP)); functionHash.put("log",new Short(LOG)); functionHash.put("ln",new Short(LN)); functionHash.put("sqrt",new Short(SQRT)); functionHash.put("sec",new Short(SEC)); functionHash.put("cosec",new Short(COSEC)); functionHash.put("cot",new Short(COT)); } /** * Base class for storage for each type of data. * Each subclass should define *
    	 * private double stack[];
    	 * private double vars[]= new double[0];
    	 * 
    * and the stack is the current data used for calculations. * Data for Variables is stored in vars and references to the Variables * in varRefs. */ private abstract static class ObjStore implements Observer { /** Contains references to Variables of this type */ Hashtable varRefs = new Hashtable(); /** The stack pointer */ int sp=0; /** Maximum size of stack */ int stackMax=0; final void incStack() {sp++; if(sp > stackMax) stackMax = sp; } final void decStack() throws ParseException {--sp; if(sp <0 ) throw new ParseException("RPEval: stack error");} /** call this to reset pointers as first step in evaluation */ final void reset() { sp = 0; } /** Add a reference to this variable. * @return the index of variable in table */ final int addVar(Variable var){ Object index = varRefs.get(var); if(index==null) { int size = varRefs.size(); expandVarArray(size+1); varRefs.put(var,new Integer(size)); copyFromVar(var,size); var.addObserver(this); return size; } return ((Integer) index).intValue(); } final public void update(Observable obs, Object arg1) { Variable var = (Variable) obs; Object index = varRefs.get(var); copyFromVar(var,((Integer) index).intValue()); } /** allocates space needed */ abstract void alloc(); final void cleanUp() { for(Enumeration e=varRefs.keys();e.hasMoreElements();) { Variable var = (Variable) e.nextElement(); var.deleteObserver(this); } varRefs.clear(); } /** Copy variable values into into private storage. * * @param var The variable * @param i index of element in array */ abstract void copyFromVar(Variable var,int i); /** expand size of array used to hold variable values. */ abstract void expandVarArray(int i); /** add two objects of same type */ abstract void add(); /** subtract two objects of same type */ abstract void sub(); /** multiply by a scaler either of left or right */ abstract void mulS(); /** assign a variable to stack value * @param i index of variable */ abstract void assign(int i); Variable getVariable(int ref) { for(Enumeration en=varRefs.keys();en.hasMoreElements();) { Variable var = (Variable) en.nextElement(); Integer index = (Integer) varRefs.get(var); if(index.intValue()==ref) return var; } return null; } } private final class ScalerStore extends ObjStore { double stack[]=new double[0]; double vars[]= new double[0]; final void alloc() { stack = new double[stackMax]; } final void expandVarArray(int size) { double newvars[] = new double[size]; System.arraycopy(vars,0,newvars,0,vars.length); vars = newvars; } final void copyFromVar(Variable var,int i){ if(var.hasValidValue()) { Double val = (Double) var.getValue(); vars[i]=val.doubleValue(); } } final void add(){ double r = stack[--sp]; stack[sp-1] += r; } final void sub(){ double r = stack[--sp]; stack[sp-1] -= r; } final void uminus(){ double r = stack[--sp]; stack[sp++] = -r; } final void mulS(){ double r = stack[--sp]; stack[sp-1] *= r; } final void div(){ double r = stack[--sp]; stack[sp-1] /= r; } final void mod(){ double r = stack[--sp]; stack[sp-1] %= r; } final void pow(){ double r = stack[--sp]; double l = stack[--sp]; stack[sp++] = Math.pow(l,r); } final void powN(int n){ double r = stack[--sp]; switch(n){ case 0: r = 1.0; break; case 1: break; case 2: r *= r; break; case 3: r *= r*r; break; case 4: r *= r*r*r; break; case 5: r *= r*r*r*r; break; default: r = Math.pow(r,n); break; } stack[sp++] = r; } final void assign(int i) { vars[i] = stack[--sp]; ++sp; } final void and(){ double r = stack[--sp]; double l = stack[--sp]; if((l != 0.0) && (r != 0.0)) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void or(){ double r = stack[--sp]; double l = stack[--sp]; if((l != 0.0) || (r != 0.0)) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void not(){ double r = stack[--sp]; if(r == 0.0) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void lt(){ double r = stack[--sp]; double l = stack[--sp]; if(l < r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void gt(){ double r = stack[--sp]; double l = stack[--sp]; if(l > r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void le(){ double r = stack[--sp]; double l = stack[--sp]; if(l <= r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void ge(){ double r = stack[--sp]; double l = stack[--sp]; if(l >= r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void eq(){ double r = stack[--sp]; double l = stack[--sp]; if(l == r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } final void neq(){ double r = stack[--sp]; double l = stack[--sp]; if(l != r) stack[sp++] = 1.0; else stack[sp++] = 0.0; } } /** * Compile the expressions to produce a set of commands in reverse Polish notation. */ public final RpCommandList compile(Node node) throws ParseException { curCommandList = new RpCommandList(this); node.jjtAccept(this,null); scalerStore.alloc(); return curCommandList; } public final Object visit(ASTStart node, Object data) throws ParseException { throw new ParseException("RpeEval: Start node encountered"); } public final Object visit(SimpleNode node, Object data) throws ParseException { throw new ParseException("RpeEval: Simple node encountered"); } public final Object visit(ASTConstant node, Object data) throws ParseException { Object obj = node.getValue(); double val; if(obj instanceof Double) val = ((Double) node.getValue()).doubleValue(); else throw new ParseException("RpeEval: only constants of double type allowed"); scalerStore.incStack(); for(short i=0;i JUnit tests to check that everything works correctly. The JUnit package needs to be used with these test. jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/GroupJepTest.java0000644000000000000000000002276710615400352022501 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.lsmp.djep.groupJep.interfaces.*; import org.lsmp.djep.groupJep.values.*; import org.lsmp.djep.groupJep.*; import org.lsmp.djep.groupJep.groups.*; import java.math.*; /* @author rich * Created on 19-Nov-2003 */ /** * Tests some strange properties of special groups. * * @author Rich Morris * Created on 19-Nov-2003 */ public class GroupJepTest extends TestCase { GroupJep j; public static final boolean SHOW_BAD=false; public GroupJepTest(String name) { super(name); } public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(GroupJepTest.class); // DJepTest jt = new DJepTest("DJepTest"); // jt.setUp(); suite.run(new TestResult()); } protected void setUp() { } public static Test suite() { return new TestSuite(GroupJepTest.class); } public void myAssertEquals(String msg,String expected,String actual) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \""+actual+" should be "+expected+"\""); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is \""+actual+"\""); } public void myAssertEquals(String msg,String expected,String actual,String ending) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \""+actual+" should be "+expected+"\""); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is \""+actual+"\": "+ending); } /** just test JUnit working OK */ public void testGood() { assertEquals(1,1); } public void valueToStringTest(String expr,String expected) throws Exception { Node node = j.parse(expr); Object val = j.evaluate(node); String res = val.toString(); String ending=""; if(val instanceof HasComplexValueI) { Complex cval = ((HasComplexValueI) val).getComplexValue(); ending = cval.toString(); } myAssertEquals(expr,expected,res,ending); } /** Tests very large numbers, 20! */ public void testZ() throws Exception { j = new GroupJep(new Integers()); valueToStringTest("1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20","2432902008176640000"); } /** Tests rationals */ public void testQ() throws Exception { j = new GroupJep(new Rationals()); System.out.println(j.getGroup().toString()); valueToStringTest("(1/2)-(1/3)","1/6"); } /** Tests Quaternions */ public void testQuartonians() throws Exception { j = new GroupJep(new Quaternions()); j.addStandardConstants(); System.out.println(j.getGroup().toString()); valueToStringTest("i*j","-k"); } /** Tests integers mod 5 */ public void testZn() throws Exception { j = new GroupJep(new Zn(BigInteger.valueOf(5))); System.out.println(j.getGroup().toString()); valueToStringTest("2*3","1"); valueToStringTest("2*4","3"); valueToStringTest("3*3","4"); valueToStringTest("3*4","2"); valueToStringTest("4*4","1"); valueToStringTest("2/3","4"); valueToStringTest("2/4","3"); valueToStringTest("3/2","4"); valueToStringTest("3/4","2"); valueToStringTest("4/2","2"); valueToStringTest("4/3","3"); } public void testZroot2() throws Exception { RingI ring = new Integers(); Number coeffs[] = new Number[]{ BigInteger.valueOf(-2), BigInteger.ZERO, BigInteger.ONE}; Polynomial p1 = new Polynomial(ring,"rt2",coeffs); j = new GroupJep(new AlgebraicExtension(ring, p1)); j.addStandardConstants(); System.out.println(j.getGroup().toString()); valueToStringTest("rt2*rt2","2"); valueToStringTest("(rt2+1)*(rt2+1)","2 rt2+3"); } public void testZ5thRootUnity() throws Exception { RingI ring = new Integers(); Number coeffs[] = new Number[]{ BigInteger.valueOf(-1), BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE}; Polynomial p1 = new Polynomial(ring,"t",coeffs); j = new GroupJep(new AlgebraicExtension(ring, p1)); j.addStandardConstants(); System.out.println(j.getGroup().toString()); valueToStringTest("t*t","t^2"); valueToStringTest("t*t*t","t^3"); valueToStringTest("t*t*t*t","t^4"); valueToStringTest("t*t*t*t*t","1"); } public void testZRoot2Root5() throws Exception { RingI ring = new Integers(); Number coeffs1[] = new Number[]{ BigInteger.valueOf(-2), BigInteger.ZERO, BigInteger.ONE}; Polynomial p1 = new Polynomial(ring,"t",coeffs1); AlgebraicExtension an1 = new AlgebraicExtension(ring, p1); Number coeffs2[] = new Number[]{ an1.valueOf("-5"), an1.valueOf("0"), an1.valueOf("1")}; Polynomial p2 = new Polynomial(an1,"s",coeffs2); AlgebraicExtension an2 = new AlgebraicExtension(an1, p2); j = new GroupJep(an2); j.addStandardConstants(); System.out.println(j.getGroup().toString()); valueToStringTest("t","t"); valueToStringTest("s","s"); valueToStringTest("t*t","2"); valueToStringTest("s*s","5"); valueToStringTest("s*t","t s"); valueToStringTest("s+t","s+t"); valueToStringTest("(t-1)*(s-1)","(t-1) s-t+1"); } public void testZtau() throws Exception { RingI ring = new Integers(); Number coeffs[] = new Number[]{ BigInteger.valueOf(-1), BigInteger.valueOf(-1), BigInteger.ONE}; Polynomial p1 = new Polynomial(ring,"t",coeffs); AlgebraicExtension an = new AlgebraicExtension(ring, p1); j = new GroupJep(an); j.addStandardConstants(); j.setAllowAssignment(true); j.setAllowUndeclared(true); System.out.println(j.getGroup().toString()); valueToStringTest("t*t","t+1"); valueToStringTest("t*t*t","2 t+1"); valueToStringTest("t*t*t*t","3 t+2"); valueToStringTest("t*t*t*t*t","5 t+3"); valueToStringTest("t*t*t*t*t*t","8 t+5"); valueToStringTest("x=2*t-1","2 t-1"); valueToStringTest("x*x","5"); valueToStringTest("-t","-t"); valueToStringTest("1-t","-t+1"); valueToStringTest("t*(1-t)","-1"); } public void testPolynomials() throws Exception { RingI ring = new Reals(); FreeGroup fg = new ExtendedFreeGroup(ring,"x"); j = new GroupJep(fg); j.addStandardConstants(); j.setAllowAssignment(true); j.setAllowUndeclared(true); Node n = j.parse("(x+7.6)*(x+5.8832)*(x-55.12)"); FreeGroupElement fge = (FreeGroupElement) j.evaluate(n); Number coeffs[] = fge.getCoeffs(); for(int i=0;i "+res1); String expr2 = "6x+3y+4x+3(15x+7y)+40"; Node node2 = j.parse(expr2); Object val2 = j.evaluate(node2); String res2 = val2.toString(); System.out.println(expr2 +" -> "+res2); } public void testPolynomialCreator() throws Exception { RingI ring = new Reals(); FreeGroup fg = new FreeGroup(ring,"x"); JEP j2 = new JEP(); j2.addStandardConstants(); j2.addStandardFunctions(); j2.setAllowUndeclared(true); Node n = j2.parse("(x+7.6)*(x+5.8832)*(x-55.12)"); PolynomialVisitor pv = new PolynomialVisitor(j2); Polynomial poly = pv.calcPolynomial(n,fg); Number coeffs[] = poly.getCoeffs(); for(int i=0;i0,x,0),x,[-2,-1,0,1,2])","[0.0,0.0,0.0,1.0,2.0]"); valueTest("Map(abs(x),x,[[-2,-1],[1,2]])","[[2.0,1.0],[1.0,2.0]]"); } public void testDotInName() throws ParseException, Exception { } public void testVecCmp() throws Exception { valueTest("[1,2,3]==[1,2,3]",1); valueTest("[1,2,3]==[1,2,4]",0); } public void testVectorSum() throws Exception { valueTest("Sum([x,x^2],x,1,10)","[55.0,385.0]"); } public void testTgtDev() throws Exception { parsePreprocSimp("v=[x,x^2.0,x^3.0]"); parsePreprocSimp("l=7"); parsePreprocSimp("v/l"); parsePreprocSimp("dv=diff(v,x)"); parsePreprocSimp("dotprod=dv.dv"); parsePreprocSimp("length=sqrt(dotprod)"); parsePreprocSimp("v+y*dv/length"); } public void testComplexMatricies() throws Exception { valueTest("v=[1+i,1-2i]","[(1.0, 1.0),(1.0, -2.0)]"); valueTest("vsum(v)","(2.0, -1.0)"); valueTest("m=[[1+i,-1+i],[1-i,-1-i]]","[[(1.0, 1.0),(-1.0, 1.0)],[(1.0, -1.0),(-1.0, -1.0)]]"); valueTest("vsum(m)","(0.0, 0.0)"); valueTest("trace(m)","(0.0, 0.0)"); valueTest("m*v","[(1.0, 5.0),(-1.0, 1.0)]"); valueTest("v*m","[(-1.0, -1.0),(-5.0, 1.0)]"); valueTest("trans(m)","[[(1.0, 1.0),(1.0, -1.0)],[(-1.0, 1.0),(-1.0, -1.0)]]"); valueTest("det(m)","(0.0, -4.0)"); } /* TODO GenMat Not jet implemented for MatrixJep (can it be done?) public void testGenMatEle() throws Exception { System.out.println("The following caused a problem as ele only acepted Double arguments"); valueTest("m=[1,2,3]","[1.0,2.0,3.0]"); valueTest("GenMat(3,ele(m,n)*10,n)","[10.0,20.0,30.0]"); } */ } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/RewriteTest.java0000644000000000000000000001026710615400352022357 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.lsmp.djep.djep.*; import org.lsmp.djep.rewrite.*; /* @author rich * Created on 19-Nov-2003 */ /** * @author Rich Morris * Created on 19-Nov-2003 */ public class RewriteTest extends DJepTest { DJep j; public static final boolean SHOW_BAD=false; public RewriteTest(String name) { super(name); } public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(RewriteTest.class); // DJepTest jt = new DJepTest("DJepTest"); // jt.setUp(); suite.run(new TestResult()); } public static Test suite() { return new TestSuite(RewriteTest.class); } public void testRewrite() throws Exception { DJep j=new DJep(); j.addStandardFunctions(); j.addStandardConstants(); j.setImplicitMul(true); j.addComplex(); j.setAllowUndeclared(true); j.setAllowAssignment(true); j.addStandardDiffRules(); j.getPrintVisitor().setMaxLen(80); j.addVariable("x", 0); RewriteVisitor ev = new RewriteVisitor(); RewriteRuleI expand = new ExpandBrackets(j); RewriteRuleI colectPower = new CollectPowers(j); RewriteRuleI rules[] = new RewriteRuleI[]{expand,colectPower}; String expresions[] = new String[]{ "x*x", "x*x^2", "x^2*x" }; for(int i=0;i\"",new Comparative(1))); // addDiffRule(new PassThroughDiffRule(this,"\"<=\"",new Comparative(2))); // addDiffRule(new PassThroughDiffRule(this,"\">=\"",new Comparative(3))); // addDiffRule(new PassThroughDiffRule(this,"\"!=\"",new Comparative(4))); // addDiffRule(new PassThroughDiffRule(this,"\"==\"",new Comparative(5))); } public void testAssignDiff() throws Exception { System.out.println("\nTesting assignment and diff"); simplifyTestString("y=x^5","y=x^5.0"); simplifyTestString("z=diff(y,x)","z=5.0*x^4.0"); Node n1 = ((DSymbolTable) j.getSymbolTable()).getPartialDeriv("y",new String[]{"x"}).getEquation(); myAssertEquals("dy/dx",((DJep) j).toString(n1),"5.0*x^4.0"); simplifyTestString("w=diff(z,x)","w=20.0*x^3.0"); Node n2 = ((DSymbolTable) j.getSymbolTable()).getPartialDeriv("y",new String[]{"x","x"}).getEquation(); myAssertEquals("d^2y/dxdx",((DJep) j).toString(n2),"20.0*x^3.0"); valueTest("x=2",2); valueTest("y",32); // x^5 valueTest("z",80); // 5 x^4 valueTest("w",160); // 20 x^3 simplifyTestString("diff(ln(y),x)","(1.0/y)*5.0*x^4.0"); } public void testChainedVaraibles() throws Exception { simplifyTestString("x=5","x=5.0"); simplifyTestString("y=x","y=x"); simplifyTestString("z=y","z=y"); simplifyTestString("w=diff(z,x)","w=1.0"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/VectorJepTest.java0000644000000000000000000001432610615400352022637 0ustar rootroot/* @author rich * Created on 22-Apr-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepJUnit; import org.lsmp.djep.vectorJep.VectorJep; import org.nfunk.jep.ParseException; import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; /** * @author Rich Morris * Created on 22-Apr-2005 */ public class VectorJepTest extends JepTest { /** * @param name */ public VectorJepTest(String name) { super(name); // TODO Auto-generated constructor stub } /** * Create a test suite. * @return the TestSuite */ public static Test suite() { return new TestSuite(VectorJepTest.class); } /** * Main entry point. * @param args */ public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(VectorJepTest.class); suite.run(new TestResult()); } protected void setUp() { j = new VectorJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); } public void testMatrix() throws Exception { System.out.println("\nTesting vector and matrix operations"); j.getSymbolTable().clearValues(); valueTest("x=2",2); valueTest("(x*x)*x*(x*x)",32.0); valueTest("y=[x^3,x^2,x]","[8.0,4.0,2.0]"); valueTest("z=[3*x^2,2*x,1]","[12.0,4.0,1.0]"); valueTest("w=y^^z","[-4.0,16.0,-16.0]"); valueTest("w.y","0.0"); valueTest("w.z","0.0"); valueTest("sqrt(w . z)","0.0"); // tests result is unwrapped from scaler valueTest("sqrt([3,4] . [3,4])","5.0"); // tests result is unwrapped from scaler valueTest("y+z","[20.0,8.0,3.0]"); valueTest("y-z","[-4.0,0.0,1.0]"); valueTest("3*y","[24.0,12.0,6.0]"); valueTest("y*4","[32.0,16.0,8.0]"); valueTest("y*z","[[96.0,32.0,8.0],[48.0,16.0,4.0],[24.0,8.0,2.0]]"); valueTest("z*y","[[96.0,48.0,24.0],[32.0,16.0,8.0],[8.0,4.0,2.0]]"); j.getSymbolTable().clearValues(); j.evaluate(j.parse("y=[cos(x),sin(x)]")); j.evaluate(j.parse("z=[-sin(x),cos(x)]")); valueTest("y . y","1.0"); valueTest("y . z","0.0"); valueTest("z . z","1.0"); j.getSymbolTable().clearValues(); valueTest("x=[[1,2],[3,4]]","[[1.0,2.0],[3.0,4.0]]"); valueTest("y=[1,-1]","[1.0,-1.0]"); valueTest("x*y","[-1.0,-1.0]"); valueTest("y*x","[-2.0,-2.0]"); valueTest("x+[y,y]","[[2.0,1.0],[4.0,3.0]]"); valueTest("ele(y,1)","1.0"); // Value: 2.0 valueTest("ele(y,2)","-1.0"); // Value: 2.0 valueTest("ele(x,[1,1])","1.0"); // Value: 2.0 valueTest("ele(x,[1,2])","2.0"); // Value: 2.0 valueTest("ele(x,[2,1])","3.0"); // Value: 2.0 valueTest("ele(x,[2,2])","4.0"); // Value: 2.0 } public void testLength() throws ParseException,Exception { System.out.println("\nTesting vector and matrix functions"); valueTest("len(5)","1"); valueTest("len([1,2,3])","3"); valueTest("len([[1,2,3],[4,5,6]])","6"); valueTest("size(5)","1"); valueTest("size([1,2,3])","3"); valueTest("size([[1,2,3],[4,5,6]])","[2,3]"); valueTest("size([[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]])","[2,3,2]"); valueTest("diag([1,2,3])","[[1.0,0.0,0.0],[0.0,2.0,0.0],[0.0,0.0,3.0]]"); valueTest("id(3)","[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]]"); valueTest("getdiag([[1,2],[3,4]])","[1.0,4.0]"); valueTest("trans([[1,2],[3,4]])","[[1.0,3.0],[2.0,4.0]]"); valueTest("det([[1,2],[3,4]])","-2.0"); valueTest("det([[1,2,3],[4,5,6],[9,8,9]])","-6.0"); valueTest("det([[1,2,3],[4,5,6],[7,8,9]])","0.0"); valueTest("det([[1,2,3,4],[5,6,77,8],[4,3,2,1],[17,9,23,19]])","9100.0"); valueTest("trace([[1,2],[3,4]])","5.0"); valueTest("trace([[1,2,3],[4,5,6],[7,8,9]])","15.0"); valueTest("trace([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])","34.0"); valueTest("vsum([[1,2],[3,4]])","10.0"); valueTest("vsum([1,2,3])","6.0"); valueTest("Map(x^3,x,[1,2,3])","[1.0,8.0,27.0]"); valueTest("Map(x*y,[x,y],[1,2,3],[4,5,6])","[4.0,10.0,18.0]"); valueTest("Map(if(x>0,x,0),x,[-2,-1,0,1,2])","[0.0,0.0,0.0,1.0,2.0]"); valueTest("Map(abs(x),x,[[-2,-1],[1,2]])","[[2.0,1.0],[1.0,2.0]]"); } public void testSumVector() throws Exception { } public void testVecCmp() throws Exception { valueTest("[1,2,3]==[1,2,3]",1); valueTest("[1,2,3]==[1,2,4]",0); } public void testDotInName() throws ParseException, Exception { } public void testGenMatEle() throws Exception { System.out.println("The following caused a problem as ele only acepted Double arguments"); valueTest("m=[1,2,3]","[1.0,2.0,3.0]"); valueTest("GenMat(3,ele(m,n)*10,n)","[10.0,20.0,30.0]"); } public void testArrayAccess() throws Exception { System.out.println("\nTests array access on lhs and rhs using the a[3] notation"); valueTest("a=[1,2,3]","[1.0,2.0,3.0]"); valueTest("a[2]=4",4); valueTest("b=a[2]",4); valueTest("b",4); valueTest("c=[[1,2],[3,4]]","[[1.0,2.0],[3.0,4.0]]"); valueTest("c[1,2]=5",5); valueTest("c","[[1.0,5.0],[3.0,4.0]]"); valueTest("c[2,1]",3); } public void testElementOperations() throws Exception { ((VectorJep) j).setElementMultiply(true); valueTest("[1,2,3] == [2,2,2]","[0.0,1.0,0.0]"); valueTest("[1,2,3] != [2,2,2]","[1.0,0.0,1.0]"); valueTest("[1,2,3] < [2,2,2]","[1.0,0.0,0.0]"); valueTest("[1,2,3] <= [2,2,2]","[1.0,1.0,0.0]"); valueTest("[1,2,3] > [2,2,2]","[0.0,0.0,1.0]"); valueTest("[1,2,3] >= [2,2,2]","[0.0,1.0,1.0]"); valueTest("[1,2,3] * [2,2,2]","[2.0,4.0,6.0]"); valueTest("[1,2,3] / [2,2,2]","[0.5,1.0,1.5]"); } public void testComplexMatricies() throws Exception { valueTest("v=[1+i,1-2i]","[(1.0, 1.0),(1.0, -2.0)]"); valueTest("vsum(v)","(2.0, -1.0)"); valueTest("m=[[1+i,-1+i],[1-i,-1-i]]","[[(1.0, 1.0),(-1.0, 1.0)],[(1.0, -1.0),(-1.0, -1.0)]]"); valueTest("vsum(m)","(0.0, 0.0)"); valueTest("trace(m)","(0.0, 0.0)"); valueTest("m*v","[(1.0, 5.0),(-1.0, 1.0)]"); valueTest("v*m","[(-1.0, -1.0),(-5.0, 1.0)]"); valueTest("trans(m)","[[(1.0, 1.0),(1.0, -1.0)],[(-1.0, 1.0),(-1.0, -1.0)]]"); valueTest("det(m)","(0.0, -4.0)"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/JepTest.java0000644000000000000000000003713310615400352021455 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /* @author rich * Created on 19-Nov-2003 */ /** * @author Rich Morris * Created on 19-Nov-2003 */ public class JepTest extends TestCase { JEP j; public static final boolean SHOW_BAD=false; public JepTest(String name) { super(name); } /** * Create a test suite. * @return the TestSuite */ public static Test suite() { return new TestSuite(JepTest.class); } /** * Main entry point. * @param args */ public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(JepTest.class); suite.run(new TestResult()); } /** * Run before each test. */ protected void setUp() { j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); } /** * Assertion with message on command line. * * @param msg message to display * @param expected expected result * @param actual actual result */ public void myAssertEquals(String msg,Object expected,Object actual) { if(!actual.equals(expected)) System.out.println("Error: '"+msg+"' is '"+actual+"' should be '"+expected+"'"); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is "+actual+""); } public void myAssertNaN(String msg,Object actual) { if(actual instanceof Double) { if(Double.isNaN( ((Double) actual).doubleValue()) ) { System.out.println("Success: Value of \""+msg+"\" is "+actual+""); } else { System.out.println("Error: \""+msg+"\" is '"+actual+"' should be NaN"); assertTrue("<"+msg+"> is "+actual+" should be NaN",false); } } else { System.out.println("Error: '"+msg+"' is '"+actual+"' should be 'NaN'"); assertTrue("<"+msg+">",false); } } /** Parse and evaluate an expression. * * @param expr string to parse * @return value after evaluate. * @throws ParseException */ public Object calcValue(String expr) throws ParseException { Node n = j.parse(expr); return calcValue(n); } public Object calcValue(Node expr) throws ParseException { Object val = j.evaluate(expr); return val; } /** * Test result j.evaluate(j.parse(expr)) * @param expr the expression to parse and evaluate * @param expected result expected * @throws Exception */ public void valueTest(String expr,Object expected) throws Exception { Object res = calcValue(expr); myAssertEquals(expr,expected,res); } public void valueTest(String expr,String expected) throws Exception { Object res = calcValue(expr); myAssertEquals(expr,expected,res.toString()); } public void valueTestNaN(String expr) throws Exception { Object res = calcValue(expr); myAssertNaN(expr,res); } /** * Test parse and evaluate which should give the result Integer(a). * @param expr * @param a expected value will be converted to an Integer. * @throws Exception */ public void valueTestInt(String expr,int a) throws Exception { valueTest(expr,new Integer(a)); } /** Test parse and evaluate with with a Double result. * * @param expr * @param a expected value will be converted to a Double. * @throws Exception */ public void valueTest(String expr,double a) throws Exception { valueTest(expr,new Double(a)); } public void valueTest(String expr,double a,double tol) throws Exception { Object res = calcValue(expr); if(res instanceof Double) { double val = ((Double) res).doubleValue(); if(Math.abs(val-a) expected: <"+a+"> but was <"+res+">",false); } } /** Test parse-evaluate with complex number and given tollerence. * * @param expr * @param expected * @param tol * @throws Exception */ public void complexValueTest(String expr,Complex expected,double tol) throws Exception { Object res = calcValue(expr); if(expected.equals((Complex) res,tol)) System.out.println("Success value of \""+expr+"\" is "+res); else { System.out.println("Error value of \""+expr+"\" is "+res+" should be "+expected); assertTrue("<"+expr+"> expected: <"+expected+"> but was <"+res+">",false); } } /////////////////// Tests //////////////// /** just test JUnit working OK */ public void testGood() { myAssertEquals("1",new Double(1),new Double(1)); myAssertNaN("NaN",new Double(Double.NaN)); } public void testSimpleSum() throws Exception { valueTest("1+2",3); valueTest("2*6+3",15); valueTest("2*(6+3)",18); } public void testLogical() throws Exception { System.out.println("\nTesting logical operations"); valueTest("T=1",1); valueTest("F=0",0); valueTest("!T",0); valueTest("!F",1); valueTest("!5",0); valueTest("-0==0",1); valueTest("!-5",0); valueTest("-!5==0",1); valueTest("-!0",-1); valueTest("-0",-0.0); valueTest("T&&T",1); valueTest("T&&F",0); valueTest("F&&T",0); valueTest("F&&F",0); valueTest("T||T",1); valueTest("T||F",1); valueTest("F||T",1); valueTest("F||F",0); calcValue("a=F"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); j.addVariable("true",new Boolean(true)); j.addVariable("false",new Boolean(false)); valueTest("true==true",1); valueTest("false==false",1); valueTest("true==false",0); valueTest("true==true&&false==false",1); valueTest("if(true==true&&false==false,6,7)",6); valueTest("if(false&&true,6,7)",7); valueTest("if(true&&false==false,6,7)",6); valueTest("if((true&&true)==true,6,7)",6); valueTest("if((!false)==true,6,7)",6); } public void testFunction() throws Exception { System.out.println("\nTesting real functions"); valueTest("abs(2.5)",2.5); valueTest("abs(-2.5)",2.5); valueTest("acos(1/sqrt(2))",Math.PI/4,0.00000001); valueTest("cos(pi/3)",0.5,0.00000001); } public void testComplex() throws Exception { System.out.println("\nTesting complex values"); double tol = 0.00000001; complexValueTest("z=complex(3,2)",new Complex(3,2),tol); complexValueTest("z*z-z",new Complex(2,10),tol); complexValueTest("z^3",new Complex(-9,46),tol); complexValueTest("(z*z-z)/z",new Complex(2,2),tol); complexValueTest("w=polar(2,pi/2)",new Complex(0,2),tol); complexValueTest("ln(-1)",new Complex(0,Math.PI),tol); complexValueTest("sqrt(-1)",new Complex(0,1),tol); complexValueTest("pow(-1,0.5)",new Complex(0,1),tol); valueTest("arg(w)",Math.PI/2); valueTest("cmod(w)",2); valueTest("re(z)",3); valueTest("im(z)",2); complexValueTest("conj(z)",new Complex(3,-2),tol); complexValueTest("exp(pi i/2)",new Complex(0,1),tol); //complexValueTest("cos(z)",new Complex(3,-2),tol); } public void testIf() throws Exception { System.out.println("\nTesting if statement"); valueTest("if(1,2,3)",2); valueTest("if(-1,2,3)",3); valueTest("if(0,2,3)",3); valueTest("if(1,2,3,4)",2); valueTest("if(-1,2,3,4)",3); valueTest("if(0,2,3,4)",4); valueTest("if(0>=0,2,3,4)",2); valueTest("x=3",3); valueTest("if(x==3,1,-1)",1); valueTest("if(x!=3,1,-1)",-1); valueTest("if(x>=3,1,-1)",1); valueTest("if(x>3,1,-1)",-1); valueTest("if(x<=3,1,-1)",1); valueTest("if(x<3,1,-1)",-1); } public void testAssign() throws Exception { System.out.println("\nTesting assignment of variables"); valueTest("x=3",3); valueTest("y=3+4",7); valueTest("z=x+y",10); valueTest("a=b=c=z",10); valueTest("b",10); valueTest("d=f=a-b",0); valueTest("x=2",2); valueTest("(x*x)*x*(x*x)",32.0); // Works fine with Multiply new org.lsmp.djep.vectorJep.VectorJep(); valueTest("(x*x)*x*(x*x)",32.0); // this created an error in 2.3.0b // as creating a VectorJep changed the operator set // and hence the broken MMultiply was used. } public void testDotInName() throws ParseException,Exception { System.out.println("\nTesting names with dot in them"); valueTest("x.x=3",3); valueTest("x.x+1",4); } public void testBinom() throws ParseException,Exception { System.out.println("\nTesting binomial coeffs"); valueTestInt("binom(0,0)",1); valueTestInt("binom(1,0)",1); valueTestInt("binom(1,1)",1); valueTestInt("binom(2,0)",1); valueTestInt("binom(2,1)",2); valueTestInt("binom(2,2)",1); valueTestInt("binom(3,0)",1); valueTestInt("binom(3,1)",3); valueTestInt("binom(3,2)",3); valueTestInt("binom(3,3)",1); valueTestInt("binom(4,0)",1); valueTestInt("binom(4,1)",4); valueTestInt("binom(4,2)",6); valueTestInt("binom(4,3)",4); valueTestInt("binom(4,4)",1); valueTestInt("binom(5,0)",1); valueTestInt("binom(5,1)",5); valueTestInt("binom(5,2)",10); valueTestInt("binom(5,3)",10); valueTestInt("binom(5,4)",5); valueTestInt("binom(5,5)",1); valueTestInt("binom(6,0)",1); valueTestInt("binom(6,1)",6); valueTestInt("binom(6,2)",15); valueTestInt("binom(6,3)",20); valueTestInt("binom(6,4)",15); valueTestInt("binom(6,5)",6); valueTestInt("binom(6,6)",1); valueTestInt("binom(10,1)",10); valueTestInt("binom(10,5)",252); } public void testNaN() throws Exception { System.out.println("\nTesting for NaN"); j.addVariable("x",new Double(Double.NaN)); System.out.println("x=NaN"); valueTestNaN("ln(x)"); valueTestNaN("log(x)"); valueTestNaN("sin(x)"); valueTestNaN("x+x"); valueTest("x!=x",1); valueTest("x==x",0); j.addVariable("y",new Double(Double.NaN)); Node n = j.parse("x+5"); System.out.println(calcValue(n)); Node n2 = j.parse("y"); System.out.println(calcValue(n2)); valueTest("x == x+5",0); valueTest("x == 0/0",0); valueTest("x == x",0); valueTest("x == 0 * x",0); valueTest("x == 5",0); valueTest("x == y",0); valueTest("y == y",0); System.out.println("Set x to Double(5)"); j.setVarValue("x",new Double(5)); valueTest("x == x+5",0); valueTest("x == x",1); } public void testAssign2() { System.out.println("\nTesting for assignment using parseExpression and getValue"); JEP parser = new JEP(); parser.addVariable("AB",12); parser.addVariable("graph",new Object()); parser.addVariable("graph1",(Double) null); parser.setAllowAssignment(true); parser.parseExpression("AB=3"); // AB = 8 System.out.println("AB=3"+parser.getValue()); parser.parseExpression("AB+2"); double result= parser.getValue(); // Result = 17 assertEquals("",5.0,result,0.0); } boolean isExpressionValid(String expression) { JEP jep = j; try{ Node n = jep.parse(expression); System.out.println("expression " + expression + " \n Parsed value " + jep.hasError()); if(jep.hasError()) { System.out.println("jep.getErrorInfo " + jep.getErrorInfo()); return false; } System.out.println("jep.getSymbolTable " + jep.getSymbolTable()); System.out.println("Eval: " +jep.evaluate(n).toString()); return true; } catch(Error e) { System.out.println(e.getMessage()); if(jep.hasError()) System.out.println("Error is : " + jep.getErrorInfo()); return false; } catch(Exception e1) { System.out.println(e1.getMessage()); if(jep.hasError()) System.out.println("Error is : " + jep.getErrorInfo()); return false; } } public void testNumParam() throws Exception { j.parse("if(3,1,2)"); j.parse("if(4,1,2,3)"); try { j.parse("if(5,1,2,3,4)"); fail("Did not trap illegal number of arguments"); } catch(ParseException e) {} j.parse("a1=1234"); j.parse("a2=5678"); j.parse("ApportionmentAmt=4321"); j.parse("a4 = 2000 + (3000 /2000) + (3.45787 * 33544 - (212.223 /2000)) + + 1200"); j.parse("a3 = if(a1 > 0 && ApportionmentAmt < 1000, if(a2 < 2000, if(a2 < 1000, 200, 0), if(a1 > 1000, if((2000 + (3000 /2000) + (3.45787 * 33544 - (212.223 /2000)) + 1200 + ApportionmentAmt / 2000 + ApportionmentAmt * ApportionmentAmt + 2000) > 0, 100, 200),200)), if(a1/a2 < 1000, a1/a2, 1, a1 * a2 + a1))"); try { j.parse("a3 = if(a1 > 0 && ApportionmentAmt < 1000, if(a2 < 2000, if(a2 < 1000, 200, 0), if(a1 > 1000, if((2000 + (3000 /2000) + (3.45787 * 33544 - (212.223 /2000)) + 1200 + ApportionmentAmt / 2000 + ApportionmentAmt * ApportionmentAmt + 2000) > 0, 100, 200)),200), if(a1/a2 < 1000, a1/a2, 1, a1 * a2 + a1))"); fail("Did not trap illegal number of arguments"); } catch(ParseException e) {} /* double a1=0,a2=0,ApportionmentAmt=0; double a3 = myif( a1 > 0 && ApportionmentAmt < 1000, myif( a2 < 2000, myif(a2 < 1000, 200, 0), myif( a1 > 1000, myif( (2000 + (3000 /2000) + (3.45787 * 33544 - (212.223 /2000)) + 1200 + ApportionmentAmt / 2000 + ApportionmentAmt * ApportionmentAmt + 2000) > 0, 100, 200 ), 333)), myif(a1/a2 < 1000, a1/a2, a1 * a2 + a1)); a3 = if(a1 > 0 && ApportionmentAmt < 1000, if(a2 < 2000, if(a2 < 1000, 200, 0), if(a1 > 1000, if( (2000 + (3000 /2000) + (3.45787 * 33544 - (212.223 /2000)) + 1200 + ApportionmentAmt / 2000 + ApportionmentAmt * ApportionmentAmt + 2000) > 0, 100, 200 ) ), 200 ), if(a1/a2 < 1000, a1/a2, 1, a1 * a2 + a1) ) */ } public void testUndeclared() throws Exception { j.setAllowUndeclared(false); try { j.parse("zap * wow"); fail("Should have found undeclared error"); } catch(ParseException e) { System.out.println("Error caught: "+e.getMessage()); } try { j.setVarValue("foo",new Double(5.0)); fail("Should have found a null pointer exception"); } catch(NullPointerException e) { System.out.println("Error caught: "+e.getClass().getName()+": "+e.getMessage()); } } public void testBad() throws Exception { if(SHOW_BAD) { valueTest("recurse = recurse+1",null); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/MRpTest.java0000644000000000000000000007250310615400352021435 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.lsmp.djep.matrixJep.*; import org.lsmp.djep.mrpe.MRpCommandList; import org.lsmp.djep.mrpe.MRpEval; import org.lsmp.djep.mrpe.MRpRes; import org.lsmp.djep.vectorJep.values.*; /* @author rich * Created on 19-Nov-2003 */ /** * JUnit test for full Matrix Rp evaluator * * @author Rich Morris * Created on 19-Nov-2003 */ public class MRpTest extends TestCase { MatrixJep mj; public static final boolean SHOW_BAD=false; public MRpTest(String name) { super(name); } public static Test suite() { return new TestSuite(MRpTest.class); } public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(MRpTest.class); // DJepTest jt = new DJepTest("DJepTest"); // jt.setUp(); suite.run(new TestResult()); } /** strings for each variable */ String matStrs[][] = new String[10][10]; String vecStrs[] = new String[10]; protected void setUp() { mj = new MatrixJep(); mj.addStandardConstants(); mj.addStandardFunctions(); mj.addComplex(); //j.setTraverse(true); mj.setAllowAssignment(true); mj.setAllowUndeclared(true); mj.setImplicitMul(true); mj.addStandardDiffRules(); for(int i=2;i<=9;++i) for(int j=2;j<=9;++j) { int num=1; StringBuffer sb = new StringBuffer("["); for(int k=0;k0)sb.append(","); sb.append("["); for(int l=0;l0)sb.append(","); sb.append(String.valueOf(num++)); } sb.append("]"); } sb.append("]"); matStrs[i][j] = sb.toString(); } for(int i=2;i<=9;++i) { int num=1; StringBuffer sb = new StringBuffer("["); for(int k=0;k0)sb.append(","); sb.append(String.valueOf(num++)); } sb.append("]"); vecStrs[i] = sb.toString(); } } public void testGood() { assertEquals(1,1); } public void myAssertEquals(String msg,String actual,String expected) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \n<"+actual+"> should be \n<"+expected+">"); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of <"+msg+"> is <"+actual+">"); } public void valueTest(String expr,double dub) throws ParseException { valueTest(expr,new Double(dub)); } public void valueTest(String expr,Object expected) throws ParseException { Node node = mj.parse(expr); Node matEqn = mj.preprocess(node); Object res = mj.evaluate(matEqn); if(mj.hasError()) fail("Evaluation Failure: "+expr+mj.getErrorInfo()); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess value of <"+expr+"> is "+res); } public void valueTest(String expr,String expected) throws ParseException { Node node = mj.parse(expr); Node matEqn = mj.preprocess(node); Object res = mj.evaluate(matEqn); if(mj.hasError()) fail("Evaluation Failure: "+expr+mj.getErrorInfo()); assertEquals("<"+expr+">",expected,res.toString()); System.out.println("Sucess value of <"+expr+"> is "+res.toString()); } public void complexValueTest(String expr,Complex expected,double tol) throws Exception { Node node = mj.preprocess(mj.parse(expr)); Object res = mj.evaluate(node); assertTrue("<"+expr+"> expected: <"+expected+"> but was <"+res+">", expected.equals((Complex) res,tol)); System.out.println("Sucess value of <"+expr+"> is "+res); } public Object calcValue(String expr) throws ParseException { Node node = mj.parse(expr); Node matEqn = mj.preprocess(node); Object res = mj.evaluate(matEqn); return res; } public void simplifyTest(String expr,String expected) throws ParseException { Node node = mj.parse(expr); Node matEqn = mj.preprocess(node); Node simp = mj.simplify(matEqn); String res = mj.toString(simp); Node node2 = mj.parse(expected); Node matEqn2 = mj.preprocess(node2); Node simp2 = mj.simplify(matEqn2); String res2 = mj.toString(simp2); if(!res2.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+res2+"\""); assertEquals("<"+expr+">",res2,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } public void simplifyTestString(String expr,String expected) throws ParseException { Node node = mj.parse(expr); Node matEqn = mj.preprocess(node); String res = mj.toString(matEqn); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } void rpTest(String eqns[], String eqn2) throws ParseException { for(int i=0;i",rpRes.toString(),matRes.toString()); if(!mat.equals(matRes)) fail("Expected <"+matRes+"> found <"+mat+">"); if(rpRes.getDims().is1D()) { double vecArray[] = (double []) rpRes.toArray(); for(int i=0;i "+rpRes.toString()); } for(int i=0;i found <"+rpMats[i]+">"); } rpe.cleanUp(); } public void testRp() throws ParseException { rpTest(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*y"); rpTest(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y+y"); rpTest(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y-y"); rpTest(new String[]{"y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*y+y"); rpTest(new String[]{"x=[1,2,3]","y=[[1,2,3],[4,5,6],[7,8,9]]"},"x*y"); rpTest(new String[]{"x=[1,2,3]","y=[[1,2,3],[4,5,6],[7,8,9]]"},"y*x"); rpTest(new String[0],"[[1,2,3],[4,5,6],[7,8,9]]*[[1,2,3],[4,5,6],[7,8,9]]"); rpTest(new String[]{"y=[1,2]"},"y+y"); rpTest(new String[]{"y=[1,2,3]"},"y+y"); rpTest(new String[]{"y=[1,2,3,4]"},"y+y"); rpTest(new String[]{"y=[1,2]"},"-y"); rpTest(new String[]{"y=[1,2,3]"},"-y"); rpTest(new String[]{"y=[1,2,3,4]"},"-y"); rpTest(new String[]{"y=[1,2]"},"y-y"); rpTest(new String[]{"y=[1,2,3]"},"y-y"); rpTest(new String[]{"y=[1,2,3,4]"},"y-y"); rpTest(new String[]{"y=[1,2]"},"y*3"); rpTest(new String[]{"y=[1,2,3]"},"y*3"); rpTest(new String[]{"y=[1,2,3,4]"},"y*3"); rpTest(new String[]{"y=[1,2]"},"5*y"); rpTest(new String[]{"y=[1,2,3]"},"5*y"); rpTest(new String[]{"y=[1,2,3,4]"},"5*y"); rpTest(new String[]{"y=[1,2,3]"},"y . y"); rpTest(new String[]{"y=[1,2,3]"},"y^^y"); rpTest(new String[]{"y=[[1,2],[3,4]]"},"y*y"); rpTest(new String[]{"y=[[1,2],[3,4]]"},"y+y"); rpTest(new String[]{"y=[[1,2],[3,4]]"},"y-y"); rpTest(new String[]{"y=[[1,2],[3,4]]"},"y*y+y"); rpTest(new String[]{"x=[1,2]","y=[[1,2],[3,4]]"},"x*y"); rpTest(new String[]{"x=[1,2]","y=[[1,2],[3,4]]"},"y*x"); rpTest(new String[0],"1*2*3+4*5*6+7*8*9"); rpTest(new String[]{"x1=1","x2=2","x3=3","x4=4","x5=5","x6=6","x7=7","x8=8","x9=9"}, "x1*x2*x3+x4*x5*x6+x7*x8*x9"); } public void testRpAllDim() throws ParseException { for(int i=2;i<=4;++i) for(int j=2;j<=4;++j) { int num=1; StringBuffer sb = new StringBuffer("x=["); for(int k=0;k0)sb.append(","); sb.append("["); for(int l=0;l0)sb.append(","); sb.append(String.valueOf(num++)); } sb.append("]"); } sb.append("]"); String varStr = sb.toString(); rpTest(new String[]{varStr},"x+x"); rpTest(new String[]{varStr},"x-x"); rpTest(new String[]{varStr},"3*x"); rpTest(new String[]{varStr},"x*5"); rpTest(new String[]{varStr},"-x"); } } public void testMul() throws ParseException { rpTest(new String[]{"x=[1,2]","y="+matStrs[2][2]},"x*y"); rpTest(new String[]{"x=[1,2]","y="+matStrs[2][3]},"x*y"); rpTest(new String[]{"x=[1,2]","y="+matStrs[2][4]},"x*y"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[3][2]},"x*y"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[3][3]},"x*y"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[3][4]},"x*y"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[4][2]},"x*y"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[4][3]},"x*y"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[4][4]},"x*y"); rpTest(new String[]{"x=[1,2]","y="+matStrs[2][2]},"y*x"); rpTest(new String[]{"x=[1,2]","y="+matStrs[3][2]},"y*x"); rpTest(new String[]{"x=[1,2]","y="+matStrs[4][2]},"y*x"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[2][3]},"y*x"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[3][3]},"y*x"); rpTest(new String[]{"x=[1,2,3]","y="+matStrs[4][3]},"y*x"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[2][4]},"y*x"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[3][4]},"y*x"); rpTest(new String[]{"x=[1,2,3,4]","y="+matStrs[4][4]},"y*x"); rpTest(new String[]{"x="+matStrs[2][2],"y="+matStrs[2][2]},"x*y"); rpTest(new String[]{"x="+matStrs[2][2],"y="+matStrs[2][3]},"x*y"); rpTest(new String[]{"x="+matStrs[2][2],"y="+matStrs[2][4]},"x*y"); rpTest(new String[]{"x="+matStrs[2][3],"y="+matStrs[3][2]},"x*y"); rpTest(new String[]{"x="+matStrs[2][3],"y="+matStrs[3][3]},"x*y"); rpTest(new String[]{"x="+matStrs[2][3],"y="+matStrs[3][4]},"x*y"); rpTest(new String[]{"x="+matStrs[2][4],"y="+matStrs[4][2]},"x*y"); rpTest(new String[]{"x="+matStrs[2][4],"y="+matStrs[4][3]},"x*y"); rpTest(new String[]{"x="+matStrs[2][4],"y="+matStrs[4][4]},"x*y"); // rpTest(new String[]{"x="+matStrs[3][2],"y="+matStrs[2][2]},"x*y"); rpTest(new String[]{"x="+matStrs[3][2],"y="+matStrs[2][3]},"x*y"); rpTest(new String[]{"x="+matStrs[3][2],"y="+matStrs[2][4]},"x*y"); rpTest(new String[]{"x="+matStrs[3][3],"y="+matStrs[3][2]},"x*y"); rpTest(new String[]{"x="+matStrs[3][3],"y="+matStrs[3][3]},"x*y"); rpTest(new String[]{"x="+matStrs[3][3],"y="+matStrs[3][4]},"x*y"); rpTest(new String[]{"x="+matStrs[3][4],"y="+matStrs[4][2]},"x*y"); rpTest(new String[]{"x="+matStrs[3][4],"y="+matStrs[4][3]},"x*y"); rpTest(new String[]{"x="+matStrs[3][4],"y="+matStrs[4][4]},"x*y"); // rpTest(new String[]{"x="+matStrs[4][2],"y="+matStrs[2][2]},"x*y"); rpTest(new String[]{"x="+matStrs[4][2],"y="+matStrs[2][3]},"x*y"); rpTest(new String[]{"x="+matStrs[4][2],"y="+matStrs[2][4]},"x*y"); rpTest(new String[]{"x="+matStrs[4][3],"y="+matStrs[3][2]},"x*y"); rpTest(new String[]{"x="+matStrs[4][3],"y="+matStrs[3][3]},"x*y"); rpTest(new String[]{"x="+matStrs[4][3],"y="+matStrs[3][4]},"x*y"); rpTest(new String[]{"x="+matStrs[4][4],"y="+matStrs[4][2]},"x*y"); rpTest(new String[]{"x="+matStrs[4][4],"y="+matStrs[4][3]},"x*y"); rpTest(new String[]{"x="+matStrs[4][4],"y="+matStrs[4][4]},"x*y"); } public void testAssign() throws ParseException { rpTest2(new String[]{"x=[[5,6],[7,8]]","x+x"}); rpTest2(new String[]{"x=[5,6]","x+x"}); rpTest2(new String[]{"x=[5,6,7]","x+x"}); rpTest2(new String[]{"x=[5,6,7,8]","x+x"}); rpTest2(new String[]{"x=5","x+x"}); for(int i=2;i<=4;++i) for(int j=2;j<=4;++j) { rpTest2(new String[]{"x="+matStrs[i][j],"x+x"}); } } public void testLogical() throws ParseException { rpTest2(new String[]{"1&&1","1&&0","0&&0","0&&1","3.14&&1"}); rpTest2(new String[]{"1||1","1||0","0||0","0||1","3.14||0"}); rpTest2(new String[]{"!0","!1","!3.14","!-3.14"}); rpTest2(new String[]{"1>1","1>0","0>0","0>1","3.14>1"}); rpTest2(new String[]{"1<1","1<0","0<0","0<1","3.14<1"}); rpTest2(new String[]{"1>=1","1>=0","0>=0","0>=1","3.14>=1"}); rpTest2(new String[]{"1<=1","1<=0","0<=0","0<=1","3.14<=1"}); rpTest2(new String[]{"1==1","1==0","0==0","0==1","3.14==1"}); rpTest2(new String[]{"1!=1","1!=0","0!=0","0!=1","3.14!=1"}); rpTest2(new String[]{"[1,2]==[1,2]"}); rpTest2(new String[]{"[1,2]!=[1,2]"}); rpTest2(new String[]{"[1,2]==[5,6]"}); rpTest2(new String[]{"[1,2]!=[5,6]"}); rpTest2(new String[]{"[1,2,3]==[1,2,3]"}); rpTest2(new String[]{"[1,2,3]!=[1,2,3]"}); rpTest2(new String[]{"[1,2,3]==[5,6,7]"}); rpTest2(new String[]{"[1,2,3]!=[5,6,7]"}); rpTest2(new String[]{"[1,2,3]==[1,2,4]"}); rpTest2(new String[]{"[1,2,3]!=[1,2,4]"}); rpTest2(new String[]{"[1,2,3,4]==[1,2,3,4]"}); rpTest2(new String[]{"[1,2,3,4]!=[1,2,3,4]"}); rpTest2(new String[]{"[1,2,3,4]==[5,6,7,8]"}); rpTest2(new String[]{"[1,2,3,4]!=[5,6,7,8]"}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"=="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); rpTest2(new String[]{matStrs[2][2]+"!="+matStrs[2][2]}); } boolean TESTALL = false; public void testVn() throws ParseException { rpTest2(new String[]{"x=[5,6,7,8,9]","x+x","x-x","2*x","x*3","x.x"}); rpTest2(new String[]{"x=[[1,2,3,4,5],[5,6,7,8,9]]","x+x","x-x","2*x","x*3"}); rpTest2(new String[]{"x=[[1,2],[3,4]]","y=[[1,2,3,4,5],[5,6,7,8,9]]","x*y"}); rpTest2(new String[]{"x=[[1,2],[3,4]]","y=[[1,2],[3,4],[5,6],[7,8],[9,10]]","y*x"}); rpTest2(new String[]{"x=[[1,2,3,4,5],[5,6,7,8,9]]","y=[[1,2],[3,4],[5,6],[7,8],[9,10]]","y*x"}); if(TESTALL) { for(int i=2;i<10;++i) for(int j=2;j<10;++j) for(int k=2;k<10;++k) { System.out.println("\n["+i+","+j+"]*["+j+","+k+"]"); rpTest2(new String[]{"x="+matStrs[i][j],"y="+matStrs[j][k],"x*y"}); } for(int i=2;i<10;++i) for(int j=2;j<10;++j) { System.out.println("\n["+i+","+j+"]*["+j+"]"); rpTest2(new String[]{"x="+matStrs[i][j],"y="+vecStrs[j],"x*y"}); } for(int j=2;j<10;++j) for(int k=2;k<10;++k) { System.out.println("\n["+j+"]*["+j+","+k+"]"); rpTest2(new String[]{"x="+vecStrs[j],"y="+matStrs[j][k],"x*y"}); } } } public void testFun() throws ParseException { rpTest2(new String[]{"x=5","y=4","x/y","x%y","x^y"}); rpTest2(new String[]{"x=0.5","cos(x)","sin(x)","tan(x)","asin(x)","acos(x)","atan(x)"}); rpTest2(new String[]{"x=0.5","cosh(x)","sinh(x)","tanh(x)","asinh(x)","acosh(x+1)","atanh(x)"}); rpTest2(new String[]{"x=0.5","sqrt(x)","ln(x)","log(x)","exp(x)","abs(x)"}); rpTest2(new String[]{"x=0.5","sec(x)","cosec(x)","cot(x)"}); } public void testUndecVar() throws ParseException { mj.setAllowUndeclared(true); MRpEval rpe = new MRpEval(mj); Node node1 = mj.parse("zap * gosh"); Node node3 = mj.preprocess(node1); rpe.compile(node3); } /* public void testSimpleSum() throws ParseException { valueTest("1+2",3); valueTest("2*6+3",15); valueTest("2*(6+3)",18); } public void testOperators() throws ParseException { // if(!Operator.OP_MULTIPLY.isDistributiveOver(Operator.OP_ADD)) // fail("* should be distrib over +"); // if(Operator.OP_MULTIPLY.isDistributiveOver(Operator.OP_DIVIDE)) // fail("* should not be distrib over /"); // if(Operator.OP_MULTIPLY.getPrecedence() > Operator.OP_ADD.getPrecedence()) // fail("* should have a lower precedence than +"); valueTest("T=1",1); valueTest("F=0",0); calcValue("a=F"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); } public void testSimp() throws ParseException { simplifyTest("2+3","5"); simplifyTest("2*3","6"); simplifyTest("2^3","8"); simplifyTest("3/2","1.5"); simplifyTest("2*3+4","10"); simplifyTest("2*(3+4)","14"); simplifyTest("0+x","x"); simplifyTest("x+0","x"); simplifyTest("0-x","0-x"); simplifyTest("x-0","x"); simplifyTest("0*x","0"); simplifyTest("x*0","0"); simplifyTest("1*x","x"); simplifyTest("x*1","x"); simplifyTest("-1*x","-x"); simplifyTest("x*-1","-x"); simplifyTest("-(-x)","x"); simplifyTest("-(-(-x))","-x"); simplifyTest("(-1)*(-1)*x","x"); simplifyTest("(-1)*(-1)*(-1)*x","-x"); simplifyTest("0/x","0"); simplifyTest("x/0","1/0"); simplifyTest("x^0","1"); simplifyTest("x^1","x"); simplifyTest("0^x","0"); simplifyTest("1^x","1"); // (a+b)+c simplifyTest("(2+3)+x","5+x"); simplifyTest("(2+x)+3","5+x"); simplifyTest("(x+2)+3","5+x"); // a+(b+c) simplifyTest("x+(2+3)","5+x"); simplifyTest("2+(x+3)","5+x"); simplifyTest("2+(3+x)","5+x"); // (a+b)-c simplifyTest("(2+3)-x","5-x"); simplifyTest("(2+x)-3","x-1"); simplifyTest("(x+2)-3","x-1"); // (a-b)+c simplifyTest("(2-3)+x","-1+x"); simplifyTest("(2-x)+3","5-x"); simplifyTest("(x-2)+3","1+x"); // a-(b+c) simplifyTest("x-(2+3)","x-5"); simplifyTest("2-(x+3)","-1-x"); simplifyTest("2-(3+x)","-1-x"); // a+(b-c) simplifyTest("x+(2-3)","x-1"); simplifyTest("2+(x-3)","-1+x"); simplifyTest("2+(3-x)","5-x"); // a-(b-c) simplifyTest("x-(2-3)","1+x"); simplifyTest("2-(x-3)","5-x"); simplifyTest("2-(3-x)","-1+x"); // (a-b)-c simplifyTest("(2-3)-x","-1-x"); simplifyTest("(2-x)-3","-1-x"); simplifyTest("(x-2)-3","x-5"); // (a*b)*c simplifyTest("(2*3)*x","6*x"); simplifyTest("(2*x)*3","6*x"); simplifyTest("(x*2)*3","6*x"); // a+(b+c) simplifyTest("x*(2*3)","6*x"); simplifyTest("2*(x*3)","6*x"); simplifyTest("2*(3*x)","6*x"); // (a+b)-c simplifyTest("(2*3)/x","6/x"); simplifyTest("(3*x)/2","1.5*x"); simplifyTest("(x*3)/2","1.5*x"); // (a-b)+c simplifyTest("(3/2)*x","1.5*x"); simplifyTest("(3/x)*2","6/x"); simplifyTest("(x/2)*3","1.5*x"); // a-(b+c) simplifyTest("x/(2*3)","x/6"); simplifyTest("3/(x*2)","1.5/x"); simplifyTest("3/(2*x)","1.5/x"); // a+(b-c) simplifyTest("x*(3/2)","1.5*x"); simplifyTest("3*(x/2)","1.5*x"); simplifyTest("3*(2/x)","6/x"); // a-(b-c) simplifyTest("x/(3/2)","x/1.5"); simplifyTest("2/(x/3)","6/x"); simplifyTest("3/(2/x)","1.5*x"); // (a-b)-c simplifyTest("(3/2)/x","1.5/x"); simplifyTest("(3/x)/2","1.5/x"); simplifyTest("(x/3)/2","x/6"); simplifyTest("x*(3+2)","5*x"); simplifyTest("3*(x+2)","6+3*x"); simplifyTest("3*(2+x)","6+3*x"); simplifyTest("(3+2)*x","5*x"); simplifyTest("(3+x)*2","6+2*x"); simplifyTest("(x+3)*2","6+x*2"); simplifyTest("x*(3-2)","x"); simplifyTest("3*(x-2)","-6+3*x"); simplifyTest("3*(2-x)","6-3*x"); simplifyTest("(3-2)*x","x"); simplifyTest("(3-x)*2","6-2*x"); simplifyTest("(x-3)*2","-6+2*x"); simplifyTest("3+(x/4)","3+x/4"); simplifyTest("2*(x/4)","0.5*x"); simplifyTest("(2*(3+(x/4)))","6+0.5*x"); simplifyTest("1+(2*(3+(x/4)))","7+0.5*x"); simplifyTest("((3+(x/4))*2)+1","7+0.5*x"); } public void testComplex() throws Exception { double tol = 0.00000001; complexValueTest("z=complex(3,2)",new Complex(3,2),tol); complexValueTest("z*z-z",new Complex(2,10),tol); complexValueTest("z^3",new Complex(-9,46),tol); complexValueTest("(z*z-z)/z",new Complex(2,2),tol); complexValueTest("w=polar(2,pi/2)",new Complex(0,2),tol); } public void testIf() throws ParseException { valueTest("if(1,2,3)",2); valueTest("if(-1,2,3)",3); valueTest("if(0,2,3)",3); valueTest("if(1,2,3,4)",2); valueTest("if(-1,2,3,4)",3); valueTest("if(0,2,3,4)",4); valueTest("if(0>=0,2,3,4)",2); valueTest("x=3",3); valueTest("if(x==3,1,-1)",1); valueTest("if(x!=3,1,-1)",-1); valueTest("if(x>=3,1,-1)",1); valueTest("if(x>3,1,-1)",-1); valueTest("if(x<=3,1,-1)",1); valueTest("if(x<3,1,-1)",-1); } public void testAssign() throws ParseException { valueTest("x=3",3); valueTest("y=3+4",7); valueTest("z=x+y",10); valueTest("a=b=c=z",10); valueTest("b",10); valueTest("d=f=a-b",0); } public void testDiff() throws ParseException { simplifyTest("diff(x^2,x)","2 x"); simplifyTest("diff(x^3,x)","3 x^2"); simplifyTest("diff(x,x)","1"); simplifyTest("diff(1,x)","0"); simplifyTest("diff(x^2+x+1,x)","2 x+1"); simplifyTest("diff((x+x^2)*(x+x^3),x)","(1+2*x)*(x+x^3)+(x+x^2)*(1+3*x^2)"); simplifyTest("diff((x+x^2)/(x+x^3),x)","((1+2*x)*(x+x^3)-(x+x^2)*(1+3*x^2))/((x+x^3)*(x+x^3))"); simplifyTest("diff(sin(x),x)","cos(x)"); simplifyTest("diff(-(x-5)^3,x)","-(3.0*(x-5.0)^2.0)"); simplifyTest("diff((x+1)^2,x)","2+2*x"); simplifyTest("diff((x+y)^2,x)","2*(x+y)"); simplifyTest("diff((x+x^2)^3,x)","3*(x+x^2)^2*(1+2*x)"); simplifyTest("diff(sin(x+1),x)","cos(x+1)"); simplifyTest("diff(sin(x+x^2),x)","cos(x+x^2)*(1+2*x)"); simplifyTest("diff(cos(x),x)","-sin(x)"); simplifyTest("diff(tan(x),x)","1/((cos(x))^2)"); simplifyTest("diff(sec(x),x)","sec(x)*tan(x)"); simplifyTest("diff(cosec(x),x)","-cosec(x) * cot(x)"); simplifyTest("diff(cot(x),x)","-(cosec(x))^2"); simplifyTest("diff(sec(x),x)","sec(x) * tan(x)"); simplifyTest("diff(cosec(x),x)","-cosec(x) * cot(x)"); simplifyTest("diff(cot(x),x)","-(cosec(x))^2"); simplifyTest("diff(asin(x),x)","1/(sqrt(1-x^2))"); simplifyTest("diff(acos(x),x)","-1/(sqrt(1-x^2))"); simplifyTest("diff(atan(x),x)","1/(1+x^2)"); simplifyTest("diff(sinh(x),x)","cosh(x)"); simplifyTest("diff(cosh(x),x)","sinh(x)"); simplifyTest("diff(tanh(x),x)","1-(tanh(x))^2"); simplifyTest("diff(asinh(x),x)","1/(sqrt(1+x^2))"); simplifyTest("diff(acosh(x),x)","1/(sqrt(x^2-1))"); simplifyTest("diff(atanh(x),x)","1/(1-x^2)"); simplifyTest("diff(sqrt(x),x)","1/(2 (sqrt(x)))"); simplifyTest("diff(exp(x),x)","exp(x)"); // simplifyTest("diff(pow(x,y),x)","y*(pow(x,y-1))"); // simplifyTest("diff(pow(x,y),y)","(ln(x)) (pow(x,y))"); simplifyTest("diff(ln(x),x)","1/x"); simplifyTest("diff(log(x),x)","(1/ln(10)) /x"); simplifyTest("diff(abs(x),x)","abs(x)/x"); simplifyTest("diff(angle(x,y),x)","y/(x^2+y^2)"); simplifyTest("diff(angle(x,y),y)","-x/(x^2+y^2)"); simplifyTest("diff(mod(x,y),x)","1"); simplifyTest("diff(mod(x,y),y)","0"); simplifyTest("diff(sum(x,x^2,x^3),x)","sum(1,2 x,3 x^2)"); // addDiffRule(new PassThroughDiffRule(this,"sum")); // addDiffRule(new PassThroughDiffRule(this,"re")); // addDiffRule(new PassThroughDiffRule(this,"im")); // addDiffRule(new PassThroughDiffRule(this,"rand")); // // MacroFunction complex = new MacroFunction("complex",2,"x+i*y",xjep); // xjep.addFunction("complex",complex); // addDiffRule(new MacroFunctionDiffRules(this,complex)); // // addDiffRule(new PassThroughDiffRule(this,"\"<\"",new Comparative(0))); // addDiffRule(new PassThroughDiffRule(this,"\">\"",new Comparative(1))); // addDiffRule(new PassThroughDiffRule(this,"\"<=\"",new Comparative(2))); // addDiffRule(new PassThroughDiffRule(this,"\">=\"",new Comparative(3))); // addDiffRule(new PassThroughDiffRule(this,"\"!=\"",new Comparative(4))); // addDiffRule(new PassThroughDiffRule(this,"\"==\"",new Comparative(5))); } public void myAssertEquals(String msg,String actual,String expected) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \""+actual+" should be "+expected+"\""); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is \""+actual+"\""); } */ public void testAssignDiff() throws ParseException { //TODO Used to be an error but new procedure for working with derivs should add test //rpTest2(new String[]{"x=2","y=x^5","z=diff(y,x)"}); } /* public void testMatrix() throws ParseException { j.getSymbolTable().clearValues(); valueTest("x=2",2); valueTest("y=[x^3,x^2,x]","[8.0,4.0,2.0]"); valueTest("z=diff(y,x)","[12.0,4.0,1.0]"); valueTest("3*y","[24.0,12.0,6.0]"); valueTest("y*4","[32.0,16.0,8.0]"); valueTest("y*z","[[96.0,32.0,8.0],[48.0,16.0,4.0],[24.0,8.0,2.0]]"); valueTest("z*y","[[96.0,48.0,24.0],[32.0,16.0,8.0],[8.0,4.0,2.0]]"); valueTest("w=y^z","[-4.0,16.0,-16.0]"); simplifyTestString("diff(w,x)","[3.0*x^2.0,2.0*x,1.0]^z+y^[6.0*x,2.0,0.0]"); simplifyTestString("diff(y . z,x)","[3.0*x^2.0,2.0*x,1.0].z+y.[6.0*x,2.0,0.0]"); valueTest("w.y",0.0); valueTest("w.z",0.0); valueTest("sqrt(w . z)",0.0); valueTest("sqrt([3,4].[3,4])",5.0); // tests result is unwrapped from scaler valueTest("y+z","[20.0,8.0,3.0]"); valueTest("y-z","[-4.0,0.0,1.0]"); j.getSymbolTable().clearValues(); // the following two tests insure that ^ is printed correctly simplifyTestString("y^z","y^z"); simplifyTestString("[8.0,4.0,2.0]^[12.0,4.0,1.0]","[8.0,4.0,2.0]^[12.0,4.0,1.0]"); simplifyTestString("y=[cos(x),sin(x)]","y=[cos(x),sin(x)]"); simplifyTestString("z=diff(y,x)","z=[-sin(x),cos(x)]"); valueTest("y.y",1.0); valueTest("y.z",0.0); valueTest("z.z",1.0); j.getSymbolTable().clearValues(); valueTest("x=[[1,2],[3,4]]","[[1.0,2.0],[3.0,4.0]]"); valueTest("y=[1,-1]","[1.0,-1.0]"); valueTest("x*y","[-1.0,-1.0]"); valueTest("y*x","[-2.0,-2.0]"); valueTest("x+[y,y]","[[2.0,1.0],[4.0,3.0]]"); valueTest("ele(y,1)","1.0"); // Value: 2.0 valueTest("ele(y,2)","-1.0"); // Value: 2.0 valueTest("ele(x,[1,1])","1.0"); // Value: 2.0 valueTest("ele(x,[1,2])","2.0"); // Value: 2.0 valueTest("ele(x,[2,1])","3.0"); // Value: 2.0 valueTest("ele(x,[2,2])","4.0"); // Value: 2.0 } public void testBad() throws ParseException { if(SHOW_BAD) { simplifyTest("1&&(1||x)","1"); simplifyTest("diff(sgn(x),x)","0"); // sgn not implemented simplifyTest("diff(re(x+i y),x)","1"); // not smart enought to work out re(i) = 1 simplifyTest("diff(re(x+i y),y)","0"); simplifyTest("diff(im(x+i y),x)","0"); simplifyTest("diff(im(x+i y),y)","1"); simplifyTest("(x/2)*3","x*1.5"); } } */ } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/RpTest.java0000644000000000000000000004717110615400352021323 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.lsmp.djep.rpe.*; /* @author rich * Created on 19-Nov-2003 */ /** * JUnit test for full Matrix Rp evaluator * * @author Rich Morris * Created on 19-Nov-2003 */ public class RpTest extends TestCase { JEP j; public static final boolean SHOW_BAD=false; public RpTest(String name) { super(name); } public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(RpTest.class); // DJepTest jt = new DJepTest("DJepTest"); // jt.setUp(); suite.run(new TestResult()); } /** strings for each variable */ String matStrs[][] = new String[10][10]; String vecStrs[] = new String[10]; protected void setUp() { j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); } public static Test suite() { return new TestSuite(RpTest.class); } public void testGood() { assertEquals(1,1); } public void myAssertEquals(String msg,String actual,String expected) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \n<"+actual+"> should be \n<"+expected+">"); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of <"+msg+"> is <"+actual+">"); } public void valueTest(String expr,double dub) throws ParseException,Exception { valueTest(expr,new Double(dub)); } public void valueTest(String expr,Object expected) throws ParseException,Exception { Node node = j.parse(expr); Object res = j.evaluate(node); if(j.hasError()) fail("Evaluation Failure: "+expr+j.getErrorInfo()); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess value of <"+expr+"> is "+res); } public void valueTest(String expr,String expected) throws ParseException,Exception { Node node = j.parse(expr); Object res = j.evaluate(node); if(j.hasError()) fail("Evaluation Failure: "+expr+j.getErrorInfo()); assertEquals("<"+expr+">",expected,res.toString()); System.out.println("Sucess value of <"+expr+"> is "+res.toString()); } public void complexValueTest(String expr,Complex expected,double tol) throws Exception { Node node = j.parse(expr); Object res = j.evaluate(node); assertTrue("<"+expr+"> expected: <"+expected+"> but was <"+res+">", expected.equals((Complex) res,tol)); System.out.println("Sucess value of <"+expr+"> is "+res); } public Object calcValue(String expr) throws ParseException,Exception { Node node = j.parse(expr); Object res = j.evaluate(node); return res; } /* public void simplifyTest(String expr,String expected) throws ParseException,Exception { Node node = j.parse(expr); String res = j.toString(node); Node node2 = j.parse(expected); Node matEqn2 = j.preprocess(node2); Node simp2 = j.simplify(matEqn2); String res2 = j.toString(simp2); if(!res2.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+res2+"\""); assertEquals("<"+expr+">",res2,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } */ /* public void simplifyTestString(String expr,String expected) throws ParseException { Node node = j.parse(expr); Node matEqn = j.preprocess(node); String res = j.toString(matEqn); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } */ void rpTest(String eqns[], String eqn2) throws ParseException,Exception { for(int i=0;i",""+rpRes,matRes.toString()); if(!matRes.equals(new Double(rpRes))) fail("Expected <"+matRes+"> found <"+rpRes+">"); } /** As before but don't test with MatrixJep.evaluate */ void rpTest2(String eqns[]) throws ParseException,Exception { Node nodes[] = new Node[eqns.length]; double rpRes[] = new double[eqns.length]; RpEval rpe = new RpEval(j); for(int i=0;i "+rpRes[i]); } for(int i=0;i found <"+rpRes[i]+">"); } rpe.cleanUp(); } public void testRp() throws ParseException,Exception { rpTest(new String[0],"1*2*3+4*5*6+7*8*9"); rpTest(new String[]{"x1=1","x2=2","x3=3","x4=4","x5=5","x6=6","x7=7","x8=8","x9=9"}, "x1*x2*x3+x4*x5*x6+x7*x8*x9"); } public void testAssign() throws ParseException,Exception { rpTest2(new String[]{"x=5","x+x"}); j.setVarValue("x",new Double(6.0)); rpTest2(new String[]{"x+x"}); } public void testLogical() throws ParseException,Exception { rpTest2(new String[]{"1&&1","1&&0","0&&0","0&&1","3.14&&1"}); rpTest2(new String[]{"1||1","1||0","0||0","0||1","3.14||0"}); rpTest2(new String[]{"!0","!1","!3.14","!-3.14"}); rpTest2(new String[]{"1>1","1>0","0>0","0>1","3.14>1"}); rpTest2(new String[]{"1<1","1<0","0<0","0<1","3.14<1"}); rpTest2(new String[]{"1>=1","1>=0","0>=0","0>=1","3.14>=1"}); rpTest2(new String[]{"1<=1","1<=0","0<=0","0<=1","3.14<=1"}); rpTest2(new String[]{"1==1","1==0","0==0","0==1","3.14==1"}); rpTest2(new String[]{"1!=1","1!=0","0!=0","0!=1","3.14!=1"}); } boolean TESTALL = false; public void testFun() throws ParseException,Exception { rpTest2(new String[]{"x=5","y=4","x/y","x%y","x^y"}); rpTest2(new String[]{"x=0.5","cos(x)","sin(x)","tan(x)","asin(x)","acos(x)","atan(x)"}); rpTest2(new String[]{"x=0.5","cosh(x)","sinh(x)","tanh(x)","asinh(x)","acosh(x+1)","atanh(x)"}); rpTest2(new String[]{"x=0.5","sqrt(x)","ln(x)","log(x)","exp(x)","abs(x)"}); rpTest2(new String[]{"x=0.5","cos(x)^2+sin(x)^2"}); // rpTest2(new String[]{"x=0.5","sec(x)","cosec(x)","cot(x)"}); } /* public void testSimpleSum() throws ParseException { valueTest("1+2",3); valueTest("2*6+3",15); valueTest("2*(6+3)",18); } public void testOperators() throws ParseException { // if(!Operator.OP_MULTIPLY.isDistributiveOver(Operator.OP_ADD)) // fail("* should be distrib over +"); // if(Operator.OP_MULTIPLY.isDistributiveOver(Operator.OP_DIVIDE)) // fail("* should not be distrib over /"); // if(Operator.OP_MULTIPLY.getPrecedence() > Operator.OP_ADD.getPrecedence()) // fail("* should have a lower precedence than +"); valueTest("T=1",1); valueTest("F=0",0); calcValue("a=F"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); } public void testSimp() throws ParseException { simplifyTest("2+3","5"); simplifyTest("2*3","6"); simplifyTest("2^3","8"); simplifyTest("3/2","1.5"); simplifyTest("2*3+4","10"); simplifyTest("2*(3+4)","14"); simplifyTest("0+x","x"); simplifyTest("x+0","x"); simplifyTest("0-x","0-x"); simplifyTest("x-0","x"); simplifyTest("0*x","0"); simplifyTest("x*0","0"); simplifyTest("1*x","x"); simplifyTest("x*1","x"); simplifyTest("-1*x","-x"); simplifyTest("x*-1","-x"); simplifyTest("-(-x)","x"); simplifyTest("-(-(-x))","-x"); simplifyTest("(-1)*(-1)*x","x"); simplifyTest("(-1)*(-1)*(-1)*x","-x"); simplifyTest("0/x","0"); simplifyTest("x/0","1/0"); simplifyTest("x^0","1"); simplifyTest("x^1","x"); simplifyTest("0^x","0"); simplifyTest("1^x","1"); // (a+b)+c simplifyTest("(2+3)+x","5+x"); simplifyTest("(2+x)+3","5+x"); simplifyTest("(x+2)+3","5+x"); // a+(b+c) simplifyTest("x+(2+3)","5+x"); simplifyTest("2+(x+3)","5+x"); simplifyTest("2+(3+x)","5+x"); // (a+b)-c simplifyTest("(2+3)-x","5-x"); simplifyTest("(2+x)-3","x-1"); simplifyTest("(x+2)-3","x-1"); // (a-b)+c simplifyTest("(2-3)+x","-1+x"); simplifyTest("(2-x)+3","5-x"); simplifyTest("(x-2)+3","1+x"); // a-(b+c) simplifyTest("x-(2+3)","x-5"); simplifyTest("2-(x+3)","-1-x"); simplifyTest("2-(3+x)","-1-x"); // a+(b-c) simplifyTest("x+(2-3)","x-1"); simplifyTest("2+(x-3)","-1+x"); simplifyTest("2+(3-x)","5-x"); // a-(b-c) simplifyTest("x-(2-3)","1+x"); simplifyTest("2-(x-3)","5-x"); simplifyTest("2-(3-x)","-1+x"); // (a-b)-c simplifyTest("(2-3)-x","-1-x"); simplifyTest("(2-x)-3","-1-x"); simplifyTest("(x-2)-3","x-5"); // (a*b)*c simplifyTest("(2*3)*x","6*x"); simplifyTest("(2*x)*3","6*x"); simplifyTest("(x*2)*3","6*x"); // a+(b+c) simplifyTest("x*(2*3)","6*x"); simplifyTest("2*(x*3)","6*x"); simplifyTest("2*(3*x)","6*x"); // (a+b)-c simplifyTest("(2*3)/x","6/x"); simplifyTest("(3*x)/2","1.5*x"); simplifyTest("(x*3)/2","1.5*x"); // (a-b)+c simplifyTest("(3/2)*x","1.5*x"); simplifyTest("(3/x)*2","6/x"); simplifyTest("(x/2)*3","1.5*x"); // a-(b+c) simplifyTest("x/(2*3)","x/6"); simplifyTest("3/(x*2)","1.5/x"); simplifyTest("3/(2*x)","1.5/x"); // a+(b-c) simplifyTest("x*(3/2)","1.5*x"); simplifyTest("3*(x/2)","1.5*x"); simplifyTest("3*(2/x)","6/x"); // a-(b-c) simplifyTest("x/(3/2)","x/1.5"); simplifyTest("2/(x/3)","6/x"); simplifyTest("3/(2/x)","1.5*x"); // (a-b)-c simplifyTest("(3/2)/x","1.5/x"); simplifyTest("(3/x)/2","1.5/x"); simplifyTest("(x/3)/2","x/6"); simplifyTest("x*(3+2)","5*x"); simplifyTest("3*(x+2)","6+3*x"); simplifyTest("3*(2+x)","6+3*x"); simplifyTest("(3+2)*x","5*x"); simplifyTest("(3+x)*2","6+2*x"); simplifyTest("(x+3)*2","6+x*2"); simplifyTest("x*(3-2)","x"); simplifyTest("3*(x-2)","-6+3*x"); simplifyTest("3*(2-x)","6-3*x"); simplifyTest("(3-2)*x","x"); simplifyTest("(3-x)*2","6-2*x"); simplifyTest("(x-3)*2","-6+2*x"); simplifyTest("3+(x/4)","3+x/4"); simplifyTest("2*(x/4)","0.5*x"); simplifyTest("(2*(3+(x/4)))","6+0.5*x"); simplifyTest("1+(2*(3+(x/4)))","7+0.5*x"); simplifyTest("((3+(x/4))*2)+1","7+0.5*x"); } public void testComplex() throws Exception { double tol = 0.00000001; complexValueTest("z=complex(3,2)",new Complex(3,2),tol); complexValueTest("z*z-z",new Complex(2,10),tol); complexValueTest("z^3",new Complex(-9,46),tol); complexValueTest("(z*z-z)/z",new Complex(2,2),tol); complexValueTest("w=polar(2,pi/2)",new Complex(0,2),tol); } public void testIf() throws ParseException { valueTest("if(1,2,3)",2); valueTest("if(-1,2,3)",3); valueTest("if(0,2,3)",3); valueTest("if(1,2,3,4)",2); valueTest("if(-1,2,3,4)",3); valueTest("if(0,2,3,4)",4); valueTest("if(0>=0,2,3,4)",2); valueTest("x=3",3); valueTest("if(x==3,1,-1)",1); valueTest("if(x!=3,1,-1)",-1); valueTest("if(x>=3,1,-1)",1); valueTest("if(x>3,1,-1)",-1); valueTest("if(x<=3,1,-1)",1); valueTest("if(x<3,1,-1)",-1); } public void testAssign() throws ParseException { valueTest("x=3",3); valueTest("y=3+4",7); valueTest("z=x+y",10); valueTest("a=b=c=z",10); valueTest("b",10); valueTest("d=f=a-b",0); } public void testDiff() throws ParseException { simplifyTest("diff(x^2,x)","2 x"); simplifyTest("diff(x^3,x)","3 x^2"); simplifyTest("diff(x,x)","1"); simplifyTest("diff(1,x)","0"); simplifyTest("diff(x^2+x+1,x)","2 x+1"); simplifyTest("diff((x+x^2)*(x+x^3),x)","(1+2*x)*(x+x^3)+(x+x^2)*(1+3*x^2)"); simplifyTest("diff((x+x^2)/(x+x^3),x)","((1+2*x)*(x+x^3)-(x+x^2)*(1+3*x^2))/((x+x^3)*(x+x^3))"); simplifyTest("diff(sin(x),x)","cos(x)"); simplifyTest("diff(-(x-5)^3,x)","-(3.0*(x-5.0)^2.0)"); simplifyTest("diff((x+1)^2,x)","2+2*x"); simplifyTest("diff((x+y)^2,x)","2*(x+y)"); simplifyTest("diff((x+x^2)^3,x)","3*(x+x^2)^2*(1+2*x)"); simplifyTest("diff(sin(x+1),x)","cos(x+1)"); simplifyTest("diff(sin(x+x^2),x)","cos(x+x^2)*(1+2*x)"); simplifyTest("diff(cos(x),x)","-sin(x)"); simplifyTest("diff(tan(x),x)","1/((cos(x))^2)"); simplifyTest("diff(sec(x),x)","sec(x)*tan(x)"); simplifyTest("diff(cosec(x),x)","-cosec(x) * cot(x)"); simplifyTest("diff(cot(x),x)","-(cosec(x))^2"); simplifyTest("diff(sec(x),x)","sec(x) * tan(x)"); simplifyTest("diff(cosec(x),x)","-cosec(x) * cot(x)"); simplifyTest("diff(cot(x),x)","-(cosec(x))^2"); simplifyTest("diff(asin(x),x)","1/(sqrt(1-x^2))"); simplifyTest("diff(acos(x),x)","-1/(sqrt(1-x^2))"); simplifyTest("diff(atan(x),x)","1/(1+x^2)"); simplifyTest("diff(sinh(x),x)","cosh(x)"); simplifyTest("diff(cosh(x),x)","sinh(x)"); simplifyTest("diff(tanh(x),x)","1-(tanh(x))^2"); simplifyTest("diff(asinh(x),x)","1/(sqrt(1+x^2))"); simplifyTest("diff(acosh(x),x)","1/(sqrt(x^2-1))"); simplifyTest("diff(atanh(x),x)","1/(1-x^2)"); simplifyTest("diff(sqrt(x),x)","1/(2 (sqrt(x)))"); simplifyTest("diff(exp(x),x)","exp(x)"); // simplifyTest("diff(pow(x,y),x)","y*(pow(x,y-1))"); // simplifyTest("diff(pow(x,y),y)","(ln(x)) (pow(x,y))"); simplifyTest("diff(ln(x),x)","1/x"); simplifyTest("diff(log(x),x)","(1/ln(10)) /x"); simplifyTest("diff(abs(x),x)","abs(x)/x"); simplifyTest("diff(angle(x,y),x)","y/(x^2+y^2)"); simplifyTest("diff(angle(x,y),y)","-x/(x^2+y^2)"); simplifyTest("diff(mod(x,y),x)","1"); simplifyTest("diff(mod(x,y),y)","0"); simplifyTest("diff(sum(x,x^2,x^3),x)","sum(1,2 x,3 x^2)"); // addDiffRule(new PassThroughDiffRule(this,"sum")); // addDiffRule(new PassThroughDiffRule(this,"re")); // addDiffRule(new PassThroughDiffRule(this,"im")); // addDiffRule(new PassThroughDiffRule(this,"rand")); // // MacroFunction complex = new MacroFunction("complex",2,"x+i*y",xjep); // xjep.addFunction("complex",complex); // addDiffRule(new MacroFunctionDiffRules(this,complex)); // // addDiffRule(new PassThroughDiffRule(this,"\"<\"",new Comparative(0))); // addDiffRule(new PassThroughDiffRule(this,"\">\"",new Comparative(1))); // addDiffRule(new PassThroughDiffRule(this,"\"<=\"",new Comparative(2))); // addDiffRule(new PassThroughDiffRule(this,"\">=\"",new Comparative(3))); // addDiffRule(new PassThroughDiffRule(this,"\"!=\"",new Comparative(4))); // addDiffRule(new PassThroughDiffRule(this,"\"==\"",new Comparative(5))); } public void myAssertEquals(String msg,String actual,String expected) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \""+actual+" should be "+expected+"\""); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is \""+actual+"\""); } public void testAssignDiff() throws ParseException { simplifyTestString("y=x^5","y=x^5.0"); simplifyTestString("z=diff(y,x)","z=5.0*x^4.0"); Node n1 = ((DSymbolTable) j.getSymbolTable()).getPartialDeriv("y",new String[]{"x"}).getEquation(); myAssertEquals("dy/dx","5.0*x^4.0",j.toString(n1)); simplifyTestString("w=diff(z,x)","w=20.0*x^3.0"); Node n2 = ((DSymbolTable) j.getSymbolTable()).getPartialDeriv("y",new String[]{"x","x"}).getEquation(); myAssertEquals("d^2y/dxdx","20.0*x^3.0",j.toString(n2)); j.getSymbolTable().clearValues(); valueTest("x=2",2); valueTest("y",32); // x^5 valueTest("z",80); // 5 x^4 valueTest("w",160); // 20 x^3 } public void testMatrix() throws ParseException { j.getSymbolTable().clearValues(); valueTest("x=2",2); valueTest("y=[x^3,x^2,x]","[8.0,4.0,2.0]"); valueTest("z=diff(y,x)","[12.0,4.0,1.0]"); valueTest("3*y","[24.0,12.0,6.0]"); valueTest("y*4","[32.0,16.0,8.0]"); valueTest("y*z","[[96.0,32.0,8.0],[48.0,16.0,4.0],[24.0,8.0,2.0]]"); valueTest("z*y","[[96.0,48.0,24.0],[32.0,16.0,8.0],[8.0,4.0,2.0]]"); valueTest("w=y^z","[-4.0,16.0,-16.0]"); simplifyTestString("diff(w,x)","[3.0*x^2.0,2.0*x,1.0]^z+y^[6.0*x,2.0,0.0]"); simplifyTestString("diff(y . z,x)","[3.0*x^2.0,2.0*x,1.0].z+y.[6.0*x,2.0,0.0]"); valueTest("w.y",0.0); valueTest("w.z",0.0); valueTest("sqrt(w . z)",0.0); valueTest("sqrt([3,4].[3,4])",5.0); // tests result is unwrapped from scaler valueTest("y+z","[20.0,8.0,3.0]"); valueTest("y-z","[-4.0,0.0,1.0]"); j.getSymbolTable().clearValues(); // the following two tests insure that ^ is printed correctly simplifyTestString("y^z","y^z"); simplifyTestString("[8.0,4.0,2.0]^[12.0,4.0,1.0]","[8.0,4.0,2.0]^[12.0,4.0,1.0]"); simplifyTestString("y=[cos(x),sin(x)]","y=[cos(x),sin(x)]"); simplifyTestString("z=diff(y,x)","z=[-sin(x),cos(x)]"); valueTest("y.y",1.0); valueTest("y.z",0.0); valueTest("z.z",1.0); j.getSymbolTable().clearValues(); valueTest("x=[[1,2],[3,4]]","[[1.0,2.0],[3.0,4.0]]"); valueTest("y=[1,-1]","[1.0,-1.0]"); valueTest("x*y","[-1.0,-1.0]"); valueTest("y*x","[-2.0,-2.0]"); valueTest("x+[y,y]","[[2.0,1.0],[4.0,3.0]]"); valueTest("ele(y,1)","1.0"); // Value: 2.0 valueTest("ele(y,2)","-1.0"); // Value: 2.0 valueTest("ele(x,[1,1])","1.0"); // Value: 2.0 valueTest("ele(x,[1,2])","2.0"); // Value: 2.0 valueTest("ele(x,[2,1])","3.0"); // Value: 2.0 valueTest("ele(x,[2,2])","4.0"); // Value: 2.0 } public void testBad() throws ParseException { if(SHOW_BAD) { simplifyTest("1&&(1||x)","1"); simplifyTest("diff(sgn(x),x)","0"); // sgn not implemented simplifyTest("diff(re(x+i y),x)","1"); // not smart enought to work out re(i) = 1 simplifyTest("diff(re(x+i y),y)","0"); simplifyTest("diff(im(x+i y),x)","0"); simplifyTest("diff(im(x+i y),y)","1"); simplifyTest("(x/2)*3","x*1.5"); } } */ } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/SJepTest.java0000644000000000000000000004354710615400352021606 0ustar rootrootpackage org.lsmp.djepJUnit; import junit.framework.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.lsmp.djep.xjep.*; import org.lsmp.djep.djep.*; import java.text.NumberFormat; import org.lsmp.djep.sjep.*; /* @author rich * Created on 19-Nov-2003 */ /** * @author Rich Morris * Created on 19-Nov-2003 */ public class SJepTest extends TestCase { DJep j; PolynomialCreator pc; public static final boolean SHOW_BAD=false; public SJepTest(String name) { super(name); } public static void main(String args[]) { // Create an instance of this class and analyse the file TestSuite suite= new TestSuite(SJepTest.class); // DJepTest jt = new DJepTest("DJepTest"); // jt.setUp(); suite.run(new TestResult()); } protected void setUp() { j = new DJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); j.addStandardDiffRules(); pc = new PolynomialCreator(j); } public static Test suite() { return new TestSuite(SJepTest.class); } public void myAssertEquals(String msg,String actual,String expected) { if(!actual.equals(expected)) System.out.println("Error \""+msg+"\" is \""+actual+" should be "+expected+"\""); assertEquals("<"+msg+">",expected,actual); System.out.println("Success: Value of \""+msg+"\" is \""+actual+"\""); } public void assertPolynomialEquals(String s1,String s2) throws ParseException { Node n1= j.parse(s1); PNodeI p1 = pc.createPoly(n1); PNodeI e1 = p1.expand(); Node n2 = j.parse(s2); PNodeI p2 = pc.createPoly(n2); PNodeI e2 = p2.expand(); if(e1.equals(e2)){ System.out.println("Sucess: \""+s1+"\" equals \""+s2+"\""); }else{ System.out.println("Error: \""+s1+"\" is not equal to \""+s2+"\""); assertTrue("<"+s1+"> should be equal to <"+s2+"> it is not",false); } } /** just test JUnit working OK */ public void testGood() { assertEquals(1,1); } public void valueTest(String expr,double dub) throws Exception { valueTest(expr,new Double(dub)); } public void valueTest(String expr,Object expected) throws Exception { Node node = j.parse(expr); Node n2 = j.preprocess(node); Object res = j.evaluate(n2); assertEquals("<"+expr+">",expected,res); System.out.println("Success value of <"+expr+"> is "+res); } public void complexValueTest(String expr,Complex expected,double tol) throws Exception { Node node = j.parse(expr); Node n2 = j.preprocess(node); Object res = j.evaluate(n2); assertTrue("<"+expr+"> expected: <"+expected+"> but was <"+res+">", expected.equals((Complex) res,tol)); System.out.println("Success value of <"+expr+"> is "+res); } public Object calcValue(String expr) throws ParseException { Node node = j.parse(expr); Node n2 = j.preprocess(node); Object res = j.evaluate(n2); return res; } public void simplifyTest(String expr,String expected) throws ParseException { Node node = j.parse(expr); Node processed = j.preprocess(node); PNodeI poly = pc.createPoly(processed); String res = poly.toString(); Node node2 = j.parse(expected); Node processed2 = j.preprocess(node2); PNodeI poly2 = pc.createPoly(processed2); String res2 = poly2.toString(); if(!res2.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+res2+"\""); assertEquals("<"+expr+">",res2,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } public void simplifyTestString(String expr,String expected) throws ParseException { Node node = j.parse(expr); Node processed = j.preprocess(node); PNodeI poly = pc.createPoly(processed); String res = poly.toString(); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } public void expandTestString(String expr,String expected) throws ParseException { Node node = j.parse(expr); Node processed = j.preprocess(node); PNodeI poly = pc.createPoly(processed); PNodeI expand = poly.expand(); String res = expand.toString(); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); // System.out.print("Full Brackets:\t"); // j.pv.setFullBrackets(true); // j.pv.println(simp); // j.pv.setFullBrackets(false); } /* public Node parseProcSimpEval(String expr,Object expected) throws ParseException,Exception { Node node = j.parse(expr); Node processed = j.preprocess(node); Node simp = j.simplify(processed); Object res = j.evaluate(simp); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Sucess: Value of \""+expr+"\" is \""+res+"\""); return simp; } */ public void testSimpleSum() throws Exception { valueTest("1+2",3); valueTest("2*6+3",15); valueTest("2*(6+3)",18); } public void testOperators() throws Exception { OperatorSet opSet = j.getOperatorSet(); if(!((XOperator) opSet.getMultiply()).isDistributiveOver(opSet.getAdd())) fail("* should be distrib over +"); if(((XOperator) opSet.getMultiply()).isDistributiveOver(opSet.getDivide())) fail("* should not be distrib over /"); if(((XOperator) opSet.getMultiply()).getPrecedence() > ((XOperator) opSet.getAdd()).getPrecedence()) fail("* should have a lower precedence than +"); valueTest("T=1",1); valueTest("F=0",0); calcValue("a=F"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=F"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=F"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=F"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); calcValue("a=T"); calcValue("b=T"); calcValue("c=T"); valueTest("(a&&(b||c)) == ((a&&b)||(a&&c))",1); valueTest("(a||(b&&c)) == ((a||b)&&(a||c))",1); } public void testPrint() throws ParseException { simplifyTestString("(a+b)+c","a+b+c"); simplifyTestString("(a-b)+c","a-b+c"); simplifyTestString("(a+b)-c","a+b-c"); simplifyTestString("(a-b)-c","a-b-c"); simplifyTestString("a+(b+c)","a+b+c"); simplifyTestString("a-(b+c)","a-b-c"); // simplifyTestString("a+(b-c)","a+b-c"); simplifyTestString("a-(b-c)","a-b+c"); simplifyTestString("(a*b)*c","a*b*c"); simplifyTestString("(a/b)*c","a*c/b"); simplifyTestString("(a*b)/c","a*b/c"); simplifyTestString("(a/b)/c","a/(b*c)"); simplifyTestString("a*(b*c)","a*b*c"); simplifyTestString("a/(b*c)","a/(b*c)"); simplifyTestString("a*(b/c)","a*b/c"); simplifyTestString("a/(b/c)","a*c/b"); //simplifyTestString("a=(b=c)","a=b=c"); //simplifyTestString("(a=b)=c","a/(b/c)"); simplifyTestString("(a*b)+c","a*b+c"); simplifyTestString("(a+b)*c","(a+b)*c"); simplifyTestString("a*(b+c)","a*(b+c)"); simplifyTestString("a+(b*c)","a+b*c"); // simplifyTestString("(a||b)||c","a||b||c"); // simplifyTestString("(a&&b)||c","a&&b||c"); // simplifyTestString("(a||b)&&c","(a||b)&&c"); // simplifyTestString("(a&&b)&&c","a&&b&&c"); // simplifyTestString("a||(b||c)","a||b||c"); // simplifyTestString("a&&(b||c)","a&&(b||c)"); // simplifyTestString("a||(b&&c)","a||b&&c"); // simplifyTestString("a&&(b&&c)","a&&b&&c"); } public void testSimp() throws ParseException { simplifyTest("2+3","5"); simplifyTest("2*3","6"); simplifyTest("2^3","8"); simplifyTest("3/2","1.5"); simplifyTest("2*3+4","10"); simplifyTest("2*(3+4)","14"); simplifyTest("0+x","x"); simplifyTest("x+0","x"); simplifyTest("0-x","0-x"); simplifyTest("x-0","x"); simplifyTest("0*x","0"); simplifyTest("x*0","0"); simplifyTest("1*x","x"); simplifyTest("x*1","x"); simplifyTest("-1*x","-x"); simplifyTest("x*-1","-x"); simplifyTest("-(-x)","x"); simplifyTest("-(-(-x))","-x"); simplifyTest("(-1)*(-1)*x","x"); simplifyTest("(-1)*(-1)*(-1)*x","-x"); simplifyTest("0/x","0"); simplifyTest("x/0","1/0"); simplifyTest("x^0","1"); simplifyTest("x^1","x"); simplifyTest("0^x","0"); simplifyTest("1^x","1"); // (a+b)+c simplifyTest("(2+3)+x","5+x"); simplifyTest("(2+x)+3","5+x"); simplifyTest("(x+2)+3","5+x"); // a+(b+c) simplifyTest("x+(2+3)","5+x"); simplifyTest("2+(x+3)","5+x"); simplifyTest("2+(3+x)","5+x"); // (a+b)-c simplifyTest("(2+3)-x","5-x"); simplifyTest("(2+x)-3","x-1"); simplifyTest("(x+2)-3","x-1"); // (a-b)+c simplifyTest("(2-3)+x","-1+x"); simplifyTest("(2-x)+3","5-x"); simplifyTest("(x-2)+3","1+x"); // a-(b+c) simplifyTest("x-(2+3)","x-5"); simplifyTest("2-(x+3)","-1-x"); simplifyTest("2-(3+x)","-1-x"); // a+(b-c) simplifyTest("x+(2-3)","x-1"); simplifyTest("2+(x-3)","-1+x"); simplifyTest("2+(3-x)","5-x"); // a-(b-c) simplifyTest("x-(2-3)","1+x"); simplifyTest("2-(x-3)","5-x"); simplifyTest("2-(3-x)","-1+x"); // (a-b)-c simplifyTest("(2-3)-x","-1-x"); simplifyTest("(2-x)-3","-1-x"); simplifyTest("(x-2)-3","x-5"); // (a*b)*c simplifyTest("(2*3)*x","6*x"); simplifyTest("(2*x)*3","6*x"); simplifyTest("(x*2)*3","6*x"); // a+(b+c) simplifyTest("x*(2*3)","6*x"); simplifyTest("2*(x*3)","6*x"); simplifyTest("2*(3*x)","6*x"); // (a+b)-c simplifyTest("(2*3)/x","6/x"); simplifyTest("(3*x)/2","1.5*x"); simplifyTest("(x*3)/2","1.5*x"); // (a-b)+c simplifyTest("(3/2)*x","1.5*x"); simplifyTest("(3/x)*2","6/x"); simplifyTest("(x/2)*3","1.5*x"); // a-(b+c) simplifyTest("x/(2*3)","x/6"); simplifyTest("3/(x*2)","1.5/x"); simplifyTest("3/(2*x)","1.5/x"); // a+(b-c) simplifyTest("x*(3/2)","1.5*x"); simplifyTest("3*(x/2)","1.5*x"); simplifyTest("3*(2/x)","6/x"); // a-(b-c) simplifyTest("x/(3/2)","x/1.5"); simplifyTest("2/(x/3)","6/x"); simplifyTest("3/(2/x)","1.5*x"); // (a-b)-c simplifyTest("(3/2)/x","1.5/x"); simplifyTest("(3/x)/2","1.5/x"); simplifyTest("(x/3)/2","x/6"); simplifyTest("x*(3+2)","5*x"); // simplifyTest("3*(x+2)","6+3*x"); // simplifyTest("3*(2+x)","6+3*x"); // simplifyTest("(3+2)*x","5*x"); // simplifyTest("(3+x)*2","6+2*x"); // simplifyTest("(x+3)*2","6+x*2"); simplifyTest("x*(3-2)","x"); // simplifyTest("3*(x-2)","-6+3*x"); // simplifyTest("3*(2-x)","6-3*x"); simplifyTest("(3-2)*x","x"); // simplifyTest("(3-x)*2","6-2*x"); // simplifyTest("(x-3)*2","-6+2*x"); // simplifyTest("3+(x/4)","3+x/4"); // simplifyTest("2*(x/4)","0.5*x"); // simplifyTest("(2*(3+(x/4)))","6+0.5*x"); // simplifyTest("1+(2*(3+(x/4)))","7+0.5*x"); // simplifyTest("((3+(x/4))*2)+1","7+0.5*x"); simplifyTest("x*x","x^2"); simplifyTest("x*x*x","x^3"); simplifyTest("(x^3)*(x^4)","x^7"); simplifyTest("(x^4)/(x^3)","x"); simplifyTest("(x^3)/(x^4)","1/x"); simplifyTest("(x^2)/(x^4)","1/x^2"); simplifyTestString("1/x","1/x"); simplifyTestString("-1/x","-1/x"); simplifyTestString("2/x","2/x"); simplifyTestString("-2/x","-2/x"); simplifyTestString("(1+x)*(1+x)","(1+x)^2"); simplifyTestString("(1+x)/(1+x)","1"); simplifyTest("2*x+x","3*x"); simplifyTest("2*x+3*x","5*x"); simplifyTest("5*x-3*x","2*x"); simplifyTest("3*x-5*x","-2*x"); simplifyTest("3*x-x","2*x"); simplifyTest("(2*x+x)^3","27*x^3"); } public void testPolySimp() throws ParseException,Exception { Node n1 = j.parse("(1.0+2.0*x+x^2.0)*(1.0+2.0*x+x^2.0)"); pc.createPoly(n1); expandTestString("(a+b)*(c+d)","a*c+a*d+b*c+b*d"); expandTestString("a*c+a*d+b*c+b*d","a*c+a*d+b*c+b*d"); expandTestString("(a+b)*(a+b)","2*a*b+a^2+b^2"); expandTestString("(a-b)*(a-b)","-2*a*b+a^2+b^2"); expandTestString("(x+7.6)*(x+5.8832)*(x-55.12)","-2464.5430784-698.4816639999999*x-41.636799999999994*x^2+x^3"); simplifyTestString("(a+b)^0","1"); simplifyTestString("(a-b)^0","1"); simplifyTestString("(a+b)^1","a+b"); simplifyTestString("(a-b)^1","a-b"); expandTestString("(a+b)^2","2*a*b+a^2+b^2"); expandTestString("(a-b)^2","-2*a*b+a^2+b^2"); expandTestString("(a+b)^3","3*a*b^2+3*a^2*b+a^3+b^3"); expandTestString("(a-b)^3","3*a*b^2-3*a^2*b+a^3-b^3"); expandTestString("1+x+x^2+x*y+y^2","1+x+x*y+x^2+y^2"); expandTestString("(5*x+3*y)^2","30*x*y+25*x^2+9*y^2"); j.getPrintVisitor().setMaxLen(80); Node Q8node = j.parse("(xx^2+yy^2+zz^2+ww^2)^4"); Node Q8expand = pc.expand(Q8node); j.println(Q8expand); expandTestString("(xx^2+yy^2+zz^2+ww^2)^4", "24*ww^2*xx^2*yy^2*zz^2+12*ww^2*xx^2*yy^4+12*ww^2*xx^2*"+ "zz^4+12*ww^2*xx^4*yy^2+12*ww^2*xx^4*zz^2+4*ww^2*xx^6+"+ "12*ww^2*yy^2*zz^4+12*ww^2*yy^4*zz^2+4*ww^2*yy^6+4*"+ "ww^2*zz^6+12*ww^4*xx^2*yy^2+12*ww^4*xx^2*zz^2+6*ww^4*"+ "xx^4+12*ww^4*yy^2*zz^2+6*ww^4*yy^4+6*ww^4*zz^4+4*"+ "ww^6*xx^2+4*ww^6*yy^2+4*ww^6*zz^2+ww^8+12*xx^2*yy^2*"+ "zz^4+12*xx^2*yy^4*zz^2+4*xx^2*yy^6+4*xx^2*zz^6+12*"+ "xx^4*yy^2*zz^2+6*xx^4*yy^4+6*xx^4*zz^4+4*xx^6*yy^2+4*"+ "xx^6*zz^2+xx^8+4*yy^2*zz^6+6*yy^4*zz^4+4*yy^6*zz^2+"+ "yy^8+zz^8"); Node n = j.parse("ln(x+1)"); Node diff = j.differentiate(n,"x"); Node simp = pc.simplify(diff); myAssertEquals("diff(ln(x+1))",j.toString(simp),"1.0/(1.0+x)"); diff = j.differentiate(simp,"x"); j.println(diff); simp = pc.simplify(diff); myAssertEquals("d^2(ln(x+1))",j.toString(simp),"-1.0/(1.0+x)^2.0"); diff = j.differentiate(simp,"x"); j.println(diff); simp = pc.simplify(diff); myAssertEquals("d^3(ln(x+1))",j.toString(simp),"2.0/(1.0+x)^3.0"); diff = j.differentiate(simp,"x"); j.println(diff); simp = pc.simplify(diff); System.out.println("D^4\t"+j.toString(simp)); j.getPrintVisitor().setMaxLen(80); diff = j.differentiate(simp,"x"); // j.println(diff); simp = pc.simplify(diff); System.out.print("D^5\t"); j.println(simp); diff = j.differentiate(simp,"x"); // j.println(diff); simp = pc.simplify(diff); System.out.print("D^6\t"); j.println(simp); diff = j.differentiate(simp,"x"); // j.println(diff); simp = pc.simplify(diff); System.out.print("D^7\t"); j.println(simp); diff = j.differentiate(simp,"x"); // j.println(diff); simp = pc.simplify(diff); System.out.print("D^8\t"); j.println(simp); } public void testTotalOrder() throws ParseException,Exception { expandTestString("y+x","x+y"); expandTestString("x^2+x","x+x^2"); expandTestString("x^3+x^2","x^2+x^3"); expandTestString("x*y+x","x+x*y"); expandTestString("x^2+x*y","x*y+x^2"); expandTestString("x+1/x","1/x+x"); expandTestString("1/x^2+1/x","1/x^2+1/x"); simplifyTestString("y+x","x+y"); simplifyTestString("x^2+x","x+x^2"); simplifyTestString("x^3+x^2","x^2+x^3"); simplifyTestString("x*y+x","x+x*y"); simplifyTestString("x^2+x*y","x*y+x^2"); simplifyTestString("x+1/x","1/x+x"); simplifyTestString("1/x^2+1/x","1/x^2+1/x"); } public void testPolySimp2() throws ParseException,Exception { expandTestString("1+2*(1+x)","3+2*x"); expandTestString("6x+3y+4x+3(15x+7y)+40","40+55*x+24*y"); expandTestString("x*y+2*x","2*x+x*y"); expandTestString("(1+x+y)^2","1+2*x+2*x*y+x^2+2*y+y^2"); } public void testFormat() throws ParseException { NumberFormat format = NumberFormat.getInstance(); j.getPrintVisitor().setNumberFormat(format); format.setMaximumFractionDigits(3); format.setMinimumFractionDigits(0); String s1 = "[10,0,0.1,0.11,0.111,0.1111]"; String r1 = j.toString(j.parse(s1)); String s2 = "[0.9,0.99,0.999,0.9999]"; String r2 = j.toString(j.parse(s2)); this.myAssertEquals(s1,r1,"[10,0,0.1,0.11,0.111,0.111]"); this.myAssertEquals(s2,r2,"[0.9,0.99,0.999,1]"); //j.addComplex(); j.println(j.parse("[0,1,i,1+i]")); j.getPrintVisitor().setMode(PrintVisitor.COMPLEX_I,true); j.println(j.simplify(j.parse("(2+i)+(1+i)"))); j.parseExpression("(2+i)+(1+i)"); Complex c = j.getComplexValue(); System.out.println(c.toString(format,true)); } public void testSimpleEquals() throws ParseException { assertPolynomialEquals("a+b-(c+d)","(a+b)-c-d"); } public void testBad() throws ParseException { if(SHOW_BAD) { simplifyTest("1&&(1||x)","1"); simplifyTest("diff(sgn(x),x)","0"); // sgn not implemented simplifyTest("diff(re(x+i y),x)","1"); // not smart enought to work out re(i) = 1 simplifyTest("diff(re(x+i y),y)","0"); simplifyTest("diff(im(x+i y),x)","0"); simplifyTest("diff(im(x+i y),y)","1"); simplifyTest("(x/2)*3","x*1.5"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/lsmp/djepJUnit/XJepTest.java0000644000000000000000000004630710615400352021610 0ustar rootroot/* @author rich * Created on 17-Apr-2005 * * See LICENSE.txt for license information. */ package org.lsmp.djepJUnit; import java.text.NumberFormat; import java.util.Vector; import org.nfunk.jep.*; import org.nfunk.jep.type.Complex; import org.lsmp.djep.xjep.*; import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; /** * @author Rich Morris * Created on 17-Apr-2005 */ public class XJepTest extends JepTest { public XJepTest(String name) { super(name); } public static Test suite() { return new TestSuite(XJepTest.class); } public static void main(String[] args) { TestSuite suite= new TestSuite(XJepTest.class); suite.run(new TestResult()); } protected void setUp() { j = new XJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); j.setAllowAssignment(true); j.setAllowUndeclared(true); j.setImplicitMul(true); } public String parsePreprocSimp(String expr) throws ParseException { XJep xj = (XJep) j; Node node = xj.parse(expr); Node matEqn = xj.preprocess(node); Node simp = xj.simplify(matEqn); String res = xj.toString(simp); return res; } public void simplifyTestString(String expr,String expected) throws ParseException { XJep xj = (XJep) j; Node node = xj.parse(expr); Node processed = xj.preprocess(node); Node simp = xj.simplify(processed); String res = xj.toString(simp); if(!expected.equals(res)) System.out.println("Error: Value of \""+expr+"\" is \""+res+"\" should be \""+expected+"\""); assertEquals("<"+expr+">",expected,res); System.out.println("Success: Value of \""+expr+"\" is \""+res+"\""); } public void simplifyTest(String expr,String expected) throws ParseException { XJep xj = (XJep) j; Node node2 = xj.parse(expected); Node processed2 = xj.preprocess(node2); Node simp2 = xj.simplify(processed2); String res2 = xj.toString(simp2); simplifyTestString(expr,res2); } public Node parseProcSimpEval(String expr,Object expected) throws ParseException,Exception { XJep xj = (XJep) j; Node node = xj.parse(expr); Node processed = xj.preprocess(node); Node simp = xj.simplify(processed); Object res = xj.evaluate(simp); myAssertEquals(expr,expected,res); return simp; } public void testLogical() throws Exception { super.testLogical(); OperatorSet opSet = j.getOperatorSet(); if(!((XOperator) opSet.getMultiply()).isDistributiveOver(opSet.getAdd())) fail("* should be distrib over +"); if(((XOperator) opSet.getMultiply()).isDistributiveOver(opSet.getDivide())) fail("* should not be distrib over /"); if(((XOperator) opSet.getMultiply()).getPrecedence() > ((XOperator) opSet.getAdd()).getPrecedence()) fail("* should have a lower precedence than +"); } public void testPrint() throws ParseException { simplifyTestString("(a+b)+c","a+b+c"); simplifyTestString("(a-b)+c","a-b+c"); simplifyTestString("(a+b)-c","a+b-c"); simplifyTestString("(a-b)-c","a-b-c"); simplifyTestString("a+(b+c)","a+b+c"); simplifyTestString("a-(b+c)","a-(b+c)"); simplifyTestString("a+(b-c)","a+b-c"); simplifyTestString("a-(b-c)","a-(b-c)"); simplifyTestString("(a*b)*c","a*b*c"); simplifyTestString("(a/b)*c","(a/b)*c"); simplifyTestString("(a*b)/c","a*b/c"); simplifyTestString("(a/b)/c","(a/b)/c"); simplifyTestString("a*(b*c)","a*b*c"); simplifyTestString("a/(b*c)","a/(b*c)"); simplifyTestString("a*(b/c)","a*b/c"); simplifyTestString("a/(b/c)","a/(b/c)"); simplifyTestString("a=(b=c)","a=b=c"); //simplifyTestString("(a=b)=c","a/(b/c)"); simplifyTestString("(a*b)+c","a*b+c"); simplifyTestString("(a+b)*c","(a+b)*c"); simplifyTestString("a*(b+c)","a*(b+c)"); simplifyTestString("a+(b*c)","a+b*c"); simplifyTestString("(a||b)||c","a||b||c"); simplifyTestString("(a&&b)||c","a&&b||c"); simplifyTestString("(a||b)&&c","(a||b)&&c"); simplifyTestString("(a&&b)&&c","a&&b&&c"); simplifyTestString("a||(b||c)","a||b||c"); simplifyTestString("a&&(b||c)","a&&(b||c)"); simplifyTestString("a||(b&&c)","a||b&&c"); simplifyTestString("a&&(b&&c)","a&&b&&c"); } public void testSimp() throws ParseException { simplifyTest("2+3","5"); simplifyTest("2*3","6"); simplifyTest("2^3","8"); simplifyTest("3/2","1.5"); simplifyTest("2*3+4","10"); simplifyTest("2*(3+4)","14"); simplifyTest("0+x","x"); simplifyTest("x+0","x"); simplifyTest("0-x","0-x"); simplifyTest("x-0","x"); simplifyTest("0*x","0"); simplifyTest("x*0","0"); simplifyTest("1*x","x"); simplifyTest("x*1","x"); simplifyTest("-1*x","-x"); simplifyTest("x*-1","-x"); simplifyTest("-(-x)","x"); simplifyTest("-(-(-x))","-x"); simplifyTest("(-1)*(-1)*x","x"); simplifyTest("(-1)*(-1)*(-1)*x","-x"); simplifyTest("0/x","0"); simplifyTest("x/0","1/0"); simplifyTest("x^0","1"); simplifyTest("x^1","x"); simplifyTest("0^x","0"); simplifyTest("1^x","1"); // (a+b)+c simplifyTest("(2+3)+x","5+x"); simplifyTest("(2+x)+3","5+x"); simplifyTest("(x+2)+3","5+x"); // a+(b+c) simplifyTest("x+(2+3)","5+x"); simplifyTest("2+(x+3)","5+x"); simplifyTest("2+(3+x)","5+x"); // (a+b)-c simplifyTest("(2+3)-x","5-x"); simplifyTest("(2+x)-3","x-1"); simplifyTest("(x+2)-3","x-1"); // (a-b)+c simplifyTest("(2-3)+x","-1+x"); simplifyTest("(2-x)+3","5-x"); simplifyTest("(x-2)+3","1+x"); // a-(b+c) simplifyTest("x-(2+3)","x-5"); simplifyTest("2-(x+3)","-1-x"); simplifyTest("2-(3+x)","-1-x"); // a+(b-c) simplifyTest("x+(2-3)","x-1"); simplifyTest("2+(x-3)","-1+x"); simplifyTest("2+(3-x)","5-x"); // a-(b-c) simplifyTest("x-(2-3)","1+x"); simplifyTest("2-(x-3)","5-x"); simplifyTest("2-(3-x)","-1+x"); // (a-b)-c simplifyTest("(2-3)-x","-1-x"); simplifyTest("(2-x)-3","-1-x"); simplifyTest("(x-2)-3","x-5"); // (a*b)*c simplifyTest("(2*3)*x","6*x"); simplifyTest("(2*x)*3","6*x"); simplifyTest("(x*2)*3","6*x"); // a+(b+c) simplifyTest("x*(2*3)","6*x"); simplifyTest("2*(x*3)","6*x"); simplifyTest("2*(3*x)","6*x"); // (a+b)-c simplifyTest("(2*3)/x","6/x"); simplifyTest("(3*x)/2","1.5*x"); simplifyTest("(x*3)/2","1.5*x"); // (a-b)+c simplifyTest("(3/2)*x","1.5*x"); simplifyTest("(3/x)*2","6/x"); simplifyTest("(x/2)*3","1.5*x"); // a-(b+c) simplifyTest("x/(2*3)","x/6"); simplifyTest("3/(x*2)","1.5/x"); simplifyTest("3/(2*x)","1.5/x"); // a+(b-c) simplifyTest("x*(3/2)","1.5*x"); simplifyTest("3*(x/2)","1.5*x"); simplifyTest("3*(2/x)","6/x"); // a-(b-c) simplifyTest("x/(3/2)","x/1.5"); simplifyTest("2/(x/3)","6/x"); simplifyTest("3/(2/x)","1.5*x"); // (a-b)-c simplifyTest("(3/2)/x","1.5/x"); simplifyTest("(3/x)/2","1.5/x"); simplifyTest("(x/3)/2","x/6"); simplifyTest("x*(3+2)","5*x"); simplifyTest("3*(x+2)","6+3*x"); simplifyTest("3*(2+x)","6+3*x"); simplifyTest("(3+2)*x","5*x"); simplifyTest("(3+x)*2","6+2*x"); simplifyTest("(x+3)*2","6+x*2"); simplifyTest("x*(3-2)","x"); simplifyTest("3*(x-2)","-6+3*x"); simplifyTest("3*(2-x)","6-3*x"); simplifyTest("(3-2)*x","x"); simplifyTest("(3-x)*2","6-2*x"); simplifyTest("(x-3)*2","-6+2*x"); simplifyTest("3+(x/4)","3+x/4"); simplifyTest("2*(x/4)","0.5*x"); simplifyTest("(2*(3+(x/4)))","6+0.5*x"); simplifyTest("1+(2*(3+(x/4)))","7+0.5*x"); simplifyTest("((3+(x/4))*2)+1","7+0.5*x"); simplifyTest("(x/2)*3","x*1.5"); } public void testMacroFun() throws Exception { j.addFunction("zap",new MacroFunction("zap",1,"x*(x-1)/2",(XJep) j)); valueTest("zap(10)",45); } public void testVariableReuse() throws Exception { XJep xj = (XJep) j; System.out.println("\nTesting variable reuse"); parseProcSimpEval("x=3",new Double(3)); Node node13 = parseProcSimpEval("y=x^2",new Double(9)); Node node15 = parseProcSimpEval("z=y+x",new Double(12)); j.setVarValue("x",new Double(4)); System.out.println("j.setVarValue(\"x\",new Double(4));"); System.out.println("j.getVarValue(y): "+j.getVarValue("y")); myAssertEquals("eval y eqn","16.0",j.evaluate(node13).toString()); System.out.println("j.getVarValue(y): "+j.getVarValue("y")); myAssertEquals("eval z eqn","20.0",j.evaluate(node15).toString()); // j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(5)); System.out.println("j.setVarValue(\"x\",new Double(5));"); myAssertEquals("j.findVarValue(y)","25.0",xj.calcVarValue("y").toString()); myAssertEquals("j.findVarValue(z)","30.0",xj.calcVarValue("z").toString()); j.getSymbolTable().clearValues(); j.setVarValue("x",new Double(6)); System.out.println("j.setVarValue(\"x\",new Double(6));"); myAssertEquals("j.findVarValue(z)","42.0",xj.calcVarValue("z").toString()); myAssertEquals("j.findVarValue(y)","36.0",xj.calcVarValue("y").toString()); parseProcSimpEval("x=7",new Double(7)); myAssertEquals("eval y eqn","49.0",j.evaluate(node13).toString()); myAssertEquals("eval z eqn","56.0",j.evaluate(node15).toString()); } public void testReentrant() throws ParseException,Exception { XJep xj = (XJep) j; xj.restartParser("x=1; // semi-colon; in comment\n y=2; z=x+y;"); Node node = xj.continueParsing(); myAssertEquals("x=1; ...","1.0",calcValue(node).toString()); node = xj.continueParsing(); myAssertEquals("..., y=2; ...","2.0",calcValue(node).toString()); node = xj.continueParsing(); myAssertEquals("..., z=x+y;","3.0",calcValue(node).toString()); node = xj.continueParsing(); assertNull("empty string ",node); } public void testFormat() throws ParseException { XJep xj = (XJep) j; NumberFormat format = NumberFormat.getInstance(); xj.getPrintVisitor().setNumberFormat(format); format.setMaximumFractionDigits(3); format.setMinimumFractionDigits(0); String s1 = "[10,0,0.1,0.11,0.111,0.1111]"; String r1 = xj.toString(j.parse(s1)); String s2 = "[0.9,0.99,0.999,0.9999]"; String r2 = xj.toString(j.parse(s2)); this.myAssertEquals(s1,r1,"[10,0,0.1,0.11,0.111,0.111]"); this.myAssertEquals(s2,r2,"[0.9,0.99,0.999,1]"); //j.addComplex(); xj.println(j.parse("[0,1,i,1+i]")); xj.getPrintVisitor().setMode(PrintVisitor.COMPLEX_I,true); xj.println(xj.simplify(j.parse("(2+i)+(1+i)"))); //j.parseExpression("(2+i)+(1+i)"); Complex c = (Complex) calcValue("(2+i)+(1+i)"); System.out.println(c.toString(format,true)); } public void testVarInEqn() throws Exception { XJep xj = (XJep) j; Node n1 = j.parse("a+b+c+d"); Vector v = xj.getVarsInEquation(n1,new Vector()); assertTrue("Does not contain a",v.contains(j.getSymbolTable().getVar("a"))); assertTrue("Does not contain b",v.contains(j.getSymbolTable().getVar("b"))); assertTrue("Does not contain c",v.contains(j.getSymbolTable().getVar("c"))); assertTrue("Does not contain d",v.contains(j.getSymbolTable().getVar("d"))); xj.preprocess(j.parse("x=a+b t")); xj.preprocess(j.parse("y=c+d t")); xj.preprocess(j.parse("f=x*y")); xj.preprocess(j.parse("g=x+y")); Node n2 = xj.preprocess(j.parse("f+g")); Vector v2 = xj.recursiveGetVarsInEquation(n2,new Vector()); Vector v3 = new Vector(); v3.add(j.getVar("a")); v3.add(j.getVar("b")); v3.add(j.getVar("t")); v3.add(j.getVar("x")); v3.add(j.getVar("c")); v3.add(j.getVar("d")); v3.add(j.getVar("y")); v3.add(j.getVar("f")); v3.add(j.getVar("g")); System.out.println(v2.toString()); assertEquals("Bad element seq",v3,v2); } public void testUndecVar() throws ParseException { j.setAllowUndeclared(true); Node node1 = ((XJep) j).parse("zap * biff * gosh"); ((XJep) j).preprocess(node1); } public void testSum() throws Exception { valueTest("Sum(x,x,1,10)",55); valueTest("Sum(x^2,x,1,5)",55); valueTest("Product(x,x,1,5)",120); valueTest("Min(x^2,x,1,5)",1); valueTest("Max(x^2,x,1,5)",25); valueTest("MinArg(x^2,x,1,5)",1); valueTest("MaxArg(x^2,x,1,5)",5); } public void testHex() throws Exception { valueTest("toHex(0)","0x0"); valueTest("toHex(0,1)","0x0.0"); valueTest("toHex(0,2)","0x0.00"); valueTest("toHex(1)","0x1"); valueTest("toHex(1,1)","0x1.0"); valueTest("toHex(1,2)","0x1.00"); valueTest("toHex(-1)","-0x1"); valueTest("toHex(-1,1)","-0x1.0"); valueTest("toHex(-1,2)","-0x1.00"); valueTest("toHex(7)","0x7"); valueTest("toHex(7,1)","0x7.0"); valueTest("toHex(7,2)","0x7.00"); valueTest("toHex(-7)","-0x7"); valueTest("toHex(-7,1)","-0x7.0"); valueTest("toHex(-7,2)","-0x7.00"); valueTest("toHex(8)","0x8"); valueTest("toHex(8,1)","0x8.0"); valueTest("toHex(8,2)","0x8.00"); valueTest("toHex(-8)","-0x8"); valueTest("toHex(-8,1)","-0x8.0"); valueTest("toHex(-8,2)","-0x8.00"); valueTest("toHex(10)","0xa"); valueTest("toHex(10,1)","0xa.0"); valueTest("toHex(10,2)","0xa.00"); valueTest("toHex(-10)","-0xa"); valueTest("toHex(-10,1)","-0xa.0"); valueTest("toHex(-10,2)","-0xa.00"); valueTest("toHex(15)","0xf"); valueTest("toHex(15,1)","0xf.0"); valueTest("toHex(15,2)","0xf.00"); valueTest("toHex(-15)","-0xf"); valueTest("toHex(-15,1)","-0xf.0"); valueTest("toHex(-15,2)","-0xf.00"); valueTest("toHex(16)","0x10"); valueTest("toHex(16,1)","0x10.0"); valueTest("toHex(16,2)","0x10.00"); valueTest("toHex(-16)","-0x10"); valueTest("toHex(-16,1)","-0x10.0"); valueTest("toHex(-16,2)","-0x10.00"); valueTest("toHex(17)","0x11"); valueTest("toHex(17,1)","0x11.0"); valueTest("toHex(17,2)","0x11.00"); valueTest("toHex(-17)","-0x11"); valueTest("toHex(-17,1)","-0x11.0"); valueTest("toHex(-17,2)","-0x11.00"); valueTest("toHex(256)","0x100"); valueTest("toHex(256,1)","0x100.0"); valueTest("toHex(256,2)","0x100.00"); valueTest("toHex(-256)","-0x100"); valueTest("toHex(-256,1)","-0x100.0"); valueTest("toHex(-256,2)","-0x100.00"); valueTest("toHex(1/16)","0x0"); valueTest("toHex(1/16,1)","0x0.1"); valueTest("toHex(1/16,2)","0x0.10"); valueTest("toHex(-1/16)","-0x0"); valueTest("toHex(-1/16,1)","-0x0.1"); valueTest("toHex(-1/16,2)","-0x0.10"); valueTest("toHex(7/16)","0x0"); valueTest("toHex(7/16,1)","0x0.7"); valueTest("toHex(7/16,2)","0x0.70"); valueTest("toHex(-7/16)","-0x0"); valueTest("toHex(-7/16,1)","-0x0.7"); valueTest("toHex(-7/16,2)","-0x0.70"); valueTest("toHex(8/16)","0x1"); valueTest("toHex(8/16,1)","0x0.8"); valueTest("toHex(8/16,2)","0x0.80"); valueTest("toHex(-8/16)","-0x1"); valueTest("toHex(-8/16,1)","-0x0.8"); valueTest("toHex(-8/16,2)","-0x0.80"); valueTest("toHex(10/16)","0x1"); valueTest("toHex(10/16,1)","0x0.a"); valueTest("toHex(10/16,2)","0x0.a0"); valueTest("toHex(-10/16)","-0x1"); valueTest("toHex(-10/16,1)","-0x0.a"); valueTest("toHex(-10/16,2)","-0x0.a0"); valueTest("toHex(15/16)","0x1"); valueTest("toHex(15/16,1)","0x0.f"); valueTest("toHex(15/16,2)","0x0.f0"); valueTest("toHex(-15/16)","-0x1"); valueTest("toHex(-15/16,1)","-0x0.f"); valueTest("toHex(-15/16,2)","-0x0.f0"); valueTest("toHex(17/16)","0x1"); valueTest("toHex(17/16,1)","0x1.1"); valueTest("toHex(17/16,2)","0x1.10"); valueTest("toHex(-17/16)","-0x1"); valueTest("toHex(-17/16,1)","-0x1.1"); valueTest("toHex(-17/16,2)","-0x1.10"); valueTest("toHex(31/16)","0x2"); valueTest("toHex(31/16,1)","0x1.f"); valueTest("toHex(31/16,2)","0x1.f0"); valueTest("toHex(-31/16)","-0x2"); valueTest("toHex(-31/16,1)","-0x1.f"); valueTest("toHex(-31/16,2)","-0x1.f0"); valueTest("toHex(1/256)","0x0"); valueTest("toHex(1/256,1)","0x0.0"); valueTest("toHex(1/256,2)","0x0.01"); valueTest("toHex(-1/256)","-0x0"); valueTest("toHex(-1/256,1)","-0x0.0"); valueTest("toHex(-1/256,2)","-0x0.01"); valueTest("toHex(15/256)","0x0"); valueTest("toHex(15/256,1)","0x0.1"); valueTest("toHex(15/256,2)","0x0.0f"); valueTest("toHex(-15/256)","-0x0"); valueTest("toHex(-15/256,1)","-0x0.1"); valueTest("toHex(-15/256,2)","-0x0.0f"); valueTest("toHex(17/256)","0x0"); valueTest("toHex(17/256,1)","0x0.1"); valueTest("toHex(17/256,2)","0x0.11"); valueTest("toHex(-17/256)","-0x0"); valueTest("toHex(-17/256,1)","-0x0.1"); valueTest("toHex(-17/256,2)","-0x0.11"); valueTest("toHex(127/256)","0x0"); valueTest("toHex(127/256,1)","0x0.8"); valueTest("toHex(127/256,2)","0x0.7f"); valueTest("toHex(-127/256)","-0x0"); valueTest("toHex(-127/256,1)","-0x0.8"); valueTest("toHex(-127/256,2)","-0x0.7f"); valueTest("toHex(128/256)","0x1"); valueTest("toHex(128/256,1)","0x0.8"); valueTest("toHex(128/256,2)","0x0.80"); valueTest("toHex(-128/256)","-0x1"); valueTest("toHex(-128/256,1)","-0x0.8"); valueTest("toHex(-128/256,2)","-0x0.80"); valueTest("toHex(240/256)","0x1"); valueTest("toHex(240/256,1)","0x0.f"); valueTest("toHex(240/256,2)","0x0.f0"); valueTest("toHex(-240/256)","-0x1"); valueTest("toHex(-240/256,1)","-0x0.f"); valueTest("toHex(-240/256,2)","-0x0.f0"); valueTest("toHex(248/256)","0x1"); valueTest("toHex(248/256,1)","0x1.0"); valueTest("toHex(248/256,2)","0x0.f8"); valueTest("toHex(-248/256)","-0x1"); valueTest("toHex(-248/256,1)","-0x1.0"); valueTest("toHex(-248/256,2)","-0x0.f8"); valueTest("toHex(1/4096)","0x0"); valueTest("toHex(1/4096,1)","0x0.0"); valueTest("toHex(1/4096,2)","0x0.00"); valueTest("toHex(1/4096,3)","0x0.001"); valueTest("toHex(1/4096,4)","0x0.0010"); valueTest("toHex(1+1/4096)","0x1"); valueTest("toHex(1+1/4096,1)","0x1.0"); valueTest("toHex(1+1/4096,2)","0x1.00"); valueTest("toHex(1+1/4096,3)","0x1.001"); valueTest("toHex(1+1/4096,4)","0x1.0010"); XJep xj = (XJep) j; BaseFormat bf = new BaseFormat(16,"0x"); bf.setMaximumFractionDigits(0); xj.getPrintVisitor().setNumberFormat(bf); String st = "10 x+15 x^2 - 16 x^3 + 32 x^4 - 256 x^5"; Node n = xj.parse(st); String res = xj.toString(n); myAssertEquals(st,"0xa*x+0xf*x^0x2-0x10*x^0x3+0x20*x^0x4-0x100*x^0x5",res); } public void testDefine() throws Exception { XJep xj = (XJep) j; //Node n = xj.parse("Define(\"sumToX\",1,\"x*(x+1)/2\")"); //xj.preprocess(n); //valueTest("sumToX(4)",10); } public void testBad() throws Exception { if(SHOW_BAD) { valueTest("recurse = recurse+1",null); simplifyTest("1&&(1||x)","1"); simplifyTest("diff(sgn(x),x)","0"); // sgn not implemented simplifyTest("diff(re(x+i y),x)","1"); // not smart enough to work out re(i) = 1 simplifyTest("diff(re(x+i y),y)","0"); simplifyTest("diff(im(x+i y),x)","0"); simplifyTest("diff(im(x+i y),y)","1"); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/0000755000000000000000000000000010615400352015477 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/0000755000000000000000000000000010615400352017653 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/package.html0000644000000000000000000000011210615400352022126 0ustar rootroot Testing classes using the junit unit testing component. jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/AllTests.java0000644000000000000000000000152110615400352022250 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jeptesting; import junit.framework.*; public class AllTests { public static void main (String[] args) { junit.textui.TestRunner.run(suite()); } public static Test suite() { TestSuite suite = new TestSuite("All JUnit Tests"); suite.addTest(new JEPTest("testParseExpression")); suite.addTestSuite(LogarithmTest.class); suite.addTestSuite(NaturalLogarithmTest.class); suite.addTestSuite(BugsTest.class); suite.addTestSuite(ComplexTest.class); return suite; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/LogarithmTest.java0000644000000000000000000000160310615400352023304 0ustar rootrootpackage org.nfunk.jeptesting; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.Logarithm; import junit.framework.Assert; import junit.framework.TestCase; public class LogarithmTest extends TestCase { public LogarithmTest(String name) { super(name); } /* * Test method for 'org.nfunk.jep.function.Logarithm.run(Stack)' * Tests the return value of log(NaN). This is a test for bug #1177557 */ public void testLogarithm() { Logarithm logFunction = new Logarithm(); java.util.Stack stack = new java.util.Stack(); stack.push(new Double(Double.NaN)); try { logFunction.run(stack); } catch (ParseException e) { Assert.fail(); } Object returnValue = stack.pop(); if (returnValue instanceof Double) { Assert.assertTrue(Double.isNaN(((Double)returnValue).doubleValue())); } else { Assert.fail(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/NaturalLogarithmTest.java0000644000000000000000000000165510615400352024642 0ustar rootrootpackage org.nfunk.jeptesting; import org.nfunk.jep.ParseException; import org.nfunk.jep.function.NaturalLogarithm; import junit.framework.Assert; import junit.framework.TestCase; public class NaturalLogarithmTest extends TestCase { public NaturalLogarithmTest(String name) { super(name); } /* * Test method for 'org.nfunk.jep.function.Logarithm.run(Stack)' * Tests the return value of log(NaN). This is a test for bug #1177557 */ public void testNaturalLogarithm() { NaturalLogarithm logFunction = new NaturalLogarithm(); java.util.Stack stack = new java.util.Stack(); stack.push(new Double(Double.NaN)); try { logFunction.run(stack); } catch (ParseException e) { Assert.fail(); } Object returnValue = stack.pop(); if (returnValue instanceof Double) { Assert.assertTrue(Double.isNaN(((Double)returnValue).doubleValue())); } else { Assert.fail(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/JEPTest.java0000644000000000000000000001715410615400352022004 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jeptesting; import java.io.*; import junit.framework.Assert; import junit.framework.TestCase; import org.nfunk.jep.*; import org.nfunk.jep.type.Complex; /** * This class is designed for testing the validity of JEP evaluations. * Expressions from a text file are evaluated with JEP in pairs of two, and * the results are compared. If they do not match, the two expressions are * printed to standard output.

    * Take for example an input text file containing the two lines *

    1+2
     *3.
    * The expressions '1+2' and '3' are evaluated with JEP and the results compared. */ public class JEPTest extends TestCase { /** The parser */ JEP myParser; /** Current line position */ int lineCount; /** * Constructor * public JEPTester() { // Set up the parser myParser = new JEP(); myParser.setImplicitMul(true); myParser.addStandardFunctions(); myParser.addStandardConstants(); myParser.addComplex(); myParser.setTraverse(false); lineCount = 0; }*/ /** * Creates a new JEPTest instance */ public JEPTest(String name) { super(name); } /** * Sets up the parser. */ public void setUp() { // Set up the parser myParser = new JEP(); myParser.setImplicitMul(true); myParser.addStandardFunctions(); myParser.addStandardConstants(); myParser.addComplex(); myParser.setTraverse(false); lineCount = 0; } /** * Runs the test. */ public void runTest() { String fileName = "JEPTestExpressions.txt"; testWithFile(fileName); testGetValue(); testGetComplexValue(); } /** * The main method checks the arguments and creates an instance * and calls it's run method. */ public static void main(String args[]) { String fileName; // get filename from argument, or use default if (args!=null && args.length>0) { fileName = args[0]; } else { fileName = "JEPTestExpressions.txt"; println("Using default input file: " + fileName); println("Start with \"java org.nfunk.jepexamples."+ "JEPTest \" to load a different input file."); } // Create an instance of this class and analyse the file JEPTest jt = new JEPTest("JEP Test"); jt.setUp(); jt.testWithFile(fileName); } public void testWithFile() { testWithFile("JEPTestExpressions.txt"); } /** * Loads the file specified in fileName. Evaluates the expressions listed * in it and compares the expressions with the results. */ public void testWithFile(String fileName) { BufferedReader reader; Object v1, v2; boolean hasError = false; // Load the input file try { reader = new BufferedReader(new FileReader(fileName)); } catch (Exception e) { Assert.assertTrue(false); println("File \""+fileName+"\" not found"); return; } // reset the line count lineCount = 0; // cycle through the expressions in pairs of two println("Evaluating and comparing expressions..."); while (true) { // get values of a pair of two lines try { v1 = parseNextLine(reader); //returns null when end of file is reached v2 = parseNextLine(reader); } catch (Exception e) { println(e.getMessage()); hasError = true; break; } // v1 or v2 is null when end of file is reached if (v1 == null || v2 == null) { println("Reached end of file."); break; } // compare the results if (!equal(v1, v2)) { hasError = true; print("Line: " + lineCount + ": "); println(v1.toString() + " != " + v2.toString()); Assert.fail(); } } // Closing remarks print("\n" + lineCount + " lines processed. "); if (hasError) { print("Errors were found.\n\n"); } else { print("No errors were found.\n\n"); } } /** * Parses a single line from the reader, and returns the * evaluation of that line. * @return evaluated line. Returns null when the end of the file * is reached. * @throws Exception when IOException occurs, parsing fails, or when * evaluation fails */ private Object parseNextLine(BufferedReader reader) throws Exception { Object value; String line, errorStr; // cycle till a valid line is found do { line = reader.readLine(); // returns null on end of file if (line == null) return null; lineCount++; } while (line.length() == 0 || line.trim().charAt(0) == '#'); // parse the expression myParser.parseExpression(line); // did an error occur while parsing? if (myParser.hasError()) { errorStr = myParser.getErrorInfo(); throw new Exception("Error while parsing line " + lineCount + ": " + errorStr); } // evaluate the expression value = myParser.getValueAsObject(); // did an error occur while evaluating? if (value == null || myParser.hasError()) { errorStr = myParser.getErrorInfo(); throw new Exception("Error while evaluating line " + lineCount + ": " + errorStr); } return value; } /** * Compares o1 and o2. Copied from Comparative.java. * @return true if o1 and o2 are equal. false otherwise. */ private boolean equal(Object param1, Object param2) { double tolerance = 1e-15; if ((param1 instanceof Complex) && (param2 instanceof Complex)) { return ((Complex)param1).equals((Complex)param2, tolerance); } if ((param1 instanceof Complex) && (param2 instanceof Number)) { return ((Complex)param1).equals(new Complex((Number) param2), tolerance); } if ((param2 instanceof Complex) && (param1 instanceof Number)) { return ((Complex)param2).equals(new Complex((Number) param1), tolerance); } if ((param1 instanceof Number) && (param2 instanceof Number)) { return Math.abs(((Number)param1).doubleValue()-((Number)param2).doubleValue()) < tolerance; } // test any other types here return param1.equals(param2); } /** * Test the getValue() method. */ public void testGetValue() { // Test whether a normal double value is returned correctly myParser.parseExpression("2.1345"); Assert.assertEquals(myParser.getValue(), 2.1345, 0); // Test whether NaN is returned for Somplex numbers myParser.parseExpression("i"); Assert.assertTrue(Double.isNaN(myParser.getValue())); // Test whether NaN is returned for String results myParser.parseExpression("\"asdf\""); Assert.assertTrue(Double.isNaN(myParser.getValue())); } /** * Test the getComplexValue() method. */ public void testGetComplexValue() { // Test whether a normal double value is returned as a Complex myParser.parseExpression("2.1345"); Assert.assertTrue(new Complex(2.1345, 0).equals( myParser.getComplexValue(), 0)); // Test whether (0, 1) is returned for i myParser.parseExpression("i"); Complex z = myParser.getComplexValue(); Assert.assertTrue(z != null); Assert.assertTrue(z.re() == 0); Assert.assertTrue(z.im() == 1); // Test whether NaN is returned for String results myParser.parseExpression("\"asdf\""); Assert.assertTrue(Double.isNaN(myParser.getValue())); } /** * Helper function for printing. */ private static void print(String str) { System.out.print(str); } /** * Helper function for printing lines. */ private static void println(String str) { System.out.println(str); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/BugsTest.java0000644000000000000000000001263010615400352022260 0ustar rootrootpackage org.nfunk.jeptesting; import java.util.Enumeration; import java.util.Stack; import junit.framework.Assert; import junit.framework.TestCase; import org.nfunk.jep.JEP; import org.nfunk.jep.ParseException; import org.nfunk.jep.SymbolTable; import org.nfunk.jep.Variable; import org.nfunk.jep.function.PostfixMathCommand; import org.nfunk.jep.type.Complex; /** * This class is intended to contain all tests related to reported bugs. * * @author Nathan Funk */ public class BugsTest extends TestCase { private JEP jep; /** * Creates a new BugsTest instance */ public BugsTest(String name) { super(name); } public void setUp() { // Set up the parser jep = new JEP(); jep.setImplicitMul(true); jep.addStandardFunctions(); jep.addStandardConstants(); jep.addComplex(); jep.setTraverse(false); } /** * Tests the uninitialized OperatorSet bug 1061200 */ public void testOpSetBug() { JEP j = new JEP(false, true, true, null); Assert.assertNotNull(j.getOperatorSet()); } /** * Tests [ 1562371 ] ParseException not sets jep.hasError() flag. * * This bug turned out to actually not be a bug. The user reported that * no error occured from a custom function during parsing, only after * evaluation. This is expected behaviour since the run() method is * not called during parsing - so even if there is a type compatibility * issue, it will not be determined while parsing. */ public void testHasError() { jep.addFunction("custFunc", new CustFunc()); jep.parseExpression("custFunc(-1)"); Assert.assertTrue(!jep.hasError()); jep.getValue(); Assert.assertTrue(jep.hasError()); // additional tests // test too many arguments jep.parseExpression("custFunc(1, 1)"); Assert.assertTrue(jep.hasError()); jep.getValue(); Assert.assertTrue(jep.hasError()); // test for empty expression causing error (should have error after parsing) jep.parseExpression(""); Assert.assertTrue(jep.hasError()); jep.getValue(); Assert.assertTrue(jep.hasError()); // test syntax error (should have error after parsing) jep.parseExpression("1+"); Assert.assertTrue(jep.hasError()); jep.getValue(); Assert.assertTrue(jep.hasError()); // test type error (should have error after evaluation) jep.parseExpression("sin([1, 1])"); Assert.assertTrue(!jep.hasError()); jep.getValue(); Assert.assertTrue(jep.hasError()); } /** * Inner class for testing bug 1562371 * This custom function returns the parameter if it is a regular number * greater than zero. It throws an exception otherwise. * @author singularsys */ private class CustFunc extends PostfixMathCommand { public CustFunc() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); if (param instanceof Number && ((Number)param).doubleValue() > 0) { inStack.push(param); } else { System.out.println("Throwing exception"); throw new ParseException("Parameter is not a Number or not >0"); } return; } } /** * Tests bug [ 1585128 ] setAllowUndeclared does not work!!! * setAllowedUndeclared should add variables to the symbol table. * * This test parses the expression "x" and checks whether only the * variable x is in the symboltable (no more no less) */ public void testSetAllowUndeclared() { jep.initSymTab(); // clear the Symbol Table jep.setAllowUndeclared(true); jep.parseExpression("x"); SymbolTable st = jep.getSymbolTable(); int i = 0; // should only contain a single variable x for (Enumeration e = st.elements(); e.hasMoreElements(); ) { Variable var = (Variable) e.nextElement(); Assert.assertTrue(var.getName().equals("x")); i++; } Assert.assertTrue(i==1); } /** * Tests [ 1589277 ] Power function and "third root". * * Simple test for (-8)^(1/3) == -2. * public void testComplexPower() { jep.initSymTab(); jep.parseExpression("(-8)^(1/3)"); Complex result = jep.getComplexValue(); Assert.assertTrue(result.equals(new Complex(-2, 0))); }*/ /** * Tests [ 1563324 ] getValueAsObject always return null after an error * * JEP 2.4.0 checks the errorList variable before evaluating * an expression if there is an error in the list, null is returned. This * behaviour is bad because errors are added to the list by * getValueAsObject. If the first evaluation fails (after a successful parse) * then an error is added to the list. Subsequent calls to getValueAsObject * fail because there is an error in the list. */ public void testBug1563324() { jep.initSymTab(); jep.setAllowUndeclared(true); // parse a valid expression jep.parseExpression("abs(x)"); // add a variable with a value that causes evaluation to fail // (the Random type is not supported by the abs function) jep.addVariable("x", new java.util.Random()); Object result = jep.getValueAsObject(); // evaluation should have failed Assert.assertTrue(jep.hasError()); // change the variable value to a value that should be evaluated jep.addVariable("x", -1); // ensure that it is evaluated correctly result = jep.getValueAsObject(); Assert.assertTrue((result instanceof Double) && ((Double)result).doubleValue() == 1.0); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jeptesting/ComplexTest.java0000644000000000000000000000224510615400352022770 0ustar rootrootpackage org.nfunk.jeptesting; import org.nfunk.jep.ParseException; import org.nfunk.jep.type.Complex; import junit.framework.Assert; import junit.framework.TestCase; public class ComplexTest extends TestCase { public ComplexTest(String name) { super(name); } /** * Test method for 'org.nfunk.jep.function.Logarithm.run(Stack)' * Tests the return value of log(NaN). This is a test for bug #1177557 */ public void testPower() { Complex one = new Complex(1, 0); Complex negOne = new Complex(-1, 0); Complex i = new Complex(0, 1); Complex two = new Complex(2, 0); Complex negTwo = new Complex(-2, 0); Complex negEight = new Complex(-8, 0); // multiplication Assert.assertTrue((one.mul(one)).equals(one,0)); Assert.assertTrue((one.mul(negOne)).equals(negOne,0)); Assert.assertTrue((negOne.mul(one)).equals(negOne,0)); // power Assert.assertTrue((one.power(one)).equals(one,0)); Assert.assertTrue((one.power(-1)).equals(one,0)); Assert.assertTrue((one.power(negOne)).equals(one,0)); Assert.assertTrue((negOne.power(two)).equals(one,0)); //Assert.assertTrue((negEight.power(1.0/3)).equals(negTwo,0)); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/0000755000000000000000000000000010615400352016255 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/SimpleNode.java0000644000000000000000000000543010615400352021161 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. SimpleNode.java */ package org.nfunk.jep; /* * The parent class for all AST node classes. Contains basic tree node methods * for traversal, adding and removing children and parent nodes, and other * methods. */ public class SimpleNode implements Node { protected Node parent; protected Node[] children; protected int id; protected Parser parser; public SimpleNode(int i) { id = i; } public SimpleNode(Parser p, int i) { this(i); parser = p; } public void jjtOpen() { } public void jjtClose() { } public void jjtSetParent(Node n) { parent = n; } public Node jjtGetParent() { return parent; } public void jjtAddChild(Node n, int i) { if (children == null) { children = new Node[i + 1]; } else if (i >= children.length) { Node c[] = new Node[i + 1]; System.arraycopy(children, 0, c, 0, children.length); children = c; } children[i] = n; } public Node jjtGetChild(int i) { return children[i]; } public int jjtGetNumChildren() { return (children == null) ? 0 : children.length; } /** Accept the visitor. **/ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException { return visitor.visit(this, data); } /** Accept the visitor. **/ public Object childrenAccept(ParserVisitor visitor, Object data) throws ParseException { if (children != null) { for (int i = 0; i < children.length; ++i) { children[i].jjtAccept(visitor, data); } } return data; } /* You can override these two methods in subclasses of SimpleNode to customize the way the node appears when the tree is dumped. If your output uses more than one line you should override toString(String), otherwise overriding toString() is probably all you need to do. */ public String toString() { return ParserTreeConstants.jjtNodeName[id]; } public String toString(String prefix) { return prefix + toString(); } /* Override this method if you want to customize how the node dumps out its children. */ public void dump(String prefix) { System.out.println(toString(prefix)); if (children != null) { for (int i = 0; i < children.length; ++i) { SimpleNode n = (SimpleNode)children[i]; if (n != null) { n.dump(prefix + " "); } } } } /** * Returns the id of the node (for simpler identification). */ public int getId() { return id; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ParserVisitor.java0000644000000000000000000000110710615400352021733 0ustar rootroot/* Generated By:JJTree: Do not edit this line. /Users/singularsys/Documents/workspace/jep-newcvs/src/org/nfunk/jep/ParserVisitor.java */ package org.nfunk.jep; public interface ParserVisitor { public Object visit(SimpleNode node, Object data) throws ParseException; public Object visit(ASTStart node, Object data) throws ParseException; public Object visit(ASTFunNode node, Object data) throws ParseException; public Object visit(ASTVarNode node, Object data) throws ParseException; public Object visit(ASTConstant node, Object data) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/SymbolTable.java0000644000000000000000000002246310615400352021344 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep; import java.util.*; /** A Hashtable which holds a list of all variables. * Heavily changed from Jep-2.24 which was just a Hashtable which stored * the values of each variable. Here the Hashtable contains * elements of type {@link Variable Variable} which contain * information about that variable. * Rather than using {@link #get get} the methods * {@link #getValue getValue(String)}, {@link #getVar getVar(String)} * should be used to return the value or variable. * The {@link #put put} method is deprecated and should be replace by one of *
      *
    • {@link #addVariable addVariable(String,Object)} adds a variable with a given name and value, returns null if variable already exists. *
    • {@link #addConstant addConstant(String,Object)} adds a 'constant' variable whos value cannot be changed. *
    • {@link #setVarValue setVarValue(String,Object)} sets the value of an existing variable. Returns false if variable does not exist. *
    • {@link #makeVarIfNeeded(String,Object)} if necessary creates a variable and set its value. *
    • {@link #makeVarIfNeeded(String)} if necessary creates a variable. Does not change the value. *
    *

    * Variables which do not have a value set are deemed to be invalid. * When Variables need to be constructed then methods in the {@link VariableFactory} * should be called, which allows different types of variables to be used. * *

    * Both SymbolTable and Variable implement the Observer/Observable pattern. * This allows objects to be informed whenever a new variable is created * or when its value has been changed. The member class StObservable is used to implement * Observer. An example of use is *

     * public class MyObserver implements Observer
     * {
     * 	public void initialise()
     * 	{
     * 		SymbolTable st = j.getSymbolTable();
     * 		st.addObserver(this);
     * 		st.addObserverToExistingVariables(this);
     * 	}
     * 
     * 	public void update(Observable arg0, Object arg1)
     * 	{
     * 		if(arg0 instanceof Variable)
     * 			println("Var changed: "+arg0);
     * 		else if(arg0 instanceof SymbolTable.StObservable)
     * 		{
     * 			println("New var: "+arg1);
     * 
     * 			// This line is vital to ensure that 
     * 			// any new variable created will be observed. 
     * 			((Variable) arg1).addObserver(this);
     * 		}
     * 	}
     * }
     * 
    * * @author Rich Morris * Created on 28-Feb-2004 */ public class SymbolTable extends Hashtable { private static final long serialVersionUID = 1127787896437151144L; private VariableFactory vf; /** SymbolTable should always be constructed an associated variable factory. */ public SymbolTable(VariableFactory varFac) { vf = varFac; } /** Private default constructors, SymbolTable should always be constructed with an explicit variable factory. */ private SymbolTable() {} /** * @deprecated The getValue or getVar methods should be used instead. */ public Object get(Object key) { return getValue(key); } /** Finds the value of the variable with the given name. * Returns null if variable does not exist. */ public Object getValue(Object key) { Variable var = (Variable) super.get(key); if(var==null) return null; return var.getValue(); } /** Finds the variable with given name. * Returns null if variable does not exist. */ public Variable getVar(String name) { return (Variable) super.get(name); } /** * @deprecated The setVarValue or makeVar methods should be used instead. */ public Object put(Object key,Object val) { return makeVarIfNeeded((String) key,val); } /** * Sets the value of variable with the given name. * @throws NullPointerException if the variable has not been previously created * with {@link #addVariable(String,Object)} first. */ public void setVarValue(String name,Object val) { Variable var = (Variable) super.get(name); if(var != null) { var.setValue(val); return; } throw new NullPointerException("Variable "+name+" does not exist."); } /** * Returns a new variable fro the variable factory. Notifies observers * when a new variable is created. If a subclass need to create a new variable it should call this method. * * @param name * @param val * @return an new Variable object. */ protected Variable createVariable(String name,Object val) { Variable var = vf.createVariable(name,val); obeservable.stSetChanged(); obeservable.notifyObservers(var); return var; } protected Variable createVariable(String name) { Variable var = vf.createVariable(name); obeservable.stSetChanged(); obeservable.notifyObservers(var); return var; } /** Creates a new variable with given value. * * @param name name of variable * @param val initial value of variable * @return a reference to the created variable. */ public Variable addVariable(String name,Object val) { Variable var = (Variable) super.get(name); if(var != null) throw new IllegalStateException("Variable "+name+" already exists."); var = createVariable(name,val); super.put(name,var); var.setValidValue(true); return var; } /** Create a constant variable with the given name and value. * Returns null if variable already exists. */ public Variable addConstant(String name,Object val) { Variable var = addVariable(name,val); var.setIsConstant(true); return var; } /** Create a variable with the given name and value. * It silently does nothing if the value cannot be set. * @return the Variable. */ public Variable makeVarIfNeeded(String name,Object val) { Variable var = (Variable) super.get(name); if(var != null) { if(var.isConstant()) throw new IllegalStateException("Attempt to change the value of constant variable "+name); var.setValue(val); return var; } var = createVariable(name,val); super.put(name,var); return var; } /** If necessary create a variable with the given name. * If the variable exists its value will not be changed. * @return the Variable. */ public Variable makeVarIfNeeded(String name) { Variable var = (Variable) super.get(name); if(var != null) return var; var = createVariable(name); super.put(name,var); return var; } /** * Returns a list of variables, one per line. */ public String toString() { StringBuffer sb = new StringBuffer(); for(Enumeration e = this.elements(); e.hasMoreElements(); ) { Variable var = (Variable) e.nextElement(); sb.append(var.toString()); sb.append("\n"); } return sb.toString(); } /** * Clears the values of all variables. * Finer control is available through the * {@link Variable#setValidValue Variable.setValidValue} method. */ public void clearValues() { for(Enumeration e = this.elements(); e.hasMoreElements(); ) { Variable var = (Variable) e.nextElement(); var.setValidValue(false); } } /** * Returns the variable factory of this instance. */ public VariableFactory getVariableFactory() { return vf; } public class StObservable extends Observable { protected synchronized void stSetChanged() { this.setChanged(); } public SymbolTable getSymbolTable() { return SymbolTable.this; } } protected StObservable obeservable = new StObservable(); /** * Adds an observer which will be notified when a new variable is created. * The observer's update method will be called whenever a new * variable is created, the second argument of this will be * a reference to the new variable. * *

    * To find out if the values of variables are changed * the Variable.addObserver method should be used. * * @param arg the observer * @see Variable#addObserver(Observer) */ public synchronized void addObserver(Observer arg) { obeservable.addObserver(arg); } public synchronized int countObservers() { return obeservable.countObservers(); } public synchronized void deleteObserver(Observer arg) { obeservable.deleteObserver(arg); } public synchronized void deleteObservers() { obeservable.deleteObservers(); } public synchronized boolean hasChanged() { return obeservable.hasChanged(); } /** Adds an observer to all variables currently in the SymbolTable. * * @param arg the object to be notified when a variable changes. */ public synchronized void addObserverToExistingVariables(Observer arg) { for(Enumeration en = this.elements();en.hasMoreElements();) { Variable var = (Variable) en.nextElement(); var.addObserver(arg); } } /** Remove all non constant elements */ public void clearNonConstants() { Vector tmp = new Vector(); for(Enumeration en = this.elements();en.hasMoreElements();) { Variable var = (Variable) en.nextElement(); if(var.isConstant()) tmp.add(var); } this.clear(); for(Enumeration en = tmp.elements();en.hasMoreElements();) { Variable var = (Variable) en.nextElement(); super.put(var.getName(),var); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/0000755000000000000000000000000010615400352020102 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Sum.java0000644000000000000000000000303110615400352021506 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; /** * This class serves mainly as an example of a function that accepts any number * of parameters. Note that the numberOfParameters is initialized to -1. */ public class Sum extends PostfixMathCommand { private Add addFun = new Add(); /** * Constructor. */ public Sum() { // Use a variable number of arguments numberOfParameters = -1; } /** * Calculates the result of summing up all parameters, which are assumed to * be of the Double type. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack if (curNumberOfParameters < 1) throw new ParseException("No arguments for Sum"); // initialize the result to the first argument Object sum = stack.pop(); Object param; int i = 1; // repeat summation for each one of the current parameters while (i < curNumberOfParameters) { // get the parameter from the stack param = stack.pop(); // add it to the sum (order is important for String arguments) sum = addFun.add(param, sum); i++; } // push the result on the inStack stack.push(sum); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Floor.java0000644000000000000000000000215210615400352022026 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; /** * A PostfixMathCommandI which find the smallest integer below the number * ceil(pi) give 3 * ceil(-i) give -4 * * @author Richard Morris * @see Math#floor(double) */ public class Floor extends PostfixMathCommand { public Floor() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(floor(param));//push the result on the inStack return; } public Object floor(Object param) throws ParseException { if (param instanceof Number) { return new Double(Math.floor(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/CosineH.java0000644000000000000000000000220110615400352022270 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class CosineH extends PostfixMathCommand { public CosineH() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(cosh(param));//push the result on the inStack return; } public Object cosh(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).cosh(); } else if (param instanceof Number) { double value = ((Number)param).doubleValue(); return new Double((Math.exp(value) + Math.exp(-value))/2); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/ArcTanH.java0000644000000000000000000000262610615400352022233 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Implements the arcTanH function. * * @author Nathan Funk * @since 2.3.0 beta 2 - Now returns Double result rather than Complex for -1 -1.0 && val < 1) { double res = Math.log((1+val)/(1-val))/2; return new Double(res); } else { Complex temp = new Complex(val,0.0); return temp.atanh(); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Ceil.java0000644000000000000000000000214410615400352021622 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; /** * A PostfixMathCommandI which find the smallest integer above the number * ceil(pi) give 4 * ceil(-i) give -3 * * @author Richard Morris * @see Math#ceil(double) */ public class Ceil extends PostfixMathCommand { public Ceil() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(ceil(param));//push the result on the inStack return; } public Object ceil(Object param) throws ParseException { if (param instanceof Number) { return new Double(Math.ceil(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/package.html0000644000000000000000000000057110615400352022366 0ustar rootroot Provides function and operator classes. Each predefined function is contained in this package as a class. Operators are also contained in classes such as Add, Subtract, Multiply, or Comparative. Interfaces and supportive classes are:

    • PostfixMathCommand
    • PostfixMathCommandI
    • ComplexPFMC
    • SpecialEvaluationI
    jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Exp.java0000644000000000000000000000266610615400352021513 0ustar rootroot/***************************************************************************** Exp function created by R. Morris JEP - Java Math Expression Parser 2.24 December 30 2002 (c) Copyright 2002, Nathan Funk See LICENSE.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.nfunk.jep.function.PostfixMathCommand; /** * The exp function. * Defines a method exp(Object param) * which calculates * @author Rich Morris * Created on 20-Jun-2003 */ public class Exp extends PostfixMathCommand { public Exp() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(exp(param));//push the result on the inStack return; } public Object exp(Object param) throws ParseException { if (param instanceof Complex) { Complex z = (Complex) param; double x = z.re(); double y = z.im(); double mod = Math.exp(x); return new Complex(mod*Math.cos(y),mod*Math.sin(y)); } else if (param instanceof Number) { return new Double(Math.exp(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/ArcCosine.java0000644000000000000000000000231710615400352022616 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * The acos function. * @author Nathan Funk * TODO How to handle acos(x) for real x with x>1 or x<-1 */ public class ArcCosine extends PostfixMathCommand { public ArcCosine() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(acos(param));//push the result on the inStack return; } public Object acos(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).acos(); } else if (param instanceof Number) { return new Double(Math.acos(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/List.java0000644000000000000000000000207110615400352021660 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; /** The list function. * Returns a Vector comprising all the children. * * @author Rich Morris * Created on 29-Feb-2004 */ public class List extends PostfixMathCommand { public List() { numberOfParameters = -1; } public void run(Stack inStack) throws ParseException { checkStack(inStack); // check the stack if(curNumberOfParameters <1) throw new ParseException("Empty list"); Vector res = new Vector(curNumberOfParameters); res.setSize(curNumberOfParameters); for(int i=curNumberOfParameters-1;i>=0;--i) { Object param = inStack.pop(); res.setElementAt(param,i); } inStack.push(res); return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/ArcCosineH.java0000644000000000000000000000266010615400352022727 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Implements the arcCosH function. * * @author Nathan Funk * @since 2.3.0 beta 2 - Now returns Double result rather than Complex for x >= 1 */ public class ArcCosineH extends PostfixMathCommand { public ArcCosineH() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(acosh(param));//push the result on the inStack return; } public Object acosh(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).acosh(); } else if (param instanceof Number) { double val = ((Number)param).doubleValue(); if(val >= 1.0) { double res = Math.log(val+Math.sqrt(val*val-1)); return new Double(res); } else { Complex temp = new Complex(((Number)param).doubleValue(),0.0); return temp.acosh(); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Power.java0000644000000000000000000000432310615400352022043 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class Power extends PostfixMathCommand { public Power() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack); // check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); inStack.push(power(param1, param2)); } public Object power(Object param1, Object param2) throws ParseException { if (param1 instanceof Complex) { if (param2 instanceof Complex) return power((Complex)param1, (Complex)param2); else if (param2 instanceof Number) return power((Complex)param1, (Number)param2); } else if (param1 instanceof Number) { if (param2 instanceof Complex) return power((Number)param1, (Complex)param2); else if (param2 instanceof Number) return power((Number)param1, (Number)param2); } throw new ParseException("Invalid parameter type"); } public Object power(Number d1, Number d2) { if (d1.doubleValue()<0 && d2.doubleValue() != d2.intValue()) { Complex c = new Complex(d1.doubleValue(), 0.0); return c.power(d2.doubleValue()); } else return new Double(Math.pow(d1.doubleValue(),d2.doubleValue())); } public Object power(Complex c1, Complex c2) { Complex temp = c1.power(c2); if (temp.im()==0) return new Double(temp.re()); else return temp; } public Object power(Complex c, Number d) { Complex temp = c.power(d.doubleValue()); if (temp.im()==0) return new Double(temp.re()); else return temp; } public Object power(Number d, Complex c) { Complex base = new Complex(d.doubleValue(), 0.0); Complex temp = base.power(c); if (temp.im()==0) return new Double(temp.re()); else return temp; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/LValueI.java0000644000000000000000000000146310615400352022252 0ustar rootroot/* Created 16-May-2006 - Richard Morris */ package org.nfunk.jep.function; import org.nfunk.jep.EvaluatorI; import org.nfunk.jep.Node; import org.nfunk.jep.ParseException; /** * @author Richard Morris * An interface for functions which can be used on the left hand side of an assignment. * For instance * a[3] = 5 * sets the third element of a to the value 5. */ public interface LValueI { /** * Performs appropriate action to set an LValue. * @param pv a pointer to the evaluator. The pv.eval() method can be used to evaluate the children of the node. * @param node The top node for the LValue * @param value the value obtained by evaluating the right hand side. * @throws ParseException */ public void set(EvaluatorI pv,Node node,Object value) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/SquareRoot.java0000644000000000000000000000274110615400352023055 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class SquareRoot extends PostfixMathCommand { public SquareRoot() { numberOfParameters = 1; } /** * Applies the function to the parameters on the stack. */ public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(sqrt(param));//push the result on the inStack return; } /** * Calculates the square root of the parameter. The parameter must * either be of type Double or Complex. * * @return The square root of the parameter. */ public Object sqrt(Object param) throws ParseException { if (param instanceof Complex) return ((Complex)param).sqrt(); if (param instanceof Number) { double value = ((Number)param).doubleValue(); // a value less than 0 will produce a complex result if (value < 0.0) { return (new Complex(value).sqrt()); } else { return new Double(Math.sqrt(value)); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/If.java0000644000000000000000000000524610615400352021312 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.nfunk.jep.function; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * The if(condExpr,posExpr,negExpr) function. * The value of trueExpr will be returned if condExpr is >0 or Boolean.TRUE * and value of negExpr will be returned if condExpr is <= 0 or Boolean.TRUE. *

    * This function performs lazy evaluation so that * only posExpr or negExpr will be evaluated. * For Complex numbers only the real part is used. *

    * An alternate form if(condExpr,posExpr,negExpr,zeroExpr) * is also available. Note most computations * are carried out over floating point doubles so * testing for zero can be dangerous. *

    * This function implements the SpecialEvaluationI interface * so that it handles setting the value of a variable. * @author Rich Morris * Created on 18-Nov-2003 * @version 2.3.0 beta 1 now supports a Boolean first argument. * @since Feb 05 Handles Number arguments, so works with Integers rather than just Doubles */ public class If extends PostfixMathCommand implements CallbackEvaluationI { /** * */ public If() { super(); numberOfParameters = -1; } /* * Performs the specified action on an expression tree. * Serves no function in standard JEP but * @param node top node of the tree * @param pv The visitor, can be used evaluate the children. * @return top node of the results. * @throws ParseException public Node process(Node node,Object data,ParserVisitor pv) throws ParseException { return null; } */ /** * Checks the number of parameters of the call. * */ public boolean checkNumberOfParameters(int n) { return (n == 3 || n == 4); } /** * */ public Object evaluate(Node node,EvaluatorI pv) throws ParseException { int num = node.jjtGetNumChildren(); if( !checkNumberOfParameters(num)) throw new ParseException("If operator must have 3 or 4 arguments."); // get value of argument Object condVal = pv.eval(node.jjtGetChild(0)); // convert to double double val; if(condVal instanceof Boolean) { if(((Boolean) condVal).booleanValue()) return pv.eval(node.jjtGetChild(1)); return pv.eval(node.jjtGetChild(2)); } else if(condVal instanceof Complex) val = ((Complex) condVal).re(); else if(condVal instanceof Number) val = ((Number) condVal).doubleValue(); else throw new ParseException("Condition in if operator must be double or complex"); if(val>0.0) return pv.eval(node.jjtGetChild(1)); else if(num ==3 || val <0.0) return pv.eval(node.jjtGetChild(2)); return pv.eval(node.jjtGetChild(3)); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Cosine.java0000644000000000000000000000211610615400352022165 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class Cosine extends PostfixMathCommand { public Cosine() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(cos(param));//push the result on the inStack return; } public Object cos(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).cos(); } else if (param instanceof Number) { return new Double(Math.cos(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Round.java0000644000000000000000000000320110615400352022030 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; /** * A PostfixMathCommandI which rounds a number * round(pi) finds the closest integer to the argument * round(pi,3) rounds the argument to 3 decimal places * @author Richard Morris * */ public class Round extends PostfixMathCommand { public Round() { numberOfParameters = -1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack if(this.curNumberOfParameters==1) { Object param = inStack.pop(); inStack.push(round(param));//push the result on the inStack } else { Object r = inStack.pop(); Object l = inStack.pop(); inStack.push(round(l,r));//push the result on the inStack } return; } private Object round(Object l, Object r) throws ParseException { if (l instanceof Number && r instanceof Number) { int dp = ((Number)r).intValue(); double val = ((Number)l).doubleValue(); double mul = Math.pow(10,dp); return new Double(Math.rint(val*mul)/mul); } throw new ParseException("Invalid parameter type"); } public Object round(Object param) throws ParseException { if (param instanceof Number) { return new Double(Math.rint(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/SpecialEvaluationI.java0000644000000000000000000000243310615400352024470 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.nfunk.jep.function; import org.nfunk.jep.*; import java.util.Stack; /** * Functions which require greater control over their evaluation should implement this interface. * * @author Rich Morris * @deprecated The interface CallbackEvaluationI should generally be used instead as its simpler and allows different evaluation schemes to be used. * @see CallbackEvaluationI * Created on 18-Nov-2003 */ public interface SpecialEvaluationI { /** * Performs some special evaluation on the node. * This method has the responsibility for evaluating the children of the node * and it should generally call *

    	 * node.jjtGetChild(i).jjtAccept(pv,data);	
    	 * 
    * for each child. Briefly the symbol table was removed as arguments to this method, it is now reinserted. * * @param node The current node * @param data The data passed to visitor, typically not used * @param pv The visitor, can be used evaluate the children * @param stack The stack of the evaluator * @param symTab The symbol table * @return the value after evaluation * @throws ParseException */ public Object evaluate(Node node,Object data,ParserVisitor pv,Stack stack,SymbolTable symTab) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/TanH.java0000644000000000000000000000224610615400352021603 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class TanH extends PostfixMathCommand { public TanH() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(tanh(param));//push the result on the inStack return; } public Object tanh(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).tanh(); } else if (param instanceof Number) { double value = ((Number)param).doubleValue(); return new Double((Math.exp(value)-Math.exp(-value))/(Math.pow(Math.E,value)+Math.pow(Math.E,-value))); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Multiply.java0000644000000000000000000000543310615400352022571 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class Multiply extends PostfixMathCommand { public Multiply() { numberOfParameters = -1; } public void run(Stack stack) throws ParseException { checkStack(stack); // check the stack Object product = stack.pop(); Object param; int i = 1; // repeat summation for each one of the current parameters while (i < curNumberOfParameters) { // get the parameter from the stack param = stack.pop(); // multiply it with the product, order is important // if matricies are used product = mul(param,product); i++; } stack.push(product); return; } public Object mul(Object param1, Object param2) throws ParseException { if (param1 instanceof Complex) { if (param2 instanceof Complex) return mul((Complex)param1, (Complex)param2); else if (param2 instanceof Number) return mul((Complex)param1, (Number)param2); else if (param2 instanceof Vector) return mul((Vector)param2, (Complex)param1); } else if (param1 instanceof Number) { if (param2 instanceof Complex) return mul((Complex)param2, (Number)param1); else if (param2 instanceof Number) return mul((Number)param1, (Number)param2); else if (param2 instanceof Vector) return mul((Vector)param2, (Number)param1); } else if (param1 instanceof Vector) { if (param2 instanceof Complex) return mul((Vector)param1, (Complex)param2); else if (param2 instanceof Number) return mul((Vector)param1, (Number)param2); } throw new ParseException("Invalid parameter type"); } public Double mul(Number d1, Number d2) { return new Double(d1.doubleValue()*d2.doubleValue()); } public Complex mul(Complex c1, Complex c2) { return c1.mul(c2); } public Complex mul(Complex c, Number d) { return c.mul(d.doubleValue()); } public Vector mul(Vector v, Number d) { Vector result = new Vector(); for (int i=0; i * pv.eval(node.jjtGetChild(i)) * * for each child. * * The SymbolTable is not passed as an argument. This is because * it is better practice to get and set variable values by using * node.getVar().setValue() rather that through the SymbolTable with * requires a hashtable lookup. * * @param node The current node * @param pv The visitor, can be used evaluate the children * @return the value after evaluation * @throws ParseException */ public Object evaluate(Node node,EvaluatorI pv) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/ComplexPFMC.java0000644000000000000000000000235010615400352023022 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Converts a pair of real numbers to a complex number Complex(x,y)=x+i y. * * @author Rich Morris * Created on 24-Mar-2004 */ public class ComplexPFMC extends PostfixMathCommand { public ComplexPFMC() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if ((param1 instanceof Number) && (param2 instanceof Number)) { double real = ((Number)param1).doubleValue(); double imag = ((Number)param2).doubleValue(); inStack.push(new Complex(real,imag)); } else { throw new ParseException("Complex: Invalid parameter types "+param1.getClass().getName()+" "+param1.getClass().getName()); } return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Imaginary.java0000644000000000000000000000201210615400352022660 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class Imaginary extends PostfixMathCommand { public Imaginary() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(im(param));//push the result on the inStack return; } public Number im(Object param) throws ParseException { if (param instanceof Complex) return new Double(((Complex)param).im()); else if (param instanceof Number) return new Double(0); throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/PostfixMathCommandI.java0000644000000000000000000000302510615400352024623 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; /** * All function classes must implement this interface to ensure that the run() * method is implemented. */ public interface PostfixMathCommandI { /** * Run the function on the stack. Pops the arguments from the stack, and * pushes the result on the top of the stack. */ public void run(Stack aStack) throws ParseException; /** * Returns the number of required parameters, or -1 if any number of * parameters is allowed. */ public int getNumberOfParameters(); /** * Sets the number of current number of parameters used in the next call * of run(). This method is only called when the reqNumberOfParameters is * -1. */ public void setCurNumberOfParameters(int n); /** * Checks the number of parameters of the function. * This method is called during the parsing of the equation to check syntax. * Functions which set numberOfParameter=-1 should overwrite this method. * @param n number of parameters function will be called with. * @return False if an illegal number of parameters is supplied, true otherwise. */ public boolean checkNumberOfParameters(int n); } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/ArcTangent2.java0000644000000000000000000000216710615400352023063 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; /** * atan2(y, x) Returns the angle whose tangent is y/x. * @author nathan */ public class ArcTangent2 extends PostfixMathCommand { public ArcTangent2() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if ((param1 instanceof Number) && (param2 instanceof Number)) { double y = ((Number)param1).doubleValue(); double x = ((Number)param2).doubleValue(); inStack.push(new Double(Math.atan2(y, x)));//push the result on the inStack } else throw new ParseException("Invalid parameter type"); return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/NaturalLogarithm.java0000644000000000000000000000263610615400352024231 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Natural logarithm. * * RJM Change: fixed so ln(positive Double) is Double. */ public class NaturalLogarithm extends PostfixMathCommand { public NaturalLogarithm() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(ln(param));//push the result on the inStack return; } public Object ln(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).log(); } else if (param instanceof Number) { // Now returns Complex if param is <0 double num = ((Number) param).doubleValue(); if( num >= 0) return new Double(Math.log(num)); else if(num != num) return new Double(Double.NaN); else { Complex temp = new Complex(num); return temp.log(); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/SineH.java0000644000000000000000000000217310615400352021756 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class SineH extends PostfixMathCommand { public SineH() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(sinh(param));//push the result on the inStack return; } public Object sinh(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).sinh(); } else if (param instanceof Number) { double value = ((Number)param).doubleValue(); return new Double((Math.exp(value)-Math.exp(-value))/2); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Comparative.java0000644000000000000000000002216410615400352023224 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Implements the comparative operations <, >, <=, >=, != and ==. * Caverts should work where arguments are Double, Complex or String * for the last two only != and == work. * For other types care might be needed. * * Complex numbers are compared using a tolerance which can be set * using setTolerance(). * * @author N Funk and R Morris * @since 2.3.0 beta 1 a bit of a rewrite to make sub classing easier, now allows Complex to be compared to Double i.e. 1+0 i == 1. * @since 2.3.0 beta 2 changed the internal lt,gt,le,ge,ne and eq method to return boolean. * If this breaks anything use * if(lt(obj1,obj2)) inStack.push(new Double(1)); * else inStack.push(new Double(0)); */ public class Comparative extends PostfixMathCommand { protected int id; double tolerance; public static final int LT = 0; public static final int GT = 1; public static final int LE = 2; public static final int GE = 3; public static final int NE = 4; public static final int EQ = 5; /** * Constructor. Sets the number of parameters to 2. Initializes the * tolerance for comparing Complex values. * @param id_in The id of the comparative operator. */ public Comparative(int id_in) { id = id_in; numberOfParameters = 2; tolerance = 1e-6; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); boolean res=false; switch(id) { case LT: res = lt(param1,param2); break; case GT: res = gt(param1,param2); break; case LE: res = le(param1,param2); break; case GE: res = ge(param1,param2); break; case NE: res = ne(param1,param2); break; case EQ: res = eq(param1,param2); break; } if(res) inStack.push(new Double(1)); else inStack.push(new Double(0)); } public boolean lt(Object param1, Object param2) throws ParseException { if ((param1 instanceof Complex) || (param2 instanceof Complex)) throw new ParseException("< not defined for complex numbers"); if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x not defined for complex numbers"); if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x>y); } throw new ParseException("> not defined for object of type "+param1.getClass().getName()+" and "+param2.getClass().getName()); } public boolean le(Object param1, Object param2) throws ParseException { if ((param1 instanceof Complex) || (param2 instanceof Complex)) throw new ParseException("<= not defined for complex numbers"); if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x<=y); } throw new ParseException("<= not defined for object of type "+param1.getClass().getName()+" and "+param2.getClass().getName()); } public boolean ge(Object param1, Object param2) throws ParseException { if ((param1 instanceof Complex) || (param2 instanceof Complex)) throw new ParseException(">= not defined for complex numbers"); if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x>=y); } throw new ParseException(">= not defined for object of type "+param1.getClass().getName()+" and "+param2.getClass().getName()); } public boolean eq(Object param1, Object param2) throws ParseException { if ((param1 instanceof Complex) && (param2 instanceof Complex)) { return ((Complex)param1).equals((Complex)param2, tolerance); } if ((param1 instanceof Complex) && (param2 instanceof Number)) { return ((Complex)param1).equals(new Complex((Number)param2), tolerance); } if ((param2 instanceof Complex) && (param1 instanceof Number)) { return ((Complex)param2).equals(new Complex((Number)param1), tolerance); } if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x==y); } if ((param1 instanceof Boolean) && (param2 instanceof Boolean)) { boolean x = ((Boolean)param1).booleanValue(); boolean y = ((Boolean)param2).booleanValue(); return (x==y); } if ((param1 instanceof Number) && (param2 instanceof Boolean)) { double x = ((Number)param1).doubleValue(); double y = ((Boolean)param2).booleanValue()?1.0:0.0; return (x==y); } if ((param1 instanceof Boolean) && (param2 instanceof Number)) { double x = ((Boolean)param1).booleanValue()?1.0:0.0; double y = ((Number)param2).doubleValue(); return (x==y); } // if we get to here, just use the equal function return param1.equals(param2); } public boolean ne(Object param1, Object param2) throws ParseException { if ((param1 instanceof Complex) && (param2 instanceof Complex)) { return !((Complex)param1).equals((Complex)param2, tolerance); } if ((param1 instanceof Complex) && (param2 instanceof Number)) { return !((Complex)param1).equals(new Complex((Number) param2), tolerance); } if ((param2 instanceof Complex) && (param1 instanceof Number)) { return !((Complex)param2).equals(new Complex((Number) param1), tolerance); } if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); return (x!=y); } if ((param1 instanceof Boolean) && (param2 instanceof Boolean)) { boolean x = ((Boolean)param1).booleanValue(); boolean y = ((Boolean)param2).booleanValue(); return (x!=y); } if ((param1 instanceof Number) && (param2 instanceof Boolean)) { double x = ((Number)param1).doubleValue(); double y = ((Boolean)param2).booleanValue()?1.0:0.0; return (x!=y); } if ((param1 instanceof Boolean) && (param2 instanceof Number)) { double x = ((Boolean)param1).booleanValue()?1.0:0.0; double y = ((Number)param2).doubleValue(); return (x!=y); } return !param1.equals(param2); } /* old code if ((param1 instanceof Complex) || (param2 instanceof Complex)) throw new ParseException(">= not defined for complex numbers"); if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); int r = (x>=y) ? 1 : 0; return new Double(r); } throw new ParseException(">= not defined for object of type "+param1.getClass().getName()+" and "+param2.getClass().getName()); } { int r; switch (id) { case NE: r = ((Complex)param1).equals((Complex)param2, tolerance) ? 0 : 1; break; case EQ: r = ((Complex)param1).equals((Complex)param2, tolerance) ? 1 : 0; break; default: throw new ParseException("Relational operator type error"); } inStack.push(new Double(r));//push the result on the inStack } else if ((param1 instanceof Number) && (param2 instanceof Number)) { double x = ((Number)param1).doubleValue(); double y = ((Number)param2).doubleValue(); int r; switch (id) { case LT: r = (xy) ? 1 : 0; break; case LE: r = (x<=y) ? 1 : 0; break; case GE: r = (x>=y) ? 1 : 0; break; case NE: r = (x!=y) ? 1 : 0; break; case EQ: r = (x==y) ? 1 : 0; break; default: throw new ParseException("Unknown relational operator"); } inStack.push(new Double(r));//push the result on the inStack } else if ((param1 instanceof String) && (param2 instanceof String)) { int r; switch (id) { case NE: r = ((String)param1).equals((String)param2) ? 0 : 1; break; case EQ: r = ((String)param1).equals((String)param2) ? 1 : 0; break; default: throw new ParseException("Relational operator type error"); } inStack.push(new Double(r));//push the result on the inStack } else { throw new ParseException("Invalid parameter type"); } return; } */ /** * Returns the tolerance used for comparing complex numbers */ public double getTolerance() { return tolerance; } /** * Sets the tolerance used for comparing complex numbers * @param d */ public void setTolerance(double d) { tolerance = d; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Arg.java0000644000000000000000000000223110615400352021454 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Argument of a complex number * @author Rich Morris * Created on 20-Nov-2003 */ public class Arg extends PostfixMathCommand { private static final Double ONE = new Double(1.0); public Arg() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(arg(param));//push the result on the inStack return; } public Number arg(Object param) throws ParseException { if (param instanceof Complex) { return new Double(((Complex)param).arg()); } else if (param instanceof Number) { return (ONE); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Binomial.java0000644000000000000000000000511710615400352022503 0ustar rootroot/* @author rich * Created on 13-Feb-2005 * * See LICENSE.txt for license information. */ package org.nfunk.jep.function; import java.util.Stack; import org.nfunk.jep.ParseException; /** * Binomial coeficients: binom(n,i). * Requires n,i integers >=0. * Often written nCi or column vector (n,i). * (n,0) = 1, (n,1) = n, (n,n-1) = n, (n,n) = 1
    * (n,i) = n! / ( i! (n-i)! )
    * Pascals triangle rule: (n,i) = (n-1,i-1) + (n-1,i)
    * Binomial theorem: (a+b)^n = sum (n,i) a^i b^(n-i), i=0..n. *

    * For efficiency the binomial coefficients are stored in a static array. * @author Rich Morris * Created on 13-Feb-2005 */ public class Binomial extends PostfixMathCommand { static final int initN = 20; static int[][] coeffs = new int[initN+1][]; /** Static initialiser for binomial coeffs */ { coeffs[0] = new int[1]; coeffs[0][0] = 1; coeffs[1] = new int[2]; coeffs[1][0] = 1; coeffs[1][1] = 1; for(int n=2;n<=initN;++n) { coeffs[n] = new int[n+1]; coeffs[n][0] = 1; coeffs[n][n] = 1; for(int j=1;j nInt) throw new ParseException("Binomial: illegal values for arguments 0n */ static public int binom(int n,int i) throws ArrayIndexOutOfBoundsException { expand(n); return coeffs[n][i]; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Add.java0000644000000000000000000000536110615400352021442 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Addition function. Supports any number of parameters although typically * only 2 parameters are used. * @author nathan */ public class Add extends PostfixMathCommand { public Add() { numberOfParameters = -1; } /** * Calculates the result of applying the "+" operator to the arguments from * the stack and pushes it back on the stack. */ public void run(Stack stack) throws ParseException { checkStack(stack);// check the stack Object sum = stack.pop(); Object param; int i = 1; // repeat summation for each one of the current parameters while (i < curNumberOfParameters) { // get the parameter from the stack param = stack.pop(); // add it to the sum (order is important for String arguments) sum = add(param, sum); i++; } stack.push(sum); return; } /** * Adds two numbers together. The parameters can be of type Number, * Complex, or String. If a certain combination of types is not supported, * a ParseException is thrown. * * @param param1 The first parameter to be added. * @param param2 The second parameter to be added. * @return The sum of param1 and param2, or concatenation of the two if * they are Strings. * @throws ParseException */ public Object add(Object param1, Object param2) throws ParseException { if (param1 instanceof Complex) { if (param2 instanceof Complex) return add((Complex)param1, (Complex)param2); else if (param2 instanceof Number) return add((Complex)param1, (Number)param2); } else if (param1 instanceof Number) { if (param2 instanceof Complex) return add((Complex)param2, (Number)param1); else if (param2 instanceof Number) return add((Number)param1, (Number)param2); } else if ((param1 instanceof String) && (param2 instanceof String)) { return (String)param1 + (String)param2; } throw new ParseException("Invalid parameter type"); } public Double add(Number d1, Number d2) { return new Double(d1.doubleValue() + d2.doubleValue()); } public Complex add(Complex c1, Complex c2) { return new Complex(c1.re() + c2.re(), c1.im() + c2.im()); } public Complex add(Complex c, Number d) { return new Complex(c.re() + d.doubleValue(), c.im()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Logarithm.java0000644000000000000000000000305510615400352022676 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Log bass 10. *

    * RJM change return real results for positive real arguments. * Speedup by using static final fields. */ public class Logarithm extends PostfixMathCommand { private static final double LOG10 = Math.log(10); private static final Complex CLOG10 = new Complex(Math.log(10),0); public Logarithm() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(log(param));//push the result on the inStack return; } public Object log(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).log().div(CLOG10); } else if (param instanceof Number) { double num = ((Number) param).doubleValue(); if( num >= 0) return new Double(Math.log(num)/LOG10); else if(num != num) return new Double(Double.NaN); else { Complex temp = new Complex(num); return temp.log().div(CLOG10); } } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Sine.java0000644000000000000000000000210510615400352021641 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class Sine extends PostfixMathCommand { public Sine() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(sin(param));//push the result on the inStack return; } public Object sin(Object param) throws ParseException { if (param instanceof Complex) { return ((Complex)param).sin(); } else if (param instanceof Number) { return new Double(Math.sin(((Number)param).doubleValue())); } throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Conjugate.java0000644000000000000000000000215010615400352022662 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** The complex conjugate of a number conj(c) * * @author Rich Morris * Created on 13-Feb-2005 */ public class Conjugate extends PostfixMathCommand { public Conjugate() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(conj(param));//push the result on the inStack return; } public Object conj(Object param) throws ParseException { if (param instanceof Complex) return ((Complex)param).conj(); else if (param instanceof Number) return param; throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Random.java0000644000000000000000000000136310615400352022170 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.lang.Math; import java.util.*; import org.nfunk.jep.*; /** * Encapsulates the Math.random() function. */ public class Random extends PostfixMathCommand { public Random() { numberOfParameters = 0; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack inStack.push(new Double(Math.random())); return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Dot.java0000644000000000000000000000305210615400352021473 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; public class Dot extends PostfixMathCommand { static Add add = new Add(); static Multiply mul = new Multiply(); public Dot() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack); // check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); inStack.push(dot(param1, param2)); return; } public Object dot(Object param1, Object param2) throws ParseException { if (param1 instanceof Vector && param2 instanceof Vector) { return dot((Vector) param1,(Vector) param2); } throw new ParseException("Dot: Invalid parameter type, both arguments must be vectors"); } public Object dot(Vector v1,Vector v2) throws ParseException { if(v1.size()!=v2.size()) throw new ParseException("Dot: both sides of dot must be same length"); int len = v1.size(); if(len<1) throw new ParseException("Dot: empty vectors parsed"); Object res = mul.mul(v1.elementAt(0),v2.elementAt(0)); for(int i=1;i * a=[4,3,2,1]; * a[2]; // returns 2 * a[2]=5; // a is now [4,5,2,1] * * @author Richard Morris */ public class Ele extends PostfixMathCommand implements LValueI { /** * */ public Ele() { numberOfParameters = 2; } public void set(EvaluatorI pv, Node node, Object value) throws ParseException { Node lhsNode = node.jjtGetChild(0); if(!(lhsNode instanceof ASTVarNode)) throw new ParseException("Ele: lhs must be a variable"); ASTVarNode vn = (ASTVarNode) lhsNode; Variable var = vn.getVar(); Object rhs = pv.eval(node.jjtGetChild(1)); int index=-1; if(rhs instanceof Number) { index=((Number) rhs).intValue()-1; } else if(rhs instanceof Vector) { Vector vec = (Vector) rhs; if(vec.size()!=1) throw new ParseException("Ele: only single dimension arrays supported in JEP"); index = ((Number) vec.firstElement()).intValue()-1; } else throw new ParseException("Ele: rhs must be a number"); Object oldVarVal = var.getValue(); if(!(oldVarVal instanceof Vector)) throw new ParseException("Ele: the value of the variable must be a Vector"); Vector newVarVal = (Vector) ((Vector) oldVarVal).clone(); newVarVal.set(index,value); var.setValue(newVarVal); } public void run(Stack s) throws ParseException { checkStack(s);// check the stack Object rhs = s.pop(); Object lhs = s.pop(); if(!(lhs instanceof Vector)) throw new ParseException("Ele: lhs must be an instance of Vector"); if(rhs instanceof Number) { int index = ((Number) rhs).intValue(); Object val = ((Vector) lhs).elementAt(index-1); s.push(val); return; } if(rhs instanceof Vector) { Vector vec = (Vector) rhs; if(vec.size()!=1) throw new ParseException("Ele: only single dimension arrays supported in JEP"); int index = ((Number) vec.firstElement()).intValue(); Object val = ((Vector) lhs).elementAt(index-1); s.push(val); return; } throw new ParseException("Ele: only single dimension arrays supported in JEP"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Str.java0000644000000000000000000000160110615400352021513 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; /** * Converts an object into its string representation. * Calls the toString method of the object. * * @author Rich Morris * Created on 27-Mar-2004 */ public class Str extends PostfixMathCommand { public Str() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(param.toString());//push the result on the inStack return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Not.java0000644000000000000000000000205010615400352021502 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; public class Not extends PostfixMathCommand { public Not() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); if (param instanceof Number) { int r = (((Number)param).doubleValue() == 0) ? 1 : 0; inStack.push(new Double(r));//push the result on the inStack } else if(param instanceof Boolean) { int r = (((Boolean)param).booleanValue()) ? 0 : 1; inStack.push(new Double(r));//push the result on the inStack } else throw new ParseException("Invalid parameter type"); return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Polar.java0000644000000000000000000000222310615400352022021 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; /** * Converts a pair of real numbers to a complex number Complex(x,y)=x+i y. * * @author Rich Morris * Created on 24-Mar-2004 */ public class Polar extends PostfixMathCommand { public Polar() { numberOfParameters = 2; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param2 = inStack.pop(); Object param1 = inStack.pop(); if ((param1 instanceof Number) && (param2 instanceof Number)) { inStack.push(Complex.polarValueOf((Number) param1,(Number) param2)); } else { throw new ParseException("Complex: Invalid parameter types "+param1.getClass().getName()+" "+param1.getClass().getName()); } return; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/Assign.java0000644000000000000000000000304610615400352022174 0ustar rootroot/* @author rich * Created on 18-Nov-2003 */ package org.nfunk.jep.function; import org.nfunk.jep.*; /** * An assignment operator so we can do * x=3+4. * This function implements the CallbackEvaluationI interface * so that it handles setting the value of a variable. * * Any Variable or function which implements the LValueI can appear on the left hand side of the equation. * * @author Rich Morris * Created on 18-Nov-2003 */ public class Assign extends PostfixMathCommand implements CallbackEvaluationI { public Assign() { super(); numberOfParameters = 2; } /** For assignment set the value of the variable on the lhs to value returned by evaluating the righthand side. * */ public Object evaluate(Node node,EvaluatorI pv) throws ParseException { if(node.jjtGetNumChildren()!=2) throw new ParseException("Assignment operator must have 2 operators."); // evaluate the value of the righthand side. Object rhsVal = pv.eval(node.jjtGetChild(1)); // Set the value of the variable on the lhs. Node lhsNode = node.jjtGetChild(0); if(lhsNode instanceof ASTVarNode) { ASTVarNode vn = (ASTVarNode) lhsNode; Variable var = vn.getVar(); var.setValue(rhsVal); return rhsVal; } else if(lhsNode instanceof ASTFunNode && ((ASTFunNode) lhsNode).getPFMC() instanceof LValueI) { ((LValueI) ((ASTFunNode) lhsNode).getPFMC()).set(pv,lhsNode,rhsVal); return rhsVal; } throw new ParseException("Assignment should have a variable or LValue for the lhs."); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/UMinus.java0000644000000000000000000000175610615400352022176 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; public class UMinus extends PostfixMathCommand { public UMinus() { numberOfParameters = 1; } public void run(Stack inStack) throws ParseException { checkStack(inStack);// check the stack Object param = inStack.pop(); inStack.push(umin(param)); return; } public Object umin(Object param) throws ParseException { if (param instanceof Complex) return ((Complex)param).neg(); if (param instanceof Number) return new Double(-((Number)param).doubleValue()); throw new ParseException("Invalid parameter type"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/function/PostfixMathCommand.java0000644000000000000000000000561510615400352024521 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.function; import java.util.*; import org.nfunk.jep.*; /** * Function classes extend this class. It is an implementation of the * PostfixMathCommandI interface. *

    * It includes a numberOfParameters member, that is checked when parsing the * expression. This member should be initialized to an appropriate value for * all classes extending this class. If an arbitrary number of parameters * should be allowed, initialize this member to -1. */ public class PostfixMathCommand implements PostfixMathCommandI { /** * Number of parameters a the function requires. Initialize this value to * -1 if any number of parameters should be allowed. */ protected int numberOfParameters; /** * Number of parameters to be used for the next run() invocation. Applies * only if the required umber of parameters is variable * (numberOfParameters = -1). */ protected int curNumberOfParameters; /** * Creates a new PostfixMathCommand class. */ public PostfixMathCommand() { numberOfParameters = 0; curNumberOfParameters = 0; } /** * Check whether the stack is not null, throw a ParseException if it is. */ protected void checkStack(Stack inStack) throws ParseException { /* Check if stack is null */ if (null == inStack) { throw new ParseException("Stack argument null"); } } /** * Return the required number of parameters. */ public int getNumberOfParameters() { return numberOfParameters; } /** * Sets the number of current number of parameters used in the next call * of run(). This method is only called when the reqNumberOfParameters is * -1. */ public void setCurNumberOfParameters(int n) { curNumberOfParameters = n; } /** * Checks the number of parameters of the function. * Functions which set numberOfParameter=-1 should overload this method * @param n number of parameters function will be called with. * @return False if an illegal number of parameters is supplied, true otherwise. */ public boolean checkNumberOfParameters(int n) { if(numberOfParameters == -1) return true; return (numberOfParameters==n); } /** * Throws an exception because this method should never be called under * normal circumstances. Each function should use it's own run() method * for evaluating the function. This includes popping off the parameters * from the stack, and pushing the result back on the stack. */ public void run(Stack s) throws ParseException { throw new ParseException("run() method of PostfixMathCommand called"); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ASTFunNode.java0000644000000000000000000000434610615400352021035 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. ASTFunNode.java */ package org.nfunk.jep; import org.nfunk.jep.function.*; // rjm unneeded import // import java.util.*; /** * Function Node */ public class ASTFunNode extends SimpleNode { /** The function class used to evaluate the node */ private PostfixMathCommandI pfmc; /** Name of the function */ private String name; /** ID of the operator (if it is one) */ private Operator opID=null; /** * Creates a new ASTFunNode */ public ASTFunNode(int id) { super(id); } /** * Creates a new ASTFunNode */ public ASTFunNode(Parser p, int id) { super(p, id); } /** * Accept the visitor. */ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException { return visitor.visit(this, data); } /** * Sets the function for a node. A name and function class must * be specified. */ public void setFunction(String name_in, PostfixMathCommandI pfmc_in) { name = name_in; pfmc = pfmc_in; } /** * Sets the opID, name and pfmc for this node by looking up the values * in the Operators class */ public void setOperator(Operator op) { opID = op; pfmc = op.getPFMC(); name = op.getName(); } /** * Returns a string containing the function name. */ public String toString() { return "Function \"" + name + "\""; } /** * Returns the math command class associated with this node. */ public PostfixMathCommandI getPFMC() { return pfmc; } /** * Returns the name of the node (operator symbol or function name). */ public String getName() { return name; } /** * Returns the id number of the operator if the node is an operator. */ public Operator getOperator() { return opID; } /** * Returns true if node is an operator. */ public boolean isOperator() { return (opID != null); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/package.html0000644000000000000000000000040110615400352020531 0ustar rootroot Provides the main parsing classes including JEP and Parser as well as related classes such as node classes. This package also includes the EvaluatorVisitor used for evaluation. The JEP class serves as the main interface with the parser. jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ParserConstants.java0000644000000000000000000000310210615400352022245 0ustar rootroot/* Generated By:JJTree&JavaCC: Do not edit this line. ParserConstants.java */ package org.nfunk.jep; public interface ParserConstants { int EOF = 0; int INTEGER_LITERAL = 7; int DECIMAL_LITERAL = 8; int FLOATING_POINT_LITERAL = 9; int EXPONENT = 10; int STRING_LITERAL = 11; int INDENTIFIER1 = 12; int LETTER1 = 13; int DIGIT1 = 14; int INDENTIFIER2 = 15; int LETTER2 = 16; int DIGIT2 = 17; int ASSIGN = 18; int SEMI = 19; int COMMA = 20; int GT = 21; int LT = 22; int EQ = 23; int LE = 24; int GE = 25; int NE = 26; int AND = 27; int OR = 28; int PLUS = 29; int MINUS = 30; int MUL = 31; int DOT = 32; int DIV = 33; int MOD = 34; int NOT = 35; int POWER = 36; int CROSS = 37; int LSQ = 38; int RSQ = 39; int LRND = 40; int RRND = 41; int COLON = 42; int NO_DOT_IN_IDENTIFIERS = 0; int DEFAULT = 1; String[] tokenImage = { "", "\" \"", "\"\\t\"", "\"\\n\"", "\"\\r\"", "", "", "", "", "", "", "", "", "", "", "", "", "", "\"=\"", "\";\"", "\",\"", "\">\"", "\"<\"", "\"==\"", "\"<=\"", "\">=\"", "\"!=\"", "\"&&\"", "\"||\"", "\"+\"", "\"-\"", "\"*\"", "\".\"", "\"/\"", "\"%\"", "\"!\"", "\"^\"", "\"^^\"", "\"[\"", "\"]\"", "\"(\"", "\")\"", "\":\"", }; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ParserTreeConstants.java0000644000000000000000000000074310615400352023075 0ustar rootroot/* Generated By:JJTree: Do not edit this line. /Users/singularsys/Documents/workspace/jep-newcvs/src/org/nfunk/jep/ParserTreeConstants.java */ package org.nfunk.jep; public interface ParserTreeConstants { public int JJTSTART = 0; public int JJTVOID = 1; public int JJTFUNNODE = 2; public int JJTVARNODE = 3; public int JJTCONSTANT = 4; public String[] jjtNodeName = { "Start", "void", "FunNode", "VarNode", "Constant", }; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Variable.java0000644000000000000000000000746210615400352020656 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* @author rich * Created on 18-Nov-2003 */ package org.nfunk.jep; import java.util.*; /** * Information about a variable. * Each variable has a name, a value. * There is a flag to indicate * whether it is a constant or not (constants cannot have their value changed). * There is also a flag to indicate whether the value of the * variable is valid, if the variable is initialised without a value * then its value is said to be invalid. *

    * @author Rich Morris * Created on 18-Nov-2003 * @version 2.3.0 beta 2 Now extends Observable so observers can track if the value has been changed. */ public class Variable extends Observable { protected String name; private Object value; private boolean isConstant = false; private boolean validValue = false; // private static final Double ZERO = new Double(0.0); /** Constructors are protected. Variables should only * be created through the associated {@link VariableFactory} * which are in turned called by {@link SymbolTable}. */ protected Variable(String name) { this.name = name; this.value = null; validValue = false; } /** Constructors are protected. Variables should only * be created through the associated {@link VariableFactory} * which are in turned called by {@link SymbolTable}. */ protected Variable(String name,Object value) { this.name = name; this.value = value; validValue = (value!=null); } public String getName() {return name;} //private void setName(String string) {name = string; } public boolean isConstant() { return this.isConstant; } public void setIsConstant(boolean b) { this.isConstant = b; } public Object getValue() { return value; } /** Is the value of this variable valid? **/ public boolean hasValidValue() { return validValue; } /** Sets whether the value of variable is valid. **/ public void setValidValue(boolean val) { if(isConstant()) return; validValue = val; } /** * Sets the value of the variable. Constant values cannot be changed. *

    * This method call java.util.Observable.notifyObservers() * to indicate to anyone interested that the value has been changed. * Note subclasses should override setValueRaw rather than this * method so they do not need to handle the Observable methods. * * @return false if tried to change a constant value. * @since 2.3.0 beta 2 added Observable */ public boolean setValue(Object object) { if(!setValueRaw(object)) return false; setChanged(); notifyObservers(object); return true; } /** * In general subclasses should override this method rather than * setValue. This is because setValue notifies any observers * and then calls this method. * @param object * @return false if tried to change a constant value. * @since 2.3.0 beta 2 */ protected boolean setValueRaw(Object object) { if(isConstant) return false; validValue = true; value = object; return true; } /** * Returns a string with the variable name followed by it's value. * For example for the variable "a" with the value 10, the following * string is returned: *

    a: 10
    * If the variable is a constant the string " (Constant" is appended. * @return A string with the variable name and value. */ public String toString() { if(!validValue || value == null) return name + ": null"; else if(isConstant) return name + ": " + value.toString() + " (Constant)"; else return name + ": " + value.toString(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/JJTParserState.java0000644000000000000000000000663010615400352021732 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. JJTParserState.java */ package org.nfunk.jep; class JJTParserState { private java.util.Stack nodes; private java.util.Stack marks; private int sp; // number of nodes on stack private int mk; // current mark private boolean node_created; JJTParserState() { nodes = new java.util.Stack(); marks = new java.util.Stack(); sp = 0; mk = 0; } /* Determines whether the current node was actually closed and pushed. This should only be called in the final user action of a node scope. */ boolean nodeCreated() { return node_created; } /* Call this to reinitialize the node stack. It is called automatically by the parser's ReInit() method. */ void reset() { nodes.removeAllElements(); marks.removeAllElements(); sp = 0; mk = 0; } /* Returns the root node of the AST. It only makes sense to call this after a successful parse. */ Node rootNode() { return (Node)nodes.elementAt(0); } /* Pushes a node on to the stack. */ void pushNode(Node n) { nodes.push(n); ++sp; } /* Returns the node on the top of the stack, and remove it from the stack. */ Node popNode() { if (--sp < mk) { mk = ((Integer)marks.pop()).intValue(); } return (Node)nodes.pop(); } /* Returns the node currently on the top of the stack. */ Node peekNode() { return (Node)nodes.peek(); } /* Returns the number of children on the stack in the current node scope. */ int nodeArity() { return sp - mk; } void clearNodeScope(Node n) { while (sp > mk) { popNode(); } mk = ((Integer)marks.pop()).intValue(); } void openNodeScope(Node n) { marks.push(new Integer(mk)); mk = sp; n.jjtOpen(); } /* A definite node is constructed from a specified number of children. That number of nodes are popped from the stack and made the children of the definite node. Then the definite node is pushed on to the stack. */ void closeNodeScope(Node n, int num) { mk = ((Integer)marks.pop()).intValue(); while (num-- > 0) { Node c = popNode(); c.jjtSetParent(n); n.jjtAddChild(c, num); } n.jjtClose(); pushNode(n); node_created = true; } /* A conditional node is constructed if its condition is true. All the nodes that have been pushed since the node was opened are made children of the the conditional node, which is then pushed on to the stack. If the condition is false the node is not constructed and they are left on the stack. */ void closeNodeScope(Node n, boolean condition) { if (condition) { int a = nodeArity(); mk = ((Integer)marks.pop()).intValue(); while (a-- > 0) { Node c = popNode(); c.jjtSetParent(n); n.jjtAddChild(c, a); } n.jjtClose(); pushNode(n); node_created = true; } else { mk = ((Integer)marks.pop()).intValue(); node_created = false; } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ASTConstant.java0000644000000000000000000000200310615400352021254 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. ASTInteger.java */ package org.nfunk.jep; /** * Constant Node */ public class ASTConstant extends SimpleNode { private Object value; public ASTConstant(int id) { super(id); } public ASTConstant(Parser p, int id) { super(p, id); } public void setValue(Object val) { value = val; } public Object getValue() { return value; } /** Accept the visitor. **/ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException { return visitor.visit(this, data); } public String toString() { return "Constant: " + getValue(); // rjm needed so sub classes print properly } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/EvaluatorVisitor.java0000644000000000000000000002355410615400352022453 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep; import java.util.*; import org.nfunk.jep.function.*; /** * This class is used for the evaluation of an expression. It uses the Visitor * design pattern to traverse the function tree and evaluate the expression * using a stack. *

    * Function nodes are evaluated by first evaluating all the children nodes, * then applying the function class associated with the node. Variable and * constant nodes are evaluated by pushing their value onto the stack. *

    * Some changes implemented by rjm. Nov 03. * Added hook to SpecialEvaluationI. * Clears stack before evaluation. * Simplifies error handling by making visit methods throw ParseException. * Changed visit(ASTVarNode node) so messages not calculated every time. */ public class EvaluatorVisitor implements ParserVisitor, EvaluatorI { /** Stack used for evaluating the expression */ protected Stack stack; /** The current error list */ //protected Vector errorList; /** The symbol table for variable lookup */ protected SymbolTable symTab; /** Flag for errors during evaluation */ //protected boolean errorFlag; /** Debug flag */ protected static final boolean debug = false; /** TrapNull **/ protected boolean trapNullValues = true; /** Constructor. Initialise the stack member */ public EvaluatorVisitor() { //errorList = null; symTab = null; stack = new Stack(); } /** * Adds an error message to the list of errors */ /*protected void addToErrorList(String errorStr) { if (errorList != null) { errorList.addElement(errorStr); } }*/ /** * Returns the value of the expression as an object. The expression * tree is specified with its top node. The algorithm uses a stack * for evaluation. *

    * The symTab parameter can be null, if no variables are expected in the * expression. If a variable is found, an error is added to the error list. *

    * An exception is thrown, if an error occurs during evaluation. * @return The value of the expression as an object. * @throws ParseException if there is a problem with the evaluation. */ public Object getValue(Node topNode,SymbolTable symTab_in) throws ParseException { // check if arguments are ok if (topNode == null) { throw new ParseException("topNode parameter is null"); } // set member vars //errorList = errorList_in; symTab = symTab_in; //errorFlag = false; stack.removeAllElements(); // rjm addition ensure stack is correct before beginning. // njf changed from clear() to removeAllElements for 1.1 compatibility // evaluate by letting the top node accept the visitor topNode.jjtAccept(this,null); /* } catch (ParseException e) { this.addToErrorList("Error: "+e.getMessage()); return null; } if(errorFlag) return null; */ // something is wrong if not exactly one item remains on the stack // or if the error flag has been set if (stack.size() != 1) { throw new ParseException("Stack corrupted"); } // return the value of the expression return stack.pop(); } /* * The following methods was used to facilitate * using visitors which implemented a interface * which sub-classed ParserVisitor. * * If sub-classed to extend to implement a different visitor * this method should be overwritten to ensure the correct * accept method is called. * This method simply calls the jjtAccept(ParserVisitor this,Object data) of node. * * We no longer need this as we use ParseVisitor everywhere, * but kept for future reference. * private Object nodeAccept(Node node, Object data) throws ParseException { return node.jjtAccept(this,data); } */ /** * Evaluates a given node, in the current context. * @param node The node to evaluate * @return result of the evaluation */ public Object eval(Node node) throws ParseException { node.jjtAccept(this,null); return stack.pop(); } /** * Evaluates a PostfixMathCommandI with given arguments. * Not used in normal use. * * @param pfmc the command to evaluate. * @param children the parameters to the function. * @return the value of the function * @throws ParseException */ public Object eval(PostfixMathCommandI pfmc,Node children[]) throws ParseException { if (pfmc instanceof SpecialEvaluationI) { ASTFunNode node = new ASTFunNode(ParserTreeConstants.JJTFUNNODE); node.setFunction("TmpFun",pfmc); node.jjtOpen(); for(int i=0;i * If a function implements SpecialEvaluationI then the * evaluate method of PFMC is called. */ public Object visit(ASTFunNode node, Object data) throws ParseException { if (node == null) return null; PostfixMathCommandI pfmc = node.getPFMC(); // check if the function class is set if (pfmc == null) throw new ParseException( "No function class associated with " + node.getName()); // Some operators (=) need a special method for evaluation // as the pfmc.run method does not have enough information // in such cases we call the evaluate method which passes // all available info. Note evaluating the children is // the responsibility of the evaluate method. if (pfmc instanceof SpecialEvaluationI) { return ((SpecialEvaluationI) pfmc).evaluate( node,data,this,stack,this.symTab); } if(pfmc instanceof CallbackEvaluationI) { Object val = ((CallbackEvaluationI) pfmc).evaluate(node,this); stack.push(val); return val; } if (debug == true) { System.out.println( "Stack size before childrenAccept: " + stack.size()); } // evaluate all children (each leaves their result on the stack) data = node.childrenAccept(this, data); if (debug == true) { System.out.println( "Stack size after childrenAccept: " + stack.size()); } if (pfmc.getNumberOfParameters() == -1) { // need to tell the class how many parameters it can take off // the stack because it accepts a variable number of params pfmc.setCurNumberOfParameters(node.jjtGetNumChildren()); } // try to run the function pfmc.run(stack); if (debug == true) { System.out.println("Stack size after run: " + stack.size()); } return data; } /** * Visit a variable node. The value of the variable is obtained from the * symbol table (symTab) and pushed onto the stack. */ public Object visit(ASTVarNode node, Object data) throws ParseException { // old code // if (symTab == null) // throw new ParseException(message += "the symbol table is null"); // Optimise (table lookup is costly?) // Object temp = symTab.get(node.getName()); // new code // try to get the variable object Variable var = node.getVar(); if (var == null) { String message = "Could not evaluate " + node.getName() + ": "; throw new ParseException(message + "the variable was not found in the symbol table"); } // get the variable value Object temp = var.getValue(); if (trapNullValues && temp == null) { String message = "Could not evaluate " + node.getName() + ": "; throw new ParseException(message + "variable not set"); } // all is fine // push the value on the stack stack.push(temp); return data; } /** * Visit a constant node. The value of the constant is pushed onto the * stack. */ public Object visit(ASTConstant node, Object data) { stack.push(node.getValue()); return data; } /** * Tests whether null variable values are trapped by evaluator. * @return true is nulls are trapped */ public boolean isTrapNullValues() { return trapNullValues; } /** * Sets the behaviour when a variable's value is null. * If true an exception will be thrown is a variable value is null. * If false then the value will be passed to other functions, this may cause error * else where. * * @param b */ public void setTrapNullValues(boolean b) { trapNullValues = b; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/OperatorSet.java0000644000000000000000000001007310615400352021370 0ustar rootroot/* @author rich * Created on 03-Aug-2003 */ package org.nfunk.jep; import org.nfunk.jep.function.*; import org.nfunk.jep.Operator; /** * The standard set of operators used in JEP. *

    * This creates instances of the PostfixMathCommands for each operator, * saving the need for multiple objects to be created. To get a reference to a particular operator use *

     * OperatorSet opSet = jep.getOperatorSet();
     * Operator myOp = opSet.getAdd();
     * 
    *

    * If a new operator ABC is added to the parser the this class * should be extended to include a method Operator getABC(). *

    * Sub classes can change which Operator is returned by each method. * @author Rich Morris * Created on 19-Oct-2003 */ public class OperatorSet { /** everyone can read but not write these operators **/ protected Operator OP_GT = new Operator(">",new Comparative(Comparative.GT)); protected Operator OP_LT = new Operator("<",new Comparative(Comparative.LT)); protected Operator OP_EQ = new Operator("==",new Comparative(Comparative.EQ)); protected Operator OP_LE = new Operator("<=",new Comparative(Comparative.LE)); protected Operator OP_GE = new Operator(">=",new Comparative(Comparative.GE)); protected Operator OP_NE = new Operator("!=",new Comparative(Comparative.NE)); protected Operator OP_AND = new Operator("&&",new Logical(0)); protected Operator OP_OR = new Operator("||",new Logical(1)); protected Operator OP_NOT = new Operator("!",new Not()); protected Operator OP_ADD = new Operator("+",new Add()); protected Operator OP_SUBTRACT = new Operator("-",new Subtract()); protected Operator OP_UMINUS = new Operator("UMinus","-",new UMinus()); protected Operator OP_MULTIPLY = new Operator("*",new Multiply()); protected Operator OP_DIVIDE = new Operator("/",new Divide()); protected Operator OP_MOD = new Operator("%",new Modulus()); /** unary division i.e. 1/x or x^(-1) **/ protected Operator OP_UDIVIDE = new Operator("UDivide","^-1",null); protected Operator OP_POWER = new Operator("^",new Power()); protected Operator OP_ASSIGN = new Operator("=",new Assign()); protected Operator OP_DOT = new Operator(".",new Dot()); protected Operator OP_CROSS = new Operator("^^",new Cross()); protected Operator OP_LIST = new Operator("LIST",new List()); protected Operator OP_ELEMENT = new Operator("[]",new Ele()); // protected Operator OP_RANGE = new Operator(":",new Range()); public OperatorSet() { } /** Gets the list of operators. Note subclasses should override this method. */ public Operator[] getOperators() { Operator ops[] = new Operator[]{ OP_GT,OP_LT,OP_GE,OP_LE,OP_EQ,OP_NE,OP_AND,OP_OR,OP_NOT, OP_ADD,OP_SUBTRACT,OP_UMINUS,OP_MULTIPLY, OP_DIVIDE,OP_MOD,OP_POWER, OP_ASSIGN,OP_DOT,OP_CROSS,OP_LIST,OP_ELEMENT /*,OP_RANGE */}; return ops; } public void printOperators() { Operator ops[] = getOperators(); for(int i=0;i */ public ParseException(Token currentTokenVal, int[][] expectedTokenSequencesVal, String[] tokenImageVal ) { super(""); specialConstructor = true; currentToken = currentTokenVal; expectedTokenSequences = expectedTokenSequencesVal; tokenImage = tokenImageVal; } /** * The following constructors are for use by you for whatever * purpose you can think of. Constructing the exception in this * manner makes the exception behave in the normal way - i.e., as * documented in the class "Throwable". The fields "errorToken", * "expectedTokenSequences", and "tokenImage" do not contain * relevant information. The JavaCC generated code does not use * these constructors. */ public ParseException() { super(); specialConstructor = false; } public ParseException(String message) { super(message); specialConstructor = false; } /** * This variable determines which constructor was used to create * this object and thereby affects the semantics of the * "getMessage" method (see below). */ protected boolean specialConstructor; /** * This is the last token that has been consumed successfully. If * this object has been created due to a parse error, the token * following this token will (therefore) be the first error token. */ public Token currentToken; /** * Each entry in this array is an array of integers. Each array * of integers represents a sequence of tokens (by their ordinal * values) that is expected at this point of the parse. */ public int[][] expectedTokenSequences; /** * This is a reference to the "tokenImage" array of the generated * parser within which the parse error occurred. This array is * defined in the generated ...Constants interface. */ public String[] tokenImage; /** * This method has the standard behavior when this object has been * created using the standard constructors. Otherwise, it uses * "currentToken" and "expectedTokenSequences" to generate a parse * error message and returns it. If this object has been created * due to a parse error, and you do not catch it (it gets thrown * from the parser), then this method is called during the printing * of the final stack trace, and hence the correct error message * gets displayed. */ public String getMessage() { if (!specialConstructor) { return super.getMessage(); } String expected = ""; int maxSize = 0; for (int i = 0; i < expectedTokenSequences.length; i++) { if (maxSize < expectedTokenSequences[i].length) { maxSize = expectedTokenSequences[i].length; } for (int j = 0; j < expectedTokenSequences[i].length; j++) { expected += tokenImage[expectedTokenSequences[i][j]] + " "; } if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { expected += "..."; } expected += eol + " "; } String retval = "Encountered \""; Token tok = currentToken.next; for (int i = 0; i < maxSize; i++) { if (i != 0) retval += " "; if (tok.kind == 0) { retval += tokenImage[0]; break; } retval += add_escapes(tok.image); tok = tok.next; } retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; retval += "." + eol; if (expectedTokenSequences.length == 1) { retval += "Was expecting:" + eol + " "; } else { retval += "Was expecting one of:" + eol + " "; } retval += expected; return retval; } /** * getErrorInfo() was added to the parser generated code to provide clean * output instead of the standard format of Exception.toString(). It returns * a short description of the error that occurred as well as the position of * next token as part of the string. */ public String getErrorInfo() { if (!specialConstructor) { try { return super.getMessage() + " at column " + currentToken.next.beginColumn + "."; } catch (Exception e) { return super.getMessage(); } } String expected = ""; int maxSize = 0; for (int i = 0; i < expectedTokenSequences.length; i++) { if (maxSize < expectedTokenSequences[i].length) { maxSize = expectedTokenSequences[i].length; } for (int j = 0; j < expectedTokenSequences[i].length; j++) { expected += tokenImage[expectedTokenSequences[i][j]] + " "; } if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { expected += "..."; } expected += eol + " "; } String retval = "Unexpected \""; Token tok = currentToken.next; for (int i = 0; i < maxSize; i++) { if (i != 0) retval += " "; if (tok.kind == 0) { retval += tokenImage[0]; break; } retval += add_escapes(tok.image); tok = tok.next; } retval += "\" at column " + currentToken.next.beginColumn + "."; return retval; } /** * The end of line string for this machine. */ protected String eol = System.getProperty("line.separator", "\n"); /** * Used to convert raw characters to their escaped version * when these raw version cannot be used as part of an ASCII * string literal. */ protected String add_escapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/FunctionTable.java0000644000000000000000000000307210615400352021657 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep; import java.util.Hashtable; import org.nfunk.jep.function.PostfixMathCommandI; /* * A Hashtable which holds a list of functions. */ public class FunctionTable extends Hashtable { private static final long serialVersionUID = -1192898221311853572L; public FunctionTable() { } /** adds the PostfixMathCommandI for the function with name s. * RJM addition Oct 03 */ public Object put(String s,PostfixMathCommandI pfmc) { return super.put(s,pfmc); } /** overrides the standard hashtable method. * If the arguments are of the wrong type then throws * ClassCastException * RJM addition Oct 03 * TODO is Hashtable always index by Strings? */ public Object put(Object o,Object p) { return put((String) o,(PostfixMathCommandI) p); } /** returns the PostfixMathCommandI for function with name s. * RJM addition Oct 03 */ public PostfixMathCommandI get(String s) { return (PostfixMathCommandI) super.get(s); } /** overrides the standard hashtable method. * If the argument is of the wrong type (i.e. not a String) * then throws ClassCastException * RJM addition Oct 03 */ public Object get(Object o) { return get((String) o); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/EvaluatorI.java0000644000000000000000000000205610615400352021176 0ustar rootroot/* @author rich * Created on 22-Apr-2005 * * See LICENSE.txt for license information. */ package org.nfunk.jep; /** * @author Rich Morris * Created on 22-Apr-2005 */ public interface EvaluatorI { /* * The following methods was used to facilitate * using visitors which implemented a interface * which sub-classed ParserVisitor. * * If sub-classed to extend to implement a different visitor * this method should be overwritten to ensure the correct * accept method is called. * This method simply calls the jjtAccept(ParserVisitor this,Object data) of node. * * We no longer need this as we use ParserVisitor everywhere, * but kept for future reference. * private Object nodeAccept(Node node, Object data) throws ParseException { return node.jjtAccept(this,data); } */ /** * Evaluates a node and returns and object with the value of the node. * * @throws ParseException if errors occur during evaluation; */ public abstract Object eval(Node node) throws ParseException; } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ASTVarNode.java0000644000000000000000000000253710615400352021035 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. ASTVarNode.java */ package org.nfunk.jep; /** * Variable Node */ public class ASTVarNode extends SimpleNode { //private String varName; private Variable var; public ASTVarNode(int id) { super(id); var = null; } public ASTVarNode(Parser p, int id) { super(p, id); } /** * Accept the visitor. */ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException { return visitor.visit(this, data); } /** * Sets the name of the variable. */ //public void setName(String varName_in) //{ // var = varName_in; //} public void setVar(Variable variable) { var = variable; } public Variable getVar() { return var; } /** * Returns the name of the variable. */ public String getName() { return var.getName(); } /** * Creates a string containing the variable's name and value */ public String toString() { String temp = "Variable: \"" + getName() + "\""; return temp; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ParserDumpVisitor.java0000644000000000000000000000437310615400352022571 0ustar rootroot/** * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * * Use of this file and the system it is part of is constrained by the * file COPYRIGHT in the root directory of this system. * */ /* This is an example of how the Visitor pattern might be used to implement the dumping code that comes with SimpleNode. It's a bit long-winded, but it does illustrate a couple of the main points. 1) the visitor can maintain state between the nodes that it visits (for example the current indentation level). 2) if you don't implement a jjtAccept() method for a subclass of SimpleNode, then SimpleNode's acceptor will get called. 3) the utility method childrenAccept() can be useful when implementing preorder or postorder tree walks. Err, that's it. */ package org.nfunk.jep; public class ParserDumpVisitor implements ParserVisitor { private int indent = 0; private String indentString() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < indent; ++i) { sb.append(" "); } return sb.toString(); } public Object visit(SimpleNode node, Object data) throws ParseException { System.out.println(indentString() + node + ": acceptor not unimplemented in subclass?"); ++indent; data = node.childrenAccept(this, data); --indent; return data; } public Object visit(ASTStart node, Object data) throws ParseException { System.out.println(indentString() + node); ++indent; data = node.childrenAccept(this, data); --indent; return data; } public Object visit(ASTFunNode node, Object data) throws ParseException { System.out.println(indentString() + node); ++indent; data = node.childrenAccept(this, data); --indent; return data; } public Object visit(ASTVarNode node, Object data) throws ParseException { System.out.println(indentString() + node); ++indent; data = node.childrenAccept(this, data); --indent; return data; } public Object visit(ASTConstant node, Object data) throws ParseException { System.out.println(indentString() + node); ++indent; data = node.childrenAccept(this, data); --indent; return data; } } /*end*/ jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/TokenMgrError.java0000644000000000000000000001036110615400352021661 0ustar rootroot/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ package org.nfunk.jep; public class TokenMgrError extends Error { /* * Ordinals for various reasons why an Error of this type can be thrown. */ /** * Lexical error occured. */ static final int LEXICAL_ERROR = 0; /** * An attempt wass made to create a second instance of a static token manager. */ static final int STATIC_LEXER_ERROR = 1; /** * Tried to change to an invalid lexical state. */ static final int INVALID_LEXICAL_STATE = 2; /** * Detected (and bailed out of) an infinite loop in the token manager. */ static final int LOOP_DETECTED = 3; /** * Indicates the reason why the exception is thrown. It will have * one of the above 4 values. */ int errorCode; /** * Replaces unprintable characters by their espaced (or unicode escaped) * equivalents in the given string */ protected static final String addEscapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } /** * Returns a detailed message for the Error when it is thrown by the * token manager to indicate a lexical error. * Parameters : * EOFSeen : indicates if EOF caused the lexicl error * curLexState : lexical state in which this error occured * errorLine : line number when the error occured * errorColumn : column number when the error occured * errorAfter : prefix that was seen before this error occured * curchar : the offending character * Note: You can customize the lexical error message by modifying this method. */ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { return("Lexical error at line " + errorLine + ", column " + errorColumn + ". Encountered: " + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + "after : \"" + addEscapes(errorAfter) + "\""); } /** * You can also modify the body of this method to customize your error messages. * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not * of end-users concern, so you can return something like : * * "Internal Error : Please file a bug report .... " * * from this method for such cases in the release version of your parser. */ public String getMessage() { return super.getMessage(); } /* * Constructors of various flavors follow. */ public TokenMgrError() { } public TokenMgrError(String message, int reason) { super(message); errorCode = reason; } public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Operator.java0000644000000000000000000000341410615400352020715 0ustar rootroot/* @author rich * Created on 03-Aug-2003 */ package org.nfunk.jep; import org.nfunk.jep.function.PostfixMathCommandI; /** * A class containing information about an operator. * * @see OperatorSet * @author Rich Morris * Created on 19-Oct-2003 */ public class Operator { /** A unique name defining the operator. */ private String name; /** The symbol for the operator, used for printing. */ private String symbol; /** Postfix mathcommand */ private PostfixMathCommandI pfmc; /** private default constructor, prevents calling with no arguments. */ private Operator() { } /** construct a new operator. * * @param name printable name of operator * @param pfmc postfix math command for opperator */ public Operator(String name,PostfixMathCommandI pfmc) { this(); this.name = name; this.pfmc = pfmc; this.symbol = name; } /** construct a new operator, with a different name and symbol * * @param name name of operator, must be unique, used when describing operator * @param symbol printable name of operator, used for printing equations * @param pfmc postfix math command for opperator */ public Operator(String name,String symbol,PostfixMathCommandI pfmc) { this(); this.name = name; this.pfmc = pfmc; this.symbol = symbol; } /** returns the symbol used by this operator. */ public final String getSymbol() {return symbol;} /** returns a unique name definig this operator. */ public final String getName() {return name;} public final PostfixMathCommandI getPFMC() { return pfmc;} public final void setPFMC(PostfixMathCommandI pfmc) { this.pfmc = pfmc;} /** returns a verbose representation of the operator. **/ public String toString() { return "Operator: \""+name+"\""; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/type/0000755000000000000000000000000010615400352017236 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/type/DoubleNumberFactory.java0000644000000000000000000000342710615400352024022 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.type; import org.nfunk.jep.ParseException; /** * Default class for creating number objects. This class can be replaced by * other NumberFactory implementations if other number types are required. This * can be done using the */ public class DoubleNumberFactory implements NumberFactory { public static Double ZERO = new Double(0.0); public static Double ONE = new Double(1.0); public static Double TWO = new Double(2.0); public static Double MINUSONE = new Double(-1.0); /** * Creates a Double object initialized to the value of the parameter. * * @param value The initialization value for the returned object. */ public Object createNumber(String value) { return new Double(value); } public Object createNumber(double value) { return new Double(value); } public Object createNumber(Number value) { return value; } public Object createNumber(boolean value) { return (value?ONE:ZERO); } public Object createNumber(float value) {return new Double(value); } public Object createNumber(int value) {return new Double(value); } public Object createNumber(short value) {return new Double(value); } public Object createNumber(Complex value) throws ParseException { throw new ParseException("Cannot create a number from a Complex value"); } public Object getMinusOne() {return MINUSONE;} public Object getOne() {return ONE;} public Object getTwo() {return TWO;} public Object getZero() {return ZERO;} } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/type/Complex.java0000644000000000000000000005062410615400352021517 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.type; import java.text.NumberFormat; /** * Represents a complex number with double precision real and imaginary * components. Includes complex arithmetic functions.

    * The two main sources of reference used for creating this class were:
    * - "Numerical Recipes in C - The Art of Scientific Computing" * (ISBN 0-521-43108-5) http://www.nr.com and
    * - The org.netlib.math.complex package (http://www.netlib.org) which was * developed by Sandy Anderson and Priyantha Jayanetti (published under * GPL).

    * Some of the arithmetic functions in this class are based on the mathematical * equations given in the source of the netlib package. The functions were * validated by comparing results with the netlib complex class.

    * It is important to note that the netlib complex package is more * extensive and efficient (e.g. Garbage collector friendly) than this * implementation. If high precision and efficiency if of necessity it is * recommended to use the netlib package. * * @author Nathan Funk * @version 2.3.0 alpha now extends Number, has add and sub methods. * @version 2.3.0 beta 1 now overrides equals and hashCode. /* @version 2.3.0 beta 2 does not implement Number anymore, as caused too many problems. */ public class Complex { /** the real component */ private double re; /** the imaginary component */ private double im; //------------------------------------------------------------------------ // Constructors /** * Default constructor. */ public Complex() { re = 0; im = 0; } /** * Constructor from a single double value. The complex number is * initialized with the real component equal to the parameter, and * the imaginary component equal to zero. */ public Complex(double re_in) { re = re_in; im = 0; } /** * Construct from a Number. This constructor uses the doubleValue() * method of the parameter to initialize the real component of the * complex number. The imaginary component is initialized to zero. */ public Complex(Number re_in) { re = re_in.doubleValue(); im = 0; } /** * Copy constructor */ public Complex(Complex z) { re = z.re; im = z.im; } /** * Initialize the real and imaginary components to the values given * by the parameters. */ public Complex(double re_in, double im_in) { re = re_in; im = im_in; } /** * Returns the real component of this object */ public double re() { return re; } /** * Returns the imaginary component of this object */ public double im() { return im; } /** * Copies the values from the parameter object to this object */ public void set(Complex z) { re = z.re; im = z.im; } /** * Sets the real and imaginary values of the object. */ public void set(double re_in, double im_in) { re = re_in; im = im_in; } /** * Sets the real component of the object */ public void setRe(double re_in) { re = re_in; } /** * Sets the imaginary component of the object */ public void setIm(double im_in) { im = im_in; } //------------------------------------------------------------------------ // Various functions /** * Compares this object with the Complex number given as parameter *

    b
    . The
    tolerance
    parameter is the radius * within which the
    b
    number must lie for the two * complex numbers to be considered equal. * * @return
    true
    if the complex number are considered equal, *
    false
    otherwise. */ public boolean equals(Complex b, double tolerance) { double temp1 = (re - b.re); double temp2 = (im - b.im); return (temp1*temp1 + temp2*temp2) <= tolerance*tolerance; } /** * Compares this object against the specified object. * The result is true if and only if the argument is not null * and is a Complex object that represents the same complex number. * Equality follows the same pattern as Double aplies to each field: *
      *
    • If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false. *
    • If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true. *
    * This definition allows hash tables to operate properly. * @since 2.3.0.2 */ public boolean equals(Object o) { if(!(o instanceof Complex)) return false; Complex c = (Complex) o; return(Double.doubleToLongBits(this.re) == Double.doubleToLongBits(c.re) && Double.doubleToLongBits(this.im) == Double.doubleToLongBits(c.im)); } /** * Always override hashCode when you override equals. * Efective Java, Joshua Bloch, Sun Press */ public int hashCode() { int result = 17; long xl = Double.doubleToLongBits(this.re); long yl = Double.doubleToLongBits(this.im); int xi = (int)(xl^(xl>>32)); int yi = (int)(yl^(yl>>32)); result = 37*result+xi; result = 37*result+yi; return result; } /** * Returns the value of this complex number as a string in the format: *
    (real, imaginary)
    . */ public String toString() { return "(" + re + ", " + im + ")"; } public String toString(NumberFormat format) { return "(" + format.format(re) +", "+format.format(im)+")"; } /** Prints using specified number format in format or "2" or "3 i" * or "(2+3 i)" if flag is true * or "2+3 i" if flag is false */ public String toString(NumberFormat format,boolean flag) { if(im == 0.0) return format.format(re); else if(re == 0.0) return format.format(im)+" i)"; else if(flag) return "(" + format.format(re) +"+"+format.format(im)+" i)"; else return format.format(re) +"+"+format.format(im)+" i"; } /** * Returns true if either the real or imaginary component of this * Complex is an infinite value. * *

    * @return true if either component of the Complex object is infinite; false, otherwise. *

    **/ public boolean isInfinite() { return (Double.isInfinite(re) || Double.isInfinite(im)); } /** * Returns true if either the real or imaginary component of this * Complex is a Not-a-Number (NaN) value. * *

    * @return true if either component of the Complex object is NaN; false, otherwise. *

    **/ public boolean isNaN() { return (Double.isNaN(re) || Double.isNaN(im)); } /** * Returns the absolute value of the complex number. *

    * Adapted from Numerical Recipes in C - * The Art of Scientific Computing
    * ISBN 0-521-43108-5 */ public double abs() { double absRe = Math.abs(re); double absIm = Math.abs(im); if (absRe == 0 && absIm == 0) { return 0; } else if (absRe>absIm) { double temp = absIm/absRe; return absRe*Math.sqrt(1 + temp*temp); } else { double temp = absRe/absIm; return absIm*Math.sqrt(1 + temp*temp); } } /** * Returns the square of the absolute value (re*re+im*im). */ public double abs2() { return re*re+im*im; } /** * Returns the argument of this complex number (Math.atan2(re,im)) */ public double arg() { return Math.atan2(im,re); } /** * Returns the negative value of this complex number. */ public Complex neg() { return new Complex(-re,-im); } /** * Multiply the complex number with a double value. * @return The result of the multiplication */ public Complex mul(double b) { return new Complex(re*b, im*b); } /** * Adds the complex number with another complex value. * @return The result of the addition * @since 2.3.0.1 */ public Complex add(Complex b) { return new Complex(re+b.re,im+b.im); } /** * Adds the complex number with another complex value. * @return The result of the addition * @since 2.3.0.1 */ public Complex sub(Complex b) { return new Complex(re-b.re,im-b.im); } /** * Multiply the complex number with another complex value. * @return The result of the multiplication */ public Complex mul(Complex b) { return new Complex(re*b.re - im*b.im, im*b.re + re*b.im); } /** * Returns the result of dividing this complex number by the parameter. */ public Complex div(Complex b) { // Adapted from Numerical Recipes in C - The Art of Scientific Computing // ISBN 0-521-43108-5 double resRe, resIm; double r, den; if (Math.abs(b.re) >= Math.abs(b.im)) { r = b.im/b.re; den = b.re + r*b.im; resRe = (re+r*im)/den; resIm = (im-r*re)/den; } else { r = b.re/b.im; den = b.im + r*b.re; resRe = (re*r+im)/den; resIm = (im*r-re)/den; } return new Complex(resRe, resIm); } /** * Returns the value of this complex number raised to the power * of a real component (in double precision).

    * This method considers special cases where a simpler algorithm * would return "ugly" results.
    * For example when the expression (-1e40)^0.5 is evaluated without * considering the special case, the argument of the base is the * double number closest to pi. When sin and cos are used for the * final evaluation of the result, the slight difference of the * argument from pi causes a non-zero value for the real component * of the result. Because the value of the base is so high, the error * is magnified.Although the error is normal for floating * point calculations, the consideration of commonly occuring special * cases improves the accuracy and aesthetics of the results.

    * If you know a more elegant way to solve this problem, please let * me know at nathanfunk@hotmail.com . */ public Complex power(double exponent) { // z^exp = abs(z)^exp * (cos(exp*arg(z)) + i*sin(exp*arg(z))) double scalar = Math.pow(abs(),exponent); boolean specialCase = false; int factor = 0; // consider special cases to avoid floating point errors // for power expressions such as (-1e20)^2 if (im==0 && re<0) {specialCase = true; factor = 2;} if (re==0 && im>0) {specialCase = true; factor = 1;} if (re==0 && im<0) {specialCase = true; factor = -1;} if (specialCase && factor*exponent == (int)(factor*exponent)) { short[] cSin = {0,1,0,-1}; //sin of 0, pi/2, pi, 3pi/2 short[] cCos = {1,0,-1,0}; //cos of 0, pi/2, pi, 3pi/2 int x = ((int)(factor*exponent))%4; if (x<0) x = 4+x; return new Complex(scalar*cCos[x], scalar*cSin[x]); } double temp = exponent * arg(); return new Complex(scalar*Math.cos(temp), scalar*Math.sin(temp)); } /** * Returns the value of this complex number raised to the power of * a complex exponent */ public Complex power(Complex exponent) { if (exponent.im == 0) return power(exponent.re); double temp1Re = Math.log(abs()); double temp1Im = arg(); double temp2Re = (temp1Re*exponent.re) - (temp1Im*exponent.im); double temp2Im = (temp1Re*exponent.im) + (temp1Im*exponent.re); double scalar = Math.exp(temp2Re); return new Complex(scalar*Math.cos(temp2Im), scalar*Math.sin(temp2Im)); } /** Returns the complex conjugate. */ public Complex conj() { return new Complex(re,-im); } /** * Returns the logarithm of this complex number. */ public Complex log() { return new Complex(Math.log(abs()), arg()); } /** * Calculates the square root of this object. * Adapted from Numerical Recipes in C - The Art of Scientific Computing * (ISBN 0-521-43108-5) */ public Complex sqrt() { Complex c; double absRe,absIm,w,r; if (re == 0 && im == 0) { c = new Complex(0,0); } else { absRe = Math.abs(re); absIm = Math.abs(im); if (absRe>=absIm) { r = absIm/absRe; w = Math.sqrt(absRe)*Math.sqrt(0.5*(1.0+Math.sqrt(1.0+r*r))); } else { r = absRe/absIm; w = Math.sqrt(absIm)*Math.sqrt(0.5*(r +Math.sqrt(1.0+r*r))); } if (re>=0) { c = new Complex(w, im/(2.0*w)); } else { if (im<0) w = -w; c = new Complex(im/(2.0*w), w); } } return c; } //------------------------------------------------------------------------ // Trigonometric functions /** * Returns the sine of this complex number. */ public Complex sin() { double izRe, izIm; double temp1Re, temp1Im; double temp2Re, temp2Im; double scalar; // sin(z) = ( exp(i*z) - exp(-i*z) ) / (2*i) izRe = -im; izIm = re; // first exp scalar = Math.exp(izRe); temp1Re = scalar * Math.cos(izIm); temp1Im = scalar * Math.sin(izIm); // second exp scalar = Math.exp(-izRe); temp2Re = scalar * Math.cos(-izIm); temp2Im = scalar * Math.sin(-izIm); temp1Re -= temp2Re; temp1Im -= temp2Im; return new Complex(0.5*temp1Im, -0.5*temp1Re); } /** * Returns the cosine of this complex number. */ public Complex cos() { double izRe, izIm; double temp1Re, temp1Im; double temp2Re, temp2Im; double scalar; // cos(z) = ( exp(i*z) + exp(-i*z) ) / 2 izRe = -im; izIm = re; // first exp scalar = Math.exp(izRe); temp1Re = scalar * Math.cos(izIm); temp1Im = scalar * Math.sin(izIm); // second exp scalar = Math.exp(-izRe); temp2Re = scalar * Math.cos(-izIm); temp2Im = scalar * Math.sin(-izIm); temp1Re += temp2Re; temp1Im += temp2Im; return new Complex(0.5*temp1Re, 0.5*temp1Im); } /** * Returns the tangent of this complex number. */ public Complex tan() { // tan(z) = sin(z)/cos(z) double izRe, izIm; double temp1Re, temp1Im; double temp2Re, temp2Im; double scalar; Complex sinResult, cosResult; // sin(z) = ( exp(i*z) - exp(-i*z) ) / (2*i) izRe = -im; izIm = re; // first exp scalar = Math.exp(izRe); temp1Re = scalar * Math.cos(izIm); temp1Im = scalar * Math.sin(izIm); // second exp scalar = Math.exp(-izRe); temp2Re = scalar * Math.cos(-izIm); temp2Im = scalar * Math.sin(-izIm); temp1Re -= temp2Re; temp1Im -= temp2Im; sinResult = new Complex(0.5*temp1Re, 0.5*temp1Im); // cos(z) = ( exp(i*z) + exp(-i*z) ) / 2 izRe = -im; izIm = re; // first exp scalar = Math.exp(izRe); temp1Re = scalar * Math.cos(izIm); temp1Im = scalar * Math.sin(izIm); // second exp scalar = Math.exp(-izRe); temp2Re = scalar * Math.cos(-izIm); temp2Im = scalar * Math.sin(-izIm); temp1Re += temp2Re; temp1Im += temp2Im; cosResult = new Complex(0.5*temp1Re, 0.5*temp1Im); return sinResult.div(cosResult); } //------------------------------------------------------------------------ // Inverse trigonometric functions public Complex asin() { Complex result; double tempRe, tempIm; // asin(z) = -i * log(i*z + sqrt(1 - z*z)) tempRe = 1.0 - ( (re*re) - (im*im) ); tempIm = 0.0 - ( (re*im) + (im*re) ); result = new Complex(tempRe, tempIm); result = result.sqrt(); result.re += -im; result.im += re; tempRe = Math.log(result.abs()); tempIm = result.arg(); result.re = tempIm; result.im = - tempRe; return result; } public Complex acos() { Complex result; double tempRe, tempIm; // acos(z) = -i * log( z + i * sqrt(1 - z*z) ) tempRe = 1.0 - ( (re*re) - (im*im) ); tempIm = 0.0 - ( (re*im) + (im*re) ); result = new Complex(tempRe, tempIm); result = result.sqrt(); tempRe = -result.im; tempIm = result.re; result.re = re + tempRe; result.im = im + tempIm; tempRe = Math.log(result.abs()); tempIm = result.arg(); result.re = tempIm; result.im = - tempRe; return result; } public Complex atan() { // atan(z) = -i/2 * log((i-z)/(i+z)) double tempRe, tempIm; Complex result = new Complex(-re, 1.0 - im); tempRe = re; tempIm = 1.0 + im; result = result.div(new Complex(tempRe, tempIm)); tempRe = Math.log(result.abs()); tempIm = result.arg(); result.re = 0.5*tempIm; result.im = -0.5*tempRe; return result; } //------------------------------------------------------------------------ // Hyperbolic trigonometric functions public Complex sinh() { double scalar; double temp1Re, temp1Im; double temp2Re, temp2Im; // sinh(z) = ( exp(z) - exp(-z) ) / 2 // first exp scalar = Math.exp(re); temp1Re = scalar * Math.cos(im); temp1Im = scalar * Math.sin(im); // second exp scalar = Math.exp(-re); temp2Re = scalar * Math.cos(-im); temp2Im = scalar * Math.sin(-im); temp1Re -= temp2Re; temp1Im -= temp2Im; return new Complex(0.5*temp1Re, 0.5*temp1Im); } public Complex cosh() { double scalar; double temp1Re, temp1Im; double temp2Re, temp2Im; // cosh(z) = ( exp(z) + exp(-z) ) / 2 // first exp scalar = Math.exp(re); temp1Re = scalar * Math.cos(im); temp1Im = scalar * Math.sin(im); // second exp scalar = Math.exp(-re); temp2Re = scalar * Math.cos(-im); temp2Im = scalar * Math.sin(-im); temp1Re += temp2Re; temp1Im += temp2Im; return new Complex(0.5*temp1Re, 0.5*temp1Im); } public Complex tanh() { double scalar; double temp1Re, temp1Im; double temp2Re, temp2Im; Complex sinRes, cosRes; // tanh(z) = sinh(z) / cosh(z) scalar = Math.exp(re); temp1Re = scalar * Math.cos(im); temp1Im = scalar * Math.sin(im); scalar = Math.exp(-re); temp2Re = scalar * Math.cos(-im); temp2Im = scalar * Math.sin(-im); temp1Re -= temp2Re; temp1Im -= temp2Im; sinRes = new Complex(0.5*temp1Re, 0.5*temp1Im); scalar = Math.exp(re); temp1Re = scalar * Math.cos(im); temp1Im = scalar * Math.sin(im); scalar = Math.exp(-re); temp2Re = scalar * Math.cos(-im); temp2Im = scalar * Math.sin(-im); temp1Re += temp2Re; temp1Im += temp2Im; cosRes = new Complex(0.5*temp1Re, 0.5*temp1Im); return sinRes.div(cosRes); } //------------------------------------------------------------------------ // Inverse hyperbolic trigonometric functions public Complex asinh() { Complex result; // asinh(z) = log(z + sqrt(z*z + 1)) result = new Complex( ((re*re) - (im*im)) + 1, (re*im) + (im*re)); result = result.sqrt(); result.re += re; result.im += im; double temp = result.arg(); result.re = Math.log(result.abs()); result.im = temp; return result; } public Complex acosh() { Complex result; // acosh(z) = log(z + sqrt(z*z - 1)) result = new Complex( ((re*re) - (im*im)) - 1, (re*im) + (im*re)); result = result.sqrt(); result.re += re; result.im += im; double temp = result.arg(); result.re = Math.log(result.abs()); result.im = temp; return result; } public Complex atanh() { // atanh(z) = 1/2 * log( (1+z)/(1-z) ) double tempRe, tempIm; Complex result = new Complex(1.0 + re, im); tempRe = 1.0 - re; tempIm = - im; result = result.div(new Complex(tempRe, tempIm)); tempRe = Math.log(result.abs()); tempIm = result.arg(); result.re = 0.5*tempRe; result.im = 0.5*tempIm; return result; } /** * Converts an [r,theta] pair to a complex number r * e^(i theta). * @param r The radius * @param theta The angle * @return The complex result. * @since 2.3.0.1 */ public static Complex polarValueOf(Number r,Number theta) { double rad = r.doubleValue(); double ang = theta.doubleValue(); return new Complex(rad*Math.cos(ang), rad*Math.sin(ang)); } /** Returns real part. * @since 2.3.0.1 */ public double doubleValue() { return re; } /** Returns real part. * @since 2.3.0.1 */ public float floatValue() { return (float) re; } /** Returns real part. * @since 2.3.0.1 */ public int intValue() { return (int) re; } /** Returns real part. * @since 2.3.0.1 */ public long longValue() { return (long) re; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/type/package.html0000644000000000000000000000010610615400352021514 0ustar rootroot Provides number factories and special type classes. jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/type/NumberFactory.java0000644000000000000000000000413110615400352022660 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.type; import org.nfunk.jep.ParseException; /** * This interface can be implemented to create numbers of any object type. * By implementing this interface and calling the setNumberFactory() method of * the JEP class, the constants in an expression will be created with that * class. */ public interface NumberFactory { /** * Creates a number object and initializes its value. * @param value The initial value of the number as a string. */ public Object createNumber(String value) throws ParseException; /** Creates a number object with given double value. */ public Object createNumber(double value) throws ParseException; /** Create a number object with given int value */ public Object createNumber(int value) throws ParseException; /** Create a number object with given short value */ public Object createNumber(short value) throws ParseException; /** Create a number object with given float value */ public Object createNumber(float value) throws ParseException; /** Create a number object with given boolean value */ public Object createNumber(boolean value) throws ParseException; /** Creates a number object from a class implementing Number, * May actually just return the class. */ public Object createNumber(Number value) throws ParseException; /** Create a number object with given Complex value */ public Object createNumber(Complex value) throws ParseException; /** Return an object representing ZERO the additive identity. */ public Object getZero(); /** Return an object representing ONE the multiplicative identity. */ public Object getOne(); /** Return an object representing ZERO-ONE. */ public Object getMinusOne(); /** Return an object representing ONE+ONE. */ public Object getTwo(); } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ASTStart.java0000644000000000000000000000140010615400352020560 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. ASTStart.java */ package org.nfunk.jep; /** * Start Node */ public class ASTStart extends SimpleNode { public ASTStart(int id) { super(id); } public ASTStart(Parser p, int id) { super(p, id); } /** Accept the visitor. **/ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException { return visitor.visit(this, data); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Parser.java0000644000000000000000000016560210615400352020366 0ustar rootroot/* Generated By:JJTree&JavaCC: Do not edit this line. Parser.java */ package org.nfunk.jep; import java.util.Vector; import org.nfunk.jep.function.*; import org.nfunk.jep.type.*; public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants, ParserConstants {/*@bgen(jjtree)*/ protected JJTParserState jjtree = new JJTParserState();private JEP jep; private SymbolTable symTab; private OperatorSet opSet; private int initialTokenManagerState = DEFAULT; public Node parseStream(java.io.Reader stream, JEP jep_in) throws ParseException { restart(stream,jep_in); // Parse the expression, and return the enable_tracing(); Node node = Start(); if (node == null) throw new ParseException("No expression entered"); return node.jjtGetChild(0); } /** * Restart the parse with the given stream. * @since 2.3.0 beta 1 */ public void restart(java.io.Reader stream, JEP jep_in) { ReInit(stream); this.token_source.SwitchTo(initialTokenManagerState); jep = jep_in; symTab = jep.getSymbolTable(); opSet = jep.getOperatorSet(); } /** * Continue parsing without re-initilising stream. * Allows renetrancy of parser so that strings like * "x=1; y=2; z=3;" can be parsed. * When a semi colon is encountered parsing finishes leaving the rest of the string unparsed. * Parsing can be resumed from the current position by using this method. * For example *

    	 * XJep j = new XJep();
    	 * Parser parse = j.getParse();
    	 * StringReader sr = new StringReader("x=1; y=2; z=3;");
    	 * parse.restart(sr,j);
    	 * Node node;
    	 * try {
    	 * while((node = j.continueParse())!=null) {
    	 *    j.println(node);
    	 * } }catch(ParseException e) {}
    	 * 
    */ public Node continueParse() throws ParseException { ASTStart node = Start(); if (node==null) return null; return node.jjtGetChild(0); } private void addToErrorList(String errorStr) { jep.errorList.addElement(errorStr); } /** * Sets the initial state that the token manager is in. * Can be used to change how x.x is interpreted, either as a single * identifier (DEFAULT) or as x x (NO_DOT_IN_IDENTIFIERS) * @param state the state to be in. Currently the only legal values are DEFAULT and NO_DOT_IN_IDENTIFIER */ public void setInitialTokenManagerState(int state) { initialTokenManagerState = state; } /** * Translate all escape sequences to characters. Inspired by Rob Millar's * unescape() method in rcm.util.Str fron the Web Sphinx project. * * @param inputStr String containing escape characters. * @return String with all escape sequences replaced. */ private String replaceEscape(String inputStr) { int len = inputStr.length(); int p = 0; int i; String metachars = "tnrbf\\\"'"; String chars = "\t\n\r\b\f\\\"'"; StringBuffer output = new StringBuffer(); while ((i = inputStr.indexOf('\\', p)) != -1) { output.append(inputStr.substring(p, i)); if (i+1 == len) break; // find metacharacter char metac = inputStr.charAt(i+1); // find the index of the metac int k = metachars.indexOf(metac); if (k == -1) { // didn't find the metachar, leave sequence as found. // This code should be unreachable if the parser // is functioning properly because strings containing // unknown escape characters should not be accepted. output.append('\\'); output.append(metac); } else { // its corresponding true char output.append(chars.charAt(k)); } // skip over both escape character & metacharacter p = i + 2; } // add the end of the input string to the output if (p < len) output.append(inputStr.substring(p)); return output.toString(); } /*************************************************************** GRAMMAR START ***************************************************************/ final public ASTStart Start() throws ParseException { /*@bgen(jjtree) Start */ ASTStart jjtn000 = new ASTStart(JJTSTART); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000); try { if (jj_2_1(1)) { Expression(); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 0: jj_consume_token(0); break; case SEMI: jj_consume_token(SEMI); break; default: jj_la1[0] = jj_gen; jj_consume_token(-1); throw new ParseException(); } jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; {if (true) return jjtn000;} } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 0: case SEMI: switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 0: jj_consume_token(0); break; case SEMI: jj_consume_token(SEMI); break; default: jj_la1[1] = jj_gen; jj_consume_token(-1); throw new ParseException(); } jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; // njf - The next line is commented out in 2.3.0 since // two "No expression entered" errors are reported // in EvaluatorVisitor and Console (one from here // the other from ParseStream() ) // Decided to just return null, and handle the error // in ParseStream. // addToErrorList("No expression entered"); {if (true) return null;} break; default: jj_la1[2] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte000;} } if (jjte000 instanceof ParseException) { {if (true) throw (ParseException)jjte000;} } {if (true) throw (Error)jjte000;} } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } throw new Error("Missing return statement in function"); } // Expresions can be like // x=3 // x=y=3 parsed as x=(y=3) final public void Expression() throws ParseException { if (jj_2_2(2147483647)) { AssignExpression(); } else if (jj_2_3(1)) { RightExpression(); } else { jj_consume_token(-1); throw new ParseException(); } } final public void AssignExpression() throws ParseException { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { LValue(); jj_consume_token(ASSIGN); Expression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; if (!jep.getAllowAssignment()) {if (true) throw new ParseException( "Syntax Error (assignment not enabled)");} jjtn001.setOperator(opSet.getAssign()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } } final public void RightExpression() throws ParseException { OrExpression(); } final public void OrExpression() throws ParseException { AndExpression(); label_1: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case OR: ; break; default: jj_la1[3] = jj_gen; break label_1; } ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(OR); AndExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getOr()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } } } final public void AndExpression() throws ParseException { EqualExpression(); label_2: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case AND: ; break; default: jj_la1[4] = jj_gen; break label_2; } ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(AND); EqualExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getAnd()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } } } final public void EqualExpression() throws ParseException { RelationalExpression(); label_3: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case EQ: case NE: ; break; default: jj_la1[5] = jj_gen; break label_3; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NE: ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(NE); RelationalExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getNE()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } break; case EQ: ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); try { jj_consume_token(EQ); RelationalExpression(); jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; jjtn002.setOperator(opSet.getEQ()); } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte002;} } if (jjte002 instanceof ParseException) { {if (true) throw (ParseException)jjte002;} } {if (true) throw (Error)jjte002;} } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } break; default: jj_la1[6] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } final public void RelationalExpression() throws ParseException { AdditiveExpression(); label_4: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case GT: case LT: case LE: case GE: ; break; default: jj_la1[7] = jj_gen; break label_4; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case LT: ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(LT); AdditiveExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getLT()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } break; case GT: ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); try { jj_consume_token(GT); AdditiveExpression(); jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; jjtn002.setOperator(opSet.getGT()); } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte002;} } if (jjte002 instanceof ParseException) { {if (true) throw (ParseException)jjte002;} } {if (true) throw (Error)jjte002;} } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } break; case LE: ASTFunNode jjtn003 = new ASTFunNode(JJTFUNNODE); boolean jjtc003 = true; jjtree.openNodeScope(jjtn003); try { jj_consume_token(LE); AdditiveExpression(); jjtree.closeNodeScope(jjtn003, 2); jjtc003 = false; jjtn003.setOperator(opSet.getLE()); } catch (Throwable jjte003) { if (jjtc003) { jjtree.clearNodeScope(jjtn003); jjtc003 = false; } else { jjtree.popNode(); } if (jjte003 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte003;} } if (jjte003 instanceof ParseException) { {if (true) throw (ParseException)jjte003;} } {if (true) throw (Error)jjte003;} } finally { if (jjtc003) { jjtree.closeNodeScope(jjtn003, 2); } } break; case GE: ASTFunNode jjtn004 = new ASTFunNode(JJTFUNNODE); boolean jjtc004 = true; jjtree.openNodeScope(jjtn004); try { jj_consume_token(GE); AdditiveExpression(); jjtree.closeNodeScope(jjtn004, 2); jjtc004 = false; jjtn004.setOperator(opSet.getGE()); } catch (Throwable jjte004) { if (jjtc004) { jjtree.clearNodeScope(jjtn004); jjtc004 = false; } else { jjtree.popNode(); } if (jjte004 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte004;} } if (jjte004 instanceof ParseException) { {if (true) throw (ParseException)jjte004;} } {if (true) throw (Error)jjte004;} } finally { if (jjtc004) { jjtree.closeNodeScope(jjtn004, 2); } } break; default: jj_la1[8] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } final public void AdditiveExpression() throws ParseException { MultiplicativeExpression(); label_5: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case PLUS: case MINUS: ; break; default: jj_la1[9] = jj_gen; break label_5; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case PLUS: ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(PLUS); MultiplicativeExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getAdd()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } break; case MINUS: ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); try { jj_consume_token(MINUS); MultiplicativeExpression(); jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; jjtn002.setOperator(opSet.getSubtract()); } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte002;} } if (jjte002 instanceof ParseException) { {if (true) throw (ParseException)jjte002;} } {if (true) throw (Error)jjte002;} } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } break; default: jj_la1[10] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } final public void MultiplicativeExpression() throws ParseException { UnaryExpression(); label_6: while (true) { if (jj_2_4(1)) { ; } else { break label_6; } if (jj_2_5(1)) { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { PowerExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; if (!jep.implicitMul) {if (true) throw new ParseException( "Syntax Error (implicit multiplication not enabled)");} jjtn001.setOperator(opSet.getMultiply()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case MUL: ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); try { jj_consume_token(MUL); UnaryExpression(); jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; jjtn002.setOperator(opSet.getMultiply()); } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte002;} } if (jjte002 instanceof ParseException) { {if (true) throw (ParseException)jjte002;} } {if (true) throw (Error)jjte002;} } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } break; case DOT: ASTFunNode jjtn003 = new ASTFunNode(JJTFUNNODE); boolean jjtc003 = true; jjtree.openNodeScope(jjtn003); try { jj_consume_token(DOT); UnaryExpression(); jjtree.closeNodeScope(jjtn003, 2); jjtc003 = false; jjtn003.setOperator(opSet.getDot()); } catch (Throwable jjte003) { if (jjtc003) { jjtree.clearNodeScope(jjtn003); jjtc003 = false; } else { jjtree.popNode(); } if (jjte003 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte003;} } if (jjte003 instanceof ParseException) { {if (true) throw (ParseException)jjte003;} } {if (true) throw (Error)jjte003;} } finally { if (jjtc003) { jjtree.closeNodeScope(jjtn003, 2); } } break; case CROSS: ASTFunNode jjtn004 = new ASTFunNode(JJTFUNNODE); boolean jjtc004 = true; jjtree.openNodeScope(jjtn004); try { jj_consume_token(CROSS); UnaryExpression(); jjtree.closeNodeScope(jjtn004, 2); jjtc004 = false; jjtn004.setOperator(opSet.getCross()); } catch (Throwable jjte004) { if (jjtc004) { jjtree.clearNodeScope(jjtn004); jjtc004 = false; } else { jjtree.popNode(); } if (jjte004 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte004;} } if (jjte004 instanceof ParseException) { {if (true) throw (ParseException)jjte004;} } {if (true) throw (Error)jjte004;} } finally { if (jjtc004) { jjtree.closeNodeScope(jjtn004, 2); } } break; case DIV: ASTFunNode jjtn005 = new ASTFunNode(JJTFUNNODE); boolean jjtc005 = true; jjtree.openNodeScope(jjtn005); try { jj_consume_token(DIV); UnaryExpression(); jjtree.closeNodeScope(jjtn005, 2); jjtc005 = false; jjtn005.setOperator(opSet.getDivide()); } catch (Throwable jjte005) { if (jjtc005) { jjtree.clearNodeScope(jjtn005); jjtc005 = false; } else { jjtree.popNode(); } if (jjte005 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte005;} } if (jjte005 instanceof ParseException) { {if (true) throw (ParseException)jjte005;} } {if (true) throw (Error)jjte005;} } finally { if (jjtc005) { jjtree.closeNodeScope(jjtn005, 2); } } break; case MOD: ASTFunNode jjtn006 = new ASTFunNode(JJTFUNNODE); boolean jjtc006 = true; jjtree.openNodeScope(jjtn006); try { jj_consume_token(MOD); UnaryExpression(); jjtree.closeNodeScope(jjtn006, 2); jjtc006 = false; jjtn006.setOperator(opSet.getMod()); } catch (Throwable jjte006) { if (jjtc006) { jjtree.clearNodeScope(jjtn006); jjtc006 = false; } else { jjtree.popNode(); } if (jjte006 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte006;} } if (jjte006 instanceof ParseException) { {if (true) throw (ParseException)jjte006;} } {if (true) throw (Error)jjte006;} } finally { if (jjtc006) { jjtree.closeNodeScope(jjtn006, 2); } } break; default: jj_la1[11] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } } final public void UnaryExpression() throws ParseException { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case PLUS: jj_consume_token(PLUS); UnaryExpression(); break; case MINUS: ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(MINUS); UnaryExpression(); jjtree.closeNodeScope(jjtn001, 1); jjtc001 = false; jjtn001.setOperator(opSet.getUMinus()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 1); } } break; case NOT: ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); try { jj_consume_token(NOT); UnaryExpression(); jjtree.closeNodeScope(jjtn002, 1); jjtc002 = false; jjtn002.setOperator(opSet.getNot()); } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte002;} } if (jjte002 instanceof ParseException) { {if (true) throw (ParseException)jjte002;} } {if (true) throw (Error)jjte002;} } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 1); } } break; default: jj_la1[12] = jj_gen; if (jj_2_6(1)) { PowerExpression(); } else { jj_consume_token(-1); throw new ParseException(); } } } final public void PowerExpression() throws ParseException { UnaryExpressionNotPlusMinus(); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case POWER: ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jj_consume_token(POWER); UnaryExpression(); jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getPower()); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } break; default: jj_la1[13] = jj_gen; ; } } final public void UnaryExpressionNotPlusMinus() throws ParseException { String identString = ""; int type; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INTEGER_LITERAL: case FLOATING_POINT_LITERAL: case STRING_LITERAL: AnyConstant(); break; default: jj_la1[14] = jj_gen; if (jj_2_7(2147483647)) { ArrayAccess(); } else if ((getToken(1).kind == INDENTIFIER1 || getToken(1).kind == INDENTIFIER2) && jep.funTab.containsKey(getToken(1).image)) { Function(); } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INDENTIFIER1: case INDENTIFIER2: Variable(); break; case LRND: jj_consume_token(LRND); Expression(); jj_consume_token(RRND); break; case LSQ: ListExpression(); break; default: jj_la1[15] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } } final public void ListExpression() throws ParseException { /*@bgen(jjtree) FunNode */ ASTFunNode jjtn000 = new ASTFunNode(JJTFUNNODE); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);jjtn000.setOperator(opSet.getList()); try { jj_consume_token(LSQ); Expression(); label_7: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case COMMA: ; break; default: jj_la1[16] = jj_gen; break label_7; } jj_consume_token(COMMA); Expression(); } jj_consume_token(RSQ); } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte000;} } if (jjte000 instanceof ParseException) { {if (true) throw (ParseException)jjte000;} } {if (true) throw (Error)jjte000;} } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } } /* void RangeExpression() #FunNode: { jjtThis.setOperator(opSet.getRange()); } { Expression() ( Expression() )+ } */ final public void LValue() throws ParseException { if (jj_2_8(2147483647)) { ArrayAccess(); } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INDENTIFIER1: case INDENTIFIER2: Variable(); break; default: jj_la1[17] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } final public void ArrayAccess() throws ParseException { Variable(); ListExpression(); ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; jjtn001.setOperator(opSet.getElement()); } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } } final public void Variable() throws ParseException { String identString = ""; ASTVarNode jjtn001 = new ASTVarNode(JJTVARNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { identString = Identifier(); jjtree.closeNodeScope(jjtn001, true); jjtc001 = false; if (symTab.containsKey(identString)) { jjtn001.setVar(symTab.getVar(identString)); } else { if (jep.allowUndeclared) { jjtn001.setVar(symTab.makeVarIfNeeded(identString)); } else { addToErrorList("Unrecognized symbol \"" + identString +"\""); } } } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, true); } } } final public void Function() throws ParseException { int reqArguments = 0; String identString = ""; ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { identString = Identifier(); if (jep.funTab.containsKey(identString)) { //Set number of required arguments reqArguments = ((PostfixMathCommandI)jep.funTab.get(identString)).getNumberOfParameters(); jjtn001.setFunction(identString, (PostfixMathCommandI)jep.funTab.get(identString)); } else { addToErrorList("!!! Unrecognized function \"" + identString +"\""); } jj_consume_token(LRND); ArgumentList(reqArguments, identString); jj_consume_token(RRND); } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte001;} } if (jjte001 instanceof ParseException) { {if (true) throw (ParseException)jjte001;} } {if (true) throw (Error)jjte001;} } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, true); } } } final public void ArgumentList(int reqArguments, String functionName) throws ParseException { int count = 0; String errorStr = ""; if (jj_2_9(1)) { Expression(); count++; label_8: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case COMMA: ; break; default: jj_la1[18] = jj_gen; break label_8; } jj_consume_token(COMMA); Expression(); count++; } } else { ; } if(reqArguments == -1) { if(!((PostfixMathCommandI)jep.funTab.get(functionName)).checkNumberOfParameters(count)) { errorStr = "Function \"" + functionName +"\" illegal number of arguments " + count; addToErrorList(errorStr); } } else if (reqArguments != count) { errorStr = "Function \"" + functionName +"\" requires " + reqArguments + " parameter"; if (reqArguments!=1) errorStr += "s"; addToErrorList(errorStr); } } final public String Identifier() throws ParseException { Token t; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INDENTIFIER1: t = jj_consume_token(INDENTIFIER1); break; case INDENTIFIER2: t = jj_consume_token(INDENTIFIER2); break; default: jj_la1[19] = jj_gen; jj_consume_token(-1); throw new ParseException(); } {if (true) return t.image;} throw new Error("Missing return statement in function"); } final public void AnyConstant() throws ParseException { /*@bgen(jjtree) Constant */ ASTConstant jjtn000 = new ASTConstant(JJTCONSTANT); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);Token t; Object value; try { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case STRING_LITERAL: t = jj_consume_token(STRING_LITERAL); jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; // strip away double quotes at end of string String temp = (t.image).substring(1,t.image.length()-1); // replace escape characters temp = replaceEscape(temp); jjtn000.setValue(temp); break; case INTEGER_LITERAL: case FLOATING_POINT_LITERAL: value = RealConstant(); jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; jjtn000.setValue(value); // } // | // value = Array() { // jjtThis.setValue(value); break; default: jj_la1[20] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { {if (true) throw (RuntimeException)jjte000;} } if (jjte000 instanceof ParseException) { {if (true) throw (ParseException)jjte000;} } {if (true) throw (Error)jjte000;} } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } } /* Vector Array() : { Object value; Vector result = new Vector(); } { value = RealConstant() { result.addElement(value); } ( value = RealConstant() { result.addElement(value); } )* { return result; } } */ final public Object RealConstant() throws ParseException { Token t; Object value; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INTEGER_LITERAL: t = jj_consume_token(INTEGER_LITERAL); break; case FLOATING_POINT_LITERAL: t = jj_consume_token(FLOATING_POINT_LITERAL); break; default: jj_la1[21] = jj_gen; jj_consume_token(-1); throw new ParseException(); } try { value = jep.getNumberFactory().createNumber(t.image); } catch (Exception e) { value = null; addToErrorList("Can't parse \"" + t.image + "\""); } {if (true) return value;} throw new Error("Missing return statement in function"); } final private boolean jj_2_1(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_1(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(0, xla); } } final private boolean jj_2_2(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_2(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(1, xla); } } final private boolean jj_2_3(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_3(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(2, xla); } } final private boolean jj_2_4(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_4(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(3, xla); } } final private boolean jj_2_5(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_5(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(4, xla); } } final private boolean jj_2_6(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_6(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(5, xla); } } final private boolean jj_2_7(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_7(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(6, xla); } } final private boolean jj_2_8(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_8(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(7, xla); } } final private boolean jj_2_9(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_9(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(8, xla); } } final private boolean jj_3R_26() { if (jj_3R_10()) return true; if (jj_scan_token(ASSIGN)) return true; if (jj_3R_9()) return true; return false; } final private boolean jj_3R_59() { if (jj_scan_token(GE)) return true; if (jj_3R_42()) return true; return false; } final private boolean jj_3R_41() { if (jj_3R_43()) return true; return false; } final private boolean jj_3_6() { if (jj_3R_17()) return true; return false; } final private boolean jj_3_3() { if (jj_3R_11()) return true; return false; } final private boolean jj_3R_24() { if (jj_3R_34()) return true; return false; } final private boolean jj_3R_9() { Token xsp; xsp = jj_scanpos; if (jj_3R_19()) { jj_scanpos = xsp; if (jj_3_3()) return true; } return false; } final private boolean jj_3R_19() { if (jj_3R_26()) return true; return false; } final private boolean jj_3R_58() { if (jj_scan_token(LE)) return true; if (jj_3R_42()) return true; return false; } final private boolean jj_3R_50() { if (jj_scan_token(NOT)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_40() { if (jj_scan_token(STRING_LITERAL)) return true; return false; } final private boolean jj_3R_37() { Token xsp; xsp = jj_scanpos; if (jj_3R_40()) { jj_scanpos = xsp; if (jj_3R_41()) return true; } return false; } final private boolean jj_3R_57() { if (jj_scan_token(GT)) return true; if (jj_3R_42()) return true; return false; } final private boolean jj_3R_49() { if (jj_scan_token(MINUS)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3_8() { if (jj_3R_18()) return true; return false; } final private boolean jj_3R_21() { if (jj_3R_24()) return true; return false; } final private boolean jj_3R_48() { if (jj_scan_token(PLUS)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_46() { Token xsp; xsp = jj_scanpos; if (jj_3R_48()) { jj_scanpos = xsp; if (jj_3R_49()) { jj_scanpos = xsp; if (jj_3R_50()) { jj_scanpos = xsp; if (jj_3_6()) return true; } } } return false; } final private boolean jj_3R_18() { if (jj_3R_24()) return true; if (jj_3R_25()) return true; return false; } final private boolean jj_3R_56() { if (jj_scan_token(LT)) return true; if (jj_3R_42()) return true; return false; } final private boolean jj_3R_52() { Token xsp; xsp = jj_scanpos; if (jj_3R_56()) { jj_scanpos = xsp; if (jj_3R_57()) { jj_scanpos = xsp; if (jj_3R_58()) { jj_scanpos = xsp; if (jj_3R_59()) return true; } } } return false; } final private boolean jj_3R_35() { if (jj_scan_token(COMMA)) return true; if (jj_3R_9()) return true; return false; } final private boolean jj_3R_34() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(12)) { jj_scanpos = xsp; if (jj_scan_token(15)) return true; } return false; } final private boolean jj_3R_39() { if (jj_3R_42()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_52()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_10() { Token xsp; xsp = jj_scanpos; if (jj_3R_20()) { jj_scanpos = xsp; if (jj_3R_21()) return true; } return false; } final private boolean jj_3R_20() { if (jj_3R_18()) return true; return false; } final private boolean jj_3_1() { if (jj_3R_9()) return true; return false; } final private boolean jj_3R_16() { if (jj_scan_token(MOD)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_54() { if (jj_scan_token(EQ)) return true; if (jj_3R_39()) return true; return false; } final private boolean jj_3R_15() { if (jj_scan_token(DIV)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_53() { if (jj_scan_token(NE)) return true; if (jj_3R_39()) return true; return false; } final private boolean jj_3R_51() { Token xsp; xsp = jj_scanpos; if (jj_3R_53()) { jj_scanpos = xsp; if (jj_3R_54()) return true; } return false; } final private boolean jj_3R_14() { if (jj_scan_token(CROSS)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_36() { if (jj_3R_39()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_51()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_64() { if (jj_scan_token(COMMA)) return true; if (jj_3R_9()) return true; return false; } final private boolean jj_3R_25() { if (jj_scan_token(LSQ)) return true; if (jj_3R_9()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_35()) { jj_scanpos = xsp; break; } } if (jj_scan_token(RSQ)) return true; return false; } final private boolean jj_3R_13() { if (jj_scan_token(DOT)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_33() { if (jj_3R_25()) return true; return false; } final private boolean jj_3R_12() { if (jj_scan_token(MUL)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_47() { if (jj_scan_token(AND)) return true; if (jj_3R_36()) return true; return false; } final private boolean jj_3_9() { if (jj_3R_9()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_64()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_63() { Token xsp; xsp = jj_scanpos; if (jj_3_9()) jj_scanpos = xsp; return false; } final private boolean jj_3R_43() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) { jj_scanpos = xsp; if (jj_scan_token(9)) return true; } return false; } final private boolean jj_3_7() { if (jj_3R_18()) return true; return false; } final private boolean jj_3R_32() { if (jj_scan_token(LRND)) return true; if (jj_3R_9()) return true; if (jj_scan_token(RRND)) return true; return false; } final private boolean jj_3R_27() { if (jj_3R_36()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_47()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_31() { if (jj_3R_24()) return true; return false; } final private boolean jj_3_4() { Token xsp; xsp = jj_scanpos; if (jj_3_5()) { jj_scanpos = xsp; if (jj_3R_12()) { jj_scanpos = xsp; if (jj_3R_13()) { jj_scanpos = xsp; if (jj_3R_14()) { jj_scanpos = xsp; if (jj_3R_15()) { jj_scanpos = xsp; if (jj_3R_16()) return true; } } } } } return false; } final private boolean jj_3_5() { if (jj_3R_17()) return true; return false; } final private boolean jj_3R_30() { if (jj_3R_38()) return true; return false; } final private boolean jj_3R_29() { if (jj_3R_18()) return true; return false; } final private boolean jj_3R_44() { if (jj_3R_46()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3_4()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_23() { Token xsp; xsp = jj_scanpos; if (jj_3R_28()) { jj_scanpos = xsp; if (jj_3R_29()) { jj_scanpos = xsp; lookingAhead = true; jj_semLA = (getToken(1).kind == INDENTIFIER1 || getToken(1).kind == INDENTIFIER2) && jep.funTab.containsKey(getToken(1).image); lookingAhead = false; if (!jj_semLA || jj_3R_30()) { jj_scanpos = xsp; if (jj_3R_31()) { jj_scanpos = xsp; if (jj_3R_32()) { jj_scanpos = xsp; if (jj_3R_33()) return true; } } } } } return false; } final private boolean jj_3R_28() { if (jj_3R_37()) return true; return false; } final private boolean jj_3R_45() { if (jj_scan_token(OR)) return true; if (jj_3R_27()) return true; return false; } final private boolean jj_3R_22() { if (jj_3R_27()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_45()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_61() { if (jj_scan_token(MINUS)) return true; if (jj_3R_44()) return true; return false; } final private boolean jj_3R_38() { if (jj_3R_34()) return true; if (jj_scan_token(LRND)) return true; if (jj_3R_63()) return true; if (jj_scan_token(RRND)) return true; return false; } final private boolean jj_3R_11() { if (jj_3R_22()) return true; return false; } final private boolean jj_3R_60() { if (jj_scan_token(PLUS)) return true; if (jj_3R_44()) return true; return false; } final private boolean jj_3R_55() { Token xsp; xsp = jj_scanpos; if (jj_3R_60()) { jj_scanpos = xsp; if (jj_3R_61()) return true; } return false; } final private boolean jj_3R_42() { if (jj_3R_44()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_55()) { jj_scanpos = xsp; break; } } return false; } final private boolean jj_3R_62() { if (jj_scan_token(POWER)) return true; if (jj_3R_46()) return true; return false; } final private boolean jj_3R_17() { if (jj_3R_23()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_62()) jj_scanpos = xsp; return false; } final private boolean jj_3_2() { if (jj_3R_10()) return true; if (jj_scan_token(ASSIGN)) return true; return false; } public ParserTokenManager token_source; JavaCharStream jj_input_stream; public Token token, jj_nt; private int jj_ntk; private Token jj_scanpos, jj_lastpos; private int jj_la; public boolean lookingAhead = false; private boolean jj_semLA; private int jj_gen; final private int[] jj_la1 = new int[22]; static private int[] jj_la1_0; static private int[] jj_la1_1; static { jj_la1_0(); jj_la1_1(); } private static void jj_la1_0() { jj_la1_0 = new int[] {0x80001,0x80001,0x80001,0x10000000,0x8000000,0x4800000,0x4800000,0x3600000,0x3600000,0x60000000,0x60000000,0x80000000,0x60000000,0x0,0xa80,0x9000,0x100000,0x9000,0x100000,0x9000,0xa80,0x280,}; } private static void jj_la1_1() { jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x27,0x8,0x10,0x0,0x140,0x0,0x0,0x0,0x0,0x0,0x0,}; } final private JJCalls[] jj_2_rtns = new JJCalls[9]; private boolean jj_rescan = false; private int jj_gc = 0; public Parser(java.io.InputStream stream) { jj_input_stream = new JavaCharStream(stream, 1, 1); token_source = new ParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(java.io.InputStream stream) { jj_input_stream.ReInit(stream, 1, 1); token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jjtree.reset(); jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public Parser(java.io.Reader stream) { jj_input_stream = new JavaCharStream(stream, 1, 1); token_source = new ParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(java.io.Reader stream) { jj_input_stream.ReInit(stream, 1, 1); token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jjtree.reset(); jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public Parser(ParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } public void ReInit(ParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jjtree.reset(); jj_gen = 0; for (int i = 0; i < 22; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } final private Token jj_consume_token(int kind) throws ParseException { Token oldToken; if ((oldToken = token).next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; if (token.kind == kind) { jj_gen++; if (++jj_gc > 100) { jj_gc = 0; for (int i = 0; i < jj_2_rtns.length; i++) { JJCalls c = jj_2_rtns[i]; while (c != null) { if (c.gen < jj_gen) c.first = null; c = c.next; } } } return token; } token = oldToken; jj_kind = kind; throw generateParseException(); } static private final class LookaheadSuccess extends java.lang.Error { } final private LookaheadSuccess jj_ls = new LookaheadSuccess(); final private boolean jj_scan_token(int kind) { if (jj_scanpos == jj_lastpos) { jj_la--; if (jj_scanpos.next == null) { jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); } else { jj_lastpos = jj_scanpos = jj_scanpos.next; } } else { jj_scanpos = jj_scanpos.next; } if (jj_rescan) { int i = 0; Token tok = token; while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } if (tok != null) jj_add_error_token(kind, i); } if (jj_scanpos.kind != kind) return true; if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; return false; } final public Token getNextToken() { if (token.next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; jj_gen++; return token; } final public Token getToken(int index) { Token t = lookingAhead ? jj_scanpos : token; for (int i = 0; i < index; i++) { if (t.next != null) t = t.next; else t = t.next = token_source.getNextToken(); } return t; } final private int jj_ntk() { if ((jj_nt=token.next) == null) return (jj_ntk = (token.next=token_source.getNextToken()).kind); else return (jj_ntk = jj_nt.kind); } private java.util.Vector jj_expentries = new java.util.Vector(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; private int jj_endpos; private void jj_add_error_token(int kind, int pos) { if (pos >= 100) return; if (pos == jj_endpos + 1) { jj_lasttokens[jj_endpos++] = kind; } else if (jj_endpos != 0) { jj_expentry = new int[jj_endpos]; for (int i = 0; i < jj_endpos; i++) { jj_expentry[i] = jj_lasttokens[i]; } boolean exists = false; for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) { int[] oldentry = (int[])(e.nextElement()); if (oldentry.length == jj_expentry.length) { exists = true; for (int i = 0; i < jj_expentry.length; i++) { if (oldentry[i] != jj_expentry[i]) { exists = false; break; } } if (exists) break; } } if (!exists) jj_expentries.addElement(jj_expentry); if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; } } public ParseException generateParseException() { jj_expentries.removeAllElements(); boolean[] la1tokens = new boolean[43]; for (int i = 0; i < 43; i++) { la1tokens[i] = false; } if (jj_kind >= 0) { la1tokens[jj_kind] = true; jj_kind = -1; } for (int i = 0; i < 22; i++) { if (jj_la1[i] == jj_gen) { for (int j = 0; j < 32; j++) { if ((jj_la1_0[i] & (1< jj_gen) { jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; switch (i) { case 0: jj_3_1(); break; case 1: jj_3_2(); break; case 2: jj_3_3(); break; case 3: jj_3_4(); break; case 4: jj_3_5(); break; case 5: jj_3_6(); break; case 6: jj_3_7(); break; case 7: jj_3_8(); break; case 8: jj_3_9(); break; } } p = p.next; } while (p != null); } jj_rescan = false; } final private void jj_save(int index, int xla) { JJCalls p = jj_2_rtns[index]; while (p.gen > jj_gen) { if (p.next == null) { p = p.next = new JJCalls(); break; } p = p.next; } p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; } static final class JJCalls { int gen; Token first; int arg; JJCalls next; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/VariableFactory.java0000644000000000000000000000235710615400352022204 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* @author rich * Created on 19-Dec-2003 */ package org.nfunk.jep; /** * A factory class which is used to create variables. * By default this class creates variables of type {@link Variable}. * This class should be subclassed if the type of variable used needs to be changed. * This class is passed to the constructor of {@link SymbolTable} * which ensures that variables of the correct type are always created. *

    * This class should only be called from the SymbolTable class and not from application code. * * @author Rich Morris * Created on 19-Dec-2003 */ public class VariableFactory { /** Create a variable with a name and value */ public Variable createVariable(String name, Object value) { Variable var = new Variable(name,value); return var; } /** Create a variable with a name but not value */ public Variable createVariable(String name) { return new Variable(name); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Parser.jj0000644000000000000000000011456710615400352020054 0ustar rootroot/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. /Users/singularsys/Documents/workspace/jep-2.4/src/org/nfunk/jep/Parser.jj */ /*@egen*//*************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. This file contains the grammar from which the parser is generated. The parser generation tools being used are JavaCC and its component JJTree. JJTree processes the .jjt file and generates the .jj file. This file is then used be JavaCC to generate the final java classes. Knowledge of parser generation is definitely beneficial if you are planning to make changes to this file. Although many parts are self explanatory, it is helpful to know how the grammar is handled by JJTree and JavaCC. You can follow the structure of the grammar by starting in the line which reads "ASTStart Start() #Start : {}". From there you will be able to trace the same path the parser follows when parsing an expression. The concept of precedence is very important. Since this is a recursive descent parser, it is easy to see which operators have higher order of precedence. The following table outlines the order incorporated in this grammar. Order of precedence (from lowest to highest): || or (logical) && and (logical) == != equal, not equal < > <= >= less, greater, less or equal, greater or equal + - addition, subtraction * / % multiplication, division, modulus ! + - not, unary +/- ^ power The order of precedence is greatly inspired by the operator precedence of the C language. See "The C Programming Language" Kernighan & Richie 2nd Ed p.53. Java also uses a very similar precedence. Note that the '^' operator is used for bitwise exclusive OR in Java and C, but represents the power operator in this grammar. ***************************************************************/ /*************************************************************** OPTIONS ***************************************************************/ options { JAVA_UNICODE_ESCAPE = true; // NODE_PACKAGE = "org.nfunk.jep.parser"; // BUILD_NODE_FILES=false; STATIC = false; // DEBUG_TOKEN_MANAGER = true; // DEBUG_PARSER = true; // DEBUG_LOOKAHEAD = true; } /*************************************************************** PARSER BEGIN ***************************************************************/ PARSER_BEGIN(Parser) package org.nfunk.jep; import java.util.Vector; import org.nfunk.jep.function.*; import org.nfunk.jep.type.*; public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ protected JJTParserState jjtree = new JJTParserState(); /*@egen*/ private JEP jep; private SymbolTable symTab; private OperatorSet opSet; private int initialTokenManagerState = DEFAULT; public Node parseStream(java.io.Reader stream, JEP jep_in) throws ParseException { restart(stream,jep_in); // Parse the expression, and return the enable_tracing(); Node node = Start(); if (node == null) throw new ParseException("No expression entered"); return node.jjtGetChild(0); } /** * Restart the parse with the given stream. * @since 2.3.0 beta 1 */ public void restart(java.io.Reader stream, JEP jep_in) { ReInit(stream); this.token_source.SwitchTo(initialTokenManagerState); jep = jep_in; symTab = jep.getSymbolTable(); opSet = jep.getOperatorSet(); } /** * Continue parsing without re-initilising stream. * Allows renetrancy of parser so that strings like * "x=1; y=2; z=3;" can be parsed. * When a semi colon is encountered parsing finishes leaving the rest of the string unparsed. * Parsing can be resumed from the current position by using this method. * For example *

    	 * XJep j = new XJep();
    	 * Parser parse = j.getParse();
    	 * StringReader sr = new StringReader("x=1; y=2; z=3;");
    	 * parse.restart(sr,j);
    	 * Node node;
    	 * try {
    	 * while((node = j.continueParse())!=null) {
    	 *    j.println(node);
    	 * } }catch(ParseException e) {}
    	 * 
    */ public Node continueParse() throws ParseException { ASTStart node = Start(); if (node==null) return null; return node.jjtGetChild(0); } private void addToErrorList(String errorStr) { jep.errorList.addElement(errorStr); } /** * Sets the initial state that the token manager is in. * Can be used to change how x.x is interpreted, either as a single * identifier (DEFAULT) or as x x (NO_DOT_IN_IDENTIFIERS) * @param state the state to be in. Currently the only legal values are DEFAULT and NO_DOT_IN_IDENTIFIER */ public void setInitialTokenManagerState(int state) { initialTokenManagerState = state; } /** * Translate all escape sequences to characters. Inspired by Rob Millar's * unescape() method in rcm.util.Str fron the Web Sphinx project. * * @param inputStr String containing escape characters. * @return String with all escape sequences replaced. */ private String replaceEscape(String inputStr) { int len = inputStr.length(); int p = 0; int i; String metachars = "tnrbf\\\"'"; String chars = "\t\n\r\b\f\\\"'"; StringBuffer output = new StringBuffer(); while ((i = inputStr.indexOf('\\', p)) != -1) { output.append(inputStr.substring(p, i)); if (i+1 == len) break; // find metacharacter char metac = inputStr.charAt(i+1); // find the index of the metac int k = metachars.indexOf(metac); if (k == -1) { // didn't find the metachar, leave sequence as found. // This code should be unreachable if the parser // is functioning properly because strings containing // unknown escape characters should not be accepted. output.append('\\'); output.append(metac); } else { // its corresponding true char output.append(chars.charAt(k)); } // skip over both escape character & metacharacter p = i + 2; } // add the end of the input string to the output if (p < len) output.append(inputStr.substring(p)); return output.toString(); } } PARSER_END(Parser) /*************************************************************** SKIP ***************************************************************/ <*> SKIP : { " " | "\t" | "\n" | "\r" | <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> | <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> } /*************************************************************** TOKENS ***************************************************************/ <*> TOKEN : /* LITERALS */ { < INTEGER_LITERAL: > | < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* > | < FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* ()? | "." (["0"-"9"])+ ()? | (["0"-"9"])+ > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < STRING_LITERAL: "\"" ( (~["\"","\\","\n","\r"]) | ("\\" ["n","t","b","r","f","\\","'","\""] ) )* "\"" > } /* IDENTIFIERS Letters before version 2.22 < #LETTER: ["_","a"-"z","A"-"Z"] > In Ver 2.3.0.1 presence of . in an identifier is switchable. In the DEFAULT lexical state identifiers can contain a . In the NO_DOT_IN_IDENTIFIERS state identifiers cannot contain a . the state can be set by using Parser.setInitialTokenManagerState */ TOKEN: { (||".")*> | < #LETTER1: [ "$", // $ "A"-"Z", // A - Z "_", // _ "a"-"z", // a - z "\u00c0"-"\u00d6", // Upper case symbols of Latin-1 Supplement "\u00d8"-"\u00f6", // Lower case symbols of Latin-1 Supplement "\u00f8"-"\u00ff", // More lower case symbols of Latin-1 Supplement "\u0100"-"\u1fff", // Many languages (including Greek) "\u3040"-"\u318f", // Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo "\u3300"-"\u337f", // CJK Compatibility "\u3400"-"\u3d2d", // CJK Unified Ideographs Extension A "\u4e00"-"\u9fff", // CJK Unified Ideographs "\uf900"-"\ufaff" // CJK Compatibility Ideographs ] > | < #DIGIT1: ["0"-"9"] > } TOKEN: { (|)*> | < #LETTER2: [ "$", // $ "A"-"Z", // A - Z "_", // _ "a"-"z", // a - z "\u00c0"-"\u00d6", // Upper case symbols of Latin-1 Supplement "\u00d8"-"\u00f6", // Lower case symbols of Latin-1 Supplement "\u00f8"-"\u00ff", // More lower case symbols of Latin-1 Supplement "\u0100"-"\u1fff", // Many languages (including Greek) "\u3040"-"\u318f", // Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo "\u3300"-"\u337f", // CJK Compatibility "\u3400"-"\u3d2d", // CJK Unified Ideographs Extension A "\u4e00"-"\u9fff", // CJK Unified Ideographs "\uf900"-"\ufaff" // CJK Compatibility Ideographs ] > | < #DIGIT2: ["0"-"9"] > } /* OPERATORS */ <*> TOKEN: { < ASSIGN:"=" > // rjm | < SEMI: ";" > // rjm | < COMMA: "," > // rjm | < GT: ">" > | < LT: "<" > | < EQ: "==" > | < LE: "<=" > | < GE: ">=" > | < NE: "!=" > | < AND: "&&" > | < OR: "||" > | < PLUS: "+" > | < MINUS:"-" > | < MUL: "*" > | < DOT: "." > // rjm | < DIV: "/" > | < MOD: "%" > | < NOT: "!" > | < POWER:"^" > | < CROSS:"^^" > // rjm | < LSQ: "[" > // rjm | < RSQ: "]" > // rjm | < LRND: "(" > // rjm | < RRND: ")" > // rjm | < COLON: ":" > // rjm } /*************************************************************** GRAMMAR START ***************************************************************/ ASTStart Start() : {/*@bgen(jjtree) Start */ ASTStart jjtn000 = new ASTStart(JJTSTART); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000); /*@egen*/ } {/*@bgen(jjtree) Start */ try { /*@egen*/ Expression() ( | )/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; } /*@egen*/ { return jjtn000; } | ( | )/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; } /*@egen*/ { // njf - The next line is commented out in 2.3.0 since // two "No expression entered" errors are reported // in EvaluatorVisitor and Console (one from here // the other from ParseStream() ) // Decided to just return null, and handle the error // in ParseStream. // addToErrorList("No expression entered"); return null; }/*@bgen(jjtree)*/ } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { throw (RuntimeException)jjte000; } if (jjte000 instanceof ParseException) { throw (ParseException)jjte000; } throw (Error)jjte000; } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } /*@egen*/ } // Expresions can be like // x=3 // x=y=3 parsed as x=(y=3) void Expression() : {} { LOOKAHEAD(LValue() ) // need to prevent javacc warning with left recusion AssignExpression() // rjm changes from OrExpresion | RightExpression() } void AssignExpression() : {} // rjm addition {/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( LValue() Expression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { if (!jep.getAllowAssignment()) throw new ParseException( "Syntax Error (assignment not enabled)"); jjtn001.setOperator(opSet.getAssign()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ } void RightExpression() : { } { OrExpression() } void OrExpression() : { } { AndExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( AndExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getOr()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ )* } void AndExpression() : { } { EqualExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( EqualExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getAnd()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ )* } void EqualExpression() : { } { RelationalExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( RelationalExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getNE()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); } try { /*@egen*/ ( RelationalExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; } /*@egen*/ { jjtn002.setOperator(opSet.getEQ()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { throw (RuntimeException)jjte002; } if (jjte002 instanceof ParseException) { throw (ParseException)jjte002; } throw (Error)jjte002; } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } /*@egen*/ )* } void RelationalExpression() : { } { AdditiveExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( AdditiveExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getLT()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); } try { /*@egen*/ ( AdditiveExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; } /*@egen*/ { jjtn002.setOperator(opSet.getGT()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { throw (RuntimeException)jjte002; } if (jjte002 instanceof ParseException) { throw (ParseException)jjte002; } throw (Error)jjte002; } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn003 = new ASTFunNode(JJTFUNNODE); boolean jjtc003 = true; jjtree.openNodeScope(jjtn003); } try { /*@egen*/ ( AdditiveExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn003, 2); jjtc003 = false; } /*@egen*/ { jjtn003.setOperator(opSet.getLE()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte003) { if (jjtc003) { jjtree.clearNodeScope(jjtn003); jjtc003 = false; } else { jjtree.popNode(); } if (jjte003 instanceof RuntimeException) { throw (RuntimeException)jjte003; } if (jjte003 instanceof ParseException) { throw (ParseException)jjte003; } throw (Error)jjte003; } finally { if (jjtc003) { jjtree.closeNodeScope(jjtn003, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn004 = new ASTFunNode(JJTFUNNODE); boolean jjtc004 = true; jjtree.openNodeScope(jjtn004); } try { /*@egen*/ ( AdditiveExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn004, 2); jjtc004 = false; } /*@egen*/ { jjtn004.setOperator(opSet.getGE()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte004) { if (jjtc004) { jjtree.clearNodeScope(jjtn004); jjtc004 = false; } else { jjtree.popNode(); } if (jjte004 instanceof RuntimeException) { throw (RuntimeException)jjte004; } if (jjte004 instanceof ParseException) { throw (ParseException)jjte004; } throw (Error)jjte004; } finally { if (jjtc004) { jjtree.closeNodeScope(jjtn004, 2); } } /*@egen*/ )* } void AdditiveExpression() : { } { MultiplicativeExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( MultiplicativeExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getAdd()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); } try { /*@egen*/ ( MultiplicativeExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; } /*@egen*/ { jjtn002.setOperator(opSet.getSubtract()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { throw (RuntimeException)jjte002; } if (jjte002 instanceof ParseException) { throw (ParseException)jjte002; } throw (Error)jjte002; } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } /*@egen*/ )* } void MultiplicativeExpression() : { } { UnaryExpression() (/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( PowerExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { if (!jep.implicitMul) throw new ParseException( "Syntax Error (implicit multiplication not enabled)"); jjtn001.setOperator(opSet.getMultiply()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn002, 2); jjtc002 = false; } /*@egen*/ { jjtn002.setOperator(opSet.getMultiply()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { throw (RuntimeException)jjte002; } if (jjte002 instanceof ParseException) { throw (ParseException)jjte002; } throw (Error)jjte002; } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn003 = new ASTFunNode(JJTFUNNODE); boolean jjtc003 = true; jjtree.openNodeScope(jjtn003); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn003, 2); jjtc003 = false; } /*@egen*/ { jjtn003.setOperator(opSet.getDot()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte003) { if (jjtc003) { jjtree.clearNodeScope(jjtn003); jjtc003 = false; } else { jjtree.popNode(); } if (jjte003 instanceof RuntimeException) { throw (RuntimeException)jjte003; } if (jjte003 instanceof ParseException) { throw (ParseException)jjte003; } throw (Error)jjte003; } finally { if (jjtc003) { jjtree.closeNodeScope(jjtn003, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn004 = new ASTFunNode(JJTFUNNODE); boolean jjtc004 = true; jjtree.openNodeScope(jjtn004); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn004, 2); jjtc004 = false; } /*@egen*/ { jjtn004.setOperator(opSet.getCross()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte004) { if (jjtc004) { jjtree.clearNodeScope(jjtn004); jjtc004 = false; } else { jjtree.popNode(); } if (jjte004 instanceof RuntimeException) { throw (RuntimeException)jjte004; } if (jjte004 instanceof ParseException) { throw (ParseException)jjte004; } throw (Error)jjte004; } finally { if (jjtc004) { jjtree.closeNodeScope(jjtn004, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn005 = new ASTFunNode(JJTFUNNODE); boolean jjtc005 = true; jjtree.openNodeScope(jjtn005); } try { /*@egen*/ (
    UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn005, 2); jjtc005 = false; } /*@egen*/ { jjtn005.setOperator(opSet.getDivide()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte005) { if (jjtc005) { jjtree.clearNodeScope(jjtn005); jjtc005 = false; } else { jjtree.popNode(); } if (jjte005 instanceof RuntimeException) { throw (RuntimeException)jjte005; } if (jjte005 instanceof ParseException) { throw (ParseException)jjte005; } throw (Error)jjte005; } finally { if (jjtc005) { jjtree.closeNodeScope(jjtn005, 2); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn006 = new ASTFunNode(JJTFUNNODE); boolean jjtc006 = true; jjtree.openNodeScope(jjtn006); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn006, 2); jjtc006 = false; } /*@egen*/ { jjtn006.setOperator(opSet.getMod()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte006) { if (jjtc006) { jjtree.clearNodeScope(jjtn006); jjtc006 = false; } else { jjtree.popNode(); } if (jjte006 instanceof RuntimeException) { throw (RuntimeException)jjte006; } if (jjte006 instanceof ParseException) { throw (ParseException)jjte006; } throw (Error)jjte006; } finally { if (jjtc006) { jjtree.closeNodeScope(jjtn006, 2); } } /*@egen*/ )* } void UnaryExpression() : { } { ( UnaryExpression()) |/*@bgen(jjtree) #FunNode( 1) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 1); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getUMinus()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 1); } } /*@egen*/ |/*@bgen(jjtree) #FunNode( 1) */ { ASTFunNode jjtn002 = new ASTFunNode(JJTFUNNODE); boolean jjtc002 = true; jjtree.openNodeScope(jjtn002); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn002, 1); jjtc002 = false; } /*@egen*/ { jjtn002.setOperator(opSet.getNot()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte002) { if (jjtc002) { jjtree.clearNodeScope(jjtn002); jjtc002 = false; } else { jjtree.popNode(); } if (jjte002 instanceof RuntimeException) { throw (RuntimeException)jjte002; } if (jjte002 instanceof ParseException) { throw (ParseException)jjte002; } throw (Error)jjte002; } finally { if (jjtc002) { jjtree.closeNodeScope(jjtn002, 1); } } /*@egen*/ | PowerExpression() } void PowerExpression() : { } { UnaryExpressionNotPlusMinus() [/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( UnaryExpression()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getPower()); } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ ] } void UnaryExpressionNotPlusMinus() : { String identString = ""; int type; } { AnyConstant() | LOOKAHEAD(ArrayAccess()) ArrayAccess() | LOOKAHEAD({ (getToken(1).kind == INDENTIFIER1 || getToken(1).kind == INDENTIFIER2) && jep.funTab.containsKey(getToken(1).image) }) Function() | Variable() | Expression() | // LOOKAHEAD( Expression() ) // RangeExpression() // | ListExpression() } void ListExpression() : {/*@bgen(jjtree) FunNode */ ASTFunNode jjtn000 = new ASTFunNode(JJTFUNNODE); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000); /*@egen*/ jjtn000.setOperator(opSet.getList()); } {/*@bgen(jjtree) FunNode */ try { /*@egen*/ Expression() ( Expression() )* /*@bgen(jjtree)*/ } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { throw (RuntimeException)jjte000; } if (jjte000 instanceof ParseException) { throw (ParseException)jjte000; } throw (Error)jjte000; } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } /*@egen*/ } /* void RangeExpression() #FunNode: { jjtThis.setOperator(opSet.getRange()); } { Expression() ( Expression() )+ } */ void LValue() : { } { LOOKAHEAD(ArrayAccess()) ArrayAccess() | Variable() } void ArrayAccess() : { } { Variable() ListExpression()/*@bgen(jjtree) #FunNode( 2) */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*//*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, 2); jjtc001 = false; } /*@egen*/ { jjtn001.setOperator(opSet.getElement()); }/*@bgen(jjtree)*/ } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, 2); } } /*@egen*/ } void Variable() : { String identString = ""; } {/*@bgen(jjtree) VarNode */ { ASTVarNode jjtn001 = new ASTVarNode(JJTVARNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ (identString = Identifier()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn001, true); jjtc001 = false; } /*@egen*/ { if (symTab.containsKey(identString)) { jjtn001.setVar(symTab.getVar(identString)); } else { if (jep.allowUndeclared) { jjtn001.setVar(symTab.makeVarIfNeeded(identString)); } else { addToErrorList("Unrecognized symbol \"" + identString +"\""); } } } )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, true); } } /*@egen*/ } void Function() : { int reqArguments = 0; String identString = ""; } {/*@bgen(jjtree) FunNode */ { ASTFunNode jjtn001 = new ASTFunNode(JJTFUNNODE); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try { /*@egen*/ ( identString = Identifier() { if (jep.funTab.containsKey(identString)) { //Set number of required arguments reqArguments = ((PostfixMathCommandI)jep.funTab.get(identString)).getNumberOfParameters(); jjtn001.setFunction(identString, (PostfixMathCommandI)jep.funTab.get(identString)); } else { addToErrorList("!!! Unrecognized function \"" + identString +"\""); } } ArgumentList(reqArguments, identString) )/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, true); } } /*@egen*/ } void ArgumentList(int reqArguments, String functionName) : { int count = 0; String errorStr = ""; } { [ Expression() { count++; } ( Expression() { count++; } )* ] { if(reqArguments == -1) { if(!((PostfixMathCommandI)jep.funTab.get(functionName)).checkNumberOfParameters(count)) { errorStr = "Function \"" + functionName +"\" illegal number of arguments " + count; addToErrorList(errorStr); } } else if (reqArguments != count) { errorStr = "Function \"" + functionName +"\" requires " + reqArguments + " parameter"; if (reqArguments!=1) errorStr += "s"; addToErrorList(errorStr); } } } String Identifier() : { Token t; } { ( t = | t = ) { return t.image; } } void AnyConstant() : {/*@bgen(jjtree) Constant */ ASTConstant jjtn000 = new ASTConstant(JJTCONSTANT); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000); /*@egen*/ Token t; Object value; } {/*@bgen(jjtree) Constant */ try { /*@egen*/ t=/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; } /*@egen*/ { // strip away double quotes at end of string String temp = (t.image).substring(1,t.image.length()-1); // replace escape characters temp = replaceEscape(temp); jjtn000.setValue(temp); } | value = RealConstant()/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; } /*@egen*/ { jjtn000.setValue(value); // } // | // value = Array() { // jjtThis.setValue(value); }/*@bgen(jjtree)*/ } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { throw (RuntimeException)jjte000; } if (jjte000 instanceof ParseException) { throw (ParseException)jjte000; } throw (Error)jjte000; } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } } /*@egen*/ } /* Vector Array() : { Object value; Vector result = new Vector(); } { value = RealConstant() { result.addElement(value); } ( value = RealConstant() { result.addElement(value); } )* { return result; } } */ Object RealConstant() : { Token t; Object value; } { (t= | t=) { try { value = jep.getNumberFactory().createNumber(t.image); } catch (Exception e) { value = null; addToErrorList("Can't parse \"" + t.image + "\""); } return value; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/evaluation/0000755000000000000000000000000010615400352020424 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/evaluation/CommandElement.java0000644000000000000000000000321010615400352024153 0ustar rootroot/* * * Created on 15-Aug-2003 */ package org.nfunk.jep.evaluation; import org.nfunk.jep.function.*; /** * * @author nathan */ public class CommandElement { public final static int VAR = 0; public final static int CONST = 1; public final static int FUNC = 2; private int type; private String varName; private PostfixMathCommandI pfmc; private int nParam; private Object value; /** * @return The function associated with this element. */ public final PostfixMathCommandI getPFMC() { return pfmc; } /** * @return The type. */ public final int getType() { return type; } /** * @return The value of this element. */ public final Object getValue() { return value; } /** * @return The variable name. */ public final String getVarName() { return varName; } /** * @return The number of parameters. */ public final int getNumParam() { return nParam; } /** * @param commandI The function associated with this element. */ public final void setPFMC(PostfixMathCommandI commandI) { pfmc = commandI; } /** * @param i The type identifier. */ public final void setType(int i) { type = i; } /** * @param object The value of the element. */ public final void setValue(Object object) { value = object; } /** * @param string The name of the variable. */ public final void setVarName(String string) { varName = string; } /** * @param i The number of parameters. */ public final void setNumParam(int i) { nParam = i; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/evaluation/package.html0000644000000000000000000000035710615400352022712 0ustar rootroot An experimental fast evaluator which "compiles" an expression into a set of CommandElement objects rather than traversing the parse tree. These classes are still experimental and are not used by default for evaluation. jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/evaluation/CommandEvaluator.java0000644000000000000000000000425210615400352024533 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jep.evaluation; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.function.*; /** * * @author nathan */ public class CommandEvaluator { private CommandElement command; private Stack stack; private PostfixMathCommandI pfmc; private int i; public CommandEvaluator() { stack = new Stack(); } public Object evaluate(CommandElement[] commands, SymbolTable symTab) throws Exception { int nCommands = commands.length; stack.removeAllElements(); // for each command i = 0; while (i * The most important methods are parseExpression(String), for parsing the * mathematical expression, and getValue() for obtaining the value of the * expression. *

    * Visit http://www.singularsys.com/jep * for the newest version of JEP, and complete documentation. * * @author Nathan Funk * @since 04/02/13 added Binom function */ public class JEP { /** Debug flag for extra command line output */ private static final boolean debug = false; /** Traverse option */ private boolean traverse; /** Allow undeclared variables option */ protected boolean allowUndeclared; /** Allow undeclared variables option */ protected boolean allowAssignment; /** Implicit multiplication option */ protected boolean implicitMul; /** Symbol Table */ protected SymbolTable symTab; /** Function Table */ protected FunctionTable funTab; /** Error List */ protected Vector errorList; /** The parser object */ protected Parser parser; /** Node at the top of the parse tree */ private Node topNode; /** Evaluator */ protected EvaluatorVisitor ev; /** Number factory */ protected NumberFactory numberFactory; /** OperatorSet */ protected OperatorSet opSet; /** * Creates a new JEP instance with the default settings. *

    * Traverse = false
    * Allow undeclared variables = false
    * Implicit multiplication = false
    * Number Factory = DoubleNumberFactory */ public JEP() { topNode = null; traverse = false; allowUndeclared = false; allowAssignment = false; implicitMul = false; numberFactory = new DoubleNumberFactory(); opSet = new OperatorSet(); initSymTab(); initFunTab(); errorList = new Vector(); ev = new EvaluatorVisitor(); parser = new Parser(new StringReader("")); //Ensure errors are reported for the initial expression //e.g. No expression entered //parseExpression(""); } /** * Creates a new JEP instance with custom settings. If the * numberFactory_in is null, the default number factory is used. * @param traverse_in The traverse option. * @param allowUndeclared_in The "allow undeclared variables" option. * @param implicitMul_in The implicit multiplication option. * @param numberFactory_in The number factory to be used. */ public JEP(boolean traverse_in, boolean allowUndeclared_in, boolean implicitMul_in, NumberFactory numberFactory_in) { topNode = null; traverse = traverse_in; allowUndeclared = allowUndeclared_in; implicitMul = implicitMul_in; if (numberFactory_in == null) { numberFactory = new DoubleNumberFactory(); } else { numberFactory = numberFactory_in; } opSet = new OperatorSet(); initSymTab(); initFunTab(); errorList = new Vector(); ev = new EvaluatorVisitor(); parser = new Parser(new StringReader("")); //Ensure errors are reported for the initial expression //e.g. No expression entered parseExpression(""); } /** This constructor copies the SymbolTable and other components * of the arguments to the new instance. Subclasses can call this * protected constructor and set the individual components * themselves. * @since 2.3.0 alpha */ protected JEP(JEP j) { this.topNode = null; this.traverse = j.traverse; this.allowUndeclared = j.allowUndeclared; this.allowAssignment = j.allowAssignment; this.implicitMul = j.implicitMul; this.ev = j.ev; this.funTab = j.funTab; this.opSet = j.opSet; this.numberFactory = j.numberFactory; this.parser = j.parser; this.symTab = j.symTab; this.errorList = j.errorList; } /** * Creates a new SymbolTable object as symTab. */ public void initSymTab() { //Init SymbolTable symTab = new SymbolTable(new VariableFactory()); } /** * Creates a new FunctionTable object as funTab. */ public void initFunTab() { //Init FunctionTable funTab = new FunctionTable(); } /** * Adds the standard functions to the parser. If this function is not called * before parsing an expression, functions such as sin() or cos() would * produce an "Unrecognized function..." error. * In most cases, this method should be called immediately after the JEP * object is created. * @since 2.3.0 alpha added if and exp functions * @since 2.3.0 beta 1 added str function */ public void addStandardFunctions() { //add functions to Function Table funTab.put("sin", new Sine()); funTab.put("cos", new Cosine()); funTab.put("tan", new Tangent()); funTab.put("asin", new ArcSine()); funTab.put("acos", new ArcCosine()); funTab.put("atan", new ArcTangent()); funTab.put("atan2", new ArcTangent2()); funTab.put("sinh", new SineH()); funTab.put("cosh", new CosineH()); funTab.put("tanh", new TanH()); funTab.put("asinh", new ArcSineH()); funTab.put("acosh", new ArcCosineH()); funTab.put("atanh", new ArcTanH()); funTab.put("log", new Logarithm()); funTab.put("ln", new NaturalLogarithm()); funTab.put("exp", new Exp()); funTab.put("pow", new Power()); funTab.put("sqrt",new SquareRoot()); funTab.put("abs", new Abs()); funTab.put("mod", new Modulus()); funTab.put("sum", new Sum()); funTab.put("rand", new org.nfunk.jep.function.Random()); // rjm additions funTab.put("if", new If()); funTab.put("str", new Str()); // rjm 13/2/05 funTab.put("binom", new Binomial()); // rjm 26/1/07 funTab.put("round",new Round()); funTab.put("floor",new Floor()); funTab.put("ceil",new Ceil()); } /** * Adds the constants pi and e to the parser. As addStandardFunctions(), * this method should be called immediately after the JEP object is * created. */ public void addStandardConstants() { //add constants to Symbol Table symTab.addConstant("pi", new Double(Math.PI)); symTab.addConstant("e", new Double(Math.E)); } /** * Call this function if you want to parse expressions which involve * complex numbers. This method specifies "i" as the imaginary unit * (0,1). Two functions re() and im() are also added for extracting the * real or imaginary components of a complex number respectively. *

    * @since 2.3.0 alpha The functions cmod and arg are added to get the modulus and argument. * @since 2.3.0 beta 1 The functions complex and polar to convert x,y and r,theta to Complex. * @since Feb 05 added complex conjugate conj. */ public void addComplex() { //add constants to Symbol Table symTab.addConstant("i", new Complex(0,1)); funTab.put("re", new Real()); funTab.put("im", new Imaginary()); funTab.put("arg", new Arg()); funTab.put("cmod", new Abs()); funTab.put("complex", new ComplexPFMC()); funTab.put("polar", new Polar()); funTab.put("conj",new Conjugate()); } /** * Adds a new function to the parser. This must be done before parsing * an expression so the parser is aware that the new function may be * contained in the expression. * @param functionName The name of the function * @param function The function object that is used for evaluating the * function */ public void addFunction(String functionName, PostfixMathCommandI function) { funTab.put(functionName, function); } /** Adds a constant. * This is a variable whose value cannot be changed. * @since 2.3.0 beta 1 */ public void addConstant(String name,Object value) { symTab.addConstant(name, value); } /** * Adds a new variable to the parser, or updates the value of an * existing variable. This must be done before parsing * an expression so the parser is aware that the new variable may be * contained in the expression. * @param name Name of the variable to be added * @param value Initial value or new value for the variable * @return Double object of the variable */ public Double addVariable(String name, double value) { Double object = new Double(value); symTab.makeVarIfNeeded(name, object); return object; } /** * Adds a new complex variable to the parser, or updates the value of an * existing variable. This must be done before parsing * an expression so the parser is aware that the new variable may be * contained in the expression. * @param name Name of the variable to be added * @param re Initial real value or new real value for the variable * @param im Initial imaginary value or new imaginary value for the variable * @return Complex object of the variable */ public Complex addVariable(String name, double re, double im) { Complex object = new Complex(re,im); symTab.makeVarIfNeeded(name, object); return object; } /** * Adds a new variable to the parser as an object, or updates the value of an * existing variable. This must be done before parsing * an expression so the parser is aware that the new variable may be * contained in the expression. * @param name Name of the variable to be added * @param object Initial value or new value for the variable */ public void addVariable(String name, Object object) { symTab.makeVarIfNeeded(name, object); } /** * Removes a variable from the parser. For example after calling * addStandardConstants(), removeVariable("e") might be called to remove * the euler constant from the set of variables. * * @return The value of the variable if it was added earlier. If * the variable is not in the table of variables, null is * returned. */ public Object removeVariable(String name) { return symTab.remove(name); } /** * Returns the value of the variable with given name. * @param name name of the variable. * @return the current value of the variable. * @since 2.3.0 alpha */ public Object getVarValue(String name) { return symTab.getVar(name).getValue(); } /** * Sets the value of a variable. * The variable must exist before hand. * @param name name of the variable. * @param val the initial value of the variable. * @throws NullPointerException if the variable has not been previously created * with {@link #addVariable(String,Object)} first. * @since 2.3.0 alpha * @since April 05 - throws an exception if variable unset. */ public void setVarValue(String name,Object val) { symTab.setVarValue(name,val); } /** * Gets the object representing the variable with a given name. * @param name the name of the variable to find. * @return the Variable object or null if name not found. * @since 2.3.0 alpha */ public Variable getVar(String name) { return symTab.getVar(name); } /** * Removes a function from the parser. * * @return If the function was added earlier, the function class instance * is returned. If the function was not present, null * is returned. */ public Object removeFunction(String name) { return funTab.remove(name); } /** * Sets the value of the traverse option. setTraverse is useful for * debugging purposes. When traverse is set to true, the parse-tree * will be dumped to the standard output device. *

    * The default value is false. * @param value The boolean traversal option. */ public void setTraverse(boolean value) { traverse = value; } /** * Returns the value of the traverse option. * @return True if the traverse option is enabled. False otherwise. */ public boolean getTraverse() { return traverse; } /** * Sets the value of the implicit multiplication option. * If this option is set to true before parsing, implicit multiplication * will be allowed. That means that an expression such as *

    "1 2"
    is valid and is interpreted as
    "1*2"
    . *

    * The default value is false. * @param value The boolean implicit multiplication option. */ public void setImplicitMul(boolean value) { implicitMul = value; } /** * Returns the value of the implicit multiplication option. * @return True if the implicit multiplication option is enabled. False otherwise. */ public boolean getImplicitMul() { return implicitMul; } /** * Sets the value for the undeclared variables option. If this option * is set to true, expressions containing variables that were not * previously added to JEP will not produce an "Unrecognized Symbol" * error. The new variables will automatically be added while parsing, * and initialized to 0. *

    * If this option is set to false, variables that were not previously * added to JEP will produce an error while parsing. *

    * The default value is false. * @param value The boolean option for allowing undeclared variables. */ public void setAllowUndeclared(boolean value) { allowUndeclared = value; } /** * Returns the value of the allowUndeclared option. * @return True if the allowUndeclared option is enabled. False otherwise. */ public boolean getAllowUndeclared() { return allowUndeclared; } /** * Sets whether assignment equations like y=x+1 are allowed. * @since 2.3.0 alpha */ public void setAllowAssignment(boolean value) { allowAssignment = value; } /** * Whether assignment equation y=x+1 equations are allowed. * @since 2.3.0 alpha */ public boolean getAllowAssignment() { return allowAssignment; } /** * Parses the expression. If there are errors in the expression, * they are added to the errorList member. Errors can be * obtained through getErrorInfo(). * @param expression_in The input expression string * @return the top node of the expression tree if the parse was successful, * null otherwise */ public Node parseExpression(String expression_in) { Reader reader = new StringReader(expression_in); try { // try parsing errorList.removeAllElements(); topNode = parser.parseStream(reader, this); // if there is an error in the list, the parse failed // so set topNode to null if (hasError()) topNode = null; } catch (Throwable e) { // an exception was thrown, so there is no parse tree topNode = null; // check the type of error if (e instanceof ParseException) { // the ParseException object contains additional error // information errorList.addElement(((ParseException)e).getMessage()); //getErrorInfo()); } else { // if the exception was not a ParseException, it was most // likely a syntax error if (debug) { System.out.println(e.getMessage()); e.printStackTrace(); } errorList.addElement("Syntax error"); } } // If traversing is enabled, print a dump of the tree to // standard output if (traverse && !hasError()) { ParserVisitor v = new ParserDumpVisitor(); try { topNode.jjtAccept(v, null); } catch(ParseException e) { errorList.addElement(e.getMessage()); } } return topNode; } /** * Parses an expression. * Returns a object of type Node, does not catch errors. * Does not set the topNode variable of the JEP instance. * This method should generally be used with the {@link #evaluate evaluate} * method rather than getValueAsObject. * @param expression represented as a string. * @return The top node of a tree representing the parsed expression. * @throws ParseException * @since 2.3.0 alpha * @since 2.3.0 beta - will raise exception if errorList non empty */ public Node parse(String expression) throws ParseException { java.io.StringReader sr = new java.io.StringReader(expression); errorList.removeAllElements(); Node node = parser.parseStream(sr, this); if (this.hasError()) throw new ParseException(getErrorInfo()); return node; } /** * Evaluate an expression. This method evaluates the argument * rather than the topNode of the JEP instance. * It should be used in conjunction with {@link #parse parse} * rather than {@link #parseExpression parseExpression}. * @param node the top node of the tree representing the expression. * @return The value of the expression * @throws ParseException if for some reason the expression could not be evaluated * @throws RuntimeException could potentially be thrown. * @since 2.3.0 alpha */ public Object evaluate(Node node) throws ParseException { return ev.getValue(node, this.symTab); } /** * Evaluates and returns the value of the expression as a double number. * @return The calculated value of the expression as a double number. * If the type of the value does not implement the Number interface * (e.g. Complex), NaN is returned. If an error occurs during evaluation, * NaN is returned and hasError() will return true. * * @see #getComplexValue() */ public double getValue() { Object value = getValueAsObject(); if(value == null) return Double.NaN; if(value instanceof Complex) { Complex c = (Complex) value; if( c.im() != 0.0) return Double.NaN; return c.re(); } if (value != null && value instanceof Number) { return ((Number)value).doubleValue(); } return Double.NaN; } /** * Evaluates and returns the value of the expression as a complex number. * @return The calculated value of the expression as a complex number if * no errors occur. Returns null otherwise. */ public Complex getComplexValue() { Object value = getValueAsObject(); if (value == null) { return null; } else if (value instanceof Complex) { return (Complex)value; } else if (value instanceof Number) { return new Complex(((Number)value).doubleValue(), 0); } else { return null; } } /** * Evaluates and returns the value of the expression as an object. * The EvaluatorVisitor member ev is used to do the evaluation procedure. * This method is useful when the type of the value is unknown, or * not important. * @return The calculated value of the expression if no errors occur. * Returns null otherwise. */ public Object getValueAsObject() { Object result; // fail by returning null if no topNode is available if (topNode == null) return null; // evaluate the expression try { result = ev.getValue(topNode,symTab); } catch(ParseException e) { if (debug) System.out.println(e); errorList.addElement("Error during evaluation: "+e.getMessage()); return null; } catch(RuntimeException e) { if (debug) System.out.println(e); errorList.addElement(e.getClass().getName()+": "+e.getMessage()); return null; } return result; } /** * Returns true if an error occurred during the most recent * action (parsing or evaluation). * @return Returns true if an error occurred during the most * recent action (parsing or evaluation). */ public boolean hasError() { return !errorList.isEmpty(); } /** * Reports information on the errors that occurred during the most recent * action. * @return A string containing information on the errors, each separated * by a newline character; null if no error has occurred */ public String getErrorInfo() { if (hasError()) { String str = ""; // iterate through all errors and add them to the return string for (int i=0; i= maxNextCharInd) FillBuff(); return nextCharBuf[nextCharInd]; } public char BeginToken() throws java.io.IOException { if (inBuf > 0) { --inBuf; if (++bufpos == bufsize) bufpos = 0; tokenBegin = bufpos; return buffer[bufpos]; } tokenBegin = 0; bufpos = -1; return readChar(); } protected void AdjustBuffSize() { if (available == bufsize) { if (tokenBegin > 2048) { bufpos = 0; available = tokenBegin; } else ExpandBuff(false); } else if (available > tokenBegin) available = bufsize; else if ((tokenBegin - available) < 2048) ExpandBuff(true); else available = tokenBegin; } protected void UpdateLineColumn(char c) { column++; if (prevCharIsLF) { prevCharIsLF = false; line += (column = 1); } else if (prevCharIsCR) { prevCharIsCR = false; if (c == '\n') { prevCharIsLF = true; } else line += (column = 1); } switch (c) { case '\r' : prevCharIsCR = true; break; case '\n' : prevCharIsLF = true; break; case '\t' : column--; column += (8 - (column & 07)); break; default : break; } bufline[bufpos] = line; bufcolumn[bufpos] = column; } public char readChar() throws java.io.IOException { if (inBuf > 0) { --inBuf; if (++bufpos == bufsize) bufpos = 0; return buffer[bufpos]; } char c; if (++bufpos == available) AdjustBuffSize(); if ((buffer[bufpos] = c = ReadByte()) == '\\') { UpdateLineColumn(c); int backSlashCnt = 1; for (;;) // Read all the backslashes { if (++bufpos == available) AdjustBuffSize(); try { if ((buffer[bufpos] = c = ReadByte()) != '\\') { UpdateLineColumn(c); // found a non-backslash char. if ((c == 'u') && ((backSlashCnt & 1) == 1)) { if (--bufpos < 0) bufpos = bufsize - 1; break; } backup(backSlashCnt); return '\\'; } } catch(java.io.IOException e) { if (backSlashCnt > 1) backup(backSlashCnt); return '\\'; } UpdateLineColumn(c); backSlashCnt++; } // Here, we have seen an odd number of backslash's followed by a 'u' try { while ((c = ReadByte()) == 'u') ++column; buffer[bufpos] = c = (char)(hexval(c) << 12 | hexval(ReadByte()) << 8 | hexval(ReadByte()) << 4 | hexval(ReadByte())); column += 4; } catch(java.io.IOException e) { throw new Error("Invalid escape character at line " + line + " column " + column + "."); } if (backSlashCnt == 1) return c; else { backup(backSlashCnt - 1); return '\\'; } } else { UpdateLineColumn(c); return (c); } } /** * @deprecated * @see #getEndColumn */ public int getColumn() { return bufcolumn[bufpos]; } /** * @deprecated * @see #getEndLine */ public int getLine() { return bufline[bufpos]; } public int getEndColumn() { return bufcolumn[bufpos]; } public int getEndLine() { return bufline[bufpos]; } public int getBeginColumn() { return bufcolumn[tokenBegin]; } public int getBeginLine() { return bufline[tokenBegin]; } public void backup(int amount) { inBuf += amount; if ((bufpos -= amount) < 0) bufpos += bufsize; } public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; nextCharBuf = new char[4096]; } public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } public JavaCharStream(java.io.Reader dstream) { this(dstream, 1, 1, 4096); } public void ReInit(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; if (buffer == null || buffersize != buffer.length) { available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; nextCharBuf = new char[4096]; } prevCharIsLF = prevCharIsCR = false; tokenBegin = inBuf = maxNextCharInd = 0; nextCharInd = bufpos = -1; } public void ReInit(java.io.Reader dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } public void ReInit(java.io.Reader dstream) { ReInit(dstream, 1, 1, 4096); } public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); } public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } public JavaCharStream(java.io.InputStream dstream) { this(dstream, 1, 1, 4096); } public void ReInit(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); } public void ReInit(java.io.InputStream dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } public void ReInit(java.io.InputStream dstream) { ReInit(dstream, 1, 1, 4096); } public String GetImage() { if (bufpos >= tokenBegin) return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); else return new String(buffer, tokenBegin, bufsize - tokenBegin) + new String(buffer, 0, bufpos + 1); } public char[] GetSuffix(int len) { char[] ret = new char[len]; if ((bufpos + 1) >= len) System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); else { System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, len - bufpos - 1); System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); } return ret; } public void Done() { nextCharBuf = null; buffer = null; bufline = null; bufcolumn = null; } /** * Method to adjust line and column numbers for the start of a token. */ public void adjustBeginLineColumn(int newLine, int newCol) { int start = tokenBegin; int len; if (bufpos >= tokenBegin) { len = bufpos - tokenBegin + inBuf + 1; } else { len = bufsize - tokenBegin + bufpos + 1 + inBuf; } int i = 0, j = 0, k = 0; int nextColDiff = 0, columnDiff = 0; while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { bufline[j] = newLine; nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; bufcolumn[j] = newCol + columnDiff; columnDiff = nextColDiff; i++; } if (i < len) { bufline[j] = newLine++; bufcolumn[j] = newCol + columnDiff; while (i++ < len) { if (bufline[j = start % bufsize] != bufline[++start % bufsize]) bufline[j] = newLine++; else bufline[j] = newLine; } } line = bufline[j]; column = bufcolumn[j]; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/ParserTokenManager.java0000644000000000000000000010225010615400352022650 0ustar rootroot/* Generated By:JJTree&JavaCC: Do not edit this line. ParserTokenManager.java */ package org.nfunk.jep; import java.util.Vector; import org.nfunk.jep.function.*; import org.nfunk.jep.type.*; public class ParserTokenManager implements ParserConstants { public java.io.PrintStream debugStream = System.out; public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } private final int jjStopStringLiteralDfa_1(int pos, long active0) { switch (pos) { case 0: if ((active0 & 0x100000000L) != 0L) return 1; if ((active0 & 0x200000000L) != 0L) return 13; return -1; default : return -1; } } private final int jjStartNfa_1(int pos, long active0) { return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); } private final int jjStopAtPos(int pos, int kind) { jjmatchedKind = kind; jjmatchedPos = pos; return pos + 1; } private final int jjStartNfaWithStates_1(int pos, int kind, int state) { jjmatchedKind = kind; jjmatchedPos = pos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return pos + 1; } return jjMoveNfa_1(state, pos + 1); } private final int jjMoveStringLiteralDfa0_1() { switch(curChar) { case 33: jjmatchedKind = 35; return jjMoveStringLiteralDfa1_1(0x4000000L); case 37: return jjStopAtPos(0, 34); case 38: return jjMoveStringLiteralDfa1_1(0x8000000L); case 40: return jjStopAtPos(0, 40); case 41: return jjStopAtPos(0, 41); case 42: return jjStopAtPos(0, 31); case 43: return jjStopAtPos(0, 29); case 44: return jjStopAtPos(0, 20); case 45: return jjStopAtPos(0, 30); case 46: return jjStartNfaWithStates_1(0, 32, 1); case 47: return jjStartNfaWithStates_1(0, 33, 13); case 58: return jjStopAtPos(0, 42); case 59: return jjStopAtPos(0, 19); case 60: jjmatchedKind = 22; return jjMoveStringLiteralDfa1_1(0x1000000L); case 61: jjmatchedKind = 18; return jjMoveStringLiteralDfa1_1(0x800000L); case 62: jjmatchedKind = 21; return jjMoveStringLiteralDfa1_1(0x2000000L); case 91: return jjStopAtPos(0, 38); case 93: return jjStopAtPos(0, 39); case 94: jjmatchedKind = 36; return jjMoveStringLiteralDfa1_1(0x2000000000L); case 124: return jjMoveStringLiteralDfa1_1(0x10000000L); default : return jjMoveNfa_1(0, 0); } } private final int jjMoveStringLiteralDfa1_1(long active0) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { jjStopStringLiteralDfa_1(0, active0); return 1; } switch(curChar) { case 38: if ((active0 & 0x8000000L) != 0L) return jjStopAtPos(1, 27); break; case 61: if ((active0 & 0x800000L) != 0L) return jjStopAtPos(1, 23); else if ((active0 & 0x1000000L) != 0L) return jjStopAtPos(1, 24); else if ((active0 & 0x2000000L) != 0L) return jjStopAtPos(1, 25); else if ((active0 & 0x4000000L) != 0L) return jjStopAtPos(1, 26); break; case 94: if ((active0 & 0x2000000000L) != 0L) return jjStopAtPos(1, 37); break; case 124: if ((active0 & 0x10000000L) != 0L) return jjStopAtPos(1, 28); break; default : break; } return jjStartNfa_1(0, active0); } private final void jjCheckNAdd(int state) { if (jjrounds[state] != jjround) { jjstateSet[jjnewStateCnt++] = state; jjrounds[state] = jjround; } } private final void jjAddStates(int start, int end) { do { jjstateSet[jjnewStateCnt++] = jjnextStates[start]; } while (start++ != end); } private final void jjCheckNAddTwoStates(int state1, int state2) { jjCheckNAdd(state1); jjCheckNAdd(state2); } private final void jjCheckNAddStates(int start, int end) { do { jjCheckNAdd(jjnextStates[start]); } while (start++ != end); } private final void jjCheckNAddStates(int start) { jjCheckNAdd(jjnextStates[start]); jjCheckNAdd(jjnextStates[start + 1]); } static final long[] jjbitVec0 = { 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL }; static final long[] jjbitVec2 = { 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL }; static final long[] jjbitVec3 = { 0x1ff00000fffffffeL, 0xffffffffffffc000L, 0xffffffffL, 0x600000000000000L }; static final long[] jjbitVec4 = { 0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL }; static final long[] jjbitVec5 = { 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL }; static final long[] jjbitVec6 = { 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffL, 0x0L }; static final long[] jjbitVec7 = { 0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L, 0x0L }; static final long[] jjbitVec8 = { 0x3fffffffffffL, 0x0L, 0x0L, 0x0L }; private final int jjMoveNfa_1(int startState, int curPos) { int[] nextStates; int startsAt = 0; jjnewStateCnt = 36; int i = 1; jjstateSet[0] = startState; int j, kind = 0x7fffffff; for (;;) { if (++jjround == 0x7fffffff) ReInitRounds(); if (curChar < 64) { long l = 1L << curChar; MatchLoop: do { switch(jjstateSet[--i]) { case 13: if (curChar == 42) jjCheckNAddTwoStates(19, 20); else if (curChar == 47) jjCheckNAddStates(0, 2); break; case 0: if ((0x3ff000000000000L & l) != 0L) { if (kind > 7) kind = 7; jjCheckNAddStates(3, 7); } else if (curChar == 47) jjAddStates(8, 9); else if (curChar == 36) { if (kind > 12) kind = 12; jjCheckNAdd(11); } else if (curChar == 34) jjCheckNAddStates(10, 12); else if (curChar == 46) jjCheckNAdd(1); break; case 1: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(1, 2); break; case 3: if ((0x280000000000L & l) != 0L) jjCheckNAdd(4); break; case 4: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(4); break; case 5: if (curChar == 34) jjCheckNAddStates(10, 12); break; case 6: if ((0xfffffffbffffdbffL & l) != 0L) jjCheckNAddStates(10, 12); break; case 8: if ((0x8400000000L & l) != 0L) jjCheckNAddStates(10, 12); break; case 9: if (curChar == 34 && kind > 11) kind = 11; break; case 10: if (curChar != 36) break; if (kind > 12) kind = 12; jjCheckNAdd(11); break; case 11: if ((0x3ff401000000000L & l) == 0L) break; if (kind > 12) kind = 12; jjCheckNAdd(11); break; case 12: if (curChar == 47) jjAddStates(8, 9); break; case 14: if ((0xffffffffffffdbffL & l) != 0L) jjCheckNAddStates(0, 2); break; case 15: if ((0x2400L & l) != 0L && kind > 5) kind = 5; break; case 16: if (curChar == 10 && kind > 5) kind = 5; break; case 17: if (curChar == 13) jjstateSet[jjnewStateCnt++] = 16; break; case 18: if (curChar == 42) jjCheckNAddTwoStates(19, 20); break; case 19: if ((0xfffffbffffffffffL & l) != 0L) jjCheckNAddTwoStates(19, 20); break; case 20: if (curChar == 42) jjAddStates(13, 14); break; case 21: if ((0xffff7fffffffffffL & l) != 0L) jjCheckNAddTwoStates(22, 20); break; case 22: if ((0xfffffbffffffffffL & l) != 0L) jjCheckNAddTwoStates(22, 20); break; case 23: if (curChar == 47 && kind > 6) kind = 6; break; case 24: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 7) kind = 7; jjCheckNAddStates(3, 7); break; case 25: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 7) kind = 7; jjCheckNAdd(25); break; case 26: if ((0x3ff000000000000L & l) != 0L) jjCheckNAddTwoStates(26, 27); break; case 27: if (curChar != 46) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(28, 29); break; case 28: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(28, 29); break; case 30: if ((0x280000000000L & l) != 0L) jjCheckNAdd(31); break; case 31: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(31); break; case 32: if ((0x3ff000000000000L & l) != 0L) jjCheckNAddTwoStates(32, 33); break; case 34: if ((0x280000000000L & l) != 0L) jjCheckNAdd(35); break; case 35: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(35); break; default : break; } } while(i != startsAt); } else if (curChar < 128) { long l = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 0: case 11: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 12) kind = 12; jjCheckNAdd(11); break; case 2: if ((0x2000000020L & l) != 0L) jjAddStates(15, 16); break; case 6: if ((0xffffffffefffffffL & l) != 0L) jjCheckNAddStates(10, 12); break; case 7: if (curChar == 92) jjstateSet[jjnewStateCnt++] = 8; break; case 8: if ((0x14404410000000L & l) != 0L) jjCheckNAddStates(10, 12); break; case 14: jjAddStates(0, 2); break; case 19: jjCheckNAddTwoStates(19, 20); break; case 21: case 22: jjCheckNAddTwoStates(22, 20); break; case 29: if ((0x2000000020L & l) != 0L) jjAddStates(17, 18); break; case 33: if ((0x2000000020L & l) != 0L) jjAddStates(19, 20); break; default : break; } } while(i != startsAt); } else { int hiByte = (int)(curChar >> 8); int i1 = hiByte >> 6; long l1 = 1L << (hiByte & 077); int i2 = (curChar & 0xff) >> 6; long l2 = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 0: case 11: if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) break; if (kind > 12) kind = 12; jjCheckNAdd(11); break; case 6: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjAddStates(10, 12); break; case 14: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjAddStates(0, 2); break; case 19: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjCheckNAddTwoStates(19, 20); break; case 21: case 22: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjCheckNAddTwoStates(22, 20); break; default : break; } } while(i != startsAt); } if (kind != 0x7fffffff) { jjmatchedKind = kind; jjmatchedPos = curPos; kind = 0x7fffffff; } ++curPos; if ((i = jjnewStateCnt) == (startsAt = 36 - (jjnewStateCnt = startsAt))) return curPos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return curPos; } } } private final int jjStopStringLiteralDfa_0(int pos, long active0) { switch (pos) { case 0: if ((active0 & 0x100000000L) != 0L) return 1; if ((active0 & 0x200000000L) != 0L) return 13; return -1; default : return -1; } } private final int jjStartNfa_0(int pos, long active0) { return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); } private final int jjStartNfaWithStates_0(int pos, int kind, int state) { jjmatchedKind = kind; jjmatchedPos = pos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return pos + 1; } return jjMoveNfa_0(state, pos + 1); } private final int jjMoveStringLiteralDfa0_0() { switch(curChar) { case 33: jjmatchedKind = 35; return jjMoveStringLiteralDfa1_0(0x4000000L); case 37: return jjStopAtPos(0, 34); case 38: return jjMoveStringLiteralDfa1_0(0x8000000L); case 40: return jjStopAtPos(0, 40); case 41: return jjStopAtPos(0, 41); case 42: return jjStopAtPos(0, 31); case 43: return jjStopAtPos(0, 29); case 44: return jjStopAtPos(0, 20); case 45: return jjStopAtPos(0, 30); case 46: return jjStartNfaWithStates_0(0, 32, 1); case 47: return jjStartNfaWithStates_0(0, 33, 13); case 58: return jjStopAtPos(0, 42); case 59: return jjStopAtPos(0, 19); case 60: jjmatchedKind = 22; return jjMoveStringLiteralDfa1_0(0x1000000L); case 61: jjmatchedKind = 18; return jjMoveStringLiteralDfa1_0(0x800000L); case 62: jjmatchedKind = 21; return jjMoveStringLiteralDfa1_0(0x2000000L); case 91: return jjStopAtPos(0, 38); case 93: return jjStopAtPos(0, 39); case 94: jjmatchedKind = 36; return jjMoveStringLiteralDfa1_0(0x2000000000L); case 124: return jjMoveStringLiteralDfa1_0(0x10000000L); default : return jjMoveNfa_0(0, 0); } } private final int jjMoveStringLiteralDfa1_0(long active0) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { jjStopStringLiteralDfa_0(0, active0); return 1; } switch(curChar) { case 38: if ((active0 & 0x8000000L) != 0L) return jjStopAtPos(1, 27); break; case 61: if ((active0 & 0x800000L) != 0L) return jjStopAtPos(1, 23); else if ((active0 & 0x1000000L) != 0L) return jjStopAtPos(1, 24); else if ((active0 & 0x2000000L) != 0L) return jjStopAtPos(1, 25); else if ((active0 & 0x4000000L) != 0L) return jjStopAtPos(1, 26); break; case 94: if ((active0 & 0x2000000000L) != 0L) return jjStopAtPos(1, 37); break; case 124: if ((active0 & 0x10000000L) != 0L) return jjStopAtPos(1, 28); break; default : break; } return jjStartNfa_0(0, active0); } private final int jjMoveNfa_0(int startState, int curPos) { int[] nextStates; int startsAt = 0; jjnewStateCnt = 36; int i = 1; jjstateSet[0] = startState; int j, kind = 0x7fffffff; for (;;) { if (++jjround == 0x7fffffff) ReInitRounds(); if (curChar < 64) { long l = 1L << curChar; MatchLoop: do { switch(jjstateSet[--i]) { case 13: if (curChar == 42) jjCheckNAddTwoStates(19, 20); else if (curChar == 47) jjCheckNAddStates(0, 2); break; case 0: if ((0x3ff000000000000L & l) != 0L) { if (kind > 7) kind = 7; jjCheckNAddStates(3, 7); } else if (curChar == 47) jjAddStates(8, 9); else if (curChar == 36) { if (kind > 15) kind = 15; jjCheckNAdd(11); } else if (curChar == 34) jjCheckNAddStates(10, 12); else if (curChar == 46) jjCheckNAdd(1); break; case 1: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(1, 2); break; case 3: if ((0x280000000000L & l) != 0L) jjCheckNAdd(4); break; case 4: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(4); break; case 5: if (curChar == 34) jjCheckNAddStates(10, 12); break; case 6: if ((0xfffffffbffffdbffL & l) != 0L) jjCheckNAddStates(10, 12); break; case 8: if ((0x8400000000L & l) != 0L) jjCheckNAddStates(10, 12); break; case 9: if (curChar == 34 && kind > 11) kind = 11; break; case 10: if (curChar != 36) break; if (kind > 15) kind = 15; jjCheckNAdd(11); break; case 11: if ((0x3ff001000000000L & l) == 0L) break; if (kind > 15) kind = 15; jjCheckNAdd(11); break; case 12: if (curChar == 47) jjAddStates(8, 9); break; case 14: if ((0xffffffffffffdbffL & l) != 0L) jjCheckNAddStates(0, 2); break; case 15: if ((0x2400L & l) != 0L && kind > 5) kind = 5; break; case 16: if (curChar == 10 && kind > 5) kind = 5; break; case 17: if (curChar == 13) jjstateSet[jjnewStateCnt++] = 16; break; case 18: if (curChar == 42) jjCheckNAddTwoStates(19, 20); break; case 19: if ((0xfffffbffffffffffL & l) != 0L) jjCheckNAddTwoStates(19, 20); break; case 20: if (curChar == 42) jjAddStates(13, 14); break; case 21: if ((0xffff7fffffffffffL & l) != 0L) jjCheckNAddTwoStates(22, 20); break; case 22: if ((0xfffffbffffffffffL & l) != 0L) jjCheckNAddTwoStates(22, 20); break; case 23: if (curChar == 47 && kind > 6) kind = 6; break; case 24: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 7) kind = 7; jjCheckNAddStates(3, 7); break; case 25: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 7) kind = 7; jjCheckNAdd(25); break; case 26: if ((0x3ff000000000000L & l) != 0L) jjCheckNAddTwoStates(26, 27); break; case 27: if (curChar != 46) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(28, 29); break; case 28: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAddTwoStates(28, 29); break; case 30: if ((0x280000000000L & l) != 0L) jjCheckNAdd(31); break; case 31: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(31); break; case 32: if ((0x3ff000000000000L & l) != 0L) jjCheckNAddTwoStates(32, 33); break; case 34: if ((0x280000000000L & l) != 0L) jjCheckNAdd(35); break; case 35: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 9) kind = 9; jjCheckNAdd(35); break; default : break; } } while(i != startsAt); } else if (curChar < 128) { long l = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 0: case 11: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 15) kind = 15; jjCheckNAdd(11); break; case 2: if ((0x2000000020L & l) != 0L) jjAddStates(15, 16); break; case 6: if ((0xffffffffefffffffL & l) != 0L) jjCheckNAddStates(10, 12); break; case 7: if (curChar == 92) jjstateSet[jjnewStateCnt++] = 8; break; case 8: if ((0x14404410000000L & l) != 0L) jjCheckNAddStates(10, 12); break; case 14: jjAddStates(0, 2); break; case 19: jjCheckNAddTwoStates(19, 20); break; case 21: case 22: jjCheckNAddTwoStates(22, 20); break; case 29: if ((0x2000000020L & l) != 0L) jjAddStates(17, 18); break; case 33: if ((0x2000000020L & l) != 0L) jjAddStates(19, 20); break; default : break; } } while(i != startsAt); } else { int hiByte = (int)(curChar >> 8); int i1 = hiByte >> 6; long l1 = 1L << (hiByte & 077); int i2 = (curChar & 0xff) >> 6; long l2 = 1L << (curChar & 077); MatchLoop: do { switch(jjstateSet[--i]) { case 0: case 11: if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) break; if (kind > 15) kind = 15; jjCheckNAdd(11); break; case 6: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjAddStates(10, 12); break; case 14: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjAddStates(0, 2); break; case 19: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjCheckNAddTwoStates(19, 20); break; case 21: case 22: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) jjCheckNAddTwoStates(22, 20); break; default : break; } } while(i != startsAt); } if (kind != 0x7fffffff) { jjmatchedKind = kind; jjmatchedPos = curPos; kind = 0x7fffffff; } ++curPos; if ((i = jjnewStateCnt) == (startsAt = 36 - (jjnewStateCnt = startsAt))) return curPos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return curPos; } } } static final int[] jjnextStates = { 14, 15, 17, 25, 26, 27, 32, 33, 13, 18, 6, 7, 9, 21, 23, 3, 4, 30, 31, 34, 35, }; private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { switch(hiByte) { case 0: return ((jjbitVec2[i2] & l2) != 0L); default : if ((jjbitVec0[i1] & l1) != 0L) return true; return false; } } private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) { switch(hiByte) { case 0: return ((jjbitVec4[i2] & l2) != 0L); case 48: return ((jjbitVec5[i2] & l2) != 0L); case 49: return ((jjbitVec6[i2] & l2) != 0L); case 51: return ((jjbitVec7[i2] & l2) != 0L); case 61: return ((jjbitVec8[i2] & l2) != 0L); default : if ((jjbitVec3[i1] & l1) != 0L) return true; return false; } } public static final String[] jjstrLiteralImages = { "", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "\75", "\73", "\54", "\76", "\74", "\75\75", "\74\75", "\76\75", "\41\75", "\46\46", "\174\174", "\53", "\55", "\52", "\56", "\57", "\45", "\41", "\136", "\136\136", "\133", "\135", "\50", "\51", "\72", }; public static final String[] lexStateNames = { "NO_DOT_IN_IDENTIFIERS", "DEFAULT", }; public static final int[] jjnewLexState = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static final long[] jjtoToken = { 0x7fffffc9a81L, }; static final long[] jjtoSkip = { 0x7eL, }; protected JavaCharStream input_stream; private final int[] jjrounds = new int[36]; private final int[] jjstateSet = new int[72]; protected char curChar; public ParserTokenManager(JavaCharStream stream) { if (JavaCharStream.staticFlag) throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); input_stream = stream; } public ParserTokenManager(JavaCharStream stream, int lexState) { this(stream); SwitchTo(lexState); } public void ReInit(JavaCharStream stream) { jjmatchedPos = jjnewStateCnt = 0; curLexState = defaultLexState; input_stream = stream; ReInitRounds(); } private final void ReInitRounds() { int i; jjround = 0x80000001; for (i = 36; i-- > 0;) jjrounds[i] = 0x80000000; } public void ReInit(JavaCharStream stream, int lexState) { ReInit(stream); SwitchTo(lexState); } public void SwitchTo(int lexState) { if (lexState >= 2 || lexState < 0) throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); else curLexState = lexState; } protected Token jjFillToken() { Token t = Token.newToken(jjmatchedKind); t.kind = jjmatchedKind; String im = jjstrLiteralImages[jjmatchedKind]; t.image = (im == null) ? input_stream.GetImage() : im; t.beginLine = input_stream.getBeginLine(); t.beginColumn = input_stream.getBeginColumn(); t.endLine = input_stream.getEndLine(); t.endColumn = input_stream.getEndColumn(); return t; } int curLexState = 1; int defaultLexState = 1; int jjnewStateCnt; int jjround; int jjmatchedPos; int jjmatchedKind; public Token getNextToken() { int kind; Token specialToken = null; Token matchedToken; int curPos = 0; EOFLoop : for (;;) { try { curChar = input_stream.BeginToken(); } catch(java.io.IOException e) { jjmatchedKind = 0; matchedToken = jjFillToken(); return matchedToken; } switch(curLexState) { case 0: try { input_stream.backup(0); while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) curChar = input_stream.BeginToken(); } catch (java.io.IOException e1) { continue EOFLoop; } jjmatchedKind = 0x7fffffff; jjmatchedPos = 0; curPos = jjMoveStringLiteralDfa0_0(); break; case 1: try { input_stream.backup(0); while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) curChar = input_stream.BeginToken(); } catch (java.io.IOException e1) { continue EOFLoop; } jjmatchedKind = 0x7fffffff; jjmatchedPos = 0; curPos = jjMoveStringLiteralDfa0_1(); break; } if (jjmatchedKind != 0x7fffffff) { if (jjmatchedPos + 1 < curPos) input_stream.backup(curPos - jjmatchedPos - 1); if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { matchedToken = jjFillToken(); if (jjnewLexState[jjmatchedKind] != -1) curLexState = jjnewLexState[jjmatchedKind]; return matchedToken; } else { if (jjnewLexState[jjmatchedKind] != -1) curLexState = jjnewLexState[jjmatchedKind]; continue EOFLoop; } } int error_line = input_stream.getEndLine(); int error_column = input_stream.getEndColumn(); String error_after = null; boolean EOFSeen = false; try { input_stream.readChar(); input_stream.backup(1); } catch (java.io.IOException e1) { EOFSeen = true; error_after = curPos <= 1 ? "" : input_stream.GetImage(); if (curChar == '\n' || curChar == '\r') { error_line++; error_column = 0; } else error_column++; } if (!EOFSeen) { input_stream.backup(1); error_after = curPos <= 1 ? "" : input_stream.GetImage(); } throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Parser.jjt0000644000000000000000000004135010615400352020225 0ustar rootroot/*************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. This file contains the grammar from which the parser is generated. The parser generation tools being used are JavaCC and its component JJTree. JJTree processes the .jjt file and generates the .jj file. This file is then used be JavaCC to generate the final java classes. Knowledge of parser generation is definitely beneficial if you are planning to make changes to this file. Although many parts are self explanatory, it is helpful to know how the grammar is handled by JJTree and JavaCC. You can follow the structure of the grammar by starting in the line which reads "ASTStart Start() #Start : {}". From there you will be able to trace the same path the parser follows when parsing an expression. The concept of precedence is very important. Since this is a recursive descent parser, it is easy to see which operators have higher order of precedence. The following table outlines the order incorporated in this grammar. Order of precedence (from lowest to highest): || or (logical) && and (logical) == != equal, not equal < > <= >= less, greater, less or equal, greater or equal + - addition, subtraction * / % multiplication, division, modulus ! + - not, unary +/- ^ power The order of precedence is greatly inspired by the operator precedence of the C language. See "The C Programming Language" Kernighan & Richie 2nd Ed p.53. Java also uses a very similar precedence. Note that the '^' operator is used for bitwise exclusive OR in Java and C, but represents the power operator in this grammar. ***************************************************************/ /*************************************************************** OPTIONS ***************************************************************/ options { JAVA_UNICODE_ESCAPE = true; MULTI = true; VISITOR = true; VISITOR_EXCEPTION = "ParseException"; NODE_DEFAULT_VOID = true; // NODE_PACKAGE = "org.nfunk.jep.parser"; // BUILD_NODE_FILES=false; STATIC = false; // DEBUG_TOKEN_MANAGER = true; // DEBUG_PARSER = true; // DEBUG_LOOKAHEAD = true; } /*************************************************************** PARSER BEGIN ***************************************************************/ PARSER_BEGIN(Parser) package org.nfunk.jep; import java.util.Vector; import org.nfunk.jep.function.*; import org.nfunk.jep.type.*; public class Parser { private JEP jep; private SymbolTable symTab; private OperatorSet opSet; private int initialTokenManagerState = DEFAULT; public Node parseStream(java.io.Reader stream, JEP jep_in) throws ParseException { restart(stream,jep_in); // Parse the expression, and return the enable_tracing(); Node node = Start(); if (node == null) throw new ParseException("No expression entered"); return node.jjtGetChild(0); } /** * Restart the parse with the given stream. * @since 2.3.0 beta 1 */ public void restart(java.io.Reader stream, JEP jep_in) { ReInit(stream); this.token_source.SwitchTo(initialTokenManagerState); jep = jep_in; symTab = jep.getSymbolTable(); opSet = jep.getOperatorSet(); } /** * Continue parsing without re-initilising stream. * Allows renetrancy of parser so that strings like * "x=1; y=2; z=3;" can be parsed. * When a semi colon is encountered parsing finishes leaving the rest of the string unparsed. * Parsing can be resumed from the current position by using this method. * For example *

    	 * XJep j = new XJep();
    	 * Parser parse = j.getParse();
    	 * StringReader sr = new StringReader("x=1; y=2; z=3;");
    	 * parse.restart(sr,j);
    	 * Node node;
    	 * try {
    	 * while((node = j.continueParse())!=null) {
    	 *    j.println(node);
    	 * } }catch(ParseException e) {}
    	 * 
    */ public Node continueParse() throws ParseException { ASTStart node = Start(); if (node==null) return null; return node.jjtGetChild(0); } private void addToErrorList(String errorStr) { jep.errorList.addElement(errorStr); } /** * Sets the initial state that the token manager is in. * Can be used to change how x.x is interpreted, either as a single * identifier (DEFAULT) or as x x (NO_DOT_IN_IDENTIFIERS) * @param state the state to be in. Currently the only legal values are DEFAULT and NO_DOT_IN_IDENTIFIER */ public void setInitialTokenManagerState(int state) { initialTokenManagerState = state; } /** * Translate all escape sequences to characters. Inspired by Rob Millar's * unescape() method in rcm.util.Str fron the Web Sphinx project. * * @param inputStr String containing escape characters. * @return String with all escape sequences replaced. */ private String replaceEscape(String inputStr) { int len = inputStr.length(); int p = 0; int i; String metachars = "tnrbf\\\"'"; String chars = "\t\n\r\b\f\\\"'"; StringBuffer output = new StringBuffer(); while ((i = inputStr.indexOf('\\', p)) != -1) { output.append(inputStr.substring(p, i)); if (i+1 == len) break; // find metacharacter char metac = inputStr.charAt(i+1); // find the index of the metac int k = metachars.indexOf(metac); if (k == -1) { // didn't find the metachar, leave sequence as found. // This code should be unreachable if the parser // is functioning properly because strings containing // unknown escape characters should not be accepted. output.append('\\'); output.append(metac); } else { // its corresponding true char output.append(chars.charAt(k)); } // skip over both escape character & metacharacter p = i + 2; } // add the end of the input string to the output if (p < len) output.append(inputStr.substring(p)); return output.toString(); } } PARSER_END(Parser) /*************************************************************** SKIP ***************************************************************/ <*> SKIP : { " " | "\t" | "\n" | "\r" | <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> | <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> } /*************************************************************** TOKENS ***************************************************************/ <*> TOKEN : /* LITERALS */ { < INTEGER_LITERAL: > | < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* > | < FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* ()? | "." (["0"-"9"])+ ()? | (["0"-"9"])+ > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < STRING_LITERAL: "\"" ( (~["\"","\\","\n","\r"]) | ("\\" ["n","t","b","r","f","\\","'","\""] ) )* "\"" > } /* IDENTIFIERS Letters before version 2.22 < #LETTER: ["_","a"-"z","A"-"Z"] > In Ver 2.3.0.1 presence of . in an identifier is switchable. In the DEFAULT lexical state identifiers can contain a . In the NO_DOT_IN_IDENTIFIERS state identifiers cannot contain a . the state can be set by using Parser.setInitialTokenManagerState */ TOKEN: { (||".")*> | < #LETTER1: [ "\u0024", // $ "\u0041"-"\u005a", // A - Z "\u005f", // _ "\u0061"-"\u007a", // a - z "\u00c0"-"\u00d6", // Upper case symbols of Latin-1 Supplement "\u00d8"-"\u00f6", // Lower case symbols of Latin-1 Supplement "\u00f8"-"\u00ff", // More lower case symbols of Latin-1 Supplement "\u0100"-"\u1fff", // Many languages (including Greek) "\u3040"-"\u318f", // Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo "\u3300"-"\u337f", // CJK Compatibility "\u3400"-"\u3d2d", // CJK Unified Ideographs Extension A "\u4e00"-"\u9fff", // CJK Unified Ideographs "\uf900"-"\ufaff" // CJK Compatibility Ideographs ] > | < #DIGIT1: ["0"-"9"] > } TOKEN: { (|)*> | < #LETTER2: [ "\u0024", // $ "\u0041"-"\u005a", // A - Z "\u005f", // _ "\u0061"-"\u007a", // a - z "\u00c0"-"\u00d6", // Upper case symbols of Latin-1 Supplement "\u00d8"-"\u00f6", // Lower case symbols of Latin-1 Supplement "\u00f8"-"\u00ff", // More lower case symbols of Latin-1 Supplement "\u0100"-"\u1fff", // Many languages (including Greek) "\u3040"-"\u318f", // Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo "\u3300"-"\u337f", // CJK Compatibility "\u3400"-"\u3d2d", // CJK Unified Ideographs Extension A "\u4e00"-"\u9fff", // CJK Unified Ideographs "\uf900"-"\ufaff" // CJK Compatibility Ideographs ] > | < #DIGIT2: ["0"-"9"] > } /* OPERATORS */ <*> TOKEN: { < ASSIGN:"=" > // rjm | < SEMI: ";" > // rjm | < COMMA: "," > // rjm | < GT: ">" > | < LT: "<" > | < EQ: "==" > | < LE: "<=" > | < GE: ">=" > | < NE: "!=" > | < AND: "&&" > | < OR: "||" > | < PLUS: "+" > | < MINUS:"-" > | < MUL: "*" > | < DOT: "." > // rjm | < DIV: "/" > | < MOD: "%" > | < NOT: "!" > | < POWER:"^" > | < CROSS:"^^" > // rjm | < LSQ: "[" > // rjm | < RSQ: "]" > // rjm | < LRND: "(" > // rjm | < RRND: ")" > // rjm | < COLON: ":" > // rjm } /*************************************************************** GRAMMAR START ***************************************************************/ ASTStart Start() #Start : { } { Expression() ( | ) { return jjtThis; } | ( | ) { // njf - The next line is commented out in 2.3.0 since // two "No expression entered" errors are reported // in EvaluatorVisitor and Console (one from here // the other from ParseStream() ) // Decided to just return null, and handle the error // in ParseStream. // addToErrorList("No expression entered"); return null; } } // Expresions can be like // x=3 // x=y=3 parsed as x=(y=3) void Expression() : {} { LOOKAHEAD(LValue() ) // need to prevent javacc warning with left recusion AssignExpression() // rjm changes from OrExpresion | RightExpression() } void AssignExpression() : {} // rjm addition { ( LValue() Expression() { if (!jep.getAllowAssignment()) throw new ParseException( "Syntax Error (assignment not enabled)"); jjtThis.setOperator(opSet.getAssign()); } ) #FunNode(2) } void RightExpression() : { } { OrExpression() } void OrExpression() : { } { AndExpression() ( ( AndExpression() { jjtThis.setOperator(opSet.getOr()); } ) #FunNode(2) )* } void AndExpression() : { } { EqualExpression() ( ( EqualExpression() { jjtThis.setOperator(opSet.getAnd()); } ) #FunNode(2) )* } void EqualExpression() : { } { RelationalExpression() ( ( RelationalExpression() { jjtThis.setOperator(opSet.getNE()); } ) #FunNode(2) | ( RelationalExpression() { jjtThis.setOperator(opSet.getEQ()); } ) #FunNode(2) )* } void RelationalExpression() : { } { AdditiveExpression() ( ( AdditiveExpression() { jjtThis.setOperator(opSet.getLT()); } ) #FunNode(2) | ( AdditiveExpression() { jjtThis.setOperator(opSet.getGT()); } ) #FunNode(2) | ( AdditiveExpression() { jjtThis.setOperator(opSet.getLE()); } ) #FunNode(2) | ( AdditiveExpression() { jjtThis.setOperator(opSet.getGE()); } ) #FunNode(2) )* } void AdditiveExpression() : { } { MultiplicativeExpression() ( ( MultiplicativeExpression() { jjtThis.setOperator(opSet.getAdd()); } ) #FunNode(2) | ( MultiplicativeExpression() { jjtThis.setOperator(opSet.getSubtract()); } ) #FunNode(2) )* } void MultiplicativeExpression() : { } { UnaryExpression() ( ( PowerExpression() { if (!jep.implicitMul) throw new ParseException( "Syntax Error (implicit multiplication not enabled)"); jjtThis.setOperator(opSet.getMultiply()); } ) #FunNode(2) | ( UnaryExpression() { jjtThis.setOperator(opSet.getMultiply()); } ) #FunNode(2) | ( UnaryExpression() { jjtThis.setOperator(opSet.getDot()); } ) #FunNode(2) | ( UnaryExpression() { jjtThis.setOperator(opSet.getCross()); } ) #FunNode(2) | (
    UnaryExpression() { jjtThis.setOperator(opSet.getDivide()); } ) #FunNode(2) | ( UnaryExpression() { jjtThis.setOperator(opSet.getMod()); } ) #FunNode(2) )* } void UnaryExpression() : { } { ( UnaryExpression()) | ( UnaryExpression() { jjtThis.setOperator(opSet.getUMinus()); } ) #FunNode(1) | ( UnaryExpression() { jjtThis.setOperator(opSet.getNot()); } ) #FunNode(1) | PowerExpression() } void PowerExpression() : { } { UnaryExpressionNotPlusMinus() [ ( UnaryExpression() { jjtThis.setOperator(opSet.getPower()); } ) #FunNode(2) ] } void UnaryExpressionNotPlusMinus() : { String identString = ""; int type; } { AnyConstant() | LOOKAHEAD(ArrayAccess()) ArrayAccess() | LOOKAHEAD({ (getToken(1).kind == INDENTIFIER1 || getToken(1).kind == INDENTIFIER2) && jep.funTab.containsKey(getToken(1).image) }) Function() | Variable() | Expression() | // LOOKAHEAD( Expression() ) // RangeExpression() // | ListExpression() } void ListExpression() #FunNode: { jjtThis.setOperator(opSet.getList()); } { Expression() ( Expression() )* } /* void RangeExpression() #FunNode: { jjtThis.setOperator(opSet.getRange()); } { Expression() ( Expression() )+ } */ void LValue() : { } { LOOKAHEAD(ArrayAccess()) ArrayAccess() | Variable() } void ArrayAccess() : { } { Variable() ListExpression() { jjtThis.setOperator(opSet.getElement()); } #FunNode(2) } void Variable() : { String identString = ""; } { (identString = Identifier() { if (symTab.containsKey(identString)) { jjtThis.setVar(symTab.getVar(identString)); } else { if (jep.allowUndeclared) { jjtThis.setVar(symTab.makeVarIfNeeded(identString)); } else { addToErrorList("Unrecognized symbol \"" + identString +"\""); } } } ) #VarNode } void Function() : { int reqArguments = 0; String identString = ""; } { ( identString = Identifier() { if (jep.funTab.containsKey(identString)) { //Set number of required arguments reqArguments = ((PostfixMathCommandI)jep.funTab.get(identString)).getNumberOfParameters(); jjtThis.setFunction(identString, (PostfixMathCommandI)jep.funTab.get(identString)); } else { addToErrorList("!!! Unrecognized function \"" + identString +"\""); } } ArgumentList(reqArguments, identString) ) #FunNode } void ArgumentList(int reqArguments, String functionName) : { int count = 0; String errorStr = ""; } { [ Expression() { count++; } ( Expression() { count++; } )* ] { if(reqArguments == -1) { if(!((PostfixMathCommandI)jep.funTab.get(functionName)).checkNumberOfParameters(count)) { errorStr = "Function \"" + functionName +"\" illegal number of arguments " + count; addToErrorList(errorStr); } } else if (reqArguments != count) { errorStr = "Function \"" + functionName +"\" requires " + reqArguments + " parameter"; if (reqArguments!=1) errorStr += "s"; addToErrorList(errorStr); } } } String Identifier() : { Token t; } { ( t = | t = ) { return t.image; } } void AnyConstant() #Constant: { Token t; Object value; } { t= { // strip away double quotes at end of string String temp = (t.image).substring(1,t.image.length()-1); // replace escape characters temp = replaceEscape(temp); jjtThis.setValue(temp); } | value = RealConstant() { jjtThis.setValue(value); // } // | // value = Array() { // jjtThis.setValue(value); } } /* Vector Array() : { Object value; Vector result = new Vector(); } { value = RealConstant() { result.addElement(value); } ( value = RealConstant() { result.addElement(value); } )* { return result; } } */ Object RealConstant() : { Token t; Object value; } { (t= | t=) { try { value = jep.getNumberFactory().createNumber(t.image); } catch (Exception e) { value = null; addToErrorList("Can't parse \"" + t.image + "\""); } return value; } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Token.java0000644000000000000000000000526510615400352020210 0ustar rootroot/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ package org.nfunk.jep; /** * Describes the input token stream. */ public class Token { /** * An integer that describes the kind of this token. This numbering * system is determined by JavaCCParser, and a table of these numbers is * stored in the file ...Constants.java. */ public int kind; /** * beginLine and beginColumn describe the position of the first character * of this token; endLine and endColumn describe the position of the * last character of this token. */ public int beginLine, beginColumn, endLine, endColumn; /** * The string image of the token. */ public String image; /** * A reference to the next regular (non-special) token from the input * stream. If this is the last token from the input stream, or if the * token manager has not read tokens beyond this one, this field is * set to null. This is true only if this token is also a regular * token. Otherwise, see below for a description of the contents of * this field. */ public Token next; /** * This field is used to access special tokens that occur prior to this * token, but after the immediately preceding regular (non-special) token. * If there are no such special tokens, this field is set to null. * When there are more than one such special token, this field refers * to the last of these special tokens, which in turn refers to the next * previous special token through its specialToken field, and so on * until the first special token (whose specialToken field is null). * The next fields of special tokens refer to other special tokens that * immediately follow it (without an intervening regular token). If there * is no such token, this field is null. */ public Token specialToken; /** * Returns the image. */ public String toString() { return image; } /** * Returns a new Token object, by default. However, if you want, you * can create and return subclass objects based on the value of ofKind. * Simply add the cases to the switch for all those special cases. * For example, if you have a subclass of Token called IDToken that * you want to create if ofKind is ID, simlpy add something like : * * case MyParserConstants.ID : return new IDToken(); * * to the following switch statement. Then you can cast matchedToken * variable to the appropriate type and use it in your lexical actions. */ public static final Token newToken(int ofKind) { switch(ofKind) { default : return new Token(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jep/Node.java0000644000000000000000000000316210615400352020007 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /* Generated By:JJTree: Do not edit this line. Node.java */ /* All AST nodes must implement this interface. It provides basic machinery for constructing the parent and child relationships between nodes. */ package org.nfunk.jep; import java.util.*; public interface Node { /** This method is called after the node has been made the current node. It indicates that child nodes can now be added to it. */ public void jjtOpen(); /** This method is called after all the child nodes have been added. */ public void jjtClose(); /** This pair of methods are used to inform the node of its parent. */ public void jjtSetParent(Node n); public Node jjtGetParent(); /** This method tells the node to add its argument to the node's list of children. */ public void jjtAddChild(Node n, int i); /** This method returns a child node. The children are numbered from zero, left to right. */ public Node jjtGetChild(int i); /** Return the number of children the node has. */ public int jjtGetNumChildren(); /** Accept the visitor. **/ public Object jjtAccept(ParserVisitor visitor, Object data) throws ParseException; /** Push the value of the node on the stack * public void evaluate(Stack stack) throws ParseException; */ } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/0000755000000000000000000000000010615400352020014 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/package.html0000644000000000000000000000140410615400352022274 0ustar rootroot A set of examples using JEP. The following examples are provided:
    • SimpleTest - The simplest example that demonstrates the use of JEP for evaluation of a single expression
    • Console - A simple command-line evaluator.
    • Evaluator - An applet that evaluates expressions entered.
    • FunctionPlotter - An applet that plots arbitrary functions entered by the user.
    • Fractal - A fractal drawing applet based on an arbitrary function.
    • JEPTester - Tests JEP evaluation by comparing expressions from consecutive lines of a text file.
    • ThreadTest - A brute force test for detecting mutlithreading issues
    • LargeExpressionTest - A simple class to test evaluation of large expression.
    jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/FractalCanvas.java0000644000000000000000000001637010615400352023376 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; import java.awt.*; import java.util.*; import org.nfunk.jep.*; import org.nfunk.jep.type.*; import org.nfunk.jep.evaluation.*; /** * This class performs the drawing of the fractal. */ public class FractalCanvas extends Canvas { private static final long serialVersionUID = -593341831485283712L; private int scaleX, scaleY; private Dimension dimensions; private int iterations, nEvals; private boolean hasError; private JEP myParser; private ExpressionCompiler expressionCompiler; private CommandEvaluator evaluator; private CommandElement[] commands; private SymbolTable symTab; private java.awt.TextField exprField; /** * Constructor. */ public FractalCanvas(String initialExpression, java.awt.TextField exprField_in) { iterations = 20; nEvals = 0; scaleX = 100; scaleY = 100; dimensions = getSize(); hasError = true; exprField = exprField_in; initParser(initialExpression); expressionCompiler = new ExpressionCompiler(); evaluator = new CommandEvaluator(); symTab = myParser.getSymbolTable(); } /** * Initializes the parser */ private void initParser(String initialExpression) { //Init Parser myParser = new JEP(); //Load the standard functions myParser.addStandardFunctions(); //Load the standard myParser.addStandardConstants(); myParser.addComplex(); //Add and initialize z to (0,0) myParser.addVariable("z",0,0); myParser.addVariable("c",0,0); setExpressionString(initialExpression); } /** * Parses a new expression */ public void setExpressionString(String newString) { nEvals = 0; //Parse the new expression myParser.parseExpression(newString); //Find out whether there was an error in the expression hasError = myParser.hasError(); if (hasError) exprField.setForeground(Color.red); else exprField.setForeground(Color.black); } public void setIterations(int iterations_in) { iterations = iterations_in; } private void paintWhite(Graphics g) { g.setColor(Color.white); g.fillRect(0,0,dimensions.width,dimensions.height); } private void paintFractalSansJEP(Graphics g) { System.out.println("paintFractalSansJEP()"); //paintRegion(g, 0,0,256,256,0,8); System.out.println("done."); } private void paintRegion(Graphics g, int x, int y, int width, int height, int depth, int depth_max) { double re, im, p, q, resq, imsq, imtemp; int count; if (depth == depth_max) { p = (double)(x+width/2-230)/scaleX; q = (double)(y+height/2-150)/scaleY; count = 0; re = 0; im = 0; resq = 0; imsq = 0; while ((count < iterations) && ((resq + imsq) < 4.0)) { imtemp = 2 * re * im; re = resq - imsq + p; im = imtemp + q; count++; resq = re * re; imsq = im * im; nEvals++; } //System.out.println("At: " + x + ", " + y + ": " + count + " "+ result); if (count != iterations) { g.setColor(new Color(0, 0, (int)(255.0*(Math.sqrt(count)/Math.sqrt(iterations))))); g.fillRect(x, y, width, height); } } else { paintRegion(g, x, y, width/2, height - height/2, depth+1, depth_max); paintRegion(g, x + width/2, y, width - width/2, height/2, depth+1, depth_max); paintRegion(g, x, y + height/2, width/2, height - height/2, depth+1, depth_max); paintRegion(g, x + width/2, y + height/2, width - width/2, height - height/2, depth+1, depth_max); } } private void paintFractal(Graphics g) { Complex z,c,temp; int count; c = myParser.addVariable("c", 0, 0); z = myParser.addVariable("z", 0, 0); for (int x = 0; x <= (dimensions.width-1); x++) { for (int y = 0; y <= (dimensions.height-1); y++) { count = 0; c.set((double)(x-230)/scaleX, (double)(y-150)/scaleY); z.set(0,0); while ((count < iterations) && (z.abs2() < 4.0)) { z.set(myParser.getComplexValue()); count++; nEvals++; } if (count != iterations) { g.setColor(new Color(0, 0, (int)(255.0*(Math.sqrt(count)/Math.sqrt(iterations))))); g.fillRect(x, y, 1, 1); } } } } private void paintFractalWithCompiler(Graphics g) { Complex z,c,temp; int count; c = myParser.addVariable("c", 0, 0); z = myParser.addVariable("z", 0, 0); try { commands = expressionCompiler.compile(myParser.getTopNode()); } catch (ParseException e) { System.out.println("Failed to compile expression"); e.printStackTrace(); } for (int x = 0; x <= (dimensions.width-1); x++) { for (int y = 0; y <= (dimensions.height-1); y++) { count = 0; c.set((double)(x-230)/scaleX, (double)(y-150)/scaleY); z.set(0,0); while ((count < iterations) && (z.abs2() < 4.0)) { try { temp = (Complex)evaluator.evaluate(commands, symTab); z.set(temp); } catch (Exception e) { //System.out.println(e.toString()); e.printStackTrace(); } count++; nEvals++; } if (count != iterations) { g.setColor(new Color(0, 0, (int)(255.0*(Math.sqrt(count)/Math.sqrt(iterations))))); g.fillRect(x, y, 1, 1); } } } } private void paintNonJEPFractal(Graphics g) { double re, im, p, q, resq, imsq, imtemp; int count; for (int x = 0; x <= (dimensions.width-1); x++) { for (int y = 0; y <= (dimensions.height-1); y++) { p = (double)(x-230)/scaleX; q = (double)(y-150)/scaleY; count = 0; re = 0; im = 0; resq = 0; imsq = 0; while ( (count < iterations) && ((resq + imsq) < 4.0) ) { imtemp = 2 * re * im; re = resq - imsq + p; im = imtemp + q; resq = re * re; imsq = im * im; count++; nEvals++; } //System.out.println("At: " + x + ", " + y + ": " + count + " "+ result); if (count != iterations) { g.setColor(new Color(0, 0, (int)(255.0*(Math.sqrt(count)/Math.sqrt(iterations))))); g.fillRect(x, y, 1, 1); } } } } public void paint(Graphics g) { Date start, finish; dimensions = getSize(); paintWhite(g); if (!hasError) { System.out.println("Painting... "); start = new Date(); nEvals = 0; //paintFractal(g); paintFractalWithCompiler(g); //paintNonJEPFractal(g); finish = new Date(); System.out.print("done. sec/eval: "); double seconds = ( finish.getTime() - start.getTime() ) / 1000.0; System.out.println(seconds/nEvals); } /* if (!initializedBuffer) { buffer = createImage(dimensions.width, dimensions.height); initializedBuffer = true; } Graphics buffergc = buffer.getGraphics(); if (changedFunction) { paintWhite(buffergc); if (!hasError) paintFractal(buffergc); g.drawImage(buffer, 0, 0, null); changedFunction = false; } else { g.drawImage(buffer, 0, 0, null); }*/ } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/FunctionPlotter.java0000644000000000000000000000467410615400352024031 0ustar rootroot/* HTML code for applet: */ package org.nfunk.jepexamples; import java.applet.*; import java.awt.*; /** * This applet is a demonstration of the possible applications of the JEP * mathematical expression parser.

    * The FunctionPlotter class arranges the text field and GraphCanvas classes * and requests a repainting of the graph when the expression in the text * field changes. All plotting (and interaction with the JEP API) is preformed * in GraphCanvas class. */ public class FunctionPlotter extends Applet { private static final long serialVersionUID = -27867883051236035L; /** The expression field */ private java.awt.TextField exprField; /** The canvas for plotting the graph */ private GraphCanvas graphCanvas; /** * Initializes the applet FunctionPlotter */ public void init () { initComponents(); } /** * Sets the layout of the applet window to BorderLayout, creates all * the components and associates them with event listeners if neccessary. */ private void initComponents () { setLayout(new BorderLayout()); setBackground (java.awt.Color.white); // get the initial expression from the parameters String expr = getParameter("initialExpression"); // write the expression into the text field if (expr!=null) exprField = new java.awt.TextField(expr); else exprField = new java.awt.TextField(""); // adjust various settings for the expression field exprField.setBackground (java.awt.Color.white); exprField.setName ("exprField"); exprField.setFont (new java.awt.Font ("Dialog", 0, 11)); exprField.setForeground (java.awt.Color.black); exprField.addTextListener (new java.awt.event.TextListener () { public void textValueChanged (java.awt.event.TextEvent evt) { exprFieldTextValueChanged (evt); } } ); add ("North", exprField); // create the graph canvas and add it graphCanvas = new GraphCanvas(expr, exprField); add ("Center", graphCanvas); } /** * Repaints the graphCanvas whenever the text in the expression field * changes. */ private void exprFieldTextValueChanged(java.awt.event.TextEvent evt) { String newExpressionString = exprField.getText(); graphCanvas.setExpressionString(newExpressionString); graphCanvas.repaint(); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/GraphCanvas.java0000644000000000000000000001223210615400352023054 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; import java.awt.*; import org.nfunk.jep.JEP; /** * This class plots a graph using the JEP API. */ public class GraphCanvas extends Canvas { private static final long serialVersionUID = -3169263228971794887L; /** Scaling of the graph in x and y directions */ private int scaleX, scaleY; /** Dimensions of the canvas */ private Dimension dimensions; /** Buffer for the graph */ private Image buffer; /** Boolean flags */ private boolean initializedBuffer, changedFunction, hasError; /** Math parser */ private JEP myParser; /** The expression field where the functions are entered */ private java.awt.TextField exprField; /** * Constructor */ public GraphCanvas(String initialExpression, java.awt.TextField exprField_in) { scaleX = 1; scaleY = 1; dimensions = getSize(); initializedBuffer = false; changedFunction = true; hasError = true; exprField = exprField_in; initParser(initialExpression); } /** * Initializes the parser */ private void initParser(String initialExpression) { // Init Parser myParser = new JEP(); // Allow implicit multiplication myParser.setImplicitMul(true); // Load the standard functions myParser.addStandardFunctions(); // Load the standard constants, and complex variables/functions myParser.addStandardConstants(); myParser.addComplex(); // Add and initialize x to 0 myParser.addVariable("x",0); // Set the string to the initial value setExpressionString(initialExpression); } /** * Sets a new string to be used as function */ public void setExpressionString(String newString) { // Parse the new expression myParser.parseExpression(newString); // Find out whether there was an error in the expression hasError = myParser.hasError(); if (hasError) exprField.setForeground(Color.red); else exprField.setForeground(Color.black); changedFunction = true; } /** * @return The value of the function at an x value of the parameter. */ private double getYValue(double xValue) { // Save the new value in the symbol table myParser.addVariable("x", xValue); return myParser.getValue(); } /** * Fills the background with white. */ private void paintWhite(Graphics g) { g.setColor(Color.white); g.fillRect(0,0,dimensions.width,dimensions.height); } /** * Paints the axes for the graph. */ private void paintAxes(Graphics g) { g.setColor(new Color(204,204,204)); g.drawLine(0,dimensions.height/2,dimensions.width-1,dimensions.height/2); g.drawLine(dimensions.width/2,0,dimensions.width/2,dimensions.height-1); } /** * Paints the graph of the function. */ private void paintCurve(Graphics2D g) { boolean firstpoint=true; int lastX=0, lastY=0; g.setColor(Color.black); for (int xAbsolute = 0; xAbsolute <= (dimensions.width-1); xAbsolute++) { double xRelative = (xAbsolute - dimensions.width/2)/scaleX; double yRelative = getYValue(xRelative); int yAbsolute = (int)(-yRelative*scaleY + dimensions.height/2); if (yAbsolute > dimensions.height) yAbsolute = dimensions.height; if (yAbsolute < -1) yAbsolute = -1; if (firstpoint != true) g.drawLine(lastX, lastY, xAbsolute, yAbsolute); else firstpoint = false; lastX = xAbsolute; lastY = yAbsolute; } } /** * Draws the graph to the Graphics object. If the image buffer has been * initialized, and the function has not changed since the last paint, * the image stored in the buffer is drawn straight to the Graphics * object with drawImage(). *

    * If a image buffer has not yet been initialized (i.e. first time after * being started) the buffer is created with createImage(). *

    * If the function has changed since the last paint, the graph is first * drawn on the buffer image, then that image is drawn on the Graphics * object. */ public void paint(Graphics g_in) { boolean changedDimensions = !dimensions.equals(getSize()); Graphics2D g = (Graphics2D) g_in; // If the buffer has not been initialized, do it now if (!initializedBuffer || changedDimensions) { dimensions = getSize(); buffer = createImage(dimensions.width,dimensions.height); initializedBuffer = true; } // Get the Graphics instance of the buffer Graphics2D buffergc = (Graphics2D) buffer.getGraphics(); // Turn on anti aliasing buffergc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Redraw the function on the buffer if (changedFunction || changedDimensions) { paintWhite(buffergc); paintAxes(buffergc); if (!hasError) paintCurve(buffergc); changedFunction = false; } // Copy the buffer to g g.drawImage(buffer, 0, 0, null); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/Console.java0000644000000000000000000000620610615400352022265 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ /** * Console - JEP Example Applet * Copyright (c) 2000 Nathan Funk * * @author Nathan Funk */ package org.nfunk.jepexamples; import java.io.*; import org.nfunk.jep.JEP; //import org.nfunk.sovler.*; /** * This class implements a simple command line utility for evaluating * mathematical expressions. * * Usage: java org.nfunk.jepexamples.Console [expression] * * If an argument is passed, it is interpreted as an expression * and evaluated. Otherwise, a prompt is printed, and the user can enter * expressions to be evaluated. To exit from the command prompt a 'q' must * be entered. */ class Console { /** The prompt string */ private String prompt; /** The input reader */ private BufferedReader br; /** Constructor */ public Console() { prompt = "JEP > "; br = new BufferedReader(new InputStreamReader(System.in)); } /** Creates a new Console object and calls run() */ public static void main(String args[]) throws IOException { Console c = new Console(); c.run(args); } /** The input loop */ public void run(String args[]) throws IOException { String command=""; JEP j = new JEP(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); //j.setTraverse(true); if (args.length>0) { // evaluate the expression passed as arguments String temp = args[0]; for (int i=1; i */ package org.nfunk.jepexamples; import java.applet.*; import java.awt.*; import java.awt.event.*; public class Fractal extends Applet implements ActionListener { private static final long serialVersionUID = -1825231934586941116L; private TextField exprField, itField; private Button button; private FractalCanvas complexCanvas; /** Initializes the applet Fractal */ public void init () { initComponents(); } private void initComponents () { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); c.fill = GridBagConstraints.BOTH; // Expression field String expr = getParameter("initialExpression"); if (expr!=null) exprField = new TextField(expr); else exprField = new TextField(""); exprField.setBackground (java.awt.Color.white); exprField.setName ("exprField"); exprField.setFont (new Font ("Dialog", 0, 11)); exprField.setForeground (Color.black); exprField.addTextListener (new java.awt.event.TextListener () { public void textValueChanged (java.awt.event.TextEvent evt) { exprFieldTextValueChanged (evt); } } ); c.gridx = 0; c.gridy = 0; c.weightx = 1; gridbag.setConstraints(exprField, c); add(exprField); // RENDER BUTTON c.gridx = 1; c.gridy = 0; c.weightx = 0.2; button = new Button("Render"); gridbag.setConstraints(button, c); add(button); button.addActionListener(this); // Iterations field itField = new TextField("20"); itField.addTextListener (new java.awt.event.TextListener () { public void textValueChanged (java.awt.event.TextEvent evt) { itFieldTextValueChanged(evt); } } ); c.gridx = 0; c.gridy = 1; c.weightx = 1; gridbag.setConstraints(itField, c); add(itField); // CANVAS c.gridx = 0; c.gridy = 2; c.gridwidth = 2; c.weighty = 1; // button2 = new Button("test"); complexCanvas = new FractalCanvas(expr, exprField); gridbag.setConstraints(complexCanvas, c); add(complexCanvas); } private void exprFieldTextValueChanged (java.awt.event.TextEvent evt) { String newExpressionString = exprField.getText(); complexCanvas.setExpressionString(newExpressionString); //complexCanvas.repaint(); } private void itFieldTextValueChanged (java.awt.event.TextEvent evt) { Integer newIterationsValue = new Integer(itField.getText()); complexCanvas.setIterations(newIterationsValue.intValue()); //complexCanvas.repaint(); } public void actionPerformed(ActionEvent ae) { String str = ae.getActionCommand(); if (str.equals("Render")) { String newExpressionString = exprField.getText(); complexCanvas.setExpressionString(newExpressionString); complexCanvas.repaint(); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/ThreadTestThread.java0000644000000000000000000000167010615400352024062 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; /** * The ThreadTestThread waits for 5 seconds before calling the evaluate method * of the ThreadTest instance. *

    * Thanks to Matthew Baird and Daniel Teng for this code. */ public class ThreadTestThread extends Thread { ThreadTest test; public ThreadTestThread(ThreadTest test_in) { test = test_in; } public void run() { try { Thread.sleep(5000); test.evaluate(); Thread.yield(); } catch (Exception e) { System.out.println(e.getMessage()); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/ThreadTest.java0000644000000000000000000000420510615400352022727 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; /** * This class tests the thread safety of the JEP package with a brute force * approach. 1000 threads are started, and each one invokes the evaluate method. * The evaluate method creates 10 JEP instances. Note that running this class * successfully does not necessarily ensure that no errors will ever occur. *

    * Thanks to Matthew Baird and Daniel Teng for this code. */ public class ThreadTest { static long time = 0; /** * Main method. Launches many threads. */ public static void main(String[] args) { int n = 1000; System.out.println("Starting " + n + " threads..."); ThreadTest test = new ThreadTest(); for (int i = 0; i < n; i++) { ThreadTestThread t = new ThreadTestThread(test); t.start(); } System.out.println("Returned from starting threads. Threads may still need to terminate."); // TODO: check why application appears to end before all thread exit } public ThreadTest() { } /** * Perform a simple evaluation using a new JEP instance. This method is * called by all ThreadTestThreads at very much the same time. */ public void evaluate() { for (int i = 0; i < 10; i++) { org.nfunk.jep.JEP myParser = new org.nfunk.jep.JEP(); String fooValue = null; Math.random(); if (Math.random() > 0.5) { fooValue = "NLS"; } else { fooValue = "NLT"; } // TODO: add more involved calculations so the execution time of the // evaluation is longer (leading to more possible thread conflicts) myParser.addVariable("foo", fooValue); myParser.parseExpression("foo == \"" + fooValue + "\""); if (myParser.getValue() != 1.0) System.out.println("Wrong value returned"); if (myParser.hasError()) System.out.println(myParser.getErrorInfo()); } } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/SimpleTest.java0000644000000000000000000000146510615400352022756 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; import org.nfunk.jep.*; /** * A seven line program for testing whether the JEP library can be found * by the compiler and at run-time.
    * Upon successful compilation and running of the program, the program should * print out one line: "1+2 = 3.0" */ public class SimpleTest { public static void main(String args[]) { JEP myParser = new JEP(); myParser.parseExpression("1+2"); System.out.println("1+2 = " + myParser.getValue()); } } jep-2.4.1-ext-1.1.1-gpl/src/org/nfunk/jepexamples/LargeExpressionTest.java0000644000000000000000000000317110615400352024633 0ustar rootroot/***************************************************************************** JEP 2.4.1, Extensions 1.1.1 April 30 2007 (c) Copyright 2007, Nathan Funk and Richard Morris See LICENSE-*.txt for license information. *****************************************************************************/ package org.nfunk.jepexamples; import java.util.*; import org.nfunk.jep.JEP; /** * This example tests how the evaluation time is influenced by the size of the * expression and symbol table. */ public class LargeExpressionTest { public static void main(String args[]) { int nEvals = 500; int nVars = 1000; Date start, finish; String str = ""; JEP myParser = new JEP(); // Test small symbol table for (int i=0; i<10; i++) { myParser.addVariable("v"+i, 0); str += "+" + "v" + i; } myParser.parseExpression(str); System.out.print("Evaluating with small symbol table... "); start = new Date(); for (int i=0; i */ package org.nfunk.jepexamples; import java.applet.Applet; import java.awt.*; import java.awt.event.*; import org.nfunk.jep.JEP; /** * This applet is an simple example for how JEP can be used to evaluate * expressions. It also displays the different options, and the effects of * their settings. */ public class Evaluator extends Applet { private static final long serialVersionUID = 4592714713689369505L; /** Parser */ private JEP myParser; /** Current xValue */ private double xValue; /* GUI components */ private TextField exprField, xField; private TextArea errorTextArea; private Label resultLabel; private Checkbox implicitCheckbox, undeclaredCheckbox; /** * This method is called if the applet is run as an standalone * program. It creates a frame for the applet and adds the applet * to that frame. */ public static void main(String args[]) { Evaluator a = new Evaluator(); a.init(); a.start(); Frame f = new Frame("Evaluator"); f.add("Center", a); f.setSize(400,200); f.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } } ); // f.show(); f.setVisible(true); } /** * The initialization function of the applet. It adds all the * components such as text fields and also creates the JEP object */ public void init() { // initialize value for x xValue = 10; // add the interface components addGUIComponents(); // Set up the parser (more initialization in parseExpression()) myParser = new JEP(); myParser.initFunTab(); // clear the contents of the function table myParser.addStandardFunctions(); myParser.setTraverse(true); // simulate changed options to initialize output optionsChanged(); } /** * Creates and adds the necessary GUI components. */ private void addGUIComponents() { setBackground(Color.white); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); // Expression c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 0.0; Label exprFieldp = new Label("Expression: ", Label.RIGHT); gridbag.setConstraints(exprFieldp,c); add(exprFieldp); c.weightx = 0.8; exprField = new TextField(27); gridbag.setConstraints(exprField,c); add(exprField); // x c.weightx = 0.0; Label xFieldp = new Label("x: ", Label.RIGHT); gridbag.setConstraints(xFieldp,c); add(xFieldp); c.weightx = 0.2; c.gridwidth = GridBagConstraints.REMAINDER; xField = new TextField("" + xValue,4); gridbag.setConstraints(xField,c); add(xField); // Result c.weightx = 0.0; c.gridwidth = 1; Label resultLabelText = new Label("Result: ", Label.RIGHT); gridbag.setConstraints(resultLabelText,c); add(resultLabelText); c.weightx = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; resultLabel = new Label("", Label.LEFT); gridbag.setConstraints(resultLabel,c); add(resultLabel); // Options c.weightx = 0.0; c.gridwidth = 1; Label optionsLabelText = new Label("Options: ", Label.RIGHT); gridbag.setConstraints(optionsLabelText,c); add(optionsLabelText); c.weightx = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; implicitCheckbox = new Checkbox("Implicit multiplication", true); gridbag.setConstraints(implicitCheckbox,c); add(implicitCheckbox); c.weightx = 0.0; c.gridwidth = 1; Label spaceLabelText = new Label(" ", Label.RIGHT); gridbag.setConstraints(spaceLabelText,c); add(spaceLabelText); c.weightx = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; undeclaredCheckbox = new Checkbox("Allow undeclared identifiers"); gridbag.setConstraints(undeclaredCheckbox,c); add(undeclaredCheckbox); // Errors c.weightx = 0.0; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTH; Label errorLabel = new Label("Errors: ", Label.RIGHT); gridbag.setConstraints(errorLabel,c); add(errorLabel); c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; errorTextArea = new TextArea(""); errorTextArea.setEditable(false); errorTextArea.setBackground(Color.white); gridbag.setConstraints(errorTextArea,c); add(errorTextArea); // Set up listeners exprField.addTextListener( new TextListener() { public void textValueChanged(TextEvent evt) { exprFieldTextValueChanged(); } } ); xField.addTextListener( new TextListener() { public void textValueChanged(TextEvent evt) { xFieldTextValueChanged(); } } ); implicitCheckbox.addItemListener( new ItemListener() { public void itemStateChanged(ItemEvent evt) { optionsChanged(); } } ); undeclaredCheckbox.addItemListener( new ItemListener() { public void itemStateChanged(ItemEvent evt) { optionsChanged(); } } ); } /** * Parses the current expression in the exprField. This method also * re-initializes the contents of the symbol and function tables. This * is necessary because the "allow undeclared variables" option adds * variables from expressions to the symbol table. */ private void parseExpression() { myParser.initSymTab(); // clear the contents of the symbol table myParser.addStandardConstants(); myParser.addComplex(); // among other things adds i to the symbol table myParser.addVariable("x", xValue); myParser.parseExpression(exprField.getText()); } /** * Whenever the expression is changed, this method is called. * The expression is parsed, and the updateResult() method * invoked. */ private void exprFieldTextValueChanged() { parseExpression(); updateResult(); } /** * Every time the value in the x field is changed, this method is * called. It takes the value from the field as a double, and * sets the value of x in the parser. */ private void xFieldTextValueChanged() { try { xValue = Double.valueOf(xField.getText()).doubleValue(); } catch (NumberFormatException e) { System.out.println("Invalid format in xField"); xValue = 0; } myParser.addVariable("x", xValue); updateResult(); } /** * Every time one of the options is changed, this method is called. The * parser settings are adjusted to the GUI settings, the expression is * parsed again, and the results updated. */ private void optionsChanged() { myParser.setImplicitMul(implicitCheckbox.getState()); myParser.setAllowUndeclared(undeclaredCheckbox.getState()); parseExpression(); updateResult(); } /** * This method uses JEP's getValueAsObject() method to obtain the current * value of the expression entered. */ private void updateResult() { Object result; String errorInfo; // Get the value result = myParser.getValueAsObject(); // Is the result ok? if (result!=null) { resultLabel.setText(result.toString()); } else { resultLabel.setText(""); } // Get the error information if ((errorInfo = myParser.getErrorInfo()) != null) { errorTextArea.setText(errorInfo); } else { errorTextArea.setText(""); } } } jep-2.4.1-ext-1.1.1-gpl/src/overview.html0000644000000000000000000000227510615400352016331 0ustar rootroot Java Expression Parser (JEP) and DJep extensions for vectors, differentation, and abstract groups. The main packages are

    • {@link org.nfunk.jep} the core jep package.
    • {@link org.lsmp.djep.xjep} extensions for simplification, priniting and tree manipulation.
    • {@link org.lsmp.djep.djep} extensions for differentation.
    • {@link org.lsmp.djep.vectorJep} extensions for working with vectors and matricies (standard version).
    • {@link org.lsmp.djep.matrixJep} extensions for working with vectors and matricies (advanced version).
    • {@link org.lsmp.djep.groupJep} extensions for working with abstract groups.
    • {@link org.lsmp.djep.rpe} a fast evaluator (unstable).
    • {@link org.lsmp.djep.sjep} improved simplification routines (experimental).
    @see Jep documentation @see DJep documentation @see JEP home page @see DJep home page @see Sourceforge project page jep-2.4.1-ext-1.1.1-gpl/README.html0000644000000000000000000000440610615400334014627 0ustar rootroot JEP - Java Expression Parser

    JEP - Java Expression Parser

    http://www.singularsys.com/jep

    Local Links

    Web Links

    Package Contents

    build.xml Build script for the ant build tool
    CHANGES.txt Change log
    COPYRIGHT.txt Copyright information
    LICENSE-*.txt License
    README.html This file
    bin/ Scripts for launching examples and tests
    build/ Compiled class files
    doc/ Documentation (incl. HTML docs and JavaDocs)
    dist/ Distribution files (incl. JAR files)
    lib/ Libraries (JUnit and Jama)
    src/ Source code (incl. the JavaCC gammar file Parser.jjt)

     


    Copyright (c) 2007 Singular Systems jep-2.4.1-ext-1.1.1-gpl/bin/0000755000000000000000000000000010615400350013546 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/bin/Fractal.bat0000644000000000000000000000175510615400346015627 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto otherStart REM -- Windows NT & XP ----------------------------------------------- :winNTStart @setlocal REM determine the location of JEP REM %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% REM change directories to the examples source code directory cd "%JEP_HOME%\src\org\nfunk\jepexamples" REM execute the applet viewer appletviewer.exe -J-classpath -J%JEP_HOME%\build\ Fractal.java REM jview.exe /cp:a %JEP_HOME%\build\ /a "%JEP_HOME%\src\org\nfunk\jepexamples\Evaluator.java" @endlocal goto mainEnd REM -- Other OS (probably Windows 9x) -------------------------------- :otherStart echo This batch file only supports Windows NT, 2000 and XP supported... goto mainEnd REM -- End ----------------------------------------------------------- :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/FunctionPlotter.bat0000644000000000000000000000176510615400334017410 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto otherStart REM -- Windows NT & XP ----------------------------------------------- :winNTStart @setlocal REM determine the location of JEP REM %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% REM change directories to the examples source code directory cd "%JEP_HOME%\src\org\nfunk\jepexamples" REM execute the applet viewer appletviewer.exe -J-classpath -J%JEP_HOME%\build\ FunctionPlotter.java REM jview.exe /cp:a %JEP_HOME%\build\ /a "%JEP_HOME%\src\org\nfunk\jepexamples\Evaluator.java" @endlocal goto mainEnd REM -- Other OS (probably Windows 9x) -------------------------------- :otherStart echo This batch file only supports Windows NT, 2000 and XP supported... goto mainEnd REM -- End ----------------------------------------------------------- :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/AllTests.sh0000644000000000000000000000014310615400334015635 0ustar rootroot#!/bin/sh java -cp ../build:../lib/junit.jar junit.awtui.TestRunner org.nfunk.jeptesting.AllTests jep-2.4.1-ext-1.1.1-gpl/bin/ThreadTest.bat0000644000000000000000000000104710615400334016311 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto win9xStart :winNTStart @setlocal rem %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% set CLASSPATH=%JEP_HOME%\build\ call java org.nfunk.jepexamples.ThreadTest REM call jview org.nfunk.jepexamples.ThreadTest @endlocal goto mainEnd :win9xStart echo No Windows 9x batch support yet... goto mainEnd :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/JEPTest.sh0000644000000000000000000000012010615400340015350 0ustar rootroot#!/bin/sh java -cp ../build:../lib/junit.jar org.nfunk.jepexamples.JEPTest $1 jep-2.4.1-ext-1.1.1-gpl/bin/AllTests.bat0000644000000000000000000000107010615400336015773 0ustar rootroot@echo off if not "%OS%"=="Windows_NT" goto win9xStart :winNTStart @setlocal rem %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% set CLASSPATH=%JEP_HOME%\build\;%JEP_HOME%\lib\junit.jar java junit.awtui.TestRunner org.nfunk.jeptesting.AllTests %1 %2 %3 %4 %5 %6 %7 %8 %9 REM call jview junit.awtui.TestRunner org.nfunk.jeptesting.AllTests %1 %2 %3 %4 %5 %6 %7 %8 %9 @endlocal goto mainEnd :win9xStart echo No Windows 9x batch support yet... goto mainEnd :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/Fractal.sh0000644000000000000000000000013210615400334015454 0ustar rootroot#!/bin/sh appletviewer -J-classpath -J../build ../src/org/nfunk/jepexamples/Fractal.java jep-2.4.1-ext-1.1.1-gpl/bin/Console.sh0000644000000000000000000000007310615400340015503 0ustar rootroot#!/bin/sh java -cp ../build org.nfunk.jepexamples.Console jep-2.4.1-ext-1.1.1-gpl/bin/Evaluator.bat0000644000000000000000000000175710615400344016215 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto otherStart REM -- Windows NT & XP ----------------------------------------------- :winNTStart @setlocal REM determine the location of JEP REM %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% REM change directories to the examples source code directory cd "%JEP_HOME%\src\org\nfunk\jepexamples" REM execute the applet viewer appletviewer.exe -J-classpath -J%JEP_HOME%\build\ Evaluator.java REM jview.exe /cp:a %JEP_HOME%\build\ /a "%JEP_HOME%\src\org\nfunk\jepexamples\Evaluator.java" @endlocal goto mainEnd REM -- Other OS (probably Windows 9x) -------------------------------- :otherStart echo This batch file only supports Windows NT, 2000 and XP supported... goto mainEnd REM -- End ----------------------------------------------------------- :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/JEPTest.bat0000644000000000000000000000106610615400334015521 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto win9xStart :winNTStart @setlocal rem %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% set CLASSPATH=%JEP_HOME%\build\;%JEP_HOME%\lib\junit.jar call java org.nfunk.jeptesting.JEPTest REM call jview org.nfunk.jeptesting.JEPTest @endlocal goto mainEnd :win9xStart echo No Windows 9x batch support yet... goto mainEnd :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/Console.bat0000644000000000000000000000104110615400336015640 0ustar rootroot@echo off echo This batch file may not run correctly if executed from a path containing space characters. if not "%OS%"=="Windows_NT" goto win9xStart :winNTStart @setlocal rem %~dp0 is name of current script under NT set JEP_HOME=%~dp0 set JEP_HOME=%JEP_HOME%\.. echo JEP_HOME = %JEP_HOME% set CLASSPATH=%JEP_HOME%\build\ call java.exe org.nfunk.jepexamples.Console REM call jview org.nfunk.jepexamples.Console @endlocal goto mainEnd :win9xStart echo No Windows 9x batch support yet... goto mainEnd :mainEnd pause jep-2.4.1-ext-1.1.1-gpl/bin/ThreadTest.sh0000644000000000000000000000007610615400344016157 0ustar rootroot#!/bin/sh java -cp ../build org.nfunk.jepexamples.ThreadTest jep-2.4.1-ext-1.1.1-gpl/bin/JEPTestExpressions.txt0000644000000000000000000001165410615400334020041 0ustar rootroot#################################################### # Plus 1+1 2 1+1+1+1+1+1+1+1 8 1+(1+(1+(1))) 4 #################################################### # Minus 1-1 0 1-1-1 -1 1-(1-1) 1 #################################################### # Multiplication 0*1 0 1*2 2 2*1 2 #################################################### # Division 4/2 2 1/2-0.5 0 #################################################### # Modulus 1 % 2 1 0 % 3 0 3 % 2 1 #################################################### # Power 1^2 1 2^2 4 1^0 1 2^0 1 1^-1 1 2^-1 0.5 #################################################### # 'Correct' precedence of unary - and ^ -1^2 -1 (-1)^2 1 #################################################### # Pi sin(pi) 0 pi*sin(0) 0 cos(pi) -1 cos(pi/2) 0 #################################################### # Sine sin(0) 0 sin(pi/2) 1 sin(pi) 0 sin(3*pi/2) -1 sin(pi/6) 0.5 sin(pi/3) 3^(0.5)/2 #################################################### # Cosine cos(0) 1 cos(pi/2) 0 cos(pi) -1 cos(3*pi/2) 0 cos(pi/6) 3^(0.5)/2 cos(pi/3) 0.5 #################################################### # Tangent tan(0) 0 tan(pi) 0 #################################################### # Inverse Sine asin(0) 0 asin(1) pi/2 asin(-1) -pi/2 #################################################### # Inverse Cosine acos(0) pi/2 acos(1) 0 acos(-1) pi #################################################### # Inverse Tangent atan(0) 0 atan(1) pi/4 atan(-1) -pi/4 atan2(0, 0) 0 atan2(1, 0) pi/2 atan2(0, 1) 0 atan2(-1, 0) -pi/2 atan2(0, -1) pi #################################################### # Logarithmic functions ln(1) 0 ln(e) 1 ln(e^32) 32 log(1) 0 log(10) 1 log(100) 2 #################################################### # Complex functions i^2 -1 i^2 i*i i-i 0 i+i 2*i (i+2)/2 i/2+1 (1+3*i)*2 (2+6*i) (1+1*i)*(2+2*i) (0+4*i) #################################################### # Boolean operators !1 0 !0 1 1==1 1 1==0 0 1!=1 0 1!=0 1 1<0 0 1<2 1 1>0 1 1>2 0 1>=1 1 1>=1.1 0 1<=1 1 1<=0.9 0 1 && 1 1 1 && 0 0 0 && 1 0 0 && 0 0 1 || 0 1 1 || 1 1 0 || 1 1 0 || 0 0 #################################################### # String functions # (need to use == operator in one line and compare # to value because JEPTester does not handle String # results) "ab" == "ab" 1 "a" == "b" 0 "ab" + "c" == "abc" 1 "a" + "b" + "c" + "d" == "abcd" 1 "abcd" + "efg" == "abcdefg" 1 "abcd" + "efg" == "abcd" 0 "abcd" + "efg" == "efg" 0 "A" == "a" 0 "a" + "b" == "ab" 1 #################################################### # exp function exp(0) 1 exp(1) e exp(2) e^2 #################################################### # abs function abs(-1) 1 abs(1) 1 abs(0) 0 abs(i) 1 abs(2*i) 2 abs(i+1) sqrt(2) #################################################### # rand function rand() < 1 1 rand() > 0 1 #################################################### # modulus function mod(11,10) 1 mod(1,2) 1 mod(1,5) 1 #################################################### # sqrt function sqrt(1) 1 sqrt(0) 0 sqrt(-1) i sqrt(25) 5 #################################################### # Sum sum(1,2) 3 # The following expression does not evaluate correctly in JEP 2.20 and 2.21 1+sum(1) 2 sum(1) 1 sum(1, 2) 3 # The following expression causes an error in JEP 2.3.0 and is a known bug sum(1, 2, 3, 4) 10 sum(1, 1, 1, 1, 1, 1, 1, 1, 1, 1) 10 sum(i) i sum(i, i) 2*i sum(1, i) 1+i sum(i, 1) 1+i sum("a", "b") == "ab" 1 #################################################### # if function if(1, 0, 1) 0 if(.001, 0, 1) 0 if(0, 0, 1) 1 if(-0.001, 0, 1) 1 #################################################### # str function str(1) == "1.0" 1 str("1") == "1" 1 #################################################### # floor function floor(1) 1 floor(1.1) 1 floor(1.9) 1 #################################################### # ceil function ceil(1) 1 ceil(1.0000001) 2 ceil(1.9) 2 #################################################### # round function round(1) 1 round(1.1) 1 round(1.9) 2 round(1.9,2) 1.9 round(1.9, 1) 1.9 round(1.9, 0) 2 round(-1.2) -1 round(-1.9) -2 #################################################### # Large expressions (TODO: add more) 1+1*2-(1+1*2)+1+1*2-(1+1*2)+1+1*2-(1+1*2)+1+1*2-(1+1*2)+1+1*2-(1+1*2) 0 #################################################### # Expressions with implicit multiplication 1 2 3 6 3sin(0) 0 sin(0)3 0 sin(3 sin(0)) 0 jep-2.4.1-ext-1.1.1-gpl/bin/applets.html0000644000000000000000000000135410615400350016107 0ustar rootroot Example Applets

    Function Plotter

    Evaluator

    Fractals

    jep-2.4.1-ext-1.1.1-gpl/bin/Evaluator.sh0000644000000000000000000000013410615400350016042 0ustar rootroot#!/bin/sh appletviewer -J-classpath -J../build ../src/org/nfunk/jepexamples/Evaluator.java jep-2.4.1-ext-1.1.1-gpl/CHANGES.txt0000644000000000000000000002602610615400336014621 0ustar rootroot== org.nfunk.* ======================================================= ---- 2.4.1 release (Apr 25, 2007) ------------------------------------ Apr 23 06 njf - added rounding functions round, ceil, and floor - added tests and updated JEPTest - applied fix for [ 1563324 ] getValueAsObject always returns null after an error - applied fix for [ 1670974 ] String to double <= comparison message incorrect - applied fix for [ 1706295 ] Wrong error output when evaluating variables Apr 22 06 njf - created branch for JEP 2.4.0 patches - updated build.xml (automatic building of commercial dist) - added classes for additional tests - added new license files ---- 2.4.0 release (Jun 8, 2006) ------------------------------------ Jun 8 06 njf - Revisions to the documentation Jun 6 06 njf - Added a COPYRIGHT.txt file including copyright and license information - Enabled deprecation output while compiling with build.xml May 26 06 njf - Switched back to JavaCC 3.2 to maintain compatibility with Java 1.2 May 20 06 rjm - Added a ElementComparative function, changed visability of field in Comparative. May 18 06 rjm - Changes to allow the a[5] syntax for access to array elements - Changed parser to handle the a[5] syntax - Added an LValueI interface for functions which can be used on lhs of an asignment, - Change Assign to work with LValueI. - Added new OP_ELEMENT to OperatorSet May 12 06 njf - Changed GraphCanvas to use Java2D anti aliasing for prettier curve drawing in function plotter applet Apr 27 06 njf - changed build.xml to rely on setting a JRE instead of a JDK enviroment variable - changed build.xml to allow compiling without having a 1.2 JRE env. var. set (doesn't ensure compatibility to old version then) Apr 26 06 njf - switched to JavaCC 4.0. Needed to regenerated JavaCharStream.java. Mar 11 06 rjm - Added serial version tags where needed Feb 18 06 njf - removed creative commons references from all source files Feb 15 06 njf - updated documentation by fixing some broken links and reapplying the dreamweaver template to all files - merged new tests from version 2.3.1 into JEPTestExpressions.txt Jan 06 njf - Created a new branch "v230-patches" on which version 2.3.1 was developed. Dec 16 05 rjm - Added a checkNumberofParameters method to PostfixMathCommandI, and a default method to PostfixMathCommand and implementations for necessary functions. May 02 05 rjm - Added more functionality to NumberFactory. CreateNumber(double) etc. and getZero() etc. May 02 05 rjm - Changed error behaviour for addVariable and setVarValue. These now throw IllegalStateExceptions. Apr 24 05 rjm - Created a CallbackEvaluationI interface which replaces SpecialEvaluationI. This facilitates functions which need access to the node tree. Apr 01 05 rjm - Variable: Fixed setting validValue for constants. Passes value to observers on setValue. Apr 01 05 rjm - SymbolTable can now have observes passed to it. Added a clearNoConstants method. Apr 01 05 rjm - Changed behaviour on errors. Removed references to Error list in EvaluationVisitor. ParseExceptions are thrown instead. getValueAsObject() traps all errors including RuntimeExceptions. evaluate() now only throws ParseException. Apr 01 05 rjm - trapNulls flag in evaluation visitor. Switchable to trap null nulles or not. Apr 01 05 rjm - Jep copy constructor fixed. Apr 01 05 rjm - If now works with Numbers Feb 13 05 rjm - Added binom, conj functions. Dec 19 njf - figured out documentation linking issues. Leaving docs as they were before Nov 1 (no frames, javadoc at /doc/javadoc) Dec 10 rjm - nodeAccept method added to jep.EvaluationVisitor so that it can be easier for sub classes to use visitor pattern. - Improved printing facilities for complex numbers. Nov 6 njf - Merged JEPTester and JEPTest into JEPTest, now in the JUnit framework Nov 3 rjm - JEP.evaluate() method will throw an exception if this.hasErrors() is true. Nov 1 njf - changed documentation to frames - added new FAQ item Oct 23 njf - added source="1.2" to javac options in build.xml avoids compile time error with 1.5 compiler by ensuring 1.2 source compatibility njf - fixed [ 1046349 ] bug in sum() njf - fixed [ 1051988 ] JEPTester falsely reports "No errors" njf - improved value comparison and error reporting in JEPTester njf - reformated Comparative.java, added comments Oct 22 njf - added simple sum test to JEPTesterExpressions.txt Oct 4 rjm - Changes the SpecialEvaluationI interface to include a SymbolTable parameter. rjm - Added rules to differentiate atan2 removed support for angle rjm - Doc update for GroupJep, improved consol and unit test or ---- 2.3.0 release (Oct 3, 2004) ------------------------------------ Oct 3 njf - created new features document for the core JEP and moved appropriate text from DJEP index.html there njf - changed "jar" and "dist" targets to create a separate djep jar without examples and test cases, then include both jars in a jep-djep-2.3.0.zip file njf - new jjdoc target in build.xml to generate grammar documentation njf - removed compile.bat and grammardoc.bat Oct 2 njf - build.xml now creates javadoc using new breakiterator (gets rid of all the "helpful" output when running javadoc) njf - added package.html files to package directories njf - updated details in documentation njf - documented error handling using hasError() and getErrorInfo() njf - added 1.2 compatibility checking in build.xml Oct 1 njf - removed org.lsmp.* from compile in build.xml njf - commented out addToErrorList("No expression entered"); from Start() in Parser.jjt njf - added getTraverse() method njf - changed @since version names in org.nfunk.* according to: 2.3.0 -> 2.3.0 alpha 2.3.1 -> 2.3.0 beta 1 2.3.2 -> 2.3.0 beta 2 2.3.3 -> 2.3.0 beta 2 2.3.0.1 -> 2.3.0 alpha ---- 2.3.0 beta 2 --------------------------------------------------- ---- 2.3.0 beta 1 --------------------------------------------------- ---- 2.3.0 alpha ---------------------------------------------------- ? njf - NumberFactory has been changed to create the number from a String representation (in order to allow creation of arbitrary precision numbers without the limitations of double) Many previous changes not included here. See the documentation for details. =============================================================================== == org.lsmp.* ================================================================= -- 1.1.1 (Apr 25, 2007) -------------------------------------------- Apr 25 07 njf - Added an AllTests class for easy execution of all tests from ant Apr 24 07 njf - Applied patch for bug [ 1567116 ] VectorJep division in MDivide.java - made a few spelling corrections for the package.html files -- 1.1.0 (Jun 9, 2006) -------------------------------------------- May 20 06 rjm - Fixed bug with differentation visitor. isConstant method returned true for b=a; a=x; when differentiating wrt x. May 20 06 rjm - Added a ElementComparative function, changed visability of field in Comparative. May 18 06 rjm - Changes to allow the a[5] syntax for access to array elements - Created a ArrayAccess function - Modified OperatorSets - Print rule for array access in MatrixJep. Apr 07 06 rjm - Added several functions to allow interegation of command lists Apr 04 06 rjm - Fixed bug with conversion of (a+b)-(c+d) to polynomial in sjep. Mar 11 06 rjm - Added serial version tags where needed Mar 4 06 rjm - fixed bug in SJep 2x+x now correctly simplifies to 3x. Dec 16 05 rjm - Added implementations of checkNumberOfParameters for necessary functions. Dec 08 05 rjm - Added MDivide function - Fixed bug in MMultiply dividing Tensor by a scaler. July 28 05 rjm - Added a Define function - NodeFactory now calls the jep evaluator in buildConstantNode. - SimplificationVisitor returns now returns null if null is parsed rather than throwing an error. - added exp() function to XJep - added macrocomplex to xjep (Why?) July 14 05 rjm - Restructured DJep so standard diffrules in DJep rather than DiffVisitor June 07 05 rjm - Fixed bug in ele which only accepted Double arguments. May 02 05 rjm - added toBase pfmc and a BaseFormat NumberFormat object. Apr 24 05 rjm - Reworked junit tests using inheretance. Apr 24 05 rjm - Simpson and Trapesium functionsa added to XJep. Apr 03 05 rjm - DifferentationVisitor is now smarter when calculating zero derivatives - PrintVisitor.getMode(int testmode) added. Apr 01 05 rjm - MVector, Matrix, Tensor no longer extend number. Apr 01 05 rjm - Added det(), trace(), vsum(), trans(), getDiag(), diag(), id(), GenMat, Map function to vectorJep. Need to check diff and matrixJep functionality. Apr 01 05 rjm - added SpecialPreprocessorI interface for matrixJep functions. Feb 13 05 rjm - added len() and size() functions - added Scaler.getInstance() and Vector.getInstance() methods. Dec 21 rjm - xjep.PrintVisitor can now work with three or more arguments to + and *. Dec 10 rjm - Implemented element by element multiplication in VectorJep nodeAccept method added to jep.EvaluationVisitor so that it can be easier for sub classes to use visitor pattern. - Improved printing facilities for complex numbers. - xjep.PrintVisitor now allows a NumberFormat object to be specified to control the printing of double values. - ExtendedFreeGroup added to GroupJep this allows a limited use of ^ and / for polynomials. Polynomials can be raised to positive integer powers and divided by constants. Oct 4 rjm - Added rules to differentiate atan2 removed support for angle rjm - Doc update for GroupJep, improved consol and unit test or working with polynomials over the reals (Doubles). Oct 1 rjm - RewriteRulesI interface added and RewriteVisitor added. Begining of an improved simplification algorithm. Sept rjm - added SumType functions equivilent to sigma notation. -- 1.0.0 (Oct 3rd, 2004) -------------------------------------------- Many previous changes not included here. See the documentation for details. jep-2.4.1-ext-1.1.1-gpl/COPYRIGHT.txt0000644000000000000000000000420410615400350015107 0ustar rootrootJEP and JEP Extensions copyright information All source code in this package except some generated code is written by Nathan Funk and Richard Morris. The generated code is output of JavaCC. The package includes the binary libraries Jama and JUnit. The copyright information for JavaCC, JAMA and JUnit is included below. ------------------------------------------------------------------------------- JavaCC https://javacc.dev.java.net/ ------------------------------------------------------------------------------- The Java Compiler Compiler (JavaCC) is a parser generator used for creating some of the source code in this package. This package only includes source code generated by JavaCC, but not the JavaCC source code itself. Java CC is released under the Berkeley Software Distribution (BSD) License (http://www.opensource.org/licenses/bsd-license.html) ------------------------------------------------------------------------------- JAMA http://math.nist.gov/javanumerics/jama/ ------------------------------------------------------------------------------- Jama is authored by members of the MathWorks (http://www.mathworks.com/) and NIST (http://www.nist.gov/). It has been released to the public domain. The following is the official Copyright Noticed as posted on the JAMA web site. Copyright Notice: This software is a cooperative product of The MathWorks and the National Institute of Standards and Technology (NIST) which has been released to the public domain. Neither The MathWorks nor NIST assumes any responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. ------------------------------------------------------------------------------- JUnit http://www.junit.org/ ------------------------------------------------------------------------------- JUnit is licensed under the Common Public License Version 1.0 http://www.opensource.org/licenses/cpl.php jep-2.4.1-ext-1.1.1-gpl/build.xml0000644000000000000000000003077310615400346014636 0ustar rootroot http://www.singularsys.com/jep Copyright © 2007 Singular Systems]]> jep-2.4.1-ext-1.1.1-gpl/LICENSE-gpl.txt0000644000000000000000000004365210615400352015415 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jep-2.4.1-ext-1.1.1-gpl/doc/0000755000000000000000000000000010615400350013543 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/html/0000755000000000000000000000000010615400350014507 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/0000755000000000000000000000000010615400344016711 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/groupjep.html0000644000000000000000000003417610615400336021446 0ustar rootroot GroupJep - Exact arithmetic over the integers, rationals and other groups.

    GroupJep - Exact arithmetic over the integers, rationals and other groups


    The org.lsmp.djep.groupJep package offers:

    • Exact arithmetic for the integers and rationals
    • A framework for allowing arbitrary groups, rings and fields to be used
    • Implementation of several groups: integers mod n, free groups, finite field extensions (allowing the use of algebraic numbers)

    This package is primarily a bit of a play thing, allowing the JEP parser and evaluator to be used with arbitrary groups. It should not be treated as a substitute for a dedicated computer algebra package but it does allow a bit of experimentation with different groups rings and fields.

    An interactive console applet interactive console applet illustrates the functionality of GroupJep.

    Basic usage

    The GroupJep package is relatively easy to use, all the standard JEP features are enabled. To create a version of JEP for a particular group the GroupJep(GroupI group) constructor should be called where the argument is the specification of a certain group. For example to work of arbitrary precision integers to calculate factorial 20 use:
    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.groups.*;

    JEP j = new GroupJep(new Integers());
    Node node = j.parse("1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20");
    Object value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 2432902008176640000
    A number of predefined groups are provided. These are all found in the org.lsmp.djep.groupJep.groups package.
    • Integers: arbitrary precision integers, implement as java.math.BigInteger.
    • Rationals: arbitrary precision rational numbers: implemented as a quotient of BigInteger's.
    • Reals: real numbers implemented as double.
    • BigReals: real numbers implemented as either BigDecimals.
    • Zn: integers mod n.
    • FreeGroup: the free group with one generator, elements a_n t^n + ...+ a_1 t + a_0.
    • AlgebraicExtension: a group extended by an algebraic number. Allows exact computation using algebraic numbers.
    Examples of the use of these groups:
    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.groups.*;

    class GroupExamples {
    public static void main(String args[])
    {
    JEP j = new GroupJep(new Integers());
    Node node = j.parse("1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20");
    Object value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 2432902008176640000

    j = new GroupJep(new Rationals());
    node = j.parse("(1/2)-(1/3)");
    value = j.evaluate(node);
    System.out.println(value.toString());
    // prints 1/6

    j = new GroupJep(new Zn(BigInteger.valueOf(5)));
    node = j.parse("3+3");
    value = j.evaluate(node);
    System.out.println(value.toString()); // prints 1

    node = j.parse("3*3");
    value = j.evaluate(node);
    System.out.println(value.toString()); // prints 4

    Free groups/Polynomials

    Any ring can be extended to form a FreeGroup with a single generator. In effect this allows JEP to function with polynomials as a basic type and they will always be reduced to their basic type.

    To use:

    import org.lsmp.djep.groupJep.interfaces.*;
    import org.lsmp.djep.groupJep.*;
    ...
    RingI ring = new Integers();
    RingI freeGroup = new FreeGroup(ring,"t");
    JEP j = new GroupJep(freeGroup);
    // this line is needed to ensure the parser recognises the symbol t
    j.addStandardConstants();

    Node node = j.parse("(t + 2)*(t+4)");
    Object value = j.evaluate(node);
    System.out.println(value.toString()); // prints t^2+5 t+6
    Note that the addStandardConstants method of JEP must be called to ensure that the variable t is added to the parser. Free groups with more than one generator can be constructed by repeatedly extending a ring:
    RingI freeGroup = new FreeGroup(new FreeGroup(new Integers(),"t"),"s");

    Polynomials in multiple variables can be defined by repeatidly extending.

    RingI ring = new Reals();
    FreeGroup fg = new ExtendedFreeGroup(ring,"x");
    FreeGroup fg2 = new ExtendedFreeGroup(fg,"y");
    j = new GroupJep(fg2);
    j.addStandardConstants();
    j.setAllowAssignment(true);
    j.setAllowUndeclared(true);
    Node n2 = j.parse("(x+1)*(y-2)");	
    FreeGroupElement fge = (FreeGroupElement) j.evaluate(n2);
    
    The coefficients of the polynomial can be found using:
    Number co1[] = fge.getCoeffs();
    for(int i=0;i<co1.length;++i)
    {
    	FreeGroupElement fge3 = (FreeGroupElement) co1[i];
    	Number co2[] = fge3.getCoeffs();
    	for(int j=0;j<co2.length;++j)
    		System.out.print(co2[j]+"\t");
    	System.out.println();
    }
    
    To calculate
    fg.setRootVal(new Complex(5.0));
    fg2.setRootVal(new Complex(4.0));
    System.out.println(fge2.toString());
    Complex val = fge2.getComplexValue();		
    

    Algebraic Numbers

    In a similar fashion a ring can be extended by an algebraic number t to form an AlgebraicExtension. The algebraic number is defined to be a root of a Polynomial equation with coefficients in the base ring.
    import org.lsmp.djep.groupJep.*;
    import org.lsmp.djep.groupJep.interfaces.*;
    import org.lsmp.djep.groupJep.groups.*;
    import org.lsmp.djep.groupJep.values.*;
    ...
    RingI ring = new Integers();
    // specify the polynomial 1 x^2 + 0 x -2
    Number coeffs[] = new Number[]{
    BigInteger.valueOf(-2),
    BigInteger.ZERO,
    BigInteger.ONE};
    Polynomial p1 = new Polynomial(ring,"rt2",coeffs);

    j = new GroupJep(new AlgebraicExtension(ring, p1));
    j.addStandardConstants();

    Node node = j.parse("(t+1)*(t+1)");
    Object value = j.evaluate(node);
    System.out.println(value.toString()); // prints 2 t+3
    System.out.println(((HasComplexValueI) value).getComplexValue());
    // prints (5.82842712474619, 0.0)
    Note in the last line the values can be converted to approximate complex numbers (in the group constructor if the polynomial is quadratic or an n-th root then an approximation to the complex value of a solution is calculate. The value returned by j.evaluate will be an object of type AlgebraicExtensionElement which implements org.lsmp.djep.groupJep.values.HasComplexValueI by providing a getComplexValue() method. This method will use the approximate value of the root to calculate the complex value of this element.

    Creating your own groups

    Creating a group class is fairly straight forward. The class must implement org.lsmp.djep.groupJep.GroupI or one of the other interfaces in the org.lsmp.djep.groupJep.interfaces package which give extra properties such as RingI, FieldI. Typically the group will subclass org.lsmp.djep.groupJep.groups.Group which provides a few default methods. All groups should provide the methods:
    public Number getZERO();
    public Number getInverse(Number num);
    public Number add(Number a,Number b);
    public Number sub(Number a,Number b);
    public boolean equals(Number a,Number b);
    public Number valueOf(String s);

    The different interfaces available and the methods they define are:

    Interface Methods
    GroupI public Number getZERO();
    public Number getInverse(Number num);
    public Number add(Number a,Number b);
    public Number sub(Number a,Number b);
    public boolean equals(Number a,Number b);
    public Number valueOf(String s);
    AbelianGroupI Same methods as GroupI.
    implies group is commutative under +.
    RingI Methods for GroupI plus:-
    public Number getONE();
    public Number mul(Number a,Number b);
    public Number getMulInverse(Number num);
    IntegralDomainI Same methods as RingI. This interface implies the group has: an identity for multiplication *; it is commutative under * and that cancellation is meaningful (if a is not 0 then a*b = a*c implies b = c).
    HasDivI Group has some notion of division i.e. integers
    public Number div(Number a,Number b);
    FieldI Same methods as for RingI plus
    public Number div(Number a,Number b);
    HasModI The modulus function is defined:
    public Number mod(Number a,Number b);
    HasPowerI The power function is defined:
    public Number pow(Number a,Number b);
    OrderedSetI There is a natural ordering to the set so <, <=, >, >= are meaningful.
    public int compare(Number a,Number b);
    will return -1 if a<b, 0 if a=b, +1 if a>b.
    HasListI List operations i.e. [a,b,c] is meaningful. public Number list(Number eles[]);
    jep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/vectorjep.html0000644000000000000000000004761010615400334021607 0ustar rootroot VectorJep - Vectors and Matrices in JEP

    Vectors and Matrices

    There are two packages which offer support for vectors and matrices

    • org.lsmp.djep.vectorJep - standard vector and matrix handling
    • org.lsmp.djep.matrixJep - advanced vector and matrix handling
    for most applications the first package should suffice. The second package allows differentiation of equations with vectors and matrices; the overloading of the ^ operator to be both power and cross product; a speed advantages; and the calculation of the dimensions of each equation. The downside is that it adds about 65K to the size of the required packages.

    Most of the functionality is common to both packages and the following syntax is allow:

    • Vectors: [1,2,3] denotes a vector, variables and equations can be used throughout i.e. [x,y,2*x+3*y]
    • Matrices: [[1,2],[3,4]] a matrix with rows [1,2] and [3,4].
    • Tensors: [[[1,2],[3,4]],[[5,6],[7,8]]] higher rank tensors are also allowed.
    • Addition and subtraction of vectors, matrices and tensors, using + and -.
    • Multiplication of matrices using * (note size of matrices must match).
    • Dot product of vectors [1,2,3].[4,5,6]
    • Cross product of vectors. The ^ operator is overloaded to be either the cross product: [1,2,3]^[4,5,6] or the power operator 2^3. The ^^ operator can be used to force interpretation as a cross product.
    • An ele(vec,index) function to access the elements of a vector and an ele(matrix,[index1,index2]) to access an element of a matrix.
    • As . is used to represent dot product it cannot normally be used inside a variable name. This behaviour can be changed by setting a flag in the parser.

    Two interactive console applet illustrate the functionality of VectorJep and MatrixJep.

    vectorJep

    The use of the package can be illustrated by

    import org.nfunk.jep.*;
    import org.lsmp.djep.vectorJep.*;
    
    public class VectorExample {
        static VectorJep j;
      
        public static void main(String args[])    {
        	// initialise
            j = new VectorJep();
            j.addStandardConstants();
            j.addStandardFunctions();
            j.addComplex();
            j.setAllowUndeclared(true);
            j.setImplicitMul(true);
            j.setAllowAssignment(true);
    
    		// parse and evaluate each equation in turn
    		
            doStuff("[1,2,3]");               // Value: [1.0,2.0,3.0]
            doStuff("[1,2,3].[4,5,6]");       // Value: 32.0
            doStuff("[1,2,3]^^[4,5,6]");      // Value: [-3.0,6.0,-3.0]
            doStuff("[1,2,3]+[4,5,6]");       // Value: [5.0,7.0,9.0]
            doStuff("[[1,2],[3,4]]");         // Value: [[1.0,2.0],[3.0,4.0]]
            doStuff("[[1,2],[3,4]]*[1,0]");   // Value: [1.0,3.0]
            doStuff("[1,0]*[[1,2],[3,4]]");   // Value: [1.0,2.0]
            doStuff("[[1,2],[3,4]]*[[1,2],[3,4]]");   // Value: [[7.0,10.0],[15.0,22.0]]
            doStuff("x=[1,2,3]");             // Value: [1.0,2.0,3.0]
            doStuff("x+x");                   // Value: [2.0,4.0,6.0]
            doStuff("x.x");                 // Value: 14.0
            doStuff("x^x");                  // Value: [0.0,0.0,0.0]
            doStuff("ele(x,2)");              // Value: 2.0
            doStuff("y=[[1,2],[3,4]]");       // Value: [[1.0,2.0],[3.0,4.0]]
            doStuff("y * y");                 // Value: [[7.0,10.0],[15.0,22.0]]
            doStuff("ele(y,[1,2])");          // Value: 2.0
    		
        }
    	// parse, evaluate and print the value of the expression 
        public static void doStuff(String str)    {
            try {
                Node node = j.parse(str);
                Object value = j.evaluate(node);
                System.out.println(str + "\tvalue " + value.toString());
            }
            catch(ParseException e) { System.out.println("Parse error "+e.getMessage()); }
            catch(Exception e) { System.out.println("evaluation error "+e.getMessage()); }
        }
    }
    

    Values returned by evaluate

    The values returned by evaluateRaw(Node node) or getValueAsObject() or getVarValue(String name) are one of the types in org.lsmp.djep.vectorJep.values. These are:

    • Scaler Scaler values.
    • MVector a vector, note the M to distinguish the class from java.util.Vector.
    • Matrix a matrix.
    • Tensor a tensor of rank 3 or higher.
    • MatrixValueI an interface defining common methods of above.
    Several methods are common to all types getDim() (returns the dimension of object) getNumEles() (returns the total number of elements) getEle(i) (returns the i-th element of the object) setEle(i,value) (sets the value of an element). In addition Matrix has a getEle(row,col) and a setEle(row,col,value). These methods allow the individual elements of vector or matrix to be set and queried.

    The evaluate(Node node) method behaves the same as evaluateRaw(Node node) however if the result is a Scaler then it will be unwrapped and the single value will be returned, typically a Double or Complex.

    Printing with vectorJep

    To keep package size down print facilities are not provided in the org.lsmp.djep.vectorJep package. However it is easy to include them by using the org.lsmp.djep.xjep.printVisitor class. For example:

    import org.lsmp.djep.xjep.PrintVisitor;
    ....
    PrintVisitor pv = new PrintVisitor();
    Node node = j.parse("[1,2,3]");
    pv.print(node);
    String str = pv.toString(node);
    

    Element by element calculations

    The vectorJep package can be set up so that element by element multiplication and division is performed instead of matrix multiplication. To switch this mode on use

    VectorJep j = new VectorJep();
    
    j.setElementMultiply(true);

    Once set [1,2,3]*[4,5,6] will evaluate to [4,10,18].

    Functions on Vectors and Matricies

    Several functions are added with the VectorJep package these are:

    Name Description Examples
    length Finds the length of a vector or the number of elements in a matrix or tensor. length(5)==1, length([1,2,3])==3, length([[1,2],[3,4]])==4
    size Finds the size of a vector, matrix or tensor. size(5)==1, size([1,2,3])==3, size([[1,2],[3,4],[5,6])==[2,3]
    det The determinant of a square matrix. det([[1,2],[3,4]])==-2
    trace The trace of a square matrix. trace([[1,2],[3,4]])==5
    vsum The sum of elements in a vector, matrix or tensor. vsum([1,2,3])==6, vsum([[1,2],[3,4]])==10
    trans The transpose of a matrix. trans([[1,2],[3,4]])==[[1,3],[2,4]]
    getdiag Extracts the diagonal from a square matrix. getdiag([[1,2],[3,4]])==[1,4]
    diag Generates a square matrix with a given diagonal. diag([1,2,3])==[[1,0,0],[0,2,0],[0,0,3]]
    GenMat Generates vectors and matrixies First argument specifies size of the vector (3) and matricies ([2,2]). Second argument is formula for each element, constants (1), functions (rand()), Third argument (if present) is list of variables used in formula. For vectors a single variable is specified whos value runs from 1 to number of elements. For matricies a two variable list ([ii,jj]) is specified whos value are the column and row indicies.
    GenMat(3,1) -> [1,1,1]
    GenMat(3,ii,ii) -> [1,2,3]
    GenMat(3,rand()) -> [0.343,0.974,0.567]
    GenMat([2,2],ii+jj,[ii,jj]) -> [[2,3],[3,4]]
    
    ele Extracts an element from a vector, matrix or tensor. ele([1,2,3],2)==2, ele([[1,2],[3,4]],[1,2])==2

    The Map function applies a function to each element of a vector or matrix. The first argument is the function to apply. The second argument is either a variable or a list of variables. The third and subsequent arguments are the vectors or matricies the function is applied to. During evaluation the variables will be set to each element of the vectors or matricies. For example

    Map(x^3,x,[1,2,3]) -> [1.0,8.0,27.0]
    Map(x*y,[x,y],[1,2,3],[4,5,6]) -> [4.0,10.0,18.0]
    Map(if(x>0,x,0),x,[-2,-1,0,1,2]) -> [0.0,0.0,0.0,1.0,2.0]
    Map(abs(x),x,[[-2,-1],[1,2]]) -> [[2.0,1.0],[1.0,2.0]]
    

    variable names with dot in them

    As the dot . symbol is used for the dot or scaler product, it cannot be normally be used in a varible name. This behaviour can be switched on or off using

    jep.getParser().setInitialTokenManagerState(ParserConstants.NO_DOT_IN_IDENTIFIERS);
    jep.getParser().setInitialTokenManagerState(ParserConstants.DEFAULT);
    

    MatrixJep

    The MatrixJep package offers the same functionality as the VectorJep package however it is implemented in a different manner internally which offers a few new features:

    • A speed improvement - matrix operations are about a third faster.
    • The preprocessing stage is used to calculate the dimension of each node.
    • All the features of the XJep package are enabled.
    • Differentiation is enabled.

    It is essential that the preprocess method is called after an equation is parsed. This will find the dimensions of each node, process the diff operator and set the equations of variables.

    A typical example of the use of this package is: (differences from vectorJep are shown in bold)

    import org.nfunk.jep.*;
    import org.lsmp.djep.matrixJep.*;
    import org.lsmp.djep.matrixJep.nodeTypes.*; // only needed if you wish 
                                              // to find the dimension of a node
    public class MatrixExample {
        static MatrixJep j;
        public static void main(String args[])    {
           	// initialise
           	j = new MatrixJep();
           	j.addStandardConstants();
           	j.addStandardFunctions();
           	j.addComplex();
           	j.setAllowUndeclared(true);
           	j.setImplicitMul(true);
           	j.setAllowAssignment(true);
           	
           	// parse and evaluate each equation in turn
           	
           	doStuff("[1,2,3]");               // Value: [1.0,2.0,3.0]
           	doStuff("[1,2,3].[4,5,6]");       // Value: 32.0
           	doStuff("[1,2,3]^^[4,5,6]");      // Value: [-3.0,6.0,-3.0]
           	doStuff("[1,2,3]+[4,5,6]");       // Value: [5.0,7.0,9.0]
           	doStuff("[[1,2],[3,4]]");         // Value: [[1.0,2.0],[3.0,4.0]]
           	doStuff("[[1,2],[3,4]]*[1,0]");   // Value: [1.0,3.0]
           	doStuff("[1,0]*[[1,2],[3,4]]");   // Value: [1.0,2.0]
           	doStuff("[[1,2],[3,4]]*[[1,2],[3,4]]");   // Value: [[7.0,10.0],[15.0,22.0]]
           	doStuff("x=[1,2,3]");             // Value: [1.0,2.0,3.0]
           	doStuff("x+x");                   // Value: [2.0,4.0,6.0]
           	doStuff("x.x");                   // Value: 14.0
           	
           		// ^ can be used to represent the cross product as well as power.
           	doStuff("x^x");                   // Value: [0.0,0.0,0.0]
           	doStuff("ele(x,2)");              // Value: 2.0
           	doStuff("y=[[1,2],[3,4]]");       // Value: [[1.0,2.0],[3.0,4.0]]
           	doStuff("y * y");                 // Value: [[7.0,10.0],[15.0,22.0]]
           	doStuff("ele(y,[1,2])");          // Value: 2.0
           	// using differentiation
           	doStuff("x=2");	                  // 2.0
           	doStuff("y=[x^3,x^2,x]");         // [8.0,4.0,2.0]
           	doStuff("z=diff(y,x)");	          // [12.0,4.0,1.0]
           	doStuff("diff([x^3,x^2,x],x)");
           	
           	// Finding the dimension of a variable	
           	System.out.println("dim(z) "+((MatrixVariableI) j.getVar("z")).getDimensions());
        }
        // parse, evaluate and print the value of the expression 
        public static void doStuff(String str)    {
            try {
                Node node = j.parse(str);
                Node proc = j.preprocess(node);
                Node simp = j.simplify(proc);
                Object value = j.evaluate(simp);
                 // Print the equation and its dimension
                j.print(simp);
                System.out.print("\t dim "+((MatrixNodeI) simp).getDim());
                System.out.println("\tvalue " + value.toString());
            }
            catch(ParseException e) { System.out.println("Parse error "+e.getMessage()); }
            catch(Exception e) { System.out.println("evaluation error "+e.getMessage()); }
        }
    }

    Note that in MatrixJep variables and Node have dimensions. Each variable will be of type MatrixVariableI and the dimension of this can be found by the getDimensions method. After the preprocess method is called the nodes in the parse tree all implement MatrixNodeI which have a getDim method. Each node also has a object of type MatrixValueI which stores intermediate values. By reusing these objects evaluation speeds are increased by a third.

    JAMA

    JAMA http://math.nist.gov/javanumerics/jama/ is a library of matrix fuctions, offering matrix solving, and other advanced matrix operations.

    The org.lsmp.djep.jama package allows these sophsticated matrix functions to be used with VectorJep and MatrixJep. Currently only a small subset (solve, rank, inverse) are implemented.

    jep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/version.html0000644000000000000000000002167410615400336021277 0ustar rootroot DJep - Version history

    Extensions Version History

    Version 1.1.1 (released 2007/04/25)

    • Fixed bug [ 1567116 ] VectorJep division

    Version 1.1.0

    New Features

    • Simplification: A new package org.lsmp.djep.sjep has a more advanced simplification algorithm. This will collect terms with the same powers so 3x+x^2+4x+x^2 is transformed to 7x+2x^2. Full expansion of polynomials is also available so (1+x)^3 it transformed to 1+3x+3x^2+x^3.
    • Fast Evaluation: Two new classes in the org.lsmp.djep.rpe package peform faster evaluation over the reals. The speed up can be between four and ten times faster. One of the classes RpEval works with singled valued functions and the other MRpEval works with vectors and matrices optimised for 2,3, and four dimensions.
    • New Functions: Several new functions have been added, including standard vector and matrix operations and wrappers around the JAMA matrix algorithms which can solve matrix equations.

    Minor Improvments

    • Evaluator now swithchable to allow null variable values.
    • SymbolTable can now tell java.util.observers when new variables are created.
    • Reworked Console aplications to make them easily extendable.
    • Rewrite Visitor can allow arbitary term rewriting rules.
    • XJep has methods to find the variables in an equation.

    Version 2.3.0 release (renamed to DJEP 1.0.0)

    No major changes were made for the release.

    Version 2.3.0 beta 1 - 12 April 2004 (formerly known as 2.3.2 beta)

    This version now has a stable API an should be used in preference to earlier versions.

    Main changes since 2.3.0a:
    • Added a groupJep package: this allows calculation over arbitrary groups like the rational numbers.
    • Changed the org.nfunk.jep.values.Complex to extend number, modified all postfix math commands to suit.
    • Changed the Scaler, MVector and Matrix types to extend number.
    • Added features for a re-enterant parser.
    • Major re-nameing of packages and classes. Removed unnecessary classes.
    • Documentation updated.
    • The ^ operator is now overloaded to be the cross product for 3D vectors as well as power.
    • Parser is now switchable for whether . can appear in an identifier x.y can either be a single variable (default for JEP,XJep and DJep) or as the dot product x . y (default for VectorJep and MatrixJep).
    • New functions if, str, complex, polar.
    • Several other minor changes.

    TODO features yet to come


    A few new functions to be added, min, max, sgn, differentiation for if.
    Vector and matrix functions: det, inverse, transpose ....
    Faster evaluation, possibly based of a reverse polish type of evaluation scheme, eliminating as much object creation as possible.
    Various conversion routines to other formats MathML etc.

    Version 2.3.0 alpha - 28 Feb 2004 (formerly known as 2.3.1 alpha)

    This is the third release of the package, released 28/Feb/04. I'm really just rushing this out as some people have been asking for documentation which is included here. Still more documentation to come. Also the code is still in a fairly mutable state and I still expect to move some things around so don't expect the the API to be stable. Hopefully it will just be the inner workings which change the main interface for users is nearly fixed. The most important changes in this package are

    • Renames org.lsmp.djep.matrixJep.MatrixDJep to org.lsmp.djep.matrixJep.MatrixDJep.
    • Moved the console applications to their own package
    • Added some more examples
    • Added some documentation
    • Added some JUnit test
    • Rationalised some of inner workings and cleaned up some unnecessary stuff, notably in relation to variables and their evaluation.

    Version 2.3.0a - Jan 04


    First release as an official part of JEP.

    Added support for vectors and matrices.
    Major reworking of differentiation, functionality now split into two packages org.lsmp.djep.xjep - printing, tree manipulation etc, and org.lsmp.djep.djep - differentiation.
    Changed the org.nfunk.jep.SymbolTable class so the elements are now of type org.nfunk.jep.Variable rather than just its value. ASTVarNodes now refer to the variable object.
    Several changes in exposed API for JEP.
    Introduced an org.nfunk.jep.Operator and org.nfunk.jep.OperatorSet types which represent the basic +,-,*,/,etc operators. Eliminates the excess creation of one object for each instance of an operator.

    Known bugs in version 2.3.0a

    Several bugs are known in version 2.3.0a.
    • Differential of "diff(a^x,x)" should be "a^x * ln(a)" but it's "a^x * ln(x)".
    • Evaluation of "(x*x)*(x*x)" causes a ParseError in VectorJep and MatrixJep. Quick fix: edit org.lsmp.djep.vectorJep.function.MMultiply.java
      On line 72: in the run method, comment out the line
      if(stack.size()!=2) throw new ParseException("Multiply: should have two children its got "+stack.size());
    • Matrix multiplication (i.e. matrix * matrix) does not work. Fix: upgrade to later version.
    • vector * vector multiplication does not work.
    • cannot combine results of matrix operations with functions ie. "sqrt([1,2].[1,2])" fails. Fix: upgrade.
    • Dot and cross product cannot be differentiated.
    • uminus is broken for MatrixJep.
    • Problems repeated evaluation of sequences of equations.
      Quick fix: always uses before reevaluation. j.getSymbolTable().clearValues();
    • Problems with using different types of JEP in the same application. They share a static Operator class which can have the wrong pfmc's for the type of JEP.

    First release

    The first release of the package was about September last year. It just included differentiation facilities. The package has had a major rework since then.
    jep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/index.html0000644000000000000000000002061010615400344020705 0ustar rootroot DJep - Java Math Expression Parser with differentiation and matrices

    Extensions - differentiation, vectors and matrices in JEP


    The JEP Extensions offer a number of additional features to the standard JEP package:

    • Printing: equations can be easily printed or converted to strings with intelligent handling of brackets.
    • Simplification: equations like 2.0*x^1.0*1.0+0.0 equations can be simplified to produce 2.0*x
    • Differentiation: equations can be differentiated, these can be specified either programtically or in the equations themselves.
    • Vectors and Matrices: Full support for vector and matrix operations.
    • Utilities for working with parse trees a number of utilities are available for programtically creating and copying and working with the parse trees.
    • Groups Exact arithmetic over integers rationals and other groups.
    • Fast Evaluation Evaluation routines for calculations over doubles. Can be up to 10 times as fast.

    These facilities are offered by packages in the org.lsmp.djep tree.


    Feature Package (JavaDoc)
    Printing org.lsmp.djep.xjep.*
    Simplification org.lsmp.djep.xjep.*, and org.lsmp.djep.sjep.*
    re-entrant parser org.lsmp.djep.xjep.*
    Variables with equations org.lsmp.djep.xjep.*
    Macro Functions (functions defined by an equation) org.lsmp.djep.xjep.*
    Utilities for examining and modifying the parse trees
    org.lsmp.djep.xjep.*
    Differentiation

    org.lsmp.djep.djep.* (1)

    Basic Vectors and Matrices org.lsmp.djep.vectorJep.*
    Advanced Vectors and Matrices org.lsmp.djep.matrixJep.* (2)
    Calculation over arbitrary groups including exact arithmetic over integers and rationals. org.lsmp.djep.groupJep.*
    Fast evaluation. Single valued org.lsmp.djep.rpe.* Matrix and vectors org.lsmp.djep.mrpe.*

    Notes: (1) requires the org.lsmp.djep.xjep.* package.
    (2) requires the org.lsmp.djep.xjep.*, org.lsmp.djep.djep.* org.lsmp.djep.vectorJep.* packages.

    Example applications

    A number of example applications can be found in the org.lsmp.djepExamples.* package. Theres fall into two types AssignmentExample, XJepExample, PrintExample, DiffExample, VectorExample, VectorPrint, and MatrixSpeed are simple applications which give examples of different features. The other types of examples are console applications which allow equations to be typed in, these are DJepConsole, VectorConsole, MatrixConsole and GroupConsole.

    Some JUnit test are available in the org.lsmp.djepJUnit.* package. These test many features of the packages and illustrate some of the features.

    Web pages

    jep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/djep.html0000644000000000000000000002123210615400336020522 0ustar rootroot DJep - differentiation in the Java expression parser

    DJep - differentiation of equations in JEP


    Faculties for differentiation are offered by DJep class in the org.lsmp.djep.djep package. The DJep class should be used instead of the JEP or XJep classes and has all the features of both classes.

    An interactive console applet interactive console applet illustrates the functionality of DJep.

    Usage

    There are two main ways differentiation can be used:

    1. Using the differentiate(Node node,String name) method of DJep.
    2. Using the "diff" operator in an equation.
    The following code gives an example of it's use
    import org.nfunk.jep.*;
    import org.lsmp.djep.xjep.*;

    public class DiffExample {
    public static void main(String[] args) {
    /* initialisation */
    DJep j = new DJep();
    j.addStandardConstants();
    j.addStandardFunctions();
    j.addComplex();
    j.setAllowUndeclared(true);
    j.setAllowAssignment(true);
    j.setImplicitMul(true);

    // Sets up standard rules for differentiating sin(x) etc.
    j.dv.addStandardDiffRules();

    try
    {
    // parse the string
    Node node = j.parse("sin(x^2)");
    // differentiate wrt x
    Node diff = j.differentiate(node,"x");
    j.println(diff);
    // simplify
    Node simp = j.simplify(diff);
    // print
    j.println(simp);

    // This time the differentiation is specified by
    // the diff(eqn,var) function
    Node node2 = j.parse("diff(cos(x^3),x)");
    // To actually make diff do its work the
    // equation needs to be preprocessed
    Node processed = j.preprocess(node2);
    j.println(processed);
    // finally simplify
    Node simp2 = j.simplify(processed);
    j.println(simp2);
    }
    catch(ParseException e)
    {
    System.out.println("Error with parsing");
    }
    }
    Note that it is usually necessary to simplify an expression after it has been differentiated. This is because the algorithm works by repeated applications of the sum, product, quotient and chain rules. Hence the derivative of "x^2" will be "2*x^1" which can be simplified to "2*x".

    Note also that if the diff(eqn,var) operator is used then the preprocess must be called. This method will scan the equation looking for any instances of diff when it encounters one it will differentiate the first argument with respect to the second argument, which must be a variable. For example preprocessing will convert "diff(x^3,x)" to "3*x^2".

    The diff operator can be used several times in an expression allowing higher derivatives to be used, for example "diff(diff(x^2*y,y),x)" is allowed.

    Assignment and differentiation

    Differentiation can be combined with assignment so it is possible to set the equation of a variable using 'y=x^5' and then differentiate it using 'diff(y,x)':

    // Combine assignment and differentiation
    Node node1 = j.parse("y=x^5");
    j.preprocess(node1);
    // A diff operator with an equation involving a variable as first argument
    Node node2 = j.parse("diff(y,x)");
    Node simp2 = j.simplify(j.preprocess(node4));
    j.println(simp2);

    When "diff(y,x)" is encountered during preprocessing and "y" is a variable with an equation then special PartialDerivative variable {dy/dx} is created and its equation calculated from the equation for "y". In the above example the variable {dy/dx} would have equation "5*x^4", and simp4 would be just contain a reference to the {dy/dx} variable. Things work correctly for more complicated expressions like "diff(y^2+x,x)" which would become "2*y*{dy/dx}+1".

    A slight change is made to the printing routines which can allow printing of the equations for normal variable (default: off) and partial derivatives (default: on). Hence

    j.println(simp2);                      // prints 5.0*x^4.0
    j.getPrintVisitor().setMode(DPrintVisitor.PRINT_PARTIAL_EQNS,false);
    j.println(simp2); // prints dy/dx
    Node node5 = j.parse("y");
    j.println(node5); // prints y
    j.dpv.setPrintVariableEquations(true);
    j.println(node5); // prints x^5

    Differentiation of functions

    The chain rule is used for differentiating functions diff(f(y),x) -> diff(f,y)*diff(y,x) and the instructions for differentiating a function are specified by objects which implement the DiffRulesI interface. A variety of different classes are provided in the org.lsmp.djep.djep.diffRules package which allow specific rules to be created. A rule is added using the addDiffRule method and the standard rules are added using addStandardDiffRules. For example

        j.addDiffRule(new MacroDiffRules(j,"COs","-sin(x)"))

    adds the rule for differentiating COs which is specified by the string "-sin(x)". There are several other ways rules can be constructed which are discussed in the JavaDoc.

    jep-2.4.1-ext-1.1.1-gpl/doc/html/extensions/xjep.html0000644000000000000000000006042210615400344020551 0ustar rootroot XJep - Extensions to the Java Expression Parser

    XJep - extensions to JEP


    The org.lsmp.djep.xjep package offers a number of extensions to the standard JEP package:

    • Printing: equations can be easily printed or converted to strings with intelligent handling of brackets.
    • Simplification equations like 2.0*x^1.0*1.0+0.0 equations can be simplified to produce 2.0*x
    • Re-entrant parsers allows equations to be separated by ;.
    • Variable with equations and lazy evaluation.
    • Macro functions functions specified by a simple function call.
    • New functions include Sum(x^2,x,1,10) finds the sum of x^2 with x running from 1 to 10.
    • Utilities for working with parse trees a number of utilities are available for programatically creating and copying and working with the parse trees.

    An interactive console applet interactive console applet illustrates the functionality of XJep.

    Basic Usage


    To use all the features mention on this page the org.lsmp.djep.xjep.XJep class should be used instead of the standard JEP class. All the standard JEP methods are available. For example
    import org.nfunk.jep.*;
    import org.lsmp.djep.xjep.*;

    public class XJepExample {
    public static void main(String[] args) {

    XJep j = new XJep();

    j.addStandardConstants();
    j.addStandardFunctions();
    j.addComplex();
    j.setAllowUndeclared(true);
    j.setImplicitMul(true);
    j.setAllowAssignment(true);

    try {
    Node node = j.parse("x = 3");
    Node processed = j.preprocess(node);
    Node simp = j.simplify(processed);
    Object value = j.evaluate(simp);
    System.out.println(value.toString());
    j.println(simp);
    } catch (ParseException e) {} catch (Exception e) {}
    }

    The parse, preprocess, simplify, evaluate sequence is the standard idiom for using this package.

    Printing and conversion to strings

    A number of different routines are available to print equations:
    public void print(Node node);  // prints the expression tree
    // specified by node on standard output
    public void print(Node node,PrintStream out); // prints on given stream
    public void println(Node node); // newline at end
    public void println(Node node,PrintStream out); // newline at end
    public String toString(Node node); // returns a string

    These methods convert the expression specified by node to a one line string representation. The routines attempt to produce as simple a representation of the string as possible. However brackets are used to resolve ambiguity. Hence the equation "a+(b*c)" will be printed as "a+b*c" whilst "a*(b+c)" will be printed as "a*(b+c)".

    XJep j = new XJep();
    ....
    try {
    // parse expression
    Node node = j.parse("a*b+c*(d+sin(x))");
    // print it
    j.println(node);
    // convert to string
    String str = j.toString(node);
    System.out.println("String is '"+str+"'");
    } catch(ParseException e) { System.out.println("Parse error"); }
    By default unnecessary brackets are removed. If you wish to print with lots of brackets (for example to examine exactly how an expression has been interpreted) then you can use:
        j.getPrintVisitor().setMode(PrintVisitor.FULL_BRACKET,true);
    j.println(node);

    At some stage in the future print facilities to produce MathML and other output formats will be included.

    The way that numbers are displayed can be set by supplying a java.text.NumberFormat object.

    NumberFormat format = NumberFormat.getInstance();
    j.getPrintVisitor().setNumberFormat(format);
    format.setMaximumFractionDigits(3);
    format.setMinimumFractionDigits(0);
    		
    String s1 = "[10,0,0.1,0.11,0.111,0.1111,0.999,0.9999]";
    Node n1 = j.parse(s1);
    System.out.println(j.toString(n1));
    

    Prints [10,0,0.1,0.11,0.111,0.111,0.999,1] i.e. numbers are displayed rounded to three decimal places.

    Simplification

    The XJep class also offers routines to simplify expressions:

    XJep j = new XJep();
    ....
    Node node=j.parse("1*x^1+0");
    j.println(node);
    Node simp=j.simplify(node);
    j.println(simp);
    which produces the output
    1.0*x^1.0+0.0
    x
    Note how redundant parts of the equation like addition by zero, multiplication by 1 and raising to the power of one are removed from the equation. Any constant expressions like 1+2*3*cos(0) will also be simplified (in this case giving 7). The simplification algorithm is not perfect and there may well be some expressions which will not be simplified completely. We hope to improve the algorithm more at a later date.

    Experimental A more advanced simplification routine is offered by the and org.lsmp.djep.sjep.* package. This converts nodes to an internal polynomial representation, ensuring that monomials of the same type are added together. Also allows full expansion of polynomials. It should also work with functions which contain other functions.

    Experimental The and org.lsmp.djep.rewrite.* package. allows arbitaty rewrite of equations. Very early in development.

    Re-entrant Parsers

    A new syntactical feature is the use of a semi-colon ; to separate expressions. This allows string like "x=1; y=2; z=x+y;" to be parsed. To enable this the re-entrant methods of the XJep class should be used to access the parser.

    public void restartParser(String string);
    public void restartParser(Reader reader);
    public Node continueParsing() throws ParseException;

    The first two methods re-initialise the parse instructing it to read equations either from the string or a  given Reader (allowing a sequence of equations to be specified in a file). The last method reads the next equation and finishes whenever a semi-colon is encountered. null is returned when there is no more to read. For example

    XJep j = new XJep();
    j.setAllowAssignment(true);
    ...
    j.restartParser("x=1; y=2; z=x+y;");
    try {
    Node node;
    while((node = j.continueParsing()) != null) {
    Node simp = j.simplify(j.preprocess(node));
    Object value = j.evaluate(simp);
    j.println(simp);
    System.out.println(value.toString);
    }
    } catch(Exception e) {}

    Note: null will also be returned if an empty equation is encountered i.e. for string "x=1; ;y=2; z=x+y;" the above loop would terminate before "y=2" is parsed.

    Variables and the preprocessing stage

    Internally variables in the org.lsmp.djep.xjep package have both a value and an equation. The equation for a variable is set using the assignment syntax "x=3" or "y=x^2". However the equations are not set by the parser. Instead a new preprocess method is called after parsing and before evaluation.

        Node node = j.parse("x=3");
        Node processed = j.preprocess(node);  // sets the equation for variable x
        Node simp = j.simplify(processed);
        Object value = j.evaluate(simp);
        Node node2 = j.parse("y=x^2");
        Node processed2 = j.preprocess(node2); // sets the equation for variable y
        Node simp2 = j.simplify(processed2);
        Object value2 = j.evaluate(simp2);

    The equation for a variable can be recovered by using

    j.getVar("y").getEquation();

    the preprocess method has additional features when DJep or MatrixJep are used.

    Reusing sets of equations

    The same set of equations can be used with different values for the variables. However, a little care is needed to keep all the variables with up to date values. There are several different strategies which could be used.

    Re-evaluation: By calling j.evaluate on each node this will bring the values of variables on the left had side of an assignment ("x=3" or "y=x^2") will be brought up-to-date.  It is important that this is carried out in the correct order, so that the equation setting the value of a variable is evaluated before equations which rely on this equation.

    XJep j = new XJep();
    ...
    // Setting up equations x=3; y=x^2; z=y+x;
    Node node1 = j.preprocess(j.parse("x=3"));
    System.out.println(j.evaluate(node1)); // prints 3
    Node node2 = j.preprocess(j.parse("y=x^2"));
    System.out.println(j.evaluate(node2)); // prints 9
    Node node3 = j.simplify(j.preprocess(j.parse("z=y+x")));
    System.out.println(j.evaluate(node3)); // prints 12

    // Change value of x, evaluate equations in turn
    j.setVarValue("x",new Double(4));
    System.out.println(j.evaluate(node2)); // prints 16
    System.out.println(j.evaluate(node3)); // prints 20
    System.out.println("z: "+j.getVarValue("z").toString()); // prints 20

    Calculating variable values from their equations: The calcVarValue method re-calculate the value of variables using it's equation. Note that is important that the preprocess call is used to set the equations for the variables. The values of the variables should be calculated in order.

    j.setVarValue("x",new Double(5));
    System.out.println(j.calcVarValue("y").toString()); // prints 25
    System.out.println(j.calcVarValue("z").toString()); // prints 30

    Lazy evaluation: A lazy evaluation strategy is used by the evaluator to calculate the values of variables. Each variable has a flag to specify whether its value is up-to date or valid. If if is valid then the current value will be used during evaluation, if not then the variable's equation is used to calculate its value. This evaluation happens in a recursive fashion, so that if z depends on y and y depends on x then the equation for x will be evaluated first.

    It should be noted that the values of variables are marked as valid whenever their equations are evaluated. This can cause curious behaviour in long chains of equations. The j.getSymbolTable().clearValues() method can be called to mark all variables as being invalid (except constants) and hence ensures that all intermediate equations will be executed as needed. This method should be called before the values of equations are set using setVarValue. 

    The upshot of the above is that if clearValues is called then there is no need to evaluate intermediate equations, just the final variable or equation needs to be calculated.

    j.getSymbolTable().clearValues();
    j.setVarValue("x",new Double(6));
    System.out.println(j.findVarValue("z").toString()); // prints 42

    j.getSymbolTable().clearValues();
    j.setVarValue("x",new Double(7));
    System.out.println(j.evaluate(node3));

    The motivation behind this scheme comes into play if differentiation when partial derivatives of variables are automatically calculated.

    Summary of Variable Use

    Summary of use of variables in the XJep package:

    Class
    Method
    Action
    JEP
    public void addConstant(String name,Object value)
    Adds a constant variable whose value can not be changed.
    JEP
    public void addVariable(String name,Object value) Adds a mutable variable.
    JEP
    public boolean setVarValue(String name,Object value) Sets the value of a mutable variable. False on error.
    JEP
    public Variable getVar(String name)
    Returns the object representing the variable.
    JEP
    public Object getVarValue(String name)
    Gets the value of the variable. Does not re-calculate.
    JEP
    public SymbolTable getSymbolTable()
    Returns the symbol table containing all the variables.
    XJep
    public Object calcVarValue(String name) Calculates the value of a variable from its equation.
    XJep
    public preprocess(Node node)
    Causes the equations of variable on the lhs of an assignment equation to be set.
    XVariable
    public Node getEquation()
    Returns the equation of a variable.
    XVariable
    public Object calcValue()
    Calculates the value of a variable from its equation.
    SymbolTable
    public void clearValues()
    Marks all non constant variables as invalid.


    There are further methods for working with variable in the Variable, XVariable, SymbolTable and XSymbolTable classes. Standard Hashtable methods can also be used

    Macro Functions

    XJep also make it easier to define you own simple functions in your code, without having to create a new sub-class of PostFixMathCommand. Such functions can be defined using an String containing its defining equation.

    // creates a function with 1 argument
    j.addFunction("zap",new MacroFunction("zap",1,"x*(x-1)/2",j));
    Node node = j.parse("zap(10)");
    System.out.println(j.evaluate(node)); // print 45
    See the MacroFunction for precise details of the syntax. Currently only works in 1D, i.e. no vectors or matrices.

    Sum type function

    An equivilent of the sigma notation for summation are provided by SumType functions. For example Sum(x^2,x,1,10) finds the sum of x^2 with x running from 1 to 10, i.e. 1^2+2^2+...+10^10. Other sum-type functions include:

    • Sum - finds sum over range.
    • Product - finds the product
    • Min - finds minimum value
    • Max - finds maximum value
    • MinArg - finds index of variable giving the minimum
    • MaxArg - finds index of variable giving the maximum
    • Simpson - implements Simpson rule for aproximation to integral.
    Note all these function begin with a capital letter to distinguish from sum(1,2,3,4) which justs finds the sum of its arguments.

    Other Functions

    The toHex() function converts to hexidecimal string toHex(255) -> 0xff. If a second argument is given this specifies number of displayed fraction digits toHex(-15/16,1) -> -0x0.1.

    toBase(val,base) and toBase(val,base,digits) convert to a given base with digits fractional digits.

    Finding Variables in equations

    getVarsInEquation find all the variables in an equation. getVarsInEquation Finds variables, in an equation. If any of those variables are defined by equations, returns those variables as well. An ordered sequence is returned, so that evaluation each variable in turn will give a correct equation.

    Other utilities

    A number of other features are included in the xjep package. These all work on the trees which are used internally to represent an equation.
    • DeepCopyVisitor: creates a copy of a node tree.
    • SubstitutionVisitor: substitutes each occurrence a variables by an equation.
    • NodeFactory: this contains useful methods for constructing an expression tree. By repeatedly calling this methods a expression tree can be constructed.
    • TreeUtils: various utility functions for determining the type of node and accessing its properties.
    • XOperatorSet: a collection of operators which contain information about their precedence, commutativity etc.
    jep-2.4.1-ext-1.1.1-gpl/doc/html/advanced.html0000644000000000000000000001062110615400346017147 0ustar rootroot JEP - Java Math Expression Parser

    Advanced features

    Manipulating expressions

    The getTopNode() method can be used to get the expression tree after parsing an expression. This will be useful if you want to do more than just evaluate the expressions you parse. For example, you may want to determine the derivative of an expression. In order to be able to this, you will need direct access to the expression tree.

    The expression tree consists of nodes. Each of the nodes in the parse tree is an object of one of the following types:

    All of them extend the SimpleNode class (which implements the Node interface). Binary operators (+,-,*,/...) and functions are ASTFunNodes. The type of operator (the function class) is stored in the pfmc member, and as a string in the name member. Use the getPFMC() and getName() methods to access these members.

    To traverse the expression tree you can use a visitor class (ParserDumpVisitor is an example class used to print out all the nodes). Look at the EvaluatorVisitor class to see how expressions are evaluated using the Visitor design pattern.

    jep-2.4.1-ext-1.1.1-gpl/doc/html/main.css0000644000000000000000000000526310615400334016155 0ustar rootrootbody { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; background: #fff; } td { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; } img { border: 0px; } a { font-family: Verdana, Arial, Helvetica, sans-serif; color: #036; font-size: 10pt; } a:visited { color: #009; } a:hover { color: #33f; } h1 { color: #003; font-family: Arial, Helvetica, sans-serif; font-size: 15pt; font-weight: bold; margin-top: 20px; margin-bottom: 20px; border-bottom: solid; border-width: 1px; border-color: #ccc; } h2 { color: #036; font-family: Arial, Helvetica, sans-serif; font-size: 13pt; margin-top: 30px; margin-bottom: 5px; padding-bottom: 0px; } h2.version { color: #000; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; font-size: 10pt; margin-top: 30px; margin-bottom: 5px; padding-bottom: 0px; } H2.version .date { color: #999; } h3 { color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; margin-bottom: 5px; } OL { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; } UL { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; } LI { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; } pre { font-size: 10pt} /*-- navcontainer ----------------------------------------------*/ #navcontainer { position: absolute; top: 12px; left: 12px; width: 180px; border: 1px solid #999; padding: 5px; /*border-right:1px solid #999;*/ } #navcontainer h1 { color: #003; font-size: 11pt; font-weight: bold; margin-top: 15px; margin-bottom: 5px; padding-top: 5px; border-top: solid #ccc 1px; border-bottom: none; } #navcontainer ul { margin: 0; padding: 0; color: #000; background: #fff; } #navcontainer ul li { display: inline; } #navcontainer ul li a { display: block; padding: 5px 5px; color: #000; text-decoration: none; } #navcontainer ul li a:hover { color: #fff; background: #036; } /*-- centercontent ----------------------------------------------*/ #centercontent { width: 500px; text-align: left; margin-left: 230px; /* margin-left:150px; margin-right:auto; */ } /*-- topbar ------------------------------------------------------*/ .topbar { margin: 20px 0 0px; text-align: right; border-bottom: 1px solid #999; color: #666; } .topbar img { border: 0px; } /*-- footer ------------------------------------------------------*/ #footer { margin: 40px 0 80px; border-top: 1px solid #999; color: #666; } jep-2.4.1-ext-1.1.1-gpl/doc/html/grammar.html0000644000000000000000000002131310615400336017027 0ustar rootroot JEP - Java Math Expression Parser

    Grammar

    This grammar was generated from the Parser.jj file using the jjdoc utility from JavaCC. Operators are ordered from lowest to highest precedence (from top to bottom).

    Start ::= ( Expression ( <EOF> | <SEMI> ) | ( <EOF> | <SEMI> ) )
    Expression ::= AssignExpression
    | OrExpression
    AssignExpression ::= ( Variable <ASSIGN> Expression )
    OrExpression ::= AndExpression ( ( <OR> AndExpression ) )*
    AndExpression ::= EqualExpression ( ( <AND> EqualExpression ) )*
    EqualExpression ::= RelationalExpression ( ( <NE> RelationalExpression ) | ( <EQ> RelationalExpression ) )*
    RelationalExpression ::= AdditiveExpression ( ( <LT> AdditiveExpression ) | ( <GT> AdditiveExpression ) | ( <LE> AdditiveExpression ) | ( <GE> AdditiveExpression ) )*
    AdditiveExpression ::= MultiplicativeExpression ( ( <PLUS> MultiplicativeExpression ) | ( <MINUS> MultiplicativeExpression ) )*
    MultiplicativeExpression ::= UnaryExpression ( ( PowerExpression ) | ( <MUL> UnaryExpression ) | ( <DOT> UnaryExpression ) | ( <CROSS> UnaryExpression ) | ( <DIV> UnaryExpression ) | ( <MOD> UnaryExpression ) )*
    UnaryExpression ::= ( <PLUS> UnaryExpression )
    | ( <MINUS> UnaryExpression )
    | ( <NOT> UnaryExpression )
    | PowerExpression
    PowerExpression ::= UnaryExpressionNotPlusMinus ( ( <POWER> UnaryExpression ) )?
    UnaryExpressionNotPlusMinus ::= AnyConstant
    | ( Function | Variable )
    | <LRND> Expression <RRND>
    | ListExpression
    ListExpression ::= ( <LSQ> Expression ( <COMMA> Expression )* <RSQ> )
    Variable ::= ( Identifier )
    Function ::= ( Identifier <LRND> ArgumentList <RRND> )
    ArgumentList ::= ( Expression ( <COMMA> Expression )* )?
    Identifier ::= ( <INDENTIFIER1> | <INDENTIFIER2> )
    AnyConstant ::= ( <STRING_LITERAL> | RealConstant )
    RealConstant ::= ( <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> )
    jep-2.4.1-ext-1.1.1-gpl/doc/html/functions.html0000644000000000000000000004636310615400346017426 0ustar rootroot JEP - Java Math Expression Parser

    Functions

    Note that you can always add new custom functions. Each of the following functions can be applied to objects of the types indicated.

    Functions added with addStandardFunctions():
        Double Complex String Vector
    Sine sin(x) Check Check    
    Cosine cos(x) Check Check    
    Tangent tan(x) Check Check    
    Arc Sine asin(x) Check Check    
    Arc Cosine acos(x) Check Check    
    Arc Tangent atan(x) Check Check    
    Arc Tangent (with 2 parameters) atan2(y, x) Check      
    Hyperbolic Sine sinh(x) Check Check    
    Hyperbolic Cosine cosh(x) Check Check    
    Hyperbolic Tangent tanh(x) Check Check    
    Inverse Hyperbolic Sine asinh(x) Check Check    
    Inverse Hyperbolic Cosine acosh(x) Check Check    
    Inverse Hyperbolic Tangent atanh(x) Check Check    
    Natural Logarithm ln(x) Check Check    
    Logarithm base 10 log(x) Check Check    
    Exponential (e^x) exp(x) Check Check    
    Absolute Value / Magnitude abs(x) Check Check    
    Random number (between 0 and 1) rand()        
    Modulus mod(x,y) = x % y Check      
    Square Root sqrt(x) Check Check    
    Sum sum(x,y,z) Check Check Check  
    If if(cond,trueval,falseval) Check      
    Str (number to string) str(x) Check Check Check Check
    Binomial coefficients binom(n,i) Integer values

    Functions added with addComplex():
        Double Complex String Vector
    Real Component re(c) Check Check    
    Imaginary Component im(c) Check Check    
    Complex Modulus (Absolute Value) cmod(c) Check Check    
    Argument (Angle of complex value, in radians) arg(c) Check Check    
    Complex conjugate conj(c) Check Check    
    Complex, constructs a complex number from real and imaginar parts complex(x,y) Check      
    Polar, constructs a complex number from modulus and argument polar(r,theta) Check      

    Custom Functions

    The following is an example of how a custom function can be added.

    Assume you want to add a function "half" to divide a number by two (for demonstration purposes).

    1. Create a class that extends PostfixMathCommand (in the org.nfunk.jep.function package). In this example we will name it "Half"
    2. In the constructor set the number of arguments to be taken. In our case this is one. Do this by writing "numberOfParameters = 1;"
      If you want to allow any number of parameters, initialize the numberOfParameters value to -1. It is highly recommended to study the Sum.java code as an example of a function that accepts any number of parameters.
    3. Implement the run(Stack inStack) method. The parameters are passed in a Stack object. This same stack is used as the output for the function. So we first need to pop the parameter off the stack, calculate the result, and finally pop the result back on the stack.
      public void run(Stack inStack) throws ParseException {
      
         // check the stack
         checkStack(inStack);
         
         // get the parameter from the stack
         Object param = inStack.pop();
      
         // check whether the argument is of the right type
      if (param instanceof Double) { // calculate the result
      double r = ((Double)param).doubleValue() / 2; // push the result on the inStack
      inStack.push(new Double(r));
      } else {
      throw new ParseException("Invalid parameter type"); } }
    4. In your main program or applet that is using the parser, add the new function. Do this by writing
      parser.addFunction("half", new Half());
    5. If numberOfParameters == -1 you may wish to overwrite the boolean checkNumberOfParameters(int n) to catch an illegal number of arguments at parse time.

    Source files

    jep-2.4.1-ext-1.1.1-gpl/doc/html/faq.html0000644000000000000000000001400010615400344016142 0ustar rootroot JEP - Java Math Expression Parser

    Frequently Asked Questions

    Q: I've noticed that JEP does not give accurate results for certain expressions. Why is this? What can I do about it?

    A: You will notice that when you evaluate something as simple as "8 - 7.9" the result will be 0.09999999999999964 rather than 0.1. These inaccuracies are the result of floating point arithmetic. Internally JEP uses the double type to represent numbers by default. Unfortunately, even for trivial calculations such as "8 - 7.9" the calculation can not be performed accurately.

    You will notice the same if you run

      double a=8, b=7.9;
      System.out.println("a-b = " + (a-b));

    in a Java program.

    Although floating point numbers are accurate enough for many applications, these types of errors should not be ignored in applications where accuracy is critical.

    The DJEP library provides tools to perform accurate calculations using more sophisiticated number types. DJEP includes GroupJep which is intended for exact arithmetic on groups. See the Groups documentation for details. It utilizes the BigInteger and BigDecimal classes to represent numbers rather than the double type.

    Q: I don't need all the functions supplied by JEP. Is there a way to not load some of them, or completely remove some from the package?

    A: Stripping down JEP into a lean mean arithmetic machine!

    Option 1:
    In some cases you will not require all the built in functions supported by JEP. The easiest way to accomplish this is simply not calling the addStandardFunctions() method before parsing. Then, you can call addFunction() for any specific functions you may require.

    Option 2:
    If you think it is necessary to minimize the size of JEP to a minimum, you can remove all function classes other than the operators (if you don't need them). This will leave you with a parser that can still do basic arithmetic, but not the fancy functions like sin() and cos(). It saves you about 17KB of classes (15% of JEP in total).

    Instructions:
    - The function classes are all located in the org.nfunk.jep.function package. Operators (+, -, *, /,…) are also implemented as functions. These should NOT be removed if you still want JEP to work properly. The following function classes are used to implement operators:

    Add Modulus Subtract
    Comparative Multiply UMinus
    Divide Not  
    Logical Power  

    - Open the source code for JEP and look for the addStandardFunctions() method. It contains a list of almost all non-operator functions. For every function class you remove from the function directory, you must also remove the associated line from this method.
    - Recompile JEP, and you should have a lean mean arithmetic machine!

    jep-2.4.1-ext-1.1.1-gpl/doc/html/types.html0000644000000000000000000002222410615400350016543 0ustar rootroot JEP - Java Math Expression Parser

    Data Types

    JEP supports a number of different data types and allows. These include numbers, strings, vectors, complex numbers. Numbers are represented by the double data type by default. It is however possible to change the internal representation as described in the section Using custom number classes.

    Strings

    Strings can be entered in an expression by using double quotes. They can be concatenated with the + operator and compared with the == and != relational operators. A sample expression involving the string type is "foo" + "bar" == "foobar", which would be evaluated by JEP as 1 (true).

    To add a string as a variable, use the addVariable(String name, Object value) method. If the result of an expression is a string, it can be obtained by calling the getValueAsObject() function.

    Vectors

    Vectors are ordered sets of Double elements. A vector is a list of values, separated by commas, and enclosed by square brackets. An example expression involving a vector is:

    [3, 4, 5]*2

    It would be evaluated as [6, 8, 10] by JEP. To add a vector as variable, use the addVariable(String name, Object value) method. If the result of an expression is a vector, it can be obtained by calling the getValueAsObject() function.

    Complex numbers

    If you want to use complex numbers in your expression, you can call addComplex() after creating the parser object. This will add the imaginary unit as constant i. Two parser functions re() and im() are also added and can be used to obtain the real and imaginary components of complex numbers. You will need to import the org.nfunk.jep.type.Complex class to be able to manipulate complex values from expressions.

    By using the imaginary unit constant i, you can work with complex numbers in your expressions. A sample complex expression would be (1+2*i)^3. Currently the (re, IM) notation is not supported.

    To obtain a complex value from an expression, you must use the getComplexValue() function. It will evaluate the expression and return the result as a Complex object. Note that the class used internally for Complex numbers is also used for returning the value.

    Adding a complex variable or constant to the parser before evaluating an expression can be done with addVariable(String name, double re, double IM). It takes three parameters: the name of the variable as string, the real component, and the imaginary component.

    Using custom number classes

    By default when an expression such as "1+2" is parsed, the constants "1" and "2" are created internally as Double objects. In most cases this is fine, but in some cases you may want to use custom classes for representing numbers.

    This is made possible through creating a number class that implements the NumberFactory interface. It includes one method called createNumber(String value), which should return an object initialized to the value of the parameter. You can load your custom number factory with the JEP constructor JEP(boolean traverse_in, Boolean allowUndeclared_in, Boolean implicitMul_in, NumberFactory numberFactory_in).

    The custom number objects need to be handled by custom functions which you can create by following the instructions on the Custom Functions page.

    Custom types

    In most cases, you will only need to work with the few built in types that JEP supplies (Double, Complex, Vector, String). But suppose you want to evaluate expressions that involve other types. This is possible by using the addVariableAsObject(String name, Object value) method to add variables of any type. The only place where the type of a variable matters, is in the function classes.

    When an expression is evaluated, values are operated on with the classes in the function package. These include the operators (such as Add and Subtract), as well as the functions (such as Sine and Cosine). Without making modifications to the source code, only the default types are handled with these classes. So, in order to be able to handle your own types, you will need to modify theses classes, or make your own function classes as described in the custom functions section.

    jep-2.4.1-ext-1.1.1-gpl/doc/html/version.html0000644000000000000000000004260710615400346017100 0ustar rootroot JEP - Java Math Expression Parser

    Version History

    Version 2.4.1 (released 2007/04/25)

    • added rounding functions round, ceil, and floor
    • fixed bug [ 1563324 ] getValueAsObject always returns null after an error
    • fixed bug [ 1670974 ] String to double <= comparison message incorrect
    • fixed bug [ 1706295 ] Wrong error output when evaluating variables

    Version 2.4.0 (released 2006/04/01)

    • Evaluator now switchable to allow null variable values.
    • SymbolTable can now tell java.util.observers when new variables are created.
    • Changes in Error handling
    • New functions binom(n,i) binomial coeffs, conj(z) - complex conjugate
    • Added anti aliasing to Function Plotter applet
    • Fixed bug 1177557: log(NaN) returns Complex(NaN,NaN) instead of NaN
    • Fixed bug 1061200: Null Pointer in Parser when using non Default constructor

    Version 2.3.1 (released 2006/01/27)

    • Fixed bug 1046349: bug in sum()
    • Fixed broken links in documentation
    • Fixed bug 1051988: JEPTester falsely reports "No errors"
    • Fixed documentation error 1358815: if - function is documented wrong
    • Added more tests for sum function
    • Updated build.xml to work with 1.5 JVMs

    Version 2.3.0 (released 2004/10/03)

    • Switched from Java 1.1 compatibility to 1.2 compatibility
    • Documentation updates
    • Fixed batch script issues from beta 2

    Version 2.3.0 beta 2 (released 2004/09/03)

    • 2004/09/11: Renamed angle() function to atan2()
    • 2004/04/12: New functions if, str, complex, polar.
    • 2004/04/12: The ^ operator is now overloaded to be the cross product for 3D vectors as well as power.
    • 2004/04/12: Various changes by Richard Morris (see DJEP Version History)
    • 2003/08/15: Added new evaluation method that more than doubles evaluation performance
    • 2003/08/15: Renamed addComplexVariable() and addVariableAsObject() to addVariable(). Now all three methods for adding different types of variables are named the same.
    • 2003/08/10: Improved error handling and reporting in EvaluatorVisitor.

    Known Issues:

    • Windows batch scripts for starting the examples are broken. This is due to switching from the MS JVM to the Sun appletviewer. Planned to be fixed for the 2.3.0 release.

    Version 2.24 (released 2002/12/31)

    • 2002/12/25: Fixed "not replacing escape sequences in strings" bug

    Version 2.23 (released 2002/08/03)

    • 2002/07/01: Started adding Number support to JEP class and functions
    • 2002/07/08: Fixed string concatenation bug
    • 2002/07/10: Added NumberFactory class and DoubleNumberFactory (with option for custom NumberFactory in JEP constructor)
    • 2002/08/02: Added website documents to distribution

    Version 2.22 (released 2002/07/04)

    • 2002/06/06: Removed symbol table information from ASTVarNode (making AST nodes into pure data structure elements)
    • 2002/06/20: Fixed sum() issue (functions with variable number of parameters)
    • 2002/06/24: Rearranged function class structure by letting PostfixMathCommand implement PostfixMathCommandI (no changes to functionality)
    • 2002/06/25: Added multiple thread testing classes
    • 2002/06/26: Made EvaluatorVisitor non-singleton (was doing more harm than good)
    • 2002/06/28: Added Unicode character support for variable names

    Version 2.21 (released 2002/06/04)

    • 2002/06/03: Fixed 1.1 compatibility issue in JEP.java (was using add() and clear() which are not included in the 1.1.8 VM).

    Version 2.20 (released 2002/05/31)

    • 2002/01/20: Combined multiplication and division to the same precedence level
    • 2002/03/10: Added implicit multiplication, allowing expressions like "3x == 3*x"
    • 2002/03/14: Improved evaluation performance through creating only one stack for evaluation
    • 2002/03/19: Changes to operator precedence (more like C and Java)
    • 2002/03/19: Now using JavaCC 2.1
    • 2002/03/24: Added a console application to the org.nfunk.jepexamples package
    • 2002/03/28: Implemented evaluation using the Visitor design pattern
    • 2002/04/13: Added setAllowUndeclared() and setImplicitMul() for control of undeclared variables, and implicit multiplication options
    • 2002/04/15: Added getSymbolTable() for obtaining list of variables in the symbol table (e.g. after parsing an expression with allowUndeclared=true)
    • 2002/04/17: Prepared directory structure for building with ant
    • 2002/04/19: Full transition of build environment to ant
    • 2002/04/20: Finally was persuaded to add the sqrt() function to the set of built-ins
    • 2002/04/27: Cleaned up error reporting using an error list in the JEP class
    • 2002/05/27: New documentation
    • 2002/05/30: Modifications to the sample applets

    Version 2.12 (released 2002/02/01)

    • 2001/08/31: Made a change to the Complex power function Complex.pow(to avoid problems with applets run in Internet Explorer (Math.exp(-Infinity) was not producing 0.0)
    • 2001/09/10: Started working on array type
    • 2001/09/20: Allowed variable number of arguments in functions
    • 2001/09/20: Fixed undetected syntax error bug involving a comma before a list of function parameters
    • 2001/10/17: Changed order of precedence for power and unary signs. Now power is of higher order than unary plus or minus
    • 2001/11/10: Tweaked complex power functions
    • 2001/11/10: Added error reporting for exceptions that occur while evaluating
    • 2001/11/17: Edited the parser class to work without static function and symbol tables
    • 2001/12/21: Completed the JEPTester class for verifying correct evaluation
    • 2002/01/06: Replaced some Vector operations that relied on AbstractList with Java 1.1 compliant code

    Version 2.11

    • 2001/08/26: Substituted the Netlib complex number class with a custom class

    Version 2.10

    • 2001/07/07: Finished adding complex numbers, and incorporated complex numbers in nearly all built in functions
    • 2001/07/08: Added string handling with concatenation with the + operator and comparison with ==
    • 2001/07/16: Renamed the package to org.nfunk.jep
    • 2001/08/24: Bugfix - subtraction of complex numbers was not working properly

    Version 2.05

    • 2001/03/21: Fixed PostfixMathCommand class to allow inheritance to classes in other packages
    • 2001/04/10: Added some error reporting functions to main interface class (Error name and position)
    • 2001/06/01: Finished adding hyperbolic trigonometric functions and packaging.

    Version 2.04

    • 2001/03/01: Fixed EOF problem (included EOF in grammar)
    • 2001/03/16: Removed a few redundant exception classes

    Version 2.03

    • 2001/02/17: Corrected order of precedence for logical operators
    • 2001/02/17: Added '&&', '||', and '!' operators to extend the logical functionality of the parser
    • 2001/02/07: Disabled the default command line output. For debugging purposes, you may want to try to use setTraverse(true)

    Version 2.0

    • 2000/10/16: Started rebuilding the whole parser with JavaCC (http://www.webgain.com/products/java_cc/)
    • 2000/10/27: Completed restructuring main background parser functions in JavaCC
    • 2000/11/17: Created a simple interface class for intuitive interaction
    • 2000/12/10: Added a few logical operators
    • 2001/01/06: Released the freshly rebuilt parser

    Version 1.1

    • 2000/11/30: Changed order of precedence so division occurs before multiplication
    • 2000/10/01: Added exponential notation (i.e. 1.23e-3)
    • 2000/10/16: Tweaked code here and there
    • 2000/10/21: Finished new sample applet
    • 2000/10/21: Repackaged and reorganized all source code and classes

    Version 1.0

    • 2000/07/03: Added more documentation
    • 2000/07/10: Removed all operator nodes such as MulNode or PlusNode, and replaced them by using FunNode nodes with PostfixMathCommands
    • 2000/08/07: Considering using JavaCC to recreate the Parser
    • 2000/09/01: Fixed multiple subtraction problem. Now 1-2-3 = (1-2)-3 instead of 1-(2-3)

    Version 0.3

    • 2000/06/01: Created Web page and posted it
    • 2000/06/02: Edited Web page, added one variable field just for integers
    • 2000/06/06: Started adding internal code documentation
    • 2000/06/09: Figured out how to create objects at run-time with the reflection package. Probably useful for future use of user defined functions
    • 2000/06/10: Finished adding capability of parsing standard functions as well as user defined functions (thanks to Ross Bagely)

    Version 0.2

    • 2000/06/18: Added SharedConstants class for the parser package
    • 2000/06/18: Added InvalidExpressionException class which is thrown inside Parser
    • 2000/06/19: Tweaked the error report of Parser
    • 2000/06/27: Simplified process of adding user defined functions by adding a parent class PostfixMathCommand, that contains a function for checking the stack passed to the command
    • 2000/06/27: Extended the FunNode class to be able to handle functions with multiple arguments, needs to be implemented in the parser yet
    • 2000/07/01: Completed expanding parser to handle functions with multiple arguments. Implemented angle function to return the angle whose tangent is equal to the ratio of the arguments x/y (using the Math.atan2 method).
    jep-2.4.1-ext-1.1.1-gpl/doc/html/operators.html0000644000000000000000000002720310615400334017421 0ustar rootroot JEP - Java Math Expression Parser

    Operators

    Built in operators

    All common arithmetic operators are supported. Boolean operators are also fully supported. Boolean expressions are evaluated to be either 1 or 0 (true or false respectively).

    An Check indicates that the operator can be used with the specific type of variable. Refer to the grammar for detailed information about operator precedence.

        Double Complex String Vector
    Power ^ Check Check    
    Boolean Not ! Check      
    Unary Plus, Unary Minus +x, -x Check Check    
    Modulus % Check      
    Division / Check Check   Check
    Multiplication * Check Check   Check
    Addition, Subtraction +, - Check Check Check (only +)  
    Less or Equal, More or Equal <=, >= Check      
    Less Than, Greater Than <, > Check      
    Not Equal, Equal !=, == Check Check Check  
    Boolean And && Check      
    Boolean Or || Check      

    Adding operators

    Adding operators is currently only possible by modifying the JEP source code. To add an operator to the parser several steps are needed:

    • Create a new token with the descriptive name AT, say, and a string representing the operator.
    • Modify the grammer rules to include a rule for the new operator
    • Create a new object implementing org.nfunk.jep.function.PostfixMathCommandI to provide methods for evaluating the operator.
    • Modify or sub class org.nfunk.jep.OperatorSet to bind the operator in the parser to PostfixMathCommand
    Before atempting to add an operator you should be familiar with adding a custom function to JEP.

    JavaCC The parser generator

    Rather than writing the parser by hand in java the parser is created using the JavaCC parser/scanner generator. This reads a file Parser.jjt which is written in a special language which defines the grammer and creates Parser.java and some other java files which implement the parser.

    You should read some of the documentation on JavaCC and JJTree before attempting to modify the parser.

    There is a three step process used to generate the parser.

    1. JJTree is run. This reads the file Parser.jjt and creates a file Parser.jj. The purpose of this step is to add code needed to handle Abstract Systax Trees which are tree structures used represent a mathematical expression. As well as creating parser.jj it also creates some other java files: Node.java which represents the basic node in the parser; ASTConstant.java a node representing a constant value "0" or "1", ASTVarNode.java a node representing a variable, ASTFunNode.java a node representing a function or operator.
    2. javacc is run. This reads Parser.jj and creates Parser.java the actual code for implementing the Parser. Parser.java is a very complicated file with nearly 2000 lines of code.
    3. Normal java comilation step which compiles Parser.java.

    This process should automatically be caried out when the project is built using the ANT build.xml file. It is not sufficient to simple recompile all the java files.

    Only the Parser.jjt file should be modified, Parser.jj, Parser.java should not be modified as they will be overwritten during the build process. Furthermore ASTConstant.java, ASTFunNode.java, ASTStart.java, ASTVarNode.java, JavaCharStream.java, JJTParserState.java, Node.java, SimpleNode.java, ParseException.java, ParserConstants.java, ParserTokenManager.java, ParseTreeConstants.java, Token.java, TokenMgrError.java should not normally be modified as these are also automatically generated.

    jep-2.4.1-ext-1.1.1-gpl/doc/html/CustFunc.java0000644000000000000000000000216610615400350017111 0ustar rootrootimport org.nfunk.jep.*; /** * An example class to test custom functions with JEP. */ class CustFunc { /** * Constructor. */ public CustFunc() { } /** * Main method. Create a new JEP object and parse an example expression * that uses the SquareRoot function. */ public static void main(String args[]) { JEP parser = new JEP(); // Create a new parser String expr = "1 + half(2)"; double value; System.out.println("Starting CustFunc..."); parser.addStandardFunctions(); parser.addStandardConstants(); parser.addFunction("half", new Half()); // Add the custom function parser.parseExpression(expr); // Parse the expression if (parser.hasError()) { System.out.println("Error while parsing"); System.out.println(parser.getErrorInfo()); return; } value = parser.getValue(); // Get the value if (parser.hasError()) { System.out.println("Error during evaluation"); System.out.println(parser.getErrorInfo()); return; } System.out.println(expr + " = " + value); // Print value } } jep-2.4.1-ext-1.1.1-gpl/doc/html/index.html0000644000000000000000000002401310615400342016505 0ustar rootroot JEP - Java Math Expression Parser

    Basic Usage

    Getting started

    Using the JEP package of classes in your project is simple! The following steps will get you started quickly.

    1. Download the JEP package
    2. Unpack the archive
    3. Move the jep-x.x.x.jar file to a directory of your choice (optional)
    4. IMPORTANT: For the Java compiler to be able to find the JEP classes when compiling your program, it needs to know their location. So you will need to add the location of the .jar file to your CLASSPATH environment variable (if you don't know how, read this). Your CLASSPATH variable should contain something like C:\java\packages\jep-x.x.x.jar, depending on where you place the jar file. Alternatively you may need to set the location of the jar archive in your Java IDE so that the compiler finds the library.
    5. In your program, create a new parser object with
      org.nfunk.jep.JEP myParser = new org.nfunk.jep.JEP();
    6. Add the standard functions and constants if you want to be able to evaluate expressions with trigonometric functions and the constants pi and e.
      myParser.addStandardFunctions();
      myParser.addStandardConstants();
    7. By default you need to specify which variables can be used in the expression. If a variable is not added before the expression is parsed, the parser will claim that the expression is invalid (this can be changed by allowing undeclared variables).
      To add the variable x and initialize it to 0 for example, write
      myParser.addVariable("x", 0);
    8. Parse the expression, and evaluate it:
      myParser.parseExpression(ExpressionString);
      result = myParser.getValue();
    9. The values of variables can be changed with the addVariable(String, double) method.

    The code of the sample applets provide more extensive look at how the parser methods are used.

    Error handling

    Errors can occur both while parsing an expression and while evaluating an expression. The hasError() method reports whether an error has occurred during the most recent action (either parsing or evaluation). If the result is true, you can then use getErrorInfo() to obtain further information on the errors that have occurred.

    Evaluating expressions

    Four methods for evaluating an expression are available:

    The first two methods call getValueAsObject() internally, and perform the necessary conversions into either a double value, or a Complex object.

    Alternate parsing and evaluation functions

    There is an alternative method to parsing and evaluating expression which allows a little more flexibility in applications especially when working with a set of related equations. These are:

    public Node parse(String expression) throws ParseException
    public Object evaluate(Node node) throws Exception
    which parse and evaluate the expression. These can be used like
    try
    {
    // Alternative syntax
    Node node1 = j.parse("z=i*pi");
    j.evaluate(node1);
    Node node2 = j.parse("exp(z)");
    Object val2 = j.evaluate(node2);
    System.out.println("Value: "+val2);
    }
    catch(ParseException e) {
    System.out.println("Error with parsing");
    }
    catch(Exception e) {
    System.out.println("Error with evaluation");
    }

    Hence its a bit easier to keep track of a number of equations. Note that using this syntax Exceptions need to be caught and the getTopNode() method will not return meaningful results.

    Implicit multiplication

    You can enable the implicit multiplication option with setImplicitMul(true). The default setting is false (no implicit multiplication).

    Implicit multiplication allows expressions such as "2 x" to be interpreted as "2*x". Note that a space is required between two variables for them to be interpreted as being multiplied. The same holds for a variable followed by a number. For example "y 3" is interpreted as "y*3", but "y3" is interpreted as a single variable with the name y3. If a variable is preceded by a number, no space is required between them for implicit multiplication to come in effect.


    jep-2.4.1-ext-1.1.1-gpl/doc/html/variables.html0000644000000000000000000002157310615400344017360 0ustar rootroot JEP - Java Math Expression Parser

    Variables

    Basics

    Two options are available in working with variables

    1. Do not allow undeclared variables (default): In this case it is necessary to add a variable before parsing an expression with that variable in it. This is accomplished with the addVariable method.
    2. Allow undeclared variables: If you allow undeclared variables, they are automatically added to the symbol table while parsing an expression.

    After an expression has been parsed, variable values can be updated using either addVariable or setVarValue. This allows repeated evaluation of an expression with different variable values.

    The value of a variable can be queried using getVarValue method. A further method getVar returns an object representing the variable.

    Variables can be constants which cannot have their values changed. To add a new constant use addConstant to add a mutable variable use addVariable.

    The SymbolTable class stores objects representing variables rather than just their values. The get and put methods of this class are deprecated. This results in a slight speed up during evaluation.

    Allowing undeclared variables

    To enable parsing of undeclared variables, use setAllowUndeclared(true). The default setting is false (undeclared variables are not allowed).

    If you do not know what variable names may occur in the expression before parsing it, you can use setAllowUndeclared(true). With this option enabled, it is not necessary to add variables to the parser before parsing an expression. If a new variable is found while parsing, it is automatically added to the symbol table. See Obtaining a list of variables to read about how to access these variables.

    Obtaining a list of variables

    While parsing an expression with undeclared variables allowed, a list of all the variables and constants that have been added to the parser, can be obtained with the getSymbolTable method. This method is most useful when the undeclared variables option is enabled. The return value is a SymbolTable object. Note that SymbolTable extends Hashtable.

    Assignment

    Assignment allows the values of variables to be set by using the = operator in equations so it is possible to do something like x=3 then y=x^2 and y will have the value 9. Assignment can be used with the standard JEP package, there is no need to use any of the packages in the org.lsmp.djep tree. To switch on assignment facilities the setAllowAssignment method of the main JEP object should be called.

    // standard initialisation
    JEP j = new JEP();
    j.addStandardConstants();
    j.addStandardFunctions();
    j.addComplex();
    j.setAllowUndeclared(true);
    j.setImplicitMul(true);

    // switch assignment facilities on
    j.setAllowAssignment(true);

    // parse assignment equations
    j.parseExpression("x=3");
    // evaluate it - no need to save the value returned
    j.getValueAsObject();
    // parse a second equation
    j.parseExpression("y=2");
    j.getValueAsObject();

    // an equation involving above variables
    j.parseExpression("x^y");
    Object val3 = j.getValueAsObject();
    System.out.println("Value is " + val3);

    Observers for variables

    Both SymbolTable and Variable implement the Observer/Observable pattern. This allows objects to be informed whenever a new variable is created or when its value has been changed. An example of use is

    public class MyObserver implements Observer
    {
        public void initialise()
        {
            SymbolTable st = j.getSymbolTable();
            st.addObserver(this);
            st.addObserverToExistingVariables(this);
        }
    
        public void update(Observable arg0, Object arg1)
        {
            if(arg0 instanceof Variable)
                println("Var changed: " + arg0);
            else if(arg0 instanceof SymbolTable.StObservable)
            {
                println("New var: "+arg1);
    
                // This line is vital to ensure that 
                // any new variable created will be observed. 
                ((Variable) arg1).addObserver(this);
            }
        }
    }
    
    jep-2.4.1-ext-1.1.1-gpl/doc/html/img/0000755000000000000000000000000010615400336015267 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/html/img/top.gif0000644000000000000000000000016610615400334016561 0ustar rootrootGIF89a&WWW!,&;0I8ͻVckEDc,sPՀ1۬D; ~R!mF2;jep-2.4.1-ext-1.1.1-gpl/doc/html/img/checkmark.gif0000644000000000000000000000026210615400336017706 0ustar rootrootGIF89a ƽ{{{ssskkkcccZZZRRRBBB999)))!!!!, @/`%"QT D;PT6lRA JZ%AY[ ;jep-2.4.1-ext-1.1.1-gpl/doc/html/img/new-window-icon.gif0000644000000000000000000000015710615400336021005 0ustar rootrootGIF89a EEE^^^!, 4xN+Rz'Vq^^BjwRMAXinStack, and the square root of it's value is * pushed back to the top of inStack. */ public void run(Stack inStack) throws ParseException { // check the stack checkStack(inStack); // get the parameter from the stack Object param = inStack.pop(); // check whether the argument is of the right type if (param instanceof Double) { // calculate the result double r = ((Double)param).doubleValue() / 2; // push the result on the inStack inStack.push(new Double(r)); } else { throw new ParseException("Invalid parameter type"); } } } jep-2.4.1-ext-1.1.1-gpl/doc/Library/0000755000000000000000000000000010615400350015147 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/Library/top bar.lbi0000644000000000000000000000016210615400350017165 0ustar rootroot
    jep-2.4.1-ext-1.1.1-gpl/doc/Templates/0000755000000000000000000000000010615400334015503 5ustar rootrootjep-2.4.1-ext-1.1.1-gpl/doc/Templates/maintemplate.dwt0000644000000000000000000000415610615400334020711 0ustar rootroot JEP - Java Math Expression Parser