1 /*
2 
3 	 _____  __ _____________ _______  ______ ___________
4 	/     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
5    |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
6    |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
7 		 \/      |__|       \/           \/     \/
8    Copyright (C) 2004 - 2020 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 
37 using namespace std;
38 
39 /** \file
40 	\brief Implementation of the standard floating point parser.
41 */
42 
43 
44 
45 /** \brief Namespace for mathematical applications. */
46 namespace mu
47 {
48 	//---------------------------------------------------------------------------
49 	/** \brief Default value recognition callback.
50 		\param [in] a_szExpr Pointer to the expression
51 		\param [in, out] a_iPos Pointer to an index storing the current position within the expression
52 		\param [out] a_fVal Pointer where the value should be stored in case one is found.
53 		\return 1 if a value was found 0 otherwise.
54 	*/
IsVal(const char_type * a_szExpr,int * a_iPos,value_type * a_fVal)55 	int Parser::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
56 	{
57 		value_type fVal(0);
58 
59 		stringstream_type stream(a_szExpr);
60 		stream.seekg(0);        // todo:  check if this really is necessary
61 		stream.imbue(Parser::s_locale);
62 		stream >> fVal;
63 		stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
64 
65 		if (iEnd == (stringstream_type::pos_type) - 1)
66 			return 0;
67 
68 		*a_iPos += (int)iEnd;
69 		*a_fVal = fVal;
70 		return 1;
71 	}
72 
73 
74 	//---------------------------------------------------------------------------
75 	/** \brief Constructor.
76 
77 	  Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
78 	*/
Parser()79 	Parser::Parser()
80 		:ParserBase()
81 	{
82 		AddValIdent(IsVal);
83 
84 		InitCharSets();
85 		InitFun();
86 		InitConst();
87 		InitOprt();
88 	}
89 
90 	//---------------------------------------------------------------------------
91 	/** \brief Define the character sets.
92 		\sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
93 
94 	  This function is used for initializing the default character sets that define
95 	  the characters to be useable in function and variable names and operators.
96 	*/
InitCharSets()97 	void Parser::InitCharSets()
98 	{
99 		DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
100 		DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}"));
101 		DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_"));
102 	}
103 
104 	//---------------------------------------------------------------------------
105 	/** \brief Initialize the default functions. */
InitFun()106 	void Parser::InitFun()
107 	{
108 		if (mu::TypeInfo<mu::value_type>::IsInteger())
109 		{
110 			// When setting MUP_BASETYPE to an integer type
111 			// Place functions for dealing with integer values here
112 			// ...
113 			// ...
114 			// ...
115 		}
116 		else
117 		{
118 			// trigonometric functions
119 			DefineFun(_T("sin"), MathImpl<value_type>::Sin);
120 			DefineFun(_T("cos"), MathImpl<value_type>::Cos);
121 			DefineFun(_T("tan"), MathImpl<value_type>::Tan);
122 			// arcus functions
123 			DefineFun(_T("asin"), MathImpl<value_type>::ASin);
124 			DefineFun(_T("acos"), MathImpl<value_type>::ACos);
125 			DefineFun(_T("atan"), MathImpl<value_type>::ATan);
126 			DefineFun(_T("atan2"), MathImpl<value_type>::ATan2);
127 			// hyperbolic functions
128 			DefineFun(_T("sinh"), MathImpl<value_type>::Sinh);
129 			DefineFun(_T("cosh"), MathImpl<value_type>::Cosh);
130 			DefineFun(_T("tanh"), MathImpl<value_type>::Tanh);
131 			// arcus hyperbolic functions
132 			DefineFun(_T("asinh"), MathImpl<value_type>::ASinh);
133 			DefineFun(_T("acosh"), MathImpl<value_type>::ACosh);
134 			DefineFun(_T("atanh"), MathImpl<value_type>::ATanh);
135 			// Logarithm functions
136 			DefineFun(_T("log2"), MathImpl<value_type>::Log2);
137 			DefineFun(_T("log10"), MathImpl<value_type>::Log10);
138 			DefineFun(_T("log"), MathImpl<value_type>::Log);
139 			DefineFun(_T("ln"), MathImpl<value_type>::Log);
140 			// misc
141 			DefineFun(_T("exp"), MathImpl<value_type>::Exp);
142 			DefineFun(_T("sqrt"), MathImpl<value_type>::Sqrt);
143 			DefineFun(_T("sign"), MathImpl<value_type>::Sign);
144 			DefineFun(_T("rint"), MathImpl<value_type>::Rint);
145 			DefineFun(_T("abs"), MathImpl<value_type>::Abs);
146 			// Functions with variable number of arguments
147 			DefineFun(_T("sum"), MathImpl<value_type>::Sum);
148 			DefineFun(_T("avg"), MathImpl<value_type>::Avg);
149 			DefineFun(_T("min"), MathImpl<value_type>::Min);
150 			DefineFun(_T("max"), MathImpl<value_type>::Max);
151 		}
152 	}
153 
154 	//---------------------------------------------------------------------------
155 	/** \brief Initialize constants.
156 
157 	  By default the parser recognizes two constants. Pi ("pi") and the Eulerian
158 	  number ("_e").
159 	*/
InitConst()160 	void Parser::InitConst()
161 	{
162 		DefineConst(_T("_pi"), MathImpl<value_type>::CONST_PI);
163 		DefineConst(_T("_e"), MathImpl<value_type>::CONST_E);
164 	}
165 
166 	//---------------------------------------------------------------------------
167 	/** \brief Initialize operators.
168 
169 	  By default only the unary minus operator is added.
170 	*/
InitOprt()171 	void Parser::InitOprt()
172 	{
173 		DefineInfixOprt(_T("-"), MathImpl<value_type>::UnaryMinus);
174 		DefineInfixOprt(_T("+"), MathImpl<value_type>::UnaryPlus);
175 	}
176 
177 	//---------------------------------------------------------------------------
OnDetectVar(string_type *,int &,int &)178 	void Parser::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
179 	{
180 		// this is just sample code to illustrate modifying variable names on the fly.
181 		// I'm not sure anyone really needs such a feature...
182 		/*
183 
184 
185 		string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);
186 		string sRepl = std::string("_") + sVar + "_";
187 
188 		int nOrigVarEnd = nEnd;
189 		cout << "variable detected!\n";
190 		cout << "  Expr: " << *pExpr << "\n";
191 		cout << "  Start: " << nStart << "\n";
192 		cout << "  End: " << nEnd << "\n";
193 		cout << "  Var: \"" << sVar << "\"\n";
194 		cout << "  Repl: \"" << sRepl << "\"\n";
195 		nEnd = nStart + sRepl.length();
196 		cout << "  End: " << nEnd << "\n";
197 		pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
198 		cout << "  New expr: " << *pExpr << "\n";
199 		*/
200 	}
201 
202 	//---------------------------------------------------------------------------
203 	/** \brief Numerically differentiate with regard to a variable.
204 		\param [in] a_Var Pointer to the differentiation variable.
205 		\param [in] a_fPos Position at which the differentiation should take place.
206 		\param [in] a_fEpsilon Epsilon used for the numerical differentiation.
207 
208 		Numerical differentiation uses a 5 point operator yielding a 4th order
209 		formula. The default value for epsilon is 0.00074 which is
210 		numeric_limits<double>::epsilon() ^ (1/5).
211 	*/
Diff(value_type * a_Var,value_type a_fPos,value_type a_fEpsilon) const212 	value_type Parser::Diff(value_type* a_Var, value_type  a_fPos, value_type  a_fEpsilon) const
213 	{
214 		value_type fRes(0);
215 		value_type fBuf(*a_Var);
216 		value_type f[4] = { 0,0,0,0 };
217 		value_type fEpsilon(a_fEpsilon);
218 
219 		// Backwards compatible calculation of epsilon inc case the user doesn't provide
220 		// his own epsilon
221 		if (fEpsilon == 0)
222 			fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
223 
224 		*a_Var = a_fPos + 2 * fEpsilon;  f[0] = Eval();
225 		*a_Var = a_fPos + 1 * fEpsilon;  f[1] = Eval();
226 		*a_Var = a_fPos - 1 * fEpsilon;  f[2] = Eval();
227 		*a_Var = a_fPos - 2 * fEpsilon;  f[3] = Eval();
228 		*a_Var = fBuf; // restore variable
229 
230 		fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon);
231 		return fRes;
232 	}
233 } // namespace mu
234