muParser API -  1.35
muParserInt.cpp
Go to the documentation of this file.
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. */
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. */
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
void DefineInfixOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of infix operators.
multiplication/division
Definition: muParserDef.h:216
#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.
virtual void InitFun()
Initialize the default functions.
virtual void InitOprt()
Initialize operators.
void AddValIdent(identfun_type a_pCallback)
Add a value parsing function.
Definition of a parser using integer value.
STL namespace.
power operator priority (highest)
Definition: muParserDef.h:217
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:309
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...
comparsion operators
Definition: muParserDef.h:214
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt=true)
Define a parser function without arguments.
Definition: muParserBase.h:134
addition
Definition: muParserDef.h:215
void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, EOprtAssociativity a_eAssociativity=oaLEFT, bool a_bAllowOpt=false)
Define a binary operator.
logic operators
Definition: muParserDef.h:213
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:294
Namespace for mathematical applications.
Definition: muParser.cpp:46
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:306
void EnableBuiltInOprt(bool a_bIsOn=true)
Enable or disable the built in binary operators.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Definition: muParserDef.h:300
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:63