muParser API -  1.35
muParser.cpp
Go to the documentation of this file.
1 /*
2 
3  _____ __ _____________ _______ ______ ___________
4  / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5  | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6  |__|_| /____/| __(____ /__| /____ >\___ >__|
7  \/ |__| \/ \/ \/
8  Copyright (C) 2004 - 2022 Ingo Berg
9 
10  Redistribution and use in source and binary forms, with or without modification, are permitted
11  provided that the following conditions are met:
12 
13  * Redistributions of source code must retain the above copyright notice, this list of
14  conditions and the following disclaimer.
15  * Redistributions in binary form must reproduce the above copyright notice, this list of
16  conditions and the following disclaimer in the documentation and/or other materials provided
17  with the distribution.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include "muParser.h"
30 #include "muParserTemplateMagic.h"
31 
32 //--- Standard includes ------------------------------------------------------------------------
33 #include <cmath>
34 #include <algorithm>
35 #include <numeric>
36 #include <cstdlib>
37 
38 
39 using namespace std;
40 
41 /** \file
42  \brief Implementation of the standard floating point parser.
43 */
44 
45 
46 
47 /** \brief Namespace for mathematical applications. */
48 namespace mu
49 {
50  //---------------------------------------------------------------------------
51  /** \brief Default value recognition callback.
52  \param [in] a_szExpr Pointer to the expression
53  \param [in, out] a_iPos Pointer to an index storing the current position within the expression
54  \param [out] a_fVal Pointer where the value should be stored in case one is found.
55  \return 1 if a value was found 0 otherwise.
56  */
57  int Parser::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
58  {
59  // There is an issue with libc++ where it creates an error if a double value is followed by a character which
60  // is the case when using postfix operators.
61  //
62  // http://cplusplus.github.io/LWG/lwg-defects.html#2381
63  //
64  // This happens only with libc++, not with libstdc++ (Gnu C++ standard library)
65  // It seems that Macs are using libc++. This is causing #123. The fix below will fix #123
66  // but is will break localization support and cause #136.
67 
68  // I'm disabling this fix. For systems using libc++ you must put a space between floating point numbers and postfix operators.
69 #if defined(__APPLE__) && defined(NEVERTRUE)
70  try
71  {
72  std::size_t charsProcessed;
73  value_type fVal = static_cast<value_type>(std::stod(string_type(a_szExpr), &charsProcessed));
74  if (charsProcessed == 0)
75  return 0;
76 
77  *a_iPos += (int)charsProcessed;
78  *a_fVal = fVal;
79  return 1;
80  }
81  catch (...)
82  {
83  return 0;
84  }
85 #else
86  value_type fVal(0);
87 
88  stringstream_type stream(a_szExpr);
89  stream.imbue(Parser::s_locale);
90  stream >> fVal;
91  stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
92 
93  if (iEnd == (stringstream_type::pos_type) - 1)
94  return 0;
95 
96  *a_iPos += (int)iEnd;
97  *a_fVal = fVal;
98  return 1;
99 #endif
100  }
101 
102 
103  //---------------------------------------------------------------------------
104  /** \brief Constructor.
105 
106  Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
107  */
108  Parser::Parser()
109  :ParserBase()
110  {
112 
113  InitCharSets();
114  InitFun();
115  InitConst();
116  InitOprt();
117  }
118 
119  //---------------------------------------------------------------------------
120  /** \brief Define the character sets.
121  \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
122 
123  This function is used for initializing the default character sets that define
124  the characters to be useable in function and variable names and operators.
125  */
127  {
128  DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
129  DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}"));
130  DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_"));
131  }
132 
133  //---------------------------------------------------------------------------
134  /** \brief Initialize the default functions. */
136  {
138  {
139  // When setting MUP_BASETYPE to an integer type
140  // Place functions for dealing with integer values here
141  // ...
142  // ...
143  // ...
144  }
145  else
146  {
147  // trigonometric functions
151  // arcus functions
156  // hyperbolic functions
160  // arcus hyperbolic functions
164  // Logarithm functions
169  // misc
175  // Functions with variable number of arguments
180  // Random number
181  DefineFun(_T("rnd"), MathImpl<value_type>::Rnd, false);
182  }
183  }
184 
185  //---------------------------------------------------------------------------
186  /** \brief Initialize constants.
187 
188  By default the parser recognizes two constants. Pi ("pi") and the Eulerian
189  number ("_e").
190  */
192  {
195  }
196 
197  //---------------------------------------------------------------------------
198  /** \brief Initialize operators.
199 
200  By default only the unary minus operator is added.
201  */
203  {
206  }
207 
208  //---------------------------------------------------------------------------
209  void Parser::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
210  {
211  // this is just sample code to illustrate modifying variable names on the fly.
212  // I'm not sure anyone really needs such a feature...
213  /*
214 
215 
216  string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
217  string sRepl = std::string("_") + sVar + "_";
218 
219  int nOrigVarEnd = nEnd;
220  cout << "variable detected!\n";
221  cout << " Expr: " << *pExpr << "\n";
222  cout << " Start: " << nStart << "\n";
223  cout << " End: " << nEnd << "\n";
224  cout << " Var: \"" << sVar << "\"\n";
225  cout << " Repl: \"" << sRepl << "\"\n";
226  nEnd = nStart + sRepl.length();
227  cout << " End: " << nEnd << "\n";
228  pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
229  cout << " New expr: " << *pExpr << "\n";
230  */
231  }
232 
233  //---------------------------------------------------------------------------
234  /** \brief Numerically differentiate with regard to a variable.
235  \param [in] a_Var Pointer to the differentiation variable.
236  \param [in] a_fPos Position at which the differentiation should take place.
237  \param [in] a_fEpsilon Epsilon used for the numerical differentiation.
238 
239  Numerical differentiation uses a 5 point operator yielding a 4th order
240  formula. The default value for epsilon is 0.00074 which is
241  numeric_limits<double>::epsilon() ^ (1/5).
242  */
243  value_type Parser::Diff(value_type* a_Var, value_type a_fPos, value_type a_fEpsilon) const
244  {
245  value_type fRes(0);
246  value_type fBuf(*a_Var);
247  value_type f[4] = { 0,0,0,0 };
248  value_type fEpsilon(a_fEpsilon);
249 
250  // Backwards compatible calculation of epsilon inc case the user doesn't provide
251  // his own epsilon
252  if (fEpsilon == 0)
253  fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
254 
255  *a_Var = a_fPos + 2 * fEpsilon; f[0] = Eval();
256  *a_Var = a_fPos + 1 * fEpsilon; f[1] = Eval();
257  *a_Var = a_fPos - 1 * fEpsilon; f[2] = Eval();
258  *a_Var = a_fPos - 2 * fEpsilon; f[3] = Eval();
259  *a_Var = fBuf; // restore variable
260 
261  fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon);
262  return fRes;
263  }
264 } // namespace mu
void DefineInfixOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of infix operators.
#define _T(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:69
void DefineNameChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of functions, variables, constants.
void InitConst() override
Initialize constants.
Definition: muParser.cpp:191
void AddValIdent(identfun_type a_pCallback)
Add a value parsing function.
STL namespace.
Definition of the standard floating point parser.
A class singling out integer types at compile time using template meta programming.
value_type Eval() const
Calculate the result.
std::basic_stringstream< char_type, std::char_traits< char_type >, std::allocator< char_type > > stringstream_type
Typedef for easily using stringstream that respect the parser stringtype.
Definition: muParserDef.h:311
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true)
Add a user defined operator.
void DefineOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of binary operators and postfix operators...
static int IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
Default value recognition callback.
Definition: muParser.cpp:57
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt=true)
Define a parser function without arguments.
Definition: muParserBase.h:139
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:296
void InitCharSets() override
Define the character sets.
Definition: muParser.cpp:126
A template class for providing wrappers for essential math functions.
Namespace for mathematical applications.
Definition: muParser.cpp:48
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:308
void DefineConst(const string_type &a_sName, value_type a_fVal)
Add a user defined constant.
value_type Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon=0) const
Numerically differentiate with regard to a variable.
Definition: muParser.cpp:243
void InitFun() override
Initialize the default functions.
Definition: muParser.cpp:135
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Definition: muParserDef.h:302
void InitOprt() override
Initialize operators.
Definition: muParser.cpp:202
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:68