NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
muParserBytecode.cpp
Go to the documentation of this file.
1/*
2 __________
3 _____ __ __\______ \_____ _______ ______ ____ _______
4 / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5 | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6 |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7 \/ \/ \/ \/
8 Copyright (C) 2011 Ingo Berg
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy of this
11 software and associated documentation files (the "Software"), to deal in the Software
12 without restriction, including without limitation the rights to use, copy, modify,
13 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in all copies or
17 substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24*/
25
26#include "muParserBytecode.h"
27#include "../../kernel.hpp"
28#include "../utils/stringtools.hpp"
29
30#include <cassert>
31#include <string>
32#include <stack>
33#include <vector>
34#include <iostream>
35
36#include "muParserDef.h"
37#include "muParserError.h"
38#include "muParserToken.h"
39#include "muParserStack.h"
41
42namespace mu
43{
44 //---------------------------------------------------------------------------
47 : m_iStackPos(0)
48 , m_iMaxStackSize(0)
49 , m_vRPN()
50 , m_bEnableOptimizer(true)
51 {
52 m_vRPN.reserve(50);
53 }
54
55 //---------------------------------------------------------------------------
61 {
62 Assign(a_ByteCode);
63 }
64
65 //---------------------------------------------------------------------------
71 {
72 Assign(a_ByteCode);
73 return *this;
74 }
75
76 //---------------------------------------------------------------------------
78 {
79 m_bEnableOptimizer = bStat;
80 }
81
82 //---------------------------------------------------------------------------
87 void ParserByteCode::Assign(const ParserByteCode& a_ByteCode)
88 {
89 if (this == &a_ByteCode)
90 return;
91
92 m_iStackPos = a_ByteCode.m_iStackPos;
93 m_vRPN = a_ByteCode.m_vRPN;
96 }
97
98 //---------------------------------------------------------------------------
104 {
105 ++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 tok.Val.isVect = false;
115 m_vRPN.push_back(tok);
116 }
117
118 //---------------------------------------------------------------------------
132 {
133 ++m_iStackPos;
135
136 // If optimization does not apply
137 SToken tok;
138 tok.Cmd = cmVAL;
139 tok.Val.ptr = nullptr;
140 tok.Val.data = 0;
141 tok.Val.data2 = a_fVal;
142 m_vRPN.push_back(tok);
143 }
144
145 //---------------------------------------------------------------------------
147 {
148 std::size_t sz = m_vRPN.size();
149 value_type& x = m_vRPN[sz - 2].Val.data2,
150 &y = m_vRPN[sz - 1].Val.data2;
151 switch (a_Oprt)
152 {
153 case cmLAND:
154 x = x != 0.0 && y != 0.0;
155 m_vRPN.pop_back();
156 break;
157 case cmLOR:
158 x = x != 0.0 || y != 0.0;
159 m_vRPN.pop_back();
160 break;
161 case cmLT:
162 x = x.real() < y.real();
163 m_vRPN.pop_back();
164 break;
165 case cmGT:
166 x = x.real() > y.real();
167 m_vRPN.pop_back();
168 break;
169 case cmLE:
170 x = x.real() <= y.real();
171 m_vRPN.pop_back();
172 break;
173 case cmGE:
174 x = x.real() >= y.real();
175 m_vRPN.pop_back();
176 break;
177 case cmNEQ:
178 x = x != y;
179 m_vRPN.pop_back();
180 break;
181 case cmEQ:
182 x = x == y;
183 m_vRPN.pop_back();
184 break;
185 case cmADD:
186 x = x + y;
187 m_vRPN.pop_back();
188 break;
189 case cmSUB:
190 x = x - y;
191 m_vRPN.pop_back();
192 break;
193 case cmMUL:
194 x = x * y;
195 m_vRPN.pop_back();
196 break;
197 case cmDIV:
198
199#if defined(MUP_MATH_EXCEPTIONS)
200 if (y == 0)
202#endif
203
204 x = x / y;
205 m_vRPN.pop_back();
206 break;
207
208 case cmPOW:
210 m_vRPN.pop_back();
211 break;
212
213 default:
214 break;
215 } // switch opcode
216 }
217
218 //---------------------------------------------------------------------------
230 {
231 bool bOptimized = false;
232
234 {
235 std::size_t sz = m_vRPN.size();
236
237 // Check for foldable constants like:
238 // cmVAL cmVAL cmADD
239 // where cmADD can stand fopr any binary operator applied to
240 // two constant values.
241 if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL)
242 {
243 ConstantFolding(a_Oprt);
244 bOptimized = true;
245 }
246 else
247 {
248 switch (a_Oprt)
249 {
250 case cmPOW:
251 // Optimization for ploynomials of low order
252 if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL)
253 {
254 if (m_vRPN[sz - 1].Val.data2 == 2.0)
255 m_vRPN[sz - 2].Cmd = cmVARPOW2;
256 else if (m_vRPN[sz - 1].Val.data2 == 3.0)
257 m_vRPN[sz - 2].Cmd = cmVARPOW3;
258 else if (m_vRPN[sz - 1].Val.data2 == 4.0)
259 m_vRPN[sz - 2].Cmd = cmVARPOW4;
260 else if (m_vRPN[sz - 1].Val.data2 == (double)intCast(m_vRPN[sz - 1].Val.data2.real()))
261 {
262 m_vRPN[sz - 2].Cmd = cmVARPOWN;
263 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data2;
264 }
265 else
266 break;
267
268 m_vRPN.pop_back();
269 bOptimized = true;
270 }
271 break;
272
273 case cmSUB:
274 case cmADD:
275 // Simple optimization based on pattern recognition for a shitload of different
276 // bytecode combinations of addition/subtraction
277 if ((m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL)
278 || (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR)
279 || (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL)
280 || (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL)
281 || (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr)
282 || (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr)
283 || (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr)
284 || (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr))
285 {
286 assert((m_vRPN[sz-2].Val.ptr == NULL && m_vRPN[sz-1].Val.ptr != NULL)
287 || (m_vRPN[sz-2].Val.ptr != NULL && m_vRPN[sz-1].Val.ptr == NULL)
288 || (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr));
289
290 m_vRPN[sz-2].Cmd = cmVARMUL;
291 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
292 m_vRPN[sz-2].Val.data2 += ((a_Oprt == cmSUB) ? -1.0 : 1.0) * m_vRPN[sz-1].Val.data2; // offset
293 m_vRPN[sz-2].Val.data += ((a_Oprt == cmSUB) ? -1.0 : 1.0) * m_vRPN[sz-1].Val.data; // multiplikatior
294 m_vRPN[sz-2].Val.isVect = false;
295 m_vRPN.pop_back();
296 bOptimized = true;
297 }
298 break;
299
300 case cmMUL:
301 if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL)
302 || (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) )
303 {
304 m_vRPN[sz-2].Cmd = cmVARMUL;
305 m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
306 m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
307 m_vRPN[sz-2].Val.data2 = 0;
308 m_vRPN[sz-2].Val.isVect = false;
309 m_vRPN.pop_back();
310 bOptimized = true;
311 }
312 else if ((m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL)
313 || (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL))
314 {
315 // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
316 m_vRPN[sz-2].Cmd = cmVARMUL;
317 m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
318 m_vRPN[sz-2].Val.isVect = false;
319
320 if (m_vRPN[sz-1].Cmd == cmVAL)
321 {
322 m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
323 m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2;
324 }
325 else
326 {
327 m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2;
328 m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2;
329 }
330 m_vRPN.pop_back();
331 bOptimized = true;
332 }
333 else if (m_vRPN[sz-1].Cmd == cmVAR
334 && m_vRPN[sz-2].Cmd == cmVAR
335 && m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr)
336 {
337 // Optimization: a*a -> a^2
338 m_vRPN[sz - 2].Cmd = cmVARPOW2;
339 m_vRPN.pop_back();
340 bOptimized = true;
341 }
342 break;
343
344 case cmDIV:
345 if (m_vRPN[sz-1].Cmd == cmVAL
346 && m_vRPN[sz-2].Cmd == cmVARMUL
347 && m_vRPN[sz-1].Val.data2 != 0.0)
348 {
349 // Optimization: 4*a/2 -> 2*a
350 m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
351 m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
352 m_vRPN.pop_back();
353 bOptimized = true;
354 }
355 break;
356
357 default:
358 break;
359 // Nothing, just avoiding warnings
360
361 } // switch a_Oprt
362 }
363 }
364
365 // If optimization can't be applied just write the value
366 if (!bOptimized)
367 {
368 --m_iStackPos;
369 SToken tok;
370 tok.Cmd = a_Oprt;
371 m_vRPN.push_back(tok);
372 }
373 }
374
375 //---------------------------------------------------------------------------
377 {
378 SToken tok;
379 tok.Cmd = a_Oprt;
380 m_vRPN.push_back(tok);
381 }
382
383 //---------------------------------------------------------------------------
395 {
396 --m_iStackPos;
397
398 SToken tok;
399 tok.Cmd = cmASSIGN;
400 tok.Val.ptr = a_pVar;
401 tok.Val.isVect = false;
402 m_vRPN.push_back(tok);
403 }
404
405
415 void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc, bool optimizeAway)
416 {
417 // Shall we try to optimize?
418 if (m_bEnableOptimizer && optimizeAway)
419 {
420 std::size_t sz = m_vRPN.size();
421 std::size_t nArg = std::abs(a_iArgc);
422
423 // Ensure that we have enough entries in the
424 // bytecode available
425 if (sz < nArg)
427
428 // Check, whether all arguments are constant
429 // values
430 for (size_t s = sz-nArg; s < sz; s++)
431 {
432 // If not a constant value, deactivate the optimizer flag
433 if (m_vRPN[s].Cmd != cmVAL)
434 {
435 optimizeAway = false;
436 break;
437 }
438 }
439
440 // Can we still optimize?
441 if (optimizeAway)
442 {
443 // switch according to argument count. Call the corresponding
444 // function and replace the first value with the result. Remove
445 // all other values afterwards
446 switch (a_iArgc)
447 {
448 case 0:
449 AddVal((*(fun_type0)a_pFun)());
450 break;
451 case 1:
452 m_vRPN[sz-1].Val.data2 = (*(fun_type1)a_pFun)(m_vRPN[sz-1].Val.data2);
453 break;
454 case 2:
455 m_vRPN[sz-2].Val.data2 = (*(fun_type2)a_pFun)(m_vRPN[sz-2].Val.data2,
456 m_vRPN[sz-1].Val.data2);
457 m_vRPN.pop_back();
458 break;
459 case 3:
460 m_vRPN[sz-3].Val.data2 = (*(fun_type3)a_pFun)(m_vRPN[sz-3].Val.data2,
461 m_vRPN[sz-2].Val.data2,
462 m_vRPN[sz-1].Val.data2);
463 m_vRPN.resize(sz-2);
464 break;
465 case 4:
466 m_vRPN[sz-4].Val.data2 = (*(fun_type4)a_pFun)(m_vRPN[sz-4].Val.data2,
467 m_vRPN[sz-3].Val.data2,
468 m_vRPN[sz-2].Val.data2,
469 m_vRPN[sz-1].Val.data2);
470 m_vRPN.resize(sz-3);
471 break;
472 case 5:
473 m_vRPN[sz-5].Val.data2 = (*(fun_type5)a_pFun)(m_vRPN[sz-5].Val.data2,
474 m_vRPN[sz-4].Val.data2,
475 m_vRPN[sz-3].Val.data2,
476 m_vRPN[sz-2].Val.data2,
477 m_vRPN[sz-1].Val.data2);
478 m_vRPN.resize(sz-4);
479 break;
480 case 6:
481 m_vRPN[sz-6].Val.data2 = (*(fun_type6)a_pFun)(m_vRPN[sz-6].Val.data2,
482 m_vRPN[sz-5].Val.data2,
483 m_vRPN[sz-4].Val.data2,
484 m_vRPN[sz-3].Val.data2,
485 m_vRPN[sz-2].Val.data2,
486 m_vRPN[sz-1].Val.data2);
487 m_vRPN.resize(sz-5);
488 break;
489 case 7:
490 m_vRPN[sz-7].Val.data2 = (*(fun_type7)a_pFun)(m_vRPN[sz-7].Val.data2,
491 m_vRPN[sz-6].Val.data2,
492 m_vRPN[sz-5].Val.data2,
493 m_vRPN[sz-4].Val.data2,
494 m_vRPN[sz-3].Val.data2,
495 m_vRPN[sz-2].Val.data2,
496 m_vRPN[sz-1].Val.data2);
497 m_vRPN.resize(sz-6);
498 break;
499 case 8:
500 m_vRPN[sz-8].Val.data2 = (*(fun_type8)a_pFun)(m_vRPN[sz-8].Val.data2,
501 m_vRPN[sz-7].Val.data2,
502 m_vRPN[sz-6].Val.data2,
503 m_vRPN[sz-5].Val.data2,
504 m_vRPN[sz-4].Val.data2,
505 m_vRPN[sz-3].Val.data2,
506 m_vRPN[sz-2].Val.data2,
507 m_vRPN[sz-1].Val.data2);
508 m_vRPN.resize(sz-7);
509 break;
510 case 9:
511 m_vRPN[sz-9].Val.data2 = (*(fun_type9)a_pFun)(m_vRPN[sz-9].Val.data2,
512 m_vRPN[sz-8].Val.data2,
513 m_vRPN[sz-7].Val.data2,
514 m_vRPN[sz-6].Val.data2,
515 m_vRPN[sz-5].Val.data2,
516 m_vRPN[sz-4].Val.data2,
517 m_vRPN[sz-3].Val.data2,
518 m_vRPN[sz-2].Val.data2,
519 m_vRPN[sz-1].Val.data2);
520 m_vRPN.resize(sz-8);
521 break;
522 case 10:
523 m_vRPN[sz-10].Val.data2 = (*(fun_type10)a_pFun)(m_vRPN[sz-10].Val.data2,
524 m_vRPN[sz-9].Val.data2,
525 m_vRPN[sz-8].Val.data2,
526 m_vRPN[sz-7].Val.data2,
527 m_vRPN[sz-6].Val.data2,
528 m_vRPN[sz-5].Val.data2,
529 m_vRPN[sz-4].Val.data2,
530 m_vRPN[sz-3].Val.data2,
531 m_vRPN[sz-2].Val.data2,
532 m_vRPN[sz-1].Val.data2);
533 m_vRPN.resize(sz-9);
534 break;
535 default:
536 {
537 if (a_iArgc > 0) // function with variable arguments store the number as a negative value
539
540 std::vector<mu::value_type> vStack;
541
542 // Copy the values to the temporary stack
543 for (size_t s = sz-nArg; s < sz; s++)
544 {
545 vStack.push_back(m_vRPN[s].Val.data2);
546 }
547
548 m_vRPN[sz-nArg].Val.data2 = (*(multfun_type)a_pFun)(&vStack[0], nArg);
549 m_vRPN.resize(sz-nArg+1);
550 }
551 }
552 }
553 }
554
555 // If optimization can't be applied just add the call to the function
556 if (!optimizeAway)
557 {
558 if (a_iArgc >= 0)
559 m_iStackPos = m_iStackPos - a_iArgc + 1;
560 else
561 // function with unlimited number of arguments
562 m_iStackPos = m_iStackPos + a_iArgc + 1;
563
565
566 SToken tok;
567 tok.Cmd = cmFUNC;
568 tok.Fun.argc = a_iArgc;
569 tok.Fun.ptr = a_pFun;
570 m_vRPN.push_back(tok);
571 }
572
573
574 }
575
576 //---------------------------------------------------------------------------
583 {
584 m_iStackPos = m_iStackPos - a_iArgc + 1;
586
587 SToken tok;
588 tok.Cmd = cmFUNC_BULK;
589 tok.Fun.argc = a_iArgc;
590 tok.Fun.ptr = a_pFun;
591 m_vRPN.push_back(tok);
592 }
593
594 //---------------------------------------------------------------------------
602 void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
603 {
604 m_iStackPos = m_iStackPos - a_iArgc + 1;
605
606 SToken tok;
607 tok.Cmd = cmFUNC_STR;
608 tok.Fun.argc = a_iArgc;
609 tok.Fun.idx = a_iIdx;
610 tok.Fun.ptr = a_pFun;
611 m_vRPN.push_back(tok);
612
614 }
615
616 //---------------------------------------------------------------------------
622 {
623 SToken tok;
624 tok.Cmd = cmEND;
625 m_vRPN.push_back(tok);
626 rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit
627
628 // Determine the if-then-else jump offsets
629 ParserStack<int> stIf, stElse;
630 int idx;
631 for (int i = 0; i < (int)m_vRPN.size(); ++i)
632 {
633 switch (m_vRPN[i].Cmd)
634 {
635 case cmIF:
636 stIf.push(i);
637 break;
638
639 case cmELSE:
640 stElse.push(i);
641 idx = stIf.pop();
642 m_vRPN[idx].Oprt.offset = i - idx;
643 break;
644
645 case cmENDIF:
646 idx = stElse.pop();
647 m_vRPN[idx].Oprt.offset = i - idx;
648 break;
649
650 default:
651 break;
652 }
653 }
654 }
655
656
669 void ParserByteCode::ChangeVar(value_type* a_pOldVar, value_type* a_pNewVar, bool isVect)
670 {
671 for (size_t i = 0; i < m_vRPN.size(); ++i)
672 {
673 if (m_vRPN[i].Cmd >= cmVAR && m_vRPN[i].Cmd < cmVAR_END && m_vRPN[i].Val.ptr == a_pOldVar)
674 {
675 m_vRPN[i].Val.ptr = a_pNewVar;
676 m_vRPN[i].Val.isVect = isVect;
677 }
678 }
679 }
680
681
682 //---------------------------------------------------------------------------
684 {
685 if (m_vRPN.size() == 0)
687 else
688 return &m_vRPN[0];
689 }
690
691 //---------------------------------------------------------------------------
693 {
694 return m_iMaxStackSize + 1;
695 }
696
697 //---------------------------------------------------------------------------
699 std::size_t ParserByteCode::GetSize() const
700 {
701 return m_vRPN.size();
702 }
703
704 //---------------------------------------------------------------------------
714 {
715 m_vRPN.clear();
716 m_iStackPos = 0;
717 m_iMaxStackSize = 0;
718 }
719
720 //---------------------------------------------------------------------------
723 {
724 if (!m_vRPN.size())
725 {
726 NumeReKernel::print("No bytecode available");
727 return;
728 }
729
731 NumeReKernel::print("Number of RPN tokens: " + toString(m_vRPN.size()));
732
733 for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd != cmEND; ++i)
734 {
735 NumeReKernel::printPreFmt("| " + toString(i) + " : \t");
736 switch (m_vRPN[i].Cmd)
737 {
738 case cmVAL:
739 NumeReKernel::printPreFmt("VAL \t[" + toString(m_vRPN[i].Val.data2, 7) + "]\n");
740 break;
741
742 case cmVAR:
743 NumeReKernel::printPreFmt("VAR \t[" + toHexString((int)m_vRPN[i].Val.ptr) + "]\n");
744 break;
745
746 case cmVARPOW2:
747 NumeReKernel::printPreFmt("VARPOW2 \t[" + toHexString((int)m_vRPN[i].Val.ptr) + "]\n");
748 break;
749
750 case cmVARPOW3:
751 NumeReKernel::printPreFmt("VARPOW3 \t[" + toHexString((int)m_vRPN[i].Val.ptr) + "]\n");
752 break;
753
754 case cmVARPOW4:
755 NumeReKernel::printPreFmt("VARPOW4 \t[" + toHexString((int)m_vRPN[i].Val.ptr) + "]\n");
756 break;
757
758 case cmVARMUL:
759 NumeReKernel::printPreFmt("VARMUL \t[" + toHexString((int)m_vRPN[i].Val.ptr) + "]");
760 NumeReKernel::printPreFmt(" * [" + toString(m_vRPN[i].Val.data, 7) + "] + [" + toString(m_vRPN[i].Val.data2, 7) + "]\n");
761 break;
762
763 case cmFUNC:
764 NumeReKernel::printPreFmt("CALL \t[ARG: " + toString(m_vRPN[i].Fun.argc) + "] [ADDR: " + toHexString((int)m_vRPN[i].Fun.ptr) + "]\n");
765 break;
766
767 case cmFUNC_STR:
768 NumeReKernel::printPreFmt("CALL STRFUNC\t[ARG:" + toString(m_vRPN[i].Fun.argc) + "] [IDX: "+ toString(m_vRPN[i].Fun.idx) + "] [ADDR: " + toHexString((int)m_vRPN[i].Fun.ptr) + "]\n");
769 break;
770
771 case cmLT:
773 break;
774 case cmGT:
776 break;
777 case cmLE:
779 break;
780 case cmGE:
782 break;
783 case cmEQ:
785 break;
786 case cmNEQ:
788 break;
789 case cmADD:
791 break;
792 case cmLAND:
794 break;
795 case cmLOR:
797 break;
798 case cmSUB:
800 break;
801 case cmMUL:
803 break;
804 case cmDIV:
806 break;
807 case cmPOW:
809 break;
810
811 case cmIF:
812 NumeReKernel::printPreFmt("IF\t[OFFSET: " + toString(m_vRPN[i].Oprt.offset) + "]\n");
813 break;
814
815 case cmELSE:
816 NumeReKernel::printPreFmt("ELSE\t[OFFSET: " + toString(m_vRPN[i].Oprt.offset) + "]\n");
817 break;
818
819 case cmENDIF:
820 NumeReKernel::printPreFmt("ENDIF\n");
821 break;
822
823 case cmASSIGN:
824 NumeReKernel::printPreFmt("ASSIGN \t[" + toHexString((int)m_vRPN[i].Oprt.ptr) + "]\n");
825 break;
826
827 default:
828 NumeReKernel::printPreFmt("(unknown \t(" + toString((int)m_vRPN[i].Cmd) + ")\n");
829 break;
830 } // switch cmdCode
831 } // while bytecode
832
834 NumeReKernel::printPreFmt("| END\n");
835 }
836} // namespace mu
static void printPreFmt(const std::string &__sLine, bool printingEnabled=true)
This member function appends the pre- formatted string to the buffer and informs the terminal that we...
Definition: kernel.cpp:2683
static void print(const std::string &__sLine, bool printingEnabled=true)
This member function appends the passed string as a new output line to the buffer and informs the ter...
Definition: kernel.cpp:2636
static void toggleTableStatus()
Toggles the table writing status, which will reduce the number or events send to the terminal.
Definition: kernel.cpp:3671
Bytecode implementation of the Math Parser.
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
rpn_type m_vRPN
The actual rpn storage.
ParserByteCode & operator=(const ParserByteCode &a_ByteCode)
Assignment operator.
void ConstantFolding(ECmdCode a_Oprt)
void EnableOptimizer(bool bStat)
std::size_t GetMaxStackSize() const
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
const SToken * GetBase() const
void ChangeVar(value_type *a_pOldVar, value_type *a_pNewVar, bool isVect)
Changes all old variable pointers to the new addresses. Will be used to compensate for different loca...
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
ParserByteCode()
Bytecode default constructor.
void clear()
Delete the bytecode.
std::size_t GetSize() const
Returns the number of entries in the bytecode.
void AddFun(generic_fun_type a_pFun, int a_iArgc, bool optimizeAway)
Add a function to the bytecode.
void AsciiDump()
Dump bytecode (for debugging only!).
void AddVar(value_type *a_pVar)
Add a Variable pointer to bytecode.
std::vector< SToken > rpn_type
Token vector for storing the RPN.
std::size_t m_iMaxStackSize
Maximum size needed for the stack.
unsigned m_iStackPos
Position in the Calculation array.
void Finalize()
Add end marker to bytecode.
void AddAssignOp(value_type *a_pVar)
Add an assignement operator.
void AddIfElse(ECmdCode a_Oprt)
Error class of the parser.
Parser stack implementation.
Definition: muParserStack.h:54
void push(const TValueType &a_Val)
Push an object into the stack.
Definition: muParserStack.h:97
TValueType pop()
Pop a value from the stack.
Definition: muParserStack.h:82
Definition of the parser bytecode class.
This file contains standard definitions used by the parser.
This file defines the error class used by the parser.
This file defines the stack used by muparser.
This file contains the parser token definition.
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
Namespace for mathematical applications.
Definition: muParser.cpp:53
value_type(* multfun_type)(const value_type *, int)
Callback type used for functions with a variable argument list.
Definition: muParserDef.h:356
value_type(* fun_type9)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:317
value_type(* fun_type6)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:308
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
value_type(* fun_type10)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:320
value_type(* fun_type2)(const value_type &, const value_type &)
Callback type used for functions with two arguments.
Definition: muParserDef.h:296
value_type(* fun_type7)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:311
value_type(* fun_type5)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:305
value_type(* fun_type1)(const value_type &)
Callback type used for functions with a single arguments.
Definition: muParserDef.h:293
ECmdCode
Bytecode values.
Definition: muParserDef.h:153
@ cmVARMUL
Definition: muParserDef.h:185
@ cmVARPOW2
Definition: muParserDef.h:181
@ cmFUNC_BULK
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: muParserDef.h:191
@ cmADD
Operator item: add.
Definition: muParserDef.h:163
@ cmGE
Operator item: greater or equal.
Definition: muParserDef.h:158
@ cmLT
Operator item: less than.
Definition: muParserDef.h:161
@ cmPOW
Operator item: y to the power of ...
Definition: muParserDef.h:167
@ cmASSIGN
Operator item: Assignment operator.
Definition: muParserDef.h:170
@ cmLAND
Definition: muParserDef.h:168
@ cmLE
Operator item: less or equal.
Definition: muParserDef.h:157
@ cmMUL
Operator item: multiply.
Definition: muParserDef.h:165
@ cmEND
end of formula
Definition: muParserDef.h:196
@ cmDIV
Operator item: division.
Definition: muParserDef.h:166
@ cmLOR
Definition: muParserDef.h:169
@ cmENDIF
For use in the ternary if-then-else operator.
Definition: muParserDef.h:175
@ cmVAR_END
Only for identifying the end of the variable block.
Definition: muParserDef.h:186
@ cmVAL
value item
Definition: muParserDef.h:177
@ cmIF
For use in the ternary if-then-else operator.
Definition: muParserDef.h:173
@ cmNEQ
Operator item: not equal.
Definition: muParserDef.h:159
@ cmGT
Operator item: greater than.
Definition: muParserDef.h:162
@ cmEQ
Operator item: equals.
Definition: muParserDef.h:160
@ cmVARPOWN
Definition: muParserDef.h:184
@ cmSUB
Operator item: subtract.
Definition: muParserDef.h:164
@ cmVARPOW3
Definition: muParserDef.h:182
@ cmFUNC_STR
Code for a function with a string parameter.
Definition: muParserDef.h:190
@ cmFUNC
Code for a generic function item.
Definition: muParserDef.h:189
@ cmVARPOW4
Definition: muParserDef.h:183
@ cmELSE
For use in the ternary if-then-else operator.
Definition: muParserDef.h:174
@ cmVAR
variable item
Definition: muParserDef.h:180
@ ecINTERNAL_ERROR
Internal error of any kind.
Definition: muParserError.h:94
@ ecDIV_BY_ZERO
Division by zero (currently unused)
Definition: muParserError.h:85
value_type(* fun_type8)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:314
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
Definition: muParserDef.h:287
value_type(* fun_type4)(const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with four arguments.
Definition: muParserDef.h:302
value_type(* fun_type0)()
Callback type used for functions without arguments.
Definition: muParserDef.h:290
value_type(* fun_type3)(const value_type &, const value_type &, const value_type &)
Callback type used for functions with three arguments.
Definition: muParserDef.h:299
#define max(a, b)
Definition: resampler.cpp:30
std::string toHexString(int nNumber)
Converts an integer to a hexadecimal number printed as string.
static T Pow(const T &v1, const T &v2)
value_type * ptr
struct mu::SToken::@11::@14 Fun
struct mu::SToken::@11::@13 Val
value_type data2
value_type data
ECmdCode Cmd
long long int intCast(const std::complex< double > &)
Casts the real part of the complex number to an integer and avoids rounding errors.
Definition: tools.cpp:1824
std::string toString(int)
Converts an integer to a string without the Settings bloat.