package graph; import java.awt.*; import java.util.*; import java.lang.*; /* ************************************************************************** ** ** Class ParseFunction ** ************************************************************************** ** Copyright (C) 1996 Leigh Brookshaw ** ** 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., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************/ /** * This class will parse a function definition and solve it returning the * value. The function may have upto 3 independent variables in it * (x,y,z). *

* Known Bugs This class is not fool proof. If the answer is wrong * then use the parenthesis to force the order of evaluation. The most * likely place this will be needed is in the use of the power command. * The exponent is not evaluated correctly if it begins with a * unary operator. * *

List of recognised commands

* * * @version $Revision: 1.8 $, $Date: 1996/08/12 23:37:08 $ * @author Leigh Brookshaw */ public class ParseFunction extends ScanString { /* ********************** ** Constants *********************/ /* ** Specifiy the integer values associated with keywords. Every integer ** in this list is associated with keyword used in the string */ static final int GROUP = 1; static final int ENDGROUP = 2; static final int ADD = 3; static final int SUBTRACT = 4; static final int DIVIDE = 5; static final int MULTIPLY = 6; static final int LOG = 7; static final int POWER = 8; static final int PI = 9; static final int E = 10; static final int SIN = 11; static final int COS = 12; static final int TAN = 13; static final int X = 14; static final int Y = 15; static final int Z = 16; static final int ASIN = 17; static final int ACOS = 18; static final int ATAN = 19; static final int RAD = 20; static final int SQRT = 21; static final int RANDOM = 22; static final int LOG10 = 23; static final int EXP = 24; static final int REMAINDER = 25; static final int COMMA = 26; static final int ATAN2 = 27; static final int J0 = 28; static final int J1 = 29; static final int JN = 30; static final int SINH = 31; static final int COSH = 32; static final int TANH = 33; static final int ASINH = 34; static final int ACOSH = 35; static final int ATANH = 36; static final int Y0 = 37; static final int Y1 = 38; static final int YN = 39; static final int FAC = 40; static final int GAMMA = 41; static final int ERF = 42; static final int ERFC = 43; static final int NORMAL = 44; static final int POISSONC = 45; static final int POISSON = 46; static final int CHISQC = 47; static final int CHISQ = 48; static final int IGAM = 49; static final int IGAMC = 50; /* ** Physical Constants in SI units */ static final int BOLTZMAN = 101; static final int ECHARGE = 102; static final int EMASS = 103; static final int PMASS = 104; static final int GRAV = 105; static final int PLANCK = 106; static final int LIGHTSPEED = 107; static final int STEFANBOLTZ = 108; static final int AVOGADRO = 109; static final int GASCONSTANT = 110; static final int GRAVACC = 111; /* ********************* ** ** Private Variables ** *********************/ /* ** The root node after parsing the string */ private Node root; /* ** Boolean flags set when any of the independent variable are encountered */ private boolean independent_x; private boolean independent_y; private boolean independent_z; /* ** Internal values for the independent variables */ private double x; private double y; private double z; /** * Debug variable. If set true debug output is printed. */ public boolean debug; /* ************************ ** ** Constructors ** **********************/ /** * Instantiate the class */ public ParseFunction() { root = null; independent_x = false; independent_y = false; independent_z = false; debug = false; x = 0.0; y = 0.0; z = 0.0; addKeyWord(",", COMMA); addKeyWord("(", GROUP); addKeyWord(")", ENDGROUP); addKeyWord("+", ADD); addKeyWord("-", SUBTRACT); addKeyWord("/", DIVIDE); addKeyWord("*", MULTIPLY); addKeyWord("log", LOG); addKeyWord("^", POWER); addKeyWord("pi", PI); addKeyWord("e", E); addKeyWord("sin", SIN); addKeyWord("cos", COS); addKeyWord("tan", TAN); addKeyWord("x", X); addKeyWord("y", Y); addKeyWord("z", Z); addKeyWord("asin", ASIN); addKeyWord("acos", ACOS); addKeyWord("atan", ATAN); addKeyWord("rad", RAD); addKeyWord("sqrt", SQRT); addKeyWord("rand", RANDOM); addKeyWord("log10", LOG10); addKeyWord("exp", EXP); addKeyWord("rem", REMAINDER); addKeyWord("atan2", ATAN2); addKeyWord("j0", J0); addKeyWord("j1", J1); addKeyWord("jn", JN); addKeyWord("sinh", SINH); addKeyWord("cosh", COSH); addKeyWord("tanh", TANH); addKeyWord("asinh", ASINH); addKeyWord("acosh", ACOSH); addKeyWord("atanh", ATANH); addKeyWord("y0", Y0); addKeyWord("y1", Y1); addKeyWord("yn", YN); addKeyWord("fac", FAC); addKeyWord("gamma", GAMMA); addKeyWord("erf", ERF); addKeyWord("erfc", ERFC); addKeyWord("normal", NORMAL); addKeyWord("poissonc", POISSONC); addKeyWord("poisson", POISSON); addKeyWord("chisq", CHISQ); addKeyWord("chisqc", CHISQC); addKeyWord("igam", IGAM); addKeyWord("igamc", IGAMC); addKeyWord("k", BOLTZMAN); addKeyWord("ec", ECHARGE); addKeyWord("me", EMASS); addKeyWord("mp", PMASS); addKeyWord("gc", GRAV); addKeyWord("h", PLANCK); addKeyWord("c", LIGHTSPEED); addKeyWord("sigma", STEFANBOLTZ); addKeyWord("na", AVOGADRO); addKeyWord("r", GASCONSTANT); addKeyWord("g", GRAVACC); } /** * Instantiate the class and define the string to parse. * @param s The string to be parsed. */ public ParseFunction(String s) { this(); setString(s); } /* ****************** ** ** Public Methods ** *****************/ /** * Parse the string. * @param s The string to parse * @return true if it was successful, false otherwise. */ public boolean parse(String s) { setString(s); return parse(); } /** * Parse the previously set string * @return true if it was successful, false otherwise. */ public boolean parse() { root = new Node(); if( parseString(root) != EOS) return false; if(debug) { System.out.println("Before Reordering:"); root.print(5); } reOrderNodes(root); if(debug) { System.out.println("After Reordering:"); root.print(5); } return true; } /** * Return the solution of the function given the independent values * @param x indpendent x value * @param y indpendent y value * @param z indpendent z value * @return solution of the function */ public double getResult(double x, double y, double z) throws Exception { this.x = x; this.y = y; this.z = z; return evaluate(root); } /** * Return the solution of the function given the independent values * @param x indpendent x value * @param y indpendent y value * @return solution of the function */ public double getResult(double x, double y) throws Exception { this.x = x; this.y = y; return evaluate(root); } /** * Return the solution of the function given the independent values * @param x indpendent x value * @return solution of the function */ public double getResult(double x) throws Exception { this.x = x; return evaluate(root); } /** * Return the solution of the function if it has no independent values * or they have already been set using the set methods * @return solution of the function * @see ParseFunction.setX() * @see ParseFunction.setY() * @see ParseFunction.setZ() */ public double getResult() throws Exception { return evaluate(root); } /** * Return an array of solutions given an array of x values * @param n number of values to process in the input array * @param x Array containing the x values. * @return Array containing the solutions. * @exception Exception * Generic exception if the array index n<=0, or x is null. */ public double[] getResults(int n, double x[]) throws Exception { if(n <= 0) throw new Exception("Array index error"); if(x == null) throw new Exception("X Array error"); double array[] = new double[n]; for(int i=0; i= right.precedence) { Node newnode = new Node(node); newnode.right = right.left; node.replace(right); node.left = newnode; right = null; reOrderNodes(node); } } } } class Node extends Object { public static final int OP = 0; public static final int VALUE = 1; public static final int INTRINSIC = 2; public static final int NULL = 3; public static final int INDEPENDENT = 4; public static final int GROUP = 5; public static final int PARAMETER = 6; public static final int P0 = 0; public static final int P1 = 1; public static final int P2 = 2; public static final int P3 = 3; public static final int P4 = 4; public static final int P5 = 5; int type; Node left; Node right; int op; double value; int precedence; public Node() { type = NULL; left = null; right = null; op = NULL; value = 0.0; precedence = P0; } public Node(Node n) { replace(n); } public void replace(Node n ) { if(n == null) return; op = n.op; type = n.type; left = n.left; right = n.right; value = n.value; precedence = n.precedence; } public void indent(int ind) { for (int i = 0; i < ind; i++) System.out.print(" "); } public void print(int indentLevel) { char l[] = new char[1]; indent(indentLevel); System.out.println("NODE type=" + type); indent(indentLevel); System.out.println(" prec="+ precedence); indent(indentLevel); switch (type) { case Node.VALUE: System.out.println(" value=" + value); break; case Node.INDEPENDENT: System.out.println(" variable=" + op); break; default: System.out.println(" op=" + op); if(left != null) left.print(indentLevel + 5); if(right != null) right.print(indentLevel + 5); break; } } }