39 #include "muParserTemplateMagic.h"
50 ,m_bEnableOptimizer(true)
77 void ParserByteCode::EnableOptimizer(
bool bStat)
79 m_bEnableOptimizer = bStat;
89 if (
this==&a_ByteCode)
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;
106 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
111 tok.Val.ptr = a_pVar;
114 m_vRPN.push_back(tok);
133 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
140 tok.Val.data2 = a_fVal;
141 m_vRPN.push_back(tok);
145 void ParserByteCode::ConstantFolding(
ECmdCode a_Oprt)
147 std::size_t sz = m_vRPN.size();
149 &y = m_vRPN[sz-1].Val.data2;
152 case cmLAND: x = (int)x && (
int)y; m_vRPN.pop_back();
break;
153 case cmLOR: x = (int)x || (
int)y; m_vRPN.pop_back();
break;
154 case cmLT: x = x < y; m_vRPN.pop_back();
break;
155 case cmGT: x = x > y; m_vRPN.pop_back();
break;
156 case cmLE: x = x <= y; m_vRPN.pop_back();
break;
157 case cmGE: x = x >= y; m_vRPN.pop_back();
break;
158 case cmNEQ: x = x != y; m_vRPN.pop_back();
break;
159 case cmEQ: x = x == y; m_vRPN.pop_back();
break;
160 case cmADD: x = x + y; m_vRPN.pop_back();
break;
161 case cmSUB: x = x - y; m_vRPN.pop_back();
break;
162 case cmMUL: x = x * y; m_vRPN.pop_back();
break;
165 #if defined(MUP_MATH_EXCEPTIONS)
196 bool bOptimized =
false;
198 if (m_bEnableOptimizer)
200 std::size_t sz = m_vRPN.size();
206 if (sz>=2 && m_vRPN[sz-2].Cmd ==
cmVAL && m_vRPN[sz-1].Cmd ==
cmVAL)
208 ConstantFolding(a_Oprt);
217 if (m_vRPN[sz-2].Cmd ==
cmVAR && m_vRPN[sz-1].Cmd ==
cmVAL)
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;
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) )
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) );
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));
252 m_vRPN[sz-2].Val.data2 += ((a_Oprt==
cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2;
253 m_vRPN[sz-2].Val.data += ((a_Oprt==
cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data;
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) )
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;
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) )
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)
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;
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;
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)
293 m_vRPN[sz-2].Cmd = cmVARPOW2;
300 if (m_vRPN[sz-1].Cmd ==
cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
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;
320 m_vRPN.push_back(tok);
325 void ParserByteCode::AddIfElse(
ECmdCode a_Oprt)
329 m_vRPN.push_back(tok);
349 tok.Oprt.ptr = a_pVar;
350 m_vRPN.push_back(tok);
363 m_iStackPos = m_iStackPos - a_iArgc + 1;
368 m_iStackPos = m_iStackPos + a_iArgc + 1;
370 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
374 tok.Fun.argc = a_iArgc;
375 tok.Fun.ptr = a_pFun;
376 m_vRPN.push_back(tok);
387 m_iStackPos = m_iStackPos - a_iArgc + 1;
388 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
392 tok.Fun.argc = a_iArgc;
393 tok.Fun.ptr = a_pFun;
394 m_vRPN.push_back(tok);
407 m_iStackPos = m_iStackPos - a_iArgc + 1;
411 tok.Fun.argc = a_iArgc;
412 tok.Fun.idx = a_iIdx;
413 tok.Fun.ptr = a_pFun;
414 m_vRPN.push_back(tok);
416 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
428 m_vRPN.push_back(tok);
429 rpn_type(m_vRPN).swap(m_vRPN);
434 for (
int i=0; i<(int)m_vRPN.size(); ++i)
436 switch(m_vRPN[i].Cmd)
445 m_vRPN[idx].Oprt.offset = i - idx;
450 m_vRPN[idx].Oprt.offset = i - idx;
460 const SToken* ParserByteCode::GetBase()
const
462 if (m_vRPN.size()==0)
469 std::size_t ParserByteCode::GetMaxStackSize()
const
471 return m_iMaxStackSize+1;
478 return m_vRPN.size();
507 mu::console() <<
_T(
"Number of RPN tokens:") << (int)m_vRPN.size() <<
_T(
"\n");
508 for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=
cmEND; ++i)
511 switch (m_vRPN[i].Cmd)
518 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
522 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
526 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
530 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
534 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]");
540 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
541 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Fun.ptr <<
_T(
"]");
547 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
548 mu::console() <<
_T(
"[IDX:") << std::dec << m_vRPN[i].Fun.idx <<
_T(
"]");
567 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
571 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
581 default:
mu::console() <<
_T(
"(unknown code: ") << m_vRPN[i].Cmd <<
_T(
")\n");
Definition of the parser bytecode class.
#define _T(x)
Activate this option in order to compile with OpenMP support.
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
std::ostream & console()
Encapsulate cout.
void push(const TValueType &a_Val)
Push an object into the stack.
Division by zero (currently unused)
Operator item: y to the power of ...
Internal error of any kind.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
Operator item: not equal.
For use in the ternary if-then-else operator.
TValueType pop()
Pop a value from the stack.
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
Parser stack implementation.
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.
std::size_t GetSize() const
Returns the number of entries in the bytecode.
Code for a generic function item.
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
void AsciiDump()
Dump bytecode (for debugging only!).
ParserByteCode()
Bytecode default constructor.
For use in the ternary if-then-else operator.
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
Error class of the parser.
For use in the ternary if-then-else operator.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
A template class for providing wrappers for essential math functions.
Namespace for mathematical applications.
Operator item: less than.
Operator item: greater than.
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
This file defines the stack used by muparser.
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Code for a function with a string parameter.
Operator item: Assignment operator.
Bytecode implementation of the Math Parser.
This file contains the parser token definition.
void clear()
Delete the bytecode.
void AddVar(value_type *a_pVar)
Add a Variable pointer to bytecode.
Operator item: less or equal.
Operator item: greater or equal.
ParserByteCode & operator=(const ParserByteCode &a_ByteCode)
Assignment operator.
void Finalize()
Add end marker to bytecode.
This file defines the error class used by the parser.
This file contains standard definitions used by the parser.