Add HeFFTe based FFT backend
[alexxy/gromacs.git] / src / external / muparser / muParserInt.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 "muParserInt.h"
30
31 #include <cmath>
32 #include <algorithm>
33 #include <numeric>
34
35 using namespace std;
36
37 /** \file
38         \brief Implementation of a parser using integer value.
39 */
40
41 /** \brief Namespace for mathematical applications. */
42 namespace mu
43 {
44         value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }
45         value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; }
46         value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); }
47         value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
48         value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
49         value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
50         value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
51         value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
52         value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
53         value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
54         value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
55         value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
56         value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
57         value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
58         value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
59         value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
60         value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
61         value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
62         value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
63         value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
64         value_type ParserInt::Not(value_type v) { return !Round(v); }
65
66         value_type ParserInt::Pow(value_type v1, value_type v2)
67         {
68                 return std::pow((double)Round(v1), (double)Round(v2));
69         }
70
71
72         value_type ParserInt::UnaryMinus(value_type v)
73         {
74                 return -Round(v);
75         }
76
77
78         value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
79         {
80                 if (!a_iArgc)
81                         throw ParserError(_T("too few arguments for function sum."));
82
83                 value_type fRes = 0;
84                 for (int i = 0; i < a_iArgc; ++i)
85                         fRes += a_afArg[i];
86
87                 return fRes;
88         }
89
90
91         value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
92         {
93                 if (!a_iArgc)
94                         throw ParserError(_T("too few arguments for function min."));
95
96                 value_type fRes = a_afArg[0];
97                 for (int i = 0; i < a_iArgc; ++i)
98                         fRes = std::min(fRes, a_afArg[i]);
99
100                 return fRes;
101         }
102
103
104         value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
105         {
106                 if (!a_iArgc)
107                         throw ParserError(_T("too few arguments for function min."));
108
109                 value_type fRes = a_afArg[0];
110                 for (int i = 0; i < a_iArgc; ++i)
111                         fRes = std::max(fRes, a_afArg[i]);
112
113                 return fRes;
114         }
115
116
117         int ParserInt::IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
118         {
119                 string_type buf(a_szExpr);
120                 std::size_t pos = buf.find_first_not_of(_T("0123456789"));
121
122                 if (pos == std::string::npos)
123                         return 0;
124
125                 stringstream_type stream(buf.substr(0, pos));
126                 int iVal(0);
127
128                 stream >> iVal;
129                 if (stream.fail())
130                         return 0;
131
132                 stringstream_type::pos_type iEnd = stream.tellg();   // Position after reading
133                 if (stream.fail())
134                         iEnd = stream.str().length();
135
136                 if (iEnd == (stringstream_type::pos_type) - 1)
137                         return 0;
138
139                 *a_iPos += (int)iEnd;
140                 *a_fVal = (value_type)iVal;
141                 return 1;
142         }
143
144
145         /** \brief Check a given position in the expression for the presence of
146                            a hex value.
147                 \param a_szExpr Pointer to the expression string
148                 \param [in/out] a_iPos Pointer to an integer value holding the current parsing
149                            position in the expression.
150                 \param [out] a_fVal Pointer to the position where the detected value shall be stored.
151
152           Hey values must be prefixed with "0x" in order to be detected properly.
153         */
154         int ParserInt::IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
155         {
156                 if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x'))
157                         return 0;
158
159                 unsigned iVal(0);
160
161                 // New code based on streams for UNICODE compliance:
162                 stringstream_type::pos_type nPos(0);
163                 stringstream_type ss(a_szExpr + 2);
164                 ss >> std::hex >> iVal;
165                 nPos = ss.tellg();
166
167                 if (nPos == (stringstream_type::pos_type)0)
168                         return 1;
169
170                 *a_iPos += (int)(2 + nPos);
171                 *a_fVal = (value_type)iVal;
172                 return 1;
173         }
174
175
176         int ParserInt::IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal)
177         {
178                 if (a_szExpr[0] != '#')
179                         return 0;
180
181                 unsigned iVal(0),
182                         iBits(sizeof(iVal) * 8),
183                         i(0);
184
185                 for (i = 0; (a_szExpr[i + 1] == '0' || a_szExpr[i + 1] == '1') && i < iBits; ++i)
186                         iVal |= (int)(a_szExpr[i + 1] == '1') << ((iBits - 1) - i);
187
188                 if (i == 0)
189                         return 0;
190
191                 if (i == iBits)
192                         throw exception_type(_T("Binary to integer conversion error (overflow)."));
193
194                 *a_fVal = (unsigned)(iVal >> (iBits - i));
195                 *a_iPos += i + 1;
196
197                 return 1;
198         }
199
200
201         /** \brief Constructor.
202
203                 Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
204         */
205         ParserInt::ParserInt()
206                 :ParserBase()
207         {
208                 AddValIdent(IsVal);    // lowest priority
209                 AddValIdent(IsBinVal);
210                 AddValIdent(IsHexVal); // highest priority
211
212                 InitCharSets();
213                 InitFun();
214                 InitOprt();
215         }
216
217
218         void ParserInt::InitConst()
219         {
220         }
221
222
223         void ParserInt::InitCharSets()
224         {
225                 DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
226                 DefineOprtChars(_T("+-*^/?<>=!%&|~'_"));
227                 DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_"));
228         }
229
230
231         /** \brief Initialize the default functions. */
232         void ParserInt::InitFun()
233         {
234                 DefineFun(_T("sign"), Sign);
235                 DefineFun(_T("abs"), Abs);
236                 DefineFun(_T("if"), Ite);
237                 DefineFun(_T("sum"), Sum);
238                 DefineFun(_T("min"), Min);
239                 DefineFun(_T("max"), Max);
240         }
241
242
243         /** \brief Initialize operators. */
244         void ParserInt::InitOprt()
245         {
246                 // disable all built in operators, not all of them useful for integer numbers
247                 // (they don't do rounding of values)
248                 EnableBuiltInOprt(false);
249
250                 // Disable all built in operators, they won't work with integer numbers
251                 // since they are designed for floating point numbers
252                 DefineInfixOprt(_T("-"), UnaryMinus);
253                 DefineInfixOprt(_T("!"), Not);
254
255                 DefineOprt(_T("&"), LogAnd, prLOGIC);
256                 DefineOprt(_T("|"), LogOr, prLOGIC);
257                 DefineOprt(_T("&&"), And, prLOGIC);
258                 DefineOprt(_T("||"), Or, prLOGIC);
259
260                 DefineOprt(_T("<"), Less, prCMP);
261                 DefineOprt(_T(">"), Greater, prCMP);
262                 DefineOprt(_T("<="), LessEq, prCMP);
263                 DefineOprt(_T(">="), GreaterEq, prCMP);
264                 DefineOprt(_T("=="), Equal, prCMP);
265                 DefineOprt(_T("!="), NotEqual, prCMP);
266
267                 DefineOprt(_T("+"), Add, prADD_SUB);
268                 DefineOprt(_T("-"), Sub, prADD_SUB);
269
270                 DefineOprt(_T("*"), Mul, prMUL_DIV);
271                 DefineOprt(_T("/"), Div, prMUL_DIV);
272                 DefineOprt(_T("%"), Mod, prMUL_DIV);
273
274                 DefineOprt(_T("^"), Pow, prPOW, oaRIGHT);
275                 DefineOprt(_T(">>"), Shr, prMUL_DIV + 1);
276                 DefineOprt(_T("<<"), Shl, prMUL_DIV + 1);
277         }
278
279 } // namespace mu