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
*
* - ( ) parenthesis , comma
*
- +, -, unary -, unary +
*
- *, /
*
- ^ (raise to a power)
*
- pi, e, All the constants in class SpecialFunction
*
- log
*
- sin, cos, tan
*
- asin, acos, atan
*
- sqrt
*
- rand
*
- exp
*
- remainder
*
- atan2
*
- All the functions in class SpecialFunction
*
- Independent variables x,y,z
*
- Scientific notation using "e", "E", "d", "D".
*
*
* @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;
}
}
}