001: /*************************************************************************
002: * *
003: * 1) This source code file, in unmodified form, and compiled classes *
004: * derived from it can be used and distributed without restriction, *
005: * including for commercial use. (Attribution is not required *
006: * but is appreciated.) *
007: * *
008: * 2) Modified versions of this file can be made and distributed *
009: * provided: the modified versions are put into a Java package *
010: * different from the original package, edu.hws; modified *
011: * versions are distributed under the same terms as the original; *
012: * and the modifications are documented in comments. (Modification *
013: * here does not include simply making subclasses that belong to *
014: * a package other than edu.hws, which can be done without any *
015: * restriction.) *
016: * *
017: * David J. Eck *
018: * Department of Mathematics and Computer Science *
019: * Hobart and William Smith Colleges *
020: * Geneva, New York 14456, USA *
021: * Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
022: * *
023: *************************************************************************/package edu.hws.jcm.data;
024:
025: /**
026: * An object belonging to this class is a function of one or more variables.
027: * It is defined by an expression, e, and a list of variables, which presumably
028: * can occur in e. The value of the function at arguments x1,x2,... is obtained by
029: * assigning the x's as the values of the variables and then evaluating
030: * the expression e.
031: *
032: * <p>Note: When the function is evaluated, the values of the variables that act
033: * as its parameters are saved and the variables are set to the values of the actual parameters
034: * provided for the function. After the evaluation, the saved values are restored.
035: * Usually, this is OK, but if setting the value of the variable has a side effect
036: * (such as changing the position of a VariableSlider), it could be a problem.
037: * So, don't use the variables associated with VariableSliders or VariableInputs
038: * in SimpleFunctions.
039: *
040: * <p>Note: A SimpleFunction is not a MathObject and does not have a name.
041: * It cannot be added to a Parser. If you want to do somethign like that,
042: * use an ExpressionFunction (defined in package edu.hws.jcm.functions).
043: */
044: public class SimpleFunction implements Function {
045:
046: private Expression e; // The expression that defines the function.
047: private Variable[] v; // The variables, presumably used in the expression,
048: // which acts as the parameter of the function.
049: private String name; // The name of the function.
050: private double[] save; // For saving values of variables when the function
051:
052: // is evaluated.
053: /**
054: * Create the function of one variable such that the value
055: * of the function at x is obtained by temporarily assigning x as the
056: * value of the variable v and then evaluating e. e and v
057: * should be non-null (or errors will result when the function
058: * is used. Note that evaluating the function will temporarily
059: * change the value of the variable.
060: */
061: public SimpleFunction(Expression e, Variable v) {
062: this (e, new Variable[] { v });
063: }
064:
065: /**
066: * Create a function. The arity of the function is
067: * the length of the array v. The value of the function
068: * at a given list of arguments is obtained by temporarily
069: * assigning the arguement values to the variables, and then
070: * returning the value of the expression. e and v should
071: * be non-null. Note that evaluating the function will
072: * temporarily change the values of the variables.
073: */
074: public SimpleFunction(Expression e, Variable[] v) {
075: this .e = e;
076: this .v = v;
077: save = new double[v.length];
078: }
079:
080: /**
081: * Return the number of arguments of this function.
082: */
083: public int getArity() {
084: return v.length;
085: }
086:
087: /**
088: * Find the value of the function at the argument values
089: * argument[0], argument[1].... (If not enough arguments are supplied,
090: * an ArrayIndexOutOfBoundsException will be thrown. Extra
091: * arguments are ignored.)
092: */
093: public double getVal(double[] arguments) {
094: return getValueWithCases(arguments, null);
095: }
096:
097: /**
098: * Find the value of the function at the argument values
099: * argument[0], argument[1].... Information about "cases" is stored in
100: * the Cases parameter, if it is non-null. See the Cases
101: * class for more information.
102: */
103: public double getValueWithCases(double[] arguments, Cases cases) {
104: for (int i = 0; i < v.length; i++) {
105: save[i] = v[i].getVal();
106: v[i].setVal(arguments[i]);
107: }
108: double val = e.getValueWithCases(cases);
109: for (int i = 0; i < v.length; i++)
110: v[i].setVal(save[i]);
111: return val;
112: }
113:
114: /**
115: * Return the derivative of the function with repect to
116: * argument number wrt, where arguments are numbered starting from 1.
117: */
118: public Function derivative(int wrt) {
119: if (wrt < 1 || wrt > v.length)
120: throw new IllegalArgumentException(
121: "Internal Error. Function does not have an argument number "
122: + wrt);
123: return new SimpleFunction(e.derivative(v[wrt - 1]), v);
124: }
125:
126: /**
127: * Return the derivative of the function with respect to the
128: * variable x. (Note that the derivative w.r.t one of the variables
129: * that are being used as the parameter of this function is ZERO!)
130: * To get the derivative with respect to the i-th parameter variable,
131: * call derivative(i).
132: */
133: public Function derivative(Variable x) {
134: for (int i = 0; i < v.length; i++)
135: if (x == v[i])
136: return new SimpleFunction(new Constant(0), v);
137: return new SimpleFunction(e.derivative(x), v);
138: }
139:
140: /**
141: * Return true if the definition of this function depends
142: * in some way on the variable x. (Note that the function does
143: * NOT depend on the variables that are being used as its parameters!)
144: */
145: public boolean dependsOn(Variable x) {
146: for (int i = 0; i < v.length; i++)
147: if (x == v[i])
148: return false;
149: return e.dependsOn(x);
150: }
151:
152: } // end class SimpleFunction
|