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