8a437af240552f8cea818a6eca301663885b1fb6
[debian/openrocket] / core / src / net / sf / openrocket / util / exp4j / CustomFunction.java
1 package net.sf.openrocket.util.exp4j;
2 import java.util.Map;
3 import java.util.Stack;
4
5 import net.sf.openrocket.util.exp4j.FunctionToken.Function;
6
7 /**
8  * this classed is used to create custom functions for exp4j<br/>
9  * <br/>
10  * <b>Example</b><br/>
11  * <code><pre>{@code 
12  * CustomFunction fooFunc = new CustomFunction("foo") {
13  *              public double applyFunction(double value) {
14  *                      return value*Math.E;
15  *              }
16  * };
17  * double varX=12d;
18  * Calculable calc = new ExpressionBuilder("foo(x)").withCustomFunction(fooFunc).withVariable("x",varX).build();
19  * assertTrue(calc.calculate() == Math.E * varX);
20  * }</pre></code>
21  * 
22  * @author ruckus
23  * 
24  */
25 public abstract class CustomFunction extends CalculationToken {
26     private int argc=1;
27
28         /**
29          * create a new single value input CustomFunction with a set name
30          * 
31          * @param value
32          *            the name of the function (e.g. foo)
33          */
34         protected CustomFunction(String value) throws InvalidCustomFunctionException{
35                 super(value);
36                 for (Function f:Function.values()) {
37                         if (value.equalsIgnoreCase(f.toString())){
38                                 throw new InvalidCustomFunctionException(value + " is already reserved as a function name");
39                         }
40                 }
41         }
42
43     /**
44      * create a new single value input CustomFunction with a set name
45      * 
46      * @param value
47      *            the name of the function (e.g. foo)
48      */
49     protected CustomFunction(String value,int argumentCount) throws InvalidCustomFunctionException{
50         super(value);
51         this.argc=argumentCount;
52         for (Function f:Function.values()) {
53             if (value.equalsIgnoreCase(f.toString())){
54                 throw new InvalidCustomFunctionException(value + " is already reserved as a function name");
55             }
56         }
57     }
58
59     /**
60          * apply the function to a value
61          * 
62          * @param values
63          *            the values to which the function should be applied.
64          * @return the function value
65          */
66         public abstract double applyFunction(double[] values);
67
68     @Override
69         void mutateStackForCalculation(Stack<Double> stack, Map<String, Double> variableValues) {
70             double[] args=new double[argc];
71             for (int i=0;i<argc;i++) {
72                 args[i]=stack.pop();
73             }
74                 stack.push(this.applyFunction(args));
75         }
76
77         @Override
78         void mutateStackForInfixTranslation(Stack<Token> operatorStack, StringBuilder output) {
79                 operatorStack.push(this);
80         }
81         public int getArgumentCount() {
82             return argc;
83         }
84 }