Java source code of 'jhplot.FND'

/**
 *    Copyright (C)  DataMelt project. The jHPLot package by S.Chekanov and Work.ORG
 *    All rights reserved.
 *
 *    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 3 of the License, or 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, see .
 *
 *    Additional permission under GNU GPL version 3 section 7:
 *    If you have received this program as a library with written permission from the DataMelt team,
 *    you can link or combine this library with your non-GPL project to convey the resulting work.
 *    In this case, this library should be considered as released under the terms of
 *    GNU Lesser public license (see ),
 *    provided you include this license notice and a URL through which recipients can access the
 *    Corresponding Source.
 **/
package jhplot;

import jplot.LinePars;
import org.nfunk.jep.*;
import org.lsmp.djep.xjep.*;
import org.lsmp.djep.djep.*;
import javax.swing.JOptionPane;
import jhplot.gui.HelpBrowser;

/**
 * Create a function in multiple dimensions. The function name could have
 * parameters named in unique way as P0, P1, P2 ... They have to be replaced
 * with values using setPar() method for evaluation
 * 
 * @author S.Chekanov
 * 
 */

public class FND extends DrawOptions {

	private FProxy proxy;
	final int maxpoints = 200;
	private static final long serialVersionUID = 1L;

	private double[] x = null;

	private double[] y = null;

	// private double[] z = null;

	private boolean isEvaluated = false;

	private XJep jep = null;
	private Node node = null;
	private Node processed = null;
	private Node simp = null;
	// private Object value = null;
	private String[] avars = null;
	private Node diff = null;

	private String fixedVars = "";

	/**
	 * Create a function in any dimension evaluation.
	 * 
	 * The function may have many independent variables.
	 * 

*

List of commands

*
    *
  • ( ) parenthesis , comma *
  • +, -, unary -, unary + *
  • *, / *
  • ^ (raise to a power) *
  • pi, e, All the constants in class SpecialFunction *
  • log *
  • sin, cos, tan, sinh, cosh, tanh *
  • asin, acos, atan, asinh, acosh, atanh *
  • sqrt *
  • rand *
  • exp *
  • remainder *
  • atan2 *
  • Special functions and constants. Look at the book *
  • All the functions in class SpecialFunction *
  • Independent variables x *
  • Scientific notation using "e", "E", "d", "D". *
* * * @prama title Title of the function * * @param name * String representing the function * @param vars * String representing variables. Each variable should be * separated by a comma. Example "x,y,z" */ public FND(String title, String name, String vars) { this.title = title; proxy = new FProxy(3, title, name, null, new double[] { 0, 0, 0, 0, 0, 0 }, maxpoints, true); name=proxy.getName(); proxy.setVariables(vars); setTitle(title); lpp.setType(LinePars.F1D); jep = new XJep(); jep.addStandardConstants(); jep.addStandardFunctions(); jep.setAllowUndeclared(true); jep.setImplicitMul(true); jep.setAllowAssignment(true); // get all variables avars = vars.split(","); for (int i = 0; i < avars.length; i++) { jep.addVariable(avars[i].trim(), 0); } jep.addVariable("x", 0); try { node = jep.parse(name); processed = jep.preprocess(node); } catch (ParseException e) { } catch (Exception e) { ErrorMessage("Error in parsing " + name); } } /** * Build a function, setting its title to the definition. * * @param title * Title * @param name * name * @param vars * Options */ public FND(String name, String vars) { this(name, name, vars); } /** * Initialize function from proxy. * * @param f */ public FND(FProxy f) { proxy = f; String name = proxy.getName(); if (proxy.getType() != 4) { ErrorMessage("Error in parsing FND. Wrong type! " + name); return; } setTitle(proxy.getTitle()); lpp.setType(LinePars.F1D); jep = new XJep(); jep.addStandardConstants(); jep.addStandardFunctions(); jep.setAllowUndeclared(true); jep.setImplicitMul(true); jep.setAllowAssignment(true); // get all variables String vars = proxy.getVariables(); avars = vars.split(","); for (int i = 0; i < avars.length; i++) { jep.addVariable(avars[i].trim(), 0); } jep.addVariable("x", 0); try { node = jep.parse(name); processed = jep.preprocess(node); } catch (ParseException e) { } catch (Exception e) { ErrorMessage("Error in parsing " + name); } } /** * Treat the function as complex. **/ public void setComplex() { jep.addComplex(); } /** * Treat the function as complex. **/ public void simplify() { String name = proxy.getName(); try { simp = jep.simplify(processed); } catch (ParseException e) { } catch (Exception e) { ErrorMessage("Error in simplification of " + name); } } /** * differentiate the expression and simplify * * @param var * variable used for differentiation **/ public void diff(String var) { String name = proxy.getName(); 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.addStandardDiffRules(); try { // parse the string node = j.parse(name); diff = j.differentiate(node, var); simp = j.simplify(diff); } catch (ParseException e) { ErrorMessage("Error in parsing " + name); } } /** * Return all variables * * @return array array with variables **/ public String[] getVars() { return avars; } /** * Convert to string **/ public String toString() { if (simp != null) { return jep.toString(simp); } return jep.toString(node); } /** * Evaluate a function at a specific point in x * * @param vars * Values for evaluation separated by commas, x=1,y=2,z=3 * @return function value at x */ public double eval(String vars) { // get all variables String[] tmp = vars.split(","); // double[] vd = new double[tmp.length]; for (int i = 0; i < tmp.length; i++) { String[] vv = tmp[i].split("="); if (vv.length != 2) { ErrorMessage("Error in parsing list of input variablse. Did you use val=number? "); } try { double d = Double.valueOf(vv[1].trim()).doubleValue(); jep.addVariable(vv[0].trim(), d); } catch (NumberFormatException nfe) { System.out .println("NumberFormatException: " + nfe.getMessage()); } } try { Object result = jep.evaluate(node); if (result instanceof Double) { return ((Double) jep.evaluate(node)).doubleValue(); } } catch (ParseException e) { return 0; } return 0; } /** * Evaluate a function at a specific point for one single variable. * Evaluation is done between xmin and xmax * * @param indvars * Define independent variable, like 'x' Only one variable is * allowed * @param xmin * xmin value for independent varible * @param xmax * xmax value for independent varible * @param vars * define values for other variables, like 'y=1,z=3' * @return true if no errors */ public boolean eval(String indvars, double xmin, double xmax, String vars) { String name = proxy.getName(); int points = proxy.getPoints(); boolean suc = true; String[] tmp = vars.split(","); // double[] vd = new double[tmp.length]; fixedVars = vars; for (int i = 0; i < tmp.length; i++) { String[] vv = tmp[i].split("="); if (vv.length != 2) { ErrorMessage("Error in parsing list of input variablse. Did you use val=number? "); } try { double d = Double.valueOf(vv[1].trim()).doubleValue(); jep.addVariable(vv[0].trim(), d); } catch (NumberFormatException nfe) { System.out .println("NumberFormatException: " + nfe.getMessage()); suc = false; } } double min = xmin; double max = xmax; x = new double[points]; y = new double[points]; for (int i = 0; i < points; i++) { x[i] = min + i * (max - min) / (points - 1); jep.addVariable(indvars.trim(), x[i]); try { Object result = jep.evaluate(node); if (result instanceof Double) { y[i] = ((Double) jep.evaluate(node)).doubleValue(); } } catch (ParseException e) { jhplot.utils.Util.ErrorMessage("Failed to parse function " + name + " Error:" + e.toString()); suc = false; } } if (suc) isEvaluated = true; return suc; } // end 1-D evaluation /** * Evaluate a function at a specific point for one single variable. * Evaluation is done between xmin and xmax. It is assumed that there are no * any other variable involved * * @param indvars * Define independent variable, like 'x' Only one variable is * allowed * @param xmin * xmin value for independent varible * @param xmax * xmax value for independent varible * @return true if no errors */ public boolean eval(String indvars, double xmin, double xmax) { boolean suc = true; String name = proxy.getName(); int points = proxy.getPoints(); double min = xmin; double max = xmax; x = new double[points]; y = new double[points]; for (int i = 0; i < points; i++) { x[i] = min + i * (max - min) / (points - 1); jep.addVariable(indvars.trim(), x[i]); try { Object result = jep.evaluate(node); if (result instanceof Double) { y[i] = ((Double) jep.evaluate(node)).doubleValue(); } } catch (ParseException e) { jhplot.utils.Util.ErrorMessage("Failed to parse function " + name + " Error:" + e.toString()); suc = false; } } if (suc) isEvaluated = true; return suc; } // end 1-D evaluation /** * Is the function was evaluated? * */ public boolean isEvaluated() { return isEvaluated; } /** * Get value in X-axis * * @param i * index * @return value in X */ public double getX(int i) { return this.x[i]; } /** * Get value in Y-axis * * @param i * index * * @return value in Y */ public double getY(int i) { return this.y[i]; } /** * Sets a name of the function, i.e. what will be used for evaluation * * @param name * Name */ public void setName(String name) { proxy.setName(name); } /** * Get the proxy of this function used for serialization and non-graphical * representations. * * @param proxy * proxy of this function. */ public FProxy get() { return proxy; } /** * Get the name of the function used for evaluation * * @return Name */ public String getName() { return proxy.getName(); } /** * Get arguments of the function (independent variables). * * @return arguments */ public String getVarString() { return proxy.getVariables(); } /** * Show online documentation. */ public void doc() { String a = this.getClass().getName(); a = a.replace(".", "/") + ".html"; new HelpBrowser(HelpBrowser.JHPLOT_HTTP + a); } /** * Set Min value in X * * @param min * Minimum value */ public void setMin(double min) { proxy.setLimit(0, min); } /** * Get the minimum value in X * * @return min Minimum value */ public double getMin() { double[] d = proxy.getLimits(); return d[0]; } /** * Set the maximum value in X * * @param max * Maximal value */ public void setMax(double max) { proxy.setLimit(1, max); } /** * Get the maximum value in X * * @return Maximal value */ public double getMax() { double[] d = proxy.getLimits(); return d[1]; } /** * Sets the number points between Min and Max for evaluation * * @param bins * Number of points */ public void setPoints(int bins) { proxy.setPoints(bins); } /** * Get the number of points * * @return Number of points */ public int getPoints() { return proxy.getPoints(); } /** * String with fixed variables * * @return String with fixed variables **/ public String getFixedVars() { return fixedVars; } /** * * Generate error message * * @param a * Message * */ private void ErrorMessage(String a) { JOptionPane dialogError = new JOptionPane(); JOptionPane.showMessageDialog(dialogError, a, "Error", JOptionPane.ERROR_MESSAGE); } }