Add HeFFTe based FFT backend
[alexxy/gromacs.git] / src / external / muparser / src / muParser.cpp
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         */
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         */
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         */
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. */
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         */
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         */
171         void Parser::InitOprt()
172         {
173                 DefineInfixOprt(_T("-"), MathImpl<value_type>::UnaryMinus);
174                 DefineInfixOprt(_T("+"), MathImpl<value_type>::UnaryPlus);
175         }
176
177         //---------------------------------------------------------------------------
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         */
212         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