muParser API -  1.35
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
Public Member Functions | List of all members
mu::ParserByteCode Class Reference

Bytecode implementation of the Math Parser. More...

#include <muParserBytecode.h>

Public Member Functions

 ParserByteCode ()
 Bytecode default constructor.
 
 ParserByteCode (const ParserByteCode &a_ByteCode)
 Copy constructor. More...
 
ParserByteCodeoperator= (const ParserByteCode &a_ByteCode)
 Assignment operator. More...
 
void Assign (const ParserByteCode &a_ByteCode)
 Copy state of another object to this. More...
 
void AddVar (value_type *a_pVar)
 Add a Variable pointer to bytecode. More...
 
void AddVal (value_type a_fVal)
 Add a Variable pointer to bytecode. More...
 
void AddOp (ECmdCode a_Oprt)
 Add an operator identifier to bytecode. More...
 
void AddIfElse (ECmdCode a_Oprt)
 
void AddAssignOp (value_type *a_pVar)
 Add an assignment operator. More...
 
void AddFun (generic_fun_type a_pFun, int a_iArgc)
 Add function to bytecode. More...
 
void AddBulkFun (generic_fun_type a_pFun, int a_iArgc)
 Add a bulk function to bytecode. More...
 
void AddStrFun (generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
 Add Strung function entry to the parser bytecode. More...
 
void EnableOptimizer (bool bStat)
 
void Finalize ()
 Add end marker to bytecode. More...
 
void clear ()
 Delete the bytecode. More...
 
std::size_t GetMaxStackSize () const
 
std::size_t GetSize () const
 Returns the number of entries in the bytecode.
 
const STokenGetBase () const
 
void AsciiDump ()
 Dump bytecode (for debugging only!).
 

Detailed Description

Bytecode implementation of the Math Parser.

The bytecode contains the formula converted to revers polish notation stored in a continious memory area. Associated with this data are operator codes, variable pointers, constant values and function pointers. Those are necessary in order to calculate the result. All those data items will be casted to the underlying datatype of the bytecode.

Author
(C) 2004-2013 Ingo Berg

Definition at line 87 of file muParserBytecode.h.

Constructor & Destructor Documentation

mu::ParserByteCode::ParserByteCode ( const ParserByteCode a_ByteCode)

Copy constructor.

Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)

Definition at line 60 of file muParserBytecode.cpp.

61  {
62  Assign(a_ByteCode);
63  }
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.

Member Function Documentation

void mu::ParserByteCode::AddAssignOp ( value_type a_pVar)

Add an assignment operator.

Operator entries in byte code consist of:

  • cmASSIGN code
  • the pointer of the destination variable
See also
ParserToken::ECmdCode

Definition at line 343 of file muParserBytecode.cpp.

344  {
345  --m_iStackPos;
346 
347  SToken tok;
348  tok.Cmd = cmASSIGN;
349  tok.Oprt.ptr = a_pVar;
350  m_vRPN.push_back(tok);
351  }
Operator item: Assignment operator.
Definition: muParserDef.h:167
void mu::ParserByteCode::AddBulkFun ( generic_fun_type  a_pFun,
int  a_iArgc 
)

Add a bulk function to bytecode.

Parameters
a_iArgcNumber of arguments, negative numbers indicate multiarg functions.
a_pFunPointer to function callback.

Definition at line 385 of file muParserBytecode.cpp.

386  {
387  m_iStackPos = m_iStackPos - a_iArgc + 1;
388  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
389 
390  SToken tok;
391  tok.Cmd = cmFUNC_BULK;
392  tok.Fun.argc = a_iArgc;
393  tok.Fun.ptr = a_pFun;
394  m_vRPN.push_back(tok);
395  }
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: muParserDef.h:187
void mu::ParserByteCode::AddFun ( generic_fun_type  a_pFun,
int  a_iArgc 
)

Add function to bytecode.

Parameters
a_iArgcNumber of arguments, negative numbers indicate multiarg functions.
a_pFunPointer to function callback.

Definition at line 359 of file muParserBytecode.cpp.

360  {
361  if (a_iArgc>=0)
362  {
363  m_iStackPos = m_iStackPos - a_iArgc + 1;
364  }
365  else
366  {
367  // function with unlimited number of arguments
368  m_iStackPos = m_iStackPos + a_iArgc + 1;
369  }
370  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
371 
372  SToken tok;
373  tok.Cmd = cmFUNC;
374  tok.Fun.argc = a_iArgc;
375  tok.Fun.ptr = a_pFun;
376  m_vRPN.push_back(tok);
377  }
Code for a generic function item.
Definition: muParserDef.h:185
void mu::ParserByteCode::AddOp ( ECmdCode  a_Oprt)

Add an operator identifier to bytecode.

Operator entries in byte code consist of:

  • value array position of the result
  • the operator code according to ParserToken::ECmdCode
See also
ParserToken::ECmdCode

Definition at line 194 of file muParserBytecode.cpp.

195  {
196  bool bOptimized = false;
197 
198  if (m_bEnableOptimizer)
199  {
200  std::size_t sz = m_vRPN.size();
201 
202  // Check for foldable constants like:
203  // cmVAL cmVAL cmADD
204  // where cmADD can stand fopr any binary operator applied to
205  // two constant values.
206  if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)
207  {
208  ConstantFolding(a_Oprt);
209  bOptimized = true;
210  }
211  else
212  {
213  switch(a_Oprt)
214  {
215  case cmPOW:
216  // Optimization for polynomials of low order
217  if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
218  {
219  if (m_vRPN[sz-1].Val.data2==2)
220  m_vRPN[sz-2].Cmd = cmVARPOW2;
221  else if (m_vRPN[sz-1].Val.data2==3)
222  m_vRPN[sz-2].Cmd = cmVARPOW3;
223  else if (m_vRPN[sz-1].Val.data2==4)
224  m_vRPN[sz-2].Cmd = cmVARPOW4;
225  else
226  break;
227 
228  m_vRPN.pop_back();
229  bOptimized = true;
230  }
231  break;
232 
233  case cmSUB:
234  case cmADD:
235  // Simple optimization based on pattern recognition for a shitload of different
236  // bytecode combinations of addition/subtraction
237  if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
238  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ||
239  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
240  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||
241  (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
242  (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
243  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
244  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) )
245  {
246  assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) ||
247  (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) ||
248  (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) );
249 
250  m_vRPN[sz-2].Cmd = cmVARMUL;
251  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable
252  m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset
253  m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand
254  m_vRPN.pop_back();
255  bOptimized = true;
256  }
257  break;
258 
259  case cmMUL:
260  if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
261  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) )
262  {
263  m_vRPN[sz-2].Cmd = cmVARMUL;
264  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
265  m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
266  m_vRPN[sz-2].Val.data2 = 0;
267  m_vRPN.pop_back();
268  bOptimized = true;
269  }
270  else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
271  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )
272  {
273  // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
274  m_vRPN[sz-2].Cmd = cmVARMUL;
275  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
276  if (m_vRPN[sz-1].Cmd == cmVAL)
277  {
278  m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
279  m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2;
280  }
281  else
282  {
283  m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2;
284  m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2;
285  }
286  m_vRPN.pop_back();
287  bOptimized = true;
288  }
289  else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&
290  m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr)
291  {
292  // Optimization: a*a -> a^2
293  m_vRPN[sz-2].Cmd = cmVARPOW2;
294  m_vRPN.pop_back();
295  bOptimized = true;
296  }
297  break;
298 
299  case cmDIV:
300  if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
301  {
302  // Optimization: 4*a/2 -> 2*a
303  m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2;
304  m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2;
305  m_vRPN.pop_back();
306  bOptimized = true;
307  }
308  break;
309 
310  } // switch a_Oprt
311  }
312  }
313 
314  // If optimization can't be applied just write the value
315  if (!bOptimized)
316  {
317  --m_iStackPos;
318  SToken tok;
319  tok.Cmd = a_Oprt;
320  m_vRPN.push_back(tok);
321  }
322  }
Operator item: y to the power of ...
Definition: muParserDef.h:164
Operator item: subtract.
Definition: muParserDef.h:161
Operator item: multiply.
Definition: muParserDef.h:162
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:247
Operator item: division.
Definition: muParserDef.h:163
Operator item: add.
Definition: muParserDef.h:160
value item
Definition: muParserDef.h:175
variable item
Definition: muParserDef.h:174
void mu::ParserByteCode::AddStrFun ( generic_fun_type  a_pFun,
int  a_iArgc,
int  a_iIdx 
)

Add Strung function entry to the parser bytecode.

Exceptions
nothrowA string function entry consists of the stack position of the return value, followed by a cmSTRFUNC code, the function pointer and an index into the string buffer maintained by the parser.

Definition at line 405 of file muParserBytecode.cpp.

406  {
407  m_iStackPos = m_iStackPos - a_iArgc + 1;
408 
409  SToken tok;
410  tok.Cmd = cmFUNC_STR;
411  tok.Fun.argc = a_iArgc;
412  tok.Fun.idx = a_iIdx;
413  tok.Fun.ptr = a_pFun;
414  m_vRPN.push_back(tok);
415 
416  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
417  }
Code for a function with a string parameter.
Definition: muParserDef.h:186
void mu::ParserByteCode::AddVal ( value_type  a_fVal)

Add a Variable pointer to bytecode.

Value entries in byte code consist of:

  • value array position of the value
  • the operator code according to ParserToken::cmVAL
  • the value stored in #mc_iSizeVal number of bytecode entries.
Parameters
a_pValValue to be added.
Exceptions
nothrow

Definition at line 130 of file muParserBytecode.cpp.

131  {
132  ++m_iStackPos;
133  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
134 
135  // If optimization does not apply
136  SToken tok;
137  tok.Cmd = cmVAL;
138  tok.Val.ptr = NULL;
139  tok.Val.data = 0;
140  tok.Val.data2 = a_fVal;
141  m_vRPN.push_back(tok);
142  }
value item
Definition: muParserDef.h:175
void mu::ParserByteCode::AddVar ( value_type a_pVar)

Add a Variable pointer to bytecode.

Parameters
a_pVarPointer to be added.
Exceptions
nothrow

Definition at line 103 of file muParserBytecode.cpp.

104  {
105  ++m_iStackPos;
106  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
107 
108  // optimization does not apply
109  SToken tok;
110  tok.Cmd = cmVAR;
111  tok.Val.ptr = a_pVar;
112  tok.Val.data = 1;
113  tok.Val.data2 = 0;
114  m_vRPN.push_back(tok);
115  }
variable item
Definition: muParserDef.h:174
void mu::ParserByteCode::Assign ( const ParserByteCode a_ByteCode)

Copy state of another object to this.

Exceptions
nowthrow

Definition at line 87 of file muParserBytecode.cpp.

Referenced by operator=(), and ParserByteCode().

88  {
89  if (this==&a_ByteCode)
90  return;
91 
92  m_iStackPos = a_ByteCode.m_iStackPos;
93  m_vRPN = a_ByteCode.m_vRPN;
94  m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
95  m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
96  }
void mu::ParserByteCode::clear ( )

Delete the bytecode.

Exceptions
nothrowThe name of this function is a violation of my own coding guidelines but this way it's more in line with the STL functions thus more intuitive.

Definition at line 490 of file muParserBytecode.cpp.

491  {
492  m_vRPN.clear();
493  m_iStackPos = 0;
494  m_iMaxStackSize = 0;
495  }
void mu::ParserByteCode::Finalize ( )

Add end marker to bytecode.

Exceptions
nothrow

Definition at line 424 of file muParserBytecode.cpp.

425  {
426  SToken tok;
427  tok.Cmd = cmEND;
428  m_vRPN.push_back(tok);
429  rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit
430 
431  // Determine the if-then-else jump offsets
432  ParserStack<int> stIf, stElse;
433  int idx;
434  for (int i=0; i<(int)m_vRPN.size(); ++i)
435  {
436  switch(m_vRPN[i].Cmd)
437  {
438  case cmIF:
439  stIf.push(i);
440  break;
441 
442  case cmELSE:
443  stElse.push(i);
444  idx = stIf.pop();
445  m_vRPN[idx].Oprt.offset = i - idx;
446  break;
447 
448  case cmENDIF:
449  idx = stElse.pop();
450  m_vRPN[idx].Oprt.offset = i - idx;
451  break;
452 
453  default:
454  break;
455  }
456  }
457  }
For use in the ternary if-then-else operator.
Definition: muParserDef.h:170
end of formula
Definition: muParserDef.h:192
For use in the ternary if-then-else operator.
Definition: muParserDef.h:171
For use in the ternary if-then-else operator.
Definition: muParserDef.h:172
ParserByteCode & mu::ParserByteCode::operator= ( const ParserByteCode a_ByteCode)

Assignment operator.

Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)

Definition at line 70 of file muParserBytecode.cpp.

71  {
72  Assign(a_ByteCode);
73  return *this;
74  }
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.

The documentation for this class was generated from the following files: