OpcUaCanOpen
CANopen OPC-UA server
muParser.cpp
Go to the documentation of this file.
1 /*
2  __________
3  _____ __ __\______ \_____ _______ ______ ____ _______
4  / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5  | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6  |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7  \/ \/ \/ \/
8 
9  Copyright (C) 2013 Ingo Berg
10 
11  Permission is hereby granted, free of charge, to any person obtaining a copy of this
12  software and associated documentation files (the "Software"), to deal in the Software
13  without restriction, including without limitation the rights to use, copy, modify,
14  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
15  permit persons to whom the Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included in all copies or
18  substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
21  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
23  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26 #include "muParser.h"
27 #include "muParserTemplateMagic.h"
28 
29 //--- Standard includes ------------------------------------------------------------------------
30 #include <cmath>
31 #include <algorithm>
32 #include <numeric>
33 
35 #define PARSER_CONST_PI 3.141592653589793238462643
36 
38 #define PARSER_CONST_E 2.718281828459045235360287
39 
40 using namespace std;
41 
49 namespace mu
50 {
51 
52 
53  //---------------------------------------------------------------------------
54  // Trigonometric function
55  value_type Parser::Sin(value_type v) { return MathImpl<value_type>::Sin(v); }
56  value_type Parser::Cos(value_type v) { return MathImpl<value_type>::Cos(v); }
57  value_type Parser::Tan(value_type v) { return MathImpl<value_type>::Tan(v); }
58  value_type Parser::ASin(value_type v) { return MathImpl<value_type>::ASin(v); }
59  value_type Parser::ACos(value_type v) { return MathImpl<value_type>::ACos(v); }
60  value_type Parser::ATan(value_type v) { return MathImpl<value_type>::ATan(v); }
61  value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }
62  value_type Parser::Sinh(value_type v) { return MathImpl<value_type>::Sinh(v); }
63  value_type Parser::Cosh(value_type v) { return MathImpl<value_type>::Cosh(v); }
64  value_type Parser::Tanh(value_type v) { return MathImpl<value_type>::Tanh(v); }
65  value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }
66  value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }
67  value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }
68 
69  //---------------------------------------------------------------------------
70  // Logarithm functions
71 
72  // Logarithm base 2
73  value_type Parser::Log2(value_type v)
74  {
75  #ifdef MUP_MATH_EXCEPTIONS
76  if (v<=0)
77  throw ParserError(ecDOMAIN_ERROR, _T("Log2"));
78  #endif
79 
80  return MathImpl<value_type>::Log2(v);
81  }
82 
83  // Logarithm base 10
84  value_type Parser::Log10(value_type v)
85  {
86  #ifdef MUP_MATH_EXCEPTIONS
87  if (v<=0)
88  throw ParserError(ecDOMAIN_ERROR, _T("Log10"));
89  #endif
90 
91  return MathImpl<value_type>::Log10(v);
92  }
93 
94 // Logarithm base e (natural logarithm)
95  value_type Parser::Ln(value_type v)
96  {
97  #ifdef MUP_MATH_EXCEPTIONS
98  if (v<=0)
99  throw ParserError(ecDOMAIN_ERROR, _T("Ln"));
100  #endif
101 
102  return MathImpl<value_type>::Log(v);
103  }
104 
105  //---------------------------------------------------------------------------
106  // misc
107  value_type Parser::Exp(value_type v) { return MathImpl<value_type>::Exp(v); }
108  value_type Parser::Abs(value_type v) { return MathImpl<value_type>::Abs(v); }
109  value_type Parser::Sqrt(value_type v)
110  {
111  #ifdef MUP_MATH_EXCEPTIONS
112  if (v<0)
113  throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));
114  #endif
115 
116  return MathImpl<value_type>::Sqrt(v);
117  }
118  value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }
119  value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }
120 
121  //---------------------------------------------------------------------------
126  value_type Parser::UnaryMinus(value_type v)
127  {
128  return -v;
129  }
130 
131  //---------------------------------------------------------------------------
136  value_type Parser::UnaryPlus(value_type v)
137  {
138  return v;
139  }
140 
141  //---------------------------------------------------------------------------
146  value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)
147  {
148  if (!a_iArgc)
149  throw exception_type(_T("too few arguments for function sum."));
150 
151  value_type fRes=0;
152  for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
153  return fRes;
154  }
155 
156  //---------------------------------------------------------------------------
161  value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)
162  {
163  if (!a_iArgc)
164  throw exception_type(_T("too few arguments for function sum."));
165 
166  value_type fRes=0;
167  for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
168  return fRes/(value_type)a_iArgc;
169  }
170 
171 
172  //---------------------------------------------------------------------------
177  value_type Parser::Min(const value_type *a_afArg, int a_iArgc)
178  {
179  if (!a_iArgc)
180  throw exception_type(_T("too few arguments for function min."));
181 
182  value_type fRes=a_afArg[0];
183  for (int i=0; i<a_iArgc; ++i)
184  fRes = std::min(fRes, a_afArg[i]);
185 
186  return fRes;
187  }
188 
189 
190  //---------------------------------------------------------------------------
195  value_type Parser::Max(const value_type *a_afArg, int a_iArgc)
196  {
197  if (!a_iArgc)
198  throw exception_type(_T("too few arguments for function min."));
199 
200  value_type fRes=a_afArg[0];
201  for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
202 
203  return fRes;
204  }
205 
206 
207  //---------------------------------------------------------------------------
214  int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)
215  {
216  value_type fVal(0);
217 
218  stringstream_type stream(a_szExpr);
219  stream.seekg(0); // todo: check if this really is necessary
220  stream.imbue(Parser::s_locale);
221  stream >> fVal;
222  stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
223 
224  if (iEnd==(stringstream_type::pos_type)-1)
225  return 0;
226 
227  *a_iPos += (int)iEnd;
228  *a_fVal = fVal;
229  return 1;
230  }
231 
232 
233  //---------------------------------------------------------------------------
238  Parser::Parser()
239  :ParserBase()
240  {
242 
243  InitCharSets();
244  InitFun();
245  InitConst();
246  InitOprt();
247  }
248 
249  //---------------------------------------------------------------------------
257  {
258  DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$.") );
259  DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );
260  DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );
261  }
262 
263  //---------------------------------------------------------------------------
266  {
268  {
269  // When setting MUP_BASETYPE to an integer type
270  // Place functions for dealing with integer values here
271  // ...
272  // ...
273  // ...
274  }
275  else
276  {
277  // trigonometric functions
278  DefineFun(_T("sin"), Sin);
279  DefineFun(_T("cos"), Cos);
280  DefineFun(_T("tan"), Tan);
281  // arcus functions
282  DefineFun(_T("asin"), ASin);
283  DefineFun(_T("acos"), ACos);
284  DefineFun(_T("atan"), ATan);
285  DefineFun(_T("atan2"), ATan2);
286  // hyperbolic functions
287  DefineFun(_T("sinh"), Sinh);
288  DefineFun(_T("cosh"), Cosh);
289  DefineFun(_T("tanh"), Tanh);
290  // arcus hyperbolic functions
291  DefineFun(_T("asinh"), ASinh);
292  DefineFun(_T("acosh"), ACosh);
293  DefineFun(_T("atanh"), ATanh);
294  // Logarithm functions
295  DefineFun(_T("log2"), Log2);
296  DefineFun(_T("log10"), Log10);
297  DefineFun(_T("log"), Ln);
298  DefineFun(_T("ln"), Ln);
299  // misc
300  DefineFun(_T("exp"), Exp);
301  DefineFun(_T("sqrt"), Sqrt);
302  DefineFun(_T("sign"), Sign);
303  DefineFun(_T("rint"), Rint);
304  DefineFun(_T("abs"), Abs);
305  // Functions with variable number of arguments
306  DefineFun(_T("sum"), Sum);
307  DefineFun(_T("avg"), Avg);
308  DefineFun(_T("min"), Min);
309  DefineFun(_T("max"), Max);
310  }
311  }
312 
313  //---------------------------------------------------------------------------
320  {
323  }
324 
325  //---------------------------------------------------------------------------
331  {
334  }
335 
336  //---------------------------------------------------------------------------
337  void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
338  {
339  // this is just sample code to illustrate modifying variable names on the fly.
340  // I'm not sure anyone really needs such a feature...
341  /*
342 
343 
344  string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
345  string sRepl = std::string("_") + sVar + "_";
346 
347  int nOrigVarEnd = nEnd;
348  cout << "variable detected!\n";
349  cout << " Expr: " << *pExpr << "\n";
350  cout << " Start: " << nStart << "\n";
351  cout << " End: " << nEnd << "\n";
352  cout << " Var: \"" << sVar << "\"\n";
353  cout << " Repl: \"" << sRepl << "\"\n";
354  nEnd = nStart + sRepl.length();
355  cout << " End: " << nEnd << "\n";
356  pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
357  cout << " New expr: " << *pExpr << "\n";
358  */
359  }
360 
361  //---------------------------------------------------------------------------
375  value_type a_fPos,
376  value_type a_fEpsilon) const
377  {
378  value_type fRes(0),
379  fBuf(*a_Var),
380  f[4] = {0,0,0,0},
381  fEpsilon(a_fEpsilon);
382 
383  // Backwards compatible calculation of epsilon inc case the user doesn't provide
384  // his own epsilon
385  if (fEpsilon==0)
386  fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
387 
388  *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval();
389  *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval();
390  *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval();
391  *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval();
392  *a_Var = fBuf; // restore variable
393 
394  fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);
395  return fRes;
396  }
397 } // namespace mu