create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / simulation / customexpression / Functions.java
1 package net.sf.openrocket.simulation.customexpression;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.SortedMap;
6 import java.util.TreeMap;
7
8 import net.sf.openrocket.l10n.Translator;
9 import net.sf.openrocket.logging.LogHelper;
10 import net.sf.openrocket.startup.Application;
11 import net.sf.openrocket.util.ArrayUtils;
12
13 import de.congrace.exp4j.CustomFunction;
14 import de.congrace.exp4j.InvalidCustomFunctionException;
15 import de.congrace.exp4j.Variable;
16
17 /*
18  * This is a singleton class which contains all the functions for custom expressions not provided by exp4j
19  */
20 public class Functions {
21         private static Functions instance = null;
22         
23         private static final LogHelper log = Application.getLogger();
24         private static final Translator trans = Application.getTranslator();
25         
26         private List<CustomFunction> allFunctions = new ArrayList<CustomFunction>();
27
28         public static Functions getInstance() {
29                 if(instance == null) {
30                         try {
31                                 instance = new Functions();
32                         } catch (InvalidCustomFunctionException e) {
33                                 log.error("Invalid custom function.");
34                         }
35                 }
36                 return instance;
37         }
38         
39         public List<CustomFunction> getAllFunction(){
40                 return allFunctions;
41         }
42         
43         // A map of available operator strings (keys) and description of function (value)
44         public static final SortedMap<String, String> AVAILABLE_OPERATORS = new TreeMap<String, String>() {{
45             put("+"             , trans.get("Operator.plus"));
46             put("-"                     , trans.get("Operator.minus"));
47             put("*"                     , trans.get("Operator.star"));
48             put("/"                     , trans.get("Operator.div"));
49             put("%"                     , trans.get("Operator.mod"));
50             put("^"                     , trans.get("Operator.pow"));
51             put("abs()"         , trans.get("Operator.abs"));
52             put("ceil()"        , trans.get("Operator.ceil"));
53             put("floor()"       , trans.get("Operator.floor"));
54             put("sqrt()"        , trans.get("Operator.sqrt"));
55             put("cbrt()"        , trans.get("Operator.cbrt"));
56             put("exp()"         , trans.get("Operator.exp"));
57             put("log()"         , trans.get("Operator.ln"));
58             put("sin()"         , trans.get("Operator.sin"));
59             put("cos()"         , trans.get("Operator.cos"));
60             put("tan()"         , trans.get("Operator.tan"));
61             put("asin()"        , trans.get("Operator.asin"));
62             put("acos()"        , trans.get("Operator.acos"));
63             put("atan()"        , trans.get("Operator.atan"));
64             put("sinh()"        , trans.get("Operator.hsin"));
65             put("cosh()"        , trans.get("Operator.hcos"));
66             put("tanh()"        , trans.get("Operator.htan"));
67             put("log10()"       , trans.get("Operator.log10"));
68             put("round()"       , trans.get("Operator.round"));
69             put("random()"      , trans.get("Operator.random"));
70             put("expm1()"       , trans.get("Operator.expm1"));
71             put("mean([:])"     , trans.get("Operator.mean"));
72             put("min([:])"      , trans.get("Operator.min"));
73             put("max([:])"      , trans.get("Operator.max"));
74             put("var([:])"      , trans.get("Operator.var"));
75             put("rms([:])"      , trans.get("Operator.rms"));
76             put("stdev([:])", trans.get("Operator.stdev"));
77             put("lclip(,)"  , trans.get("Operator.lclip"));
78             put("uclip(,)"  , trans.get("Operator.uclip"));
79             put("binf([:],,)"   , trans.get("Operator.binf"));
80             put("trapz([:])"    , trans.get("Operator.trapz"));
81             put("tnear([:],)"   , trans.get("Operator.tnear"));
82         }}; 
83         
84         
85         protected Functions() throws InvalidCustomFunctionException {
86                 
87                 CustomFunction meanFn = new CustomFunction("mean") {
88                         @Override
89                         public Variable applyFunction(List<Variable> vars) {
90                         double[] vals;
91                         try{
92                                 vals = vars.get(0).getArrayValue();
93                         } catch (Exception e) {
94                                 return new Variable("Invalid");
95                         }
96                         return new Variable("double MEAN result, ", ArrayUtils.mean(vals));
97                         }       
98                 };
99                 allFunctions.add(meanFn);
100                 
101                 CustomFunction minFn = new CustomFunction("min") {
102                         @Override
103                         public Variable applyFunction(List<Variable> vars) {
104                         double[] vals;
105                         try{
106                                 vals = vars.get(0).getArrayValue();
107                         } catch (Exception e) {
108                                 return new Variable("Invalid");
109                         }
110                         return new Variable("double MIN result, ", ArrayUtils.min(vals));
111                         }
112                 };
113                 allFunctions.add(minFn);
114                 
115                 CustomFunction maxFn = new CustomFunction("max") {
116                         @Override
117                         public Variable applyFunction(List<Variable> vars) {
118                         double[] vals;
119                         try{
120                                 vals = vars.get(0).getArrayValue();
121                         } catch (Exception e) {
122                                 return new Variable("Invalid");
123                         }
124                         return new Variable("double MAX result, ", ArrayUtils.max(vals));
125                         }
126                 };
127                 allFunctions.add(maxFn);
128         
129                 CustomFunction varFn = new CustomFunction("var") {
130                         @Override
131                         public Variable applyFunction(List<Variable> vars) {
132                         double[] vals;
133                         try{
134                                 vals = vars.get(0).getArrayValue();
135                         } catch (Exception e) {
136                                 return new Variable("Invalid");
137                         }
138                         return new Variable("double VAR result, ", ArrayUtils.variance(vals));
139                         }
140                 };
141                 allFunctions.add(varFn);
142                 
143                 CustomFunction stdevFn = new CustomFunction("stdev") {
144                         @Override
145                         public Variable applyFunction(List<Variable> vars) {
146                         double[] vals;
147                         try{
148                                 vals = vars.get(0).getArrayValue();
149                         } catch (Exception e) {
150                                 return new Variable("Invalid");
151                         }
152                         return new Variable("double STDEV result, ", ArrayUtils.stdev(vals));
153                         }
154                 };
155                 allFunctions.add(stdevFn);
156                 
157                 CustomFunction rmsFn = new CustomFunction("rms") {
158                         @Override
159                         public Variable applyFunction(List<Variable> vars) {
160                         double[] vals;
161                         try{
162                                 vals = vars.get(0).getArrayValue();
163                         } catch (Exception e) {
164                                 return new Variable("Invalid");
165                         }
166                         return new Variable("double RMS result, ", ArrayUtils.rms(vals));
167                         }
168                 };
169                 allFunctions.add(rmsFn);
170                 
171                 CustomFunction lclipFn = new CustomFunction("lclip",2) {
172                         @Override
173                         public Variable applyFunction(List<Variable> vars) {
174                         double val, clip;
175                         try{
176                                 val = vars.get(0).getDoubleValue();
177                                 clip = vars.get(1).getDoubleValue();
178                         } catch (Exception e) {
179                                 return new Variable("Invalid");
180                         }
181                         if (val < clip){
182                                 val = clip;
183                         }
184                         return new Variable("double LCLIP result, ", val);
185                         }
186                 };
187                 allFunctions.add(lclipFn);
188                 
189                 CustomFunction uclipFn = new CustomFunction("uclip",2) {
190                         @Override
191                         public Variable applyFunction(List<Variable> vars) {
192                                 double val, clip;
193                         try{
194                                 val = vars.get(0).getDoubleValue();
195                                 clip = vars.get(1).getDoubleValue();
196                         } catch (Exception e) {
197                                 return new Variable("Invalid");
198                         }
199                         if (val > clip){
200                                 val = clip;
201                         }
202                         return new Variable("double UCLIP result, ", val);
203                         }
204                 };
205                 allFunctions.add(uclipFn);
206                 
207                 CustomFunction binfFn = new CustomFunction("binf", 3) {
208                         @Override
209                         public Variable applyFunction(List<Variable> vars) {
210                                 double[] range;
211                                 double min, max;
212                                 try{
213                                         range = vars.get(0).getArrayValue();
214                                         min = vars.get(1).getDoubleValue();
215                                         max = vars.get(2).getDoubleValue();
216                                 } catch (Exception e) {
217                                         return new Variable("Invalid");
218                                 }
219                                 
220                                 int ins = 0;
221                                 for (double x: range){
222                                         if (x < max && x > min){
223                                                 ins++;
224                                         }
225                                 }
226                                 return new Variable("double BINF result", (double) ins/ (double) range.length);
227                         }
228                 };
229                 allFunctions.add(binfFn);
230                 
231                 CustomFunction rombintFn = new CustomFunction("trapz") {
232                         @Override
233                         public Variable applyFunction(List<Variable> vars) {
234                                 double[] range;
235                                 double dt = 0;
236                                 try{
237                                         range = vars.get(0).getArrayValue();
238                                         dt = vars.get(0).getStep();
239                                 } catch (Exception e) {
240                                         return new Variable("Invalid");
241                                 }
242                                 
243                                 return new Variable("double TRAPZ result", ArrayUtils.trapz(range, dt) );
244                         }
245                 };
246                 allFunctions.add(rombintFn);
247                 
248                 CustomFunction tnearFn = new CustomFunction("tnear", 2) {
249                         @Override
250                         public Variable applyFunction(List<Variable> vars) {
251                                 double[] range;
252                                 double dt = 0;
253                                 double start = 0;
254                                 double near = 0;
255                                 try{
256                                         range = vars.get(0).getArrayValue();
257                                         dt = vars.get(0).getStep();
258                                         start = vars.get(0).getStart();
259                                         near = vars.get(1).getDoubleValue();
260                                 } catch (Exception e) {
261                                         return new Variable("Invalid");
262                                 }
263                                 
264                                 return new Variable("double TNEAR result", ArrayUtils.tnear(range, near, start, dt) );
265                         } 
266                 };
267                 allFunctions.add(tnearFn);
268         }
269 }