create changelog entry
[debian/openrocket] / core / src / de / congrace / exp4j / FunctionToken.java
1 /*
2 Copyright 2011 frank asseg
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16  */
17 package de.congrace.exp4j;
18
19 import java.util.Stack;
20
21 /**
22  * A {@link Token} for functions
23  * 
24  * @author fas@congrace.de
25  * 
26  */
27 class FunctionToken extends CalculationToken {
28         /**
29          * the functionNames that can be used in an expression
30          * 
31          * @author ruckus
32          * 
33          */
34         enum Function {
35                 ABS, ACOS, ASIN, ATAN, CBRT, CEIL, COS, COSH, EXP, EXPM1, FLOOR, ROUND, RANDOM, LOG, SIN, SINH, SQRT, TAN, TANH, LOG10
36         }
37
38         private Function function;
39
40         /**
41          * construct a new {@link FunctionToken}
42          * 
43          * @param value
44          *            the name of the function
45          * @throws UnknownFunctionException
46          *             if an unknown function name is encountered
47          */
48         FunctionToken(String value) throws UnknownFunctionException {
49                 super(value);
50                 try {
51                         function = Function.valueOf(value.toUpperCase());
52                 } catch (IllegalArgumentException e) {
53                         throw new UnknownFunctionException(value);
54                 }
55                 if (function == null) {
56                         throw new UnknownFunctionException(value);
57                 }
58         }
59
60         /**
61          * apply a function to a variable
62          * 
63          * @param x
64          *            the value the function should be applied to
65          * @return the result of the function
66          */
67         public Variable applyFunction(Variable var) {
68                 
69                 // The names here are strictly unused, but are useful for debugging
70                 String name = function.name() + " result (#"+var.hashCode()+"), ";
71                 
72                 switch (var.getPrimary()) {
73                         case DOUBLE:
74                                 name = "double "+name;
75                                 double x = var.getDoubleValue();
76                                 return new Variable(name, applyFunction(x) );   
77                         
78                         case ARRAY:
79                                 name = "array "+name;
80                                 double[] input = var.getArrayValue();
81                                 double[] result = new double[input.length];
82                                 for (int i = 0; i < input.length; i++){
83                                         result[i] = applyFunction(input[i]);
84                                 }
85                                 return new Variable(name, result);
86                         
87                         default:
88                                 return new Variable("Invalid");
89                 }
90         }
91         
92         /*
93          * The actual function application on a double
94          */
95         private double applyFunction(double x){
96                 switch (function) {
97                 case ABS:
98                         return Math.abs(x);
99                 case ACOS:
100                         return Math.acos(x);
101                 case ASIN:
102                         return Math.asin(x);
103                 case ATAN:
104                         return Math.atan(x);
105                 case CBRT:
106                         return Math.cbrt(x);
107                 case CEIL:
108                         return Math.ceil(x);
109                 case COS:
110                         return Math.cos(x);
111                 case COSH:
112                         return Math.cosh(x);
113                 case EXP:
114                         return Math.exp(x);
115                 case EXPM1:
116                         return Math.expm1(x);
117                 case FLOOR:
118                         return Math.floor(x);
119                 case ROUND:
120                         return Math.round(x);
121                 case RANDOM:
122                         return Math.random()*x;
123                 case LOG:
124                         return Math.log(x);
125                 case LOG10:
126                         return Math.log10(x);
127                 case SIN:
128                         return Math.sin(x);
129                 case SINH:
130                         return Math.sinh(x);
131                 case SQRT:
132                         return Math.sqrt(x);
133                 case TAN:
134                         return Math.tan(x);
135                 case TANH:
136                         return Math.tanh(x);
137                 default:
138                         return Double.NaN; // should not happen ;)
139                 }
140         }
141
142         /**
143          * 
144          * get the {@link Function}
145          * 
146          * @return the correspoding {@link Function}
147          */
148         Function getFunction() {
149                 return function;
150         }
151
152         @Override
153         void mutateStackForCalculation(Stack<Variable> stack, VariableSet variableValues) {
154                 stack.push(this.applyFunction(stack.pop()));
155         }
156
157         @Override
158         void mutateStackForInfixTranslation(Stack<Token> operatorStack, StringBuilder output) {
159                 operatorStack.push(this);
160         }
161 }