exprtk.hpp
Go to the documentation of this file.
1/*
2 ******************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * Author: Arash Partow (1999-2021) *
6 * URL: http://www.partow.net/programming/exprtk/index.html *
7 * *
8 * Copyright notice: *
9 * Free use of the C++ Mathematical Expression Toolkit Library is *
10 * permitted under the guidelines and in accordance with the most *
11 * current version of the MIT License. *
12 * http://www.opensource.org/licenses/MIT *
13 * *
14 * Example expressions: *
15 * (00) (y + x / y) * (x - y / x) *
16 * (01) (x^2 / sin(2 * pi / y)) - x / 2 *
17 * (02) sqrt(1 - (x^2)) *
18 * (03) 1 - sin(2 * x) + cos(pi / y) *
19 * (04) a * exp(2 * t) + c *
20 * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) *
21 * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
22 * (07) z := x + sin(2 * pi / y) *
23 * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
24 * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
25 * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) *
26 * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
27 * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
28 * *
29 ******************************************************************
30*/
31
32
33#ifndef INCLUDE_EXPRTK_HPP
34#define INCLUDE_EXPRTK_HPP
35
36
37#include <algorithm>
38#include <cassert>
39#include <cctype>
40#include <cmath>
41#include <complex>
42#include <cstdio>
43#include <cstdlib>
44#include <cstring>
45#include <deque>
46#include <exception>
47#include <functional>
48#include <iterator>
49#include <limits>
50#include <list>
51#include <map>
52#include <set>
53#include <stack>
54#include <stdexcept>
55#include <string>
56#include <utility>
57#include <vector>
58
59
60namespace exprtk
61{
62 #ifdef exprtk_enable_debugging
63 #define exprtk_debug(params) printf params
64 #else
65 #define exprtk_debug(params) (void)0
66 #endif
67
68 #define exprtk_error_location \
69 "exprtk.hpp:" + details::to_str(__LINE__) \
70
71 #if defined(__GNUC__) && (__GNUC__ >= 7)
72
73 #define exprtk_disable_fallthrough_begin \
74 _Pragma ("GCC diagnostic push") \
75 _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
76
77 #define exprtk_disable_fallthrough_end \
78 _Pragma ("GCC diagnostic pop") \
79
80 #else
81 #define exprtk_disable_fallthrough_begin (void)0;
82 #define exprtk_disable_fallthrough_end (void)0;
83 #endif
84
85 namespace details
86 {
87 typedef unsigned char uchar_t;
88 typedef char char_t;
90 typedef char_t* char_ptr;
91 typedef uchar_t const* uchar_cptr;
92 typedef char_t const* char_cptr;
93 typedef unsigned long long int _uint64_t;
94 typedef long long int _int64_t;
95
96 inline bool is_whitespace(const char_t c)
97 {
98 return (' ' == c) || ('\n' == c) ||
99 ('\r' == c) || ('\t' == c) ||
100 ('\b' == c) || ('\v' == c) ||
101 ('\f' == c) ;
102 }
103
104 inline bool is_operator_char(const char_t c)
105 {
106 return ('+' == c) || ('-' == c) ||
107 ('*' == c) || ('/' == c) ||
108 ('^' == c) || ('<' == c) ||
109 ('>' == c) || ('=' == c) ||
110 (',' == c) || ('!' == c) ||
111 ('(' == c) || (')' == c) ||
112 ('[' == c) || (']' == c) ||
113 ('{' == c) || ('}' == c) ||
114 ('%' == c) || (':' == c) ||
115 ('?' == c) || ('&' == c) ||
116 ('|' == c) || (';' == c) ;
117 }
118
119 inline bool is_letter(const char_t c)
120 {
121 return (('a' <= c) && (c <= 'z')) ||
122 (('A' <= c) && (c <= 'Z')) ;
123 }
124
125 inline bool is_digit(const char_t c)
126 {
127 return ('0' <= c) && (c <= '9');
128 }
129
130 inline bool is_letter_or_digit(const char_t c)
131 {
132 return is_letter(c) || is_digit(c);
133 }
134
135 inline bool is_left_bracket(const char_t c)
136 {
137 return ('(' == c) || ('[' == c) || ('{' == c);
138 }
139
140 inline bool is_right_bracket(const char_t c)
141 {
142 return (')' == c) || (']' == c) || ('}' == c);
143 }
144
145 inline bool is_bracket(const char_t c)
146 {
147 return is_left_bracket(c) || is_right_bracket(c);
148 }
149
150 inline bool is_sign(const char_t c)
151 {
152 return ('+' == c) || ('-' == c);
153 }
154
155 inline bool is_invalid(const char_t c)
156 {
157 return !is_whitespace (c) &&
158 !is_operator_char(c) &&
159 !is_letter (c) &&
160 !is_digit (c) &&
161 ('.' != c) &&
162 ('_' != c) &&
163 ('$' != c) &&
164 ('~' != c) &&
165 ('\'' != c);
166 }
167
168 inline bool is_valid_string_char(const char_t c)
169 {
170 return std::isprint(static_cast<unsigned char>(c)) ||
171 is_whitespace(c);
172 }
173
174 #ifndef exprtk_disable_caseinsensitivity
176 {
177 for (std::size_t i = 0; i < s.size(); ++i)
178 {
179 s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
180 }
181 }
182
183 inline bool imatch(const char_t c1, const char_t c2)
184 {
185 return std::tolower(c1) == std::tolower(c2);
186 }
187
188 inline bool imatch(const std::string& s1, const std::string& s2)
189 {
190 if (s1.size() == s2.size())
191 {
192 for (std::size_t i = 0; i < s1.size(); ++i)
193 {
194 if (std::tolower(s1[i]) != std::tolower(s2[i]))
195 {
196 return false;
197 }
198 }
199
200 return true;
201 }
202
203 return false;
204 }
205
207 {
208 inline bool operator() (const std::string& s1, const std::string& s2) const
209 {
210 const std::size_t length = std::min(s1.size(),s2.size());
211
212 for (std::size_t i = 0; i < length; ++i)
213 {
214 const char_t c1 = static_cast<char>(std::tolower(s1[i]));
215 const char_t c2 = static_cast<char>(std::tolower(s2[i]));
216
217 if (c1 > c2)
218 return false;
219 else if (c1 < c2)
220 return true;
221 }
222
223 return s1.size() < s2.size();
224 }
225 };
226
227 #else
228 inline void case_normalise(std::string&)
229 {}
230
231 inline bool imatch(const char_t c1, const char_t c2)
232 {
233 return c1 == c2;
234 }
235
236 inline bool imatch(const std::string& s1, const std::string& s2)
237 {
238 return s1 == s2;
239 }
240
241 struct ilesscompare
242 {
243 inline bool operator() (const std::string& s1, const std::string& s2) const
244 {
245 return s1 < s2;
246 }
247 };
248 #endif
249
250 inline bool is_valid_sf_symbol(const std::string& symbol)
251 {
252 // Special function: $f12 or $F34
253 return (4 == symbol.size()) &&
254 ('$' == symbol[0]) &&
255 imatch('f',symbol[1]) &&
256 is_digit(symbol[2]) &&
257 is_digit(symbol[3]);
258 }
259
260 inline const char_t& front(const std::string& s)
261 {
262 return s[0];
263 }
264
265 inline const char_t& back(const std::string& s)
266 {
267 return s[s.size() - 1];
268 }
269
270 inline std::string to_str(int i)
271 {
272 if (0 == i)
273 return std::string("0");
274
275 std::string result;
276
277 if (i < 0)
278 {
279 for ( ; i; i /= 10)
280 {
281 result += '0' + char(-(i % 10));
282 }
283
284 result += '-';
285 }
286 else
287 {
288 for ( ; i; i /= 10)
289 {
290 result += '0' + char(i % 10);
291 }
292 }
293
294 std::reverse(result.begin(), result.end());
295
296 return result;
297 }
298
299 inline std::string to_str(std::size_t i)
300 {
301 return to_str(static_cast<int>(i));
302 }
303
304 inline bool is_hex_digit(const std::string::value_type digit)
305 {
306 return (('0' <= digit) && (digit <= '9')) ||
307 (('A' <= digit) && (digit <= 'F')) ||
308 (('a' <= digit) && (digit <= 'f')) ;
309 }
310
312 {
313 if (('0' <= h) && (h <= '9'))
314 return (h - '0');
315 else
316 return static_cast<unsigned char>(std::toupper(h) - 'A');
317 }
318
319 template <typename Iterator>
320 inline bool parse_hex(Iterator& itr, Iterator end,
321 std::string::value_type& result)
322 {
323 if (
324 (end == (itr )) ||
325 (end == (itr + 1)) ||
326 (end == (itr + 2)) ||
327 (end == (itr + 3)) ||
328 ('0' != *(itr )) ||
329 ('X' != std::toupper(*(itr + 1))) ||
330 (!is_hex_digit(*(itr + 2))) ||
331 (!is_hex_digit(*(itr + 3)))
332 )
333 {
334 return false;
335 }
336
337 result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
338 hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
339
340 return true;
341 }
342
344 {
345 typedef std::string::iterator str_itr_t;
346
347 str_itr_t itr1 = s.begin();
348 str_itr_t itr2 = s.begin();
349 str_itr_t end = s.end ();
350
351 std::size_t removal_count = 0;
352
353 while (end != itr1)
354 {
355 if ('\\' == (*itr1))
356 {
357 if (end == ++itr1)
358 {
359 return false;
360 }
361 else if (parse_hex(itr1, end, *itr2))
362 {
363 itr1+= 4;
364 itr2+= 1;
365 removal_count +=4;
366 }
367 else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
368 else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
369 else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; }
370 else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; }
371 else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; }
372 else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; }
373 else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; }
374 else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; }
375 else
376 {
377 (*itr2++) = (*itr1++);
378 ++removal_count;
379 }
380 continue;
381 }
382 else
383 (*itr2++) = (*itr1++);
384 }
385
386 if ((removal_count > s.size()) || (0 == removal_count))
387 return false;
388
389 s.resize(s.size() - removal_count);
390
391 return true;
392 }
393
395 {
396 public:
397
398 build_string(const std::size_t& initial_size = 64)
399 {
400 data_.reserve(initial_size);
401 }
402
404 {
405 data_ += s;
406 return (*this);
407 }
408
410 {
411 data_ += std::string(s);
412 return (*this);
413 }
414
415 inline operator std::string () const
416 {
417 return data_;
418 }
419
420 inline std::string as_string() const
421 {
422 return data_;
423 }
424
425 private:
426
427 std::string data_;
428 };
429
431 {
432 "break", "case", "continue", "default", "false", "for",
433 "if", "else", "ilike", "in", "like", "and", "nand", "nor",
434 "not", "null", "or", "repeat", "return", "shl", "shr",
435 "swap", "switch", "true", "until", "var", "while", "xnor",
436 "xor", "&", "|"
437 };
438
439 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
440
442 {
443 "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
444 "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
445 "continue", "cos", "cosh", "cot", "csc", "default",
446 "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
447 "expm1", "false", "floor", "for", "frac", "grad2deg",
448 "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
449 "like", "log", "log10", "log2", "logn", "log1p", "mand",
450 "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
451 "not", "not_equal", "null", "or", "pow", "rad2deg",
452 "repeat", "return", "root", "round", "roundn", "sec", "sgn",
453 "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
454 "switch", "tan", "tanh", "true", "trunc", "until", "var",
455 "while", "xnor", "xor", "&", "|"
456 };
457
458 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
459
461 {
462 "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
463 "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
464 "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
465 "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
466 "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
467 "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
468 "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
469 "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
470 "rad2deg", "grad2deg"
471 };
472
473 static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
474
476 {
477 "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
478 };
479
480 static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
481
483 {
484 "if", "switch", "for", "while", "repeat", "return"
485 };
486
487 static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
488
490 {
491 "+", "-", "*", "/", "%", "^"
492 };
493
494 static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
495
497 {
498 ":=", "+=", "-=",
499 "*=", "/=", "%="
500 };
501
502 static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
503
505 {
506 "<", "<=", "==",
507 "=", "!=", "<>",
508 ">=", ">"
509 };
510
511 static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
512
513 inline bool is_reserved_word(const std::string& symbol)
514 {
515 for (std::size_t i = 0; i < reserved_words_size; ++i)
516 {
517 if (imatch(symbol, reserved_words[i]))
518 {
519 return true;
520 }
521 }
522
523 return false;
524 }
525
526 inline bool is_reserved_symbol(const std::string& symbol)
527 {
528 for (std::size_t i = 0; i < reserved_symbols_size; ++i)
529 {
530 if (imatch(symbol, reserved_symbols[i]))
531 {
532 return true;
533 }
534 }
535
536 return false;
537 }
538
539 inline bool is_base_function(const std::string& function_name)
540 {
541 for (std::size_t i = 0; i < base_function_list_size; ++i)
542 {
543 if (imatch(function_name, base_function_list[i]))
544 {
545 return true;
546 }
547 }
548
549 return false;
550 }
551
552 inline bool is_control_struct(const std::string& cntrl_strct)
553 {
554 for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
555 {
556 if (imatch(cntrl_strct, cntrl_struct_list[i]))
557 {
558 return true;
559 }
560 }
561
562 return false;
563 }
564
565 inline bool is_logic_opr(const std::string& lgc_opr)
566 {
567 for (std::size_t i = 0; i < logic_ops_list_size; ++i)
568 {
569 if (imatch(lgc_opr, logic_ops_list[i]))
570 {
571 return true;
572 }
573 }
574
575 return false;
576 }
577
578 struct cs_match
579 {
580 static inline bool cmp(const char_t c0, const char_t c1)
581 {
582 return (c0 == c1);
583 }
584 };
585
587 {
588 static inline bool cmp(const char_t c0, const char_t c1)
589 {
590 return (std::tolower(c0) == std::tolower(c1));
591 }
592 };
593
594 template <typename Iterator, typename Compare>
595 inline bool match_impl(const Iterator pattern_begin,
596 const Iterator pattern_end ,
597 const Iterator data_begin ,
598 const Iterator data_end ,
599 const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
600 const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
601 {
602 const Iterator null_itr(0);
603
604 Iterator d_itr = data_begin;
605 Iterator p_itr = pattern_begin;
606 Iterator tb_p_itr = null_itr;
607 Iterator tb_d_itr = null_itr;
608
609 while (d_itr != data_end)
610 {
611 if (zero_or_more == *p_itr)
612 {
613 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
614 {
615 ++p_itr;
616 }
617
618 if (pattern_end == p_itr)
619 return true;
620
621 const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
622
623 while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
624 {
625 ++d_itr;
626 }
627
628 tb_p_itr = p_itr;
629 tb_d_itr = d_itr;
630
631 continue;
632 }
633 else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
634 {
635 if (null_itr == tb_d_itr)
636 return false;
637
638 d_itr = tb_d_itr++;
639 p_itr = tb_p_itr;
640
641 continue;
642 }
643
644 ++p_itr;
645 ++d_itr;
646 }
647
648 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
649 {
650 ++p_itr;
651 }
652
653 return (pattern_end == p_itr);
654 }
655
656 inline bool wc_match(const std::string& wild_card,
657 const std::string& str)
658 {
659 return match_impl<char_cptr,cs_match>(
660 wild_card.data(), wild_card.data() + wild_card.size(),
661 str.data(), str.data() + str.size(),
662 '*', '?');
663 }
664
665 inline bool wc_imatch(const std::string& wild_card,
666 const std::string& str)
667 {
668 return match_impl<char_cptr,cis_match>(
669 wild_card.data(), wild_card.data() + wild_card.size(),
670 str.data(), str.data() + str.size(),
671 '*', '?');
672 }
673
674 inline bool sequence_match(const std::string& pattern,
675 const std::string& str,
676 std::size_t& diff_index,
677 char_t& diff_value)
678 {
679 if (str.empty())
680 {
681 return ("Z" == pattern);
682 }
683 else if ('*' == pattern[0])
684 return false;
685
686 typedef std::string::const_iterator itr_t;
687
688 itr_t p_itr = pattern.begin();
689 itr_t s_itr = str .begin();
690
691 itr_t p_end = pattern.end();
692 itr_t s_end = str .end();
693
694 while ((s_end != s_itr) && (p_end != p_itr))
695 {
696 if ('*' == (*p_itr))
697 {
698 const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
699
700 if ('*' == target)
701 {
702 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
703 diff_value = static_cast<char>(std::toupper(*p_itr));
704
705 return false;
706 }
707 else
708 ++p_itr;
709
710 while (s_itr != s_end)
711 {
712 if (target != std::toupper(*s_itr))
713 break;
714 else
715 ++s_itr;
716 }
717
718 continue;
719 }
720 else if (
721 ('?' != *p_itr) &&
722 std::toupper(*p_itr) != std::toupper(*s_itr)
723 )
724 {
725 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
726 diff_value = static_cast<char>(std::toupper(*p_itr));
727
728 return false;
729 }
730
731 ++p_itr;
732 ++s_itr;
733 }
734
735 return (
736 (s_end == s_itr) &&
737 (
738 (p_end == p_itr) ||
739 ('*' == *p_itr)
740 )
741 );
742 }
743
744 static const double pow10[] = {
745 1.0,
746 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
747 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
748 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
749 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
750 };
751
752 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
753
754 namespace numeric
755 {
756 namespace constant
757 {
758 static const double e = 2.71828182845904523536028747135266249775724709369996;
759 static const double pi = 3.14159265358979323846264338327950288419716939937510;
760 static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
761 static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
762 static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
763 static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
764 static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
765 static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
766 static const double log2 = 0.69314718055994530941723212145817656807550013436026;
767 static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
768 }
769
770 namespace details
771 {
773 struct real_type_tag { real_type_tag () {} };
775 struct int_type_tag { int_type_tag () {} };
776
777 template <typename T>
779 {
782 };
783
784 #define exprtk_register_real_type_tag(T) \
785 template <> struct number_type<T> \
786 { typedef real_type_tag type; number_type() {} }; \
787
788 #define exprtk_register_complex_type_tag(T) \
789 template <> struct number_type<std::complex<T> > \
790 { typedef complex_type_tag type; number_type() {} }; \
791
792 #define exprtk_register_int_type_tag(T) \
793 template <> struct number_type<T> \
794 { typedef int_type_tag type; number_type() {} }; \
795
799
803
807 exprtk_register_int_type_tag(unsigned short)
808 exprtk_register_int_type_tag(unsigned int )
810
811 #undef exprtk_register_real_type_tag
812 #undef exprtk_register_int_type_tag
813
814 template <typename T>
815 struct epsilon_type {};
816
817 #define exprtk_define_epsilon_type(Type, Epsilon) \
818 template <> struct epsilon_type<Type> \
819 { \
820 static inline Type value() \
821 { \
822 const Type epsilon = static_cast<Type>(Epsilon); \
823 return epsilon; \
824 } \
825 }; \
826
827 exprtk_define_epsilon_type(float , 0.000001f)
828 exprtk_define_epsilon_type(double , 0.0000000001)
829 exprtk_define_epsilon_type(long double, 0.000000000001)
830
831 #undef exprtk_define_epsilon_type
832
833 template <typename T>
834 inline bool is_nan_impl(const T v, real_type_tag)
835 {
836 return std::not_equal_to<T>()(v,v);
837 }
838
839 template <typename T>
840 inline int to_int32_impl(const T v, real_type_tag)
841 {
842 return static_cast<int>(v);
843 }
844
845 template <typename T>
847 {
848 return static_cast<_int64_t>(v);
849 }
850
851 template <typename T>
852 inline bool is_true_impl(const T v)
853 {
854 return std::not_equal_to<T>()(T(0),v);
855 }
856
857 template <typename T>
858 inline bool is_false_impl(const T v)
859 {
860 return std::equal_to<T>()(T(0),v);
861 }
862
863 template <typename T>
864 inline T abs_impl(const T v, real_type_tag)
865 {
866 return ((v < T(0)) ? -v : v);
867 }
868
869 template <typename T>
870 inline T min_impl(const T v0, const T v1, real_type_tag)
871 {
872 return std::min<T>(v0,v1);
873 }
874
875 template <typename T>
876 inline T max_impl(const T v0, const T v1, real_type_tag)
877 {
878 return std::max<T>(v0,v1);
879 }
880
881 template <typename T>
882 inline T equal_impl(const T v0, const T v1, real_type_tag)
883 {
884 const T epsilon = epsilon_type<T>::value();
885 return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
886 }
887
888 inline float equal_impl(const float v0, const float v1, real_type_tag)
889 {
890 const float epsilon = epsilon_type<float>::value();
891 return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
892 }
893
894 template <typename T>
895 inline T equal_impl(const T v0, const T v1, int_type_tag)
896 {
897 return (v0 == v1) ? 1 : 0;
898 }
899
900 template <typename T>
901 inline T expm1_impl(const T v, real_type_tag)
902 {
903 // return std::expm1<T>(v);
904 if (abs_impl(v,real_type_tag()) < T(0.00001))
905 return v + (T(0.5) * v * v);
906 else
907 return std::exp(v) - T(1);
908 }
909
910 template <typename T>
911 inline T expm1_impl(const T v, int_type_tag)
912 {
913 return T(std::exp<double>(v)) - T(1);
914 }
915
916 template <typename T>
917 inline T nequal_impl(const T v0, const T v1, real_type_tag)
918 {
919 typedef real_type_tag rtg;
920 const T epsilon = epsilon_type<T>::value();
921 return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
922 }
923
924 inline float nequal_impl(const float v0, const float v1, real_type_tag)
925 {
926 typedef real_type_tag rtg;
927 const float epsilon = epsilon_type<float>::value();
928 return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
929 }
930
931 template <typename T>
932 inline T nequal_impl(const T v0, const T v1, int_type_tag)
933 {
934 return (v0 != v1) ? 1 : 0;
935 }
936
937 template <typename T>
938 inline T modulus_impl(const T v0, const T v1, real_type_tag)
939 {
940 return std::fmod(v0,v1);
941 }
942
943 template <typename T>
944 inline T modulus_impl(const T v0, const T v1, int_type_tag)
945 {
946 return v0 % v1;
947 }
948
949 template <typename T>
950 inline T pow_impl(const T v0, const T v1, real_type_tag)
951 {
952 return std::pow(v0,v1);
953 }
954
955 template <typename T>
956 inline T pow_impl(const T v0, const T v1, int_type_tag)
957 {
958 return std::pow(static_cast<double>(v0),static_cast<double>(v1));
959 }
960
961 template <typename T>
962 inline T logn_impl(const T v0, const T v1, real_type_tag)
963 {
964 return std::log(v0) / std::log(v1);
965 }
966
967 template <typename T>
968 inline T logn_impl(const T v0, const T v1, int_type_tag)
969 {
970 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
971 }
972
973 template <typename T>
974 inline T log1p_impl(const T v, real_type_tag)
975 {
976 if (v > T(-1))
977 {
978 if (abs_impl(v,real_type_tag()) > T(0.0001))
979 {
980 return std::log(T(1) + v);
981 }
982 else
983 return (T(-0.5) * v + T(1)) * v;
984 }
985 else
986 return std::numeric_limits<T>::quiet_NaN();
987 }
988
989 template <typename T>
990 inline T log1p_impl(const T v, int_type_tag)
991 {
992 if (v > T(-1))
993 {
994 return std::log(T(1) + v);
995 }
996 else
997 return std::numeric_limits<T>::quiet_NaN();
998 }
999
1000 template <typename T>
1001 inline T root_impl(const T v0, const T v1, real_type_tag)
1002 {
1003 if (v1 < T(0))
1004 return std::numeric_limits<T>::quiet_NaN();
1005
1006 const std::size_t n = static_cast<std::size_t>(v1);
1007
1008 if ((v0 < T(0)) && (0 == (n % 2)))
1009 return std::numeric_limits<T>::quiet_NaN();
1010
1011 return std::pow(v0, T(1) / n);
1012 }
1013
1014 template <typename T>
1015 inline T root_impl(const T v0, const T v1, int_type_tag)
1016 {
1017 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1018 }
1019
1020 template <typename T>
1021 inline T round_impl(const T v, real_type_tag)
1022 {
1023 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1024 }
1025
1026 template <typename T>
1027 inline T roundn_impl(const T v0, const T v1, real_type_tag)
1028 {
1029 const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1))));
1030 const T p10 = T(pow10[index]);
1031
1032 if (v0 < T(0))
1033 return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1034 else
1035 return T(std::floor((v0 * p10) + T(0.5)) / p10);
1036 }
1037
1038 template <typename T>
1039 inline T roundn_impl(const T v0, const T, int_type_tag)
1040 {
1041 return v0;
1042 }
1043
1044 template <typename T>
1045 inline T hypot_impl(const T v0, const T v1, real_type_tag)
1046 {
1047 return std::sqrt((v0 * v0) + (v1 * v1));
1048 }
1049
1050 template <typename T>
1051 inline T hypot_impl(const T v0, const T v1, int_type_tag)
1052 {
1053 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1054 }
1055
1056 template <typename T>
1057 inline T atan2_impl(const T v0, const T v1, real_type_tag)
1058 {
1059 return std::atan2(v0,v1);
1060 }
1061
1062 template <typename T>
1063 inline T atan2_impl(const T, const T, int_type_tag)
1064 {
1065 return 0;
1066 }
1067
1068 template <typename T>
1069 inline T shr_impl(const T v0, const T v1, real_type_tag)
1070 {
1071 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1072 }
1073
1074 template <typename T>
1075 inline T shr_impl(const T v0, const T v1, int_type_tag)
1076 {
1077 return v0 >> v1;
1078 }
1079
1080 template <typename T>
1081 inline T shl_impl(const T v0, const T v1, real_type_tag)
1082 {
1083 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1084 }
1085
1086 template <typename T>
1087 inline T shl_impl(const T v0, const T v1, int_type_tag)
1088 {
1089 return v0 << v1;
1090 }
1091
1092 template <typename T>
1093 inline T sgn_impl(const T v, real_type_tag)
1094 {
1095 if (v > T(0)) return T(+1);
1096 else if (v < T(0)) return T(-1);
1097 else return T( 0);
1098 }
1099
1100 template <typename T>
1101 inline T sgn_impl(const T v, int_type_tag)
1102 {
1103 if (v > T(0)) return T(+1);
1104 else if (v < T(0)) return T(-1);
1105 else return T( 0);
1106 }
1107
1108 template <typename T>
1109 inline T and_impl(const T v0, const T v1, real_type_tag)
1110 {
1111 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1112 }
1113
1114 template <typename T>
1115 inline T and_impl(const T v0, const T v1, int_type_tag)
1116 {
1117 return v0 && v1;
1118 }
1119
1120 template <typename T>
1121 inline T nand_impl(const T v0, const T v1, real_type_tag)
1122 {
1123 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1124 }
1125
1126 template <typename T>
1127 inline T nand_impl(const T v0, const T v1, int_type_tag)
1128 {
1129 return !(v0 && v1);
1130 }
1131
1132 template <typename T>
1133 inline T or_impl(const T v0, const T v1, real_type_tag)
1134 {
1135 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1136 }
1137
1138 template <typename T>
1139 inline T or_impl(const T v0, const T v1, int_type_tag)
1140 {
1141 return (v0 || v1);
1142 }
1143
1144 template <typename T>
1145 inline T nor_impl(const T v0, const T v1, real_type_tag)
1146 {
1147 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1148 }
1149
1150 template <typename T>
1151 inline T nor_impl(const T v0, const T v1, int_type_tag)
1152 {
1153 return !(v0 || v1);
1154 }
1155
1156 template <typename T>
1157 inline T xor_impl(const T v0, const T v1, real_type_tag)
1158 {
1159 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1160 }
1161
1162 template <typename T>
1163 inline T xor_impl(const T v0, const T v1, int_type_tag)
1164 {
1165 return v0 ^ v1;
1166 }
1167
1168 template <typename T>
1169 inline T xnor_impl(const T v0, const T v1, real_type_tag)
1170 {
1171 const bool v0_true = is_true_impl(v0);
1172 const bool v1_true = is_true_impl(v1);
1173
1174 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1175 return T(1);
1176 else
1177 return T(0);
1178 }
1179
1180 template <typename T>
1181 inline T xnor_impl(const T v0, const T v1, int_type_tag)
1182 {
1183 const bool v0_true = is_true_impl(v0);
1184 const bool v1_true = is_true_impl(v1);
1185
1186 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1187 return T(1);
1188 else
1189 return T(0);
1190 }
1191
1192 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1193 #define exprtk_define_erf(TT,impl) \
1194 inline TT erf_impl(TT v) { return impl(v); } \
1195
1196 exprtk_define_erf( float,::erff)
1197 exprtk_define_erf( double,::erf )
1198 exprtk_define_erf(long double,::erfl)
1199 #undef exprtk_define_erf
1200 #endif
1201
1202 template <typename T>
1203 inline T erf_impl(T v, real_type_tag)
1204 {
1205 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1206 // Credits: Abramowitz & Stegun Equations 7.1.25-28
1207 static const T c[] = {
1208 T( 1.26551223), T(1.00002368),
1209 T( 0.37409196), T(0.09678418),
1210 T(-0.18628806), T(0.27886807),
1211 T(-1.13520398), T(1.48851587),
1212 T(-0.82215223), T(0.17087277)
1213 };
1214
1215 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1216
1217 T result = T(1) - t * std::exp((-v * v) -
1218 c[0] + t * (c[1] + t *
1219 (c[2] + t * (c[3] + t *
1220 (c[4] + t * (c[5] + t *
1221 (c[6] + t * (c[7] + t *
1222 (c[8] + t * (c[9]))))))))));
1223
1224 return (v >= T(0)) ? result : -result;
1225 #else
1226 return erf_impl(v);
1227 #endif
1228 }
1229
1230 template <typename T>
1231 inline T erf_impl(T v, int_type_tag)
1232 {
1233 return erf_impl(static_cast<double>(v),real_type_tag());
1234 }
1235
1236 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1237 #define exprtk_define_erfc(TT,impl) \
1238 inline TT erfc_impl(TT v) { return impl(v); } \
1239
1240 exprtk_define_erfc( float,::erfcf)
1241 exprtk_define_erfc( double,::erfc )
1242 exprtk_define_erfc(long double,::erfcl)
1243 #undef exprtk_define_erfc
1244 #endif
1245
1246 template <typename T>
1247 inline T erfc_impl(T v, real_type_tag)
1248 {
1249 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1250 return T(1) - erf_impl(v,real_type_tag());
1251 #else
1252 return erfc_impl(v);
1253 #endif
1254 }
1255
1256 template <typename T>
1258 {
1259 return erfc_impl(static_cast<double>(v),real_type_tag());
1260 }
1261
1262 template <typename T>
1264 {
1265 T cnd = T(0.5) * (T(1) + erf_impl(
1266 abs_impl(v,real_type_tag()) /
1268 return (v < T(0)) ? (T(1) - cnd) : cnd;
1269 }
1270
1271 template <typename T>
1273 {
1274 return ncdf_impl(static_cast<double>(v),real_type_tag());
1275 }
1276
1277 template <typename T>
1279 {
1280 if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1281 return(std::sin(v) / v);
1282 else
1283 return T(1);
1284 }
1285
1286 template <typename T>
1288 {
1289 return sinc_impl(static_cast<double>(v),real_type_tag());
1290 }
1291
1292 template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
1293 template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
1294 template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
1295 template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
1296 template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
1297 template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
1298 template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1299 template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
1300 template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1301 template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
1302 template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1303 template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
1304 template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1305 template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1306 template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
1307 template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
1308 template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
1309 template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1310 template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1311 template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
1312 template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1313 template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1314 template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1315 template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1316 template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1317 template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
1318 template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
1319 template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
1320 template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
1321 template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1322 template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
1323
1324 template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1325 template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); }
1326
1327 template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1328 template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
1329 template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
1330 template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1331 template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1332 template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
1333 template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
1334 template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
1335 template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
1336 template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
1337 template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
1338 template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1339 template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
1340 template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
1341 template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1342 template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1343 template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1344 template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1345 template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1346 template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1347 template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1348 template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1349 template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1350 template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1351 template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1352 template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1353 template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1354 template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1355 template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356
1357 template <typename T>
1358 inline bool is_integer_impl(const T& v, real_type_tag)
1359 {
1360 return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1361 }
1362
1363 template <typename T>
1364 inline bool is_integer_impl(const T&, int_type_tag)
1365 {
1366 return true;
1367 }
1368 }
1369
1370 template <typename Type>
1371 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1372
1373 template <> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
1374 template <> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
1375 template <> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
1376 template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1377
1378 template <typename T>
1379 inline int to_int32(const T v)
1380 {
1381 const typename details::number_type<T>::type num_type;
1382 return to_int32_impl(v, num_type);
1383 }
1384
1385 template <typename T>
1386 inline _int64_t to_int64(const T v)
1387 {
1388 const typename details::number_type<T>::type num_type;
1389 return to_int64_impl(v, num_type);
1390 }
1391
1392 template <typename T>
1393 inline bool is_nan(const T v)
1394 {
1395 const typename details::number_type<T>::type num_type;
1396 return is_nan_impl(v, num_type);
1397 }
1398
1399 template <typename T>
1400 inline T min(const T v0, const T v1)
1401 {
1402 const typename details::number_type<T>::type num_type;
1403 return min_impl(v0, v1, num_type);
1404 }
1405
1406 template <typename T>
1407 inline T max(const T v0, const T v1)
1408 {
1409 const typename details::number_type<T>::type num_type;
1410 return max_impl(v0, v1, num_type);
1411 }
1412
1413 template <typename T>
1414 inline T equal(const T v0, const T v1)
1415 {
1416 const typename details::number_type<T>::type num_type;
1417 return equal_impl(v0, v1, num_type);
1418 }
1419
1420 template <typename T>
1421 inline T nequal(const T v0, const T v1)
1422 {
1423 const typename details::number_type<T>::type num_type;
1424 return nequal_impl(v0, v1, num_type);
1425 }
1426
1427 template <typename T>
1428 inline T modulus(const T v0, const T v1)
1429 {
1430 const typename details::number_type<T>::type num_type;
1431 return modulus_impl(v0, v1, num_type);
1432 }
1433
1434 template <typename T>
1435 inline T pow(const T v0, const T v1)
1436 {
1437 const typename details::number_type<T>::type num_type;
1438 return pow_impl(v0, v1, num_type);
1439 }
1440
1441 template <typename T>
1442 inline T logn(const T v0, const T v1)
1443 {
1444 const typename details::number_type<T>::type num_type;
1445 return logn_impl(v0, v1, num_type);
1446 }
1447
1448 template <typename T>
1449 inline T root(const T v0, const T v1)
1450 {
1451 const typename details::number_type<T>::type num_type;
1452 return root_impl(v0, v1, num_type);
1453 }
1454
1455 template <typename T>
1456 inline T roundn(const T v0, const T v1)
1457 {
1458 const typename details::number_type<T>::type num_type;
1459 return roundn_impl(v0, v1, num_type);
1460 }
1461
1462 template <typename T>
1463 inline T hypot(const T v0, const T v1)
1464 {
1465 const typename details::number_type<T>::type num_type;
1466 return hypot_impl(v0, v1, num_type);
1467 }
1468
1469 template <typename T>
1470 inline T atan2(const T v0, const T v1)
1471 {
1472 const typename details::number_type<T>::type num_type;
1473 return atan2_impl(v0, v1, num_type);
1474 }
1475
1476 template <typename T>
1477 inline T shr(const T v0, const T v1)
1478 {
1479 const typename details::number_type<T>::type num_type;
1480 return shr_impl(v0, v1, num_type);
1481 }
1482
1483 template <typename T>
1484 inline T shl(const T v0, const T v1)
1485 {
1486 const typename details::number_type<T>::type num_type;
1487 return shl_impl(v0, v1, num_type);
1488 }
1489
1490 template <typename T>
1491 inline T and_opr(const T v0, const T v1)
1492 {
1493 const typename details::number_type<T>::type num_type;
1494 return and_impl(v0, v1, num_type);
1495 }
1496
1497 template <typename T>
1498 inline T nand_opr(const T v0, const T v1)
1499 {
1500 const typename details::number_type<T>::type num_type;
1501 return nand_impl(v0, v1, num_type);
1502 }
1503
1504 template <typename T>
1505 inline T or_opr(const T v0, const T v1)
1506 {
1507 const typename details::number_type<T>::type num_type;
1508 return or_impl(v0, v1, num_type);
1509 }
1510
1511 template <typename T>
1512 inline T nor_opr(const T v0, const T v1)
1513 {
1514 const typename details::number_type<T>::type num_type;
1515 return nor_impl(v0, v1, num_type);
1516 }
1517
1518 template <typename T>
1519 inline T xor_opr(const T v0, const T v1)
1520 {
1521 const typename details::number_type<T>::type num_type;
1522 return xor_impl(v0, v1, num_type);
1523 }
1524
1525 template <typename T>
1526 inline T xnor_opr(const T v0, const T v1)
1527 {
1528 const typename details::number_type<T>::type num_type;
1529 return xnor_impl(v0, v1, num_type);
1530 }
1531
1532 template <typename T>
1533 inline bool is_integer(const T v)
1534 {
1535 const typename details::number_type<T>::type num_type;
1536 return is_integer_impl(v, num_type);
1537 }
1538
1539 template <typename T, unsigned int N>
1541 {
1542 static inline T result(T v)
1543 {
1544 unsigned int k = N;
1545 T l = T(1);
1546
1547 while (k)
1548 {
1549 if (k & 1)
1550 {
1551 l *= v;
1552 --k;
1553 }
1554
1555 v *= v;
1556 k >>= 1;
1557 }
1558
1559 return l;
1560 }
1561 };
1562
1563 template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
1564 template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
1565 template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
1566 template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
1567 template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
1568 template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
1569 template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
1570 template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
1571 template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
1572 template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
1573 template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
1574
1575 #define exprtk_define_unary_function(FunctionName) \
1576 template <typename T> \
1577 inline T FunctionName (const T v) \
1578 { \
1579 const typename details::number_type<T>::type num_type; \
1580 return FunctionName##_impl(v,num_type); \
1581 } \
1582
1623 #undef exprtk_define_unary_function
1624 }
1625
1626 template <typename T>
1627 inline T compute_pow10(T d, const int exponent)
1628 {
1629 static const double fract10[] =
1630 {
1631 0.0,
1632 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
1633 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
1634 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
1635 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
1636 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
1637 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
1638 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
1639 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
1640 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
1641 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
1642 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
1643 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
1644 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
1645 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
1646 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
1647 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
1648 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
1649 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
1650 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
1651 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
1652 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
1653 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
1654 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
1655 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
1656 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
1657 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
1658 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
1659 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
1660 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
1661 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
1662 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1663 };
1664
1665 static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1666
1667 const int e = std::abs(exponent);
1668
1669 if (exponent >= std::numeric_limits<T>::min_exponent10)
1670 {
1671 if (e < fract10_size)
1672 {
1673 if (exponent > 0)
1674 return T(d * fract10[e]);
1675 else
1676 return T(d / fract10[e]);
1677 }
1678 else
1679 return T(d * std::pow(10.0, 10.0 * exponent));
1680 }
1681 else
1682 {
1683 d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1684 return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1685 }
1686 }
1687
1688 template <typename Iterator, typename T>
1689 inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1690 {
1691 if (itr == end)
1692 return false;
1693
1694 const bool negative = ('-' == (*itr));
1695
1696 if (negative || ('+' == (*itr)))
1697 {
1698 if (end == ++itr)
1699 return false;
1700 }
1701
1702 static const uchar_t zero = static_cast<uchar_t>('0');
1703
1704 while ((end != itr) && (zero == (*itr))) ++itr;
1705
1706 bool return_result = true;
1707 unsigned int digit = 0;
1708 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1709
1710 if (length <= 4)
1711 {
1713 switch (length)
1714 {
1715 #ifdef exprtk_use_lut
1716
1717 #define exprtk_process_digit \
1718 if ((digit = details::digit_table[(int)*itr++]) < 10) \
1719 result = result * 10 + (digit); \
1720 else \
1721 { \
1722 return_result = false; \
1723 break; \
1724 } \
1725
1726 #else
1727
1728 #define exprtk_process_digit \
1729 if ((digit = (*itr++ - zero)) < 10) \
1730 result = result * T(10) + digit; \
1731 else \
1732 { \
1733 return_result = false; \
1734 break; \
1735 } \
1736
1737 #endif
1738
1739 case 4 : exprtk_process_digit
1740 case 3 : exprtk_process_digit
1741 case 2 : exprtk_process_digit
1742 case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1743
1744 #undef exprtk_process_digit
1745 }
1747 }
1748 else
1749 return_result = false;
1750
1751 if (length && return_result)
1752 {
1753 result = result * 10 + static_cast<T>(digit);
1754 ++itr;
1755 }
1756
1757 result = negative ? -result : result;
1758 return return_result;
1759 }
1760
1761 template <typename Iterator, typename T>
1762 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1763 {
1764 typedef typename std::iterator_traits<Iterator>::value_type type;
1765
1766 static const std::size_t nan_length = 3;
1767
1768 if (std::distance(itr,end) != static_cast<int>(nan_length))
1769 return false;
1770
1771 if (static_cast<type>('n') == (*itr))
1772 {
1773 if (
1774 (static_cast<type>('a') != *(itr + 1)) ||
1775 (static_cast<type>('n') != *(itr + 2))
1776 )
1777 {
1778 return false;
1779 }
1780 }
1781 else if (
1782 (static_cast<type>('A') != *(itr + 1)) ||
1783 (static_cast<type>('N') != *(itr + 2))
1784 )
1785 {
1786 return false;
1787 }
1788
1789 t = std::numeric_limits<T>::quiet_NaN();
1790
1791 return true;
1792 }
1793
1794 template <typename Iterator, typename T>
1795 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1796 {
1797 static const char_t inf_uc[] = "INFINITY";
1798 static const char_t inf_lc[] = "infinity";
1799 static const std::size_t inf_length = 8;
1800
1801 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1802
1803 if ((3 != length) && (inf_length != length))
1804 return false;
1805
1806 char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1807
1808 while (end != itr)
1809 {
1810 if (*inf_itr == static_cast<char>(*itr))
1811 {
1812 ++itr;
1813 ++inf_itr;
1814 continue;
1815 }
1816 else
1817 return false;
1818 }
1819
1820 if (negative)
1821 t = -std::numeric_limits<T>::infinity();
1822 else
1823 t = std::numeric_limits<T>::infinity();
1824
1825 return true;
1826 }
1827
1828 template <typename T>
1829 inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
1830 {
1831 using namespace details::numeric;
1832 return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
1833 }
1834
1835 template <typename Iterator, typename T>
1836 inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1837 {
1838 if (end == itr_external) return false;
1839
1840 Iterator itr = itr_external;
1841
1842 T d = T(0);
1843
1844 const bool negative = ('-' == (*itr));
1845
1846 if (negative || '+' == (*itr))
1847 {
1848 if (end == ++itr)
1849 return false;
1850 }
1851
1852 bool instate = false;
1853
1854 static const char_t zero = static_cast<uchar_t>('0');
1855
1856 #define parse_digit_1(d) \
1857 if ((digit = (*itr - zero)) < 10) \
1858 { d = d * T(10) + digit; } \
1859 else \
1860 { break; } \
1861 if (end == ++itr) break; \
1862
1863 #define parse_digit_2(d) \
1864 if ((digit = (*itr - zero)) < 10) \
1865 { d = d * T(10) + digit; } \
1866 else { break; } \
1867 ++itr; \
1868
1869 if ('.' != (*itr))
1870 {
1871 const Iterator curr = itr;
1872
1873 while ((end != itr) && (zero == (*itr))) ++itr;
1874
1875 while (end != itr)
1876 {
1877 unsigned int digit;
1878 parse_digit_1(d)
1879 parse_digit_1(d)
1880 parse_digit_2(d)
1881 }
1882
1883 if (curr != itr) instate = true;
1884 }
1885
1886 int exponent = 0;
1887
1888 if (end != itr)
1889 {
1890 if ('.' == (*itr))
1891 {
1892 const Iterator curr = ++itr;
1893 T tmp_d = T(0);
1894
1895 while (end != itr)
1896 {
1897 unsigned int digit;
1898 parse_digit_1(tmp_d)
1899 parse_digit_1(tmp_d)
1900 parse_digit_2(tmp_d)
1901 }
1902
1903 if (curr != itr)
1904 {
1905 instate = true;
1906
1907 const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
1908
1909 if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
1910 return false;
1911
1912 d += compute_pow10(tmp_d, frac_exponent);
1913 }
1914
1915 #undef parse_digit_1
1916 #undef parse_digit_2
1917 }
1918
1919 if (end != itr)
1920 {
1921 typename std::iterator_traits<Iterator>::value_type c = (*itr);
1922
1923 if (('e' == c) || ('E' == c))
1924 {
1925 int exp = 0;
1926
1927 if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1928 {
1929 if (end == itr)
1930 return false;
1931 else
1932 c = (*itr);
1933 }
1934
1935 exponent += exp;
1936 }
1937
1938 if (end != itr)
1939 {
1940 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1941 ++itr;
1942 else if ('#' == c)
1943 {
1944 if (end == ++itr)
1945 return false;
1946 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1947 {
1948 if (('i' == (*itr)) || ('I' == (*itr)))
1949 {
1950 return parse_inf(itr, end, t, negative);
1951 }
1952 else if (('n' == (*itr)) || ('N' == (*itr)))
1953 {
1954 return parse_nan(itr, end, t);
1955 }
1956 else
1957 return false;
1958 }
1959 else
1960 return false;
1961 }
1962 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1963 {
1964 if (('i' == (*itr)) || ('I' == (*itr)))
1965 {
1966 return parse_inf(itr, end, t, negative);
1967 }
1968 else if (('n' == (*itr)) || ('N' == (*itr)))
1969 {
1970 return parse_nan(itr, end, t);
1971 }
1972 else
1973 return false;
1974 }
1975 else
1976 return false;
1977 }
1978 }
1979 }
1980
1981 if ((end != itr) || (!instate))
1982 return false;
1983 else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
1984 return false;
1985 else if (exponent)
1986 d = compute_pow10(d,exponent);
1987
1988 t = static_cast<T>((negative) ? -d : d);
1989 return true;
1990 }
1991
1992 template <typename T>
1993 inline bool string_to_real(const std::string& s, T& t)
1994 {
1995 const typename numeric::details::number_type<T>::type num_type;
1996
1997 char_cptr begin = s.data();
1998 char_cptr end = s.data() + s.size();
1999
2000 return string_to_real(begin, end, t, num_type);
2001 }
2002
2003 template <typename T>
2005 {
2006 /*
2007 Note: The following definitions for Type, may require tweaking
2008 based on the compiler and target architecture. The benchmark
2009 should provide enough information to make the right choice.
2010 */
2011 //typedef T Type;
2012 //typedef const T Type;
2013 typedef const T& Type;
2014 typedef T& RefType;
2015 typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2016 typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2017 typedef T (*bfunc_t)(Type t0, Type t1);
2018 typedef T (*ufunc_t)(Type t0);
2019 };
2020
2021 } // namespace details
2022
2024 {
2026 {
2031 e_all_loops = 7
2033
2035 {
2038 e_timeout = 2
2040
2042
2046 {}
2047
2049
2051 {
2055 };
2056
2058 {
2059 throw std::runtime_error("ExprTk Loop run-time violation.");
2060 }
2061
2063 };
2064
2066
2067 namespace lexer
2068 {
2069 struct token
2070 {
2072 {
2075 e_eof = 6, e_number = 7, e_symbol = 8,
2076 e_string = 9, e_assign = 10, e_addass = 11,
2077 e_subass = 12, e_mulass = 13, e_divass = 14,
2078 e_modass = 15, e_shr = 16, e_shl = 17,
2079 e_lte = 18, e_ne = 19, e_gte = 20,
2080 e_swap = 21, e_lt = '<', e_gt = '>',
2081 e_eq = '=', e_rbracket = ')', e_lbracket = '(',
2083 e_lcrlbracket = '{', e_comma = ',', e_add = '+',
2084 e_sub = '-', e_div = '/', e_mul = '*',
2085 e_mod = '%', e_pow = '^', e_colon = ':',
2086 e_ternary = '?'
2088
2090 : type(e_none),
2091 value(""),
2092 position(std::numeric_limits<std::size_t>::max())
2093 {}
2094
2095 void clear()
2096 {
2097 type = e_none;
2098 value = "";
2100 }
2101
2102 template <typename Iterator>
2104 const Iterator begin, const Iterator end,
2105 const Iterator base_begin = Iterator(0))
2106 {
2107 type = tt;
2108 value.assign(begin,end);
2109 if (base_begin)
2110 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2111 return (*this);
2112 }
2113
2114 template <typename Iterator>
2115 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2116 {
2117 type = e_symbol;
2118 value.assign(begin,end);
2119 if (base_begin)
2120 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2121 return (*this);
2122 }
2123
2124 template <typename Iterator>
2125 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2126 {
2127 type = e_number;
2128 value.assign(begin,end);
2129 if (base_begin)
2130 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2131 return (*this);
2132 }
2133
2134 template <typename Iterator>
2135 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2136 {
2137 type = e_string;
2138 value.assign(begin,end);
2139 if (base_begin)
2140 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2141 return (*this);
2142 }
2143
2144 inline token& set_string(const std::string& s, const std::size_t p)
2145 {
2146 type = e_string;
2147 value = s;
2148 position = p;
2149 return (*this);
2150 }
2151
2152 template <typename Iterator>
2153 inline token& set_error(const token_type et,
2154 const Iterator begin, const Iterator end,
2155 const Iterator base_begin = Iterator(0))
2156 {
2157 if (
2158 (e_error == et) ||
2159 (e_err_symbol == et) ||
2160 (e_err_number == et) ||
2161 (e_err_string == et) ||
2162 (e_err_sfunc == et)
2163 )
2164 {
2165 type = et;
2166 }
2167 else
2168 type = e_error;
2169
2170 value.assign(begin,end);
2171
2172 if (base_begin)
2173 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2174
2175 return (*this);
2176 }
2177
2179 {
2180 switch (t)
2181 {
2182 case e_none : return "NONE";
2183 case e_error : return "ERROR";
2184 case e_err_symbol : return "ERROR_SYMBOL";
2185 case e_err_number : return "ERROR_NUMBER";
2186 case e_err_string : return "ERROR_STRING";
2187 case e_eof : return "EOF";
2188 case e_number : return "NUMBER";
2189 case e_symbol : return "SYMBOL";
2190 case e_string : return "STRING";
2191 case e_assign : return ":=";
2192 case e_addass : return "+=";
2193 case e_subass : return "-=";
2194 case e_mulass : return "*=";
2195 case e_divass : return "/=";
2196 case e_modass : return "%=";
2197 case e_shr : return ">>";
2198 case e_shl : return "<<";
2199 case e_lte : return "<=";
2200 case e_ne : return "!=";
2201 case e_gte : return ">=";
2202 case e_lt : return "<";
2203 case e_gt : return ">";
2204 case e_eq : return "=";
2205 case e_rbracket : return ")";
2206 case e_lbracket : return "(";
2207 case e_rsqrbracket : return "]";
2208 case e_lsqrbracket : return "[";
2209 case e_rcrlbracket : return "}";
2210 case e_lcrlbracket : return "{";
2211 case e_comma : return ",";
2212 case e_add : return "+";
2213 case e_sub : return "-";
2214 case e_div : return "/";
2215 case e_mul : return "*";
2216 case e_mod : return "%";
2217 case e_pow : return "^";
2218 case e_colon : return ":";
2219 case e_ternary : return "?";
2220 case e_swap : return "<=>";
2221 default : return "UNKNOWN";
2222 }
2223 }
2224
2225 inline bool is_error() const
2226 {
2227 return (
2228 (e_error == type) ||
2229 (e_err_symbol == type) ||
2230 (e_err_number == type) ||
2231 (e_err_string == type) ||
2232 (e_err_sfunc == type)
2233 );
2234 }
2235
2238 std::size_t position;
2239 };
2240
2242 {
2243 public:
2244
2246 typedef std::vector<token_t> token_list_t;
2247 typedef token_list_t::iterator token_list_itr_t;
2249
2251 : base_itr_(0),
2252 s_itr_ (0),
2253 s_end_ (0)
2254 {
2255 clear();
2256 }
2257
2258 inline void clear()
2259 {
2260 base_itr_ = 0;
2261 s_itr_ = 0;
2262 s_end_ = 0;
2263 token_list_.clear();
2264 token_itr_ = token_list_.end();
2265 store_token_itr_ = token_list_.end();
2266 }
2267
2268 inline bool process(const std::string& str)
2269 {
2270 base_itr_ = str.data();
2271 s_itr_ = str.data();
2272 s_end_ = str.data() + str.size();
2273
2274 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2275 token_list_.clear();
2276
2277 while (!is_end(s_itr_))
2278 {
2279 scan_token();
2280
2281 if (!token_list_.empty() && token_list_.back().is_error())
2282 return false;
2283 }
2284
2285 return true;
2286 }
2287
2288 inline bool empty() const
2289 {
2290 return token_list_.empty();
2291 }
2292
2293 inline std::size_t size() const
2294 {
2295 return token_list_.size();
2296 }
2297
2298 inline void begin()
2299 {
2300 token_itr_ = token_list_.begin();
2301 store_token_itr_ = token_list_.begin();
2302 }
2303
2304 inline void store()
2305 {
2306 store_token_itr_ = token_itr_;
2307 }
2308
2309 inline void restore()
2310 {
2311 token_itr_ = store_token_itr_;
2312 }
2313
2315 {
2316 if (token_list_.end() != token_itr_)
2317 {
2318 return *token_itr_++;
2319 }
2320 else
2321 return eof_token_;
2322 }
2323
2325 {
2326 if (token_list_.end() != token_itr_)
2327 {
2328 return *token_itr_;
2329 }
2330 else
2331 return eof_token_;
2332 }
2333
2334 inline token_t& operator[](const std::size_t& index)
2335 {
2336 if (index < token_list_.size())
2337 return token_list_[index];
2338 else
2339 return eof_token_;
2340 }
2341
2342 inline token_t operator[](const std::size_t& index) const
2343 {
2344 if (index < token_list_.size())
2345 return token_list_[index];
2346 else
2347 return eof_token_;
2348 }
2349
2350 inline bool finished() const
2351 {
2352 return (token_list_.end() == token_itr_);
2353 }
2354
2356 {
2357 if (
2358 !token_list_.empty() &&
2359 (token_list_.end() != token_itr_)
2360 )
2361 {
2362 token_t t = *token_itr_;
2363
2364 t.type = tk_type;
2365 token_itr_ = token_list_.insert(token_itr_,t);
2366 }
2367 }
2368
2369 inline std::string substr(const std::size_t& begin, const std::size_t& end)
2370 {
2371 const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2372 const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
2373
2374 return std::string(begin_itr,end_itr);
2375 }
2376
2377 inline std::string remaining() const
2378 {
2379 if (finished())
2380 return "";
2381 else if (token_list_.begin() != token_itr_)
2382 return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2383 else
2384 return std::string(base_itr_ + token_itr_->position, s_end_);
2385 }
2386
2387 private:
2388
2389 inline bool is_end(details::char_cptr itr)
2390 {
2391 return (s_end_ == itr);
2392 }
2393
2394 #ifndef exprtk_disable_comments
2395 inline bool is_comment_start(details::char_cptr itr)
2396 {
2397 const char_t c0 = *(itr + 0);
2398 const char_t c1 = *(itr + 1);
2399
2400 if ('#' == c0)
2401 return true;
2402 else if (!is_end(itr + 1))
2403 {
2404 if (('/' == c0) && ('/' == c1)) return true;
2405 if (('/' == c0) && ('*' == c1)) return true;
2406 }
2407 return false;
2408 }
2409 #else
2410 inline bool is_comment_start(details::char_cptr)
2411 {
2412 return false;
2413 }
2414 #endif
2415
2416 inline void skip_whitespace()
2417 {
2418 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2419 {
2420 ++s_itr_;
2421 }
2422 }
2423
2424 inline void skip_comments()
2425 {
2426 #ifndef exprtk_disable_comments
2427 // The following comment styles are supported:
2428 // 1. // .... \n
2429 // 2. # .... \n
2430 // 3. /* .... */
2431 struct test
2432 {
2433 static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2434 {
2435 mode = 0;
2436 if ('#' == c0) { mode = 1; incr = 1; }
2437 else if ('/' == c0)
2438 {
2439 if ('/' == c1) { mode = 1; incr = 2; }
2440 else if ('*' == c1) { mode = 2; incr = 2; }
2441 }
2442 return (0 != mode);
2443 }
2444
2445 static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2446 {
2447 if (
2448 ((1 == mode) && ('\n' == c0)) ||
2449 ((2 == mode) && ( '*' == c0) && ('/' == c1))
2450 )
2451 {
2452 mode = 0;
2453 return true;
2454 }
2455 else
2456 return false;
2457 }
2458 };
2459
2460 int mode = 0;
2461 int increment = 0;
2462
2463 if (is_end(s_itr_))
2464 return;
2465 else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2466 return;
2467
2468 details::char_cptr cmt_start = s_itr_;
2469
2470 s_itr_ += increment;
2471
2472 while (!is_end(s_itr_))
2473 {
2474 if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2475 {
2476 ++s_itr_;
2477 return;
2478 }
2479
2480 if ((2 == mode))
2481 {
2482 if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2483 {
2484 s_itr_ += 2;
2485 return;
2486 }
2487 }
2488
2489 ++s_itr_;
2490 }
2491
2492 if (2 == mode)
2493 {
2494 token_t t;
2495 t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2496 token_list_.push_back(t);
2497 }
2498 #endif
2499 }
2500
2501 inline void scan_token()
2502 {
2503 if (details::is_whitespace(*s_itr_))
2504 {
2505 skip_whitespace();
2506 return;
2507 }
2508 else if (is_comment_start(s_itr_))
2509 {
2510 skip_comments();
2511 return;
2512 }
2513 else if (details::is_operator_char(*s_itr_))
2514 {
2515 scan_operator();
2516 return;
2517 }
2518 else if (details::is_letter(*s_itr_))
2519 {
2520 scan_symbol();
2521 return;
2522 }
2523 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2524 {
2525 scan_number();
2526 return;
2527 }
2528 else if ('$' == (*s_itr_))
2529 {
2530 scan_special_function();
2531 return;
2532 }
2533 #ifndef exprtk_disable_string_capabilities
2534 else if ('\'' == (*s_itr_))
2535 {
2536 scan_string();
2537 return;
2538 }
2539 #endif
2540 else if ('~' == (*s_itr_))
2541 {
2542 token_t t;
2543 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2544 token_list_.push_back(t);
2545 ++s_itr_;
2546 return;
2547 }
2548 else
2549 {
2550 token_t t;
2551 t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2552 token_list_.push_back(t);
2553 ++s_itr_;
2554 }
2555 }
2556
2557 inline void scan_operator()
2558 {
2559 token_t t;
2560
2561 const char_t c0 = s_itr_[0];
2562
2563 if (!is_end(s_itr_ + 1))
2564 {
2565 const char_t c1 = s_itr_[1];
2566
2567 if (!is_end(s_itr_ + 2))
2568 {
2569 const char_t c2 = s_itr_[2];
2570
2571 if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2572 {
2573 t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2574 token_list_.push_back(t);
2575 s_itr_ += 3;
2576 return;
2577 }
2578 }
2579
2581
2582 if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2583 else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2584 else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2585 else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2586 else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2587 else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2588 else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2589 else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2590 else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2591 else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2592 else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2593 else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2594 else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2595
2596 if (token_t::e_none != ttype)
2597 {
2598 t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2599 token_list_.push_back(t);
2600 s_itr_ += 2;
2601 return;
2602 }
2603 }
2604
2605 if ('<' == c0)
2606 t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2607 else if ('>' == c0)
2608 t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2609 else if (';' == c0)
2610 t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2611 else if ('&' == c0)
2612 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2613 else if ('|' == c0)
2614 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2615 else
2616 t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2617
2618 token_list_.push_back(t);
2619 ++s_itr_;
2620 }
2621
2622 inline void scan_symbol()
2623 {
2624 details::char_cptr initial_itr = s_itr_;
2625
2626 while (!is_end(s_itr_))
2627 {
2628 if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2629 {
2630 if ('.' != (*s_itr_))
2631 break;
2632 /*
2633 Permit symbols that contain a 'dot'
2634 Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2635 Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2636 */
2637 if (
2638 (s_itr_ != initial_itr) &&
2639 !is_end(s_itr_ + 1) &&
2640 !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2641 ('_' != (*(s_itr_ + 1)))
2642 )
2643 break;
2644 }
2645
2646 ++s_itr_;
2647 }
2648
2649 token_t t;
2650 t.set_symbol(initial_itr,s_itr_,base_itr_);
2651 token_list_.push_back(t);
2652 }
2653
2654 inline void scan_number()
2655 {
2656 /*
2657 Attempt to match a valid numeric value in one of the following formats:
2658 (01) 123456
2659 (02) 123456.
2660 (03) 123.456
2661 (04) 123.456e3
2662 (05) 123.456E3
2663 (06) 123.456e+3
2664 (07) 123.456E+3
2665 (08) 123.456e-3
2666 (09) 123.456E-3
2667 (00) .1234
2668 (11) .1234e3
2669 (12) .1234E+3
2670 (13) .1234e+3
2671 (14) .1234E-3
2672 (15) .1234e-3
2673 */
2674
2675 details::char_cptr initial_itr = s_itr_;
2676 bool dot_found = false;
2677 bool e_found = false;
2678 bool post_e_sign_found = false;
2679 bool post_e_digit_found = false;
2680 token_t t;
2681
2682 while (!is_end(s_itr_))
2683 {
2684 if ('.' == (*s_itr_))
2685 {
2686 if (dot_found)
2687 {
2688 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2689 token_list_.push_back(t);
2690
2691 return;
2692 }
2693
2694 dot_found = true;
2695 ++s_itr_;
2696
2697 continue;
2698 }
2699 else if ('e' == std::tolower(*s_itr_))
2700 {
2701 const char_t& c = *(s_itr_ + 1);
2702
2703 if (is_end(s_itr_ + 1))
2704 {
2705 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2706 token_list_.push_back(t);
2707
2708 return;
2709 }
2710 else if (
2711 ('+' != c) &&
2712 ('-' != c) &&
2714 )
2715 {
2716 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2717 token_list_.push_back(t);
2718
2719 return;
2720 }
2721
2722 e_found = true;
2723 ++s_itr_;
2724
2725 continue;
2726 }
2727 else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2728 {
2729 if (post_e_sign_found)
2730 {
2731 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2732 token_list_.push_back(t);
2733
2734 return;
2735 }
2736
2737 post_e_sign_found = true;
2738 ++s_itr_;
2739
2740 continue;
2741 }
2742 else if (e_found && details::is_digit(*s_itr_))
2743 {
2744 post_e_digit_found = true;
2745 ++s_itr_;
2746
2747 continue;
2748 }
2749 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2750 break;
2751 else
2752 ++s_itr_;
2753 }
2754
2755 t.set_numeric(initial_itr, s_itr_, base_itr_);
2756 token_list_.push_back(t);
2757
2758 return;
2759 }
2760
2761 inline void scan_special_function()
2762 {
2763 details::char_cptr initial_itr = s_itr_;
2764 token_t t;
2765
2766 // $fdd(x,x,x) = at least 11 chars
2767 if (std::distance(s_itr_,s_end_) < 11)
2768 {
2769 t.set_error(
2771 initial_itr, std::min(initial_itr + 11, s_end_),
2772 base_itr_);
2773 token_list_.push_back(t);
2774
2775 return;
2776 }
2777
2778 if (
2779 !(('$' == *s_itr_) &&
2780 (details::imatch ('f',*(s_itr_ + 1))) &&
2781 (details::is_digit(*(s_itr_ + 2))) &&
2782 (details::is_digit(*(s_itr_ + 3))))
2783 )
2784 {
2785 t.set_error(
2787 initial_itr, std::min(initial_itr + 4, s_end_),
2788 base_itr_);
2789 token_list_.push_back(t);
2790
2791 return;
2792 }
2793
2794 s_itr_ += 4; // $fdd = 4chars
2795
2796 t.set_symbol(initial_itr, s_itr_, base_itr_);
2797 token_list_.push_back(t);
2798
2799 return;
2800 }
2801
2802 #ifndef exprtk_disable_string_capabilities
2803 inline void scan_string()
2804 {
2805 details::char_cptr initial_itr = s_itr_ + 1;
2806 token_t t;
2807
2808 if (std::distance(s_itr_,s_end_) < 2)
2809 {
2810 t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2811 token_list_.push_back(t);
2812
2813 return;
2814 }
2815
2816 ++s_itr_;
2817
2818 bool escaped_found = false;
2819 bool escaped = false;
2820
2821 while (!is_end(s_itr_))
2822 {
2823 if (!details::is_valid_string_char(*s_itr_))
2824 {
2825 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2826 token_list_.push_back(t);
2827
2828 return;
2829 }
2830 else if (!escaped && ('\\' == *s_itr_))
2831 {
2832 escaped_found = true;
2833 escaped = true;
2834 ++s_itr_;
2835
2836 continue;
2837 }
2838 else if (!escaped)
2839 {
2840 if ('\'' == *s_itr_)
2841 break;
2842 }
2843 else if (escaped)
2844 {
2845 if (
2846 !is_end(s_itr_) && ('0' == *(s_itr_)) &&
2847 ((s_itr_ + 4) <= s_end_)
2848 )
2849 {
2850 const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1)));
2851
2852 const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2853 details::is_hex_digit(*(s_itr_ + 3)) ;
2854
2855 if (!(x_seperator && both_digits))
2856 {
2857 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2858 token_list_.push_back(t);
2859
2860 return;
2861 }
2862 else
2863 s_itr_ += 3;
2864 }
2865
2866 escaped = false;
2867 }
2868
2869 ++s_itr_;
2870 }
2871
2872 if (is_end(s_itr_))
2873 {
2874 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2875 token_list_.push_back(t);
2876
2877 return;
2878 }
2879
2880 if (!escaped_found)
2881 t.set_string(initial_itr, s_itr_, base_itr_);
2882 else
2883 {
2884 std::string parsed_string(initial_itr,s_itr_);
2885
2886 if (!details::cleanup_escapes(parsed_string))
2887 {
2888 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2889 token_list_.push_back(t);
2890
2891 return;
2892 }
2893
2894 t.set_string(
2895 parsed_string,
2896 static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2897 }
2898
2899 token_list_.push_back(t);
2900 ++s_itr_;
2901
2902 return;
2903 }
2904 #endif
2905
2906 private:
2907
2908 token_list_t token_list_;
2909 token_list_itr_t token_itr_;
2910 token_list_itr_t store_token_itr_;
2911 token_t eof_token_;
2912 details::char_cptr base_itr_;
2913 details::char_cptr s_itr_;
2914 details::char_cptr s_end_;
2915
2916 friend class token_scanner;
2917 friend class token_modifier;
2918 friend class token_inserter;
2919 friend class token_joiner;
2920 };
2921
2923 {
2924 public:
2925
2926 virtual void init() { }
2927 virtual void reset() { }
2928 virtual bool result() { return true; }
2929 virtual std::size_t process(generator&) { return 0; }
2930 virtual ~helper_interface() { }
2931 };
2932
2934 {
2935 public:
2936
2938 {}
2939
2940 explicit token_scanner(const std::size_t& stride)
2941 : stride_(stride)
2942 {
2943 if (stride > 4)
2944 {
2945 throw std::invalid_argument("token_scanner() - Invalid stride value");
2946 }
2947 }
2948
2949 inline std::size_t process(generator& g)
2950 {
2951 if (g.token_list_.size() >= stride_)
2952 {
2953 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2954 {
2955 token t;
2956
2957 switch (stride_)
2958 {
2959 case 1 :
2960 {
2961 const token& t0 = g.token_list_[i];
2962
2963 if (!operator()(t0))
2964 {
2965 return i;
2966 }
2967 }
2968 break;
2969
2970 case 2 :
2971 {
2972 const token& t0 = g.token_list_[i ];
2973 const token& t1 = g.token_list_[i + 1];
2974
2975 if (!operator()(t0, t1))
2976 {
2977 return i;
2978 }
2979 }
2980 break;
2981
2982 case 3 :
2983 {
2984 const token& t0 = g.token_list_[i ];
2985 const token& t1 = g.token_list_[i + 1];
2986 const token& t2 = g.token_list_[i + 2];
2987
2988 if (!operator()(t0, t1, t2))
2989 {
2990 return i;
2991 }
2992 }
2993 break;
2994
2995 case 4 :
2996 {
2997 const token& t0 = g.token_list_[i ];
2998 const token& t1 = g.token_list_[i + 1];
2999 const token& t2 = g.token_list_[i + 2];
3000 const token& t3 = g.token_list_[i + 3];
3001
3002 if (!operator()(t0, t1, t2, t3))
3003 {
3004 return i;
3005 }
3006 }
3007 break;
3008 }
3009 }
3010 }
3011
3012 return (g.token_list_.size() - stride_ + 1);
3013 }
3014
3015 virtual bool operator() (const token&)
3016 {
3017 return false;
3018 }
3019
3020 virtual bool operator() (const token&, const token&)
3021 {
3022 return false;
3023 }
3024
3025 virtual bool operator() (const token&, const token&, const token&)
3026 {
3027 return false;
3028 }
3029
3030 virtual bool operator() (const token&, const token&, const token&, const token&)
3031 {
3032 return false;
3033 }
3034
3035 private:
3036
3037 const std::size_t stride_;
3038 };
3039
3041 {
3042 public:
3043
3044 inline std::size_t process(generator& g)
3045 {
3046 std::size_t changes = 0;
3047
3048 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3049 {
3050 if (modify(g.token_list_[i])) changes++;
3051 }
3052
3053 return changes;
3054 }
3055
3056 virtual bool modify(token& t) = 0;
3057 };
3058
3060 {
3061 public:
3062
3063 explicit token_inserter(const std::size_t& stride)
3064 : stride_(stride)
3065 {
3066 if (stride > 5)
3067 {
3068 throw std::invalid_argument("token_inserter() - Invalid stride value");
3069 }
3070 }
3071
3072 inline std::size_t process(generator& g)
3073 {
3074 if (g.token_list_.empty())
3075 return 0;
3076 else if (g.token_list_.size() < stride_)
3077 return 0;
3078
3079 std::size_t changes = 0;
3080
3081 typedef std::pair<std::size_t, token> insert_t;
3082 std::vector<insert_t> insert_list;
3083 insert_list.reserve(10000);
3084
3085 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3086 {
3087 int insert_index = -1;
3088 token t;
3089
3090 switch (stride_)
3091 {
3092 case 1 : insert_index = insert(g.token_list_[i],t);
3093 break;
3094
3095 case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3096 break;
3097
3098 case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3099 break;
3100
3101 case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t);
3102 break;
3103
3104 case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t);
3105 break;
3106 }
3107
3108 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3109 {
3110 insert_list.push_back(insert_t(i, t));
3111 changes++;
3112 }
3113 }
3114
3115 if (!insert_list.empty())
3116 {
3117 generator::token_list_t token_list;
3118
3119 std::size_t insert_index = 0;
3120
3121 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3122 {
3123 token_list.push_back(g.token_list_[i]);
3124
3125 if (
3126 (insert_index < insert_list.size()) &&
3127 (insert_list[insert_index].first == i)
3128 )
3129 {
3130 token_list.push_back(insert_list[insert_index].second);
3131 insert_index++;
3132 }
3133 }
3134
3135 std::swap(g.token_list_,token_list);
3136 }
3137
3138 return changes;
3139 }
3140
3141 #define token_inserter_empty_body \
3142 { \
3143 return -1; \
3144 } \
3145
3146 inline virtual int insert(const token&, token&)
3148
3149 inline virtual int insert(const token&, const token&, token&)
3151
3152 inline virtual int insert(const token&, const token&, const token&, token&)
3154
3155 inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3157
3158 inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3160
3161 #undef token_inserter_empty_body
3162
3163 private:
3164
3165 const std::size_t stride_;
3166 };
3167
3169 {
3170 public:
3171
3172 explicit token_joiner(const std::size_t& stride)
3173 : stride_(stride)
3174 {}
3175
3176 inline std::size_t process(generator& g)
3177 {
3178 if (g.token_list_.empty())
3179 return 0;
3180
3181 switch (stride_)
3182 {
3183 case 2 : return process_stride_2(g);
3184 case 3 : return process_stride_3(g);
3185 default : return 0;
3186 }
3187 }
3188
3189 virtual bool join(const token&, const token&, token&) { return false; }
3190 virtual bool join(const token&, const token&, const token&, token&) { return false; }
3191
3192 private:
3193
3194 inline std::size_t process_stride_2(generator& g)
3195 {
3196 if (g.token_list_.size() < 2)
3197 return 0;
3198
3199 std::size_t changes = 0;
3200
3201 generator::token_list_t token_list;
3202 token_list.reserve(10000);
3203
3204 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3205 {
3206 token t;
3207
3208 for ( ; ; )
3209 {
3210 if (!join(g[i], g[i + 1], t))
3211 {
3212 token_list.push_back(g[i]);
3213 break;
3214 }
3215
3216 token_list.push_back(t);
3217
3218 ++changes;
3219
3220 i+=2;
3221
3222 if (static_cast<std::size_t>(i) >= g.token_list_.size())
3223 break;
3224 }
3225 }
3226
3227 token_list.push_back(g.token_list_.back());
3228
3229 std::swap(token_list, g.token_list_);
3230
3231 return changes;
3232 }
3233
3234 inline std::size_t process_stride_3(generator& g)
3235 {
3236 if (g.token_list_.size() < 3)
3237 return 0;
3238
3239 std::size_t changes = 0;
3240
3241 generator::token_list_t token_list;
3242 token_list.reserve(10000);
3243
3244 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3245 {
3246 token t;
3247
3248 for ( ; ; )
3249 {
3250 if (!join(g[i], g[i + 1], g[i + 2], t))
3251 {
3252 token_list.push_back(g[i]);
3253 break;
3254 }
3255
3256 token_list.push_back(t);
3257
3258 ++changes;
3259
3260 i+=3;
3261
3262 if (static_cast<std::size_t>(i) >= g.token_list_.size())
3263 break;
3264 }
3265 }
3266
3267 token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
3268 token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
3269
3270 std::swap(token_list, g.token_list_);
3271
3272 return changes;
3273 }
3274
3275 const std::size_t stride_;
3276 };
3277
3278 namespace helper
3279 {
3280
3281 inline void dump(const lexer::generator& generator)
3282 {
3283 for (std::size_t i = 0; i < generator.size(); ++i)
3284 {
3285 const lexer::token& t = generator[i];
3286 printf("Token[%02d] @ %03d %6s --> '%s'\n",
3287 static_cast<int>(i),
3288 static_cast<int>(t.position),
3289 t.to_str(t.type).c_str(),
3290 t.value.c_str());
3291 }
3292 }
3293
3295 {
3296 public:
3297
3299
3301 : lexer::token_inserter(2)
3302 {}
3303
3304 inline void ignore_symbol(const std::string& symbol)
3305 {
3306 ignore_set_.insert(symbol);
3307 }
3308
3309 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3310 {
3311 bool match = false;
3312 new_token.type = lexer::token::e_mul;
3313 new_token.value = "*";
3314 new_token.position = t1.position;
3315
3316 if (t0.type == lexer::token::e_symbol)
3317 {
3318 if (ignore_set_.end() != ignore_set_.find(t0.value))
3319 {
3320 return -1;
3321 }
3322 else if (!t0.value.empty() && ('$' == t0.value[0]))
3323 {
3324 return -1;
3325 }
3326 }
3327
3328 if (t1.type == lexer::token::e_symbol)
3329 {
3330 if (ignore_set_.end() != ignore_set_.find(t1.value))
3331 {
3332 return -1;
3333 }
3334 }
3335 if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
3336 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
3337 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3338 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3339 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
3340 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
3341 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
3342 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
3343 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
3344 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3345 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3346 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
3347
3348 return (match) ? 1 : -1;
3349 }
3350
3351 private:
3352
3353 std::set<std::string,details::ilesscompare> ignore_set_;
3354 };
3355
3357 {
3358 public:
3359
3360 explicit operator_joiner(const std::size_t& stride)
3361 : token_joiner(stride)
3362 {}
3363
3364 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3365 {
3366 // ': =' --> ':='
3367 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3368 {
3370 t.value = ":=";
3371 t.position = t0.position;
3372
3373 return true;
3374 }
3375 // '+ =' --> '+='
3376 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3377 {
3379 t.value = "+=";
3380 t.position = t0.position;
3381
3382 return true;
3383 }
3384 // '- =' --> '-='
3385 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3386 {
3388 t.value = "-=";
3389 t.position = t0.position;
3390
3391 return true;
3392 }
3393 // '* =' --> '*='
3394 else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3395 {
3397 t.value = "*=";
3398 t.position = t0.position;
3399
3400 return true;
3401 }
3402 // '/ =' --> '/='
3403 else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3404 {
3406 t.value = "/=";
3407 t.position = t0.position;
3408
3409 return true;
3410 }
3411 // '% =' --> '%='
3412 else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3413 {
3415 t.value = "%=";
3416 t.position = t0.position;
3417
3418 return true;
3419 }
3420 // '> =' --> '>='
3421 else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3422 {
3423 t.type = lexer::token::e_gte;
3424 t.value = ">=";
3425 t.position = t0.position;
3426
3427 return true;
3428 }
3429 // '< =' --> '<='
3430 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3431 {
3432 t.type = lexer::token::e_lte;
3433 t.value = "<=";
3434 t.position = t0.position;
3435
3436 return true;
3437 }
3438 // '= =' --> '=='
3439 else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3440 {
3441 t.type = lexer::token::e_eq;
3442 t.value = "==";
3443 t.position = t0.position;
3444
3445 return true;
3446 }
3447 // '! =' --> '!='
3448 else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3449 {
3450 t.type = lexer::token::e_ne;
3451 t.value = "!=";
3452 t.position = t0.position;
3453
3454 return true;
3455 }
3456 // '< >' --> '<>'
3457 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3458 {
3459 t.type = lexer::token::e_ne;
3460 t.value = "<>";
3461 t.position = t0.position;
3462
3463 return true;
3464 }
3465 // '<= >' --> '<=>'
3466 else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3467 {
3468 t.type = lexer::token::e_swap;
3469 t.value = "<=>";
3470 t.position = t0.position;
3471
3472 return true;
3473 }
3474 // '+ -' --> '-'
3475 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3476 {
3477 t.type = lexer::token::e_sub;
3478 t.value = "-";
3479 t.position = t0.position;
3480
3481 return true;
3482 }
3483 // '- +' --> '-'
3484 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3485 {
3486 t.type = lexer::token::e_sub;
3487 t.value = "-";
3488 t.position = t0.position;
3489
3490 return true;
3491 }
3492 // '- -' --> '+'
3493 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3494 {
3495 /*
3496 Note: May need to reconsider this when wanting to implement
3497 pre/postfix decrement operator
3498 */
3499 t.type = lexer::token::e_add;
3500 t.value = "+";
3501 t.position = t0.position;
3502
3503 return true;
3504 }
3505 else
3506 return false;
3507 }
3508
3509 inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3510 {
3511 // '[ * ]' --> '[*]'
3512 if (
3514 (t1.type == lexer::token::e_mul ) &&
3516 )
3517 {
3519 t.value = "[*]";
3520 t.position = t0.position;
3521
3522 return true;
3523 }
3524 else
3525 return false;
3526 }
3527 };
3528
3530 {
3531 public:
3532
3533 using lexer::token_scanner::operator();
3534
3536 : token_scanner(1),
3537 state_(true)
3538 {}
3539
3540 bool result()
3541 {
3542 if (!stack_.empty())
3543 {
3545 t.value = stack_.top().first;
3546 t.position = stack_.top().second;
3547 error_token_ = t;
3548 state_ = false;
3549
3550 return false;
3551 }
3552 else
3553 return state_;
3554 }
3555
3557 {
3558 return error_token_;
3559 }
3560
3561 void reset()
3562 {
3563 // Why? because msvc doesn't support swap properly.
3564 stack_ = std::stack<std::pair<char,std::size_t> >();
3565 state_ = true;
3566 error_token_.clear();
3567 }
3568
3570 {
3571 if (
3572 !t.value.empty() &&
3573 (lexer::token::e_string != t.type) &&
3574 (lexer::token::e_symbol != t.type) &&
3576 )
3577 {
3578 details::char_t c = t.value[0];
3579
3580 if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
3581 else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3582 else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3584 {
3585 if (stack_.empty())
3586 {
3587 state_ = false;
3588 error_token_ = t;
3589
3590 return false;
3591 }
3592 else if (c != stack_.top().first)
3593 {
3594 state_ = false;
3595 error_token_ = t;
3596
3597 return false;
3598 }
3599 else
3600 stack_.pop();
3601 }
3602 }
3603
3604 return true;
3605 }
3606
3607 private:
3608
3609 bool state_;
3610 std::stack<std::pair<char,std::size_t> > stack_;
3611 lexer::token error_token_;
3612 };
3613
3615 {
3616 public:
3617
3618 using lexer::token_scanner::operator();
3619
3621 : token_scanner (1),
3622 current_index_(0)
3623 {}
3624
3625 bool result()
3626 {
3627 return error_list_.empty();
3628 }
3629
3630 void reset()
3631 {
3632 error_list_.clear();
3633 current_index_ = 0;
3634 }
3635
3637 {
3638 if (token::e_number == t.type)
3639 {
3640 double v;
3641
3642 if (!exprtk::details::string_to_real(t.value,v))
3643 {
3644 error_list_.push_back(current_index_);
3645 }
3646 }
3647
3648 ++current_index_;
3649
3650 return true;
3651 }
3652
3653 std::size_t error_count() const
3654 {
3655 return error_list_.size();
3656 }
3657
3658 std::size_t error_index(const std::size_t& i)
3659 {
3660 if (i < error_list_.size())
3661 return error_list_[i];
3662 else
3664 }
3665
3667 {
3668 error_list_.clear();
3669 }
3670
3671 private:
3672
3673 std::size_t current_index_;
3674 std::vector<std::size_t> error_list_;
3675 };
3676
3678 {
3679 private:
3680
3681 typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3682
3683 public:
3684
3685 bool remove(const std::string& target_symbol)
3686 {
3687 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3688
3689 if (replace_map_.end() == itr)
3690 return false;
3691
3692 replace_map_.erase(itr);
3693
3694 return true;
3695 }
3696
3697 bool add_replace(const std::string& target_symbol,
3698 const std::string& replace_symbol,
3700 {
3701 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3702
3703 if (replace_map_.end() != itr)
3704 {
3705 return false;
3706 }
3707
3708 replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3709
3710 return true;
3711 }
3712
3713 void clear()
3714 {
3715 replace_map_.clear();
3716 }
3717
3718 private:
3719
3720 bool modify(lexer::token& t)
3721 {
3722 if (lexer::token::e_symbol == t.type)
3723 {
3724 if (replace_map_.empty())
3725 return false;
3726
3727 const replace_map_t::iterator itr = replace_map_.find(t.value);
3728
3729 if (replace_map_.end() != itr)
3730 {
3731 t.value = itr->second.first;
3732 t.type = itr->second.second;
3733
3734 return true;
3735 }
3736 }
3737
3738 return false;
3739 }
3740
3741 replace_map_t replace_map_;
3742 };
3743
3745 {
3746 private:
3747
3748 typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3749 typedef std::set<token_pair_t> set_t;
3750
3751 public:
3752
3753 using lexer::token_scanner::operator();
3754
3756 : lexer::token_scanner(2)
3757 {
3762
3763 add_invalid_set1(lexer::token::e_assign );
3764 add_invalid_set1(lexer::token::e_shr );
3765 add_invalid_set1(lexer::token::e_shl );
3766 add_invalid_set1(lexer::token::e_lte );
3767 add_invalid_set1(lexer::token::e_ne );
3768 add_invalid_set1(lexer::token::e_gte );
3769 add_invalid_set1(lexer::token::e_lt );
3770 add_invalid_set1(lexer::token::e_gt );
3771 add_invalid_set1(lexer::token::e_eq );
3772 add_invalid_set1(lexer::token::e_comma );
3773 add_invalid_set1(lexer::token::e_add );
3774 add_invalid_set1(lexer::token::e_sub );
3775 add_invalid_set1(lexer::token::e_div );
3776 add_invalid_set1(lexer::token::e_mul );
3777 add_invalid_set1(lexer::token::e_mod );
3778 add_invalid_set1(lexer::token::e_pow );
3779 add_invalid_set1(lexer::token::e_colon );
3780 add_invalid_set1(lexer::token::e_ternary);
3781 }
3782
3783 bool result()
3784 {
3785 return error_list_.empty();
3786 }
3787
3788 bool operator() (const lexer::token& t0, const lexer::token& t1)
3789 {
3790 const set_t::value_type p = std::make_pair(t0.type,t1.type);
3791
3792 if (invalid_bracket_check(t0.type,t1.type))
3793 {
3794 error_list_.push_back(std::make_pair(t0,t1));
3795 }
3796 else if (invalid_comb_.find(p) != invalid_comb_.end())
3797 {
3798 error_list_.push_back(std::make_pair(t0,t1));
3799 }
3800
3801 return true;
3802 }
3803
3804 std::size_t error_count() const
3805 {
3806 return error_list_.size();
3807 }
3808
3809 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3810 {
3811 if (index < error_list_.size())
3812 {
3813 return error_list_[index];
3814 }
3815 else
3816 {
3817 static const lexer::token error_token;
3818 return std::make_pair(error_token,error_token);
3819 }
3820 }
3821
3823 {
3824 error_list_.clear();
3825 }
3826
3827 private:
3828
3830 {
3831 invalid_comb_.insert(std::make_pair(base,t));
3832 }
3833
3834 void add_invalid_set1(lexer::token::token_type t)
3835 {
3836 add_invalid(t, lexer::token::e_assign);
3837 add_invalid(t, lexer::token::e_shr );
3838 add_invalid(t, lexer::token::e_shl );
3839 add_invalid(t, lexer::token::e_lte );
3840 add_invalid(t, lexer::token::e_ne );
3841 add_invalid(t, lexer::token::e_gte );
3842 add_invalid(t, lexer::token::e_lt );
3843 add_invalid(t, lexer::token::e_gt );
3844 add_invalid(t, lexer::token::e_eq );
3845 add_invalid(t, lexer::token::e_comma );
3846 add_invalid(t, lexer::token::e_div );
3847 add_invalid(t, lexer::token::e_mul );
3848 add_invalid(t, lexer::token::e_mod );
3849 add_invalid(t, lexer::token::e_pow );
3850 add_invalid(t, lexer::token::e_colon );
3851 }
3852
3853 bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
3854 {
3855 if (details::is_right_bracket(static_cast<char>(base)))
3856 {
3857 switch (t)
3858 {
3859 case lexer::token::e_assign : return (']' != base);
3860 case lexer::token::e_string : return (')' != base);
3861 default : return false;
3862 }
3863 }
3864 else if (details::is_left_bracket(static_cast<char>(base)))
3865 {
3866 if (details::is_right_bracket(static_cast<char>(t)))
3867 return false;
3868 else if (details::is_left_bracket(static_cast<char>(t)))
3869 return false;
3870 else
3871 {
3872 switch (t)
3873 {
3874 case lexer::token::e_number : return false;
3875 case lexer::token::e_symbol : return false;
3876 case lexer::token::e_string : return false;
3877 case lexer::token::e_add : return false;
3878 case lexer::token::e_sub : return false;
3879 case lexer::token::e_colon : return false;
3880 case lexer::token::e_ternary : return false;
3881 default : return true ;
3882 }
3883 }
3884 }
3885 else if (details::is_right_bracket(static_cast<char>(t)))
3886 {
3887 switch (base)
3888 {
3889 case lexer::token::e_number : return false;
3890 case lexer::token::e_symbol : return false;
3891 case lexer::token::e_string : return false;
3892 case lexer::token::e_eof : return false;
3893 case lexer::token::e_colon : return false;
3894 case lexer::token::e_ternary : return false;
3895 default : return true ;
3896 }
3897 }
3898 else if (details::is_left_bracket(static_cast<char>(t)))
3899 {
3900 switch (base)
3901 {
3902 case lexer::token::e_rbracket : return true;
3903 case lexer::token::e_rsqrbracket : return true;
3904 case lexer::token::e_rcrlbracket : return true;
3905 default : return false;
3906 }
3907 }
3908
3909 return false;
3910 }
3911
3912 set_t invalid_comb_;
3913 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3914 };
3915
3917 {
3918 private:
3919
3921 typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3922 typedef std::set<token_triplet_t> set_t;
3923
3924 public:
3925
3926 using lexer::token_scanner::operator();
3927
3929 : lexer::token_scanner(3)
3930 {
3934
3941
3948 }
3949
3950 bool result()
3951 {
3952 return error_list_.empty();
3953 }
3954
3955 bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3956 {
3957 const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3958
3959 if (invalid_comb_.find(p) != invalid_comb_.end())
3960 {
3961 error_list_.push_back(std::make_pair(t0,t1));
3962 }
3963
3964 return true;
3965 }
3966
3967 std::size_t error_count() const
3968 {
3969 return error_list_.size();
3970 }
3971
3972 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3973 {
3974 if (index < error_list_.size())
3975 {
3976 return error_list_[index];
3977 }
3978 else
3979 {
3980 static const lexer::token error_token;
3981 return std::make_pair(error_token,error_token);
3982 }
3983 }
3984
3986 {
3987 error_list_.clear();
3988 }
3989
3990 private:
3991
3992 void add_invalid(token_t t0, token_t t1, token_t t2)
3993 {
3994 invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3995 }
3996
3997 set_t invalid_comb_;
3998 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3999 };
4000
4002 {
4004 {
4005 if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
4006 token_scanner_list.end (),
4007 scanner))
4008 {
4009 return false;
4010 }
4011
4012 token_scanner_list.push_back(scanner);
4013
4014 return true;
4015 }
4016
4018 {
4019 if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
4020 token_modifier_list.end (),
4021 modifier))
4022 {
4023 return false;
4024 }
4025
4026 token_modifier_list.push_back(modifier);
4027
4028 return true;
4029 }
4030
4032 {
4033 if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
4034 token_joiner_list.end (),
4035 joiner))
4036 {
4037 return false;
4038 }
4039
4040 token_joiner_list.push_back(joiner);
4041
4042 return true;
4043 }
4044
4046 {
4047 if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
4048 token_inserter_list.end (),
4049 inserter))
4050 {
4051 return false;
4052 }
4053
4054 token_inserter_list.push_back(inserter);
4055
4056 return true;
4057 }
4058
4060 {
4061 error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
4062
4063 for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
4064 {
4066
4067 modifier.reset();
4068 modifier.process(g);
4069
4070 if (!modifier.result())
4071 {
4073
4074 return false;
4075 }
4076 }
4077
4078 return true;
4079 }
4080
4082 {
4083 error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
4084
4085 for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
4086 {
4087 lexer::token_joiner& joiner = (*token_joiner_list[i]);
4088
4089 joiner.reset();
4090 joiner.process(g);
4091
4092 if (!joiner.result())
4093 {
4095
4096 return false;
4097 }
4098 }
4099
4100 return true;
4101 }
4102
4104 {
4105 error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4106
4107 for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4108 {
4110
4111 inserter.reset();
4112 inserter.process(g);
4113
4114 if (!inserter.result())
4115 {
4117
4118 return false;
4119 }
4120 }
4121
4122 return true;
4123 }
4124
4126 {
4127 error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4128
4129 for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4130 {
4132
4133 scanner.reset();
4134 scanner.process(g);
4135
4136 if (!scanner.result())
4137 {
4139
4140 return false;
4141 }
4142 }
4143
4144 return true;
4145 }
4146
4147 std::vector<lexer::token_scanner*> token_scanner_list;
4148 std::vector<lexer::token_modifier*> token_modifier_list;
4149 std::vector<lexer::token_joiner*> token_joiner_list;
4150 std::vector<lexer::token_inserter*> token_inserter_list;
4151
4156 };
4157 }
4158
4160 {
4161 public:
4162
4165
4166 inline bool init(const std::string& str)
4167 {
4168 if (!lexer_.process(str))
4169 {
4170 return false;
4171 }
4172
4173 lexer_.begin();
4174
4175 next_token();
4176
4177 return true;
4178 }
4179
4181 {
4182 return lexer_;
4183 }
4184
4185 inline const generator_t& lexer() const
4186 {
4187 return lexer_;
4188 }
4189
4190 inline void store_token()
4191 {
4192 lexer_.store();
4193 store_current_token_ = current_token_;
4194 }
4195
4196 inline void restore_token()
4197 {
4198 lexer_.restore();
4199 current_token_ = store_current_token_;
4200 }
4201
4202 inline void next_token()
4203 {
4204 current_token_ = lexer_.next_token();
4205 }
4206
4207 inline const token_t& current_token() const
4208 {
4209 return current_token_;
4210 }
4211
4213 {
4215 e_advance = 1
4217
4218 inline void advance_token(const token_advance_mode mode)
4219 {
4220 if (e_advance == mode)
4221 {
4222 next_token();
4223 }
4224 }
4225
4226 inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4227 {
4228 if (current_token().type != ttype)
4229 {
4230 return false;
4231 }
4232
4233 advance_token(mode);
4234
4235 return true;
4236 }
4237
4238 inline bool token_is(const token_t::token_type& ttype,
4239 const std::string& value,
4240 const token_advance_mode mode = e_advance)
4241 {
4242 if (
4243 (current_token().type != ttype) ||
4245 )
4246 {
4247 return false;
4248 }
4249
4250 advance_token(mode);
4251
4252 return true;
4253 }
4254
4255 inline bool peek_token_is(const token_t::token_type& ttype)
4256 {
4257 return (lexer_.peek_next_token().type == ttype);
4258 }
4259
4260 inline bool peek_token_is(const std::string& s)
4261 {
4262 return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4263 }
4264
4265 private:
4266
4267 generator_t lexer_;
4268 token_t current_token_;
4269 token_t store_current_token_;
4270 };
4271 }
4272
4273 template <typename T>
4275 {
4276 public:
4277
4278 typedef T* data_ptr_t;
4279
4280 vector_view(data_ptr_t data, const std::size_t& size)
4281 : size_(size),
4282 data_(data),
4283 data_ref_(0)
4284 {}
4285
4287 : size_(vv.size_),
4288 data_(vv.data_),
4289 data_ref_(0)
4290 {}
4291
4293 {
4294 data_ = data;
4295
4296 if (!data_ref_.empty())
4297 {
4298 for (std::size_t i = 0; i < data_ref_.size(); ++i)
4299 {
4300 (*data_ref_[i]) = data;
4301 }
4302 }
4303 }
4304
4305 inline data_ptr_t data() const
4306 {
4307 return data_;
4308 }
4309
4310 inline std::size_t size() const
4311 {
4312 return size_;
4313 }
4314
4315 inline const T& operator[](const std::size_t index) const
4316 {
4317 return data_[index];
4318 }
4319
4320 inline T& operator[](const std::size_t index)
4321 {
4322 return data_[index];
4323 }
4324
4325 void set_ref(data_ptr_t* data_ref)
4326 {
4327 data_ref_.push_back(data_ref);
4328 }
4329
4330 private:
4331
4332 const std::size_t size_;
4333 data_ptr_t data_;
4334 std::vector<data_ptr_t*> data_ref_;
4335 };
4336
4337 template <typename T>
4339 const std::size_t size, const std::size_t offset = 0)
4340 {
4341 return vector_view<T>(data + offset, size);
4342 }
4343
4344 template <typename T>
4345 inline vector_view<T> make_vector_view(std::vector<T>& v,
4346 const std::size_t size, const std::size_t offset = 0)
4347 {
4348 return vector_view<T>(v.data() + offset, size);
4349 }
4350
4351 template <typename T> class results_context;
4352
4353 template <typename T>
4355 {
4357 {
4361 e_string
4363
4365 : data(0),
4366 size(0),
4368 {}
4369
4370 union
4371 {
4372 void* data;
4374 };
4375
4376 std::size_t size;
4378
4380 {
4381 public:
4382
4383 explicit parameter_list(std::vector<type_store>& pl)
4384 : parameter_list_(pl)
4385 {}
4386
4387 inline bool empty() const
4388 {
4389 return parameter_list_.empty();
4390 }
4391
4392 inline std::size_t size() const
4393 {
4394 return parameter_list_.size();
4395 }
4396
4397 inline type_store& operator[](const std::size_t& index)
4398 {
4399 return parameter_list_[index];
4400 }
4401
4402 inline const type_store& operator[](const std::size_t& index) const
4403 {
4404 return parameter_list_[index];
4405 }
4406
4408 {
4409 return parameter_list_[0];
4410 }
4411
4412 inline const type_store& front() const
4413 {
4414 return parameter_list_[0];
4415 }
4416
4418 {
4419 return parameter_list_.back();
4420 }
4421
4422 inline const type_store& back() const
4423 {
4424 return parameter_list_.back();
4425 }
4426
4427 private:
4428
4429 std::vector<type_store>& parameter_list_;
4430
4431 friend class results_context<T>;
4432 };
4433
4434 template <typename ViewType>
4436 {
4438 typedef ViewType value_t;
4439
4441 : ts_(ts),
4442 data_(reinterpret_cast<value_t*>(ts_.data))
4443 {}
4444
4445 explicit type_view(const type_store_t& ts)
4446 : ts_(const_cast<type_store_t&>(ts)),
4447 data_(reinterpret_cast<value_t*>(ts_.data))
4448 {}
4449
4450 inline std::size_t size() const
4451 {
4452 return ts_.size;
4453 }
4454
4455 inline value_t& operator[](const std::size_t& i)
4456 {
4457 return data_[i];
4458 }
4459
4460 inline const value_t& operator[](const std::size_t& i) const
4461 {
4462 return data_[i];
4463 }
4464
4465 inline const value_t* begin() const { return data_; }
4466 inline value_t* begin() { return data_; }
4467
4468 inline const value_t* end() const
4469 {
4470 return static_cast<value_t*>(data_ + ts_.size);
4471 }
4472
4473 inline value_t* end()
4474 {
4475 return static_cast<value_t*>(data_ + ts_.size);
4476 }
4477
4480 };
4481
4484
4486 {
4488 typedef T value_t;
4489
4491 : v_(*reinterpret_cast<value_t*>(ts.data))
4492 {}
4493
4494 explicit scalar_view(const type_store_t& ts)
4495 : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4496 {}
4497
4499 {
4500 return v_;
4501 }
4502
4503 inline const value_t& operator() () const
4504 {
4505 return v_;
4506 }
4507
4508 template <typename IntType>
4509 inline bool to_int(IntType& i) const
4510 {
4512 return false;
4513
4514 i = static_cast<IntType>(v_);
4515
4516 return true;
4517 }
4518
4519 template <typename UIntType>
4520 inline bool to_uint(UIntType& u) const
4521 {
4522 if (v_ < T(0))
4523 return false;
4525 return false;
4526
4527 u = static_cast<UIntType>(v_);
4528
4529 return true;
4530 }
4531
4532 T& v_;
4533 };
4534 };
4535
4536 template <typename StringView>
4537 inline std::string to_str(const StringView& view)
4538 {
4539 return std::string(view.begin(),view.size());
4540 }
4541
4542 #ifndef exprtk_disable_return_statement
4543 namespace details
4544 {
4545 template <typename T> class return_node;
4546 template <typename T> class return_envelope_node;
4547 }
4548 #endif
4549
4550 template <typename T>
4552 {
4553 public:
4554
4556
4558 : results_available_(false)
4559 {}
4560
4561 inline std::size_t count() const
4562 {
4563 if (results_available_)
4564 return parameter_list_.size();
4565 else
4566 return 0;
4567 }
4568
4569 inline type_store_t& operator[](const std::size_t& index)
4570 {
4571 return parameter_list_[index];
4572 }
4573
4574 inline const type_store_t& operator[](const std::size_t& index) const
4575 {
4576 return parameter_list_[index];
4577 }
4578
4579 private:
4580
4581 inline void clear()
4582 {
4583 results_available_ = false;
4584 }
4585
4586 typedef std::vector<type_store_t> ts_list_t;
4587 typedef typename type_store_t::parameter_list parameter_list_t;
4588
4589 inline void assign(const parameter_list_t& pl)
4590 {
4591 parameter_list_ = pl.parameter_list_;
4592 results_available_ = true;
4593 }
4594
4595 bool results_available_;
4596 ts_list_t parameter_list_;
4597
4598 #ifndef exprtk_disable_return_statement
4599 friend class details::return_node<T>;
4600 friend class details::return_envelope_node<T>;
4601 #endif
4602 };
4603
4604 namespace details
4605 {
4607 {
4632
4633 // Do not add new functions/operators after this point.
4634 e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4635 e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4636 e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4637 e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4638 e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4639 e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4640 e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4641 e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4642 e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4643 e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4644 e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4645 e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4646 e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4647 e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4648 e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4649 e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4650 e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4651 e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4652 e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4653 e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4654 e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4655 e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4656 e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4657 e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4658 e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4660 e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4661 e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4662 e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4663 e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4664 e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4665 e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4666 e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4667 e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4668 e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4669 e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4670 e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4671 e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4672 e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4673 e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4674 e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4675 e_sf4ext60 = 2060, e_sf4ext61 = 2061
4677
4679 {
4680 switch (opr)
4681 {
4682 case e_add : return "+" ;
4683 case e_sub : return "-" ;
4684 case e_mul : return "*" ;
4685 case e_div : return "/" ;
4686 case e_mod : return "%" ;
4687 case e_pow : return "^" ;
4688 case e_assign : return ":=" ;
4689 case e_addass : return "+=" ;
4690 case e_subass : return "-=" ;
4691 case e_mulass : return "*=" ;
4692 case e_divass : return "/=" ;
4693 case e_modass : return "%=" ;
4694 case e_lt : return "<" ;
4695 case e_lte : return "<=" ;
4696 case e_eq : return "==" ;
4697 case e_equal : return "=" ;
4698 case e_ne : return "!=" ;
4699 case e_nequal : return "<>" ;
4700 case e_gte : return ">=" ;
4701 case e_gt : return ">" ;
4702 case e_and : return "and" ;
4703 case e_or : return "or" ;
4704 case e_xor : return "xor" ;
4705 case e_nand : return "nand";
4706 case e_nor : return "nor" ;
4707 case e_xnor : return "xnor";
4708 default : return "N/A" ;
4709 }
4710 }
4711
4713 {
4714 base_operation_t(const operator_type t, const unsigned int& np)
4715 : type(t),
4716 num_params(np)
4717 {}
4718
4720 unsigned int num_params;
4721 };
4722
4723 namespace loop_unroll
4724 {
4725 #ifndef exprtk_disable_superscalar_unroll
4726 const unsigned int global_loop_batch_size = 16;
4727 #else
4728 const unsigned int global_loop_batch_size = 4;
4729 #endif
4730
4731 struct details
4732 {
4733 explicit details(const std::size_t& vsize,
4734 const unsigned int loop_batch_size = global_loop_batch_size)
4735 : batch_size(loop_batch_size ),
4736 remainder (vsize % batch_size),
4737 upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4738 {}
4739
4740 unsigned int batch_size;
4743 };
4744 }
4745
4746 #ifdef exprtk_enable_debugging
4747 inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4748 {
4749 if (size)
4750 exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4751 else
4752 exprtk_debug(("%s - addr: %p size: %d\n",
4753 s.c_str(),
4754 ptr,
4755 static_cast<unsigned int>(size)));
4756 }
4757 #else
4758 inline void dump_ptr(const std::string&, const void*) {}
4759 inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4760 #endif
4761
4762 template <typename T>
4764 {
4765 public:
4766
4768 typedef T* data_t;
4769
4770 private:
4771
4772 struct control_block
4773 {
4774 control_block()
4775 : ref_count(1),
4776 size (0),
4777 data (0),
4778 destruct (true)
4779 {}
4780
4781 explicit control_block(const std::size_t& dsize)
4782 : ref_count(1 ),
4783 size (dsize),
4784 data (0 ),
4785 destruct (true )
4786 { create_data(); }
4787
4788 control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4789 : ref_count(1 ),
4790 size (dsize ),
4791 data (dptr ),
4792 destruct (dstrct)
4793 {}
4794
4795 ~control_block()
4796 {
4797 if (data && destruct && (0 == ref_count))
4798 {
4799 dump_ptr("~control_block() data",data);
4800 delete[] data;
4801 data = reinterpret_cast<data_t>(0);
4802 }
4803 }
4804
4805 static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4806 {
4807 if (dsize)
4808 {
4809 if (0 == data_ptr)
4810 return (new control_block(dsize));
4811 else
4812 return (new control_block(dsize, data_ptr, dstrct));
4813 }
4814 else
4815 return (new control_block);
4816 }
4817
4818 static inline void destroy(control_block*& cntrl_blck)
4819 {
4820 if (cntrl_blck)
4821 {
4822 if (
4823 (0 != cntrl_blck->ref_count) &&
4824 (0 == --cntrl_blck->ref_count)
4825 )
4826 {
4827 delete cntrl_blck;
4828 }
4829
4830 cntrl_blck = 0;
4831 }
4832 }
4833
4834 std::size_t ref_count;
4835 std::size_t size;
4836 data_t data;
4837 bool destruct;
4838
4839 private:
4840
4841 control_block(const control_block&);
4842 control_block& operator=(const control_block&);
4843
4844 inline void create_data()
4845 {
4846 destruct = true;
4847 data = new T[size];
4848 std::fill_n(data, size, T(0));
4849 dump_ptr("control_block::create_data() - data",data,size);
4850 }
4851 };
4852
4853 public:
4854
4856 : control_block_(control_block::create(0))
4857 {}
4858
4859 explicit vec_data_store(const std::size_t& size)
4860 : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true))
4861 {}
4862
4863 vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4864 : control_block_(control_block::create(size, data, dstrct))
4865 {}
4866
4868 {
4869 control_block_ = vds.control_block_;
4870 control_block_->ref_count++;
4871 }
4872
4874 {
4875 control_block::destroy(control_block_);
4876 }
4877
4878 type& operator=(const type& vds)
4879 {
4880 if (this != &vds)
4881 {
4882 std::size_t final_size = min_size(control_block_, vds.control_block_);
4883
4884 vds.control_block_->size = final_size;
4885 control_block_->size = final_size;
4886
4887 if (control_block_->destruct || (0 == control_block_->data))
4888 {
4889 control_block::destroy(control_block_);
4890
4891 control_block_ = vds.control_block_;
4892 control_block_->ref_count++;
4893 }
4894 }
4895
4896 return (*this);
4897 }
4898
4899 inline data_t data()
4900 {
4901 return control_block_->data;
4902 }
4903
4904 inline data_t data() const
4905 {
4906 return control_block_->data;
4907 }
4908
4909 inline std::size_t size()
4910 {
4911 return control_block_->size;
4912 }
4913
4914 inline std::size_t size() const
4915 {
4916 return control_block_->size;
4917 }
4918
4919 inline data_t& ref()
4920 {
4921 return control_block_->data;
4922 }
4923
4924 inline void dump() const
4925 {
4926 #ifdef exprtk_enable_debugging
4927 exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4928 size(),
4929 data(),
4930 (control_block_->destruct ? 'T' : 'F')));
4931
4932 for (std::size_t i = 0; i < size(); ++i)
4933 {
4934 if (5 == i)
4935 exprtk_debug(("\n"));
4936
4937 exprtk_debug(("%15.10f ",data()[i]));
4938 }
4939 exprtk_debug(("\n"));
4940 #endif
4941 }
4942
4943 static inline void match_sizes(type& vds0, type& vds1)
4944 {
4945 const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4946 vds0.control_block_->size = size;
4947 vds1.control_block_->size = size;
4948 }
4949
4950 private:
4951
4952 static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4953 {
4954 const std::size_t size0 = cb0->size;
4955 const std::size_t size1 = cb1->size;
4956
4957 if (size0 && size1)
4958 return std::min(size0,size1);
4959 else
4960 return (size0) ? size0 : size1;
4961 }
4962
4963 control_block* control_block_;
4964 };
4965
4966 namespace numeric
4967 {
4968 namespace details
4969 {
4970 template <typename T>
4971 inline T process_impl(const operator_type operation, const T arg)
4972 {
4973 switch (operation)
4974 {
4975 case e_abs : return numeric::abs (arg);
4976 case e_acos : return numeric::acos (arg);
4977 case e_acosh : return numeric::acosh(arg);
4978 case e_asin : return numeric::asin (arg);
4979 case e_asinh : return numeric::asinh(arg);
4980 case e_atan : return numeric::atan (arg);
4981 case e_atanh : return numeric::atanh(arg);
4982 case e_ceil : return numeric::ceil (arg);
4983 case e_cos : return numeric::cos (arg);
4984 case e_cosh : return numeric::cosh (arg);
4985 case e_exp : return numeric::exp (arg);
4986 case e_expm1 : return numeric::expm1(arg);
4987 case e_floor : return numeric::floor(arg);
4988 case e_log : return numeric::log (arg);
4989 case e_log10 : return numeric::log10(arg);
4990 case e_log2 : return numeric::log2 (arg);
4991 case e_log1p : return numeric::log1p(arg);
4992 case e_neg : return numeric::neg (arg);
4993 case e_pos : return numeric::pos (arg);
4994 case e_round : return numeric::round(arg);
4995 case e_sin : return numeric::sin (arg);
4996 case e_sinc : return numeric::sinc (arg);
4997 case e_sinh : return numeric::sinh (arg);
4998 case e_sqrt : return numeric::sqrt (arg);
4999 case e_tan : return numeric::tan (arg);
5000 case e_tanh : return numeric::tanh (arg);
5001 case e_cot : return numeric::cot (arg);
5002 case e_sec : return numeric::sec (arg);
5003 case e_csc : return numeric::csc (arg);
5004 case e_r2d : return numeric::r2d (arg);
5005 case e_d2r : return numeric::d2r (arg);
5006 case e_d2g : return numeric::d2g (arg);
5007 case e_g2d : return numeric::g2d (arg);
5008 case e_notl : return numeric::notl (arg);
5009 case e_sgn : return numeric::sgn (arg);
5010 case e_erf : return numeric::erf (arg);
5011 case e_erfc : return numeric::erfc (arg);
5012 case e_ncdf : return numeric::ncdf (arg);
5013 case e_frac : return numeric::frac (arg);
5014 case e_trunc : return numeric::trunc(arg);
5015
5016 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
5017 return std::numeric_limits<T>::quiet_NaN();
5018 }
5019 }
5020
5021 template <typename T>
5022 inline T process_impl(const operator_type operation, const T arg0, const T arg1)
5023 {
5024 switch (operation)
5025 {
5026 case e_add : return (arg0 + arg1);
5027 case e_sub : return (arg0 - arg1);
5028 case e_mul : return (arg0 * arg1);
5029 case e_div : return (arg0 / arg1);
5030 case e_mod : return modulus<T>(arg0,arg1);
5031 case e_pow : return pow<T>(arg0,arg1);
5032 case e_atan2 : return atan2<T>(arg0,arg1);
5033 case e_min : return std::min<T>(arg0,arg1);
5034 case e_max : return std::max<T>(arg0,arg1);
5035 case e_logn : return logn<T>(arg0,arg1);
5036 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
5037 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
5038 case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5039 case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5040 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
5041 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
5042 case e_and : return and_opr <T>(arg0,arg1);
5043 case e_nand : return nand_opr<T>(arg0,arg1);
5044 case e_or : return or_opr <T>(arg0,arg1);
5045 case e_nor : return nor_opr <T>(arg0,arg1);
5046 case e_xor : return xor_opr <T>(arg0,arg1);
5047 case e_xnor : return xnor_opr<T>(arg0,arg1);
5048 case e_root : return root <T>(arg0,arg1);
5049 case e_roundn : return roundn <T>(arg0,arg1);
5050 case e_equal : return equal (arg0,arg1);
5051 case e_nequal : return nequal (arg0,arg1);
5052 case e_hypot : return hypot <T>(arg0,arg1);
5053 case e_shr : return shr <T>(arg0,arg1);
5054 case e_shl : return shl <T>(arg0,arg1);
5055
5056 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
5057 return std::numeric_limits<T>::quiet_NaN();
5058 }
5059 }
5060
5061 template <typename T>
5062 inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
5063 {
5064 switch (operation)
5065 {
5066 case e_add : return (arg0 + arg1);
5067 case e_sub : return (arg0 - arg1);
5068 case e_mul : return (arg0 * arg1);
5069 case e_div : return (arg0 / arg1);
5070 case e_mod : return arg0 % arg1;
5071 case e_pow : return pow<T>(arg0,arg1);
5072 case e_min : return std::min<T>(arg0,arg1);
5073 case e_max : return std::max<T>(arg0,arg1);
5074 case e_logn : return logn<T>(arg0,arg1);
5075 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
5076 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
5077 case e_eq : return (arg0 == arg1) ? T(1) : T(0);
5078 case e_ne : return (arg0 != arg1) ? T(1) : T(0);
5079 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
5080 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
5081 case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
5082 case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
5083 case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
5084 case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
5085 case e_xor : return arg0 ^ arg1;
5086 case e_xnor : return !(arg0 ^ arg1);
5087 case e_root : return root<T>(arg0,arg1);
5088 case e_equal : return arg0 == arg1;
5089 case e_nequal : return arg0 != arg1;
5090 case e_hypot : return hypot<T>(arg0,arg1);
5091 case e_shr : return arg0 >> arg1;
5092 case e_shl : return arg0 << arg1;
5093
5094 default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
5095 return std::numeric_limits<T>::quiet_NaN();
5096 }
5097 }
5098 }
5099
5100 template <typename T>
5101 inline T process(const operator_type operation, const T arg)
5102 {
5104 }
5105
5106 template <typename T>
5107 inline T process(const operator_type operation, const T arg0, const T arg1)
5108 {
5109 return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5110 }
5111 }
5112
5113 template <typename Node>
5115 {
5116 typedef Node* node_ptr_t;
5117 typedef Node** node_pp_t;
5118 typedef std::vector<node_pp_t> noderef_list_t;
5119
5121
5123 };
5124
5125 template <typename Node>
5126 struct node_depth_base;
5127
5128 template <typename T>
5129 class expression_node : public node_collector_interface<expression_node<T> >,
5130 public node_depth_base<expression_node<T> >
5131 {
5132 public:
5133
5135 {
5172 e_swap
5174
5175 typedef T value_type;
5180
5182 {}
5183
5184 inline virtual T value() const
5185 {
5186 return std::numeric_limits<T>::quiet_NaN();
5187 }
5188
5189 inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5190 {
5191 return reinterpret_cast<expression_ptr>(index * 0);
5192 }
5193
5194 inline virtual node_type type() const
5195 {
5196 return e_none;
5197 }
5198 };
5199
5200 template <typename T>
5201 inline bool is_generally_string_node(const expression_node<T>* node);
5202
5203 inline bool is_true(const double v)
5204 {
5205 return std::not_equal_to<double>()(0.0,v);
5206 }
5207
5208 inline bool is_true(const long double v)
5209 {
5210 return std::not_equal_to<long double>()(0.0L,v);
5211 }
5212
5213 inline bool is_true(const float v)
5214 {
5215 return std::not_equal_to<float>()(0.0f,v);
5216 }
5217
5218 template <typename T>
5219 inline bool is_true(const std::complex<T>& v)
5220 {
5221 return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5222 }
5223
5224 template <typename T>
5225 inline bool is_true(const expression_node<T>* node)
5226 {
5227 return std::not_equal_to<T>()(T(0),node->value());
5228 }
5229
5230 template <typename T>
5231 inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
5232 {
5233 return std::not_equal_to<T>()(T(0),node.first->value());
5234 }
5235
5236 template <typename T>
5237 inline bool is_false(const expression_node<T>* node)
5238 {
5239 return std::equal_to<T>()(T(0),node->value());
5240 }
5241
5242 template <typename T>
5243 inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
5244 {
5245 return std::equal_to<T>()(T(0),node.first->value());
5246 }
5247
5248 template <typename T>
5249 inline bool is_unary_node(const expression_node<T>* node)
5250 {
5251 return node && (details::expression_node<T>::e_unary == node->type());
5252 }
5253
5254 template <typename T>
5255 inline bool is_neg_unary_node(const expression_node<T>* node)
5256 {
5257 return node && (details::expression_node<T>::e_neg == node->type());
5258 }
5259
5260 template <typename T>
5261 inline bool is_binary_node(const expression_node<T>* node)
5262 {
5263 return node && (details::expression_node<T>::e_binary == node->type());
5264 }
5265
5266 template <typename T>
5267 inline bool is_variable_node(const expression_node<T>* node)
5268 {
5269 return node && (details::expression_node<T>::e_variable == node->type());
5270 }
5271
5272 template <typename T>
5273 inline bool is_ivariable_node(const expression_node<T>* node)
5274 {
5275 return node &&
5276 (
5281 );
5282 }
5283
5284 template <typename T>
5286 {
5287 return node && (details::expression_node<T>::e_vecelem == node->type());
5288 }
5289
5290 template <typename T>
5292 {
5293 return node && (details::expression_node<T>::e_rbvecelem == node->type());
5294 }
5295
5296 template <typename T>
5298 {
5299 return node && (details::expression_node<T>::e_rbveccelem == node->type());
5300 }
5301
5302 template <typename T>
5303 inline bool is_vector_node(const expression_node<T>* node)
5304 {
5305 return node && (details::expression_node<T>::e_vector == node->type());
5306 }
5307
5308 template <typename T>
5309 inline bool is_ivector_node(const expression_node<T>* node)
5310 {
5311 if (node)
5312 {
5313 switch (node->type())
5314 {
5325 default : return false;
5326 }
5327 }
5328 else
5329 return false;
5330 }
5331
5332 template <typename T>
5333 inline bool is_constant_node(const expression_node<T>* node)
5334 {
5335 return node && (details::expression_node<T>::e_constant == node->type());
5336 }
5337
5338 template <typename T>
5339 inline bool is_null_node(const expression_node<T>* node)
5340 {
5341 return node && (details::expression_node<T>::e_null == node->type());
5342 }
5343
5344 template <typename T>
5345 inline bool is_break_node(const expression_node<T>* node)
5346 {
5347 return node && (details::expression_node<T>::e_break == node->type());
5348 }
5349
5350 template <typename T>
5351 inline bool is_continue_node(const expression_node<T>* node)
5352 {
5353 return node && (details::expression_node<T>::e_continue == node->type());
5354 }
5355
5356 template <typename T>
5357 inline bool is_swap_node(const expression_node<T>* node)
5358 {
5359 return node && (details::expression_node<T>::e_swap == node->type());
5360 }
5361
5362 template <typename T>
5363 inline bool is_function(const expression_node<T>* node)
5364 {
5365 return node && (details::expression_node<T>::e_function == node->type());
5366 }
5367
5368 template <typename T>
5369 inline bool is_return_node(const expression_node<T>* node)
5370 {
5371 return node && (details::expression_node<T>::e_return == node->type());
5372 }
5373
5374 template <typename T> class unary_node;
5375
5376 template <typename T>
5377 inline bool is_negate_node(const expression_node<T>* node)
5378 {
5379 if (node && is_unary_node(node))
5380 {
5381 return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5382 }
5383 else
5384 return false;
5385 }
5386
5387 template <typename T>
5389 {
5390 return (0 != node) &&
5391 !is_variable_node(node) &&
5392 !is_string_node (node) ;
5393 }
5394
5395 template <std::size_t N, typename T>
5397 {
5398 for (std::size_t i = 0; i < N; ++i)
5399 {
5400 if (0 == b[i]) return false;
5401 }
5402
5403 return true;
5404 }
5405
5406 template <typename T,
5407 typename Allocator,
5408 template <typename, typename> class Sequence>
5409 inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5410 {
5411 for (std::size_t i = 0; i < b.size(); ++i)
5412 {
5413 if (0 == b[i]) return false;
5414 }
5415
5416 return true;
5417 }
5418
5419 template <std::size_t N, typename T>
5421 {
5422 for (std::size_t i = 0; i < N; ++i)
5423 {
5424 if (0 == b[i])
5425 return false;
5426 else if (!is_variable_node(b[i]))
5427 return false;
5428 }
5429
5430 return true;
5431 }
5432
5433 template <typename T,
5434 typename Allocator,
5435 template <typename, typename> class Sequence>
5436 inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5437 {
5438 for (std::size_t i = 0; i < b.size(); ++i)
5439 {
5440 if (0 == b[i])
5441 return false;
5442 else if (!is_variable_node(b[i]))
5443 return false;
5444 }
5445
5446 return true;
5447 }
5448
5449 template <typename Node>
5451 {
5452 public:
5453
5455
5457 typedef typename nci_t::node_pp_t node_pp_t;
5459
5461 {
5462 std::vector<node_pp_t> node_delete_list;
5463 node_delete_list.reserve(1000);
5464
5465 collect_nodes(root, node_delete_list);
5466
5467 for (std::size_t i = 0; i < node_delete_list.size(); ++i)
5468 {
5469 node_ptr_t& node = *node_delete_list[i];
5470 exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node)));
5471 delete node;
5472 node = reinterpret_cast<node_ptr_t>(0);
5473 }
5474 }
5475
5476 private:
5477
5478 static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
5479 {
5480 std::deque<node_ptr_t> node_list;
5481 node_list.push_back(root);
5482 node_delete_list.push_back(&root);
5483
5484 noderef_list_t child_node_delete_list;
5485 child_node_delete_list.reserve(1000);
5486
5487 while (!node_list.empty())
5488 {
5489 node_list.front()->collect_nodes(child_node_delete_list);
5490
5491 if (!child_node_delete_list.empty())
5492 {
5493 for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
5494 {
5495 node_pp_t& node = child_node_delete_list[i];
5496
5497 if (0 == (*node))
5498 {
5499 exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
5500 }
5501
5502 node_list.push_back(*node);
5503 }
5504
5505 node_delete_list.insert(
5506 node_delete_list.end(),
5507 child_node_delete_list.begin(), child_node_delete_list.end());
5508
5509 child_node_delete_list.clear();
5510 }
5511
5512 node_list.pop_front();
5513 }
5514
5515 std::reverse(node_delete_list.begin(), node_delete_list.end());
5516 }
5517 };
5518
5519 template <typename NodeAllocator, typename T, std::size_t N>
5520 inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5521 {
5522 for (std::size_t i = 0; i < N; ++i)
5523 {
5525 }
5526 }
5527
5528 template <typename NodeAllocator,
5529 typename T,
5530 typename Allocator,
5531 template <typename, typename> class Sequence>
5532 inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5533 {
5534 for (std::size_t i = 0; i < b.size(); ++i)
5535 {
5537 }
5538
5539 b.clear();
5540 }
5541
5542 template <typename NodeAllocator, typename T>
5543 inline void free_node(NodeAllocator&, expression_node<T>*& node)
5544 {
5545 if ((0 == node) || is_variable_node(node) || is_string_node(node))
5546 {
5547 return;
5548 }
5549
5551 ::delete_nodes(node);
5552 }
5553
5554 template <typename T>
5556 {
5557 if (0 != node)
5558 {
5560 ::delete_nodes(node);
5561 }
5562 }
5563
5564 template <typename Node>
5566 {
5568 : depth_set(false),
5569 depth(0)
5570 {}
5571
5572 virtual ~node_depth_base() {}
5573
5574 virtual std::size_t node_depth() const { return 1; }
5575
5576 std::size_t compute_node_depth(const Node* const& node) const
5577 {
5578 if (!depth_set)
5579 {
5580 depth = 1 + (node ? node->node_depth() : 0);
5581 depth_set = true;
5582 }
5583
5584 return depth;
5585 }
5586
5587 std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const
5588 {
5589 if (!depth_set)
5590 {
5591 depth = 1 + (branch.first ? branch.first->node_depth() : 0);
5592 depth_set = true;
5593 }
5594
5595 return depth;
5596 }
5597
5598 template <std::size_t N>
5599 std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const
5600 {
5601 if (!depth_set)
5602 {
5603 depth = 0;
5604 for (std::size_t i = 0; i < N; ++i)
5605 {
5606 if (branch[i].first)
5607 {
5608 depth = std::max(depth,branch[i].first->node_depth());
5609 }
5610 }
5611 depth += 1;
5612 depth_set = true;
5613 }
5614
5615 return depth;
5616 }
5617
5618 template <typename BranchType>
5619 std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
5620 {
5621 if (!depth_set)
5622 {
5624 depth_set = true;
5625 }
5626
5627 return depth;
5628 }
5629
5630 template <typename BranchType>
5631 std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
5632 const BranchType& n2) const
5633 {
5634 if (!depth_set)
5635 {
5636 depth = 1 + std::max(
5638 compute_node_depth(n2));
5639 depth_set = true;
5640 }
5641
5642 return depth;
5643 }
5644
5645 template <typename BranchType>
5646 std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
5647 const BranchType& n2, const BranchType& n3) const
5648 {
5649 if (!depth_set)
5650 {
5651 depth = 1 + std::max(
5654 depth_set = true;
5655 }
5656
5657 return depth;
5658 }
5659
5660 template <typename Allocator,
5661 template <typename, typename> class Sequence>
5662 std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const
5663 {
5664 if (!depth_set)
5665 {
5666 for (std::size_t i = 0; i < branch_list.size(); ++i)
5667 {
5668 if (branch_list[i])
5669 {
5670 depth = std::max(depth, compute_node_depth(branch_list[i]));
5671 }
5672 }
5673 depth_set = true;
5674 }
5675
5676 return depth;
5677 }
5678
5679 template <typename Allocator,
5680 template <typename, typename> class Sequence>
5681 std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const
5682 {
5683 if (!depth_set)
5684 {
5685 for (std::size_t i = 0; i < branch_list.size(); ++i)
5686 {
5687 if (branch_list[i].first)
5688 {
5689 depth = std::max(depth, compute_node_depth(branch_list[i].first));
5690 }
5691 }
5692 depth_set = true;
5693 }
5694
5695 return depth;
5696 }
5697
5698 mutable bool depth_set;
5699 mutable std::size_t depth;
5700
5701 template <typename NodeSequence>
5702 void collect(Node*const& node,
5703 const bool deletable,
5704 NodeSequence& delete_node_list) const
5705 {
5706 if ((0 != node) && deletable)
5707 {
5708 delete_node_list.push_back(const_cast<Node**>(&node));
5709 }
5710 }
5711
5712 template <typename NodeSequence>
5713 void collect(const std::pair<Node*, bool>& branch,
5714 NodeSequence& delete_node_list) const
5715 {
5716 collect(branch.first, branch.second, delete_node_list);
5717 }
5718
5719 template <typename NodeSequence>
5720 void collect(Node*& node,
5721 NodeSequence& delete_node_list) const
5722 {
5723 collect(node, branch_deletable(node), delete_node_list);
5724 }
5725
5726 template <std::size_t N, typename NodeSequence>
5727 void collect(const std::pair<Node*, bool>(&branch)[N],
5728 NodeSequence& delete_node_list) const
5729 {
5730 for (std::size_t i = 0; i < N; ++i)
5731 {
5732 collect(branch[i].first, branch[i].second, delete_node_list);
5733 }
5734 }
5735
5736 template <typename Allocator,
5737 template <typename, typename> class Sequence,
5738 typename NodeSequence>
5739 void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch,
5740 NodeSequence& delete_node_list) const
5741 {
5742 for (std::size_t i = 0; i < branch.size(); ++i)
5743 {
5744 collect(branch[i].first, branch[i].second, delete_node_list);
5745 }
5746 }
5747
5748 template <typename Allocator,
5749 template <typename, typename> class Sequence,
5750 typename NodeSequence>
5751 void collect(const Sequence<Node*, Allocator>& branch_list,
5752 NodeSequence& delete_node_list) const
5753 {
5754 for (std::size_t i = 0; i < branch_list.size(); ++i)
5755 {
5756 collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
5757 }
5758 }
5759
5760 template <typename Boolean,
5761 typename AllocatorT,
5762 typename AllocatorB,
5763 template <typename, typename> class Sequence,
5764 typename NodeSequence>
5765 void collect(const Sequence<Node*, AllocatorT>& branch_list,
5766 const Sequence<Boolean, AllocatorB>& branch_deletable_list,
5767 NodeSequence& delete_node_list) const
5768 {
5769 for (std::size_t i = 0; i < branch_list.size(); ++i)
5770 {
5771 collect(branch_list[i], branch_deletable_list[i], delete_node_list);
5772 }
5773 }
5774 };
5775
5776 template <typename Type>
5778 {
5779 private:
5780
5781 typedef Type value_type;
5782 typedef value_type* value_ptr;
5783 typedef const value_ptr const_value_ptr;
5784
5785 class vector_holder_base
5786 {
5787 public:
5788
5789 virtual ~vector_holder_base() {}
5790
5791 inline value_ptr operator[](const std::size_t& index) const
5792 {
5793 return value_at(index);
5794 }
5795
5796 inline std::size_t size() const
5797 {
5798 return vector_size();
5799 }
5800
5801 inline value_ptr data() const
5802 {
5803 return value_at(0);
5804 }
5805
5806 virtual inline bool rebaseable() const
5807 {
5808 return false;
5809 }
5810
5811 virtual void set_ref(value_ptr*) {}
5812
5813 protected:
5814
5815 virtual value_ptr value_at(const std::size_t&) const = 0;
5816 virtual std::size_t vector_size() const = 0;
5817 };
5818
5819 class array_vector_impl : public vector_holder_base
5820 {
5821 public:
5822
5823 array_vector_impl(const Type* vec, const std::size_t& vec_size)
5824 : vec_(vec),
5825 size_(vec_size)
5826 {}
5827
5828 protected:
5829
5830 value_ptr value_at(const std::size_t& index) const
5831 {
5832 if (index < size_)
5833 return const_cast<const_value_ptr>(vec_ + index);
5834 else
5835 return const_value_ptr(0);
5836 }
5837
5838 std::size_t vector_size() const
5839 {
5840 return size_;
5841 }
5842
5843 private:
5844
5845 array_vector_impl operator=(const array_vector_impl&);
5846
5847 const Type* vec_;
5848 const std::size_t size_;
5849 };
5850
5851 template <typename Allocator,
5852 template <typename, typename> class Sequence>
5853 class sequence_vector_impl : public vector_holder_base
5854 {
5855 public:
5856
5857 typedef Sequence<Type,Allocator> sequence_t;
5858
5859 sequence_vector_impl(sequence_t& seq)
5860 : sequence_(seq)
5861 {}
5862
5863 protected:
5864
5865 value_ptr value_at(const std::size_t& index) const
5866 {
5867 return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5868 }
5869
5870 std::size_t vector_size() const
5871 {
5872 return sequence_.size();
5873 }
5874
5875 private:
5876
5877 sequence_vector_impl operator=(const sequence_vector_impl&);
5878
5879 sequence_t& sequence_;
5880 };
5881
5882 class vector_view_impl : public vector_holder_base
5883 {
5884 public:
5885
5886 typedef exprtk::vector_view<Type> vector_view_t;
5887
5888 vector_view_impl(vector_view_t& vec_view)
5889 : vec_view_(vec_view)
5890 {}
5891
5892 void set_ref(value_ptr* ref)
5893 {
5894 vec_view_.set_ref(ref);
5895 }
5896
5897 virtual inline bool rebaseable() const
5898 {
5899 return true;
5900 }
5901
5902 protected:
5903
5904 value_ptr value_at(const std::size_t& index) const
5905 {
5906 return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5907 }
5908
5909 std::size_t vector_size() const
5910 {
5911 return vec_view_.size();
5912 }
5913
5914 private:
5915
5916 vector_view_impl operator=(const vector_view_impl&);
5917
5918 vector_view_t& vec_view_;
5919 };
5920
5921 public:
5922
5924
5925 vector_holder(Type* vec, const std::size_t& vec_size)
5926 : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5927 {}
5928
5930 : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5931 {}
5932
5933 template <typename Allocator>
5934 vector_holder(std::vector<Type,Allocator>& vec)
5935 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5936 {}
5937
5939 : vector_holder_base_(new(buffer)vector_view_impl(vec))
5940 {}
5941
5942 inline value_ptr operator[](const std::size_t& index) const
5943 {
5944 return (*vector_holder_base_)[index];
5945 }
5946
5947 inline std::size_t size() const
5948 {
5949 return vector_holder_base_->size();
5950 }
5951
5952 inline value_ptr data() const
5953 {
5954 return vector_holder_base_->data();
5955 }
5956
5957 void set_ref(value_ptr* ref)
5958 {
5959 vector_holder_base_->set_ref(ref);
5960 }
5961
5962 bool rebaseable() const
5963 {
5964 return vector_holder_base_->rebaseable();
5965 }
5966
5967 private:
5968
5969 mutable vector_holder_base* vector_holder_base_;
5970 uchar_t buffer[64];
5971 };
5972
5973 template <typename T>
5974 class null_node : public expression_node<T>
5975 {
5976 public:
5977
5978 inline T value() const
5979 {
5980 return std::numeric_limits<T>::quiet_NaN();
5981 }
5982
5983 inline typename expression_node<T>::node_type type() const
5984 {
5986 }
5987 };
5988
5989 template <typename T, std::size_t N>
5990 inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
5992 const std::size_t& index)
5993 {
5994 if (b && (index < N))
5995 {
5996 branch[index] = std::make_pair(b,branch_deletable(b));
5997 }
5998 }
5999
6000 template <typename T>
6001 inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
6002 {
6003 if (b)
6004 {
6005 branch = std::make_pair(b,branch_deletable(b));
6006 }
6007 }
6008
6009 template <std::size_t N, typename T>
6010 inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
6012 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
6013 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
6014 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
6015 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
6016 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
6017 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
6018 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
6019 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
6020 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
6021 {
6022 construct_branch_pair(branch, b0, 0);
6023 construct_branch_pair(branch, b1, 1);
6024 construct_branch_pair(branch, b2, 2);
6025 construct_branch_pair(branch, b3, 3);
6026 construct_branch_pair(branch, b4, 4);
6027 construct_branch_pair(branch, b5, 5);
6028 construct_branch_pair(branch, b6, 6);
6029 construct_branch_pair(branch, b7, 7);
6030 construct_branch_pair(branch, b8, 8);
6031 construct_branch_pair(branch, b9, 9);
6032 }
6033
6034 template <typename T>
6036 {
6037 public:
6038
6040 typedef std::pair<expression_ptr,bool> branch_t;
6041
6042 explicit null_eq_node(expression_ptr branch, const bool equality = true)
6043 : equality_(equality)
6044 {
6045 construct_branch_pair(branch_, branch);
6046 }
6047
6048 inline T value() const
6049 {
6050 assert(branch_.first);
6051
6052 const T v = branch_.first->value();
6053 const bool result = details::numeric::is_nan(v);
6054
6055 if (result)
6056 return (equality_) ? T(1) : T(0);
6057 else
6058 return (equality_) ? T(0) : T(1);
6059 }
6060
6061 inline typename expression_node<T>::node_type type() const
6062 {
6064 }
6065
6067 {
6068 return details::e_eq;
6069 }
6070
6071 inline expression_node<T>* branch(const std::size_t&) const
6072 {
6073 return branch_.first;
6074 }
6075
6076 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6077 {
6078 expression_node<T>::ndb_t::collect(branch_,node_delete_list);
6079 }
6080
6081 std::size_t node_depth() const
6082 {
6084 }
6085
6086 private:
6087
6088 bool equality_;
6089 branch_t branch_;
6090 };
6091
6092 template <typename T>
6094 {
6095 public:
6096
6097 explicit literal_node(const T& v)
6098 : value_(v)
6099 {}
6100
6101 inline T value() const
6102 {
6103 return value_;
6104 }
6105
6106 inline typename expression_node<T>::node_type type() const
6107 {
6109 }
6110
6111 inline expression_node<T>* branch(const std::size_t&) const
6112 {
6113 return reinterpret_cast<expression_node<T>*>(0);
6114 }
6115
6116 private:
6117
6119 literal_node<T>& operator=(literal_node<T>&) { return (*this); }
6120
6121 const T value_;
6122 };
6123
6124 template <typename T>
6125 struct range_pack;
6126
6127 template <typename T>
6128 struct range_data_type;
6129
6130 template <typename T>
6132 {
6133 public:
6134
6136
6138 {}
6139
6140 virtual range_t& range_ref() = 0;
6141
6142 virtual const range_t& range_ref() const = 0;
6143 };
6144
6145 #ifndef exprtk_disable_string_capabilities
6146 template <typename T>
6148 {
6149 public:
6150
6152
6154 {}
6155
6156 virtual std::string str () const = 0;
6157
6158 virtual char_cptr base() const = 0;
6159
6160 virtual std::size_t size() const = 0;
6161 };
6162
6163 template <typename T>
6165 public string_base_node<T>,
6166 public range_interface <T>
6167 {
6168 public:
6169
6171
6173 : value_(v)
6174 {
6175 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
6176 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
6177 rp_.cache.first = rp_.n0_c.second;
6178 rp_.cache.second = rp_.n1_c.second;
6179 }
6180
6181 inline T value() const
6182 {
6183 return std::numeric_limits<T>::quiet_NaN();
6184 }
6185
6186 inline typename expression_node<T>::node_type type() const
6187 {
6189 }
6190
6191 inline expression_node<T>* branch(const std::size_t&) const
6192 {
6193 return reinterpret_cast<expression_node<T>*>(0);
6194 }
6195
6197 {
6198 return value_;
6199 }
6200
6202 {
6203 return value_.data();
6204 }
6205
6206 std::size_t size() const
6207 {
6208 return value_.size();
6209 }
6210
6212 {
6213 return rp_;
6214 }
6215
6216 const range_t& range_ref() const
6217 {
6218 return rp_;
6219 }
6220
6221 private:
6222
6225
6226 const std::string value_;
6227 range_t rp_;
6228 };
6229 #endif
6230
6231 template <typename T>
6232 class unary_node : public expression_node<T>
6233 {
6234 public:
6235
6237 typedef std::pair<expression_ptr,bool> branch_t;
6238
6240 : operation_(opr)
6241 {
6243 }
6244
6245 inline T value() const
6246 {
6247 assert(branch_.first);
6248
6249 const T arg = branch_.first->value();
6250
6251 return numeric::process<T>(operation_,arg);
6252 }
6253
6254 inline typename expression_node<T>::node_type type() const
6255 {
6257 }
6258
6260 {
6261 return operation_;
6262 }
6263
6264 inline expression_node<T>* branch(const std::size_t&) const
6265 {
6266 return branch_.first;
6267 }
6268
6269 inline void release()
6270 {
6271 branch_.second = false;
6272 }
6273
6274 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6275 {
6277 }
6278
6279 std::size_t node_depth() const
6280 {
6282 }
6283
6284 protected:
6285
6288 };
6289
6290 template <typename T>
6292 {
6293 public:
6294
6296 typedef std::pair<expression_ptr,bool> branch_t;
6297
6299 expression_ptr branch0,
6300 expression_ptr branch1)
6301 : operation_(opr)
6302 {
6303 init_branches<2>(branch_, branch0, branch1);
6304 }
6305
6306 inline T value() const
6307 {
6308 assert(branch_[0].first);
6309 assert(branch_[1].first);
6310
6311 const T arg0 = branch_[0].first->value();
6312 const T arg1 = branch_[1].first->value();
6313
6314 return numeric::process<T>(operation_,arg0,arg1);
6315 }
6316
6317 inline typename expression_node<T>::node_type type() const
6318 {
6320 }
6321
6323 {
6324 return operation_;
6325 }
6326
6327 inline expression_node<T>* branch(const std::size_t& index = 0) const
6328 {
6329 if (0 == index)
6330 return branch_[0].first;
6331 else if (1 == index)
6332 return branch_[1].first;
6333 else
6334 return reinterpret_cast<expression_ptr>(0);
6335 }
6336
6337 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6338 {
6340 }
6341
6342 std::size_t node_depth() const
6343 {
6344 return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
6345 }
6346
6347 protected:
6348
6351 };
6352
6353 template <typename T, typename Operation>
6355 {
6356 public:
6357
6359 typedef std::pair<expression_ptr,bool> branch_t;
6360
6362 {
6363 init_branches<2>(branch_, branch0, branch1);
6364 }
6365
6366 inline T value() const
6367 {
6368 assert(branch_[0].first);
6369 assert(branch_[1].first);
6370
6371 const T arg0 = branch_[0].first->value();
6372 const T arg1 = branch_[1].first->value();
6373
6374 return Operation::process(arg0,arg1);
6375 }
6376
6377 inline typename expression_node<T>::node_type type() const
6378 {
6380 }
6381
6383 {
6384 return Operation::operation();
6385 }
6386
6387 inline expression_node<T>* branch(const std::size_t& index = 0) const
6388 {
6389 if (0 == index)
6390 return branch_[0].first;
6391 else if (1 == index)
6392 return branch_[1].first;
6393 else
6394 return reinterpret_cast<expression_ptr>(0);
6395 }
6396
6397 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6398 {
6400 }
6401
6402 std::size_t node_depth() const
6403 {
6404 return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
6405 }
6406
6407 protected:
6408
6410 };
6411
6412 template <typename T>
6414 {
6415 public:
6416
6418 typedef std::pair<expression_ptr,bool> branch_t;
6419
6421 expression_ptr branch0,
6422 expression_ptr branch1,
6423 expression_ptr branch2)
6424 : operation_(opr)
6425 {
6426 init_branches<3>(branch_, branch0, branch1, branch2);
6427 }
6428
6429 inline T value() const
6430 {
6431 assert(branch_[0].first);
6432 assert(branch_[1].first);
6433 assert(branch_[2].first);
6434
6435 const T arg0 = branch_[0].first->value();
6436 const T arg1 = branch_[1].first->value();
6437 const T arg2 = branch_[2].first->value();
6438
6439 switch (operation_)
6440 {
6441 case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6442
6443 case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6444
6445 case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
6446 return arg1;
6447 else
6448 return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
6449
6450 default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6451 return std::numeric_limits<T>::quiet_NaN();
6452 }
6453 }
6454
6455 inline typename expression_node<T>::node_type type() const
6456 {
6458 }
6459
6460 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6461 {
6463 }
6464
6465 std::size_t node_depth() const
6466 {
6467 return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
6468 }
6469
6470 protected:
6471
6474 };
6475
6476 template <typename T>
6478 {
6479 public:
6480
6482 typedef std::pair<expression_ptr,bool> branch_t;
6483
6485 expression_ptr branch0,
6486 expression_ptr branch1,
6487 expression_ptr branch2,
6488 expression_ptr branch3)
6489 : operation_(opr)
6490 {
6491 init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6492 }
6493
6494 inline T value() const
6495 {
6496 return std::numeric_limits<T>::quiet_NaN();
6497 }
6498
6499 inline typename expression_node<T>::node_type type() const
6500 {
6502 }
6503
6504 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6505 {
6507 }
6508
6509 std::size_t node_depth() const
6510 {
6511 return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
6512 }
6513
6514 protected:
6515
6518 };
6519
6520 template <typename T>
6522 {
6523 public:
6524
6526 typedef std::pair<expression_ptr,bool> branch_t;
6527
6529 expression_ptr consequent,
6530 expression_ptr alternative)
6531 {
6532 construct_branch_pair(condition_ , condition );
6533 construct_branch_pair(consequent_ , consequent );
6534 construct_branch_pair(alternative_, alternative);
6535 }
6536
6537 inline T value() const
6538 {
6539 assert(condition_ .first);
6540 assert(consequent_ .first);
6541 assert(alternative_.first);
6542
6543 if (is_true(condition_))
6544 return consequent_.first->value();
6545 else
6546 return alternative_.first->value();
6547 }
6548
6549 inline typename expression_node<T>::node_type type() const
6550 {
6552 }
6553
6554 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6555 {
6556 expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
6557 expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
6558 expression_node<T>::ndb_t::collect(alternative_, node_delete_list);
6559 }
6560
6561 std::size_t node_depth() const
6562 {
6564 (condition_, consequent_, alternative_);
6565 }
6566
6567 private:
6568
6569 branch_t condition_;
6570 branch_t consequent_;
6571 branch_t alternative_;
6572 };
6573
6574 template <typename T>
6576 {
6577 public:
6578
6579 // Consequent only conditional statement node
6581 typedef std::pair<expression_ptr,bool> branch_t;
6582
6584 expression_ptr consequent)
6585 {
6586 construct_branch_pair(condition_ , condition );
6587 construct_branch_pair(consequent_, consequent);
6588 }
6589
6590 inline T value() const
6591 {
6592 assert(condition_ .first);
6593 assert(consequent_.first);
6594
6595 if (is_true(condition_))
6596 return consequent_.first->value();
6597 else
6598 return std::numeric_limits<T>::quiet_NaN();
6599 }
6600
6601 inline typename expression_node<T>::node_type type() const
6602 {
6604 }
6605
6606 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6607 {
6608 expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
6609 expression_node<T>::ndb_t::collect(consequent_, node_delete_list);
6610 }
6611
6612 std::size_t node_depth() const
6613 {
6615 compute_node_depth(condition_, consequent_);
6616 }
6617
6618 private:
6619
6620 branch_t condition_;
6621 branch_t consequent_;
6622 };
6623
6624 #ifndef exprtk_disable_break_continue
6625 template <typename T>
6627 {
6628 public:
6629
6630 explicit break_exception(const T& v)
6631 : value(v)
6632 {}
6633
6635 };
6636
6638 {};
6639
6640 template <typename T>
6641 class break_node : public expression_node<T>
6642 {
6643 public:
6644
6646 typedef std::pair<expression_ptr,bool> branch_t;
6647
6649 {
6650 construct_branch_pair(return_, ret);
6651 }
6652
6653 inline T value() const
6654 {
6655 throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN());
6656 #ifndef _MSC_VER
6657 return std::numeric_limits<T>::quiet_NaN();
6658 #endif
6659 }
6660
6661 inline typename expression_node<T>::node_type type() const
6662 {
6664 }
6665
6666 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6667 {
6668 expression_node<T>::ndb_t::collect(return_, node_delete_list);
6669 }
6670
6671 std::size_t node_depth() const
6672 {
6674 }
6675
6676 private:
6677
6678 branch_t return_;
6679 };
6680
6681 template <typename T>
6683 {
6684 public:
6685
6686 inline T value() const
6687 {
6688 throw continue_exception();
6689 #ifndef _MSC_VER
6690 return std::numeric_limits<T>::quiet_NaN();
6691 #endif
6692 }
6693
6694 inline typename expression_node<T>::node_type type() const
6695 {
6697 }
6698 };
6699 #endif
6700
6701 #ifdef exprtk_enable_runtime_checks
6702 struct loop_runtime_checker
6703 {
6706 : iteration_count_(0),
6707 loop_runtime_check_(loop_rt_chk),
6708 loop_type(lp_typ)
6709 {}
6710
6711 inline void reset(const _uint64_t initial_value = 0) const
6712 {
6713 iteration_count_ = initial_value;
6714 }
6715
6716 inline bool check() const
6717 {
6718 if (
6719 (0 == loop_runtime_check_) ||
6720 (++iteration_count_ <= loop_runtime_check_->max_loop_iterations)
6721 )
6722 {
6723 return true;
6724 }
6725
6726 loop_runtime_check::violation_context ctxt;
6727 ctxt.loop = loop_type;
6729
6730 loop_runtime_check_->handle_runtime_violation(ctxt);
6731
6732 return false;
6733 }
6734
6735 mutable _uint64_t iteration_count_;
6736 mutable loop_runtime_check_ptr loop_runtime_check_;
6738 };
6739 #else
6741 {
6743 {}
6744
6745 inline void reset(const _uint64_t = 0) const
6746 {}
6747
6748 inline bool check() const
6749 {
6750 return true;
6751 }
6752 };
6753 #endif
6754
6755 template <typename T>
6758 {
6759 public:
6760
6762 typedef std::pair<expression_ptr,bool> branch_t;
6763
6765 expression_ptr loop_body,
6767 : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop)
6768 {
6769 construct_branch_pair(condition_, condition);
6770 construct_branch_pair(loop_body_, loop_body);
6771 }
6772
6773 inline T value() const
6774 {
6775 assert(condition_.first);
6776 assert(loop_body_.first);
6777
6778 T result = T(0);
6779
6781
6782 while (is_true(condition_) && loop_runtime_checker::check())
6783 {
6784 result = loop_body_.first->value();
6785 }
6786
6787 return result;
6788 }
6789
6790 inline typename expression_node<T>::node_type type() const
6791 {
6793 }
6794
6795 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6796 {
6797 expression_node<T>::ndb_t::collect(condition_, node_delete_list);
6798 expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
6799 }
6800
6801 std::size_t node_depth() const
6802 {
6803 return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
6804 }
6805
6806 private:
6807
6808 branch_t condition_;
6809 branch_t loop_body_;
6810 };
6811
6812 template <typename T>
6815 {
6816 public:
6817
6819 typedef std::pair<expression_ptr,bool> branch_t;
6820
6822 expression_ptr loop_body,
6824 : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
6825 {
6826 construct_branch_pair(condition_, condition);
6827 construct_branch_pair(loop_body_, loop_body);
6828 }
6829
6830 inline T value() const
6831 {
6832 assert(condition_.first);
6833 assert(loop_body_.first);
6834
6835 T result = T(0);
6836
6838
6839 do
6840 {
6841 result = loop_body_.first->value();
6842 }
6843 while (is_false(condition_.first) && loop_runtime_checker::check());
6844
6845 return result;
6846 }
6847
6848 inline typename expression_node<T>::node_type type() const
6849 {
6851 }
6852
6853 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6854 {
6855 expression_node<T>::ndb_t::collect(condition_, node_delete_list);
6856 expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
6857 }
6858
6859 std::size_t node_depth() const
6860 {
6861 return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
6862 }
6863
6864 private:
6865
6866 branch_t condition_;
6867 branch_t loop_body_;
6868 };
6869
6870 template <typename T>
6873 {
6874 public:
6875
6877 typedef std::pair<expression_ptr,bool> branch_t;
6878
6880 expression_ptr condition,
6881 expression_ptr incrementor,
6882 expression_ptr loop_body,
6884 : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
6885 {
6886 construct_branch_pair(initialiser_, initialiser);
6887 construct_branch_pair(condition_ , condition );
6888 construct_branch_pair(incrementor_, incrementor);
6889 construct_branch_pair(loop_body_ , loop_body );
6890 }
6891
6892 inline T value() const
6893 {
6894 assert(condition_.first);
6895 assert(loop_body_.first);
6896
6897 T result = T(0);
6898
6900
6901 if (initialiser_.first)
6902 initialiser_.first->value();
6903
6904 if (incrementor_.first)
6905 {
6906 while (is_true(condition_) && loop_runtime_checker::check())
6907 {
6908 result = loop_body_.first->value();
6909 incrementor_.first->value();
6910 }
6911 }
6912 else
6913 {
6914 while (is_true(condition_) && loop_runtime_checker::check())
6915 {
6916 result = loop_body_.first->value();
6917 }
6918 }
6919
6920 return result;
6921 }
6922
6923 inline typename expression_node<T>::node_type type() const
6924 {
6926 }
6927
6928 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6929 {
6930 expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
6931 expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
6932 expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
6933 expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
6934 }
6935
6936 std::size_t node_depth() const
6937 {
6939 (initialiser_, condition_, incrementor_, loop_body_);
6940 }
6941
6942 private:
6943
6944 branch_t initialiser_;
6945 branch_t condition_ ;
6946 branch_t incrementor_;
6947 branch_t loop_body_ ;
6948 };
6949
6950 #ifndef exprtk_disable_break_continue
6951 template <typename T>
6954 {
6955 public:
6956
6958 typedef std::pair<expression_ptr,bool> branch_t;
6959
6961 expression_ptr loop_body,
6963 : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
6964 {
6965 construct_branch_pair(condition_, condition);
6966 construct_branch_pair(loop_body_, loop_body);
6967 }
6968
6969 inline T value() const
6970 {
6971 assert(condition_.first);
6972 assert(loop_body_.first);
6973
6974 T result = T(0);
6975
6977
6978 while (is_true(condition_) && loop_runtime_checker::check())
6979 {
6980 try
6981 {
6982 result = loop_body_.first->value();
6983 }
6984 catch(const break_exception<T>& e)
6985 {
6986 return e.value;
6987 }
6988 catch(const continue_exception&)
6989 {}
6990 }
6991
6992 return result;
6993 }
6994
6995 inline typename expression_node<T>::node_type type() const
6996 {
6998 }
6999
7000 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7001 {
7002 expression_node<T>::ndb_t::collect(condition_, node_delete_list);
7003 expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
7004 }
7005
7006 std::size_t node_depth() const
7007 {
7008 return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7009 }
7010
7011 private:
7012
7013 branch_t condition_;
7014 branch_t loop_body_;
7015 };
7016
7017 template <typename T>
7020 {
7021 public:
7022
7024 typedef std::pair<expression_ptr,bool> branch_t;
7025
7027 expression_ptr loop_body,
7029 : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
7030 {
7031 construct_branch_pair(condition_, condition);
7032 construct_branch_pair(loop_body_, loop_body);
7033 }
7034
7035 inline T value() const
7036 {
7037 assert(condition_.first);
7038 assert(loop_body_.first);
7039
7040 T result = T(0);
7041
7043
7044 do
7045 {
7046 try
7047 {
7048 result = loop_body_.first->value();
7049 }
7050 catch(const break_exception<T>& e)
7051 {
7052 return e.value;
7053 }
7054 catch(const continue_exception&)
7055 {}
7056 }
7057 while (is_false(condition_.first) && loop_runtime_checker::check());
7058
7059 return result;
7060 }
7061
7062 inline typename expression_node<T>::node_type type() const
7063 {
7065 }
7066
7067 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7068 {
7069 expression_node<T>::ndb_t::collect(condition_, node_delete_list);
7070 expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
7071 }
7072
7073 std::size_t node_depth() const
7074 {
7075 return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7076 }
7077
7078 private:
7079
7080 branch_t condition_;
7081 branch_t loop_body_;
7082 };
7083
7084 template <typename T>
7087 {
7088 public:
7089
7091 typedef std::pair<expression_ptr,bool> branch_t;
7092
7094 expression_ptr condition,
7095 expression_ptr incrementor,
7096 expression_ptr loop_body,
7098 : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
7099 {
7100 construct_branch_pair(initialiser_, initialiser);
7101 construct_branch_pair(condition_ , condition );
7102 construct_branch_pair(incrementor_, incrementor);
7103 construct_branch_pair(loop_body_ , loop_body );
7104 }
7105
7106 inline T value() const
7107 {
7108 assert(condition_.first);
7109 assert(loop_body_.first);
7110
7111 T result = T(0);
7112
7114
7115 if (initialiser_.first)
7116 initialiser_.first->value();
7117
7118 if (incrementor_.first)
7119 {
7120 while (is_true(condition_) && loop_runtime_checker::check())
7121 {
7122 try
7123 {
7124 result = loop_body_.first->value();
7125 }
7126 catch(const break_exception<T>& e)
7127 {
7128 return e.value;
7129 }
7130 catch(const continue_exception&)
7131 {}
7132
7133 incrementor_.first->value();
7134 }
7135 }
7136 else
7137 {
7138 while (is_true(condition_) && loop_runtime_checker::check())
7139 {
7140 try
7141 {
7142 result = loop_body_.first->value();
7143 }
7144 catch(const break_exception<T>& e)
7145 {
7146 return e.value;
7147 }
7148 catch(const continue_exception&)
7149 {}
7150 }
7151 }
7152
7153 return result;
7154 }
7155
7156 inline typename expression_node<T>::node_type type() const
7157 {
7159 }
7160
7161 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7162 {
7163 expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
7164 expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7165 expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
7166 expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
7167 }
7168
7169 std::size_t node_depth() const
7170 {
7172 (initialiser_, condition_, incrementor_, loop_body_);
7173 }
7174
7175 private:
7176
7177 branch_t initialiser_;
7178 branch_t condition_ ;
7179 branch_t incrementor_;
7180 branch_t loop_body_ ;
7181 };
7182 #endif
7183
7184 template <typename T>
7186 {
7187 public:
7188
7190 typedef std::pair<expression_ptr,bool> branch_t;
7191
7192 template <typename Allocator,
7193 template <typename, typename> class Sequence>
7194 explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
7195 {
7196 if (1 != (arg_list.size() & 1))
7197 return;
7198
7199 arg_list_.resize(arg_list.size());
7200
7201 for (std::size_t i = 0; i < arg_list.size(); ++i)
7202 {
7203 if (arg_list[i])
7204 {
7205 construct_branch_pair(arg_list_[i], arg_list[i]);
7206 }
7207 else
7208 {
7209 arg_list_.clear();
7210 return;
7211 }
7212 }
7213 }
7214
7215 inline T value() const
7216 {
7217 if (!arg_list_.empty())
7218 {
7219 const std::size_t upper_bound = (arg_list_.size() - 1);
7220
7221 for (std::size_t i = 0; i < upper_bound; i += 2)
7222 {
7223 expression_ptr condition = arg_list_[i ].first;
7224 expression_ptr consequent = arg_list_[i + 1].first;
7225
7226 if (is_true(condition))
7227 {
7228 return consequent->value();
7229 }
7230 }
7231
7232 return arg_list_[upper_bound].first->value();
7233 }
7234 else
7235 return std::numeric_limits<T>::quiet_NaN();
7236 }
7237
7238 inline typename expression_node<T>::node_type type() const
7239 {
7241 }
7242
7243 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7244 {
7246 }
7247
7248 std::size_t node_depth() const
7249 {
7251 }
7252
7253 protected:
7254
7255 std::vector<branch_t> arg_list_;
7256 };
7257
7258 template <typename T, typename Switch_N>
7259 class switch_n_node : public switch_node<T>
7260 {
7261 public:
7262
7264
7265 template <typename Allocator,
7266 template <typename, typename> class Sequence>
7267 explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
7268 : switch_node<T>(arg_list)
7269 {}
7270
7271 inline T value() const
7272 {
7274 }
7275 };
7276
7277 template <typename T>
7279 {
7280 public:
7281
7283 typedef std::pair<expression_ptr,bool> branch_t;
7284
7285 template <typename Allocator,
7286 template <typename, typename> class Sequence>
7287 explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
7288 {
7289 if (0 != (arg_list.size() & 1))
7290 return;
7291
7292 arg_list_.resize(arg_list.size());
7293
7294 for (std::size_t i = 0; i < arg_list.size(); ++i)
7295 {
7296 if (arg_list[i])
7297 {
7298 construct_branch_pair(arg_list_[i], arg_list[i]);
7299 }
7300 else
7301 {
7302 arg_list_.clear();
7303 return;
7304 }
7305 }
7306 }
7307
7308 inline T value() const
7309 {
7310 T result = T(0);
7311
7312 if (arg_list_.empty())
7313 {
7314 return std::numeric_limits<T>::quiet_NaN();
7315 }
7316
7317 const std::size_t upper_bound = (arg_list_.size() - 1);
7318
7319 for (std::size_t i = 0; i < upper_bound; i += 2)
7320 {
7321 expression_ptr condition = arg_list_[i ].first;
7322 expression_ptr consequent = arg_list_[i + 1].first;
7323
7324 if (is_true(condition))
7325 {
7326 result = consequent->value();
7327 }
7328 }
7329
7330 return result;
7331 }
7332
7333 inline typename expression_node<T>::node_type type() const
7334 {
7336 }
7337
7338 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7339 {
7340 expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
7341 }
7342
7343 std::size_t node_depth() const
7344 {
7346 }
7347
7348 private:
7349
7350 std::vector<branch_t> arg_list_;
7351 };
7352
7353 template <typename T>
7355 {
7356 public:
7357
7358 virtual ~ivariable()
7359 {}
7360
7361 virtual T& ref() = 0;
7362 virtual const T& ref() const = 0;
7363 };
7364
7365 template <typename T>
7367 public ivariable <T>
7368 {
7369 public:
7370
7371 static T null_value;
7372
7373 explicit variable_node()
7374 : value_(&null_value)
7375 {}
7376
7377 explicit variable_node(T& v)
7378 : value_(&v)
7379 {}
7380
7381 inline bool operator <(const variable_node<T>& v) const
7382 {
7383 return this < (&v);
7384 }
7385
7386 inline T value() const
7387 {
7388 return (*value_);
7389 }
7390
7391 inline T& ref()
7392 {
7393 return (*value_);
7394 }
7395
7396 inline const T& ref() const
7397 {
7398 return (*value_);
7399 }
7400
7401 inline typename expression_node<T>::node_type type() const
7402 {
7404 }
7405
7406 private:
7407
7408 T* value_;
7409 };
7410
7411 template <typename T>
7412 T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
7413
7414 template <typename T>
7416 {
7418 typedef std::pair<std::size_t,std::size_t> cached_range_t;
7419
7421 : n0_e (std::make_pair(false,expression_node_ptr(0))),
7422 n1_e (std::make_pair(false,expression_node_ptr(0))),
7423 n0_c (std::make_pair(false,0)),
7424 n1_c (std::make_pair(false,0)),
7425 cache(std::make_pair(0,0))
7426 {}
7427
7428 void clear()
7429 {
7430 n0_e = std::make_pair(false,expression_node_ptr(0));
7431 n1_e = std::make_pair(false,expression_node_ptr(0));
7432 n0_c = std::make_pair(false,0);
7433 n1_c = std::make_pair(false,0);
7434 cache = std::make_pair(0,0);
7435 }
7436
7437 void free()
7438 {
7439 if (n0_e.first && n0_e.second)
7440 {
7441 n0_e.first = false;
7442
7443 if (
7444 !is_variable_node(n0_e.second) &&
7445 !is_string_node (n0_e.second)
7446 )
7447 {
7448 destroy_node(n0_e.second);
7449 }
7450 }
7451
7452 if (n1_e.first && n1_e.second)
7453 {
7454 n1_e.first = false;
7455
7456 if (
7457 !is_variable_node(n1_e.second) &&
7458 !is_string_node (n1_e.second)
7459 )
7460 {
7461 destroy_node(n1_e.second);
7462 }
7463 }
7464 }
7465
7466 bool const_range() const
7467 {
7468 return ( n0_c.first && n1_c.first) &&
7469 (!n0_e.first && !n1_e.first);
7470 }
7471
7472 bool var_range() const
7473 {
7474 return ( n0_e.first && n1_e.first) &&
7475 (!n0_c.first && !n1_c.first);
7476 }
7477
7478 bool operator() (std::size_t& r0, std::size_t& r1,
7479 const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
7480 {
7481 if (n0_c.first)
7482 r0 = n0_c.second;
7483 else if (n0_e.first)
7484 {
7485 r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
7486 }
7487 else
7488 return false;
7489
7490 if (n1_c.first)
7491 r1 = n1_c.second;
7492 else if (n1_e.first)
7493 {
7494 r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
7495 }
7496 else
7497 return false;
7498
7499 if (
7502 )
7503 {
7504 r1 = size - 1;
7505 }
7506
7507 cache.first = r0;
7508 cache.second = r1;
7509
7510 #ifndef exprtk_enable_runtime_checks
7511 return (r0 <= r1);
7512 #else
7513 return range_runtime_check(r0, r1, size);
7514 #endif
7515 }
7516
7517 inline std::size_t const_size() const
7518 {
7519 return (n1_c.second - n0_c.second + 1);
7520 }
7521
7522 inline std::size_t cache_size() const
7523 {
7524 return (cache.second - cache.first + 1);
7525 }
7526
7527 std::pair<bool,expression_node_ptr> n0_e;
7528 std::pair<bool,expression_node_ptr> n1_e;
7529 std::pair<bool,std::size_t > n0_c;
7530 std::pair<bool,std::size_t > n1_c;
7532
7533 #ifdef exprtk_enable_runtime_checks
7534 bool range_runtime_check(const std::size_t r0,
7535 const std::size_t r1,
7536 const std::size_t size) const
7537 {
7538 if (r0 >= size)
7539 {
7540 throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)");
7541 return false;
7542 }
7543
7544 if (r1 >= size)
7545 {
7546 throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)");
7547 return false;
7548 }
7549
7550 return (r0 <= r1);
7551 }
7552 #endif
7553 };
7554
7555 template <typename T>
7556 class string_base_node;
7557
7558 template <typename T>
7560 {
7563
7565 : range(0),
7566 data (0),
7567 size (0),
7568 type_size(0),
7569 str_node (0)
7570 {}
7571
7573 void* data;
7574 std::size_t size;
7575 std::size_t type_size;
7577 };
7578
7579 template <typename T> class vector_node;
7580
7581 template <typename T>
7583 {
7584 public:
7585
7588
7590 {}
7591
7592 virtual std::size_t size () const = 0;
7593
7594 virtual vector_node_ptr vec() const = 0;
7595
7596 virtual vector_node_ptr vec() = 0;
7597
7598 virtual vds_t& vds () = 0;
7599
7600 virtual const vds_t& vds () const = 0;
7601
7602 virtual bool side_effect () const { return false; }
7603 };
7604
7605 template <typename T>
7606 class vector_node : public expression_node <T>,
7607 public vector_interface<T>
7608 {
7609 public:
7610
7615
7617 : vector_holder_(vh),
7618 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7619 {
7620 vector_holder_->set_ref(&vds_.ref());
7621 }
7622
7624 : vector_holder_(vh),
7625 vds_(vds)
7626 {}
7627
7628 inline T value() const
7629 {
7630 return vds().data()[0];
7631 }
7632
7634 {
7635 return const_cast<vector_node_ptr>(this);
7636 }
7637
7639 {
7640 return this;
7641 }
7642
7643 inline typename expression_node<T>::node_type type() const
7644 {
7646 }
7647
7648 std::size_t size() const
7649 {
7650 return vds().size();
7651 }
7652
7654 {
7655 return vds_;
7656 }
7657
7658 const vds_t& vds() const
7659 {
7660 return vds_;
7661 }
7662
7664 {
7665 return (*vector_holder_);
7666 }
7667
7668 private:
7669
7670 vector_holder_t* vector_holder_;
7671 vds_t vds_;
7672 };
7673
7674 template <typename T>
7676 public ivariable <T>
7677 {
7678 public:
7679
7683 typedef std::pair<expression_ptr,bool> branch_t;
7684
7686 : vec_holder_(vec_holder),
7687 vector_base_((*vec_holder)[0])
7688 {
7690 }
7691
7692 inline T value() const
7693 {
7694 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7695 }
7696
7697 inline T& ref()
7698 {
7699 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7700 }
7701
7702 inline const T& ref() const
7703 {
7704 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7705 }
7706
7707 inline typename expression_node<T>::node_type type() const
7708 {
7710 }
7711
7713 {
7714 return (*vec_holder_);
7715 }
7716
7717 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7718 {
7719 expression_node<T>::ndb_t::collect(index_, node_delete_list);
7720 }
7721
7722 std::size_t node_depth() const
7723 {
7725 }
7726
7727 private:
7728
7729 vector_holder_ptr vec_holder_;
7730 T* vector_base_;
7731 branch_t index_;
7732 };
7733
7734 template <typename T>
7736 public ivariable <T>
7737 {
7738 public:
7739
7744 typedef std::pair<expression_ptr,bool> branch_t;
7745
7747 : vector_holder_(vec_holder),
7748 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7749 {
7750 vector_holder_->set_ref(&vds_.ref());
7752 }
7753
7754 inline T value() const
7755 {
7756 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7757 }
7758
7759 inline T& ref()
7760 {
7761 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7762 }
7763
7764 inline const T& ref() const
7765 {
7766 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7767 }
7768
7769 inline typename expression_node<T>::node_type type() const
7770 {
7772 }
7773
7775 {
7776 return (*vector_holder_);
7777 }
7778
7779 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7780 {
7781 expression_node<T>::ndb_t::template collect(index_, node_delete_list);
7782 }
7783
7784 std::size_t node_depth() const
7785 {
7787 }
7788
7789 private:
7790
7791 vector_holder_ptr vector_holder_;
7792 vds_t vds_;
7793 branch_t index_;
7794 };
7795
7796 template <typename T>
7798 public ivariable <T>
7799 {
7800 public:
7801
7806
7808 : index_(index),
7809 vector_holder_(vec_holder),
7810 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7811 {
7812 vector_holder_->set_ref(&vds_.ref());
7813 }
7814
7815 inline T value() const
7816 {
7817 return *(vds_.data() + index_);
7818 }
7819
7820 inline T& ref()
7821 {
7822 return *(vds_.data() + index_);
7823 }
7824
7825 inline const T& ref() const
7826 {
7827 return *(vds_.data() + index_);
7828 }
7829
7830 inline typename expression_node<T>::node_type type() const
7831 {
7833 }
7834
7836 {
7837 return (*vector_holder_);
7838 }
7839
7840 private:
7841
7842 const std::size_t index_;
7843 vector_holder_ptr vector_holder_;
7844 vds_t vds_;
7845 };
7846
7847 template <typename T>
7849 {
7850 public:
7851
7853
7855 const std::size_t& size,
7856 const std::vector<expression_ptr>& initialiser_list,
7857 const bool single_value_initialse)
7858 : vector_base_(vector_base),
7859 initialiser_list_(initialiser_list),
7860 size_(size),
7861 single_value_initialse_(single_value_initialse)
7862 {}
7863
7864 inline T value() const
7865 {
7866 if (single_value_initialse_)
7867 {
7868 for (std::size_t i = 0; i < size_; ++i)
7869 {
7870 *(vector_base_ + i) = initialiser_list_[0]->value();
7871 }
7872 }
7873 else
7874 {
7875 std::size_t il_size = initialiser_list_.size();
7876
7877 for (std::size_t i = 0; i < il_size; ++i)
7878 {
7879 *(vector_base_ + i) = initialiser_list_[i]->value();
7880 }
7881
7882 if (il_size < size_)
7883 {
7884 for (std::size_t i = il_size; i < size_; ++i)
7885 {
7886 *(vector_base_ + i) = T(0);
7887 }
7888 }
7889 }
7890
7891 return *(vector_base_);
7892 }
7893
7894 inline typename expression_node<T>::node_type type() const
7895 {
7897 }
7898
7899 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7900 {
7901 expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
7902 }
7903
7904 std::size_t node_depth() const
7905 {
7906 return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
7907 }
7908
7909 private:
7910
7912
7913 mutable T* vector_base_;
7914 std::vector<expression_ptr> initialiser_list_;
7915 const std::size_t size_;
7916 const bool single_value_initialse_;
7917 };
7918
7919 template <typename T>
7920 class swap_node : public expression_node<T>
7921 {
7922 public:
7923
7926
7928 : var0_(var0),
7929 var1_(var1)
7930 {}
7931
7932 inline T value() const
7933 {
7934 std::swap(var0_->ref(),var1_->ref());
7935 return var1_->ref();
7936 }
7937
7938 inline typename expression_node<T>::node_type type() const
7939 {
7941 }
7942
7943 private:
7944
7945 variable_node_ptr var0_;
7946 variable_node_ptr var1_;
7947 };
7948
7949 template <typename T>
7951 {
7952 public:
7953
7956
7958 : binary_node<T>(details::e_swap, var0, var1),
7959 var0_(dynamic_cast<ivariable_ptr>(var0)),
7960 var1_(dynamic_cast<ivariable_ptr>(var1))
7961 {}
7962
7963 inline T value() const
7964 {
7965 std::swap(var0_->ref(),var1_->ref());
7966 return var1_->ref();
7967 }
7968
7969 inline typename expression_node<T>::node_type type() const
7970 {
7972 }
7973
7974 private:
7975
7976 ivariable_ptr var0_;
7977 ivariable_ptr var1_;
7978 };
7979
7980 template <typename T>
7981 class swap_vecvec_node : public binary_node <T>,
7982 public vector_interface<T>
7983 {
7984 public:
7985
7989
7991 expression_ptr branch1)
7992 : binary_node<T>(details::e_swap, branch0, branch1),
7993 vec0_node_ptr_(0),
7994 vec1_node_ptr_(0),
7995 vec_size_ (0),
7996 initialised_ (false)
7997 {
7999 {
8000 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
8001
8002 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
8003 {
8004 vec0_node_ptr_ = vi->vec();
8005 vds() = vi->vds();
8006 }
8007 }
8008
8010 {
8011 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
8012
8013 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
8014 {
8015 vec1_node_ptr_ = vi->vec();
8016 }
8017 }
8018
8019 if (vec0_node_ptr_ && vec1_node_ptr_)
8020 {
8021 vec_size_ = std::min(vec0_node_ptr_->vds().size(),
8022 vec1_node_ptr_->vds().size());
8023
8024 initialised_ = true;
8025 }
8026 }
8027
8028 inline T value() const
8029 {
8030 assert(binary_node<T>::branch_[0].first);
8031 assert(binary_node<T>::branch_[1].first);
8032
8033 if (initialised_)
8034 {
8035 binary_node<T>::branch_[0].first->value();
8036 binary_node<T>::branch_[1].first->value();
8037
8038 T* vec0 = vec0_node_ptr_->vds().data();
8039 T* vec1 = vec1_node_ptr_->vds().data();
8040
8041 for (std::size_t i = 0; i < vec_size_; ++i)
8042 {
8043 std::swap(vec0[i],vec1[i]);
8044 }
8045
8046 return vec1_node_ptr_->value();
8047 }
8048 else
8049 return std::numeric_limits<T>::quiet_NaN();
8050 }
8051
8053 {
8054 return vec0_node_ptr_;
8055 }
8056
8058 {
8059 return vec0_node_ptr_;
8060 }
8061
8062 inline typename expression_node<T>::node_type type() const
8063 {
8065 }
8066
8067 std::size_t size() const
8068 {
8069 return vec_size_;
8070 }
8071
8073 {
8074 return vds_;
8075 }
8076
8077 const vds_t& vds() const
8078 {
8079 return vds_;
8080 }
8081
8082 private:
8083
8084 vector_node<T>* vec0_node_ptr_;
8085 vector_node<T>* vec1_node_ptr_;
8086 std::size_t vec_size_;
8087 bool initialised_;
8088 vds_t vds_;
8089 };
8090
8091 #ifndef exprtk_disable_string_capabilities
8092 template <typename T>
8094 public string_base_node<T>,
8095 public range_interface <T>
8096 {
8097 public:
8098
8100
8102
8104 : value_(&null_value)
8105 {}
8106
8108 : value_(&v)
8109 {
8110 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8111 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
8112 rp_.cache.first = rp_.n0_c.second;
8113 rp_.cache.second = rp_.n1_c.second;
8114 }
8115
8116 inline bool operator <(const stringvar_node<T>& v) const
8117 {
8118 return this < (&v);
8119 }
8120
8121 inline T value() const
8122 {
8123 rp_.n1_c.second = (*value_).size() - 1;
8124 rp_.cache.second = rp_.n1_c.second;
8125
8126 return std::numeric_limits<T>::quiet_NaN();
8127 }
8128
8130 {
8131 return ref();
8132 }
8133
8135 {
8136 return &(*value_)[0];
8137 }
8138
8139 std::size_t size() const
8140 {
8141 return ref().size();
8142 }
8143
8145 {
8146 return (*value_);
8147 }
8148
8149 const std::string& ref() const
8150 {
8151 return (*value_);
8152 }
8153
8155 {
8156 return rp_;
8157 }
8158
8159 const range_t& range_ref() const
8160 {
8161 return rp_;
8162 }
8163
8164 inline typename expression_node<T>::node_type type() const
8165 {
8167 }
8168
8169 private:
8170
8171 std::string* value_;
8172 mutable range_t rp_;
8173 };
8174
8175 template <typename T>
8177
8178 template <typename T>
8180 public string_base_node<T>,
8181 public range_interface <T>
8182 {
8183 public:
8184
8186
8188
8189 explicit string_range_node(std::string& v, const range_t& rp)
8190 : value_(&v),
8191 rp_(rp)
8192 {}
8193
8195 {
8196 rp_.free();
8197 }
8198
8199 inline bool operator <(const string_range_node<T>& v) const
8200 {
8201 return this < (&v);
8202 }
8203
8204 inline T value() const
8205 {
8206 return std::numeric_limits<T>::quiet_NaN();
8207 }
8208
8209 inline std::string str() const
8210 {
8211 return (*value_);
8212 }
8213
8215 {
8216 return &(*value_)[0];
8217 }
8218
8219 std::size_t size() const
8220 {
8221 return ref().size();
8222 }
8223
8224 inline range_t range() const
8225 {
8226 return rp_;
8227 }
8228
8229 inline virtual std::string& ref()
8230 {
8231 return (*value_);
8232 }
8233
8234 inline virtual const std::string& ref() const
8235 {
8236 return (*value_);
8237 }
8238
8240 {
8241 return rp_;
8242 }
8243
8244 inline const range_t& range_ref() const
8245 {
8246 return rp_;
8247 }
8248
8249 inline typename expression_node<T>::node_type type() const
8250 {
8252 }
8253
8254 private:
8255
8256 std::string* value_;
8257 range_t rp_;
8258 };
8259
8260 template <typename T>
8262
8263 template <typename T>
8265 public string_base_node<T>,
8266 public range_interface <T>
8267 {
8268 public:
8269
8271
8272 explicit const_string_range_node(const std::string& v, const range_t& rp)
8273 : value_(v),
8274 rp_(rp)
8275 {}
8276
8278 {
8279 rp_.free();
8280 }
8281
8282 inline T value() const
8283 {
8284 return std::numeric_limits<T>::quiet_NaN();
8285 }
8286
8288 {
8289 return value_;
8290 }
8291
8293 {
8294 return value_.data();
8295 }
8296
8297 std::size_t size() const
8298 {
8299 return value_.size();
8300 }
8301
8303 {
8304 return rp_;
8305 }
8306
8308 {
8309 return rp_;
8310 }
8311
8312 const range_t& range_ref() const
8313 {
8314 return rp_;
8315 }
8316
8317 inline typename expression_node<T>::node_type type() const
8318 {
8320 }
8321
8322 private:
8323
8325
8326 const std::string value_;
8327 range_t rp_;
8328 };
8329
8330 template <typename T>
8332 public string_base_node<T>,
8333 public range_interface <T>
8334 {
8335 public:
8336
8344 typedef std::pair<expression_ptr,bool> branch_t;
8345
8346
8348 : initialised_(false),
8349 str_base_ptr_ (0),
8350 str_range_ptr_(0),
8351 base_range_(brange)
8352 {
8353 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8354 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8355 range_.cache.first = range_.n0_c.second;
8356 range_.cache.second = range_.n1_c.second;
8357
8358 construct_branch_pair(branch_, str_branch);
8359
8360 if (is_generally_string_node(branch_.first))
8361 {
8362 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
8363
8364 if (0 == str_base_ptr_)
8365 return;
8366
8367 str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
8368
8369 if (0 == str_range_ptr_)
8370 return;
8371 }
8372
8373 initialised_ = (str_base_ptr_ && str_range_ptr_);
8374 }
8375
8377 {
8378 base_range_.free();
8379 }
8380
8381 inline T value() const
8382 {
8383 if (initialised_)
8384 {
8385 assert(branch_.first);
8386
8387 branch_.first->value();
8388
8389 std::size_t str_r0 = 0;
8390 std::size_t str_r1 = 0;
8391
8392 std::size_t r0 = 0;
8393 std::size_t r1 = 0;
8394
8395 const range_t& range = str_range_ptr_->range_ref();
8396
8397 const std::size_t base_str_size = str_base_ptr_->size();
8398
8399 if (
8400 range (str_r0, str_r1, base_str_size) &&
8401 base_range_( r0, r1, base_str_size)
8402 )
8403 {
8404 const std::size_t size = (r1 - r0) + 1;
8405
8406 range_.n1_c.second = size - 1;
8407 range_.cache.second = range_.n1_c.second;
8408
8409 value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
8410 }
8411 }
8412
8413 return std::numeric_limits<T>::quiet_NaN();
8414 }
8415
8417 {
8418 return value_;
8419 }
8420
8422 {
8423 return &value_[0];
8424 }
8425
8426 std::size_t size() const
8427 {
8428 return value_.size();
8429 }
8430
8432 {
8433 return range_;
8434 }
8435
8436 const range_t& range_ref() const
8437 {
8438 return range_;
8439 }
8440
8441 inline typename expression_node<T>::node_type type() const
8442 {
8444 }
8445
8446 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
8447 {
8448 expression_node<T>::ndb_t::collect(branch_, node_delete_list);
8449 }
8450
8451 std::size_t node_depth() const
8452 {
8454 }
8455
8456 private:
8457
8458 bool initialised_;
8459 branch_t branch_;
8460 str_base_ptr str_base_ptr_;
8461 irange_ptr str_range_ptr_;
8462 mutable range_t base_range_;
8463 mutable range_t range_;
8464 mutable std::string value_;
8465 };
8466
8467 template <typename T>
8469 public string_base_node<T>,
8470 public range_interface <T>
8471 {
8472 public:
8473
8480
8482 expression_ptr branch0,
8483 expression_ptr branch1)
8484 : binary_node<T>(opr, branch0, branch1),
8485 initialised_(false),
8486 str0_base_ptr_ (0),
8487 str1_base_ptr_ (0),
8488 str0_range_ptr_(0),
8489 str1_range_ptr_(0)
8490 {
8491 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8492 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8493
8494 range_.cache.first = range_.n0_c.second;
8495 range_.cache.second = range_.n1_c.second;
8496
8498 {
8499 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8500
8501 if (0 == str0_base_ptr_)
8502 return;
8503
8504 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8505
8506 if (0 == str0_range_ptr_)
8507 return;
8508 }
8509
8511 {
8512 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8513
8514 if (0 == str1_base_ptr_)
8515 return;
8516
8517 str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8518
8519 if (0 == str1_range_ptr_)
8520 return;
8521 }
8522
8523 initialised_ = str0_base_ptr_ &&
8524 str1_base_ptr_ &&
8525 str0_range_ptr_ &&
8526 str1_range_ptr_ ;
8527 }
8528
8529 inline T value() const
8530 {
8531 if (initialised_)
8532 {
8533 assert(binary_node<T>::branch_[0].first);
8534 assert(binary_node<T>::branch_[1].first);
8535
8536 binary_node<T>::branch_[0].first->value();
8537 binary_node<T>::branch_[1].first->value();
8538
8539 std::size_t str0_r0 = 0;
8540 std::size_t str0_r1 = 0;
8541
8542 std::size_t str1_r0 = 0;
8543 std::size_t str1_r1 = 0;
8544
8545 const range_t& range0 = str0_range_ptr_->range_ref();
8546 const range_t& range1 = str1_range_ptr_->range_ref();
8547
8548 if (
8549 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8550 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8551 )
8552 {
8553 const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8554 const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8555
8556 value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8557 value_.append(str1_base_ptr_->base() + str1_r0, size1);
8558
8559 range_.n1_c.second = value_.size() - 1;
8560 range_.cache.second = range_.n1_c.second;
8561 }
8562 }
8563
8564 return std::numeric_limits<T>::quiet_NaN();
8565 }
8566
8568 {
8569 return value_;
8570 }
8571
8573 {
8574 return &value_[0];
8575 }
8576
8577 std::size_t size() const
8578 {
8579 return value_.size();
8580 }
8581
8583 {
8584 return range_;
8585 }
8586
8587 const range_t& range_ref() const
8588 {
8589 return range_;
8590 }
8591
8592 inline typename expression_node<T>::node_type type() const
8593 {
8595 }
8596
8597 private:
8598
8599 bool initialised_;
8600 str_base_ptr str0_base_ptr_;
8601 str_base_ptr str1_base_ptr_;
8602 irange_ptr str0_range_ptr_;
8603 irange_ptr str1_range_ptr_;
8604 mutable range_t range_;
8605 mutable std::string value_;
8606 };
8607
8608 template <typename T>
8609 class swap_string_node : public binary_node <T>,
8610 public string_base_node<T>,
8611 public range_interface <T>
8612 {
8613 public:
8614
8622
8624 : binary_node<T>(details::e_swap, branch0, branch1),
8625 initialised_(false),
8626 str0_node_ptr_(0),
8627 str1_node_ptr_(0)
8628 {
8630 {
8631 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8632 }
8633
8635 {
8636 str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8637 }
8638
8639 initialised_ = (str0_node_ptr_ && str1_node_ptr_);
8640 }
8641
8642 inline T value() const
8643 {
8644 if (initialised_)
8645 {
8646 assert(binary_node<T>::branch_[0].first);
8647 assert(binary_node<T>::branch_[1].first);
8648
8649 binary_node<T>::branch_[0].first->value();
8650 binary_node<T>::branch_[1].first->value();
8651
8652 std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
8653 }
8654
8655 return std::numeric_limits<T>::quiet_NaN();
8656 }
8657
8659 {
8660 return str0_node_ptr_->str();
8661 }
8662
8664 {
8665 return str0_node_ptr_->base();
8666 }
8667
8668 std::size_t size() const
8669 {
8670 return str0_node_ptr_->size();
8671 }
8672
8674 {
8675 return str0_node_ptr_->range_ref();
8676 }
8677
8678 const range_t& range_ref() const
8679 {
8680 return str0_node_ptr_->range_ref();
8681 }
8682
8683 inline typename expression_node<T>::node_type type() const
8684 {
8686 }
8687
8688 private:
8689
8690 bool initialised_;
8691 strvar_node_ptr str0_node_ptr_;
8692 strvar_node_ptr str1_node_ptr_;
8693 };
8694
8695 template <typename T>
8697 {
8698 public:
8699
8706
8708 expression_ptr branch1)
8709 : binary_node<T>(details::e_default, branch0, branch1),
8710 str0_base_ptr_ (0),
8711 str1_base_ptr_ (0),
8712 str0_range_ptr_(0),
8713 str1_range_ptr_(0),
8714 initialised_(false)
8715 {
8717 {
8718 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8719
8720 if (0 == str0_base_ptr_)
8721 return;
8722
8723 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8724
8725 if (0 == range)
8726 return;
8727
8728 str0_range_ptr_ = &(range->range_ref());
8729 }
8730
8732 {
8733 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8734
8735 if (0 == str1_base_ptr_)
8736 return;
8737
8738 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8739
8740 if (0 == range)
8741 return;
8742
8743 str1_range_ptr_ = &(range->range_ref());
8744 }
8745
8746 initialised_ = str0_base_ptr_ &&
8747 str1_base_ptr_ &&
8748 str0_range_ptr_ &&
8749 str1_range_ptr_ ;
8750 }
8751
8752 inline T value() const
8753 {
8754 if (initialised_)
8755 {
8756 assert(binary_node<T>::branch_[0].first);
8757 assert(binary_node<T>::branch_[1].first);
8758
8759 binary_node<T>::branch_[0].first->value();
8760 binary_node<T>::branch_[1].first->value();
8761
8762 std::size_t str0_r0 = 0;
8763 std::size_t str0_r1 = 0;
8764
8765 std::size_t str1_r0 = 0;
8766 std::size_t str1_r1 = 0;
8767
8768 const range_t& range0 = (*str0_range_ptr_);
8769 const range_t& range1 = (*str1_range_ptr_);
8770
8771 if (
8772 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8773 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8774 )
8775 {
8776 const std::size_t size0 = range0.cache_size();
8777 const std::size_t size1 = range1.cache_size();
8778 const std::size_t max_size = std::min(size0,size1);
8779
8780 char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8781 char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8782
8783 loop_unroll::details lud(max_size);
8784 char_cptr upper_bound = s0 + lud.upper_bound;
8785
8786 while (s0 < upper_bound)
8787 {
8788 #define exprtk_loop(N) \
8789 std::swap(s0[N], s1[N]); \
8790
8791 exprtk_loop( 0) exprtk_loop( 1)
8792 exprtk_loop( 2) exprtk_loop( 3)
8793 #ifndef exprtk_disable_superscalar_unroll
8794 exprtk_loop( 4) exprtk_loop( 5)
8795 exprtk_loop( 6) exprtk_loop( 7)
8796 exprtk_loop( 8) exprtk_loop( 9)
8797 exprtk_loop(10) exprtk_loop(11)
8798 exprtk_loop(12) exprtk_loop(13)
8799 exprtk_loop(14) exprtk_loop(15)
8800 #endif
8801
8802 s0 += lud.batch_size;
8803 s1 += lud.batch_size;
8804 }
8805
8806 int i = 0;
8807
8809 switch (lud.remainder)
8810 {
8811 #define case_stmt(N) \
8812 case N : { std::swap(s0[i], s1[i]); ++i; } \
8813
8814 #ifndef exprtk_disable_superscalar_unroll
8815 case_stmt(15) case_stmt(14)
8816 case_stmt(13) case_stmt(12)
8817 case_stmt(11) case_stmt(10)
8818 case_stmt( 9) case_stmt( 8)
8819 case_stmt( 7) case_stmt( 6)
8820 case_stmt( 5) case_stmt( 4)
8821 #endif
8822 case_stmt( 3) case_stmt( 2)
8823 case_stmt( 1)
8824 }
8826
8827 #undef exprtk_loop
8828 #undef case_stmt
8829 }
8830 }
8831
8832 return std::numeric_limits<T>::quiet_NaN();
8833 }
8834
8835 inline typename expression_node<T>::node_type type() const
8836 {
8838 }
8839
8840 private:
8841
8844
8845 str_base_ptr str0_base_ptr_;
8846 str_base_ptr str1_base_ptr_;
8847 range_ptr str0_range_ptr_;
8848 range_ptr str1_range_ptr_;
8849 bool initialised_;
8850 };
8851
8852 template <typename T>
8854 {
8855 public:
8856
8858
8860 : value_(&null_value)
8861 {}
8862
8864 : value_(&v)
8865 {}
8866
8867 inline T value() const
8868 {
8869 return T((*value_).size());
8870 }
8871
8872 inline typename expression_node<T>::node_type type() const
8873 {
8875 }
8876
8877 private:
8878
8879 std::string* value_;
8880 };
8881
8882 template <typename T>
8884
8885 template <typename T>
8887 {
8888 public:
8889
8892 typedef std::pair<expression_ptr,bool> branch_t;
8893
8894
8896 : str_base_ptr_(0)
8897 {
8898 construct_branch_pair(branch_, branch);
8899
8900 if (is_generally_string_node(branch_.first))
8901 {
8902 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
8903
8904 if (0 == str_base_ptr_)
8905 return;
8906 }
8907 }
8908
8909 inline T value() const
8910 {
8911 T result = std::numeric_limits<T>::quiet_NaN();
8912
8913 if (str_base_ptr_)
8914 {
8915 branch_.first->value();
8916 result = T(str_base_ptr_->size());
8917 }
8918
8919 return result;
8920 }
8921
8922 inline typename expression_node<T>::node_type type() const
8923 {
8925 }
8926
8927 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
8928 {
8929 expression_node<T>::ndb_t::collect(branch_, node_delete_list);
8930 }
8931
8932 std::size_t node_depth() const
8933 {
8935 }
8936
8937 private:
8938
8939 branch_t branch_;
8940 str_base_ptr str_base_ptr_;
8941 };
8942
8944 {
8945 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8946 { s.assign(data,size); }
8947 };
8948
8950 {
8951 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8952 { s.append(data,size); }
8953 };
8954
8955 template <typename T, typename AssignmentProcess = asn_assignment>
8957 public string_base_node<T>,
8958 public range_interface <T>
8959 {
8960 public:
8961
8969
8971 expression_ptr branch0,
8972 expression_ptr branch1)
8973 : binary_node<T>(opr, branch0, branch1),
8974 initialised_(false),
8975 str0_base_ptr_ (0),
8976 str1_base_ptr_ (0),
8977 str0_node_ptr_ (0),
8978 str1_range_ptr_(0)
8979 {
8981 {
8982 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8983
8984 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8985 }
8986
8988 {
8989 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8990
8991 if (0 == str1_base_ptr_)
8992 return;
8993
8994 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8995
8996 if (0 == range)
8997 return;
8998
8999 str1_range_ptr_ = &(range->range_ref());
9000 }
9001
9002 initialised_ = str0_base_ptr_ &&
9003 str1_base_ptr_ &&
9004 str0_node_ptr_ &&
9005 str1_range_ptr_ ;
9006 }
9007
9008 inline T value() const
9009 {
9010 if (initialised_)
9011 {
9012 assert(binary_node<T>::branch_[0].first);
9013 assert(binary_node<T>::branch_[1].first);
9014
9015 binary_node<T>::branch_[1].first->value();
9016
9017 std::size_t r0 = 0;
9018 std::size_t r1 = 0;
9019
9020 const range_t& range = (*str1_range_ptr_);
9021
9022 if (range(r0, r1, str1_base_ptr_->size()))
9023 {
9024 AssignmentProcess::execute(str0_node_ptr_->ref(),
9025 str1_base_ptr_->base() + r0,
9026 (r1 - r0) + 1);
9027
9028 binary_node<T>::branch_[0].first->value();
9029 }
9030 }
9031
9032 return std::numeric_limits<T>::quiet_NaN();
9033 }
9034
9036 {
9037 return str0_node_ptr_->str();
9038 }
9039
9041 {
9042 return str0_node_ptr_->base();
9043 }
9044
9045 std::size_t size() const
9046 {
9047 return str0_node_ptr_->size();
9048 }
9049
9051 {
9052 return str0_node_ptr_->range_ref();
9053 }
9054
9055 const range_t& range_ref() const
9056 {
9057 return str0_node_ptr_->range_ref();
9058 }
9059
9060 inline typename expression_node<T>::node_type type() const
9061 {
9063 }
9064
9065 private:
9066
9067 bool initialised_;
9068 str_base_ptr str0_base_ptr_;
9069 str_base_ptr str1_base_ptr_;
9070 strvar_node_ptr str0_node_ptr_;
9071 range_ptr str1_range_ptr_;
9072 };
9073
9074 template <typename T, typename AssignmentProcess = asn_assignment>
9076 public string_base_node<T>,
9077 public range_interface <T>
9078 {
9079 public:
9080
9089
9091 expression_ptr branch0,
9092 expression_ptr branch1)
9093 : binary_node<T>(opr, branch0, branch1),
9094 initialised_(false),
9095 str0_base_ptr_ (0),
9096 str1_base_ptr_ (0),
9097 str0_rng_node_ptr_ (0),
9098 str0_range_ptr_ (0),
9099 str1_range_ptr_ (0)
9100 {
9102 {
9103 str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first);
9104
9105 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
9106
9107 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
9108
9109 if (0 == range)
9110 return;
9111
9112 str0_range_ptr_ = &(range->range_ref());
9113 }
9114
9116 {
9117 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
9118
9119 if (0 == str1_base_ptr_)
9120 return;
9121
9122 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
9123
9124 if (0 == range)
9125 return;
9126
9127 str1_range_ptr_ = &(range->range_ref());
9128 }
9129
9130 initialised_ = str0_base_ptr_ &&
9131 str1_base_ptr_ &&
9132 str0_rng_node_ptr_ &&
9133 str0_range_ptr_ &&
9134 str1_range_ptr_ ;
9135 }
9136
9137 inline T value() const
9138 {
9139 if (initialised_)
9140 {
9141 assert(binary_node<T>::branch_[0].first);
9142 assert(binary_node<T>::branch_[1].first);
9143
9144 binary_node<T>::branch_[0].first->value();
9145 binary_node<T>::branch_[1].first->value();
9146
9147 std::size_t s0_r0 = 0;
9148 std::size_t s0_r1 = 0;
9149
9150 std::size_t s1_r0 = 0;
9151 std::size_t s1_r1 = 0;
9152
9153 const range_t& range0 = (*str0_range_ptr_);
9154 const range_t& range1 = (*str1_range_ptr_);
9155
9156 if (
9157 range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
9158 range1(s1_r0, s1_r1, str1_base_ptr_->size())
9159 )
9160 {
9161 const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
9162
9163 std::copy(str1_base_ptr_->base() + s1_r0,
9164 str1_base_ptr_->base() + s1_r0 + size,
9165 const_cast<char_ptr>(base() + s0_r0));
9166 }
9167 }
9168
9169 return std::numeric_limits<T>::quiet_NaN();
9170 }
9171
9173 {
9174 return str0_base_ptr_->str();
9175 }
9176
9178 {
9179 return str0_base_ptr_->base();
9180 }
9181
9182 std::size_t size() const
9183 {
9184 return str0_base_ptr_->size();
9185 }
9186
9188 {
9189 return str0_rng_node_ptr_->range_ref();
9190 }
9191
9192 const range_t& range_ref() const
9193 {
9194 return str0_rng_node_ptr_->range_ref();
9195 }
9196
9197 inline typename expression_node<T>::node_type type() const
9198 {
9200 }
9201
9202 private:
9203
9204 bool initialised_;
9205 str_base_ptr str0_base_ptr_;
9206 str_base_ptr str1_base_ptr_;
9207 str_rng_node_ptr str0_rng_node_ptr_;
9208 range_ptr str0_range_ptr_;
9209 range_ptr str1_range_ptr_;
9210 };
9211
9212 template <typename T>
9214 public string_base_node<T>,
9215 public range_interface <T>
9216 {
9217 public:
9218
9225
9227 expression_ptr consequent,
9228 expression_ptr alternative)
9229 : trinary_node<T>(details::e_default,consequent,alternative,condition),
9230 initialised_(false),
9231 str0_base_ptr_ (0),
9232 str1_base_ptr_ (0),
9233 str0_range_ptr_(0),
9234 str1_range_ptr_(0),
9235 condition_ (condition),
9236 consequent_ (consequent),
9237 alternative_(alternative)
9238 {
9239 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
9240 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
9241
9242 range_.cache.first = range_.n0_c.second;
9243 range_.cache.second = range_.n1_c.second;
9244
9246 {
9247 str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
9248
9249 if (0 == str0_base_ptr_)
9250 return;
9251
9252 str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
9253
9254 if (0 == str0_range_ptr_)
9255 return;
9256 }
9257
9259 {
9260 str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
9261
9262 if (0 == str1_base_ptr_)
9263 return;
9264
9265 str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
9266
9267 if (0 == str1_range_ptr_)
9268 return;
9269 }
9270
9271 initialised_ = str0_base_ptr_ &&
9272 str1_base_ptr_ &&
9273 str0_range_ptr_ &&
9274 str1_range_ptr_ ;
9275
9276 }
9277
9278 inline T value() const
9279 {
9280 if (initialised_)
9281 {
9282 assert(condition_ );
9283 assert(consequent_ );
9284 assert(alternative_);
9285
9286 std::size_t r0 = 0;
9287 std::size_t r1 = 0;
9288
9289 if (is_true(condition_))
9290 {
9291 consequent_->value();
9292
9293 const range_t& range = str0_range_ptr_->range_ref();
9294
9295 if (range(r0, r1, str0_base_ptr_->size()))
9296 {
9297 const std::size_t size = (r1 - r0) + 1;
9298
9299 value_.assign(str0_base_ptr_->base() + r0, size);
9300
9301 range_.n1_c.second = value_.size() - 1;
9302 range_.cache.second = range_.n1_c.second;
9303
9304 return T(1);
9305 }
9306 }
9307 else
9308 {
9309 alternative_->value();
9310
9311 const range_t& range = str1_range_ptr_->range_ref();
9312
9313 if (range(r0, r1, str1_base_ptr_->size()))
9314 {
9315 const std::size_t size = (r1 - r0) + 1;
9316
9317 value_.assign(str1_base_ptr_->base() + r0, size);
9318
9319 range_.n1_c.second = value_.size() - 1;
9320 range_.cache.second = range_.n1_c.second;
9321
9322 return T(0);
9323 }
9324 }
9325 }
9326
9327 return std::numeric_limits<T>::quiet_NaN();
9328 }
9329
9331 {
9332 return value_;
9333 }
9334
9336 {
9337 return &value_[0];
9338 }
9339
9340 std::size_t size() const
9341 {
9342 return value_.size();
9343 }
9344
9346 {
9347 return range_;
9348 }
9349
9350 const range_t& range_ref() const
9351 {
9352 return range_;
9353 }
9354
9355 inline typename expression_node<T>::node_type type() const
9356 {
9358 }
9359
9360 private:
9361
9362 bool initialised_;
9363 str_base_ptr str0_base_ptr_;
9364 str_base_ptr str1_base_ptr_;
9365 irange_ptr str0_range_ptr_;
9366 irange_ptr str1_range_ptr_;
9367 mutable range_t range_;
9368 mutable std::string value_;
9369
9370 expression_ptr condition_;
9371 expression_ptr consequent_;
9372 expression_ptr alternative_;
9373 };
9374
9375 template <typename T>
9377 public string_base_node<T>,
9378 public range_interface <T>
9379 {
9380 public:
9381
9388
9390 expression_ptr consequent)
9391 : binary_node<T>(details::e_default, consequent, condition),
9392 initialised_(false),
9393 str0_base_ptr_ (0),
9394 str0_range_ptr_(0),
9395 condition_ (condition),
9396 consequent_(consequent)
9397 {
9398 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
9399 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
9400
9401 range_.cache.first = range_.n0_c.second;
9402 range_.cache.second = range_.n1_c.second;
9403
9405 {
9406 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
9407
9408 if (0 == str0_base_ptr_)
9409 return;
9410
9411 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
9412
9413 if (0 == str0_range_ptr_)
9414 return;
9415 }
9416
9417 initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
9418 }
9419
9420 inline T value() const
9421 {
9422 if (initialised_)
9423 {
9424 assert(condition_ );
9425 assert(consequent_);
9426
9427 if (is_true(condition_))
9428 {
9429 consequent_->value();
9430
9431 const range_t& range = str0_range_ptr_->range_ref();
9432
9433 std::size_t r0 = 0;
9434 std::size_t r1 = 0;
9435
9436 if (range(r0, r1, str0_base_ptr_->size()))
9437 {
9438 const std::size_t size = (r1 - r0) + 1;
9439
9440 value_.assign(str0_base_ptr_->base() + r0, size);
9441
9442 range_.n1_c.second = value_.size() - 1;
9443 range_.cache.second = range_.n1_c.second;
9444
9445 return T(1);
9446 }
9447 }
9448 }
9449
9450 return std::numeric_limits<T>::quiet_NaN();
9451 }
9452
9454 {
9455 return value_;
9456 }
9457
9459 {
9460 return &value_[0];
9461 }
9462
9463 std::size_t size() const
9464 {
9465 return value_.size();
9466 }
9467
9469 {
9470 return range_;
9471 }
9472
9473 const range_t& range_ref() const
9474 {
9475 return range_;
9476 }
9477
9478 inline typename expression_node<T>::node_type type() const
9479 {
9481 }
9482
9483 private:
9484
9485 bool initialised_;
9486 str_base_ptr str0_base_ptr_;
9487 irange_ptr str0_range_ptr_;
9488 mutable range_t range_;
9489 mutable std::string value_;
9490
9491 expression_ptr condition_;
9492 expression_ptr consequent_;
9493 };
9494
9495 template <typename T, typename VarArgFunction>
9497 public string_base_node<T>,
9498 public range_interface <T>
9499 {
9500 public:
9501
9508 typedef std::pair<expression_ptr,bool> branch_t;
9509
9510 template <typename Allocator,
9511 template <typename, typename> class Sequence>
9512 explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9513 : initialised_(false),
9514 str_base_ptr_ (0),
9515 str_range_ptr_(0)
9516 {
9517 construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
9518
9519 if (0 == final_node_.first)
9520 return;
9521 else if (!is_generally_string_node(final_node_.first))
9522 return;
9523
9524 str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
9525
9526 if (0 == str_base_ptr_)
9527 return;
9528
9529 str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
9530
9531 if (0 == str_range_ptr_)
9532 return;
9533
9534 initialised_ = str_base_ptr_ && str_range_ptr_;
9535
9536 if (arg_list.size() > 1)
9537 {
9538 const std::size_t arg_list_size = arg_list.size() - 1;
9539
9540 arg_list_.resize(arg_list_size);
9541
9542 for (std::size_t i = 0; i < arg_list_size; ++i)
9543 {
9544 if (arg_list[i])
9545 {
9546 construct_branch_pair(arg_list_[i], arg_list[i]);
9547 }
9548 else
9549 {
9550 arg_list_.clear();
9551 return;
9552 }
9553 }
9554 }
9555 }
9556
9557 inline T value() const
9558 {
9559 if (!arg_list_.empty())
9560 {
9561 VarArgFunction::process(arg_list_);
9562 }
9563
9564 final_node_.first->value();
9565
9566 return std::numeric_limits<T>::quiet_NaN();
9567 }
9568
9570 {
9571 return str_base_ptr_->str();
9572 }
9573
9575 {
9576 return str_base_ptr_->base();
9577 }
9578
9579 std::size_t size() const
9580 {
9581 return str_base_ptr_->size();
9582 }
9583
9585 {
9586 return str_range_ptr_->range_ref();
9587 }
9588
9589 const range_t& range_ref() const
9590 {
9591 return str_range_ptr_->range_ref();
9592 }
9593
9594 inline typename expression_node<T>::node_type type() const
9595 {
9597 }
9598
9599 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
9600 {
9601 expression_node<T>::ndb_t::collect(final_node_, node_delete_list);
9602 expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list);
9603 }
9604
9605 std::size_t node_depth() const
9606 {
9607 return std::max(
9610 }
9611
9612 private:
9613
9614 bool initialised_;
9615 branch_t final_node_;
9616 str_base_ptr str_base_ptr_;
9617 irange_ptr str_range_ptr_;
9618 std::vector<branch_t> arg_list_;
9619 };
9620 #endif
9621
9622 template <typename T, std::size_t N>
9623 inline T axn(T a, T x)
9624 {
9625 // a*x^n
9627 }
9628
9629 template <typename T, std::size_t N>
9630 inline T axnb(T a, T x, T b)
9631 {
9632 // a*x^n+b
9634 }
9635
9636 template <typename T>
9637 struct sf_base
9638 {
9645 };
9646
9647 #define define_sfop3(NN,OP0,OP1) \
9648 template <typename T> \
9649 struct sf##NN##_op : public sf_base<T> \
9650 { \
9651 typedef typename sf_base<T>::Type const Type; \
9652 static inline T process(Type x, Type y, Type z) \
9653 { \
9654 return (OP0); \
9655 } \
9656 static inline std::string id() \
9657 { \
9658 return (OP1); \
9659 } \
9660 }; \
9661
9662 define_sfop3(00,(x + y) / z ,"(t+t)/t")
9663 define_sfop3(01,(x + y) * z ,"(t+t)*t")
9664 define_sfop3(02,(x + y) - z ,"(t+t)-t")
9665 define_sfop3(03,(x + y) + z ,"(t+t)+t")
9666 define_sfop3(04,(x - y) + z ,"(t-t)+t")
9667 define_sfop3(05,(x - y) / z ,"(t-t)/t")
9668 define_sfop3(06,(x - y) * z ,"(t-t)*t")
9669 define_sfop3(07,(x * y) + z ,"(t*t)+t")
9670 define_sfop3(08,(x * y) - z ,"(t*t)-t")
9671 define_sfop3(09,(x * y) / z ,"(t*t)/t")
9672 define_sfop3(10,(x * y) * z ,"(t*t)*t")
9673 define_sfop3(11,(x / y) + z ,"(t/t)+t")
9674 define_sfop3(12,(x / y) - z ,"(t/t)-t")
9675 define_sfop3(13,(x / y) / z ,"(t/t)/t")
9676 define_sfop3(14,(x / y) * z ,"(t/t)*t")
9677 define_sfop3(15,x / (y + z) ,"t/(t+t)")
9678 define_sfop3(16,x / (y - z) ,"t/(t-t)")
9679 define_sfop3(17,x / (y * z) ,"t/(t*t)")
9680 define_sfop3(18,x / (y / z) ,"t/(t/t)")
9681 define_sfop3(19,x * (y + z) ,"t*(t+t)")
9682 define_sfop3(20,x * (y - z) ,"t*(t-t)")
9683 define_sfop3(21,x * (y * z) ,"t*(t*t)")
9684 define_sfop3(22,x * (y / z) ,"t*(t/t)")
9685 define_sfop3(23,x - (y + z) ,"t-(t+t)")
9686 define_sfop3(24,x - (y - z) ,"t-(t-t)")
9687 define_sfop3(25,x - (y / z) ,"t-(t/t)")
9688 define_sfop3(26,x - (y * z) ,"t-(t*t)")
9689 define_sfop3(27,x + (y * z) ,"t+(t*t)")
9690 define_sfop3(28,x + (y / z) ,"t+(t/t)")
9691 define_sfop3(29,x + (y + z) ,"t+(t+t)")
9692 define_sfop3(30,x + (y - z) ,"t+(t-t)")
9693 define_sfop3(31,(axnb<T,2>(x,y,z))," ")
9694 define_sfop3(32,(axnb<T,3>(x,y,z))," ")
9695 define_sfop3(33,(axnb<T,4>(x,y,z))," ")
9696 define_sfop3(34,(axnb<T,5>(x,y,z))," ")
9697 define_sfop3(35,(axnb<T,6>(x,y,z))," ")
9698 define_sfop3(36,(axnb<T,7>(x,y,z))," ")
9699 define_sfop3(37,(axnb<T,8>(x,y,z))," ")
9700 define_sfop3(38,(axnb<T,9>(x,y,z))," ")
9701 define_sfop3(39,x * numeric::log(y) + z,"")
9702 define_sfop3(40,x * numeric::log(y) - z,"")
9703 define_sfop3(41,x * numeric::log10(y) + z,"")
9704 define_sfop3(42,x * numeric::log10(y) - z,"")
9705 define_sfop3(43,x * numeric::sin(y) + z ,"")
9706 define_sfop3(44,x * numeric::sin(y) - z ,"")
9707 define_sfop3(45,x * numeric::cos(y) + z ,"")
9708 define_sfop3(46,x * numeric::cos(y) - z ,"")
9709 define_sfop3(47,details::is_true(x) ? y : z,"")
9710
9711 #define define_sfop4(NN,OP0,OP1) \
9712 template <typename T> \
9713 struct sf##NN##_op : public sf_base<T> \
9714 { \
9715 typedef typename sf_base<T>::Type const Type; \
9716 static inline T process(Type x, Type y, Type z, Type w) \
9717 { \
9718 return (OP0); \
9719 } \
9720 static inline std::string id() \
9721 { \
9722 return (OP1); \
9723 } \
9724 }; \
9725
9726 define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9727 define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9728 define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9729 define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9730 define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9731 define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9732 define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9733 define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9734 define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9735 define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9736 define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9737 define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9738 define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9739 define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9740 define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9741 define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9742 define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9743 define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9744 define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9745 define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9746 define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9747 define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9748 define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9749 define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9750 define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9751 define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9752 define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9753 define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9754 define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9755 define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9756 define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9757 define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9758 define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9759 define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9760 define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9761 define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9762
9763 define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9764 define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9765 define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9766 define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9767 define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9768 define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9769 define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9770 define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9771 define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9772 define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9773 define_sfop4(94,((x < y) ? z : w),"")
9774 define_sfop4(95,((x <= y) ? z : w),"")
9775 define_sfop4(96,((x > y) ? z : w),"")
9776 define_sfop4(97,((x >= y) ? z : w),"")
9777 define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9778 define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9779
9780 define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9781 define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9782 define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9783 define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9784 define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9785 define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9786 define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9787 define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9788 define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9789 define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9790 define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9791 define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9792 define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9793 define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9794 define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9795 define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9796 define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9797 define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9798 define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9799 define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9800 define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9801 define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9802 define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9803 define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9804 define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9805 define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9806 define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9807 define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9808 define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9809 define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9810 define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9811 define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9812 define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9813 define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9814 define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9815 define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9816 define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9817 define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9818 define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9819 define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9820 define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9821 define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9822 define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9823 define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9824 define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9825 define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9826 define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9827 define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9828 define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9829 define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9830 define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9831 define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9832 define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9833 define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9834 define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9835 define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9836 define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9837 define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9838 define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9839 define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9840 define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9841 define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9842
9843 #undef define_sfop3
9844 #undef define_sfop4
9845
9846 template <typename T, typename SpecialFunction>
9847 class sf3_node : public trinary_node<T>
9848 {
9849 public:
9850
9851 typedef expression_node<T>* expression_ptr;
9852
9853 sf3_node(const operator_type& opr,
9854 expression_ptr branch0,
9855 expression_ptr branch1,
9856 expression_ptr branch2)
9857 : trinary_node<T>(opr, branch0, branch1, branch2)
9858 {}
9859
9860 inline T value() const
9861 {
9862 assert(trinary_node<T>::branch_[0].first);
9863 assert(trinary_node<T>::branch_[1].first);
9864 assert(trinary_node<T>::branch_[2].first);
9865
9866 const T x = trinary_node<T>::branch_[0].first->value();
9867 const T y = trinary_node<T>::branch_[1].first->value();
9868 const T z = trinary_node<T>::branch_[2].first->value();
9869
9870 return SpecialFunction::process(x, y, z);
9871 }
9872 };
9873
9874 template <typename T, typename SpecialFunction>
9875 class sf4_node : public quaternary_node<T>
9876 {
9877 public:
9878
9880
9882 expression_ptr branch0,
9883 expression_ptr branch1,
9884 expression_ptr branch2,
9885 expression_ptr branch3)
9886 : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9887 {}
9888
9889 inline T value() const
9890 {
9891 assert(quaternary_node<T>::branch_[0].first);
9892 assert(quaternary_node<T>::branch_[1].first);
9893 assert(quaternary_node<T>::branch_[2].first);
9894 assert(quaternary_node<T>::branch_[3].first);
9895
9896 const T x = quaternary_node<T>::branch_[0].first->value();
9897 const T y = quaternary_node<T>::branch_[1].first->value();
9898 const T z = quaternary_node<T>::branch_[2].first->value();
9899 const T w = quaternary_node<T>::branch_[3].first->value();
9900
9901 return SpecialFunction::process(x, y, z, w);
9902 }
9903 };
9904
9905 template <typename T, typename SpecialFunction>
9907 {
9908 public:
9909
9911
9912 sf3_var_node(const T& v0, const T& v1, const T& v2)
9913 : v0_(v0),
9914 v1_(v1),
9915 v2_(v2)
9916 {}
9917
9918 inline T value() const
9919 {
9920 return SpecialFunction::process(v0_, v1_, v2_);
9921 }
9922
9923 inline typename expression_node<T>::node_type type() const
9924 {
9926 }
9927
9928 private:
9929
9932
9933 const T& v0_;
9934 const T& v1_;
9935 const T& v2_;
9936 };
9937
9938 template <typename T, typename SpecialFunction>
9940 {
9941 public:
9942
9944
9945 sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9946 : v0_(v0),
9947 v1_(v1),
9948 v2_(v2),
9949 v3_(v3)
9950 {}
9951
9952 inline T value() const
9953 {
9954 return SpecialFunction::process(v0_, v1_, v2_, v3_);
9955 }
9956
9957 inline typename expression_node<T>::node_type type() const
9958 {
9960 }
9961
9962 private:
9963
9966
9967 const T& v0_;
9968 const T& v1_;
9969 const T& v2_;
9970 const T& v3_;
9971 };
9972
9973 template <typename T, typename VarArgFunction>
9975 {
9976 public:
9977
9979 typedef std::pair<expression_ptr,bool> branch_t;
9980
9981 template <typename Allocator,
9982 template <typename, typename> class Sequence>
9983 explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9984 {
9985 arg_list_.resize(arg_list.size());
9986
9987 for (std::size_t i = 0; i < arg_list.size(); ++i)
9988 {
9989 if (arg_list[i])
9990 {
9991 construct_branch_pair(arg_list_[i],arg_list[i]);
9992 }
9993 else
9994 {
9995 arg_list_.clear();
9996 return;
9997 }
9998 }
9999 }
10000
10001 inline T value() const
10002 {
10003 return VarArgFunction::process(arg_list_);
10004 }
10005
10006 inline typename expression_node<T>::node_type type() const
10007 {
10009 }
10010
10011 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
10012 {
10013 expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
10014 }
10015
10016 std::size_t node_depth() const
10017 {
10019 }
10020
10021 private:
10022
10023 std::vector<branch_t> arg_list_;
10024 };
10025
10026 template <typename T, typename VarArgFunction>
10028 {
10029 public:
10030
10032
10033 template <typename Allocator,
10034 template <typename, typename> class Sequence>
10035 explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
10036 {
10037 arg_list_.resize(arg_list.size());
10038
10039 for (std::size_t i = 0; i < arg_list.size(); ++i)
10040 {
10041 if (arg_list[i] && is_variable_node(arg_list[i]))
10042 {
10043 variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
10044 arg_list_[i] = (&var_node_ptr->ref());
10045 }
10046 else
10047 {
10048 arg_list_.clear();
10049 return;
10050 }
10051 }
10052 }
10053
10054 inline T value() const
10055 {
10056 if (!arg_list_.empty())
10057 return VarArgFunction::process(arg_list_);
10058 else
10059 return std::numeric_limits<T>::quiet_NaN();
10060 }
10061
10062 inline typename expression_node<T>::node_type type() const
10063 {
10065 }
10066
10067 private:
10068
10069 std::vector<const T*> arg_list_;
10070 };
10071
10072 template <typename T, typename VecFunction>
10074 {
10075 public:
10076
10078 typedef std::pair<expression_ptr,bool> branch_t;
10079
10081 : ivec_ptr_(0)
10082 {
10083 construct_branch_pair(v_, v);
10084
10085 if (is_ivector_node(v_.first))
10086 {
10087 ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
10088 }
10089 else
10090 ivec_ptr_ = 0;
10091 }
10092
10093 inline T value() const
10094 {
10095 if (ivec_ptr_)
10096 {
10097 assert(v_.first);
10098
10099 v_.first->value();
10100
10101 return VecFunction::process(ivec_ptr_);
10102 }
10103 else
10104 return std::numeric_limits<T>::quiet_NaN();
10105 }
10106
10107 inline typename expression_node<T>::node_type type() const
10108 {
10110 }
10111
10112 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
10113 {
10114 expression_node<T>::ndb_t::collect(v_, node_delete_list);
10115 }
10116
10117 std::size_t node_depth() const
10118 {
10120 }
10121
10122 private:
10123
10124 vector_interface<T>* ivec_ptr_;
10125 branch_t v_;
10126 };
10127
10128 template <typename T>
10130 {
10131 public:
10132
10134
10136 expression_ptr branch0,
10137 expression_ptr branch1)
10138 : binary_node<T>(opr, branch0, branch1),
10139 var_node_ptr_(0)
10140 {
10142 {
10143 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10144 }
10145 }
10146
10147 inline T value() const
10148 {
10149 if (var_node_ptr_)
10150 {
10151 assert(binary_node<T>::branch_[1].first);
10152
10153 T& result = var_node_ptr_->ref();
10154
10155 result = binary_node<T>::branch_[1].first->value();
10156
10157 return result;
10158 }
10159 else
10160 return std::numeric_limits<T>::quiet_NaN();
10161 }
10162
10163 private:
10164
10165 variable_node<T>* var_node_ptr_;
10166 };
10167
10168 template <typename T>
10170 {
10171 public:
10172
10174
10176 expression_ptr branch0,
10177 expression_ptr branch1)
10178 : binary_node<T>(opr, branch0, branch1),
10179 vec_node_ptr_(0)
10180 {
10182 {
10183 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10184 }
10185 }
10186
10187 inline T value() const
10188 {
10189 if (vec_node_ptr_)
10190 {
10191 assert(binary_node<T>::branch_[1].first);
10192
10193 T& result = vec_node_ptr_->ref();
10194
10195 result = binary_node<T>::branch_[1].first->value();
10196
10197 return result;
10198 }
10199 else
10200 return std::numeric_limits<T>::quiet_NaN();
10201 }
10202
10203 private:
10204
10205 vector_elem_node<T>* vec_node_ptr_;
10206 };
10207
10208 template <typename T>
10210 {
10211 public:
10212
10214
10216 expression_ptr branch0,
10217 expression_ptr branch1)
10218 : binary_node<T>(opr, branch0, branch1),
10219 rbvec_node_ptr_(0)
10220 {
10222 {
10223 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10224 }
10225 }
10226
10227 inline T value() const
10228 {
10229 if (rbvec_node_ptr_)
10230 {
10231 assert(binary_node<T>::branch_[1].first);
10232
10233 T& result = rbvec_node_ptr_->ref();
10234
10235 result = binary_node<T>::branch_[1].first->value();
10236
10237 return result;
10238 }
10239 else
10240 return std::numeric_limits<T>::quiet_NaN();
10241 }
10242
10243 private:
10244
10245 rebasevector_elem_node<T>* rbvec_node_ptr_;
10246 };
10247
10248 template <typename T>
10250 {
10251 public:
10252
10254
10256 expression_ptr branch0,
10257 expression_ptr branch1)
10258 : binary_node<T>(opr, branch0, branch1),
10259 rbvec_node_ptr_(0)
10260 {
10262 {
10263 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10264 }
10265 }
10266
10267 inline T value() const
10268 {
10269 if (rbvec_node_ptr_)
10270 {
10271 assert(binary_node<T>::branch_[1].first);
10272
10273 T& result = rbvec_node_ptr_->ref();
10274
10275 result = binary_node<T>::branch_[1].first->value();
10276
10277 return result;
10278 }
10279 else
10280 return std::numeric_limits<T>::quiet_NaN();
10281 }
10282
10283 private:
10284
10285 rebasevector_celem_node<T>* rbvec_node_ptr_;
10286 };
10287
10288 template <typename T>
10290 public vector_interface<T>
10291 {
10292 public:
10293
10297
10299 expression_ptr branch0,
10300 expression_ptr branch1)
10301 : binary_node<T>(opr, branch0, branch1),
10302 vec_node_ptr_(0)
10303 {
10305 {
10306 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10307 vds() = vec_node_ptr_->vds();
10308 }
10309 }
10310
10311 inline T value() const
10312 {
10313 if (vec_node_ptr_)
10314 {
10315 assert(binary_node<T>::branch_[1].first);
10316
10317 const T v = binary_node<T>::branch_[1].first->value();
10318
10319 T* vec = vds().data();
10320
10322 const T* upper_bound = vec + lud.upper_bound;
10323
10324 while (vec < upper_bound)
10325 {
10326 #define exprtk_loop(N) \
10327 vec[N] = v; \
10328
10329 exprtk_loop( 0) exprtk_loop( 1)
10330 exprtk_loop( 2) exprtk_loop( 3)
10331 #ifndef exprtk_disable_superscalar_unroll
10332 exprtk_loop( 4) exprtk_loop( 5)
10333 exprtk_loop( 6) exprtk_loop( 7)
10334 exprtk_loop( 8) exprtk_loop( 9)
10335 exprtk_loop(10) exprtk_loop(11)
10336 exprtk_loop(12) exprtk_loop(13)
10337 exprtk_loop(14) exprtk_loop(15)
10338 #endif
10339
10340 vec += lud.batch_size;
10341 }
10342
10344 switch (lud.remainder)
10345 {
10346 #define case_stmt(N) \
10347 case N : *vec++ = v; \
10348
10349 #ifndef exprtk_disable_superscalar_unroll
10350 case_stmt(15) case_stmt(14)
10351 case_stmt(13) case_stmt(12)
10352 case_stmt(11) case_stmt(10)
10353 case_stmt( 9) case_stmt( 8)
10354 case_stmt( 7) case_stmt( 6)
10355 case_stmt( 5) case_stmt( 4)
10356 #endif
10357 case_stmt( 3) case_stmt( 2)
10358 case_stmt( 1)
10359 }
10361
10362 #undef exprtk_loop
10363 #undef case_stmt
10364
10365 return vec_node_ptr_->value();
10366 }
10367 else
10368 return std::numeric_limits<T>::quiet_NaN();
10369 }
10370
10372 {
10373 return vec_node_ptr_;
10374 }
10375
10377 {
10378 return vec_node_ptr_;
10379 }
10380
10381 inline typename expression_node<T>::node_type type() const
10382 {
10384 }
10385
10386 std::size_t size() const
10387 {
10388 return vds().size();
10389 }
10390
10392 {
10393 return vds_;
10394 }
10395
10396 const vds_t& vds() const
10397 {
10398 return vds_;
10399 }
10400
10401 private:
10402
10403 vector_node<T>* vec_node_ptr_;
10404 vds_t vds_;
10405 };
10406
10407 template <typename T>
10409 public vector_interface<T>
10410 {
10411 public:
10412
10416
10418 expression_ptr branch0,
10419 expression_ptr branch1)
10420 : binary_node<T>(opr, branch0, branch1),
10421 vec0_node_ptr_(0),
10422 vec1_node_ptr_(0),
10423 initialised_(false),
10424 src_is_ivec_(false)
10425 {
10427 {
10428 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10429 vds() = vec0_node_ptr_->vds();
10430 }
10431
10433 {
10434 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10435 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10436 }
10437 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10438 {
10439 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10440
10441 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10442 {
10443 vec1_node_ptr_ = vi->vec();
10444
10445 if (!vi->side_effect())
10446 {
10447 vi->vds() = vds();
10448 src_is_ivec_ = true;
10449 }
10450 else
10451 vds_t::match_sizes(vds(),vi->vds());
10452 }
10453 }
10454
10455 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10456 }
10457
10458 inline T value() const
10459 {
10460 if (initialised_)
10461 {
10462 assert(binary_node<T>::branch_[1].first);
10463
10464 binary_node<T>::branch_[1].first->value();
10465
10466 if (src_is_ivec_)
10467 return vec0_node_ptr_->value();
10468
10469 T* vec0 = vec0_node_ptr_->vds().data();
10470 T* vec1 = vec1_node_ptr_->vds().data();
10471
10473 const T* upper_bound = vec0 + lud.upper_bound;
10474
10475 while (vec0 < upper_bound)
10476 {
10477 #define exprtk_loop(N) \
10478 vec0[N] = vec1[N]; \
10479
10480 exprtk_loop( 0) exprtk_loop( 1)
10481 exprtk_loop( 2) exprtk_loop( 3)
10482 #ifndef exprtk_disable_superscalar_unroll
10483 exprtk_loop( 4) exprtk_loop( 5)
10484 exprtk_loop( 6) exprtk_loop( 7)
10485 exprtk_loop( 8) exprtk_loop( 9)
10486 exprtk_loop(10) exprtk_loop(11)
10487 exprtk_loop(12) exprtk_loop(13)
10488 exprtk_loop(14) exprtk_loop(15)
10489 #endif
10490
10491 vec0 += lud.batch_size;
10492 vec1 += lud.batch_size;
10493 }
10494
10496 switch (lud.remainder)
10497 {
10498 #define case_stmt(N) \
10499 case N : *vec0++ = *vec1++; \
10500
10501 #ifndef exprtk_disable_superscalar_unroll
10502 case_stmt(15) case_stmt(14)
10503 case_stmt(13) case_stmt(12)
10504 case_stmt(11) case_stmt(10)
10505 case_stmt( 9) case_stmt( 8)
10506 case_stmt( 7) case_stmt( 6)
10507 case_stmt( 5) case_stmt( 4)
10508 #endif
10509 case_stmt( 3) case_stmt( 2)
10510 case_stmt( 1)
10511 }
10513
10514 #undef exprtk_loop
10515 #undef case_stmt
10516
10517 return vec0_node_ptr_->value();
10518 }
10519 else
10520 return std::numeric_limits<T>::quiet_NaN();
10521 }
10522
10524 {
10525 return vec0_node_ptr_;
10526 }
10527
10529 {
10530 return vec0_node_ptr_;
10531 }
10532
10533 inline typename expression_node<T>::node_type type() const
10534 {
10536 }
10537
10538 std::size_t size() const
10539 {
10540 return vds().size();
10541 }
10542
10544 {
10545 return vds_;
10546 }
10547
10548 const vds_t& vds() const
10549 {
10550 return vds_;
10551 }
10552
10553 private:
10554
10555 vector_node<T>* vec0_node_ptr_;
10556 vector_node<T>* vec1_node_ptr_;
10557 bool initialised_;
10558 bool src_is_ivec_;
10559 vds_t vds_;
10560 };
10561
10562 template <typename T, typename Operation>
10564 {
10565 public:
10566
10568
10570 expression_ptr branch0,
10571 expression_ptr branch1)
10572 : binary_node<T>(opr, branch0, branch1),
10573 var_node_ptr_(0)
10574 {
10576 {
10577 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10578 }
10579 }
10580
10581 inline T value() const
10582 {
10583 if (var_node_ptr_)
10584 {
10585 assert(binary_node<T>::branch_[1].first);
10586
10587 T& v = var_node_ptr_->ref();
10589
10590 return v;
10591 }
10592 else
10593 return std::numeric_limits<T>::quiet_NaN();
10594 }
10595
10596 private:
10597
10598 variable_node<T>* var_node_ptr_;
10599 };
10600
10601 template <typename T, typename Operation>
10603 {
10604 public:
10605
10607
10609 expression_ptr branch0,
10610 expression_ptr branch1)
10611 : binary_node<T>(opr, branch0, branch1),
10612 vec_node_ptr_(0)
10613 {
10615 {
10616 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10617 }
10618 }
10619
10620 inline T value() const
10621 {
10622 if (vec_node_ptr_)
10623 {
10624 assert(binary_node<T>::branch_[1].first);
10625
10626 T& v = vec_node_ptr_->ref();
10628
10629 return v;
10630 }
10631 else
10632 return std::numeric_limits<T>::quiet_NaN();
10633 }
10634
10635 private:
10636
10637 vector_elem_node<T>* vec_node_ptr_;
10638 };
10639
10640 template <typename T, typename Operation>
10642 {
10643 public:
10644
10646
10648 expression_ptr branch0,
10649 expression_ptr branch1)
10650 : binary_node<T>(opr, branch0, branch1),
10651 rbvec_node_ptr_(0)
10652 {
10654 {
10655 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10656 }
10657 }
10658
10659 inline T value() const
10660 {
10661 if (rbvec_node_ptr_)
10662 {
10663 assert(binary_node<T>::branch_[1].first);
10664
10665 T& v = rbvec_node_ptr_->ref();
10667
10668 return v;
10669 }
10670 else
10671 return std::numeric_limits<T>::quiet_NaN();
10672 }
10673
10674 private:
10675
10676 rebasevector_elem_node<T>* rbvec_node_ptr_;
10677 };
10678
10679 template <typename T, typename Operation>
10681 {
10682 public:
10683
10685
10687 expression_ptr branch0,
10688 expression_ptr branch1)
10689 : binary_node<T>(opr, branch0, branch1),
10690 rbvec_node_ptr_(0)
10691 {
10693 {
10694 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10695 }
10696 }
10697
10698 inline T value() const
10699 {
10700 if (rbvec_node_ptr_)
10701 {
10702 assert(binary_node<T>::branch_[1].first);
10703
10704 T& v = rbvec_node_ptr_->ref();
10706
10707 return v;
10708 }
10709 else
10710 return std::numeric_limits<T>::quiet_NaN();
10711 }
10712
10713 private:
10714
10715 rebasevector_celem_node<T>* rbvec_node_ptr_;
10716 };
10717
10718 template <typename T, typename Operation>
10720 public vector_interface<T>
10721 {
10722 public:
10723
10727
10729 expression_ptr branch0,
10730 expression_ptr branch1)
10731 : binary_node<T>(opr, branch0, branch1),
10732 vec_node_ptr_(0)
10733 {
10735 {
10736 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10737 vds() = vec_node_ptr_->vds();
10738 }
10739 }
10740
10741 inline T value() const
10742 {
10743 if (vec_node_ptr_)
10744 {
10745 assert(binary_node<T>::branch_[1].first);
10746
10747 const T v = binary_node<T>::branch_[1].first->value();
10748
10749 T* vec = vds().data();
10750
10752 const T* upper_bound = vec + lud.upper_bound;
10753
10754 while (vec < upper_bound)
10755 {
10756 #define exprtk_loop(N) \
10757 Operation::assign(vec[N],v); \
10758
10759 exprtk_loop( 0) exprtk_loop( 1)
10760 exprtk_loop( 2) exprtk_loop( 3)
10761 #ifndef exprtk_disable_superscalar_unroll
10762 exprtk_loop( 4) exprtk_loop( 5)
10763 exprtk_loop( 6) exprtk_loop( 7)
10764 exprtk_loop( 8) exprtk_loop( 9)
10765 exprtk_loop(10) exprtk_loop(11)
10766 exprtk_loop(12) exprtk_loop(13)
10767 exprtk_loop(14) exprtk_loop(15)
10768 #endif
10769
10770 vec += lud.batch_size;
10771 }
10772
10774 switch (lud.remainder)
10775 {
10776 #define case_stmt(N) \
10777 case N : Operation::assign(*vec++,v); \
10778
10779 #ifndef exprtk_disable_superscalar_unroll
10780 case_stmt(15) case_stmt(14)
10781 case_stmt(13) case_stmt(12)
10782 case_stmt(11) case_stmt(10)
10783 case_stmt( 9) case_stmt( 8)
10784 case_stmt( 7) case_stmt( 6)
10785 case_stmt( 5) case_stmt( 4)
10786 #endif
10787 case_stmt( 3) case_stmt( 2)
10788 case_stmt( 1)
10789 }
10791
10792
10793 #undef exprtk_loop
10794 #undef case_stmt
10795
10796 return vec_node_ptr_->value();
10797 }
10798 else
10799 return std::numeric_limits<T>::quiet_NaN();
10800 }
10801
10803 {
10804 return vec_node_ptr_;
10805 }
10806
10808 {
10809 return vec_node_ptr_;
10810 }
10811
10812 inline typename expression_node<T>::node_type type() const
10813 {
10815 }
10816
10817 std::size_t size() const
10818 {
10819 return vds().size();
10820 }
10821
10823 {
10824 return vds_;
10825 }
10826
10827 const vds_t& vds() const
10828 {
10829 return vds_;
10830 }
10831
10832 bool side_effect() const
10833 {
10834 return true;
10835 }
10836
10837 private:
10838
10839 vector_node<T>* vec_node_ptr_;
10840 vds_t vds_;
10841 };
10842
10843 template <typename T, typename Operation>
10845 public vector_interface<T>
10846 {
10847 public:
10848
10852
10854 expression_ptr branch0,
10855 expression_ptr branch1)
10856 : binary_node<T>(opr, branch0, branch1),
10857 vec0_node_ptr_(0),
10858 vec1_node_ptr_(0),
10859 initialised_(false)
10860 {
10862 {
10863 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10864 vds() = vec0_node_ptr_->vds();
10865 }
10866
10868 {
10869 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10870 vec1_node_ptr_->vds() = vds();
10871 }
10872 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10873 {
10874 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10875
10876 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10877 {
10878 vec1_node_ptr_ = vi->vec();
10879 vec1_node_ptr_->vds() = vds();
10880 }
10881 else
10882 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10883 }
10884
10885 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10886 }
10887
10888 inline T value() const
10889 {
10890 if (initialised_)
10891 {
10892 assert(binary_node<T>::branch_[0].first);
10893 assert(binary_node<T>::branch_[1].first);
10894
10895 binary_node<T>::branch_[0].first->value();
10896 binary_node<T>::branch_[1].first->value();
10897
10898 T* vec0 = vec0_node_ptr_->vds().data();
10899 const T* vec1 = vec1_node_ptr_->vds().data();
10900
10902 const T* upper_bound = vec0 + lud.upper_bound;
10903
10904 while (vec0 < upper_bound)
10905 {
10906 #define exprtk_loop(N) \
10907 vec0[N] = Operation::process(vec0[N], vec1[N]); \
10908
10909 exprtk_loop( 0) exprtk_loop( 1)
10910 exprtk_loop( 2) exprtk_loop( 3)
10911 #ifndef exprtk_disable_superscalar_unroll
10912 exprtk_loop( 4) exprtk_loop( 5)
10913 exprtk_loop( 6) exprtk_loop( 7)
10914 exprtk_loop( 8) exprtk_loop( 9)
10915 exprtk_loop(10) exprtk_loop(11)
10916 exprtk_loop(12) exprtk_loop(13)
10917 exprtk_loop(14) exprtk_loop(15)
10918 #endif
10919
10920 vec0 += lud.batch_size;
10921 vec1 += lud.batch_size;
10922 }
10923
10924 int i = 0;
10925
10927 switch (lud.remainder)
10928 {
10929 #define case_stmt(N) \
10930 case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10931
10932 #ifndef exprtk_disable_superscalar_unroll
10933 case_stmt(15) case_stmt(14)
10934 case_stmt(13) case_stmt(12)
10935 case_stmt(11) case_stmt(10)
10936 case_stmt( 9) case_stmt( 8)
10937 case_stmt( 7) case_stmt( 6)
10938 case_stmt( 5) case_stmt( 4)
10939 #endif
10940 case_stmt( 3) case_stmt( 2)
10941 case_stmt( 1)
10942 }
10944
10945 #undef exprtk_loop
10946 #undef case_stmt
10947
10948 return vec0_node_ptr_->value();
10949 }
10950 else
10951 return std::numeric_limits<T>::quiet_NaN();
10952 }
10953
10955 {
10956 return vec0_node_ptr_;
10957 }
10958
10960 {
10961 return vec0_node_ptr_;
10962 }
10963
10964 inline typename expression_node<T>::node_type type() const
10965 {
10967 }
10968
10969 std::size_t size() const
10970 {
10971 return vds().size();
10972 }
10973
10975 {
10976 return vds_;
10977 }
10978
10979 const vds_t& vds() const
10980 {
10981 return vds_;
10982 }
10983
10984 bool side_effect() const
10985 {
10986 return true;
10987 }
10988
10989 private:
10990
10991 vector_node<T>* vec0_node_ptr_;
10992 vector_node<T>* vec1_node_ptr_;
10993 bool initialised_;
10994 vds_t vds_;
10995 };
10996
10997 template <typename T, typename Operation>
10999 public vector_interface<T>
11000 {
11001 public:
11002
11007
11009 expression_ptr branch0,
11010 expression_ptr branch1)
11011 : binary_node<T>(opr, branch0, branch1),
11012 vec0_node_ptr_(0),
11013 vec1_node_ptr_(0),
11014 temp_ (0),
11015 temp_vec_node_(0),
11016 initialised_(false)
11017 {
11018 bool v0_is_ivec = false;
11019 bool v1_is_ivec = false;
11020
11022 {
11023 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
11024 }
11025 else if (is_ivector_node(binary_node<T>::branch_[0].first))
11026 {
11027 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11028
11029 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
11030 {
11031 vec0_node_ptr_ = vi->vec();
11032 v0_is_ivec = true;
11033 }
11034 }
11035
11037 {
11038 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
11039 }
11040 else if (is_ivector_node(binary_node<T>::branch_[1].first))
11041 {
11042 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11043
11044 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
11045 {
11046 vec1_node_ptr_ = vi->vec();
11047 v1_is_ivec = true;
11048 }
11049 }
11050
11051 if (vec0_node_ptr_ && vec1_node_ptr_)
11052 {
11053 vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
11054 vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
11055
11056 if (v0_is_ivec && (vec0.size() <= vec1.size()))
11057 vds_ = vds_t(vec0_node_ptr_->vds());
11058 else if (v1_is_ivec && (vec1.size() <= vec0.size()))
11059 vds_ = vds_t(vec1_node_ptr_->vds());
11060 else
11061 vds_ = vds_t(std::min(vec0.size(),vec1.size()));
11062
11063 temp_ = new vector_holder<T>(vds().data(),vds().size());
11064 temp_vec_node_ = new vector_node<T> (vds(),temp_);
11065
11066 initialised_ = true;
11067 }
11068 }
11069
11071 {
11072 delete temp_;
11073 delete temp_vec_node_;
11074 }
11075
11076 inline T value() const
11077 {
11078 if (initialised_)
11079 {
11080 assert(binary_node<T>::branch_[0].first);
11081 assert(binary_node<T>::branch_[1].first);
11082
11083 binary_node<T>::branch_[0].first->value();
11084 binary_node<T>::branch_[1].first->value();
11085
11086 const T* vec0 = vec0_node_ptr_->vds().data();
11087 const T* vec1 = vec1_node_ptr_->vds().data();
11088 T* vec2 = vds().data();
11089
11091 const T* upper_bound = vec2 + lud.upper_bound;
11092
11093 while (vec2 < upper_bound)
11094 {
11095 #define exprtk_loop(N) \
11096 vec2[N] = Operation::process(vec0[N], vec1[N]); \
11097
11098 exprtk_loop( 0) exprtk_loop( 1)
11099 exprtk_loop( 2) exprtk_loop( 3)
11100 #ifndef exprtk_disable_superscalar_unroll
11101 exprtk_loop( 4) exprtk_loop( 5)
11102 exprtk_loop( 6) exprtk_loop( 7)
11103 exprtk_loop( 8) exprtk_loop( 9)
11104 exprtk_loop(10) exprtk_loop(11)
11105 exprtk_loop(12) exprtk_loop(13)
11106 exprtk_loop(14) exprtk_loop(15)
11107 #endif
11108
11109 vec0 += lud.batch_size;
11110 vec1 += lud.batch_size;
11111 vec2 += lud.batch_size;
11112 }
11113
11114 int i = 0;
11115
11117 switch (lud.remainder)
11118 {
11119 #define case_stmt(N) \
11120 case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
11121
11122 #ifndef exprtk_disable_superscalar_unroll
11123 case_stmt(15) case_stmt(14)
11124 case_stmt(13) case_stmt(12)
11125 case_stmt(11) case_stmt(10)
11126 case_stmt( 9) case_stmt( 8)
11127 case_stmt( 7) case_stmt( 6)
11128 case_stmt( 5) case_stmt( 4)
11129 #endif
11130 case_stmt( 3) case_stmt( 2)
11131 case_stmt( 1)
11132 }
11134
11135 #undef exprtk_loop
11136 #undef case_stmt
11137
11138 return (vds().data())[0];
11139 }
11140 else
11141 return std::numeric_limits<T>::quiet_NaN();
11142 }
11143
11145 {
11146 return temp_vec_node_;
11147 }
11148
11150 {
11151 return temp_vec_node_;
11152 }
11153
11154 inline typename expression_node<T>::node_type type() const
11155 {
11157 }
11158
11159 std::size_t size() const
11160 {
11161 return vds_.size();
11162 }
11163
11165 {
11166 return vds_;
11167 }
11168
11169 const vds_t& vds() const
11170 {
11171 return vds_;
11172 }
11173
11174 private:
11175
11176 vector_node_ptr vec0_node_ptr_;
11177 vector_node_ptr vec1_node_ptr_;
11178 vector_holder_ptr temp_;
11179 vector_node_ptr temp_vec_node_;
11180 bool initialised_;
11181 vds_t vds_;
11182 };
11183
11184 template <typename T, typename Operation>
11186 public vector_interface<T>
11187 {
11188 public:
11189
11194
11196 expression_ptr branch0,
11197 expression_ptr branch1)
11198 : binary_node<T>(opr, branch0, branch1),
11199 vec0_node_ptr_(0),
11200 temp_ (0),
11201 temp_vec_node_(0)
11202 {
11203 bool v0_is_ivec = false;
11204
11206 {
11207 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
11208 }
11209 else if (is_ivector_node(binary_node<T>::branch_[0].first))
11210 {
11211 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11212
11213 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
11214 {
11215 vec0_node_ptr_ = vi->vec();
11216 v0_is_ivec = true;
11217 }
11218 }
11219
11220 if (vec0_node_ptr_)
11221 {
11222 if (v0_is_ivec)
11223 vds() = vec0_node_ptr_->vds();
11224 else
11225 vds() = vds_t(vec0_node_ptr_->size());
11226
11227 temp_ = new vector_holder<T>(vds());
11228 temp_vec_node_ = new vector_node<T> (vds(),temp_);
11229 }
11230 }
11231
11233 {
11234 delete temp_;
11235 delete temp_vec_node_;
11236 }
11237
11238 inline T value() const
11239 {
11240 if (vec0_node_ptr_)
11241 {
11242 assert(binary_node<T>::branch_[0].first);
11243 assert(binary_node<T>::branch_[1].first);
11244
11245 binary_node<T>::branch_[0].first->value();
11246 const T v = binary_node<T>::branch_[1].first->value();
11247
11248 const T* vec0 = vec0_node_ptr_->vds().data();
11249 T* vec1 = vds().data();
11250
11252 const T* upper_bound = vec0 + lud.upper_bound;
11253
11254 while (vec0 < upper_bound)
11255 {
11256 #define exprtk_loop(N) \
11257 vec1[N] = Operation::process(vec0[N], v); \
11258
11259 exprtk_loop( 0) exprtk_loop( 1)
11260 exprtk_loop( 2) exprtk_loop( 3)
11261 #ifndef exprtk_disable_superscalar_unroll
11262 exprtk_loop( 4) exprtk_loop( 5)
11263 exprtk_loop( 6) exprtk_loop( 7)
11264 exprtk_loop( 8) exprtk_loop( 9)
11265 exprtk_loop(10) exprtk_loop(11)
11266 exprtk_loop(12) exprtk_loop(13)
11267 exprtk_loop(14) exprtk_loop(15)
11268 #endif
11269
11270 vec0 += lud.batch_size;
11271 vec1 += lud.batch_size;
11272 }
11273
11274 int i = 0;
11275
11277 switch (lud.remainder)
11278 {
11279 #define case_stmt(N) \
11280 case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
11281
11282 #ifndef exprtk_disable_superscalar_unroll
11283 case_stmt(15) case_stmt(14)
11284 case_stmt(13) case_stmt(12)
11285 case_stmt(11) case_stmt(10)
11286 case_stmt( 9) case_stmt( 8)
11287 case_stmt( 7) case_stmt( 6)
11288 case_stmt( 5) case_stmt( 4)
11289 #endif
11290 case_stmt( 3) case_stmt( 2)
11291 case_stmt( 1)
11292 }
11294
11295 #undef exprtk_loop
11296 #undef case_stmt
11297
11298 return (vds().data())[0];
11299 }
11300 else
11301 return std::numeric_limits<T>::quiet_NaN();
11302 }
11303
11305 {
11306 return temp_vec_node_;
11307 }
11308
11310 {
11311 return temp_vec_node_;
11312 }
11313
11314 inline typename expression_node<T>::node_type type() const
11315 {
11317 }
11318
11319 std::size_t size() const
11320 {
11321 return vds().size();
11322 }
11323
11325 {
11326 return vds_;
11327 }
11328
11329 const vds_t& vds() const
11330 {
11331 return vds_;
11332 }
11333
11334 private:
11335
11336 vector_node_ptr vec0_node_ptr_;
11337 vector_holder_ptr temp_;
11338 vector_node_ptr temp_vec_node_;
11339 vds_t vds_;
11340 };
11341
11342 template <typename T, typename Operation>
11344 public vector_interface<T>
11345 {
11346 public:
11347
11352
11354 expression_ptr branch0,
11355 expression_ptr branch1)
11356 : binary_node<T>(opr, branch0, branch1),
11357 vec1_node_ptr_(0),
11358 temp_ (0),
11359 temp_vec_node_(0)
11360 {
11361 bool v1_is_ivec = false;
11362
11364 {
11365 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
11366 }
11367 else if (is_ivector_node(binary_node<T>::branch_[1].first))
11368 {
11369 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11370
11371 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
11372 {
11373 vec1_node_ptr_ = vi->vec();
11374 v1_is_ivec = true;
11375 }
11376 }
11377
11378 if (vec1_node_ptr_)
11379 {
11380 if (v1_is_ivec)
11381 vds() = vec1_node_ptr_->vds();
11382 else
11383 vds() = vds_t(vec1_node_ptr_->size());
11384
11385 temp_ = new vector_holder<T>(vds());
11386 temp_vec_node_ = new vector_node<T> (vds(),temp_);
11387 }
11388 }
11389
11391 {
11392 delete temp_;
11393 delete temp_vec_node_;
11394 }
11395
11396 inline T value() const
11397 {
11398 if (vec1_node_ptr_)
11399 {
11400 assert(binary_node<T>::branch_[0].first);
11401 assert(binary_node<T>::branch_[1].first);
11402
11403 const T v = binary_node<T>::branch_[0].first->value();
11404 binary_node<T>::branch_[1].first->value();
11405
11406 T* vec0 = vds().data();
11407 const T* vec1 = vec1_node_ptr_->vds().data();
11408
11410 const T* upper_bound = vec0 + lud.upper_bound;
11411
11412 while (vec0 < upper_bound)
11413 {
11414 #define exprtk_loop(N) \
11415 vec0[N] = Operation::process(v, vec1[N]); \
11416
11417 exprtk_loop( 0) exprtk_loop( 1)
11418 exprtk_loop( 2) exprtk_loop( 3)
11419 #ifndef exprtk_disable_superscalar_unroll
11420 exprtk_loop( 4) exprtk_loop( 5)
11421 exprtk_loop( 6) exprtk_loop( 7)
11422 exprtk_loop( 8) exprtk_loop( 9)
11423 exprtk_loop(10) exprtk_loop(11)
11424 exprtk_loop(12) exprtk_loop(13)
11425 exprtk_loop(14) exprtk_loop(15)
11426 #endif
11427
11428 vec0 += lud.batch_size;
11429 vec1 += lud.batch_size;
11430 }
11431
11432 int i = 0;
11433
11435 switch (lud.remainder)
11436 {
11437 #define case_stmt(N) \
11438 case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
11439
11440 #ifndef exprtk_disable_superscalar_unroll
11441 case_stmt(15) case_stmt(14)
11442 case_stmt(13) case_stmt(12)
11443 case_stmt(11) case_stmt(10)
11444 case_stmt( 9) case_stmt( 8)
11445 case_stmt( 7) case_stmt( 6)
11446 case_stmt( 5) case_stmt( 4)
11447 #endif
11448 case_stmt( 3) case_stmt( 2)
11449 case_stmt( 1)
11450 }
11452
11453 #undef exprtk_loop
11454 #undef case_stmt
11455
11456 return (vds().data())[0];
11457 }
11458 else
11459 return std::numeric_limits<T>::quiet_NaN();
11460 }
11461
11463 {
11464 return temp_vec_node_;
11465 }
11466
11468 {
11469 return temp_vec_node_;
11470 }
11471
11472 inline typename expression_node<T>::node_type type() const
11473 {
11475 }
11476
11477 std::size_t size() const
11478 {
11479 return vds().size();
11480 }
11481
11483 {
11484 return vds_;
11485 }
11486
11487 const vds_t& vds() const
11488 {
11489 return vds_;
11490 }
11491
11492 private:
11493
11494 vector_node_ptr vec1_node_ptr_;
11495 vector_holder_ptr temp_;
11496 vector_node_ptr temp_vec_node_;
11497 vds_t vds_;
11498 };
11499
11500 template <typename T, typename Operation>
11501 class unary_vector_node : public unary_node <T>,
11502 public vector_interface<T>
11503 {
11504 public:
11505
11510
11512 : unary_node<T>(opr, branch0),
11513 vec0_node_ptr_(0),
11514 temp_ (0),
11515 temp_vec_node_(0)
11516 {
11517 bool vec0_is_ivec = false;
11518
11520 {
11521 vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first);
11522 }
11524 {
11525 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11526
11527 if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first)))
11528 {
11529 vec0_node_ptr_ = vi->vec();
11530 vec0_is_ivec = true;
11531 }
11532 }
11533
11534 if (vec0_node_ptr_)
11535 {
11536 if (vec0_is_ivec)
11537 vds_ = vec0_node_ptr_->vds();
11538 else
11539 vds_ = vds_t(vec0_node_ptr_->size());
11540
11541 temp_ = new vector_holder<T>(vds());
11542 temp_vec_node_ = new vector_node<T> (vds(),temp_);
11543 }
11544 }
11545
11547 {
11548 delete temp_;
11549 delete temp_vec_node_;
11550 }
11551
11552 inline T value() const
11553 {
11554 assert(unary_node<T>::branch_.first);
11555
11557
11558 if (vec0_node_ptr_)
11559 {
11560 const T* vec0 = vec0_node_ptr_->vds().data();
11561 T* vec1 = vds().data();
11562
11564 const T* upper_bound = vec0 + lud.upper_bound;
11565
11566 while (vec0 < upper_bound)
11567 {
11568 #define exprtk_loop(N) \
11569 vec1[N] = Operation::process(vec0[N]); \
11570
11571 exprtk_loop( 0) exprtk_loop( 1)
11572 exprtk_loop( 2) exprtk_loop( 3)
11573 #ifndef exprtk_disable_superscalar_unroll
11574 exprtk_loop( 4) exprtk_loop( 5)
11575 exprtk_loop( 6) exprtk_loop( 7)
11576 exprtk_loop( 8) exprtk_loop( 9)
11577 exprtk_loop(10) exprtk_loop(11)
11578 exprtk_loop(12) exprtk_loop(13)
11579 exprtk_loop(14) exprtk_loop(15)
11580 #endif
11581
11582 vec0 += lud.batch_size;
11583 vec1 += lud.batch_size;
11584 }
11585
11586 int i = 0;
11587
11589 switch (lud.remainder)
11590 {
11591 #define case_stmt(N) \
11592 case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11593
11594 #ifndef exprtk_disable_superscalar_unroll
11595 case_stmt(15) case_stmt(14)
11596 case_stmt(13) case_stmt(12)
11597 case_stmt(11) case_stmt(10)
11598 case_stmt( 9) case_stmt( 8)
11599 case_stmt( 7) case_stmt( 6)
11600 case_stmt( 5) case_stmt( 4)
11601 #endif
11602 case_stmt( 3) case_stmt( 2)
11603 case_stmt( 1)
11604 }
11606
11607 #undef exprtk_loop
11608 #undef case_stmt
11609
11610 return (vds().data())[0];
11611 }
11612 else
11613 return std::numeric_limits<T>::quiet_NaN();
11614 }
11615
11617 {
11618 return temp_vec_node_;
11619 }
11620
11622 {
11623 return temp_vec_node_;
11624 }
11625
11626 inline typename expression_node<T>::node_type type() const
11627 {
11629 }
11630
11631 std::size_t size() const
11632 {
11633 return vds().size();
11634 }
11635
11637 {
11638 return vds_;
11639 }
11640
11641 const vds_t& vds() const
11642 {
11643 return vds_;
11644 }
11645
11646 private:
11647
11648 vector_node_ptr vec0_node_ptr_;
11649 vector_holder_ptr temp_;
11650 vector_node_ptr temp_vec_node_;
11651 vds_t vds_;
11652 };
11653
11654 template <typename T>
11655 class scand_node : public binary_node<T>
11656 {
11657 public:
11658
11660
11662 expression_ptr branch0,
11663 expression_ptr branch1)
11664 : binary_node<T>(opr, branch0, branch1)
11665 {}
11666
11667 inline T value() const
11668 {
11669 assert(binary_node<T>::branch_[0].first);
11670 assert(binary_node<T>::branch_[1].first);
11671
11672 return (
11673 std::not_equal_to<T>()
11674 (T(0),binary_node<T>::branch_[0].first->value()) &&
11675 std::not_equal_to<T>()
11676 (T(0),binary_node<T>::branch_[1].first->value())
11677 ) ? T(1) : T(0);
11678 }
11679 };
11680
11681 template <typename T>
11682 class scor_node : public binary_node<T>
11683 {
11684 public:
11685
11687
11689 expression_ptr branch0,
11690 expression_ptr branch1)
11691 : binary_node<T>(opr, branch0, branch1)
11692 {}
11693
11694 inline T value() const
11695 {
11696 assert(binary_node<T>::branch_[0].first);
11697 assert(binary_node<T>::branch_[1].first);
11698
11699 return (
11700 std::not_equal_to<T>()
11701 (T(0),binary_node<T>::branch_[0].first->value()) ||
11702 std::not_equal_to<T>()
11703 (T(0),binary_node<T>::branch_[1].first->value())
11704 ) ? T(1) : T(0);
11705 }
11706 };
11707
11708 template <typename T, typename IFunction, std::size_t N>
11710 {
11711 public:
11712
11713 // Function of N paramters.
11715 typedef std::pair<expression_ptr,bool> branch_t;
11716 typedef IFunction ifunction;
11717
11719 : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11720 parameter_count_(func->param_count)
11721 {}
11722
11723 template <std::size_t NumBranches>
11724 bool init_branches(expression_ptr (&b)[NumBranches])
11725 {
11726 // Needed for incompetent and broken msvc compiler versions
11727 #ifdef _MSC_VER
11728 #pragma warning(push)
11729 #pragma warning(disable: 4127)
11730 #endif
11731 if (N != NumBranches)
11732 return false;
11733 else
11734 {
11735 for (std::size_t i = 0; i < NumBranches; ++i)
11736 {
11737 if (b[i])
11738 branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11739 else
11740 return false;
11741 }
11742 return true;
11743 }
11744 #ifdef _MSC_VER
11745 #pragma warning(pop)
11746 #endif
11747 }
11748
11749 inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11750 {
11751 return this < (&fn);
11752 }
11753
11754 inline T value() const
11755 {
11756 // Needed for incompetent and broken msvc compiler versions
11757 #ifdef _MSC_VER
11758 #pragma warning(push)
11759 #pragma warning(disable: 4127)
11760 #endif
11761 if ((0 == function_) || (0 == N))
11762 return std::numeric_limits<T>::quiet_NaN();
11763 else
11764 {
11765 T v[N];
11767 return invoke<T,N>::execute(*function_,v);
11768 }
11769 #ifdef _MSC_VER
11770 #pragma warning(pop)
11771 #endif
11772 }
11773
11774 template <typename T_, std::size_t BranchCount>
11776 {
11777 static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11778 {
11779 for (std::size_t i = 0; i < BranchCount; ++i)
11780 {
11781 v[i] = b[i].first->value();
11782 }
11783 }
11784 };
11785
11786 template <typename T_>
11787 struct evaluate_branches <T_,5>
11788 {
11789 static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11790 {
11791 v[0] = b[0].first->value();
11792 v[1] = b[1].first->value();
11793 v[2] = b[2].first->value();
11794 v[3] = b[3].first->value();
11795 v[4] = b[4].first->value();
11796 }
11797 };
11798
11799 template <typename T_>
11800 struct evaluate_branches <T_,4>
11801 {
11802 static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11803 {
11804 v[0] = b[0].first->value();
11805 v[1] = b[1].first->value();
11806 v[2] = b[2].first->value();
11807 v[3] = b[3].first->value();
11808 }
11809 };
11810
11811 template <typename T_>
11812 struct evaluate_branches <T_,3>
11813 {
11814 static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11815 {
11816 v[0] = b[0].first->value();
11817 v[1] = b[1].first->value();
11818 v[2] = b[2].first->value();
11819 }
11820 };
11821
11822 template <typename T_>
11823 struct evaluate_branches <T_,2>
11824 {
11825 static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11826 {
11827 v[0] = b[0].first->value();
11828 v[1] = b[1].first->value();
11829 }
11830 };
11831
11832 template <typename T_>
11833 struct evaluate_branches <T_,1>
11834 {
11835 static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11836 {
11837 v[0] = b[0].first->value();
11838 }
11839 };
11840
11841 template <typename T_, std::size_t ParamCount>
11842 struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11843
11844 template <typename T_>
11845 struct invoke<T_,20>
11846 {
11847 static inline T_ execute(ifunction& f, T_ (&v)[20])
11848 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
11849 };
11850
11851 template <typename T_>
11852 struct invoke<T_,19>
11853 {
11854 static inline T_ execute(ifunction& f, T_ (&v)[19])
11855 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
11856 };
11857
11858 template <typename T_>
11859 struct invoke<T_,18>
11860 {
11861 static inline T_ execute(ifunction& f, T_ (&v)[18])
11862 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
11863 };
11864
11865 template <typename T_>
11866 struct invoke<T_,17>
11867 {
11868 static inline T_ execute(ifunction& f, T_ (&v)[17])
11869 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
11870 };
11871
11872 template <typename T_>
11873 struct invoke<T_,16>
11874 {
11875 static inline T_ execute(ifunction& f, T_ (&v)[16])
11876 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
11877 };
11878
11879 template <typename T_>
11880 struct invoke<T_,15>
11881 {
11882 static inline T_ execute(ifunction& f, T_ (&v)[15])
11883 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
11884 };
11885
11886 template <typename T_>
11887 struct invoke<T_,14>
11888 {
11889 static inline T_ execute(ifunction& f, T_ (&v)[14])
11890 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
11891 };
11892
11893 template <typename T_>
11894 struct invoke<T_,13>
11895 {
11896 static inline T_ execute(ifunction& f, T_ (&v)[13])
11897 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
11898 };
11899
11900 template <typename T_>
11901 struct invoke<T_,12>
11902 {
11903 static inline T_ execute(ifunction& f, T_ (&v)[12])
11904 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
11905 };
11906
11907 template <typename T_>
11908 struct invoke<T_,11>
11909 {
11910 static inline T_ execute(ifunction& f, T_ (&v)[11])
11911 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
11912 };
11913
11914 template <typename T_>
11915 struct invoke<T_,10>
11916 {
11917 static inline T_ execute(ifunction& f, T_ (&v)[10])
11918 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11919 };
11920
11921 template <typename T_>
11922 struct invoke<T_,9>
11923 {
11924 static inline T_ execute(ifunction& f, T_ (&v)[9])
11925 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11926 };
11927
11928 template <typename T_>
11929 struct invoke<T_,8>
11930 {
11931 static inline T_ execute(ifunction& f, T_ (&v)[8])
11932 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11933 };
11934
11935 template <typename T_>
11936 struct invoke<T_,7>
11937 {
11938 static inline T_ execute(ifunction& f, T_ (&v)[7])
11939 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11940 };
11941
11942 template <typename T_>
11943 struct invoke<T_,6>
11944 {
11945 static inline T_ execute(ifunction& f, T_ (&v)[6])
11946 { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11947 };
11948
11949 template <typename T_>
11950 struct invoke<T_,5>
11951 {
11952 static inline T_ execute(ifunction& f, T_ (&v)[5])
11953 { return f(v[0],v[1],v[2],v[3],v[4]); }
11954 };
11955
11956 template <typename T_>
11957 struct invoke<T_,4>
11958 {
11959 static inline T_ execute(ifunction& f, T_ (&v)[4])
11960 { return f(v[0],v[1],v[2],v[3]); }
11961 };
11962
11963 template <typename T_>
11964 struct invoke<T_,3>
11965 {
11966 static inline T_ execute(ifunction& f, T_ (&v)[3])
11967 { return f(v[0],v[1],v[2]); }
11968 };
11969
11970 template <typename T_>
11971 struct invoke<T_,2>
11972 {
11973 static inline T_ execute(ifunction& f, T_ (&v)[2])
11974 { return f(v[0],v[1]); }
11975 };
11976
11977 template <typename T_>
11978 struct invoke<T_,1>
11979 {
11980 static inline T_ execute(ifunction& f, T_ (&v)[1])
11981 { return f(v[0]); }
11982 };
11983
11984 inline typename expression_node<T>::node_type type() const
11985 {
11987 }
11988
11989 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
11990 {
11991 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
11992 }
11993
11994 std::size_t node_depth() const
11995 {
11996 return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
11997 }
11998
11999 private:
12000
12001 ifunction* function_;
12002 std::size_t parameter_count_;
12003 branch_t branch_[N];
12004 };
12005
12006 template <typename T, typename IFunction>
12007 class function_N_node<T,IFunction,0> : public expression_node<T>
12008 {
12009 public:
12010
12012 typedef IFunction ifunction;
12013
12015 : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
12016 {}
12017
12018 inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
12019 {
12020 return this < (&fn);
12021 }
12022
12023 inline T value() const
12024 {
12025 if (function_)
12026 return (*function_)();
12027 else
12028 return std::numeric_limits<T>::quiet_NaN();
12029 }
12030
12031 inline typename expression_node<T>::node_type type() const
12032 {
12034 }
12035
12036 private:
12037
12038 ifunction* function_;
12039 };
12040
12041 template <typename T, typename VarArgFunction>
12043 {
12044 public:
12045
12047
12048 vararg_function_node(VarArgFunction* func,
12049 const std::vector<expression_ptr>& arg_list)
12050 : function_(func),
12051 arg_list_(arg_list)
12052 {
12053 value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
12054 }
12055
12057 {
12058 return this < (&fn);
12059 }
12060
12061 inline T value() const
12062 {
12063 if (function_)
12064 {
12065 populate_value_list();
12066 return (*function_)(value_list_);
12067 }
12068 else
12069 return std::numeric_limits<T>::quiet_NaN();
12070 }
12071
12072 inline typename expression_node<T>::node_type type() const
12073 {
12075 }
12076
12077 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12078 {
12079 for (std::size_t i = 0; i < arg_list_.size(); ++i)
12080 {
12081 if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
12082 {
12083 node_delete_list.push_back(&arg_list_[i]);
12084 }
12085 }
12086 }
12087
12088 std::size_t node_depth() const
12089 {
12091 }
12092
12093 private:
12094
12095 inline void populate_value_list() const
12096 {
12097 for (std::size_t i = 0; i < arg_list_.size(); ++i)
12098 {
12099 value_list_[i] = arg_list_[i]->value();
12100 }
12101 }
12102
12103 VarArgFunction* function_;
12104 std::vector<expression_ptr> arg_list_;
12105 mutable std::vector<T> value_list_;
12106 };
12107
12108 template <typename T, typename GenericFunction>
12110 {
12111 public:
12112
12122 typedef std::pair<expression_ptr,bool> branch_t;
12123 typedef std::pair<void*,std::size_t> void_t;
12124 typedef std::vector<T> tmp_vs_t;
12125 typedef std::vector<type_store_t> typestore_list_t;
12126 typedef std::vector<range_data_type_t> range_list_t;
12127
12128 explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
12129 GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
12130 : function_(func),
12131 arg_list_(arg_list)
12132 {}
12133
12135 {}
12136
12137 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12138 {
12139 expression_node<T>::ndb_t::collect(branch_, node_delete_list);
12140 }
12141
12142 std::size_t node_depth() const
12143 {
12145 }
12146
12147 virtual bool init_branches()
12148 {
12149 expr_as_vec1_store_.resize(arg_list_.size(),T(0) );
12150 typestore_list_ .resize(arg_list_.size(),type_store_t() );
12151 range_list_ .resize(arg_list_.size(),range_data_type_t());
12152 branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast<expression_ptr>(0),false));
12153
12154 for (std::size_t i = 0; i < arg_list_.size(); ++i)
12155 {
12157
12158 if (0 == arg_list_[i])
12159 return false;
12160 else if (is_ivector_node(arg_list_[i]))
12161 {
12162 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
12163
12164 if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
12165 return false;
12166
12167 ts.size = vi->size();
12168 ts.data = vi->vds().data();
12170 vi->vec()->vec_holder().set_ref(&ts.vec_data);
12171 }
12172 #ifndef exprtk_disable_string_capabilities
12173 else if (is_generally_string_node(arg_list_[i]))
12174 {
12175 string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
12176
12177 if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
12178 return false;
12179
12180 ts.size = sbn->size();
12181 ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
12183
12184 range_list_[i].data = ts.data;
12185 range_list_[i].size = ts.size;
12186 range_list_[i].type_size = sizeof(char);
12187 range_list_[i].str_node = sbn;
12188
12189 range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
12190
12191 if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
12192 return false;
12193
12194 const range_t& rp = ri->range_ref();
12195
12196 if (
12197 rp.const_range() &&
12198 is_const_string_range_node(arg_list_[i])
12199 )
12200 {
12201 ts.size = rp.const_size();
12202 ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
12203 range_list_[i].range = reinterpret_cast<range_t*>(0);
12204 }
12205 else
12206 range_list_[i].range = &(ri->range_ref());
12207 }
12208 #endif
12209 else if (is_variable_node(arg_list_[i]))
12210 {
12212
12213 if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
12214 return false;
12215
12216 ts.size = 1;
12217 ts.data = &var->ref();
12219 }
12220 else
12221 {
12222 ts.size = 1;
12223 ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
12225 }
12226
12227 branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
12228 }
12229
12230 return true;
12231 }
12232
12234 {
12235 return this < (&fn);
12236 }
12237
12238 inline T value() const
12239 {
12240 if (function_)
12241 {
12242 if (populate_value_list())
12243 {
12244 typedef typename GenericFunction::parameter_list_t parameter_list_t;
12245
12246 return (*function_)(parameter_list_t(typestore_list_));
12247 }
12248 }
12249
12250 return std::numeric_limits<T>::quiet_NaN();
12251 }
12252
12253 inline typename expression_node<T>::node_type type() const
12254 {
12256 }
12257
12258 protected:
12259
12260 inline virtual bool populate_value_list() const
12261 {
12262 for (std::size_t i = 0; i < branch_.size(); ++i)
12263 {
12264 expr_as_vec1_store_[i] = branch_[i].first->value();
12265 }
12266
12267 for (std::size_t i = 0; i < branch_.size(); ++i)
12268 {
12269 range_data_type_t& rdt = range_list_[i];
12270
12271 if (rdt.range)
12272 {
12273 const range_t& rp = (*rdt.range);
12274 std::size_t r0 = 0;
12275 std::size_t r1 = 0;
12276
12277 if (rp(r0, r1, rdt.size))
12278 {
12280
12281 ts.size = rp.cache_size();
12282 #ifndef exprtk_disable_string_capabilities
12283 if (ts.type == type_store_t::e_string)
12284 ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
12285 else
12286 #endif
12287 ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
12288 }
12289 else
12290 return false;
12291 }
12292 }
12293
12294 return true;
12295 }
12296
12297 GenericFunction* function_;
12299
12300 private:
12301
12302 std::vector<expression_ptr> arg_list_;
12303 std::vector<branch_t> branch_;
12304 mutable tmp_vs_t expr_as_vec1_store_;
12305 mutable range_list_t range_list_;
12306 };
12307
12308 #ifndef exprtk_disable_string_capabilities
12309 template <typename T, typename StringFunction>
12310 class string_function_node : public generic_function_node<T,StringFunction>,
12311 public string_base_node<T>,
12312 public range_interface <T>
12313 {
12314 public:
12315
12318
12319 string_function_node(StringFunction* func,
12320 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
12321 : gen_function_t(arg_list,func)
12322 {
12323 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
12324 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
12325 range_.cache.first = range_.n0_c.second;
12326 range_.cache.second = range_.n1_c.second;
12327 }
12328
12330 {
12331 return this < (&fn);
12332 }
12333
12334 inline T value() const
12335 {
12337 {
12339 {
12340 typedef typename StringFunction::parameter_list_t parameter_list_t;
12341
12342 const T result = (*gen_function_t::function_)
12343 (
12345 parameter_list_t(gen_function_t::typestore_list_)
12346 );
12347
12348 range_.n1_c.second = ret_string_.size() - 1;
12349 range_.cache.second = range_.n1_c.second;
12350
12351 return result;
12352 }
12353 }
12354
12355 return std::numeric_limits<T>::quiet_NaN();
12356 }
12357
12358 inline typename expression_node<T>::node_type type() const
12359 {
12361 }
12362
12364 {
12365 return ret_string_;
12366 }
12367
12369 {
12370 return &ret_string_[0];
12371 }
12372
12373 std::size_t size() const
12374 {
12375 return ret_string_.size();
12376 }
12377
12379 {
12380 return range_;
12381 }
12382
12383 const range_t& range_ref() const
12384 {
12385 return range_;
12386 }
12387
12388 protected:
12389
12392 };
12393 #endif
12394
12395 template <typename T, typename GenericFunction>
12396 class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
12397 {
12398 public:
12399
12402
12403 multimode_genfunction_node(GenericFunction* func,
12404 const std::size_t& param_seq_index,
12405 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
12406 : gen_function_t(arg_list,func),
12407 param_seq_index_(param_seq_index)
12408 {}
12409
12410 inline T value() const
12411 {
12413 {
12415 {
12416 typedef typename GenericFunction::parameter_list_t parameter_list_t;
12417
12419 (
12420 param_seq_index_,
12421 parameter_list_t(gen_function_t::typestore_list_)
12422 );
12423 }
12424 }
12425
12426 return std::numeric_limits<T>::quiet_NaN();
12427 }
12428
12429 inline typename expression_node<T>::node_type type() const
12430 {
12432 }
12433
12434 private:
12435
12436 std::size_t param_seq_index_;
12437 };
12438
12439 #ifndef exprtk_disable_string_capabilities
12440 template <typename T, typename StringFunction>
12441 class multimode_strfunction_node : public string_function_node<T,StringFunction>
12442 {
12443 public:
12444
12447
12448 multimode_strfunction_node(StringFunction* func,
12449 const std::size_t& param_seq_index,
12450 const std::vector<typename str_function_t::expression_ptr>& arg_list)
12451 : str_function_t(func,arg_list),
12452 param_seq_index_(param_seq_index)
12453 {}
12454
12455 inline T value() const
12456 {
12458 {
12460 {
12461 typedef typename StringFunction::parameter_list_t parameter_list_t;
12462
12463 const T result = (*str_function_t::function_)
12464 (
12465 param_seq_index_,
12467 parameter_list_t(str_function_t::typestore_list_)
12468 );
12469
12472
12473 return result;
12474 }
12475 }
12476
12477 return std::numeric_limits<T>::quiet_NaN();
12478 }
12479
12480 inline typename expression_node<T>::node_type type() const
12481 {
12483 }
12484
12485 private:
12486
12487 const std::size_t param_seq_index_;
12488 };
12489 #endif
12490
12492 {};
12493
12494 template <typename T>
12496 {
12497 public:
12498
12500 {}
12501
12504
12506 {
12507 return std::numeric_limits<T>::quiet_NaN();
12508 }
12509 };
12510
12511 #ifndef exprtk_disable_return_statement
12512 template <typename T>
12513 class return_node : public generic_function_node<T,null_igenfunc<T> >
12514 {
12515 public:
12516
12521
12522 return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
12524 : gen_function_t (arg_list),
12525 results_context_(&rc)
12526 {}
12527
12528 inline T value() const
12529 {
12530 if (
12531 (0 != results_context_) &&
12533 )
12534 {
12535 typedef typename type_store<T>::parameter_list parameter_list_t;
12536
12537 results_context_->
12538 assign(parameter_list_t(gen_function_t::typestore_list_));
12539
12540 throw return_exception();
12541 }
12542
12543 return std::numeric_limits<T>::quiet_NaN();
12544 }
12545
12546 inline typename expression_node<T>::node_type type() const
12547 {
12549 }
12550
12551 private:
12552
12553 results_context_t* results_context_;
12554 };
12555
12556 template <typename T>
12558 {
12559 public:
12560
12563 typedef std::pair<expression_ptr,bool> branch_t;
12564
12566 : results_context_(&rc ),
12567 return_invoked_ (false)
12568 {
12569 construct_branch_pair(body_, body);
12570 }
12571
12572 inline T value() const
12573 {
12574 assert(body_.first);
12575
12576 try
12577 {
12578 return_invoked_ = false;
12579 results_context_->clear();
12580
12581 return body_.first->value();
12582 }
12583 catch(const return_exception&)
12584 {
12585 return_invoked_ = true;
12586 return std::numeric_limits<T>::quiet_NaN();
12587 }
12588 }
12589
12590 inline typename expression_node<T>::node_type type() const
12591 {
12593 }
12594
12595 inline bool* retinvk_ptr()
12596 {
12597 return &return_invoked_;
12598 }
12599
12600 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12601 {
12602 expression_node<T>::ndb_t::collect(body_, node_delete_list);
12603 }
12604
12605 std::size_t node_depth() const
12606 {
12608 }
12609
12610 private:
12611
12612 results_context_t* results_context_;
12613 mutable bool return_invoked_;
12614 branch_t body_;
12615 };
12616 #endif
12617
12618 #define exprtk_define_unary_op(OpName) \
12619 template <typename T> \
12620 struct OpName##_op \
12621 { \
12622 typedef typename functor_t<T>::Type Type; \
12623 typedef typename expression_node<T>::node_type node_t; \
12624 \
12625 static inline T process(Type v) \
12626 { \
12627 return numeric:: OpName (v); \
12628 } \
12629 \
12630 static inline node_t type() \
12631 { \
12632 return expression_node<T>::e_##OpName; \
12633 } \
12634 \
12635 static inline details::operator_type operation() \
12636 { \
12637 return details::e_##OpName; \
12638 } \
12639 }; \
12640
12681 #undef exprtk_define_unary_op
12682
12683 template <typename T>
12684 struct opr_base
12685 {
12686 typedef typename details::functor_t<T>::Type Type;
12687 typedef typename details::functor_t<T>::RefType RefType;
12688 typedef typename details::functor_t<T> functor_t;
12689 typedef typename functor_t::qfunc_t quaternary_functor_t;
12690 typedef typename functor_t::tfunc_t trinary_functor_t;
12691 typedef typename functor_t::bfunc_t binary_functor_t;
12692 typedef typename functor_t::ufunc_t unary_functor_t;
12693 };
12694
12695 template <typename T>
12696 struct add_op : public opr_base<T>
12697 {
12698 typedef typename opr_base<T>::Type Type;
12699 typedef typename opr_base<T>::RefType RefType;
12700
12701 static inline T process(Type t1, Type t2) { return t1 + t2; }
12702 static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
12703 static inline void assign(RefType t1, Type t2) { t1 += t2; }
12706 };
12707
12708 template <typename T>
12709 struct mul_op : public opr_base<T>
12710 {
12711 typedef typename opr_base<T>::Type Type;
12712 typedef typename opr_base<T>::RefType RefType;
12713
12714 static inline T process(Type t1, Type t2) { return t1 * t2; }
12715 static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
12716 static inline void assign(RefType t1, Type t2) { t1 *= t2; }
12719 };
12720
12721 template <typename T>
12722 struct sub_op : public opr_base<T>
12723 {
12724 typedef typename opr_base<T>::Type Type;
12725 typedef typename opr_base<T>::RefType RefType;
12726
12727 static inline T process(Type t1, Type t2) { return t1 - t2; }
12728 static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
12729 static inline void assign(RefType t1, Type t2) { t1 -= t2; }
12732 };
12733
12734 template <typename T>
12735 struct div_op : public opr_base<T>
12736 {
12737 typedef typename opr_base<T>::Type Type;
12738 typedef typename opr_base<T>::RefType RefType;
12739
12740 static inline T process(Type t1, Type t2) { return t1 / t2; }
12741 static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
12742 static inline void assign(RefType t1, Type t2) { t1 /= t2; }
12745 };
12746
12747 template <typename T>
12748 struct mod_op : public opr_base<T>
12749 {
12750 typedef typename opr_base<T>::Type Type;
12751 typedef typename opr_base<T>::RefType RefType;
12752
12753 static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
12754 static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
12757 };
12758
12759 template <typename T>
12760 struct pow_op : public opr_base<T>
12761 {
12762 typedef typename opr_base<T>::Type Type;
12763 typedef typename opr_base<T>::RefType RefType;
12764
12765 static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
12766 static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
12769 };
12770
12771 template <typename T>
12772 struct lt_op : public opr_base<T>
12773 {
12774 typedef typename opr_base<T>::Type Type;
12775
12776 static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
12777 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
12780 };
12781
12782 template <typename T>
12783 struct lte_op : public opr_base<T>
12784 {
12785 typedef typename opr_base<T>::Type Type;
12786
12787 static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12788 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12791 };
12792
12793 template <typename T>
12794 struct gt_op : public opr_base<T>
12795 {
12796 typedef typename opr_base<T>::Type Type;
12797
12798 static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
12799 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
12802 };
12803
12804 template <typename T>
12805 struct gte_op : public opr_base<T>
12806 {
12807 typedef typename opr_base<T>::Type Type;
12808
12809 static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12810 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12813 };
12814
12815 template <typename T>
12816 struct eq_op : public opr_base<T>
12817 {
12818 typedef typename opr_base<T>::Type Type;
12819 static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12820 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12823 };
12824
12825 template <typename T>
12826 struct equal_op : public opr_base<T>
12827 {
12828 typedef typename opr_base<T>::Type Type;
12829
12830 static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
12831 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12834 };
12835
12836 template <typename T>
12837 struct ne_op : public opr_base<T>
12838 {
12839 typedef typename opr_base<T>::Type Type;
12840
12841 static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12842 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
12845 };
12846
12847 template <typename T>
12848 struct and_op : public opr_base<T>
12849 {
12850 typedef typename opr_base<T>::Type Type;
12851
12852 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
12855 };
12856
12857 template <typename T>
12858 struct nand_op : public opr_base<T>
12859 {
12860 typedef typename opr_base<T>::Type Type;
12861
12862 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
12865 };
12866
12867 template <typename T>
12868 struct or_op : public opr_base<T>
12869 {
12870 typedef typename opr_base<T>::Type Type;
12871
12872 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
12875 };
12876
12877 template <typename T>
12878 struct nor_op : public opr_base<T>
12879 {
12880 typedef typename opr_base<T>::Type Type;
12881
12882 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
12885 };
12886
12887 template <typename T>
12888 struct xor_op : public opr_base<T>
12889 {
12890 typedef typename opr_base<T>::Type Type;
12891
12892 static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
12895 };
12896
12897 template <typename T>
12898 struct xnor_op : public opr_base<T>
12899 {
12900 typedef typename opr_base<T>::Type Type;
12901
12902 static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
12905 };
12906
12907 template <typename T>
12908 struct in_op : public opr_base<T>
12909 {
12910 typedef typename opr_base<T>::Type Type;
12911
12912 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12913 static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
12916 };
12917
12918 template <typename T>
12919 struct like_op : public opr_base<T>
12920 {
12921 typedef typename opr_base<T>::Type Type;
12922
12923 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12924 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
12927 };
12928
12929 template <typename T>
12930 struct ilike_op : public opr_base<T>
12931 {
12932 typedef typename opr_base<T>::Type Type;
12933
12934 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12935 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
12938 };
12939
12940 template <typename T>
12941 struct inrange_op : public opr_base<T>
12942 {
12943 typedef typename opr_base<T>::Type Type;
12944
12945 static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
12946 static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12947 {
12948 return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12949 }
12952 };
12953
12954 template <typename T>
12956 {
12957 return n->value();
12958 }
12959
12960 template <typename T>
12961 inline T value(std::pair<details::expression_node<T>*,bool> n)
12962 {
12963 return n.first->value();
12964 }
12965
12966 template <typename T>
12967 inline T value(const T* t)
12968 {
12969 return (*t);
12970 }
12971
12972 template <typename T>
12973 inline T value(const T& t)
12974 {
12975 return t;
12976 }
12977
12978 template <typename T>
12979 struct vararg_add_op : public opr_base<T>
12980 {
12981 typedef typename opr_base<T>::Type Type;
12982
12983 template <typename Type,
12984 typename Allocator,
12985 template <typename, typename> class Sequence>
12986 static inline T process(const Sequence<Type,Allocator>& arg_list)
12987 {
12988 switch (arg_list.size())
12989 {
12990 case 0 : return T(0);
12991 case 1 : return process_1(arg_list);
12992 case 2 : return process_2(arg_list);
12993 case 3 : return process_3(arg_list);
12994 case 4 : return process_4(arg_list);
12995 case 5 : return process_5(arg_list);
12996 default :
12997 {
12998 T result = T(0);
12999
13000 for (std::size_t i = 0; i < arg_list.size(); ++i)
13001 {
13002 result += value(arg_list[i]);
13003 }
13004
13005 return result;
13006 }
13007 }
13008 }
13009
13010 template <typename Sequence>
13011 static inline T process_1(const Sequence& arg_list)
13012 {
13013 return value(arg_list[0]);
13014 }
13015
13016 template <typename Sequence>
13017 static inline T process_2(const Sequence& arg_list)
13018 {
13019 return value(arg_list[0]) + value(arg_list[1]);
13020 }
13021
13022 template <typename Sequence>
13023 static inline T process_3(const Sequence& arg_list)
13024 {
13025 return value(arg_list[0]) + value(arg_list[1]) +
13026 value(arg_list[2]) ;
13027 }
13028
13029 template <typename Sequence>
13030 static inline T process_4(const Sequence& arg_list)
13031 {
13032 return value(arg_list[0]) + value(arg_list[1]) +
13033 value(arg_list[2]) + value(arg_list[3]) ;
13034 }
13035
13036 template <typename Sequence>
13037 static inline T process_5(const Sequence& arg_list)
13038 {
13039 return value(arg_list[0]) + value(arg_list[1]) +
13040 value(arg_list[2]) + value(arg_list[3]) +
13041 value(arg_list[4]) ;
13042 }
13043 };
13044
13045 template <typename T>
13046 struct vararg_mul_op : public opr_base<T>
13047 {
13048 typedef typename opr_base<T>::Type Type;
13049
13050 template <typename Type,
13051 typename Allocator,
13052 template <typename, typename> class Sequence>
13053 static inline T process(const Sequence<Type,Allocator>& arg_list)
13054 {
13055 switch (arg_list.size())
13056 {
13057 case 0 : return T(0);
13058 case 1 : return process_1(arg_list);
13059 case 2 : return process_2(arg_list);
13060 case 3 : return process_3(arg_list);
13061 case 4 : return process_4(arg_list);
13062 case 5 : return process_5(arg_list);
13063 default :
13064 {
13065 T result = T(value(arg_list[0]));
13066
13067 for (std::size_t i = 1; i < arg_list.size(); ++i)
13068 {
13069 result *= value(arg_list[i]);
13070 }
13071
13072 return result;
13073 }
13074 }
13075 }
13076
13077 template <typename Sequence>
13078 static inline T process_1(const Sequence& arg_list)
13079 {
13080 return value(arg_list[0]);
13081 }
13082
13083 template <typename Sequence>
13084 static inline T process_2(const Sequence& arg_list)
13085 {
13086 return value(arg_list[0]) * value(arg_list[1]);
13087 }
13088
13089 template <typename Sequence>
13090 static inline T process_3(const Sequence& arg_list)
13091 {
13092 return value(arg_list[0]) * value(arg_list[1]) *
13093 value(arg_list[2]) ;
13094 }
13095
13096 template <typename Sequence>
13097 static inline T process_4(const Sequence& arg_list)
13098 {
13099 return value(arg_list[0]) * value(arg_list[1]) *
13100 value(arg_list[2]) * value(arg_list[3]) ;
13101 }
13102
13103 template <typename Sequence>
13104 static inline T process_5(const Sequence& arg_list)
13105 {
13106 return value(arg_list[0]) * value(arg_list[1]) *
13107 value(arg_list[2]) * value(arg_list[3]) *
13108 value(arg_list[4]) ;
13109 }
13110 };
13111
13112 template <typename T>
13113 struct vararg_avg_op : public opr_base<T>
13114 {
13115 typedef typename opr_base<T>::Type Type;
13116
13117 template <typename Type,
13118 typename Allocator,
13119 template <typename, typename> class Sequence>
13120 static inline T process(const Sequence<Type,Allocator>& arg_list)
13121 {
13122 switch (arg_list.size())
13123 {
13124 case 0 : return T(0);
13125 case 1 : return process_1(arg_list);
13126 case 2 : return process_2(arg_list);
13127 case 3 : return process_3(arg_list);
13128 case 4 : return process_4(arg_list);
13129 case 5 : return process_5(arg_list);
13130 default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
13131 }
13132 }
13133
13134 template <typename Sequence>
13135 static inline T process_1(const Sequence& arg_list)
13136 {
13137 return value(arg_list[0]);
13138 }
13139
13140 template <typename Sequence>
13141 static inline T process_2(const Sequence& arg_list)
13142 {
13143 return (value(arg_list[0]) + value(arg_list[1])) / T(2);
13144 }
13145
13146 template <typename Sequence>
13147 static inline T process_3(const Sequence& arg_list)
13148 {
13149 return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
13150 }
13151
13152 template <typename Sequence>
13153 static inline T process_4(const Sequence& arg_list)
13154 {
13155 return (value(arg_list[0]) + value(arg_list[1]) +
13156 value(arg_list[2]) + value(arg_list[3])) / T(4);
13157 }
13158
13159 template <typename Sequence>
13160 static inline T process_5(const Sequence& arg_list)
13161 {
13162 return (value(arg_list[0]) + value(arg_list[1]) +
13163 value(arg_list[2]) + value(arg_list[3]) +
13164 value(arg_list[4])) / T(5);
13165 }
13166 };
13167
13168 template <typename T>
13169 struct vararg_min_op : public opr_base<T>
13170 {
13171 typedef typename opr_base<T>::Type Type;
13172
13173 template <typename Type,
13174 typename Allocator,
13175 template <typename, typename> class Sequence>
13176 static inline T process(const Sequence<Type,Allocator>& arg_list)
13177 {
13178 switch (arg_list.size())
13179 {
13180 case 0 : return T(0);
13181 case 1 : return process_1(arg_list);
13182 case 2 : return process_2(arg_list);
13183 case 3 : return process_3(arg_list);
13184 case 4 : return process_4(arg_list);
13185 case 5 : return process_5(arg_list);
13186 default :
13187 {
13188 T result = T(value(arg_list[0]));
13189
13190 for (std::size_t i = 1; i < arg_list.size(); ++i)
13191 {
13192 const T v = value(arg_list[i]);
13193
13194 if (v < result)
13195 result = v;
13196 }
13197
13198 return result;
13199 }
13200 }
13201 }
13202
13203 template <typename Sequence>
13204 static inline T process_1(const Sequence& arg_list)
13205 {
13206 return value(arg_list[0]);
13207 }
13208
13209 template <typename Sequence>
13210 static inline T process_2(const Sequence& arg_list)
13211 {
13212 return std::min<T>(value(arg_list[0]),value(arg_list[1]));
13213 }
13214
13215 template <typename Sequence>
13216 static inline T process_3(const Sequence& arg_list)
13217 {
13218 return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
13219 }
13220
13221 template <typename Sequence>
13222 static inline T process_4(const Sequence& arg_list)
13223 {
13224 return std::min<T>(
13225 std::min<T>(value(arg_list[0]), value(arg_list[1])),
13226 std::min<T>(value(arg_list[2]), value(arg_list[3])));
13227 }
13228
13229 template <typename Sequence>
13230 static inline T process_5(const Sequence& arg_list)
13231 {
13232 return std::min<T>(
13233 std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
13234 std::min<T>(value(arg_list[2]), value(arg_list[3]))),
13235 value(arg_list[4]));
13236 }
13237 };
13238
13239 template <typename T>
13240 struct vararg_max_op : public opr_base<T>
13241 {
13242 typedef typename opr_base<T>::Type Type;
13243
13244 template <typename Type,
13245 typename Allocator,
13246 template <typename, typename> class Sequence>
13247 static inline T process(const Sequence<Type,Allocator>& arg_list)
13248 {
13249 switch (arg_list.size())
13250 {
13251 case 0 : return T(0);
13252 case 1 : return process_1(arg_list);
13253 case 2 : return process_2(arg_list);
13254 case 3 : return process_3(arg_list);
13255 case 4 : return process_4(arg_list);
13256 case 5 : return process_5(arg_list);
13257 default :
13258 {
13259 T result = T(value(arg_list[0]));
13260
13261 for (std::size_t i = 1; i < arg_list.size(); ++i)
13262 {
13263 const T v = value(arg_list[i]);
13264
13265 if (v > result)
13266 result = v;
13267 }
13268
13269 return result;
13270 }
13271 }
13272 }
13273
13274 template <typename Sequence>
13275 static inline T process_1(const Sequence& arg_list)
13276 {
13277 return value(arg_list[0]);
13278 }
13279
13280 template <typename Sequence>
13281 static inline T process_2(const Sequence& arg_list)
13282 {
13283 return std::max<T>(value(arg_list[0]),value(arg_list[1]));
13284 }
13285
13286 template <typename Sequence>
13287 static inline T process_3(const Sequence& arg_list)
13288 {
13289 return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
13290 }
13291
13292 template <typename Sequence>
13293 static inline T process_4(const Sequence& arg_list)
13294 {
13295 return std::max<T>(
13296 std::max<T>(value(arg_list[0]), value(arg_list[1])),
13297 std::max<T>(value(arg_list[2]), value(arg_list[3])));
13298 }
13299
13300 template <typename Sequence>
13301 static inline T process_5(const Sequence& arg_list)
13302 {
13303 return std::max<T>(
13304 std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
13305 std::max<T>(value(arg_list[2]), value(arg_list[3]))),
13306 value(arg_list[4]));
13307 }
13308 };
13309
13310 template <typename T>
13311 struct vararg_mand_op : public opr_base<T>
13312 {
13313 typedef typename opr_base<T>::Type Type;
13314
13315 template <typename Type,
13316 typename Allocator,
13317 template <typename, typename> class Sequence>
13318 static inline T process(const Sequence<Type,Allocator>& arg_list)
13319 {
13320 switch (arg_list.size())
13321 {
13322 case 1 : return process_1(arg_list);
13323 case 2 : return process_2(arg_list);
13324 case 3 : return process_3(arg_list);
13325 case 4 : return process_4(arg_list);
13326 case 5 : return process_5(arg_list);
13327 default :
13328 {
13329 for (std::size_t i = 0; i < arg_list.size(); ++i)
13330 {
13331 if (std::equal_to<T>()(T(0), value(arg_list[i])))
13332 return T(0);
13333 }
13334
13335 return T(1);
13336 }
13337 }
13338 }
13339
13340 template <typename Sequence>
13341 static inline T process_1(const Sequence& arg_list)
13342 {
13343 return std::not_equal_to<T>()
13344 (T(0), value(arg_list[0])) ? T(1) : T(0);
13345 }
13346
13347 template <typename Sequence>
13348 static inline T process_2(const Sequence& arg_list)
13349 {
13350 return (
13351 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13352 std::not_equal_to<T>()(T(0), value(arg_list[1]))
13353 ) ? T(1) : T(0);
13354 }
13355
13356 template <typename Sequence>
13357 static inline T process_3(const Sequence& arg_list)
13358 {
13359 return (
13360 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13361 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13362 std::not_equal_to<T>()(T(0), value(arg_list[2]))
13363 ) ? T(1) : T(0);
13364 }
13365
13366 template <typename Sequence>
13367 static inline T process_4(const Sequence& arg_list)
13368 {
13369 return (
13370 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13371 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13372 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
13373 std::not_equal_to<T>()(T(0), value(arg_list[3]))
13374 ) ? T(1) : T(0);
13375 }
13376
13377 template <typename Sequence>
13378 static inline T process_5(const Sequence& arg_list)
13379 {
13380 return (
13381 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13382 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13383 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
13384 std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
13385 std::not_equal_to<T>()(T(0), value(arg_list[4]))
13386 ) ? T(1) : T(0);
13387 }
13388 };
13389
13390 template <typename T>
13391 struct vararg_mor_op : public opr_base<T>
13392 {
13393 typedef typename opr_base<T>::Type Type;
13394
13395 template <typename Type,
13396 typename Allocator,
13397 template <typename, typename> class Sequence>
13398 static inline T process(const Sequence<Type,Allocator>& arg_list)
13399 {
13400 switch (arg_list.size())
13401 {
13402 case 1 : return process_1(arg_list);
13403 case 2 : return process_2(arg_list);
13404 case 3 : return process_3(arg_list);
13405 case 4 : return process_4(arg_list);
13406 case 5 : return process_5(arg_list);
13407 default :
13408 {
13409 for (std::size_t i = 0; i < arg_list.size(); ++i)
13410 {
13411 if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
13412 return T(1);
13413 }
13414
13415 return T(0);
13416 }
13417 }
13418 }
13419
13420 template <typename Sequence>
13421 static inline T process_1(const Sequence& arg_list)
13422 {
13423 return std::not_equal_to<T>()
13424 (T(0), value(arg_list[0])) ? T(1) : T(0);
13425 }
13426
13427 template <typename Sequence>
13428 static inline T process_2(const Sequence& arg_list)
13429 {
13430 return (
13431 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13432 std::not_equal_to<T>()(T(0), value(arg_list[1]))
13433 ) ? T(1) : T(0);
13434 }
13435
13436 template <typename Sequence>
13437 static inline T process_3(const Sequence& arg_list)
13438 {
13439 return (
13440 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13441 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13442 std::not_equal_to<T>()(T(0), value(arg_list[2]))
13443 ) ? T(1) : T(0);
13444 }
13445
13446 template <typename Sequence>
13447 static inline T process_4(const Sequence& arg_list)
13448 {
13449 return (
13450 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13451 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13452 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
13453 std::not_equal_to<T>()(T(0), value(arg_list[3]))
13454 ) ? T(1) : T(0);
13455 }
13456
13457 template <typename Sequence>
13458 static inline T process_5(const Sequence& arg_list)
13459 {
13460 return (
13461 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13462 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13463 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
13464 std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
13465 std::not_equal_to<T>()(T(0), value(arg_list[4]))
13466 ) ? T(1) : T(0);
13467 }
13468 };
13469
13470 template <typename T>
13471 struct vararg_multi_op : public opr_base<T>
13472 {
13473 typedef typename opr_base<T>::Type Type;
13474
13475 template <typename Type,
13476 typename Allocator,
13477 template <typename, typename> class Sequence>
13478 static inline T process(const Sequence<Type,Allocator>& arg_list)
13479 {
13480 switch (arg_list.size())
13481 {
13482 case 0 : return std::numeric_limits<T>::quiet_NaN();
13483 case 1 : return process_1(arg_list);
13484 case 2 : return process_2(arg_list);
13485 case 3 : return process_3(arg_list);
13486 case 4 : return process_4(arg_list);
13487 case 5 : return process_5(arg_list);
13488 case 6 : return process_6(arg_list);
13489 case 7 : return process_7(arg_list);
13490 case 8 : return process_8(arg_list);
13491 default :
13492 {
13493 for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
13494 {
13495 value(arg_list[i]);
13496 }
13497
13498 return value(arg_list.back());
13499 }
13500 }
13501 }
13502
13503 template <typename Sequence>
13504 static inline T process_1(const Sequence& arg_list)
13505 {
13506 return value(arg_list[0]);
13507 }
13508
13509 template <typename Sequence>
13510 static inline T process_2(const Sequence& arg_list)
13511 {
13512 value(arg_list[0]);
13513 return value(arg_list[1]);
13514 }
13515
13516 template <typename Sequence>
13517 static inline T process_3(const Sequence& arg_list)
13518 {
13519 value(arg_list[0]);
13520 value(arg_list[1]);
13521 return value(arg_list[2]);
13522 }
13523
13524 template <typename Sequence>
13525 static inline T process_4(const Sequence& arg_list)
13526 {
13527 value(arg_list[0]);
13528 value(arg_list[1]);
13529 value(arg_list[2]);
13530 return value(arg_list[3]);
13531 }
13532
13533 template <typename Sequence>
13534 static inline T process_5(const Sequence& arg_list)
13535 {
13536 value(arg_list[0]);
13537 value(arg_list[1]);
13538 value(arg_list[2]);
13539 value(arg_list[3]);
13540 return value(arg_list[4]);
13541 }
13542
13543 template <typename Sequence>
13544 static inline T process_6(const Sequence& arg_list)
13545 {
13546 value(arg_list[0]);
13547 value(arg_list[1]);
13548 value(arg_list[2]);
13549 value(arg_list[3]);
13550 value(arg_list[4]);
13551 return value(arg_list[5]);
13552 }
13553
13554 template <typename Sequence>
13555 static inline T process_7(const Sequence& arg_list)
13556 {
13557 value(arg_list[0]);
13558 value(arg_list[1]);
13559 value(arg_list[2]);
13560 value(arg_list[3]);
13561 value(arg_list[4]);
13562 value(arg_list[5]);
13563 return value(arg_list[6]);
13564 }
13565
13566 template <typename Sequence>
13567 static inline T process_8(const Sequence& arg_list)
13568 {
13569 value(arg_list[0]);
13570 value(arg_list[1]);
13571 value(arg_list[2]);
13572 value(arg_list[3]);
13573 value(arg_list[4]);
13574 value(arg_list[5]);
13575 value(arg_list[6]);
13576 return value(arg_list[7]);
13577 }
13578 };
13579
13580 template <typename T>
13582 {
13584
13585 static inline T process(const ivector_ptr v)
13586 {
13587 const T* vec = v->vec()->vds().data();
13588 const std::size_t vec_size = v->vec()->vds().size();
13589
13590 loop_unroll::details lud(vec_size);
13591
13592 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13593 {
13594 T result = T(0);
13595 int i = 0;
13596
13598 switch (vec_size)
13599 {
13600 #define case_stmt(N) \
13601 case N : result += vec[i++]; \
13602
13603 #ifndef exprtk_disable_superscalar_unroll
13604 case_stmt(16) case_stmt(15)
13605 case_stmt(14) case_stmt(13)
13606 case_stmt(12) case_stmt(11)
13607 case_stmt(10) case_stmt( 9)
13608 case_stmt( 8) case_stmt( 7)
13609 case_stmt( 6) case_stmt( 5)
13610 #endif
13611 case_stmt( 4) case_stmt( 3)
13612 case_stmt( 2) case_stmt( 1)
13613 }
13615
13616 #undef case_stmt
13617
13618 return result;
13619 }
13620
13621 T r[] = {
13622 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
13623 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
13624 };
13625
13626 const T* upper_bound = vec + lud.upper_bound;
13627
13628 while (vec < upper_bound)
13629 {
13630 #define exprtk_loop(N) \
13631 r[N] += vec[N]; \
13632
13633 exprtk_loop( 0) exprtk_loop( 1)
13634 exprtk_loop( 2) exprtk_loop( 3)
13635 #ifndef exprtk_disable_superscalar_unroll
13636 exprtk_loop( 4) exprtk_loop( 5)
13637 exprtk_loop( 6) exprtk_loop( 7)
13638 exprtk_loop( 8) exprtk_loop( 9)
13639 exprtk_loop(10) exprtk_loop(11)
13640 exprtk_loop(12) exprtk_loop(13)
13641 exprtk_loop(14) exprtk_loop(15)
13642 #endif
13643
13644 vec += lud.batch_size;
13645 }
13646
13647 int i = 0;
13648
13650 switch (lud.remainder)
13651 {
13652 #define case_stmt(N) \
13653 case N : r[0] += vec[i++]; \
13654
13655 #ifndef exprtk_disable_superscalar_unroll
13656 case_stmt(15) case_stmt(14)
13657 case_stmt(13) case_stmt(12)
13658 case_stmt(11) case_stmt(10)
13659 case_stmt( 9) case_stmt( 8)
13660 case_stmt( 7) case_stmt( 6)
13661 case_stmt( 5) case_stmt( 4)
13662 #endif
13663 case_stmt( 3) case_stmt( 2)
13664 case_stmt( 1)
13665 }
13667
13668 #undef exprtk_loop
13669 #undef case_stmt
13670
13671 return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13672 #ifndef exprtk_disable_superscalar_unroll
13673 + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13674 + (r[ 8] + r[ 9] + r[10] + r[11])
13675 + (r[12] + r[13] + r[14] + r[15])
13676 #endif
13677 ;
13678 }
13679 };
13680
13681 template <typename T>
13683 {
13685
13686 static inline T process(const ivector_ptr v)
13687 {
13688 const T* vec = v->vec()->vds().data();
13689 const std::size_t vec_size = v->vec()->vds().size();
13690
13691 loop_unroll::details lud(vec_size);
13692
13693 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13694 {
13695 T result = T(1);
13696 int i = 0;
13697
13699 switch (vec_size)
13700 {
13701 #define case_stmt(N) \
13702 case N : result *= vec[i++]; \
13703
13704 #ifndef exprtk_disable_superscalar_unroll
13705 case_stmt(16) case_stmt(15)
13706 case_stmt(14) case_stmt(13)
13707 case_stmt(12) case_stmt(11)
13708 case_stmt(10) case_stmt( 9)
13709 case_stmt( 8) case_stmt( 7)
13710 case_stmt( 6) case_stmt( 5)
13711 #endif
13712 case_stmt( 4) case_stmt( 3)
13713 case_stmt( 2) case_stmt( 1)
13714 }
13716
13717 #undef case_stmt
13718
13719 return result;
13720 }
13721
13722 T r[] = {
13723 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13724 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13725 };
13726
13727 const T* upper_bound = vec + lud.upper_bound;
13728
13729 while (vec < upper_bound)
13730 {
13731 #define exprtk_loop(N) \
13732 r[N] *= vec[N]; \
13733
13734 exprtk_loop( 0) exprtk_loop( 1)
13735 exprtk_loop( 2) exprtk_loop( 3)
13736 #ifndef exprtk_disable_superscalar_unroll
13737 exprtk_loop( 4) exprtk_loop( 5)
13738 exprtk_loop( 6) exprtk_loop( 7)
13739 exprtk_loop( 8) exprtk_loop( 9)
13740 exprtk_loop(10) exprtk_loop(11)
13741 exprtk_loop(12) exprtk_loop(13)
13742 exprtk_loop(14) exprtk_loop(15)
13743 #endif
13744
13745 vec += lud.batch_size;
13746 }
13747
13748 int i = 0;
13749
13751 switch (lud.remainder)
13752 {
13753 #define case_stmt(N) \
13754 case N : r[0] *= vec[i++]; \
13755
13756 #ifndef exprtk_disable_superscalar_unroll
13757 case_stmt(15) case_stmt(14)
13758 case_stmt(13) case_stmt(12)
13759 case_stmt(11) case_stmt(10)
13760 case_stmt( 9) case_stmt( 8)
13761 case_stmt( 7) case_stmt( 6)
13762 case_stmt( 5) case_stmt( 4)
13763 #endif
13764 case_stmt( 3) case_stmt( 2)
13765 case_stmt( 1)
13766 }
13768
13769 #undef exprtk_loop
13770 #undef case_stmt
13771
13772 return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13773 #ifndef exprtk_disable_superscalar_unroll
13774 + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13775 + (r[ 8] * r[ 9] * r[10] * r[11])
13776 + (r[12] * r[13] * r[14] * r[15])
13777 #endif
13778 ;
13779 }
13780 };
13781
13782 template <typename T>
13784 {
13786
13787 static inline T process(const ivector_ptr v)
13788 {
13789 const std::size_t vec_size = v->vec()->vds().size();
13790
13791 return vec_add_op<T>::process(v) / vec_size;
13792 }
13793 };
13794
13795 template <typename T>
13797 {
13799
13800 static inline T process(const ivector_ptr v)
13801 {
13802 const T* vec = v->vec()->vds().data();
13803 const std::size_t vec_size = v->vec()->vds().size();
13804
13805 T result = vec[0];
13806
13807 for (std::size_t i = 1; i < vec_size; ++i)
13808 {
13809 const T v_i = vec[i];
13810
13811 if (v_i < result)
13812 result = v_i;
13813 }
13814
13815 return result;
13816 }
13817 };
13818
13819 template <typename T>
13821 {
13823
13824 static inline T process(const ivector_ptr v)
13825 {
13826 const T* vec = v->vec()->vds().data();
13827 const std::size_t vec_size = v->vec()->vds().size();
13828
13829 T result = vec[0];
13830
13831 for (std::size_t i = 1; i < vec_size; ++i)
13832 {
13833 const T v_i = vec[i];
13834
13835 if (v_i > result)
13836 result = v_i;
13837 }
13838
13839 return result;
13840 }
13841 };
13842
13843 template <typename T>
13845 {
13846 public:
13847
13849 {}
13850
13851 inline virtual operator_type operation() const
13852 {
13853 return details::e_default;
13854 }
13855
13856 virtual const T& v0() const = 0;
13857
13858 virtual const T& v1() const = 0;
13859 };
13860
13861 template <typename T>
13863 {
13864 public:
13865
13867 {}
13868
13869 inline virtual operator_type operation() const
13870 {
13871 return details::e_default;
13872 }
13873
13874 virtual const T c() const = 0;
13875
13876 virtual const T& v() const = 0;
13877 };
13878
13879 template <typename T>
13881 {
13882 public:
13883
13885 {}
13886
13887 inline virtual operator_type operation() const
13888 {
13889 return details::e_default;
13890 }
13891
13892 virtual const T c() const = 0;
13893
13894 virtual const T& v() const = 0;
13895 };
13896
13897 template <typename T>
13899 {
13900 public:
13901
13903 {}
13904
13905 virtual const T& v() const = 0;
13906 };
13907
13908 template <typename T>
13910 {
13911 public:
13912
13914 {}
13915
13916 virtual const T& v() const = 0;
13917 };
13918
13919 template <typename T>
13921 {
13922 public:
13923
13925 {}
13926
13927 inline virtual operator_type operation() const
13928 {
13929 return details::e_default;
13930 }
13931
13932 virtual const T c() const = 0;
13933
13934 virtual void set_c(const T) = 0;
13935
13936 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13937 };
13938
13939 template <typename T>
13941 {
13942 public:
13943
13945 {}
13946
13947 inline virtual operator_type operation() const
13948 {
13949 return details::e_default;
13950 }
13951
13952 virtual const T c() const = 0;
13953
13954 virtual void set_c(const T) = 0;
13955
13956 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13957 };
13958
13959 template <typename T>
13961 {
13962 public:
13963
13965 {}
13966
13967 inline virtual operator_type operation() const
13968 {
13969 return details::e_default;
13970 }
13971
13972 virtual const T& v() const = 0;
13973 };
13974
13975 template <typename T>
13977 {
13978 public:
13979
13981 {}
13982
13983 inline virtual operator_type operation() const
13984 {
13985 return details::e_default;
13986 }
13987 };
13988
13989 template <typename T>
13991 {
13992 public:
13993
13995 {}
13996
13997 inline virtual operator_type operation() const
13998 {
13999 return details::e_default;
14000 }
14001 };
14002
14003 template <typename T>
14005 {
14006 public:
14007
14009 {}
14010
14011 virtual std::string type_id() const = 0;
14012 };
14013
14014 template <typename T>
14016 {
14017 public:
14018
14020 {}
14021
14022 virtual std::string type_id() const = 0;
14023 };
14024
14025 template <typename T, typename Operation>
14027 {
14028 public:
14029
14031 typedef Operation operation_t;
14032
14033 explicit unary_variable_node(const T& var)
14034 : v_(var)
14035 {}
14036
14037 inline T value() const
14038 {
14039 return Operation::process(v_);
14040 }
14041
14042 inline typename expression_node<T>::node_type type() const
14043 {
14044 return Operation::type();
14045 }
14046
14048 {
14049 return Operation::operation();
14050 }
14051
14052 inline const T& v() const
14053 {
14054 return v_;
14055 }
14056
14057 private:
14058
14061
14062 const T& v_;
14063 };
14064
14065 template <typename T>
14066 class uvouv_node : public expression_node<T>
14067 {
14068 public:
14069
14070 // UOpr1(v0) Op UOpr2(v1)
14071
14074 typedef typename functor_t::bfunc_t bfunc_t;
14075 typedef typename functor_t::ufunc_t ufunc_t;
14076
14077 explicit uvouv_node(const T& var0,const T& var1,
14078 ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
14079 : v0_(var0),
14080 v1_(var1),
14081 u0_(uf0 ),
14082 u1_(uf1 ),
14083 f_ (bf )
14084 {}
14085
14086 inline T value() const
14087 {
14088 return f_(u0_(v0_),u1_(v1_));
14089 }
14090
14091 inline typename expression_node<T>::node_type type() const
14092 {
14094 }
14095
14097 {
14098 return details::e_default;
14099 }
14100
14101 inline const T& v0()
14102 {
14103 return v0_;
14104 }
14105
14106 inline const T& v1()
14107 {
14108 return v1_;
14109 }
14110
14111 inline ufunc_t u0()
14112 {
14113 return u0_;
14114 }
14115
14116 inline ufunc_t u1()
14117 {
14118 return u1_;
14119 }
14120
14121 inline ufunc_t f()
14122 {
14123 return f_;
14124 }
14125
14126 private:
14127
14129 uvouv_node<T>& operator=(uvouv_node<T>&);
14130
14131 const T& v0_;
14132 const T& v1_;
14133 const ufunc_t u0_;
14134 const ufunc_t u1_;
14135 const bfunc_t f_;
14136 };
14137
14138 template <typename T, typename Operation>
14140 {
14141 public:
14142
14144 typedef std::pair<expression_ptr,bool> branch_t;
14145 typedef Operation operation_t;
14146
14148 {
14149 construct_branch_pair(branch_, branch);
14150 }
14151
14152 inline T value() const
14153 {
14154 return Operation::process(branch_.first->value());
14155 }
14156
14157 inline typename expression_node<T>::node_type type() const
14158 {
14159 return Operation::type();
14160 }
14161
14163 {
14164 return Operation::operation();
14165 }
14166
14167 inline expression_node<T>* branch(const std::size_t&) const
14168 {
14169 return branch_.first;
14170 }
14171
14172 inline void release()
14173 {
14174 branch_.second = false;
14175 }
14176
14177 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
14178 {
14179 expression_node<T>::ndb_t::collect(branch_, node_delete_list);
14180 }
14181
14182 std::size_t node_depth() const
14183 {
14185 }
14186
14187 private:
14188
14191
14192 branch_t branch_;
14193 };
14194
14195 template <typename T> struct is_const { enum {result = 0}; };
14196 template <typename T> struct is_const <const T> { enum {result = 1}; };
14197 template <typename T> struct is_const_ref { enum {result = 0}; };
14198 template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
14199 template <typename T> struct is_ref { enum {result = 0}; };
14200 template <typename T> struct is_ref<T&> { enum {result = 1}; };
14201 template <typename T> struct is_ref<const T&> { enum {result = 0}; };
14202
14203 template <std::size_t State>
14204 struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
14205
14206 template <>
14207 struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
14208
14209 #define exprtk_crtype(Type) \
14210 param_to_str<is_const_ref< Type >::result>::result() \
14211
14212 template <typename T>
14214 {
14216 typedef typename functor_t::bfunc_t bfunc_t;
14217
14218 struct mode0
14219 {
14220 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
14221 {
14222 // (T0 o0 T1) o1 T2
14223 return bf1(bf0(t0,t1),t2);
14224 }
14225
14226 template <typename T0, typename T1, typename T2>
14227 static inline std::string id()
14228 {
14229 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
14230 exprtk_crtype(T1) + ")o(" +
14231 exprtk_crtype(T2) + ")" ;
14232 return result;
14233 }
14234 };
14235
14236 struct mode1
14237 {
14238 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
14239 {
14240 // T0 o0 (T1 o1 T2)
14241 return bf0(t0,bf1(t1,t2));
14242 }
14243
14244 template <typename T0, typename T1, typename T2>
14245 static inline std::string id()
14246 {
14247 static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
14248 exprtk_crtype(T1) + "o" +
14249 exprtk_crtype(T2) + ")" ;
14250 return result;
14251 }
14252 };
14253 };
14254
14255 template <typename T>
14257 {
14259 typedef typename functor_t::bfunc_t bfunc_t;
14260
14261 struct mode0
14262 {
14263 static inline T process(const T& t0, const T& t1,
14264 const T& t2, const T& t3,
14265 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14266 {
14267 // (T0 o0 T1) o1 (T2 o2 T3)
14268 return bf1(bf0(t0,t1),bf2(t2,t3));
14269 }
14270
14271 template <typename T0, typename T1, typename T2, typename T3>
14272 static inline std::string id()
14273 {
14274 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
14275 exprtk_crtype(T1) + ")o" +
14276 "(" + exprtk_crtype(T2) + "o" +
14277 exprtk_crtype(T3) + ")" ;
14278 return result;
14279 }
14280 };
14281
14282 struct mode1
14283 {
14284 static inline T process(const T& t0, const T& t1,
14285 const T& t2, const T& t3,
14286 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14287 {
14288 // (T0 o0 (T1 o1 (T2 o2 T3))
14289 return bf0(t0,bf1(t1,bf2(t2,t3)));
14290 }
14291 template <typename T0, typename T1, typename T2, typename T3>
14292 static inline std::string id()
14293 {
14294 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
14295 exprtk_crtype(T1) + ")o(" +
14296 exprtk_crtype(T2) + "o" +
14297 exprtk_crtype(T3) + "))" ;
14298 return result;
14299 }
14300 };
14301
14302 struct mode2
14303 {
14304 static inline T process(const T& t0, const T& t1,
14305 const T& t2, const T& t3,
14306 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14307 {
14308 // (T0 o0 ((T1 o1 T2) o2 T3)
14309 return bf0(t0,bf2(bf1(t1,t2),t3));
14310 }
14311
14312 template <typename T0, typename T1, typename T2, typename T3>
14313 static inline std::string id()
14314 {
14315 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
14316 exprtk_crtype(T1) + "o" +
14317 exprtk_crtype(T2) + ")o(" +
14318 exprtk_crtype(T3) + "))" ;
14319 return result;
14320 }
14321 };
14322
14323 struct mode3
14324 {
14325 static inline T process(const T& t0, const T& t1,
14326 const T& t2, const T& t3,
14327 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14328 {
14329 // (((T0 o0 T1) o1 T2) o2 T3)
14330 return bf2(bf1(bf0(t0,t1),t2),t3);
14331 }
14332
14333 template <typename T0, typename T1, typename T2, typename T3>
14334 static inline std::string id()
14335 {
14336 static const std::string result = "((" + exprtk_crtype(T0) + "o" +
14337 exprtk_crtype(T1) + ")o(" +
14338 exprtk_crtype(T2) + "))o(" +
14339 exprtk_crtype(T3) + ")";
14340 return result;
14341 }
14342 };
14343
14344 struct mode4
14345 {
14346 static inline T process(const T& t0, const T& t1,
14347 const T& t2, const T& t3,
14348 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14349 {
14350 // ((T0 o0 (T1 o1 T2)) o2 T3
14351 return bf2(bf0(t0,bf1(t1,t2)),t3);
14352 }
14353
14354 template <typename T0, typename T1, typename T2, typename T3>
14355 static inline std::string id()
14356 {
14357 static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
14358 exprtk_crtype(T1) + "o" +
14359 exprtk_crtype(T2) + "))o(" +
14360 exprtk_crtype(T3) + ")" ;
14361 return result;
14362 }
14363 };
14364 };
14365
14366 #undef exprtk_crtype
14367
14368 template <typename T, typename T0, typename T1>
14369 struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
14370 template <typename T, typename T0, typename T1>
14372
14373 #define synthesis_node_type_define(T0_,T1_,v_) \
14374 template <typename T, typename T0, typename T1> \
14375 struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
14376 template <typename T, typename T0, typename T1> \
14377 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
14378
14379 synthesis_node_type_define(const T0&, const T1&, e_vov)
14380 synthesis_node_type_define(const T0&, const T1 , e_voc)
14381 synthesis_node_type_define(const T0 , const T1&, e_cov)
14382 synthesis_node_type_define( T0&, T1&, e_none)
14383 synthesis_node_type_define(const T0 , const T1 , e_none)
14384 synthesis_node_type_define( T0&, const T1 , e_none)
14386 synthesis_node_type_define(const T0&, T1&, e_none)
14388 #undef synthesis_node_type_define
14389
14390 template <typename T, typename T0, typename T1, typename T2>
14391 struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
14392 template <typename T, typename T0, typename T1, typename T2>
14394
14395 #define synthesis_node_type_define(T0_,T1_,T2_,v_) \
14396 template <typename T, typename T0, typename T1, typename T2> \
14397 struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
14398 template <typename T, typename T0, typename T1, typename T2> \
14399 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
14400
14401 synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
14402 synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
14403 synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
14404 synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
14405 synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
14406 synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
14407 synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
14408 synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
14410 #undef synthesis_node_type_define
14411
14412 template <typename T, typename T0, typename T1, typename T2, typename T3>
14414 template <typename T, typename T0, typename T1, typename T2, typename T3>
14416
14417 #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \
14418 template <typename T, typename T0, typename T1, typename T2, typename T3> \
14419 struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
14420 template <typename T, typename T0, typename T1, typename T2, typename T3> \
14421 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
14422
14423 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
14424 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
14425 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
14426 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
14427 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
14428 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
14429 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
14430 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
14431 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
14432 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
14433 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
14434 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
14435 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
14436 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
14437 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
14438 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
14439 #undef synthesis_node_type_define
14440
14441 template <typename T, typename T0, typename T1>
14442 class T0oT1 : public expression_node<T>
14443 {
14444 public:
14445
14447 typedef typename functor_t::bfunc_t bfunc_t;
14448 typedef T value_type;
14450
14451 T0oT1(T0 p0, T1 p1, const bfunc_t p2)
14452 : t0_(p0),
14453 t1_(p1),
14454 f_ (p2)
14455 {}
14456
14457 inline typename expression_node<T>::node_type type() const
14458 {
14460 return result;
14461 }
14462
14464 {
14465 return e_default;
14466 }
14467
14468 inline T value() const
14469 {
14470 return f_(t0_,t1_);
14471 }
14472
14473 inline T0 t0() const
14474 {
14475 return t0_;
14476 }
14477
14478 inline T1 t1() const
14479 {
14480 return t1_;
14481 }
14482
14483 inline bfunc_t f() const
14484 {
14485 return f_;
14486 }
14487
14488 template <typename Allocator>
14489 static inline expression_node<T>* allocate(Allocator& allocator,
14490 T0 p0, T1 p1,
14491 bfunc_t p2)
14492 {
14493 return allocator
14494 .template allocate_type<node_type, T0, T1, bfunc_t&>
14495 (p0, p1, p2);
14496 }
14497
14498 private:
14499
14501 T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
14502
14503 T0 t0_;
14504 T1 t1_;
14505 const bfunc_t f_;
14506 };
14507
14508 template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
14510 {
14511 public:
14512
14514 typedef typename functor_t::bfunc_t bfunc_t;
14515 typedef T value_type;
14517 typedef ProcessMode process_mode_t;
14518
14519 T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
14520 : t0_(p0),
14521 t1_(p1),
14522 t2_(p2),
14523 f0_(p3),
14524 f1_(p4)
14525 {}
14526
14527 inline typename expression_node<T>::node_type type() const
14528 {
14530 return result;
14531 }
14532
14534 {
14535 return e_default;
14536 }
14537
14538 inline T value() const
14539 {
14540 return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
14541 }
14542
14543 inline T0 t0() const
14544 {
14545 return t0_;
14546 }
14547
14548 inline T1 t1() const
14549 {
14550 return t1_;
14551 }
14552
14553 inline T2 t2() const
14554 {
14555 return t2_;
14556 }
14557
14558 bfunc_t f0() const
14559 {
14560 return f0_;
14561 }
14562
14563 bfunc_t f1() const
14564 {
14565 return f1_;
14566 }
14567
14569 {
14570 return id();
14571 }
14572
14573 static inline std::string id()
14574 {
14575 return process_mode_t::template id<T0,T1,T2>();
14576 }
14577
14578 template <typename Allocator>
14579 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
14580 {
14581 return allocator
14582 .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
14583 (p0, p1, p2, p3, p4);
14584 }
14585
14586 private:
14587
14588 T0oT1oT2(node_type&) {}
14589 node_type& operator=(node_type&) { return (*this); }
14590
14591 T0 t0_;
14592 T1 t1_;
14593 T2 t2_;
14594 const bfunc_t f0_;
14595 const bfunc_t f1_;
14596 };
14597
14598 template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
14600 {
14601 public:
14602
14604 typedef typename functor_t::bfunc_t bfunc_t;
14605 typedef T value_type;
14606 typedef T0_ T0;
14607 typedef T1_ T1;
14608 typedef T2_ T2;
14609 typedef T3_ T3;
14611 typedef ProcessMode process_mode_t;
14612
14613 T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
14614 : t0_(p0),
14615 t1_(p1),
14616 t2_(p2),
14617 t3_(p3),
14618 f0_(p4),
14619 f1_(p5),
14620 f2_(p6)
14621 {}
14622
14623 inline T value() const
14624 {
14625 return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
14626 }
14627
14628 inline T0 t0() const
14629 {
14630 return t0_;
14631 }
14632
14633 inline T1 t1() const
14634 {
14635 return t1_;
14636 }
14637
14638 inline T2 t2() const
14639 {
14640 return t2_;
14641 }
14642
14643 inline T3 t3() const
14644 {
14645 return t3_;
14646 }
14647
14648 inline bfunc_t f0() const
14649 {
14650 return f0_;
14651 }
14652
14653 inline bfunc_t f1() const
14654 {
14655 return f1_;
14656 }
14657
14658 inline bfunc_t f2() const
14659 {
14660 return f2_;
14661 }
14662
14663 inline std::string type_id() const
14664 {
14665 return id();
14666 }
14667
14668 static inline std::string id()
14669 {
14670 return process_mode_t::template id<T0, T1, T2, T3>();
14671 }
14672
14673 template <typename Allocator>
14674 static inline expression_node<T>* allocate(Allocator& allocator,
14675 T0 p0, T1 p1, T2 p2, T3 p3,
14676 bfunc_t p4, bfunc_t p5, bfunc_t p6)
14677 {
14678 return allocator
14679 .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14680 (p0, p1, p2, p3, p4, p5, p6);
14681 }
14682
14683 private:
14684
14686 node_type& operator=(node_type&) { return (*this); }
14687
14688 T0 t0_;
14689 T1 t1_;
14690 T2 t2_;
14691 T3 t3_;
14692 const bfunc_t f0_;
14693 const bfunc_t f1_;
14694 const bfunc_t f2_;
14695 };
14696
14697 template <typename T, typename T0, typename T1, typename T2>
14699 {
14700 public:
14701
14703 typedef typename functor_t::tfunc_t tfunc_t;
14704 typedef T value_type;
14706
14707 T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14708 : t0_(p0),
14709 t1_(p1),
14710 t2_(p2),
14711 f_ (p3)
14712 {}
14713
14714 inline typename expression_node<T>::node_type type() const
14715 {
14717 return result;
14718 }
14719
14721 {
14722 return e_default;
14723 }
14724
14725 inline T value() const
14726 {
14727 return f_(t0_, t1_, t2_);
14728 }
14729
14730 inline T0 t0() const
14731 {
14732 return t0_;
14733 }
14734
14735 inline T1 t1() const
14736 {
14737 return t1_;
14738 }
14739
14740 inline T2 t2() const
14741 {
14742 return t2_;
14743 }
14744
14745 tfunc_t f() const
14746 {
14747 return f_;
14748 }
14749
14751 {
14752 return id();
14753 }
14754
14755 static inline std::string id()
14756 {
14757 return "sf3";
14758 }
14759
14760 template <typename Allocator>
14761 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14762 {
14763 return allocator
14764 .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14765 (p0, p1, p2, p3);
14766 }
14767
14768 private:
14769
14771 node_type& operator=(node_type&) { return (*this); }
14772
14773 T0 t0_;
14774 T1 t1_;
14775 T2 t2_;
14776 const tfunc_t f_;
14777 };
14778
14779 template <typename T, typename T0, typename T1, typename T2>
14781 {
14782 public:
14783
14785 {}
14786
14787 virtual T0 t0() const = 0;
14788
14789 virtual T1 t1() const = 0;
14790
14791 virtual T2 t2() const = 0;
14792 };
14793
14794 template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14795 class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14796 {
14797 public:
14798
14800 typedef typename functor_t::tfunc_t tfunc_t;
14801 typedef T value_type;
14803
14805 : t0_(p0),
14806 t1_(p1),
14807 t2_(p2)
14808 {}
14809
14810 inline typename expression_node<T>::node_type type() const
14811 {
14813 return result;
14814 }
14815
14817 {
14818 return e_default;
14819 }
14820
14821 inline T value() const
14822 {
14823 return SF3Operation::process(t0_, t1_, t2_);
14824 }
14825
14826 T0 t0() const
14827 {
14828 return t0_;
14829 }
14830
14831 T1 t1() const
14832 {
14833 return t1_;
14834 }
14835
14836 T2 t2() const
14837 {
14838 return t2_;
14839 }
14840
14842 {
14843 return id();
14844 }
14845
14846 static inline std::string id()
14847 {
14848 return SF3Operation::id();
14849 }
14850
14851 template <typename Allocator>
14852 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14853 {
14854 return allocator
14855 .template allocate_type<node_type, T0, T1, T2>
14856 (p0, p1, p2);
14857 }
14858
14859 private:
14860
14862 node_type& operator=(node_type&) { return (*this); }
14863
14864 T0 t0_;
14865 T1 t1_;
14866 T2 t2_;
14867 };
14868
14869 template <typename T>
14871 {
14872 switch (n->type())
14873 {
14874 case expression_node<T>::e_vovov : return true;
14875 case expression_node<T>::e_vovoc : return true;
14876 case expression_node<T>::e_vocov : return true;
14877 case expression_node<T>::e_covov : return true;
14878 case expression_node<T>::e_covoc : return true;
14879 default : return false;
14880 }
14881 }
14882
14883 template <typename T, typename T0, typename T1, typename T2, typename T3>
14885 {
14886 public:
14887
14889 typedef typename functor_t::qfunc_t qfunc_t;
14890 typedef T value_type;
14892
14893 T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14894 : t0_(p0),
14895 t1_(p1),
14896 t2_(p2),
14897 t3_(p3),
14898 f_ (p4)
14899 {}
14900
14901 inline typename expression_node<T>::node_type type() const
14902 {
14904 return result;
14905 }
14906
14908 {
14909 return e_default;
14910 }
14911
14912 inline T value() const
14913 {
14914 return f_(t0_, t1_, t2_, t3_);
14915 }
14916
14917 inline T0 t0() const
14918 {
14919 return t0_;
14920 }
14921
14922 inline T1 t1() const
14923 {
14924 return t1_;
14925 }
14926
14927 inline T2 t2() const
14928 {
14929 return t2_;
14930 }
14931
14932 inline T3 t3() const
14933 {
14934 return t3_;
14935 }
14936
14937 qfunc_t f() const
14938 {
14939 return f_;
14940 }
14941
14943 {
14944 return id();
14945 }
14946
14947 static inline std::string id()
14948 {
14949 return "sf4";
14950 }
14951
14952 template <typename Allocator>
14953 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14954 {
14955 return allocator
14956 .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14957 (p0, p1, p2, p3, p4);
14958 }
14959
14960 private:
14961
14963 node_type& operator=(node_type&) { return (*this); }
14964
14965 T0 t0_;
14966 T1 t1_;
14967 T2 t2_;
14968 T3 t3_;
14969 const qfunc_t f_;
14970 };
14971
14972 template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14974 {
14975 public:
14976
14978 typedef typename functor_t::tfunc_t tfunc_t;
14979 typedef T value_type;
14981
14982 T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14983 : t0_(p0),
14984 t1_(p1),
14985 t2_(p2),
14986 t3_(p3)
14987 {}
14988
14989 inline typename expression_node<T>::node_type type() const
14990 {
14992 return result;
14993 }
14994
14996 {
14997 return e_default;
14998 }
14999
15000 inline T value() const
15001 {
15002 return SF4Operation::process(t0_, t1_, t2_, t3_);
15003 }
15004
15005 inline T0 t0() const
15006 {
15007 return t0_;
15008 }
15009
15010 inline T1 t1() const
15011 {
15012 return t1_;
15013 }
15014
15015 inline T2 t2() const
15016 {
15017 return t2_;
15018 }
15019
15020 inline T3 t3() const
15021 {
15022 return t3_;
15023 }
15024
15026 {
15027 return id();
15028 }
15029
15030 static inline std::string id()
15031 {
15032 return SF4Operation::id();
15033 }
15034
15035 template <typename Allocator>
15036 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
15037 {
15038 return allocator
15039 .template allocate_type<node_type, T0, T1, T2, T3>
15040 (p0, p1, p2, p3);
15041 }
15042
15043 private:
15044
15046 node_type& operator=(node_type&) { return (*this); }
15047
15048 T0 t0_;
15049 T1 t1_;
15050 T2 t2_;
15051 T3 t3_;
15052 };
15053
15054 template <typename T>
15056 {
15057 switch (n->type())
15058 {
15059 case expression_node<T>::e_vovovov : return true;
15060 case expression_node<T>::e_vovovoc : return true;
15061 case expression_node<T>::e_vovocov : return true;
15062 case expression_node<T>::e_vocovov : return true;
15063 case expression_node<T>::e_covovov : return true;
15064 case expression_node<T>::e_covocov : return true;
15065 case expression_node<T>::e_vocovoc : return true;
15066 case expression_node<T>::e_covovoc : return true;
15067 case expression_node<T>::e_vococov : return true;
15068 default : return false;
15069 }
15070 }
15071
15072 template <typename T, typename T0, typename T1>
15074 {
15076 };
15077
15078 template <typename T, typename T0, typename T1, typename T2>
15080 {
15085 };
15086
15087 template <typename T, typename T0, typename T1, typename T2, typename T3>
15089 {
15096 };
15097
15098 template <typename T, typename Operation>
15099 class vov_node : public vov_base_node<T>
15100 {
15101 public:
15102
15104 typedef Operation operation_t;
15105
15106 // variable op variable node
15107 explicit vov_node(const T& var0, const T& var1)
15108 : v0_(var0),
15109 v1_(var1)
15110 {}
15111
15112 inline T value() const
15113 {
15114 return Operation::process(v0_,v1_);
15115 }
15116
15117 inline typename expression_node<T>::node_type type() const
15118 {
15119 return Operation::type();
15120 }
15121
15123 {
15124 return Operation::operation();
15125 }
15126
15127 inline const T& v0() const
15128 {
15129 return v0_;
15130 }
15131
15132 inline const T& v1() const
15133 {
15134 return v1_;
15135 }
15136
15137 protected:
15138
15139 const T& v0_;
15140 const T& v1_;
15141
15142 private:
15143
15146 };
15147
15148 template <typename T, typename Operation>
15149 class cov_node : public cov_base_node<T>
15150 {
15151 public:
15152
15154 typedef Operation operation_t;
15155
15156 // constant op variable node
15157 explicit cov_node(const T& const_var, const T& var)
15158 : c_(const_var),
15159 v_(var)
15160 {}
15161
15162 inline T value() const
15163 {
15164 return Operation::process(c_,v_);
15165 }
15166
15167 inline typename expression_node<T>::node_type type() const
15168 {
15169 return Operation::type();
15170 }
15171
15173 {
15174 return Operation::operation();
15175 }
15176
15177 inline const T c() const
15178 {
15179 return c_;
15180 }
15181
15182 inline const T& v() const
15183 {
15184 return v_;
15185 }
15186
15187 protected:
15188
15189 const T c_;
15190 const T& v_;
15191
15192 private:
15193
15196 };
15197
15198 template <typename T, typename Operation>
15199 class voc_node : public voc_base_node<T>
15200 {
15201 public:
15202
15204 typedef Operation operation_t;
15205
15206 // variable op constant node
15207 explicit voc_node(const T& var, const T& const_var)
15208 : v_(var),
15209 c_(const_var)
15210 {}
15211
15212 inline T value() const
15213 {
15214 return Operation::process(v_,c_);
15215 }
15216
15218 {
15219 return Operation::operation();
15220 }
15221
15222 inline const T c() const
15223 {
15224 return c_;
15225 }
15226
15227 inline const T& v() const
15228 {
15229 return v_;
15230 }
15231
15232 protected:
15233
15234 const T& v_;
15235 const T c_;
15236
15237 private:
15238
15241 };
15242
15243 template <typename T, typename Operation>
15244 class vob_node : public vob_base_node<T>
15245 {
15246 public:
15247
15249 typedef std::pair<expression_ptr,bool> branch_t;
15250 typedef Operation operation_t;
15251
15252 // variable op constant node
15253 explicit vob_node(const T& var, const expression_ptr branch)
15254 : v_(var)
15255 {
15256 construct_branch_pair(branch_, branch);
15257 }
15258
15259 inline T value() const
15260 {
15261 assert(branch_.first);
15262 return Operation::process(v_,branch_.first->value());
15263 }
15264
15266 {
15267 return Operation::operation();
15268 }
15269
15270 inline const T& v() const
15271 {
15272 return v_;
15273 }
15274
15275 inline expression_node<T>* branch(const std::size_t&) const
15276 {
15277 return branch_.first;
15278 }
15279
15280 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15281 {
15282 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15283 }
15284
15285 std::size_t node_depth() const
15286 {
15288 }
15289
15290 private:
15291
15294
15295 const T& v_;
15296 branch_t branch_;
15297 };
15298
15299 template <typename T, typename Operation>
15300 class bov_node : public bov_base_node<T>
15301 {
15302 public:
15303
15305 typedef std::pair<expression_ptr,bool> branch_t;
15306 typedef Operation operation_t;
15307
15308 // variable op constant node
15309 explicit bov_node(const expression_ptr branch, const T& var)
15310 : v_(var)
15311 {
15312 construct_branch_pair(branch_, branch);
15313 }
15314
15315 inline T value() const
15316 {
15317 assert(branch_.first);
15318 return Operation::process(branch_.first->value(),v_);
15319 }
15320
15322 {
15323 return Operation::operation();
15324 }
15325
15326 inline const T& v() const
15327 {
15328 return v_;
15329 }
15330
15331 inline expression_node<T>* branch(const std::size_t&) const
15332 {
15333 return branch_.first;
15334 }
15335
15336 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15337 {
15338 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15339 }
15340
15341 std::size_t node_depth() const
15342 {
15344 }
15345
15346 private:
15347
15350
15351 const T& v_;
15352 branch_t branch_;
15353 };
15354
15355 template <typename T, typename Operation>
15356 class cob_node : public cob_base_node<T>
15357 {
15358 public:
15359
15361 typedef std::pair<expression_ptr,bool> branch_t;
15362 typedef Operation operation_t;
15363
15364 // variable op constant node
15365 explicit cob_node(const T const_var, const expression_ptr branch)
15366 : c_(const_var)
15367 {
15368 construct_branch_pair(branch_, branch);
15369 }
15370
15371 inline T value() const
15372 {
15373 assert(branch_.first);
15374 return Operation::process(c_,branch_.first->value());
15375 }
15376
15378 {
15379 return Operation::operation();
15380 }
15381
15382 inline const T c() const
15383 {
15384 return c_;
15385 }
15386
15387 inline void set_c(const T new_c)
15388 {
15389 (*const_cast<T*>(&c_)) = new_c;
15390 }
15391
15392 inline expression_node<T>* branch(const std::size_t&) const
15393 {
15394 return branch_.first;
15395 }
15396
15397 inline expression_node<T>* move_branch(const std::size_t&)
15398 {
15399 branch_.second = false;
15400 return branch_.first;
15401 }
15402
15403 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15404 {
15405 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15406 }
15407
15408 std::size_t node_depth() const
15409 {
15411 }
15412
15413 private:
15414
15417
15418 const T c_;
15419 branch_t branch_;
15420 };
15421
15422 template <typename T, typename Operation>
15423 class boc_node : public boc_base_node<T>
15424 {
15425 public:
15426
15428 typedef std::pair<expression_ptr,bool> branch_t;
15429 typedef Operation operation_t;
15430
15431 // variable op constant node
15432 explicit boc_node(const expression_ptr branch, const T const_var)
15433 : c_(const_var)
15434 {
15435 construct_branch_pair(branch_, branch);
15436 }
15437
15438 inline T value() const
15439 {
15440 assert(branch_.first);
15441 return Operation::process(branch_.first->value(),c_);
15442 }
15443
15445 {
15446 return Operation::operation();
15447 }
15448
15449 inline const T c() const
15450 {
15451 return c_;
15452 }
15453
15454 inline void set_c(const T new_c)
15455 {
15456 (*const_cast<T*>(&c_)) = new_c;
15457 }
15458
15459 inline expression_node<T>* branch(const std::size_t&) const
15460 {
15461 return branch_.first;
15462 }
15463
15464 inline expression_node<T>* move_branch(const std::size_t&)
15465 {
15466 branch_.second = false;
15467 return branch_.first;
15468 }
15469
15470 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15471 {
15472 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15473 }
15474
15475 std::size_t node_depth() const
15476 {
15478 }
15479
15480 private:
15481
15484
15485 const T c_;
15486 branch_t branch_;
15487 };
15488
15489 #ifndef exprtk_disable_string_capabilities
15490 template <typename T, typename SType0, typename SType1, typename Operation>
15491 class sos_node : public sos_base_node<T>
15492 {
15493 public:
15494
15496 typedef Operation operation_t;
15497
15498 // string op string node
15499 explicit sos_node(SType0 p0, SType1 p1)
15500 : s0_(p0),
15501 s1_(p1)
15502 {}
15503
15504 inline T value() const
15505 {
15506 return Operation::process(s0_,s1_);
15507 }
15508
15509 inline typename expression_node<T>::node_type type() const
15510 {
15511 return Operation::type();
15512 }
15513
15515 {
15516 return Operation::operation();
15517 }
15518
15519 inline std::string& s0()
15520 {
15521 return s0_;
15522 }
15523
15524 inline std::string& s1()
15525 {
15526 return s1_;
15527 }
15528
15529 protected:
15530
15531 SType0 s0_;
15532 SType1 s1_;
15533
15534 private:
15535
15538 };
15539
15540 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15542 {
15543 public:
15544
15546 typedef Operation operation_t;
15547
15548 // string-range op string node
15549 explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
15550 : s0_ (p0 ),
15551 s1_ (p1 ),
15552 rp0_(rp0)
15553 {}
15554
15556 {
15557 rp0_.free();
15558 }
15559
15560 inline T value() const
15561 {
15562 std::size_t r0 = 0;
15563 std::size_t r1 = 0;
15564
15565 if (rp0_(r0, r1, s0_.size()))
15566 return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
15567 else
15568 return T(0);
15569 }
15570
15571 inline typename expression_node<T>::node_type type() const
15572 {
15573 return Operation::type();
15574 }
15575
15577 {
15578 return Operation::operation();
15579 }
15580
15581 inline std::string& s0()
15582 {
15583 return s0_;
15584 }
15585
15586 inline std::string& s1()
15587 {
15588 return s1_;
15589 }
15590
15591 protected:
15592
15593 SType0 s0_;
15594 SType1 s1_;
15595 RangePack rp0_;
15596
15597 private:
15598
15601 };
15602
15603 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15605 {
15606 public:
15607
15609 typedef Operation operation_t;
15610
15611 // string op string range node
15612 explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
15613 : s0_ (p0 ),
15614 s1_ (p1 ),
15615 rp1_(rp1)
15616 {}
15617
15619 {
15620 rp1_.free();
15621 }
15622
15623 inline T value() const
15624 {
15625 std::size_t r0 = 0;
15626 std::size_t r1 = 0;
15627
15628 if (rp1_(r0, r1, s1_.size()))
15629 return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
15630 else
15631 return T(0);
15632 }
15633
15634 inline typename expression_node<T>::node_type type() const
15635 {
15636 return Operation::type();
15637 }
15638
15640 {
15641 return Operation::operation();
15642 }
15643
15644 inline std::string& s0()
15645 {
15646 return s0_;
15647 }
15648
15649 inline std::string& s1()
15650 {
15651 return s1_;
15652 }
15653
15654 protected:
15655
15656 SType0 s0_;
15657 SType1 s1_;
15658 RangePack rp1_;
15659
15660 private:
15661
15664 };
15665
15666 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15668 {
15669 public:
15670
15672 typedef Operation operation_t;
15673
15674 // string-range op string-range node
15675 explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15676 : s0_ (p0 ),
15677 s1_ (p1 ),
15678 rp0_(rp0),
15679 rp1_(rp1)
15680 {}
15681
15683 {
15684 rp0_.free();
15685 rp1_.free();
15686 }
15687
15688 inline T value() const
15689 {
15690 std::size_t r0_0 = 0;
15691 std::size_t r0_1 = 0;
15692 std::size_t r1_0 = 0;
15693 std::size_t r1_1 = 0;
15694
15695 if (
15696 rp0_(r0_0, r1_0, s0_.size()) &&
15697 rp1_(r0_1, r1_1, s1_.size())
15698 )
15699 {
15700 return Operation::process(
15701 s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15702 s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15703 );
15704 }
15705 else
15706 return T(0);
15707 }
15708
15709 inline typename expression_node<T>::node_type type() const
15710 {
15711 return Operation::type();
15712 }
15713
15715 {
15716 return Operation::operation();
15717 }
15718
15719 inline std::string& s0()
15720 {
15721 return s0_;
15722 }
15723
15724 inline std::string& s1()
15725 {
15726 return s1_;
15727 }
15728
15729 protected:
15730
15731 SType0 s0_;
15732 SType1 s1_;
15733 RangePack rp0_;
15734 RangePack rp1_;
15735
15736 private:
15737
15740 };
15741
15742 template <typename T, typename Operation>
15744 {
15745 public:
15746
15753
15755 expression_ptr branch0,
15756 expression_ptr branch1)
15757 : binary_node<T>(opr, branch0, branch1),
15758 str0_base_ptr_ (0),
15759 str1_base_ptr_ (0),
15760 str0_range_ptr_(0),
15761 str1_range_ptr_(0)
15762 {
15764 {
15765 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15766
15767 if (0 == str0_base_ptr_)
15768 return;
15769
15770 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15771
15772 if (0 == range)
15773 return;
15774
15775 str0_range_ptr_ = &(range->range_ref());
15776 }
15777
15779 {
15780 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15781
15782 if (0 == str1_base_ptr_)
15783 return;
15784
15785 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15786
15787 if (0 == range)
15788 return;
15789
15790 str1_range_ptr_ = &(range->range_ref());
15791 }
15792 }
15793
15794 inline T value() const
15795 {
15796 if (
15797 str0_base_ptr_ &&
15798 str1_base_ptr_ &&
15799 str0_range_ptr_ &&
15800 str1_range_ptr_
15801 )
15802 {
15803 binary_node<T>::branch_[0].first->value();
15804 binary_node<T>::branch_[1].first->value();
15805
15806 std::size_t str0_r0 = 0;
15807 std::size_t str0_r1 = 0;
15808
15809 std::size_t str1_r0 = 0;
15810 std::size_t str1_r1 = 0;
15811
15812 const range_t& range0 = (*str0_range_ptr_);
15813 const range_t& range1 = (*str1_range_ptr_);
15814
15815 if (
15816 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15817 range1(str1_r0, str1_r1, str1_base_ptr_->size())
15818 )
15819 {
15820 return Operation::process(
15821 str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15822 str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15823 );
15824 }
15825 }
15826
15827 return std::numeric_limits<T>::quiet_NaN();
15828 }
15829
15830 inline typename expression_node<T>::node_type type() const
15831 {
15832 return Operation::type();
15833 }
15834
15836 {
15837 return Operation::operation();
15838 }
15839
15840 private:
15841
15844
15845 str_base_ptr str0_base_ptr_;
15846 str_base_ptr str1_base_ptr_;
15847 range_ptr str0_range_ptr_;
15848 range_ptr str1_range_ptr_;
15849 };
15850
15851 template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15852 class sosos_node : public sosos_base_node<T>
15853 {
15854 public:
15855
15857 typedef Operation operation_t;
15858
15859 // variable op variable node
15860 explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15861 : s0_(p0),
15862 s1_(p1),
15863 s2_(p2)
15864 {}
15865
15866 inline T value() const
15867 {
15868 return Operation::process(s0_,s1_,s2_);
15869 }
15870
15871 inline typename expression_node<T>::node_type type() const
15872 {
15873 return Operation::type();
15874 }
15875
15877 {
15878 return Operation::operation();
15879 }
15880
15881 inline std::string& s0()
15882 {
15883 return s0_;
15884 }
15885
15886 inline std::string& s1()
15887 {
15888 return s1_;
15889 }
15890
15891 inline std::string& s2()
15892 {
15893 return s2_;
15894 }
15895
15896 protected:
15897
15898 SType0 s0_;
15899 SType1 s1_;
15900 SType2 s2_;
15901
15902 private:
15903
15906 };
15907 #endif
15908
15909 template <typename T, typename PowOp>
15910 class ipow_node : public expression_node<T>
15911 {
15912 public:
15913
15915 typedef PowOp operation_t;
15916
15917 explicit ipow_node(const T& v)
15918 : v_(v)
15919 {}
15920
15921 inline T value() const
15922 {
15923 return PowOp::result(v_);
15924 }
15925
15926 inline typename expression_node<T>::node_type type() const
15927 {
15929 }
15930
15931 private:
15932
15934 ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
15935
15936 const T& v_;
15937 };
15938
15939 template <typename T, typename PowOp>
15940 class bipow_node : public expression_node<T>
15941 {
15942 public:
15943
15945 typedef std::pair<expression_ptr, bool> branch_t;
15946 typedef PowOp operation_t;
15947
15949 {
15950 construct_branch_pair(branch_, branch);
15951 }
15952
15953 inline T value() const
15954 {
15955 assert(branch_.first);
15956 return PowOp::result(branch_.first->value());
15957 }
15958
15959 inline typename expression_node<T>::node_type type() const
15960 {
15962 }
15963
15964 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15965 {
15966 expression_node<T>::ndb_t::collect(branch_, node_delete_list);
15967 }
15968
15969 std::size_t node_depth() const
15970 {
15972 }
15973
15974 private:
15975
15977 bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
15978
15979 branch_t branch_;
15980 };
15981
15982 template <typename T, typename PowOp>
15984 {
15985 public:
15986
15988 typedef PowOp operation_t;
15989
15990 explicit ipowinv_node(const T& v)
15991 : v_(v)
15992 {}
15993
15994 inline T value() const
15995 {
15996 return (T(1) / PowOp::result(v_));
15997 }
15998
15999 inline typename expression_node<T>::node_type type() const
16000 {
16002 }
16003
16004 private:
16005
16008
16009 const T& v_;
16010 };
16011
16012 template <typename T, typename PowOp>
16014 {
16015 public:
16016
16018 typedef std::pair<expression_ptr, bool> branch_t;
16019 typedef PowOp operation_t;
16020
16022 {
16023 construct_branch_pair(branch_, branch);
16024 }
16025
16026 inline T value() const
16027 {
16028 assert(branch_.first);
16029 return (T(1) / PowOp::result(branch_.first->value()));
16030 }
16031
16032 inline typename expression_node<T>::node_type type() const
16033 {
16035 }
16036
16037 void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
16038 {
16039 expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
16040 }
16041
16042 std::size_t node_depth() const
16043 {
16045 }
16046
16047 private:
16048
16051
16052 branch_t branch_;
16053 };
16054
16055 template <typename T>
16056 inline bool is_vov_node(const expression_node<T>* node)
16057 {
16058 return (0 != dynamic_cast<const vov_base_node<T>*>(node));
16059 }
16060
16061 template <typename T>
16062 inline bool is_cov_node(const expression_node<T>* node)
16063 {
16064 return (0 != dynamic_cast<const cov_base_node<T>*>(node));
16065 }
16066
16067 template <typename T>
16068 inline bool is_voc_node(const expression_node<T>* node)
16069 {
16070 return (0 != dynamic_cast<const voc_base_node<T>*>(node));
16071 }
16072
16073 template <typename T>
16074 inline bool is_cob_node(const expression_node<T>* node)
16075 {
16076 return (0 != dynamic_cast<const cob_base_node<T>*>(node));
16077 }
16078
16079 template <typename T>
16080 inline bool is_boc_node(const expression_node<T>* node)
16081 {
16082 return (0 != dynamic_cast<const boc_base_node<T>*>(node));
16083 }
16084
16085 template <typename T>
16086 inline bool is_t0ot1ot2_node(const expression_node<T>* node)
16087 {
16088 return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
16089 }
16090
16091 template <typename T>
16093 {
16094 return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
16095 }
16096
16097 template <typename T>
16098 inline bool is_uv_node(const expression_node<T>* node)
16099 {
16100 return (0 != dynamic_cast<const uv_base_node<T>*>(node));
16101 }
16102
16103 template <typename T>
16104 inline bool is_string_node(const expression_node<T>* node)
16105 {
16106 return node && (expression_node<T>::e_stringvar == node->type());
16107 }
16108
16109 template <typename T>
16111 {
16112 return node && (expression_node<T>::e_stringvarrng == node->type());
16113 }
16114
16115 template <typename T>
16117 {
16118 return node && (expression_node<T>::e_stringconst == node->type());
16119 }
16120
16121 template <typename T>
16123 {
16124 return node && (expression_node<T>::e_cstringvarrng == node->type());
16125 }
16126
16127 template <typename T>
16129 {
16130 return node && (expression_node<T>::e_strass == node->type());
16131 }
16132
16133 template <typename T>
16135 {
16136 return node && (expression_node<T>::e_strconcat == node->type());
16137 }
16138
16139 template <typename T>
16141 {
16142 return node && (expression_node<T>::e_strfunction == node->type());
16143 }
16144
16145 template <typename T>
16147 {
16148 return node && (expression_node<T>::e_strcondition == node->type());
16149 }
16150
16151 template <typename T>
16153 {
16154 return node && (expression_node<T>::e_strccondition == node->type());
16155 }
16156
16157 template <typename T>
16159 {
16160 return node && (expression_node<T>::e_stringvararg == node->type());
16161 }
16162
16163 template <typename T>
16165 {
16166 return node && (expression_node<T>::e_strgenrange == node->type());
16167 }
16168
16169 template <typename T>
16171 {
16172 if (node)
16173 {
16174 switch (node->type())
16175 {
16186 case expression_node<T>::e_stringvararg : return true;
16187 default : return false;
16188 }
16189 }
16190
16191 return false;
16192 }
16193
16195 {
16196 public:
16197
16198 template <typename ResultNode, typename OpType, typename ExprNode>
16199 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
16200 {
16202 allocate<ResultNode>(operation, branch[0]);
16203 result->node_depth();
16204 return result;
16205 }
16206
16207 template <typename ResultNode, typename OpType, typename ExprNode>
16208 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
16209 {
16211 allocate<ResultNode>(operation, branch[0], branch[1]);
16212 result->node_depth();
16213 return result;
16214 }
16215
16216 template <typename ResultNode, typename OpType, typename ExprNode>
16217 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
16218 {
16220 allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
16221 result->node_depth();
16222 return result;
16223 }
16224
16225 template <typename ResultNode, typename OpType, typename ExprNode>
16226 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
16227 {
16229 allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
16230 result->node_depth();
16231 return result;
16232 }
16233
16234 template <typename ResultNode, typename OpType, typename ExprNode>
16235 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
16236 {
16238 allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
16239 result->node_depth();
16240 return result;
16241 }
16242
16243 template <typename ResultNode, typename OpType, typename ExprNode>
16244 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
16245 {
16247 allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
16248 result->node_depth();
16249 return result;
16250 }
16251
16252 template <typename node_type>
16254 {
16255 return (new node_type());
16256 }
16257
16258 template <typename node_type,
16259 typename Type,
16260 typename Allocator,
16261 template <typename, typename> class Sequence>
16262 inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
16263 {
16265 result = (new node_type(seq));
16266 result->node_depth();
16267 return result;
16268 }
16269
16270 template <typename node_type, typename T1>
16272 {
16274 result = (new node_type(t1));
16275 result->node_depth();
16276 return result;
16277 }
16278
16279 template <typename node_type, typename T1>
16281 {
16283 result = (new node_type(t1));
16284 result->node_depth();
16285 return result;
16286 }
16287
16288 template <typename node_type,
16289 typename T1, typename T2>
16291 {
16293 result = (new node_type(t1, t2));
16294 result->node_depth();
16295 return result;
16296 }
16297
16298 template <typename node_type,
16299 typename T1, typename T2>
16301 {
16303 result = (new node_type(t1, t2));
16304 result->node_depth();
16305 return result;
16306 }
16307
16308 template <typename node_type,
16309 typename T1, typename T2>
16311 {
16313 result = (new node_type(t1, t2));
16314 result->node_depth();
16315 return result;
16316 }
16317
16318 template <typename node_type,
16319 typename T1, typename T2>
16321 {
16323 result = (new node_type(t1, t2));
16324 result->node_depth();
16325 return result;
16326 }
16327
16328 template <typename node_type,
16329 typename T1, typename T2>
16331 {
16333 result = (new node_type(t1, t2));
16334 result->node_depth();
16335 return result;
16336 }
16337
16338 template <typename node_type,
16339 typename T1, typename T2, typename T3>
16341 {
16343 result = (new node_type(t1, t2, t3));
16344 result->node_depth();
16345 return result;
16346 }
16347
16348 template <typename node_type,
16349 typename T1, typename T2, typename T3, typename T4>
16351 {
16353 result = (new node_type(t1, t2, t3, t4));
16354 result->node_depth();
16355 return result;
16356 }
16357
16358 template <typename node_type,
16359 typename T1, typename T2, typename T3>
16361 {
16363 result = (new node_type(t1, t2, t3));
16364 result->node_depth();
16365 return result;
16366 }
16367
16368 template <typename node_type,
16369 typename T1, typename T2, typename T3, typename T4>
16371 {
16373 result = (new node_type(t1, t2, t3, t4));
16374 result->node_depth();
16375 return result;
16376 }
16377
16378 template <typename node_type,
16379 typename T1, typename T2, typename T3, typename T4, typename T5>
16380 inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
16381 {
16383 result = (new node_type(t1, t2, t3, t4, t5));
16384 result->node_depth();
16385 return result;
16386 }
16387
16388 template <typename node_type,
16389 typename T1, typename T2, typename T3>
16391 const T3& t3) const
16392 {
16394 result = (new node_type(t1, t2, t3));
16395 result->node_depth();
16396 return result;
16397 }
16398
16399 template <typename node_type,
16400 typename T1, typename T2,
16401 typename T3, typename T4>
16403 const T3& t3, const T4& t4) const
16404 {
16406 result = (new node_type(t1, t2, t3, t4));
16407 result->node_depth();
16408 return result;
16409 }
16410
16411 template <typename node_type,
16412 typename T1, typename T2,
16413 typename T3, typename T4, typename T5>
16415 const T3& t3, const T4& t4,
16416 const T5& t5) const
16417 {
16419 result = (new node_type(t1, t2, t3, t4, t5));
16420 result->node_depth();
16421 return result;
16422 }
16423
16424 template <typename node_type,
16425 typename T1, typename T2,
16426 typename T3, typename T4, typename T5, typename T6>
16428 const T3& t3, const T4& t4,
16429 const T5& t5, const T6& t6) const
16430 {
16432 result = (new node_type(t1, t2, t3, t4, t5, t6));
16433 result->node_depth();
16434 return result;
16435 }
16436
16437 template <typename node_type,
16438 typename T1, typename T2,
16439 typename T3, typename T4,
16440 typename T5, typename T6, typename T7>
16442 const T3& t3, const T4& t4,
16443 const T5& t5, const T6& t6,
16444 const T7& t7) const
16445 {
16447 result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
16448 result->node_depth();
16449 return result;
16450 }
16451
16452 template <typename node_type,
16453 typename T1, typename T2,
16454 typename T3, typename T4,
16455 typename T5, typename T6,
16456 typename T7, typename T8>
16458 const T3& t3, const T4& t4,
16459 const T5& t5, const T6& t6,
16460 const T7& t7, const T8& t8) const
16461 {
16463 result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
16464 result->node_depth();
16465 return result;
16466 }
16467
16468 template <typename node_type,
16469 typename T1, typename T2,
16470 typename T3, typename T4,
16471 typename T5, typename T6,
16472 typename T7, typename T8, typename T9>
16474 const T3& t3, const T4& t4,
16475 const T5& t5, const T6& t6,
16476 const T7& t7, const T8& t8,
16477 const T9& t9) const
16478 {
16480 result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
16481 result->node_depth();
16482 return result;
16483 }
16484
16485 template <typename node_type,
16486 typename T1, typename T2,
16487 typename T3, typename T4,
16488 typename T5, typename T6,
16489 typename T7, typename T8,
16490 typename T9, typename T10>
16492 const T3& t3, const T4& t4,
16493 const T5& t5, const T6& t6,
16494 const T7& t7, const T8& t8,
16495 const T9& t9, const T10& t10) const
16496 {
16498 result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
16499 result->node_depth();
16500 return result;
16501 }
16502
16503 template <typename node_type,
16504 typename T1, typename T2, typename T3>
16506 {
16508 result = (new node_type(t1, t2, t3));
16509 result->node_depth();
16510 return result;
16511 }
16512
16513 template <typename node_type,
16514 typename T1, typename T2,
16515 typename T3, typename T4>
16517 T3 t3, T4 t4) const
16518 {
16520 result = (new node_type(t1, t2, t3, t4));
16521 result->node_depth();
16522 return result;
16523 }
16524
16525 template <typename node_type,
16526 typename T1, typename T2,
16527 typename T3, typename T4,
16528 typename T5>
16530 T3 t3, T4 t4,
16531 T5 t5) const
16532 {
16534 result = (new node_type(t1, t2, t3, t4, t5));
16535 result->node_depth();
16536 return result;
16537 }
16538
16539 template <typename node_type,
16540 typename T1, typename T2,
16541 typename T3, typename T4,
16542 typename T5, typename T6>
16544 T3 t3, T4 t4,
16545 T5 t5, T6 t6) const
16546 {
16548 result = (new node_type(t1, t2, t3, t4, t5, t6));
16549 result->node_depth();
16550 return result;
16551 }
16552
16553 template <typename node_type,
16554 typename T1, typename T2,
16555 typename T3, typename T4,
16556 typename T5, typename T6, typename T7>
16558 T3 t3, T4 t4,
16559 T5 t5, T6 t6,
16560 T7 t7) const
16561 {
16563 result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
16564 result->node_depth();
16565 return result;
16566 }
16567
16568 template <typename T>
16569 void inline free(expression_node<T>*& e) const
16570 {
16571 exprtk_debug(("node_allocator::free() - deleting expression_node "
16572 "type: %03d addr: %p\n",
16573 static_cast<int>(e->type()),
16574 reinterpret_cast<void*>(e)));
16575 delete e;
16576 e = 0;
16577 }
16578 };
16579
16580 inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
16581 {
16582 #define register_op(Symbol,Type,Args) \
16583 m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
16584
16585 register_op( "abs", e_abs , 1)
16586 register_op( "acos", e_acos , 1)
16587 register_op( "acosh", e_acosh , 1)
16588 register_op( "asin", e_asin , 1)
16589 register_op( "asinh", e_asinh , 1)
16590 register_op( "atan", e_atan , 1)
16591 register_op( "atanh", e_atanh , 1)
16592 register_op( "ceil", e_ceil , 1)
16593 register_op( "cos", e_cos , 1)
16594 register_op( "cosh", e_cosh , 1)
16595 register_op( "exp", e_exp , 1)
16596 register_op( "expm1", e_expm1 , 1)
16597 register_op( "floor", e_floor , 1)
16598 register_op( "log", e_log , 1)
16599 register_op( "log10", e_log10 , 1)
16600 register_op( "log2", e_log2 , 1)
16601 register_op( "log1p", e_log1p , 1)
16602 register_op( "round", e_round , 1)
16603 register_op( "sin", e_sin , 1)
16604 register_op( "sinc", e_sinc , 1)
16605 register_op( "sinh", e_sinh , 1)
16606 register_op( "sec", e_sec , 1)
16607 register_op( "csc", e_csc , 1)
16608 register_op( "sqrt", e_sqrt , 1)
16609 register_op( "tan", e_tan , 1)
16610 register_op( "tanh", e_tanh , 1)
16611 register_op( "cot", e_cot , 1)
16612 register_op( "rad2deg", e_r2d , 1)
16613 register_op( "deg2rad", e_d2r , 1)
16614 register_op( "deg2grad", e_d2g , 1)
16615 register_op( "grad2deg", e_g2d , 1)
16616 register_op( "sgn", e_sgn , 1)
16617 register_op( "not", e_notl , 1)
16618 register_op( "erf", e_erf , 1)
16619 register_op( "erfc", e_erfc , 1)
16620 register_op( "ncdf", e_ncdf , 1)
16621 register_op( "frac", e_frac , 1)
16622 register_op( "trunc", e_trunc , 1)
16623 register_op( "atan2", e_atan2 , 2)
16624 register_op( "mod", e_mod , 2)
16625 register_op( "logn", e_logn , 2)
16626 register_op( "pow", e_pow , 2)
16627 register_op( "root", e_root , 2)
16628 register_op( "roundn", e_roundn , 2)
16629 register_op( "equal", e_equal , 2)
16630 register_op("not_equal", e_nequal , 2)
16631 register_op( "hypot", e_hypot , 2)
16632 register_op( "shr", e_shr , 2)
16633 register_op( "shl", e_shl , 2)
16634 register_op( "clamp", e_clamp , 3)
16635 register_op( "iclamp", e_iclamp , 3)
16636 register_op( "inrange", e_inrange , 3)
16637 #undef register_op
16638 }
16639
16640 } // namespace details
16641
16643 {
16644 public:
16645
16647 : allow_zero_parameters_(false),
16648 has_side_effects_(true),
16649 min_num_args_(0),
16650 max_num_args_(std::numeric_limits<std::size_t>::max())
16651 {}
16652
16654 {
16655 return allow_zero_parameters_;
16656 }
16657
16658 inline bool& has_side_effects()
16659 {
16660 return has_side_effects_;
16661 }
16662
16663 std::size_t& min_num_args()
16664 {
16665 return min_num_args_;
16666 }
16667
16668 std::size_t& max_num_args()
16669 {
16670 return max_num_args_;
16671 }
16672
16673 private:
16674
16675 bool allow_zero_parameters_;
16676 bool has_side_effects_;
16677 std::size_t min_num_args_;
16678 std::size_t max_num_args_;
16679 };
16680
16681 template <typename FunctionType>
16682 void enable_zero_parameters(FunctionType& func)
16683 {
16684 func.allow_zero_parameters() = true;
16685
16686 if (0 != func.min_num_args())
16687 {
16688 func.min_num_args() = 0;
16689 }
16690 }
16691
16692 template <typename FunctionType>
16693 void disable_zero_parameters(FunctionType& func)
16694 {
16695 func.allow_zero_parameters() = false;
16696 }
16697
16698 template <typename FunctionType>
16699 void enable_has_side_effects(FunctionType& func)
16700 {
16701 func.has_side_effects() = true;
16702 }
16703
16704 template <typename FunctionType>
16705 void disable_has_side_effects(FunctionType& func)
16706 {
16707 func.has_side_effects() = false;
16708 }
16709
16710 template <typename FunctionType>
16711 void set_min_num_args(FunctionType& func, const std::size_t& num_args)
16712 {
16713 func.min_num_args() = num_args;
16714
16715 if ((0 != func.min_num_args()) && func.allow_zero_parameters())
16716 func.allow_zero_parameters() = false;
16717 }
16718
16719 template <typename FunctionType>
16720 void set_max_num_args(FunctionType& func, const std::size_t& num_args)
16721 {
16722 func.max_num_args() = num_args;
16723 }
16724
16725 template <typename T>
16727 {
16728 public:
16729
16730 explicit ifunction(const std::size_t& pc)
16731 : param_count(pc)
16732 {}
16733
16734 virtual ~ifunction()
16735 {}
16736
16737 #define empty_method_body(N) \
16738 { \
16739 exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
16740 return std::numeric_limits<T>::quiet_NaN(); \
16741 } \
16742
16743 inline virtual T operator() ()
16745
16746 inline virtual T operator() (const T&)
16748
16749 inline virtual T operator() (const T&,const T&)
16751
16752 inline virtual T operator() (const T&, const T&, const T&)
16754
16755 inline virtual T operator() (const T&, const T&, const T&, const T&)
16757
16758 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16760
16761 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16763
16764 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16766
16767 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16769
16770 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16772
16773 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16775
16776 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16777 const T&)
16779
16780 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16781 const T&, const T&)
16783
16784 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16785 const T&, const T&, const T&)
16787
16788 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16789 const T&, const T&, const T&, const T&)
16791
16792 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16793 const T&, const T&, const T&, const T&, const T&)
16795
16796 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16797 const T&, const T&, const T&, const T&, const T&, const T&)
16799
16800 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16801 const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16803
16804 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16805 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16807
16808 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16809 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16811
16812 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16813 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16815
16816 #undef empty_method_body
16817
16818 std::size_t param_count;
16819 };
16820
16821 template <typename T>
16823 {
16824 public:
16825
16827 {}
16828
16829 inline virtual T operator() (const std::vector<T>&)
16830 {
16831 exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
16832 return std::numeric_limits<T>::quiet_NaN();
16833 }
16834 };
16835
16836 template <typename T>
16838 {
16839 public:
16840
16842 {
16845 e_rtrn_overload = 2
16847
16848 typedef T type;
16851
16852 igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16853 : parameter_sequence(param_seq),
16854 rtrn_type(rtr_type)
16855 {}
16856
16858 {}
16859
16860 #define igeneric_function_empty_body(N) \
16861 { \
16862 exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
16863 return std::numeric_limits<T>::quiet_NaN(); \
16864 } \
16865
16866 // f(i_0,i_1,....,i_N) --> Scalar
16867 inline virtual T operator() (parameter_list_t)
16869
16870 // f(i_0,i_1,....,i_N) --> String
16871 inline virtual T operator() (std::string&, parameter_list_t)
16873
16874 // f(psi,i_0,i_1,....,i_N) --> Scalar
16875 inline virtual T operator() (const std::size_t&, parameter_list_t)
16877
16878 // f(psi,i_0,i_1,....,i_N) --> String
16879 inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16881
16882 std::string parameter_sequence;
16884 };
16885
16886 template <typename T> class parser;
16887 template <typename T> class expression_helper;
16888
16889 template <typename T>
16891 {
16892 public:
16893
16894 typedef T (*ff00_functor)();
16895 typedef T (*ff01_functor)(T);
16896 typedef T (*ff02_functor)(T, T);
16897 typedef T (*ff03_functor)(T, T, T);
16898 typedef T (*ff04_functor)(T, T, T, T);
16899 typedef T (*ff05_functor)(T, T, T, T, T);
16900 typedef T (*ff06_functor)(T, T, T, T, T, T);
16901 typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16902 typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16903 typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16904 typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16905 typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16906 typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16907 typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16908 typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16909 typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16910
16911 protected:
16912
16914 {
16915 using exprtk::ifunction<T>::operator();
16916
16917 explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
16918 inline T operator() ()
16919 { return f(); }
16920 ff00_functor f;
16921 };
16922
16924 {
16925 using exprtk::ifunction<T>::operator();
16926
16927 explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
16928 inline T operator() (const T& v0)
16929 { return f(v0); }
16930 ff01_functor f;
16931 };
16932
16934 {
16935 using exprtk::ifunction<T>::operator();
16936
16937 explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
16938 inline T operator() (const T& v0, const T& v1)
16939 { return f(v0, v1); }
16940 ff02_functor f;
16941 };
16942
16944 {
16945 using exprtk::ifunction<T>::operator();
16946
16947 explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
16948 inline T operator() (const T& v0, const T& v1, const T& v2)
16949 { return f(v0, v1, v2); }
16950 ff03_functor f;
16951 };
16952
16954 {
16955 using exprtk::ifunction<T>::operator();
16956
16957 explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
16958 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16959 { return f(v0, v1, v2, v3); }
16960 ff04_functor f;
16961 };
16962
16964 {
16965 using exprtk::ifunction<T>::operator();
16966
16967 explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
16968 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16969 { return f(v0, v1, v2, v3, v4); }
16970 ff05_functor f;
16971 };
16972
16974 {
16975 using exprtk::ifunction<T>::operator();
16976
16977 explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
16978 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16979 { return f(v0, v1, v2, v3, v4, v5); }
16980 ff06_functor f;
16981 };
16982
16984 {
16985 using exprtk::ifunction<T>::operator();
16986
16987 explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
16988 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16989 const T& v5, const T& v6)
16990 { return f(v0, v1, v2, v3, v4, v5, v6); }
16991 ff07_functor f;
16992 };
16993
16995 {
16996 using exprtk::ifunction<T>::operator();
16997
16998 explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
16999 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17000 const T& v5, const T& v6, const T& v7)
17001 { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
17002 ff08_functor f;
17003 };
17004
17006 {
17007 using exprtk::ifunction<T>::operator();
17008
17009 explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
17010 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17011 const T& v5, const T& v6, const T& v7, const T& v8)
17012 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
17013 ff09_functor f;
17014 };
17015
17017 {
17018 using exprtk::ifunction<T>::operator();
17019
17020 explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
17021 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17022 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
17023 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
17024 ff10_functor f;
17025 };
17026
17028 {
17029 using exprtk::ifunction<T>::operator();
17030
17031 explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
17032 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17033 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
17034 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
17035 ff11_functor f;
17036 };
17037
17039 {
17040 using exprtk::ifunction<T>::operator();
17041
17042 explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
17043 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17044 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17045 const T& v10, const T& v11)
17046 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
17047 ff12_functor f;
17048 };
17049
17051 {
17052 using exprtk::ifunction<T>::operator();
17053
17054 explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
17055 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17056 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17057 const T& v10, const T& v11, const T& v12)
17058 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
17059 ff13_functor f;
17060 };
17061
17063 {
17064 using exprtk::ifunction<T>::operator();
17065
17066 explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
17067 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17068 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17069 const T& v10, const T& v11, const T& v12, const T& v13)
17070 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
17071 ff14_functor f;
17072 };
17073
17075 {
17076 using exprtk::ifunction<T>::operator();
17077
17078 explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
17079 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17080 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17081 const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
17082 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
17083 ff15_functor f;
17084 };
17085
17086 template <typename Type, typename RawType>
17088 {
17095 #ifndef exprtk_disable_string_capabilities
17097 #endif
17098
17099 typedef Type type_t;
17101 typedef std::pair<bool,type_ptr> type_pair_t;
17102 typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
17103 typedef typename type_map_t::iterator tm_itr_t;
17104 typedef typename type_map_t::const_iterator tm_const_itr_t;
17105
17106 enum { lut_size = 256 };
17107
17109 std::size_t size;
17110
17112 : size(0)
17113 {}
17114
17115 struct deleter
17116 {
17117 #define exprtk_define_process(Type) \
17118 static inline void process(std::pair<bool,Type*>& n) \
17119 { \
17120 delete n.second; \
17121 } \
17122
17125 #ifndef exprtk_disable_string_capabilities
17127 #endif
17128
17129 #undef exprtk_define_process
17130
17131 template <typename DeleteType>
17132 static inline void process(std::pair<bool,DeleteType*>&)
17133 {}
17134 };
17135
17136 inline bool symbol_exists(const std::string& symbol_name) const
17137 {
17138 if (symbol_name.empty())
17139 return false;
17140 else if (map.end() != map.find(symbol_name))
17141 return true;
17142 else
17143 return false;
17144 }
17145
17146 template <typename PtrType>
17147 inline std::string entity_name(const PtrType& ptr) const
17148 {
17149 if (map.empty())
17150 return std::string();
17151
17152 tm_const_itr_t itr = map.begin();
17153
17154 while (map.end() != itr)
17155 {
17156 if (itr->second.second == ptr)
17157 {
17158 return itr->first;
17159 }
17160 else
17161 ++itr;
17162 }
17163
17164 return std::string();
17165 }
17166
17167 inline bool is_constant(const std::string& symbol_name) const
17168 {
17169 if (symbol_name.empty())
17170 return false;
17171 else
17172 {
17173 const tm_const_itr_t itr = map.find(symbol_name);
17174
17175 if (map.end() == itr)
17176 return false;
17177 else
17178 return (*itr).second.first;
17179 }
17180 }
17181
17182 template <typename Tie, typename RType>
17183 inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
17184 {
17185 if (symbol_name.size() > 1)
17186 {
17187 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
17188 {
17189 if (details::imatch(symbol_name, details::reserved_symbols[i]))
17190 {
17191 return false;
17192 }
17193 }
17194 }
17195
17196 const tm_itr_t itr = map.find(symbol_name);
17197
17198 if (map.end() == itr)
17199 {
17200 map[symbol_name] = Tie::make(t,is_const);
17201 ++size;
17202 }
17203
17204 return true;
17205 }
17206
17208 {
17209 static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
17210 {
17211 return std::make_pair(is_const, new vector_t(v.first, v.second));
17212 }
17213 };
17214
17216 {
17217 template <typename Allocator>
17218 static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
17219 {
17220 return std::make_pair(is_const, new vector_t(v));
17221 }
17222 };
17223
17225 {
17226 static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
17227 {
17228 return std::make_pair(is_const, new vector_t(v));
17229 }
17230 };
17231
17233 {
17234 template <typename Allocator>
17235 static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
17236 {
17237 return std::make_pair(is_const, new vector_t(v));
17238 }
17239 };
17240
17241 template <std::size_t v_size>
17242 inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
17243 {
17244 return add_impl<tie_array,std::pair<T*,std::size_t> >
17245 (symbol_name, std::make_pair(v,v_size), is_const);
17246 }
17247
17248 inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
17249 {
17250 return add_impl<tie_array,std::pair<T*,std::size_t> >
17251 (symbol_name, std::make_pair(v,v_size), is_const);
17252 }
17253
17254 template <typename Allocator>
17255 inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
17256 {
17257 return add_impl<tie_stdvec,std::vector<T,Allocator>&>
17258 (symbol_name, v, is_const);
17259 }
17260
17261 inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
17262 {
17263 return add_impl<tie_vecview,exprtk::vector_view<T>&>
17264 (symbol_name, v, is_const);
17265 }
17266
17267 template <typename Allocator>
17268 inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
17269 {
17270 return add_impl<tie_stddeq,std::deque<T,Allocator>&>
17271 (symbol_name, v, is_const);
17272 }
17273
17274 inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
17275 {
17276 struct tie
17277 {
17278 static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
17279 {
17280 return std::make_pair(is_const, new variable_node_t(t));
17281 }
17282
17283 #ifndef exprtk_disable_string_capabilities
17284 static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
17285 {
17286 return std::make_pair(is_const, new stringvar_node_t(t));
17287 }
17288 #endif
17289
17290 static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
17291 {
17292 return std::make_pair(is_constant,&t);
17293 }
17294
17295 static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
17296 {
17297 return std::make_pair(is_const,&t);
17298 }
17299
17300 static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
17301 {
17302 return std::make_pair(is_constant,&t);
17303 }
17304 };
17305
17306 const tm_itr_t itr = map.find(symbol_name);
17307
17308 if (map.end() == itr)
17309 {
17310 map[symbol_name] = tie::make(t,is_const);
17311 ++size;
17312 }
17313
17314 return true;
17315 }
17316
17317 inline type_ptr get(const std::string& symbol_name) const
17318 {
17319 const tm_const_itr_t itr = map.find(symbol_name);
17320
17321 if (map.end() == itr)
17322 return reinterpret_cast<type_ptr>(0);
17323 else
17324 return itr->second.second;
17325 }
17326
17327 template <typename TType, typename TRawType, typename PtrType>
17329 {
17330 static inline bool test(const PtrType, const void*)
17331 {
17332 return false;
17333 }
17334 };
17335
17336 template <typename TType, typename TRawType>
17337 struct ptr_match<TType,TRawType,variable_node_t*>
17338 {
17339 static inline bool test(const variable_node_t* p, const void* ptr)
17340 {
17341 exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
17342 return (&(p->ref()) == ptr);
17343 }
17344 };
17345
17346 inline type_ptr get_from_varptr(const void* ptr) const
17347 {
17348 tm_const_itr_t itr = map.begin();
17349
17350 while (map.end() != itr)
17351 {
17352 type_ptr ret_ptr = itr->second.second;
17353
17355 {
17356 return ret_ptr;
17357 }
17358
17359 ++itr;
17360 }
17361
17362 return type_ptr(0);
17363 }
17364
17365 inline bool remove(const std::string& symbol_name, const bool delete_node = true)
17366 {
17367 const tm_itr_t itr = map.find(symbol_name);
17368
17369 if (map.end() != itr)
17370 {
17371 if (delete_node)
17372 {
17373 deleter::process((*itr).second);
17374 }
17375
17376 map.erase(itr);
17377 --size;
17378
17379 return true;
17380 }
17381 else
17382 return false;
17383 }
17384
17385 inline RawType& type_ref(const std::string& symbol_name)
17386 {
17387 struct init_type
17388 {
17389 static inline double set(double) { return (0.0); }
17390 static inline double set(long double) { return (0.0); }
17391 static inline float set(float) { return (0.0f); }
17392 static inline std::string set(std::string) { return std::string(""); }
17393 };
17394
17395 static RawType null_type = init_type::set(RawType());
17396
17397 const tm_const_itr_t itr = map.find(symbol_name);
17398
17399 if (map.end() == itr)
17400 return null_type;
17401 else
17402 return itr->second.second->ref();
17403 }
17404
17405 inline void clear(const bool delete_node = true)
17406 {
17407 if (!map.empty())
17408 {
17409 if (delete_node)
17410 {
17411 tm_itr_t itr = map.begin();
17412 tm_itr_t end = map.end ();
17413
17414 while (end != itr)
17415 {
17416 deleter::process((*itr).second);
17417 ++itr;
17418 }
17419 }
17420
17421 map.clear();
17422 }
17423
17424 size = 0;
17425 }
17426
17427 template <typename Allocator,
17428 template <typename, typename> class Sequence>
17429 inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
17430 {
17431 std::size_t count = 0;
17432
17433 if (!map.empty())
17434 {
17435 tm_const_itr_t itr = map.begin();
17436 tm_const_itr_t end = map.end ();
17437
17438 while (end != itr)
17439 {
17440 list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
17441 ++itr;
17442 ++count;
17443 }
17444 }
17445
17446 return count;
17447 }
17448
17449 template <typename Allocator,
17450 template <typename, typename> class Sequence>
17451 inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
17452 {
17453 std::size_t count = 0;
17454
17455 if (!map.empty())
17456 {
17457 tm_const_itr_t itr = map.begin();
17458 tm_const_itr_t end = map.end ();
17459
17460 while (end != itr)
17461 {
17462 vlist.push_back((*itr).first);
17463 ++itr;
17464 ++count;
17465 }
17466 }
17467
17468 return count;
17469 }
17470 };
17471
17476 #ifndef exprtk_disable_string_capabilities
17479 #endif
17486
17487 static const std::size_t lut_size = 256;
17488
17489 // Symbol Table Holder
17491 {
17492 struct st_data
17493 {
17501 #ifndef exprtk_disable_string_capabilities
17503 #endif
17504
17506 {
17507 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
17508 {
17509 reserved_symbol_table_.insert(details::reserved_words[i]);
17510 }
17511
17512 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
17513 {
17514 reserved_symbol_table_.insert(details::reserved_symbols[i]);
17515 }
17516 }
17517
17519 {
17520 for (std::size_t i = 0; i < free_function_list_.size(); ++i)
17521 {
17522 delete free_function_list_[i];
17523 }
17524 }
17525
17526 inline bool is_reserved_symbol(const std::string& symbol) const
17527 {
17528 return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
17529 }
17530
17531 static inline st_data* create()
17532 {
17533 return (new st_data);
17534 }
17535
17536 static inline void destroy(st_data*& sd)
17537 {
17538 delete sd;
17539 sd = reinterpret_cast<st_data*>(0);
17540 }
17541
17543 std::list<std::string> local_stringvar_list_;
17544 std::set<std::string> reserved_symbol_table_;
17545 std::vector<ifunction<T>*> free_function_list_;
17546 };
17547
17549 : ref_count(1),
17550 data_(st_data::create())
17551 {}
17552
17554 : ref_count(1),
17555 data_(data)
17556 {}
17557
17559 {
17560 if (data_ && (0 == ref_count))
17561 {
17562 st_data::destroy(data_);
17563 }
17564 }
17565
17566 static inline control_block* create()
17567 {
17568 return (new control_block);
17569 }
17570
17571 template <typename SymTab>
17572 static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
17573 {
17574 if (cntrl_blck)
17575 {
17576 if (
17577 (0 != cntrl_blck->ref_count) &&
17578 (0 == --cntrl_blck->ref_count)
17579 )
17580 {
17581 if (sym_tab)
17582 sym_tab->clear();
17583
17584 delete cntrl_blck;
17585 }
17586
17587 cntrl_blck = 0;
17588 }
17589 }
17590
17591 std::size_t ref_count;
17593 };
17594
17595 public:
17596
17598 : control_block_(control_block::create())
17599 {
17600 clear();
17601 }
17602
17604 {
17605 control_block::destroy(control_block_,this);
17606 }
17607
17609 {
17610 control_block_ = st.control_block_;
17611 control_block_->ref_count++;
17612 }
17613
17615 {
17616 if (this != &st)
17617 {
17618 control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
17619
17620 control_block_ = st.control_block_;
17621 control_block_->ref_count++;
17622 }
17623
17624 return (*this);
17625 }
17626
17627 inline bool operator==(const symbol_table<T>& st) const
17628 {
17629 return (this == &st) || (control_block_ == st.control_block_);
17630 }
17631
17632 inline void clear_variables(const bool delete_node = true)
17633 {
17634 local_data().variable_store.clear(delete_node);
17635 }
17636
17637 inline void clear_functions()
17638 {
17639 local_data().function_store.clear();
17640 }
17641
17642 inline void clear_strings()
17643 {
17644 #ifndef exprtk_disable_string_capabilities
17645 local_data().stringvar_store.clear();
17646 #endif
17647 }
17648
17649 inline void clear_vectors()
17650 {
17651 local_data().vector_store.clear();
17652 }
17653
17655 {
17656 local_data().local_symbol_list_.clear();
17657 }
17658
17659 inline void clear()
17660 {
17661 if (!valid()) return;
17662 clear_variables ();
17663 clear_functions ();
17664 clear_strings ();
17665 clear_vectors ();
17666 clear_local_constants();
17667 }
17668
17669 inline std::size_t variable_count() const
17670 {
17671 if (valid())
17672 return local_data().variable_store.size;
17673 else
17674 return 0;
17675 }
17676
17677 #ifndef exprtk_disable_string_capabilities
17678 inline std::size_t stringvar_count() const
17679 {
17680 if (valid())
17681 return local_data().stringvar_store.size;
17682 else
17683 return 0;
17684 }
17685 #endif
17686
17687 inline std::size_t function_count() const
17688 {
17689 if (valid())
17690 return local_data().function_store.size;
17691 else
17692 return 0;
17693 }
17694
17695 inline std::size_t vector_count() const
17696 {
17697 if (valid())
17698 return local_data().vector_store.size;
17699 else
17700 return 0;
17701 }
17702
17703 inline variable_ptr get_variable(const std::string& variable_name) const
17704 {
17705 if (!valid())
17706 return reinterpret_cast<variable_ptr>(0);
17707 else if (!valid_symbol(variable_name))
17708 return reinterpret_cast<variable_ptr>(0);
17709 else
17710 return local_data().variable_store.get(variable_name);
17711 }
17712
17713 inline variable_ptr get_variable(const T& var_ref) const
17714 {
17715 if (!valid())
17716 return reinterpret_cast<variable_ptr>(0);
17717 else
17718 return local_data().variable_store.get_from_varptr(
17719 reinterpret_cast<const void*>(&var_ref));
17720 }
17721
17722 #ifndef exprtk_disable_string_capabilities
17723 inline stringvar_ptr get_stringvar(const std::string& string_name) const
17724 {
17725 if (!valid())
17726 return reinterpret_cast<stringvar_ptr>(0);
17727 else if (!valid_symbol(string_name))
17728 return reinterpret_cast<stringvar_ptr>(0);
17729 else
17730 return local_data().stringvar_store.get(string_name);
17731 }
17732 #endif
17733
17734 inline function_ptr get_function(const std::string& function_name) const
17735 {
17736 if (!valid())
17737 return reinterpret_cast<function_ptr>(0);
17738 else if (!valid_symbol(function_name))
17739 return reinterpret_cast<function_ptr>(0);
17740 else
17741 return local_data().function_store.get(function_name);
17742 }
17743
17744 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
17745 {
17746 if (!valid())
17747 return reinterpret_cast<vararg_function_ptr>(0);
17748 else if (!valid_symbol(vararg_function_name))
17749 return reinterpret_cast<vararg_function_ptr>(0);
17750 else
17751 return local_data().vararg_function_store.get(vararg_function_name);
17752 }
17753
17754 inline generic_function_ptr get_generic_function(const std::string& function_name) const
17755 {
17756 if (!valid())
17757 return reinterpret_cast<generic_function_ptr>(0);
17758 else if (!valid_symbol(function_name))
17759 return reinterpret_cast<generic_function_ptr>(0);
17760 else
17761 return local_data().generic_function_store.get(function_name);
17762 }
17763
17764 inline generic_function_ptr get_string_function(const std::string& function_name) const
17765 {
17766 if (!valid())
17767 return reinterpret_cast<generic_function_ptr>(0);
17768 else if (!valid_symbol(function_name))
17769 return reinterpret_cast<generic_function_ptr>(0);
17770 else
17771 return local_data().string_function_store.get(function_name);
17772 }
17773
17774 inline generic_function_ptr get_overload_function(const std::string& function_name) const
17775 {
17776 if (!valid())
17777 return reinterpret_cast<generic_function_ptr>(0);
17778 else if (!valid_symbol(function_name))
17779 return reinterpret_cast<generic_function_ptr>(0);
17780 else
17781 return local_data().overload_function_store.get(function_name);
17782 }
17783
17785
17786 inline vector_holder_ptr get_vector(const std::string& vector_name) const
17787 {
17788 if (!valid())
17789 return reinterpret_cast<vector_holder_ptr>(0);
17790 else if (!valid_symbol(vector_name))
17791 return reinterpret_cast<vector_holder_ptr>(0);
17792 else
17793 return local_data().vector_store.get(vector_name);
17794 }
17795
17796 inline T& variable_ref(const std::string& symbol_name)
17797 {
17798 static T null_var = T(0);
17799 if (!valid())
17800 return null_var;
17801 else if (!valid_symbol(symbol_name))
17802 return null_var;
17803 else
17804 return local_data().variable_store.type_ref(symbol_name);
17805 }
17806
17807 #ifndef exprtk_disable_string_capabilities
17808 inline std::string& stringvar_ref(const std::string& symbol_name)
17809 {
17810 static std::string null_stringvar;
17811 if (!valid())
17812 return null_stringvar;
17813 else if (!valid_symbol(symbol_name))
17814 return null_stringvar;
17815 else
17816 return local_data().stringvar_store.type_ref(symbol_name);
17817 }
17818 #endif
17819
17820 inline bool is_constant_node(const std::string& symbol_name) const
17821 {
17822 if (!valid())
17823 return false;
17824 else if (!valid_symbol(symbol_name))
17825 return false;
17826 else
17827 return local_data().variable_store.is_constant(symbol_name);
17828 }
17829
17830 #ifndef exprtk_disable_string_capabilities
17831 inline bool is_constant_string(const std::string& symbol_name) const
17832 {
17833 if (!valid())
17834 return false;
17835 else if (!valid_symbol(symbol_name))
17836 return false;
17837 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17838 return false;
17839 else
17840 return local_data().stringvar_store.is_constant(symbol_name);
17841 }
17842 #endif
17843
17844 inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17845 {
17846 if (!valid())
17847 return false;
17848 else if (!valid_symbol(variable_name))
17849 return false;
17850 else if (symbol_exists(variable_name))
17851 return false;
17852
17853 local_data().local_symbol_list_.push_back(value);
17854 T& t = local_data().local_symbol_list_.back();
17855
17856 return add_variable(variable_name,t);
17857 }
17858
17859 #ifndef exprtk_disable_string_capabilities
17860 inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17861 {
17862 if (!valid())
17863 return false;
17864 else if (!valid_symbol(stringvar_name))
17865 return false;
17866 else if (symbol_exists(stringvar_name))
17867 return false;
17868
17869 local_data().local_stringvar_list_.push_back(value);
17870 std::string& s = local_data().local_stringvar_list_.back();
17871
17872 return add_stringvar(stringvar_name,s);
17873 }
17874 #endif
17875
17876 inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17877 {
17878 if (!valid())
17879 return false;
17880 else if (!valid_symbol(variable_name))
17881 return false;
17882 else if (symbol_exists(variable_name))
17883 return false;
17884 else
17885 return local_data().variable_store.add(variable_name, t, is_constant);
17886 }
17887
17888 inline bool add_constant(const std::string& constant_name, const T& value)
17889 {
17890 if (!valid())
17891 return false;
17892 else if (!valid_symbol(constant_name))
17893 return false;
17894 else if (symbol_exists(constant_name))
17895 return false;
17896
17897 local_data().local_symbol_list_.push_back(value);
17898 T& t = local_data().local_symbol_list_.back();
17899
17900 return add_variable(constant_name, t, true);
17901 }
17902
17903 #ifndef exprtk_disable_string_capabilities
17904 inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17905 {
17906 if (!valid())
17907 return false;
17908 else if (!valid_symbol(stringvar_name))
17909 return false;
17910 else if (symbol_exists(stringvar_name))
17911 return false;
17912 else
17913 return local_data().stringvar_store.add(stringvar_name, s, is_constant);
17914 }
17915 #endif
17916
17917 inline bool add_function(const std::string& function_name, function_t& function)
17918 {
17919 if (!valid())
17920 return false;
17921 else if (!valid_symbol(function_name))
17922 return false;
17923 else if (symbol_exists(function_name))
17924 return false;
17925 else
17926 return local_data().function_store.add(function_name,function);
17927 }
17928
17929 inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17930 {
17931 if (!valid())
17932 return false;
17933 else if (!valid_symbol(vararg_function_name))
17934 return false;
17935 else if (symbol_exists(vararg_function_name))
17936 return false;
17937 else
17938 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17939 }
17940
17941 inline bool add_function(const std::string& function_name, generic_function_t& function)
17942 {
17943 if (!valid())
17944 return false;
17945 else if (!valid_symbol(function_name))
17946 return false;
17947 else if (symbol_exists(function_name))
17948 return false;
17949 else
17950 {
17951 switch (function.rtrn_type)
17952 {
17953 case generic_function_t::e_rtrn_scalar :
17954 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
17955 local_data().generic_function_store.add(function_name,function) : false;
17956
17957 case generic_function_t::e_rtrn_string :
17958 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
17959 local_data().string_function_store.add(function_name,function) : false;
17960
17961 case generic_function_t::e_rtrn_overload :
17962 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
17963 local_data().overload_function_store.add(function_name,function) : false;
17964 }
17965 }
17966
17967 return false;
17968 }
17969
17970 #define exprtk_define_freefunction(NN) \
17971 inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17972 { \
17973 if (!valid()) \
17974 { return false; } \
17975 if (!valid_symbol(function_name)) \
17976 { return false; } \
17977 if (symbol_exists(function_name)) \
17978 { return false; } \
17979 \
17980 exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
17981 \
17982 local_data().free_function_list_.push_back(ifunc); \
17983 \
17984 return add_function(function_name,(*local_data().free_function_list_.back())); \
17985 } \
17986
17995
17996 #undef exprtk_define_freefunction
17997
17998 inline bool add_reserved_function(const std::string& function_name, function_t& function)
17999 {
18000 if (!valid())
18001 return false;
18002 else if (!valid_symbol(function_name,false))
18003 return false;
18004 else if (symbol_exists(function_name,false))
18005 return false;
18006 else
18007 return local_data().function_store.add(function_name,function);
18008 }
18009
18010 inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
18011 {
18012 if (!valid())
18013 return false;
18014 else if (!valid_symbol(vararg_function_name,false))
18015 return false;
18016 else if (symbol_exists(vararg_function_name,false))
18017 return false;
18018 else
18019 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
18020 }
18021
18023 {
18024 if (!valid())
18025 return false;
18026 else if (!valid_symbol(function_name,false))
18027 return false;
18028 else if (symbol_exists(function_name,false))
18029 return false;
18030 else
18031 {
18032 switch (function.rtrn_type)
18033 {
18034 case generic_function_t::e_rtrn_scalar :
18035 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
18036 local_data().generic_function_store.add(function_name,function) : false;
18037
18038 case generic_function_t::e_rtrn_string :
18039 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
18040 local_data().string_function_store.add(function_name,function) : false;
18041
18042 case generic_function_t::e_rtrn_overload :
18043 return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
18044 local_data().overload_function_store.add(function_name,function) : false;
18045 }
18046 }
18047
18048 return false;
18049 }
18050
18051 template <std::size_t N>
18052 inline bool add_vector(const std::string& vector_name, T (&v)[N])
18053 {
18054 if (!valid())
18055 return false;
18056 else if (!valid_symbol(vector_name))
18057 return false;
18058 else if (symbol_exists(vector_name))
18059 return false;
18060 else
18061 return local_data().vector_store.add(vector_name,v);
18062 }
18063
18064 inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
18065 {
18066 if (!valid())
18067 return false;
18068 else if (!valid_symbol(vector_name))
18069 return false;
18070 else if (symbol_exists(vector_name))
18071 return false;
18072 else if (0 == v_size)
18073 return false;
18074 else
18075 return local_data().vector_store.add(vector_name, v, v_size);
18076 }
18077
18078 template <typename Allocator>
18079 inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
18080 {
18081 if (!valid())
18082 return false;
18083 else if (!valid_symbol(vector_name))
18084 return false;
18085 else if (symbol_exists(vector_name))
18086 return false;
18087 else if (0 == v.size())
18088 return false;
18089 else
18090 return local_data().vector_store.add(vector_name,v);
18091 }
18092
18093 inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
18094 {
18095 if (!valid())
18096 return false;
18097 else if (!valid_symbol(vector_name))
18098 return false;
18099 else if (symbol_exists(vector_name))
18100 return false;
18101 else if (0 == v.size())
18102 return false;
18103 else
18104 return local_data().vector_store.add(vector_name,v);
18105 }
18106
18107 inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
18108 {
18109 if (!valid())
18110 return false;
18111 else
18112 return local_data().variable_store.remove(variable_name, delete_node);
18113 }
18114
18115 #ifndef exprtk_disable_string_capabilities
18116 inline bool remove_stringvar(const std::string& string_name)
18117 {
18118 if (!valid())
18119 return false;
18120 else
18121 return local_data().stringvar_store.remove(string_name);
18122 }
18123 #endif
18124
18125 inline bool remove_function(const std::string& function_name)
18126 {
18127 if (!valid())
18128 return false;
18129 else
18130 return local_data().function_store.remove(function_name);
18131 }
18132
18133 inline bool remove_vararg_function(const std::string& vararg_function_name)
18134 {
18135 if (!valid())
18136 return false;
18137 else
18138 return local_data().vararg_function_store.remove(vararg_function_name);
18139 }
18140
18141 inline bool remove_vector(const std::string& vector_name)
18142 {
18143 if (!valid())
18144 return false;
18145 else
18146 return local_data().vector_store.remove(vector_name);
18147 }
18148
18149 inline bool add_constants()
18150 {
18151 return add_pi () &&
18152 add_epsilon () &&
18153 add_infinity() ;
18154 }
18155
18156 inline bool add_pi()
18157 {
18159 static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
18160 return add_constant("pi",local_pi);
18161 }
18162
18163 inline bool add_epsilon()
18164 {
18165 static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
18166 return add_constant("epsilon",local_epsilon);
18167 }
18168
18169 inline bool add_infinity()
18170 {
18171 static const T local_infinity = std::numeric_limits<T>::infinity();
18172 return add_constant("inf",local_infinity);
18173 }
18174
18175 template <typename Package>
18176 inline bool add_package(Package& package)
18177 {
18178 return package.register_package(*this);
18179 }
18180
18181 template <typename Allocator,
18182 template <typename, typename> class Sequence>
18183 inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
18184 {
18185 if (!valid())
18186 return 0;
18187 else
18188 return local_data().variable_store.get_list(vlist);
18189 }
18190
18191 template <typename Allocator,
18192 template <typename, typename> class Sequence>
18193 inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
18194 {
18195 if (!valid())
18196 return 0;
18197 else
18198 return local_data().variable_store.get_list(vlist);
18199 }
18200
18201 #ifndef exprtk_disable_string_capabilities
18202 template <typename Allocator,
18203 template <typename, typename> class Sequence>
18204 inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
18205 {
18206 if (!valid())
18207 return 0;
18208 else
18209 return local_data().stringvar_store.get_list(svlist);
18210 }
18211
18212 template <typename Allocator,
18213 template <typename, typename> class Sequence>
18214 inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
18215 {
18216 if (!valid())
18217 return 0;
18218 else
18219 return local_data().stringvar_store.get_list(svlist);
18220 }
18221 #endif
18222
18223 template <typename Allocator,
18224 template <typename, typename> class Sequence>
18225 inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
18226 {
18227 if (!valid())
18228 return 0;
18229 else
18230 return local_data().vector_store.get_list(vlist);
18231 }
18232
18233 inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
18234 {
18235 /*
18236 Function will return true if symbol_name exists as either a
18237 reserved symbol, variable, stringvar, vector or function name
18238 in any of the type stores.
18239 */
18240 if (!valid())
18241 return false;
18242 else if (local_data().variable_store.symbol_exists(symbol_name))
18243 return true;
18244 #ifndef exprtk_disable_string_capabilities
18245 else if (local_data().stringvar_store.symbol_exists(symbol_name))
18246 return true;
18247 #endif
18248 else if (local_data().vector_store.symbol_exists(symbol_name))
18249 return true;
18250 else if (local_data().function_store.symbol_exists(symbol_name))
18251 return true;
18252 else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
18253 return true;
18254 else
18255 return false;
18256 }
18257
18258 inline bool is_variable(const std::string& variable_name) const
18259 {
18260 if (!valid())
18261 return false;
18262 else
18263 return local_data().variable_store.symbol_exists(variable_name);
18264 }
18265
18266 #ifndef exprtk_disable_string_capabilities
18267 inline bool is_stringvar(const std::string& stringvar_name) const
18268 {
18269 if (!valid())
18270 return false;
18271 else
18272 return local_data().stringvar_store.symbol_exists(stringvar_name);
18273 }
18274
18275 inline bool is_conststr_stringvar(const std::string& symbol_name) const
18276 {
18277 if (!valid())
18278 return false;
18279 else if (!valid_symbol(symbol_name))
18280 return false;
18281 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
18282 return false;
18283
18284 return (
18285 local_data().stringvar_store.symbol_exists(symbol_name) ||
18286 local_data().stringvar_store.is_constant (symbol_name)
18287 );
18288 }
18289 #endif
18290
18291 inline bool is_function(const std::string& function_name) const
18292 {
18293 if (!valid())
18294 return false;
18295 else
18296 return local_data().function_store.symbol_exists(function_name);
18297 }
18298
18299 inline bool is_vararg_function(const std::string& vararg_function_name) const
18300 {
18301 if (!valid())
18302 return false;
18303 else
18304 return local_data().vararg_function_store.symbol_exists(vararg_function_name);
18305 }
18306
18307 inline bool is_vector(const std::string& vector_name) const
18308 {
18309 if (!valid())
18310 return false;
18311 else
18312 return local_data().vector_store.symbol_exists(vector_name);
18313 }
18314
18316 {
18317 return local_data().variable_store.entity_name(ptr);
18318 }
18319
18321 {
18322 return local_data().vector_store.entity_name(ptr);
18323 }
18324
18325 #ifndef exprtk_disable_string_capabilities
18327 {
18328 return local_data().stringvar_store.entity_name(ptr);
18329 }
18330
18332 {
18333 return local_data().stringvar_store.entity_name(ptr);
18334 }
18335 #endif
18336
18337 inline bool valid() const
18338 {
18339 // Symbol table sanity check.
18340 return control_block_ && control_block_->data_;
18341 }
18342
18343 inline void load_from(const symbol_table<T>& st)
18344 {
18345 {
18346 std::vector<std::string> name_list;
18347
18348 st.local_data().function_store.get_list(name_list);
18349
18350 if (!name_list.empty())
18351 {
18352 for (std::size_t i = 0; i < name_list.size(); ++i)
18353 {
18354 exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
18355 add_function(name_list[i],ifunc);
18356 }
18357 }
18358 }
18359
18360 {
18361 std::vector<std::string> name_list;
18362
18363 st.local_data().vararg_function_store.get_list(name_list);
18364
18365 if (!name_list.empty())
18366 {
18367 for (std::size_t i = 0; i < name_list.size(); ++i)
18368 {
18369 exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
18370 add_function(name_list[i],ivafunc);
18371 }
18372 }
18373 }
18374
18375 {
18376 std::vector<std::string> name_list;
18377
18378 st.local_data().generic_function_store.get_list(name_list);
18379
18380 if (!name_list.empty())
18381 {
18382 for (std::size_t i = 0; i < name_list.size(); ++i)
18383 {
18384 exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
18385 add_function(name_list[i],ifunc);
18386 }
18387 }
18388 }
18389
18390 {
18391 std::vector<std::string> name_list;
18392
18393 st.local_data().string_function_store.get_list(name_list);
18394
18395 if (!name_list.empty())
18396 {
18397 for (std::size_t i = 0; i < name_list.size(); ++i)
18398 {
18399 exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
18400 add_function(name_list[i],ifunc);
18401 }
18402 }
18403 }
18404
18405 {
18406 std::vector<std::string> name_list;
18407
18408 st.local_data().overload_function_store.get_list(name_list);
18409
18410 if (!name_list.empty())
18411 {
18412 for (std::size_t i = 0; i < name_list.size(); ++i)
18413 {
18414 exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
18415 add_function(name_list[i],ifunc);
18416 }
18417 }
18418 }
18419 }
18420
18421 private:
18422
18423 inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
18424 {
18425 if (symbol.empty())
18426 return false;
18427 else if (!details::is_letter(symbol[0]))
18428 return false;
18429 else if (symbol.size() > 1)
18430 {
18431 for (std::size_t i = 1; i < symbol.size(); ++i)
18432 {
18433 if (
18434 !details::is_letter_or_digit(symbol[i]) &&
18435 ('_' != symbol[i])
18436 )
18437 {
18438 if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
18439 continue;
18440 else
18441 return false;
18442 }
18443 }
18444 }
18445
18446 return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
18447 }
18448
18449 inline bool valid_function(const std::string& symbol) const
18450 {
18451 if (symbol.empty())
18452 return false;
18453 else if (!details::is_letter(symbol[0]))
18454 return false;
18455 else if (symbol.size() > 1)
18456 {
18457 for (std::size_t i = 1; i < symbol.size(); ++i)
18458 {
18459 if (
18460 !details::is_letter_or_digit(symbol[i]) &&
18461 ('_' != symbol[i])
18462 )
18463 {
18464 if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
18465 continue;
18466 else
18467 return false;
18468 }
18469 }
18470 }
18471
18472 return true;
18473 }
18474
18475 typedef typename control_block::st_data local_data_t;
18476
18477 inline local_data_t& local_data()
18478 {
18479 return *(control_block_->data_);
18480 }
18481
18482 inline const local_data_t& local_data() const
18483 {
18484 return *(control_block_->data_);
18485 }
18486
18487 control_block* control_block_;
18488
18489 friend class parser<T>;
18490 };
18491
18492 template <typename T>
18493 class function_compositor;
18494
18495 template <typename T>
18497 {
18498 private:
18499
18502 typedef std::vector<symbol_table<T> > symtab_list_t;
18503
18504 struct control_block
18505 {
18506 enum data_type
18507 {
18508 e_unknown ,
18509 e_expr ,
18510 e_vecholder,
18511 e_data ,
18512 e_vecdata ,
18513 e_string
18514 };
18515
18517 {
18519 : pointer(0),
18520 type(e_unknown),
18521 size(0)
18522 {}
18523
18524 data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
18525 : pointer(ptr),
18526 type(dt),
18527 size(sz)
18528 {}
18529
18530 void* pointer;
18531 data_type type;
18532 std::size_t size;
18533 };
18534
18535 typedef std::vector<data_pack> local_data_list_t;
18537
18538 control_block()
18539 : ref_count(0),
18540 expr (0),
18541 results (0),
18542 retinv_null(false),
18543 return_invoked(&retinv_null)
18544 {}
18545
18546 explicit control_block(expression_ptr e)
18547 : ref_count(1),
18548 expr (e),
18549 results (0),
18550 retinv_null(false),
18551 return_invoked(&retinv_null)
18552 {}
18553
18554 ~control_block()
18555 {
18556 if (expr && details::branch_deletable(expr))
18557 {
18558 destroy_node(expr);
18559 }
18560
18561 if (!local_data_list.empty())
18562 {
18563 for (std::size_t i = 0; i < local_data_list.size(); ++i)
18564 {
18565 switch (local_data_list[i].type)
18566 {
18567 case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
18568 break;
18569
18570 case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
18571 break;
18572
18573 case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer);
18574 break;
18575
18576 case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer);
18577 break;
18578
18579 case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer);
18580 break;
18581
18582 default : break;
18583 }
18584 }
18585 }
18586
18587 if (results)
18588 {
18589 delete results;
18590 }
18591 }
18592
18593 static inline control_block* create(expression_ptr e)
18594 {
18595 return new control_block(e);
18596 }
18597
18598 static inline void destroy(control_block*& cntrl_blck)
18599 {
18600 if (cntrl_blck)
18601 {
18602 if (
18603 (0 != cntrl_blck->ref_count) &&
18604 (0 == --cntrl_blck->ref_count)
18605 )
18606 {
18607 delete cntrl_blck;
18608 }
18609
18610 cntrl_blck = 0;
18611 }
18612 }
18613
18614 std::size_t ref_count;
18615 expression_ptr expr;
18616 local_data_list_t local_data_list;
18617 results_context_t* results;
18618 bool retinv_null;
18619 bool* return_invoked;
18620
18621 friend class function_compositor<T>;
18622 };
18623
18624 public:
18625
18627 : control_block_(0)
18628 {
18629 set_expression(new details::null_node<T>());
18630 }
18631
18633 : control_block_ (e.control_block_ ),
18634 symbol_table_list_(e.symbol_table_list_)
18635 {
18636 control_block_->ref_count++;
18637 }
18638
18640 : control_block_(0)
18641 {
18642 set_expression(new details::null_node<T>());
18643 symbol_table_list_.push_back(symbol_table);
18644 }
18645
18647 {
18648 if (this != &e)
18649 {
18650 if (control_block_)
18651 {
18652 if (
18653 (0 != control_block_->ref_count) &&
18654 (0 == --control_block_->ref_count)
18655 )
18656 {
18657 delete control_block_;
18658 }
18659
18660 control_block_ = 0;
18661 }
18662
18663 control_block_ = e.control_block_;
18664 control_block_->ref_count++;
18665 symbol_table_list_ = e.symbol_table_list_;
18666 }
18667
18668 return *this;
18669 }
18670
18671 inline bool operator==(const expression<T>& e) const
18672 {
18673 return (this == &e);
18674 }
18675
18676 inline bool operator!() const
18677 {
18678 return (
18679 (0 == control_block_ ) ||
18680 (0 == control_block_->expr)
18681 );
18682 }
18683
18685 {
18686 control_block::destroy(control_block_);
18687
18688 return (*this);
18689 }
18690
18692 {
18693 control_block::destroy(control_block_);
18694 }
18695
18696 inline T value() const
18697 {
18698 assert(control_block_ );
18699 assert(control_block_->expr);
18700
18701 return control_block_->expr->value();
18702 }
18703
18704 inline T operator() () const
18705 {
18706 return value();
18707 }
18708
18709 inline operator T() const
18710 {
18711 return value();
18712 }
18713
18714 inline operator bool() const
18715 {
18716 return details::is_true(value());
18717 }
18718
18720 {
18721 symbol_table_list_.push_back(st);
18722 }
18723
18724 inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
18725 {
18726 return symbol_table_list_[index];
18727 }
18728
18729 inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
18730 {
18731 return symbol_table_list_[index];
18732 }
18733
18735
18736 inline const results_context_t& results() const
18737 {
18738 if (control_block_->results)
18739 return (*control_block_->results);
18740 else
18741 {
18742 static const results_context_t null_results;
18743 return null_results;
18744 }
18745 }
18746
18747 inline bool return_invoked() const
18748 {
18749 return (*control_block_->return_invoked);
18750 }
18751
18752 private:
18753
18754 inline symtab_list_t get_symbol_table_list() const
18755 {
18756 return symbol_table_list_;
18757 }
18758
18759 inline void set_expression(const expression_ptr expr)
18760 {
18761 if (expr)
18762 {
18763 if (control_block_)
18764 {
18765 if (0 == --control_block_->ref_count)
18766 {
18767 delete control_block_;
18768 }
18769 }
18770
18771 control_block_ = control_block::create(expr);
18772 }
18773 }
18774
18775 inline void register_local_var(expression_ptr expr)
18776 {
18777 if (expr)
18778 {
18779 if (control_block_)
18780 {
18781 control_block_->
18782 local_data_list.push_back(
18783 typename expression<T>::control_block::
18784 data_pack(reinterpret_cast<void*>(expr),
18785 control_block::e_expr));
18786 }
18787 }
18788 }
18789
18790 inline void register_local_var(vector_holder_ptr vec_holder)
18791 {
18792 if (vec_holder)
18793 {
18794 if (control_block_)
18795 {
18796 control_block_->
18797 local_data_list.push_back(
18798 typename expression<T>::control_block::
18799 data_pack(reinterpret_cast<void*>(vec_holder),
18800 control_block::e_vecholder));
18801 }
18802 }
18803 }
18804
18805 inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18806 {
18807 if (data)
18808 {
18809 if (control_block_)
18810 {
18811 typename control_block::data_type dt = control_block::e_data;
18812
18813 switch (data_mode)
18814 {
18815 case 0 : dt = control_block::e_data; break;
18816 case 1 : dt = control_block::e_vecdata; break;
18817 case 2 : dt = control_block::e_string; break;
18818 }
18819
18820 control_block_->
18821 local_data_list.push_back(
18822 typename expression<T>::control_block::
18823 data_pack(reinterpret_cast<void*>(data), dt, size));
18824 }
18825 }
18826 }
18827
18828 inline const typename control_block::local_data_list_t& local_data_list()
18829 {
18830 if (control_block_)
18831 {
18832 return control_block_->local_data_list;
18833 }
18834 else
18835 {
18836 static typename control_block::local_data_list_t null_local_data_list;
18837 return null_local_data_list;
18838 }
18839 }
18840
18841 inline void register_return_results(results_context_t* rc)
18842 {
18843 if (control_block_ && rc)
18844 {
18845 control_block_->results = rc;
18846 }
18847 }
18848
18849 inline void set_retinvk(bool* retinvk_ptr)
18850 {
18851 if (control_block_)
18852 {
18853 control_block_->return_invoked = retinvk_ptr;
18854 }
18855 }
18856
18857 control_block* control_block_;
18858 symtab_list_t symbol_table_list_;
18859
18860 friend class parser<T>;
18861 friend class expression_helper<T>;
18862 friend class function_compositor<T>;
18863 };
18864
18865 template <typename T>
18867 {
18868 public:
18869
18870 static inline bool is_constant(const expression<T>& expr)
18871 {
18872 return details::is_constant_node(expr.control_block_->expr);
18873 }
18874
18875 static inline bool is_variable(const expression<T>& expr)
18876 {
18877 return details::is_variable_node(expr.control_block_->expr);
18878 }
18879
18880 static inline bool is_unary(const expression<T>& expr)
18881 {
18882 return details::is_unary_node(expr.control_block_->expr);
18883 }
18884
18885 static inline bool is_binary(const expression<T>& expr)
18886 {
18887 return details::is_binary_node(expr.control_block_->expr);
18888 }
18889
18890 static inline bool is_function(const expression<T>& expr)
18891 {
18892 return details::is_function(expr.control_block_->expr);
18893 }
18894
18895 static inline bool is_null(const expression<T>& expr)
18896 {
18897 return details::is_null_node(expr.control_block_->expr);
18898 }
18899 };
18900
18901 template <typename T>
18902 inline bool is_valid(const expression<T>& expr)
18903 {
18904 return !expression_helper<T>::is_null(expr);
18905 }
18906
18907 namespace parser_error
18908 {
18910 {
18918 e_parser = 8
18920
18921 struct type
18922 {
18924 : mode(parser_error::e_unknown),
18925 line_no (0),
18926 column_no(0)
18927 {}
18928
18934 std::size_t line_no;
18935 std::size_t column_no;
18936 };
18937
18938 inline type make_error(const error_mode mode,
18939 const std::string& diagnostic = "",
18940 const std::string& src_location = "")
18941 {
18942 type t;
18943 t.mode = mode;
18944 t.token.type = lexer::token::e_error;
18945 t.diagnostic = diagnostic;
18946 t.src_location = src_location;
18947 exprtk_debug(("%s\n",diagnostic .c_str()));
18948 return t;
18949 }
18950
18951 inline type make_error(const error_mode mode,
18952 const lexer::token& tk,
18953 const std::string& diagnostic = "",
18954 const std::string& src_location = "")
18955 {
18956 type t;
18957 t.mode = mode;
18958 t.token = tk;
18959 t.diagnostic = diagnostic;
18960 t.src_location = src_location;
18961 exprtk_debug(("%s\n",diagnostic .c_str()));
18962 return t;
18963 }
18964
18966 {
18967 switch (mode)
18968 {
18969 case e_unknown : return std::string("Unknown Error");
18970 case e_syntax : return std::string("Syntax Error" );
18971 case e_token : return std::string("Token Error" );
18972 case e_numeric : return std::string("Numeric Error");
18973 case e_symtab : return std::string("Symbol Error" );
18974 case e_lexer : return std::string("Lexer Error" );
18975 case e_helper : return std::string("Helper Error" );
18976 case e_parser : return std::string("Parser Error" );
18977 default : return std::string("Unknown Error");
18978 }
18979 }
18980
18981 inline bool update_error(type& error, const std::string& expression)
18982 {
18983 if (
18984 expression.empty() ||
18985 (error.token.position > expression.size()) ||
18986 (std::numeric_limits<std::size_t>::max() == error.token.position)
18987 )
18988 {
18989 return false;
18990 }
18991
18992 std::size_t error_line_start = 0;
18993
18994 for (std::size_t i = error.token.position; i > 0; --i)
18995 {
18996 const details::char_t c = expression[i];
18997
18998 if (('\n' == c) || ('\r' == c))
18999 {
19000 error_line_start = i + 1;
19001 break;
19002 }
19003 }
19004
19005 std::size_t next_nl_position = std::min(expression.size(),
19006 expression.find_first_of('\n',error.token.position + 1));
19007
19008 error.column_no = error.token.position - error_line_start;
19009 error.error_line = expression.substr(error_line_start,
19010 next_nl_position - error_line_start);
19011
19012 error.line_no = 0;
19013
19014 for (std::size_t i = 0; i < next_nl_position; ++i)
19015 {
19016 if ('\n' == expression[i])
19017 ++error.line_no;
19018 }
19019
19020 return true;
19021 }
19022
19023 inline void dump_error(const type& error)
19024 {
19025 printf("Position: %02d Type: [%s] Msg: %s\n",
19026 static_cast<int>(error.token.position),
19027 exprtk::parser_error::to_str(error.mode).c_str(),
19028 error.diagnostic.c_str());
19029 }
19030 }
19031
19032 namespace details
19033 {
19034 template <typename Parser>
19035 inline void disable_type_checking(Parser& p)
19036 {
19037 p.state_.type_check_enabled = false;
19038 }
19039 }
19040
19041 template <typename T>
19043 {
19044 private:
19045
19046 enum precedence_level
19047 {
19048 e_level00,
19049 e_level01,
19050 e_level02,
19051 e_level03,
19052 e_level04,
19053 e_level05,
19054 e_level06,
19055 e_level07,
19056 e_level08,
19057 e_level09,
19058 e_level10,
19059 e_level11,
19060 e_level12,
19061 e_level13,
19062 e_level14
19063 };
19064
19065 typedef const T& cref_t;
19066 typedef const T const_t;
19067 typedef ifunction <T> F;
19068 typedef ivararg_function <T> VAF;
19069 typedef igeneric_function <T> GF;
19070 typedef ifunction <T> ifunction_t;
19084 #ifndef exprtk_disable_break_continue
19088 #endif
19096 #ifndef exprtk_disable_string_capabilities
19107 #endif
19116 typedef lexer::token token_t;
19120 typedef typename expression<T>::symtab_list_t symbol_table_list_t;
19122
19123 typedef typename details::functor_t<T> functor_t;
19124 typedef typename functor_t::qfunc_t quaternary_functor_t;
19125 typedef typename functor_t::tfunc_t trinary_functor_t;
19126 typedef typename functor_t::bfunc_t binary_functor_t;
19127 typedef typename functor_t::ufunc_t unary_functor_t;
19128
19130
19131 typedef std::map<operator_t, unary_functor_t> unary_op_map_t;
19132 typedef std::map<operator_t, binary_functor_t> binary_op_map_t;
19133 typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
19134
19135 typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
19136 typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
19137
19138 typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
19139 typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
19140 typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
19141
19145
19153
19159
19164
19166
19167 typedef parser_helper prsrhlpr_t;
19168
19169 struct scope_element
19170 {
19171 enum element_type
19172 {
19173 e_none ,
19174 e_variable,
19175 e_vector ,
19176 e_vecelem ,
19177 e_string
19178 };
19179
19180 typedef details::vector_holder<T> vector_holder_t;
19181 typedef variable_node_t* variable_node_ptr;
19182 typedef vector_holder_t* vector_holder_ptr;
19184 #ifndef exprtk_disable_string_capabilities
19185 typedef stringvar_node_t* stringvar_node_ptr;
19186 #endif
19187
19188 scope_element()
19189 : name("???"),
19193 ref_count(0),
19194 ip_index (0),
19195 type (e_none),
19196 active(false),
19197 data (0),
19198 var_node(0),
19199 vec_node(0)
19200 #ifndef exprtk_disable_string_capabilities
19201 ,str_node(0)
19202 #endif
19203 {}
19204
19205 bool operator < (const scope_element& se) const
19206 {
19207 if (ip_index < se.ip_index)
19208 return true;
19209 else if (ip_index > se.ip_index)
19210 return false;
19211 else if (depth < se.depth)
19212 return true;
19213 else if (depth > se.depth)
19214 return false;
19215 else if (index < se.index)
19216 return true;
19217 else if (index > se.index)
19218 return false;
19219 else
19220 return (name < se.name);
19221 }
19222
19223 void clear()
19224 {
19225 name = "???";
19229 type = e_none;
19230 active = false;
19231 ref_count = 0;
19232 ip_index = 0;
19233 data = 0;
19234 var_node = 0;
19235 vec_node = 0;
19236 #ifndef exprtk_disable_string_capabilities
19237 str_node = 0;
19238 #endif
19239 }
19240
19242 std::size_t size;
19243 std::size_t index;
19244 std::size_t depth;
19245 std::size_t ref_count;
19246 std::size_t ip_index;
19247 element_type type;
19248 bool active;
19249 void* data;
19250 expression_node_ptr var_node;
19251 vector_holder_ptr vec_node;
19252 #ifndef exprtk_disable_string_capabilities
19253 stringvar_node_ptr str_node;
19254 #endif
19255 };
19256
19257 class scope_element_manager
19258 {
19259 public:
19260
19262 typedef variable_node_t* variable_node_ptr;
19263 typedef parser<T> parser_t;
19264
19265 explicit scope_element_manager(parser<T>& p)
19266 : parser_(p),
19267 input_param_cnt_(0)
19268 {}
19269
19270 inline std::size_t size() const
19271 {
19272 return element_.size();
19273 }
19274
19275 inline bool empty() const
19276 {
19277 return element_.empty();
19278 }
19279
19280 inline scope_element& get_element(const std::size_t& index)
19281 {
19282 if (index < element_.size())
19283 return element_[index];
19284 else
19285 return null_element_;
19286 }
19287
19288 inline scope_element& get_element(const std::string& var_name,
19289 const std::size_t index = std::numeric_limits<std::size_t>::max())
19290 {
19291 const std::size_t current_depth = parser_.state_.scope_depth;
19292
19293 for (std::size_t i = 0; i < element_.size(); ++i)
19294 {
19295 scope_element& se = element_[i];
19296
19297 if (se.depth > current_depth)
19298 continue;
19299 else if (
19300 details::imatch(se.name, var_name) &&
19301 (se.index == index)
19302 )
19303 return se;
19304 }
19305
19306 return null_element_;
19307 }
19308
19309 inline scope_element& get_active_element(const std::string& var_name,
19310 const std::size_t index = std::numeric_limits<std::size_t>::max())
19311 {
19312 const std::size_t current_depth = parser_.state_.scope_depth;
19313
19314 for (std::size_t i = 0; i < element_.size(); ++i)
19315 {
19316 scope_element& se = element_[i];
19317
19318 if (se.depth > current_depth)
19319 continue;
19320 else if (
19321 details::imatch(se.name, var_name) &&
19322 (se.index == index) &&
19323 (se.active)
19324 )
19325 return se;
19326 }
19327
19328 return null_element_;
19329 }
19330
19331 inline bool add_element(const scope_element& se)
19332 {
19333 for (std::size_t i = 0; i < element_.size(); ++i)
19334 {
19335 scope_element& cse = element_[i];
19336
19337 if (
19338 details::imatch(cse.name, se.name) &&
19339 (cse.depth <= se.depth) &&
19340 (cse.index == se.index) &&
19341 (cse.size == se.size ) &&
19342 (cse.type == se.type ) &&
19343 (cse.active)
19344 )
19345 return false;
19346 }
19347
19348 element_.push_back(se);
19349 std::sort(element_.begin(),element_.end());
19350
19351 return true;
19352 }
19353
19354 inline void deactivate(const std::size_t& scope_depth)
19355 {
19356 exprtk_debug(("deactivate() - Scope depth: %d\n",
19357 static_cast<int>(parser_.state_.scope_depth)));
19358
19359 for (std::size_t i = 0; i < element_.size(); ++i)
19360 {
19361 scope_element& se = element_[i];
19362
19363 if (se.active && (se.depth >= scope_depth))
19364 {
19365 exprtk_debug(("deactivate() - element[%02d] '%s'\n",
19366 static_cast<int>(i),
19367 se.name.c_str()));
19368
19369 se.active = false;
19370 }
19371 }
19372 }
19373
19374 inline void free_element(scope_element& se)
19375 {
19376 exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
19377
19378 switch (se.type)
19379 {
19380 case scope_element::e_variable : delete reinterpret_cast<T*>(se.data);
19381 delete se.var_node;
19382 break;
19383
19384 case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data);
19385 delete se.vec_node;
19386 break;
19387
19388 case scope_element::e_vecelem : delete se.var_node;
19389 break;
19390
19391 #ifndef exprtk_disable_string_capabilities
19392 case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data);
19393 delete se.str_node;
19394 break;
19395 #endif
19396
19397 default : return;
19398 }
19399
19400 se.clear();
19401 }
19402
19403 inline void cleanup()
19404 {
19405 for (std::size_t i = 0; i < element_.size(); ++i)
19406 {
19407 free_element(element_[i]);
19408 }
19409
19410 element_.clear();
19411
19412 input_param_cnt_ = 0;
19413 }
19414
19415 inline std::size_t next_ip_index()
19416 {
19417 return ++input_param_cnt_;
19418 }
19419
19420 inline expression_node_ptr get_variable(const T& v)
19421 {
19422 for (std::size_t i = 0; i < element_.size(); ++i)
19423 {
19424 scope_element& se = element_[i];
19425
19426 if (
19427 se.active &&
19428 se.var_node &&
19429 details::is_variable_node(se.var_node)
19430 )
19431 {
19432 variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
19433
19434 if (&(vn->ref()) == (&v))
19435 {
19436 return se.var_node;
19437 }
19438 }
19439 }
19440
19441 return expression_node_ptr(0);
19442 }
19443
19444 private:
19445
19446 scope_element_manager& operator=(const scope_element_manager&);
19447
19448 parser_t& parser_;
19449 std::vector<scope_element> element_;
19450 scope_element null_element_;
19451 std::size_t input_param_cnt_;
19452 };
19453
19454 class scope_handler
19455 {
19456 public:
19457
19458 typedef parser<T> parser_t;
19459
19460 explicit scope_handler(parser<T>& p)
19461 : parser_(p)
19462 {
19463 parser_.state_.scope_depth++;
19464 #ifdef exprtk_enable_debugging
19465 const std::string depth(2 * parser_.state_.scope_depth,'-');
19466 exprtk_debug(("%s> Scope Depth: %02d\n",
19467 depth.c_str(),
19468 static_cast<int>(parser_.state_.scope_depth)));
19469 #endif
19470 }
19471
19472 ~scope_handler()
19473 {
19474 parser_.sem_.deactivate(parser_.state_.scope_depth);
19475 parser_.state_.scope_depth--;
19476 #ifdef exprtk_enable_debugging
19477 const std::string depth(2 * parser_.state_.scope_depth,'-');
19478 exprtk_debug(("<%s Scope Depth: %02d\n",
19479 depth.c_str(),
19480 static_cast<int>(parser_.state_.scope_depth)));
19481 #endif
19482 }
19483
19484 private:
19485
19486 scope_handler& operator=(const scope_handler&);
19487
19488 parser_t& parser_;
19489 };
19490
19491 class stack_limit_handler
19492 {
19493 public:
19494
19495 typedef parser<T> parser_t;
19496
19497 explicit stack_limit_handler(parser<T>& p)
19498 : parser_(p),
19499 limit_exceeded_(false)
19500 {
19501 if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
19502 {
19503 limit_exceeded_ = true;
19504 parser_.set_error(
19506 "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
19507 " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
19509 }
19510 }
19511
19512 ~stack_limit_handler()
19513 {
19514 parser_.state_.stack_depth--;
19515 }
19516
19517 bool operator!()
19518 {
19519 return limit_exceeded_;
19520 }
19521
19522 private:
19523
19524 stack_limit_handler& operator=(const stack_limit_handler&);
19525
19526 parser_t& parser_;
19527 bool limit_exceeded_;
19528 };
19529
19530 struct symtab_store
19531 {
19532 symbol_table_list_t symtab_list_;
19533
19534 typedef typename symbol_table_t::local_data_t local_data_t;
19535 typedef typename symbol_table_t::variable_ptr variable_ptr;
19536 typedef typename symbol_table_t::function_ptr function_ptr;
19537 #ifndef exprtk_disable_string_capabilities
19538 typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
19539 #endif
19541 typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr;
19542 typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
19543
19544 inline bool empty() const
19545 {
19546 return symtab_list_.empty();
19547 }
19548
19549 inline void clear()
19550 {
19551 symtab_list_.clear();
19552 }
19553
19554 inline bool valid() const
19555 {
19556 if (!empty())
19557 {
19558 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19559 {
19560 if (symtab_list_[i].valid())
19561 return true;
19562 }
19563 }
19564
19565 return false;
19566 }
19567
19568 inline bool valid_symbol(const std::string& symbol) const
19569 {
19570 if (!symtab_list_.empty())
19571 return symtab_list_[0].valid_symbol(symbol);
19572 else
19573 return false;
19574 }
19575
19576 inline bool valid_function_name(const std::string& symbol) const
19577 {
19578 if (!symtab_list_.empty())
19579 return symtab_list_[0].valid_function(symbol);
19580 else
19581 return false;
19582 }
19583
19584 inline variable_ptr get_variable(const std::string& variable_name) const
19585 {
19586 if (!valid_symbol(variable_name))
19587 return reinterpret_cast<variable_ptr>(0);
19588
19589 variable_ptr result = reinterpret_cast<variable_ptr>(0);
19590
19591 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19592 {
19593 if (!symtab_list_[i].valid())
19594 continue;
19595 else
19596 result = local_data(i)
19597 .variable_store.get(variable_name);
19598
19599 if (result) break;
19600 }
19601
19602 return result;
19603 }
19604
19605 inline variable_ptr get_variable(const T& var_ref) const
19606 {
19607 variable_ptr result = reinterpret_cast<variable_ptr>(0);
19608
19609 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19610 {
19611 if (!symtab_list_[i].valid())
19612 continue;
19613 else
19614 result = local_data(i).variable_store
19615 .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
19616
19617 if (result) break;
19618 }
19619
19620 return result;
19621 }
19622
19623 #ifndef exprtk_disable_string_capabilities
19624 inline stringvar_ptr get_stringvar(const std::string& string_name) const
19625 {
19626 if (!valid_symbol(string_name))
19627 return reinterpret_cast<stringvar_ptr>(0);
19628
19629 stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
19630
19631 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19632 {
19633 if (!symtab_list_[i].valid())
19634 continue;
19635 else
19636 result = local_data(i)
19637 .stringvar_store.get(string_name);
19638
19639 if (result) break;
19640 }
19641
19642 return result;
19643 }
19644 #endif
19645
19646 inline function_ptr get_function(const std::string& function_name) const
19647 {
19648 if (!valid_function_name(function_name))
19649 return reinterpret_cast<function_ptr>(0);
19650
19651 function_ptr result = reinterpret_cast<function_ptr>(0);
19652
19653 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19654 {
19655 if (!symtab_list_[i].valid())
19656 continue;
19657 else
19658 result = local_data(i)
19659 .function_store.get(function_name);
19660
19661 if (result) break;
19662 }
19663
19664 return result;
19665 }
19666
19667 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
19668 {
19669 if (!valid_function_name(vararg_function_name))
19670 return reinterpret_cast<vararg_function_ptr>(0);
19671
19672 vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
19673
19674 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19675 {
19676 if (!symtab_list_[i].valid())
19677 continue;
19678 else
19679 result = local_data(i)
19680 .vararg_function_store.get(vararg_function_name);
19681
19682 if (result) break;
19683 }
19684
19685 return result;
19686 }
19687
19688 inline generic_function_ptr get_generic_function(const std::string& function_name) const
19689 {
19690 if (!valid_function_name(function_name))
19691 return reinterpret_cast<generic_function_ptr>(0);
19692
19693 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19694
19695 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19696 {
19697 if (!symtab_list_[i].valid())
19698 continue;
19699 else
19700 result = local_data(i)
19701 .generic_function_store.get(function_name);
19702
19703 if (result) break;
19704 }
19705
19706 return result;
19707 }
19708
19709 inline generic_function_ptr get_string_function(const std::string& function_name) const
19710 {
19711 if (!valid_function_name(function_name))
19712 return reinterpret_cast<generic_function_ptr>(0);
19713
19714 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19715
19716 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19717 {
19718 if (!symtab_list_[i].valid())
19719 continue;
19720 else
19721 result =
19722 local_data(i).string_function_store.get(function_name);
19723
19724 if (result) break;
19725 }
19726
19727 return result;
19728 }
19729
19730 inline generic_function_ptr get_overload_function(const std::string& function_name) const
19731 {
19732 if (!valid_function_name(function_name))
19733 return reinterpret_cast<generic_function_ptr>(0);
19734
19735 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19736
19737 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19738 {
19739 if (!symtab_list_[i].valid())
19740 continue;
19741 else
19742 result =
19743 local_data(i).overload_function_store.get(function_name);
19744
19745 if (result) break;
19746 }
19747
19748 return result;
19749 }
19750
19751 inline vector_holder_ptr get_vector(const std::string& vector_name) const
19752 {
19753 if (!valid_symbol(vector_name))
19754 return reinterpret_cast<vector_holder_ptr>(0);
19755
19756 vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
19757
19758 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19759 {
19760 if (!symtab_list_[i].valid())
19761 continue;
19762 else
19763 result =
19764 local_data(i).vector_store.get(vector_name);
19765
19766 if (result) break;
19767 }
19768
19769 return result;
19770 }
19771
19772 inline bool is_constant_node(const std::string& symbol_name) const
19773 {
19774 if (!valid_symbol(symbol_name))
19775 return false;
19776
19777 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19778 {
19779 if (!symtab_list_[i].valid())
19780 continue;
19781 else if (local_data(i).variable_store.is_constant(symbol_name))
19782 return true;
19783 }
19784
19785 return false;
19786 }
19787
19788 #ifndef exprtk_disable_string_capabilities
19789 inline bool is_constant_string(const std::string& symbol_name) const
19790 {
19791 if (!valid_symbol(symbol_name))
19792 return false;
19793
19794 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19795 {
19796 if (!symtab_list_[i].valid())
19797 continue;
19798 else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19799 continue;
19800 else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19801 return true;
19802 }
19803
19804 return false;
19805 }
19806 #endif
19807
19808 inline bool symbol_exists(const std::string& symbol) const
19809 {
19810 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19811 {
19812 if (!symtab_list_[i].valid())
19813 continue;
19814 else if (symtab_list_[i].symbol_exists(symbol))
19815 return true;
19816 }
19817
19818 return false;
19819 }
19820
19821 inline bool is_variable(const std::string& variable_name) const
19822 {
19823 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19824 {
19825 if (!symtab_list_[i].valid())
19826 continue;
19827 else if (
19828 symtab_list_[i].local_data().variable_store
19829 .symbol_exists(variable_name)
19830 )
19831 return true;
19832 }
19833
19834 return false;
19835 }
19836
19837 #ifndef exprtk_disable_string_capabilities
19838 inline bool is_stringvar(const std::string& stringvar_name) const
19839 {
19840 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19841 {
19842 if (!symtab_list_[i].valid())
19843 continue;
19844 else if (
19845 symtab_list_[i].local_data().stringvar_store
19846 .symbol_exists(stringvar_name)
19847 )
19848 return true;
19849 }
19850
19851 return false;
19852 }
19853
19854 inline bool is_conststr_stringvar(const std::string& symbol_name) const
19855 {
19856 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19857 {
19858 if (!symtab_list_[i].valid())
19859 continue;
19860 else if (
19861 symtab_list_[i].local_data().stringvar_store
19862 .symbol_exists(symbol_name)
19863 )
19864 {
19865 return (
19866 local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19867 local_data(i).stringvar_store.is_constant (symbol_name)
19868 );
19869
19870 }
19871 }
19872
19873 return false;
19874 }
19875 #endif
19876
19877 inline bool is_function(const std::string& function_name) const
19878 {
19879 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19880 {
19881 if (!symtab_list_[i].valid())
19882 continue;
19883 else if (
19884 local_data(i).vararg_function_store
19885 .symbol_exists(function_name)
19886 )
19887 return true;
19888 }
19889
19890 return false;
19891 }
19892
19893 inline bool is_vararg_function(const std::string& vararg_function_name) const
19894 {
19895 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19896 {
19897 if (!symtab_list_[i].valid())
19898 continue;
19899 else if (
19900 local_data(i).vararg_function_store
19901 .symbol_exists(vararg_function_name)
19902 )
19903 return true;
19904 }
19905
19906 return false;
19907 }
19908
19909 inline bool is_vector(const std::string& vector_name) const
19910 {
19911 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19912 {
19913 if (!symtab_list_[i].valid())
19914 continue;
19915 else if (
19916 local_data(i).vector_store
19917 .symbol_exists(vector_name)
19918 )
19919 return true;
19920 }
19921
19922 return false;
19923 }
19924
19925 inline std::string get_variable_name(const expression_node_ptr& ptr) const
19926 {
19927 return local_data().variable_store.entity_name(ptr);
19928 }
19929
19930 inline std::string get_vector_name(const vector_holder_ptr& ptr) const
19931 {
19932 return local_data().vector_store.entity_name(ptr);
19933 }
19934
19935 #ifndef exprtk_disable_string_capabilities
19936 inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
19937 {
19938 return local_data().stringvar_store.entity_name(ptr);
19939 }
19940
19941 inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
19942 {
19943 return local_data().stringvar_store.entity_name(ptr);
19944 }
19945 #endif
19946
19947 inline local_data_t& local_data(const std::size_t& index = 0)
19948 {
19949 return symtab_list_[index].local_data();
19950 }
19951
19952 inline const local_data_t& local_data(const std::size_t& index = 0) const
19953 {
19954 return symtab_list_[index].local_data();
19955 }
19956
19957 inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19958 {
19959 return symtab_list_[index];
19960 }
19961 };
19962
19963 struct parser_state
19964 {
19965 parser_state()
19966 : type_check_enabled(true)
19967 {
19968 reset();
19969 }
19970
19971 void reset()
19972 {
19973 parsing_return_stmt = false;
19974 parsing_break_stmt = false;
19975 return_stmt_present = false;
19976 side_effect_present = false;
19977 scope_depth = 0;
19978 stack_depth = 0;
19979 parsing_loop_stmt_count = 0;
19980 }
19981
19982 #ifndef exprtk_enable_debugging
19983 void activate_side_effect(const std::string&)
19984 #else
19985 void activate_side_effect(const std::string& source)
19986 #endif
19987 {
19988 if (!side_effect_present)
19989 {
19990 side_effect_present = true;
19991
19992 exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19993 }
19994 }
19995
19996 bool parsing_return_stmt;
19997 bool parsing_break_stmt;
19998 bool return_stmt_present;
19999 bool side_effect_present;
20000 bool type_check_enabled;
20001 std::size_t scope_depth;
20002 std::size_t stack_depth;
20003 std::size_t parsing_loop_stmt_count;
20004 };
20005
20006 public:
20007
20009 {
20010
20012 {
20013 e_usr_unknown_type = 0,
20014 e_usr_variable_type = 1,
20015 e_usr_constant_type = 2
20017
20019 {
20020 e_usrmode_default = 0,
20021 e_usrmode_extended = 1
20023
20025
20026 unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
20027 : mode(m)
20028 {}
20029
20031 {}
20032
20033 virtual bool process(const std::string& /*unknown_symbol*/,
20034 usr_symbol_type& st,
20035 T& default_value,
20036 std::string& error_message)
20037 {
20038 if (e_usrmode_default != mode)
20039 return false;
20040
20041 st = e_usr_variable_type;
20042 default_value = T(0);
20043 error_message.clear();
20044
20045 return true;
20046 }
20047
20048 virtual bool process(const std::string& /* unknown_symbol */,
20049 symbol_table_t& /* symbol_table */,
20050 std::string& /* error_message */)
20051 {
20052 return false;
20053 }
20054 };
20055
20057 {
20058 e_ct_none = 0,
20059 e_ct_variables = 1,
20060 e_ct_functions = 2,
20061 e_ct_assignments = 4
20063
20065 {
20066 e_st_unknown = 0,
20067 e_st_variable = 1,
20068 e_st_vector = 2,
20069 e_st_vecelem = 3,
20070 e_st_string = 4,
20071 e_st_function = 5,
20072 e_st_local_variable = 6,
20073 e_st_local_vector = 7,
20074 e_st_local_string = 8
20076
20078 {
20079 public:
20080
20081 typedef std::pair<std::string,symbol_type> symbol_t;
20082 typedef std::vector<symbol_t> symbol_list_t;
20083
20084 dependent_entity_collector(const std::size_t options = e_ct_none)
20085 : options_(options),
20086 collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ),
20087 collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ),
20088 collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
20089 return_present_ (false),
20090 final_stmt_return_(false)
20091 {}
20092
20093 template <typename Allocator,
20094 template <typename, typename> class Sequence>
20095 inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
20096 {
20097 if (!collect_variables_ && !collect_functions_)
20098 return 0;
20099 else if (symbol_name_list_.empty())
20100 return 0;
20101
20102 for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
20103 {
20104 details::case_normalise(symbol_name_list_[i].first);
20105 }
20106
20107 std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
20108
20109 std::unique_copy(symbol_name_list_.begin(),
20110 symbol_name_list_.end (),
20111 std::back_inserter(symbols_list));
20112
20113 return symbols_list.size();
20114 }
20115
20116 template <typename Allocator,
20117 template <typename, typename> class Sequence>
20118 inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
20119 {
20120 if (!collect_assignments_)
20121 return 0;
20122 else if (assignment_name_list_.empty())
20123 return 0;
20124
20125 for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
20126 {
20127 details::case_normalise(assignment_name_list_[i].first);
20128 }
20129
20130 std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
20131
20132 std::unique_copy(assignment_name_list_.begin(),
20133 assignment_name_list_.end (),
20134 std::back_inserter(assignment_list));
20135
20136 return assignment_list.size();
20137 }
20138
20139 void clear()
20140 {
20141 symbol_name_list_ .clear();
20142 assignment_name_list_.clear();
20143 retparam_list_ .clear();
20144 return_present_ = false;
20145 final_stmt_return_ = false;
20146 }
20147
20149 {
20150 return collect_variables_;
20151 }
20152
20154 {
20155 return collect_functions_;
20156 }
20157
20159 {
20160 return collect_assignments_;
20161 }
20162
20163 bool return_present() const
20164 {
20165 return return_present_;
20166 }
20167
20169 {
20170 return final_stmt_return_;
20171 }
20172
20173 typedef std::vector<std::string> retparam_list_t;
20174
20176 {
20177 return retparam_list_;
20178 }
20179
20180 private:
20181
20182 inline void add_symbol(const std::string& symbol, const symbol_type st)
20183 {
20184 switch (st)
20185 {
20186 case e_st_variable :
20187 case e_st_vector :
20188 case e_st_string :
20189 case e_st_local_variable :
20190 case e_st_local_vector :
20191 case e_st_local_string : if (collect_variables_)
20192 symbol_name_list_
20193 .push_back(std::make_pair(symbol, st));
20194 break;
20195
20196 case e_st_function : if (collect_functions_)
20197 symbol_name_list_
20198 .push_back(std::make_pair(symbol, st));
20199 break;
20200
20201 default : return;
20202 }
20203 }
20204
20205 inline void add_assignment(const std::string& symbol, const symbol_type st)
20206 {
20207 switch (st)
20208 {
20209 case e_st_variable :
20210 case e_st_vector :
20211 case e_st_string : if (collect_assignments_)
20212 assignment_name_list_
20213 .push_back(std::make_pair(symbol, st));
20214 break;
20215
20216 default : return;
20217 }
20218 }
20219
20220 std::size_t options_;
20221 bool collect_variables_;
20222 bool collect_functions_;
20223 bool collect_assignments_;
20224 bool return_present_;
20225 bool final_stmt_return_;
20226 symbol_list_t symbol_name_list_;
20227 symbol_list_t assignment_name_list_;
20228 retparam_list_t retparam_list_;
20229
20230 friend class parser<T>;
20231 };
20232
20234 {
20235 private:
20236
20237 typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
20238 typedef disabled_entity_set_t::iterator des_itr_t;
20239
20240 public:
20241
20243 {
20245 e_replacer = 1,
20246 e_joiner = 2,
20247 e_numeric_check = 4,
20248 e_bracket_check = 8,
20249 e_sequence_check = 16,
20250 e_commutative_check = 32,
20251 e_strength_reduction = 64,
20252 e_disable_vardef = 128,
20253 e_collect_vars = 256,
20254 e_collect_funcs = 512,
20255 e_collect_assings = 1024,
20256 e_disable_usr_on_rsrvd = 2048,
20257 e_disable_zero_return = 4096
20259
20261 {
20262 e_bf_unknown = 0,
20263 e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
20264 e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
20265 e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
20266 e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
20267 e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
20268 e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
20269 e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
20270 e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
20271 e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
20272 e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
20273 e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
20274 e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
20275 e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
20276 e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad,
20277 e_bf_rad2deg , e_bf_grad2deg
20279
20281 {
20282 e_ctrl_unknown = 0,
20288 e_ctrl_return
20290
20292 {
20293 e_logic_unknown = 0,
20294 e_logic_and, e_logic_nand, e_logic_nor,
20295 e_logic_not, e_logic_or, e_logic_xnor,
20296 e_logic_xor, e_logic_scand, e_logic_scor
20298
20300 {
20301 e_arith_unknown = 0,
20302 e_arith_add, e_arith_sub, e_arith_mul,
20303 e_arith_div, e_arith_mod, e_arith_pow
20305
20307 {
20308 e_assign_unknown = 0,
20309 e_assign_assign, e_assign_addass, e_assign_subass,
20310 e_assign_mulass, e_assign_divass, e_assign_modass
20312
20314 {
20315 e_ineq_unknown = 0,
20316 e_ineq_lt, e_ineq_lte, e_ineq_eq,
20317 e_ineq_equal, e_ineq_ne, e_ineq_nequal,
20318 e_ineq_gte, e_ineq_gt
20320
20321 static const std::size_t compile_all_opts = e_replacer +
20322 e_joiner +
20323 e_numeric_check +
20324 e_bracket_check +
20325 e_sequence_check +
20326 e_commutative_check +
20327 e_strength_reduction;
20328
20329 settings_store(const std::size_t compile_options = compile_all_opts)
20330 : max_stack_depth_(400),
20331 max_node_depth_(10000)
20332 {
20333 load_compile_options(compile_options);
20334 }
20335
20337 {
20338 disabled_func_set_.clear();
20339 return (*this);
20340 }
20341
20343 {
20344 disabled_ctrl_set_.clear();
20345 return (*this);
20346 }
20347
20349 {
20350 disabled_logic_set_.clear();
20351 return (*this);
20352 }
20353
20355 {
20356 disabled_arithmetic_set_.clear();
20357 return (*this);
20358 }
20359
20361 {
20362 disabled_assignment_set_.clear();
20363 return (*this);
20364 }
20365
20367 {
20368 disabled_inequality_set_.clear();
20369 return (*this);
20370 }
20371
20373 {
20374 disable_vardef_ = false;
20375 return (*this);
20376 }
20377
20379 {
20382 std::insert_iterator<disabled_entity_set_t>
20383 (disabled_func_set_, disabled_func_set_.begin()));
20384 return (*this);
20385 }
20386
20388 {
20391 std::insert_iterator<disabled_entity_set_t>
20392 (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
20393 return (*this);
20394 }
20395
20397 {
20398 std::copy(details::logic_ops_list,
20400 std::insert_iterator<disabled_entity_set_t>
20401 (disabled_logic_set_, disabled_logic_set_.begin()));
20402 return (*this);
20403 }
20404
20406 {
20409 std::insert_iterator<disabled_entity_set_t>
20410 (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
20411 return (*this);
20412 }
20413
20415 {
20418 std::insert_iterator<disabled_entity_set_t>
20419 (disabled_assignment_set_, disabled_assignment_set_.begin()));
20420 return (*this);
20421 }
20422
20424 {
20427 std::insert_iterator<disabled_entity_set_t>
20428 (disabled_inequality_set_, disabled_inequality_set_.begin()));
20429 return (*this);
20430 }
20431
20433 {
20434 disable_vardef_ = true;
20435 return (*this);
20436 }
20437
20438 bool replacer_enabled () const { return enable_replacer_; }
20439 bool commutative_check_enabled () const { return enable_commutative_check_; }
20440 bool joiner_enabled () const { return enable_joiner_; }
20441 bool numeric_check_enabled () const { return enable_numeric_check_; }
20442 bool bracket_check_enabled () const { return enable_bracket_check_; }
20443 bool sequence_check_enabled () const { return enable_sequence_check_; }
20444 bool strength_reduction_enabled () const { return enable_strength_reduction_; }
20445 bool collect_variables_enabled () const { return enable_collect_vars_; }
20446 bool collect_functions_enabled () const { return enable_collect_funcs_; }
20447 bool collect_assignments_enabled() const { return enable_collect_assings_; }
20448 bool vardef_disabled () const { return disable_vardef_; }
20449 bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
20450 bool zero_return_disabled () const { return disable_zero_return_; }
20451
20452 bool function_enabled(const std::string& function_name) const
20453 {
20454 if (disabled_func_set_.empty())
20455 return true;
20456 else
20457 return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
20458 }
20459
20460 bool control_struct_enabled(const std::string& control_struct) const
20461 {
20462 if (disabled_ctrl_set_.empty())
20463 return true;
20464 else
20465 return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
20466 }
20467
20468 bool logic_enabled(const std::string& logic_operation) const
20469 {
20470 if (disabled_logic_set_.empty())
20471 return true;
20472 else
20473 return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
20474 }
20475
20476 bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
20477 {
20478 if (disabled_logic_set_.empty())
20479 return true;
20480 else
20481 return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
20482 .find(arith_opr_to_string(arithmetic_operation));
20483 }
20484
20485 bool assignment_enabled(const details::operator_type& assignment) const
20486 {
20487 if (disabled_assignment_set_.empty())
20488 return true;
20489 else
20490 return disabled_assignment_set_.end() == disabled_assignment_set_
20491 .find(assign_opr_to_string(assignment));
20492 }
20493
20494 bool inequality_enabled(const details::operator_type& inequality) const
20495 {
20496 if (disabled_inequality_set_.empty())
20497 return true;
20498 else
20499 return disabled_inequality_set_.end() == disabled_inequality_set_
20500 .find(inequality_opr_to_string(inequality));
20501 }
20502
20503 bool function_disabled(const std::string& function_name) const
20504 {
20505 if (disabled_func_set_.empty())
20506 return false;
20507 else
20508 return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
20509 }
20510
20511 bool control_struct_disabled(const std::string& control_struct) const
20512 {
20513 if (disabled_ctrl_set_.empty())
20514 return false;
20515 else
20516 return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
20517 }
20518
20519 bool logic_disabled(const std::string& logic_operation) const
20520 {
20521 if (disabled_logic_set_.empty())
20522 return false;
20523 else
20524 return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
20525 }
20526
20527 bool assignment_disabled(const details::operator_type assignment_operation) const
20528 {
20529 if (disabled_assignment_set_.empty())
20530 return false;
20531 else
20532 return disabled_assignment_set_.end() != disabled_assignment_set_
20533 .find(assign_opr_to_string(assignment_operation));
20534 }
20535
20536 bool logic_disabled(const details::operator_type logic_operation) const
20537 {
20538 if (disabled_logic_set_.empty())
20539 return false;
20540 else
20541 return disabled_logic_set_.end() != disabled_logic_set_
20542 .find(logic_opr_to_string(logic_operation));
20543 }
20544
20545 bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
20546 {
20547 if (disabled_arithmetic_set_.empty())
20548 return false;
20549 else
20550 return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
20551 .find(arith_opr_to_string(arithmetic_operation));
20552 }
20553
20554 bool inequality_disabled(const details::operator_type& inequality) const
20555 {
20556 if (disabled_inequality_set_.empty())
20557 return false;
20558 else
20559 return disabled_inequality_set_.end() != disabled_inequality_set_
20560 .find(inequality_opr_to_string(inequality));
20561 }
20562
20564 {
20565 if (
20566 (e_bf_unknown != bf) &&
20567 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
20568 )
20569 {
20570 disabled_func_set_.insert(details::base_function_list[bf - 1]);
20571 }
20572
20573 return (*this);
20574 }
20575
20577 {
20578 if (
20579 (e_ctrl_unknown != ctrl_struct) &&
20580 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
20581 )
20582 {
20583 disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
20584 }
20585
20586 return (*this);
20587 }
20588
20590 {
20591 if (
20592 (e_logic_unknown != logic) &&
20593 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
20594 )
20595 {
20596 disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
20597 }
20598
20599 return (*this);
20600 }
20601
20603 {
20604 if (
20605 (e_arith_unknown != arithmetic) &&
20606 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
20607 )
20608 {
20609 disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
20610 }
20611
20612 return (*this);
20613 }
20614
20616 {
20617 if (
20618 (e_assign_unknown != assignment) &&
20619 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
20620 )
20621 {
20622 disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
20623 }
20624
20625 return (*this);
20626 }
20627
20629 {
20630 if (
20631 (e_ineq_unknown != inequality) &&
20632 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
20633 )
20634 {
20635 disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
20636 }
20637
20638 return (*this);
20639 }
20640
20642 {
20643 if (
20644 (e_bf_unknown != bf) &&
20645 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
20646 )
20647 {
20648 const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
20649
20650 if (disabled_func_set_.end() != itr)
20651 {
20652 disabled_func_set_.erase(itr);
20653 }
20654 }
20655
20656 return (*this);
20657 }
20658
20660 {
20661 if (
20662 (e_ctrl_unknown != ctrl_struct) &&
20663 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
20664 )
20665 {
20666 const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
20667
20668 if (disabled_ctrl_set_.end() != itr)
20669 {
20670 disabled_ctrl_set_.erase(itr);
20671 }
20672 }
20673
20674 return (*this);
20675 }
20676
20678 {
20679 if (
20680 (e_logic_unknown != logic) &&
20681 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
20682 )
20683 {
20684 const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
20685
20686 if (disabled_logic_set_.end() != itr)
20687 {
20688 disabled_logic_set_.erase(itr);
20689 }
20690 }
20691
20692 return (*this);
20693 }
20694
20696 {
20697 if (
20698 (e_arith_unknown != arithmetic) &&
20699 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
20700 )
20701 {
20702 const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
20703
20704 if (disabled_arithmetic_set_.end() != itr)
20705 {
20706 disabled_arithmetic_set_.erase(itr);
20707 }
20708 }
20709
20710 return (*this);
20711 }
20712
20714 {
20715 if (
20716 (e_assign_unknown != assignment) &&
20717 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
20718 )
20719 {
20720 const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
20721
20722 if (disabled_assignment_set_.end() != itr)
20723 {
20724 disabled_assignment_set_.erase(itr);
20725 }
20726 }
20727
20728 return (*this);
20729 }
20730
20732 {
20733 if (
20734 (e_ineq_unknown != inequality) &&
20735 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
20736 )
20737 {
20738 const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
20739
20740 if (disabled_inequality_set_.end() != itr)
20741 {
20742 disabled_inequality_set_.erase(itr);
20743 }
20744 }
20745
20746 return (*this);
20747 }
20748
20749 void set_max_stack_depth(const std::size_t mx_stack_depth)
20750 {
20751 max_stack_depth_ = mx_stack_depth;
20752 }
20753
20754 void set_max_node_depth(const std::size_t max_node_depth)
20755 {
20756 max_node_depth_ = max_node_depth;
20757 }
20758
20759 private:
20760
20761 void load_compile_options(const std::size_t compile_options)
20762 {
20763 enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
20764 enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
20765 enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
20766 enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
20767 enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
20768 enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
20769 enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
20770 enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
20771 enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
20772 enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
20773 disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
20774 disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
20775 disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
20776 }
20777
20778 std::string assign_opr_to_string(details::operator_type opr) const
20779 {
20780 switch (opr)
20781 {
20782 case details::e_assign : return ":=";
20783 case details::e_addass : return "+=";
20784 case details::e_subass : return "-=";
20785 case details::e_mulass : return "*=";
20786 case details::e_divass : return "/=";
20787 case details::e_modass : return "%=";
20788 default : return "";
20789 }
20790 }
20791
20792 std::string arith_opr_to_string(details::operator_type opr) const
20793 {
20794 switch (opr)
20795 {
20796 case details::e_add : return "+";
20797 case details::e_sub : return "-";
20798 case details::e_mul : return "*";
20799 case details::e_div : return "/";
20800 case details::e_mod : return "%";
20801 default : return "";
20802 }
20803 }
20804
20805 std::string inequality_opr_to_string(details::operator_type opr) const
20806 {
20807 switch (opr)
20808 {
20809 case details::e_lt : return "<";
20810 case details::e_lte : return "<=";
20811 case details::e_eq : return "==";
20812 case details::e_equal : return "=";
20813 case details::e_ne : return "!=";
20814 case details::e_nequal: return "<>";
20815 case details::e_gte : return ">=";
20816 case details::e_gt : return ">";
20817 default : return "";
20818 }
20819 }
20820
20821 std::string logic_opr_to_string(details::operator_type opr) const
20822 {
20823 switch (opr)
20824 {
20825 case details::e_and : return "and" ;
20826 case details::e_or : return "or" ;
20827 case details::e_xor : return "xor" ;
20828 case details::e_nand : return "nand";
20829 case details::e_nor : return "nor" ;
20830 case details::e_xnor : return "xnor";
20831 case details::e_notl : return "not" ;
20832 default : return "" ;
20833 }
20834 }
20835
20836 bool enable_replacer_;
20837 bool enable_joiner_;
20838 bool enable_numeric_check_;
20839 bool enable_bracket_check_;
20840 bool enable_sequence_check_;
20841 bool enable_commutative_check_;
20842 bool enable_strength_reduction_;
20843 bool enable_collect_vars_;
20844 bool enable_collect_funcs_;
20845 bool enable_collect_assings_;
20846 bool disable_vardef_;
20847 bool disable_rsrvd_sym_usr_;
20848 bool disable_zero_return_;
20849
20850 disabled_entity_set_t disabled_func_set_ ;
20851 disabled_entity_set_t disabled_ctrl_set_ ;
20852 disabled_entity_set_t disabled_logic_set_;
20853 disabled_entity_set_t disabled_arithmetic_set_;
20854 disabled_entity_set_t disabled_assignment_set_;
20855 disabled_entity_set_t disabled_inequality_set_;
20856
20857 std::size_t max_stack_depth_;
20858 std::size_t max_node_depth_;
20859
20860 friend class parser<T>;
20861 };
20862
20864
20865 parser(const settings_t& settings = settings_t())
20866 : settings_(settings),
20867 resolve_unknown_symbol_(false),
20868 results_context_(0),
20869 unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20870 #ifdef _MSC_VER
20871 #pragma warning(push)
20872 #pragma warning (disable:4355)
20873 #endif
20874 sem_(*this),
20875 #ifdef _MSC_VER
20876 #pragma warning(pop)
20877 #endif
20878 operator_joiner_2_(2),
20879 operator_joiner_3_(3),
20880 loop_runtime_check_(0)
20881 {
20882 init_precompilation();
20883
20884 load_operations_map (base_ops_map_ );
20885 load_unary_operations_map (unary_op_map_ );
20886 load_binary_operations_map (binary_op_map_ );
20887 load_inv_binary_operations_map(inv_binary_op_map_);
20888 load_sf3_map (sf3_map_ );
20889 load_sf4_map (sf4_map_ );
20890
20891 expression_generator_.init_synthesize_map();
20892 expression_generator_.set_parser(*this);
20893 expression_generator_.set_uom(unary_op_map_);
20894 expression_generator_.set_bom(binary_op_map_);
20895 expression_generator_.set_ibom(inv_binary_op_map_);
20896 expression_generator_.set_sf3m(sf3_map_);
20897 expression_generator_.set_sf4m(sf4_map_);
20898 expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20899 }
20900
20902 {}
20903
20905 {
20906 if (settings_.collect_variables_enabled())
20907 dec_.collect_variables() = true;
20908
20909 if (settings_.collect_functions_enabled())
20910 dec_.collect_functions() = true;
20911
20912 if (settings_.collect_assignments_enabled())
20913 dec_.collect_assignments() = true;
20914
20915 if (settings_.replacer_enabled())
20916 {
20917 symbol_replacer_.clear();
20918 symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
20919 symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
20920 helper_assembly_.token_modifier_list.clear();
20921 helper_assembly_.register_modifier(&symbol_replacer_);
20922 }
20923
20924 if (settings_.commutative_check_enabled())
20925 {
20926 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20927 {
20928 commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20929 }
20930
20931 helper_assembly_.token_inserter_list.clear();
20932 helper_assembly_.register_inserter(&commutative_inserter_);
20933 }
20934
20935 if (settings_.joiner_enabled())
20936 {
20937 helper_assembly_.token_joiner_list.clear();
20938 helper_assembly_.register_joiner(&operator_joiner_2_);
20939 helper_assembly_.register_joiner(&operator_joiner_3_);
20940 }
20941
20942 if (
20943 settings_.numeric_check_enabled () ||
20944 settings_.bracket_check_enabled () ||
20945 settings_.sequence_check_enabled()
20946 )
20947 {
20948 helper_assembly_.token_scanner_list.clear();
20949
20950 if (settings_.numeric_check_enabled())
20951 {
20952 helper_assembly_.register_scanner(&numeric_checker_);
20953 }
20954
20955 if (settings_.bracket_check_enabled())
20956 {
20957 helper_assembly_.register_scanner(&bracket_checker_);
20958 }
20959
20960 if (settings_.sequence_check_enabled())
20961 {
20962 helper_assembly_.register_scanner(&sequence_validator_ );
20963 helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20964 }
20965 }
20966 }
20967
20968 inline bool compile(const std::string& expression_string, expression<T>& expr)
20969 {
20970 state_ .reset();
20971 error_list_ .clear();
20972 brkcnt_list_ .clear();
20973 synthesis_error_.clear();
20974 sem_ .cleanup();
20975
20976 return_cleanup();
20977
20978 expression_generator_.set_allocator(node_allocator_);
20979
20980 if (expression_string.empty())
20981 {
20982 set_error(
20984 "ERR001 - Empty expression!",
20986
20987 return false;
20988 }
20989
20990 if (!init(expression_string))
20991 {
20992 process_lexer_errors();
20993 return false;
20994 }
20995
20996 if (lexer().empty())
20997 {
20998 set_error(
21000 "ERR002 - Empty expression!",
21002
21003 return false;
21004 }
21005
21006 if (!run_assemblies())
21007 {
21008 return false;
21009 }
21010
21011 symtab_store_.symtab_list_ = expr.get_symbol_table_list();
21012 dec_.clear();
21013
21014 lexer().begin();
21015
21016 next_token();
21017
21018 expression_node_ptr e = parse_corpus();
21019
21020 if ((0 != e) && (token_t::e_eof == current_token().type))
21021 {
21022 bool* retinvk_ptr = 0;
21023
21024 if (state_.return_stmt_present)
21025 {
21026 dec_.return_present_ = true;
21027
21028 e = expression_generator_
21029 .return_envelope(e, results_context_, retinvk_ptr);
21030 }
21031
21032 expr.set_expression(e);
21033 expr.set_retinvk(retinvk_ptr);
21034
21035 register_local_vars(expr);
21036 register_return_results(expr);
21037
21038 return !(!expr);
21039 }
21040 else
21041 {
21042 if (error_list_.empty())
21043 {
21044 set_error(
21046 current_token(),
21047 "ERR003 - Invalid expression encountered",
21049 }
21050
21051 if ((0 != e) && branch_deletable(e))
21052 {
21053 destroy_node(e);
21054 }
21055
21056 dec_.clear ();
21057 sem_.cleanup ();
21058 return_cleanup();
21059
21060 return false;
21061 }
21062 }
21063
21064 inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
21065 {
21067
21069
21070 compile(expression_string,expression);
21071
21072 return expression;
21073 }
21074
21076 {
21077 for (std::size_t i = 0; i < lexer().size(); ++i)
21078 {
21079 if (lexer()[i].is_error())
21080 {
21081 std::string diagnostic = "ERR004 - ";
21082
21083 switch (lexer()[i].type)
21084 {
21085 case lexer::token::e_error : diagnostic += "General token error";
21086 break;
21087
21088 case lexer::token::e_err_symbol : diagnostic += "Symbol error";
21089 break;
21090
21091 case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
21092 break;
21093
21094 case lexer::token::e_err_string : diagnostic += "Invalid string token";
21095 break;
21096
21097 case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
21098 break;
21099
21100 default : diagnostic += "Unknown compiler error";
21101 }
21102
21103 set_error(
21105 lexer()[i],
21106 diagnostic + ": " + lexer()[i].value,
21108 }
21109 }
21110 }
21111
21112 inline bool run_assemblies()
21113 {
21114 if (settings_.commutative_check_enabled())
21115 {
21116 helper_assembly_.run_inserters(lexer());
21117 }
21118
21119 if (settings_.joiner_enabled())
21120 {
21121 helper_assembly_.run_joiners(lexer());
21122 }
21123
21124 if (settings_.replacer_enabled())
21125 {
21126 helper_assembly_.run_modifiers(lexer());
21127 }
21128
21129 if (
21130 settings_.numeric_check_enabled () ||
21131 settings_.bracket_check_enabled () ||
21132 settings_.sequence_check_enabled()
21133 )
21134 {
21135 if (!helper_assembly_.run_scanners(lexer()))
21136 {
21137 if (helper_assembly_.error_token_scanner)
21138 {
21139 lexer::helper::bracket_checker* bracket_checker_ptr = 0;
21140 lexer::helper::numeric_checker* numeric_checker_ptr = 0;
21141 lexer::helper::sequence_validator* sequence_validator_ptr = 0;
21142 lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
21143
21144 if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
21145 {
21146 set_error(
21148 bracket_checker_ptr->error_token(),
21149 "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
21151 }
21152 else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
21153 {
21154 for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
21155 {
21156 lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
21157
21158 set_error(
21160 error_token,
21161 "ERR006 - Invalid numeric token: '" + error_token.value + "'",
21163 }
21164
21165 if (numeric_checker_ptr->error_count())
21166 {
21167 numeric_checker_ptr->clear_errors();
21168 }
21169 }
21170 else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
21171 {
21172 for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
21173 {
21174 std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
21175
21176 set_error(
21178 error_token.first,
21179 "ERR007 - Invalid token sequence: '" +
21180 error_token.first.value + "' and '" +
21181 error_token.second.value + "'",
21183 }
21184
21185 if (sequence_validator_ptr->error_count())
21186 {
21187 sequence_validator_ptr->clear_errors();
21188 }
21189 }
21190 else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
21191 {
21192 for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
21193 {
21194 std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
21195
21196 set_error(
21198 error_token.first,
21199 "ERR008 - Invalid token sequence: '" +
21200 error_token.first.value + "' and '" +
21201 error_token.second.value + "'",
21203 }
21204
21205 if (sequence_validator3_ptr->error_count())
21206 {
21207 sequence_validator3_ptr->clear_errors();
21208 }
21209 }
21210 }
21211
21212 return false;
21213 }
21214 }
21215
21216 return true;
21217 }
21218
21220 {
21221 return settings_;
21222 }
21223
21224 inline parser_error::type get_error(const std::size_t& index) const
21225 {
21226 if (index < error_list_.size())
21227 return error_list_[index];
21228 else
21229 throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
21230 }
21231
21232 inline std::string error() const
21233 {
21234 if (!error_list_.empty())
21235 {
21236 return error_list_[0].diagnostic;
21237 }
21238 else
21239 return std::string("No Error");
21240 }
21241
21242 inline std::size_t error_count() const
21243 {
21244 return error_list_.size();
21245 }
21246
21248 {
21249 return dec_;
21250 }
21251
21252 inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
21253 {
21254 if (!settings_.replacer_enabled())
21255 return false;
21256 else if (details::is_reserved_word(old_symbol))
21257 return false;
21258 else
21259 return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
21260 }
21261
21262 inline bool remove_replace_symbol(const std::string& symbol)
21263 {
21264 if (!settings_.replacer_enabled())
21265 return false;
21266 else if (details::is_reserved_word(symbol))
21267 return false;
21268 else
21269 return symbol_replacer_.remove(symbol);
21270 }
21271
21273 {
21274 resolve_unknown_symbol_ = true;
21275
21276 if (usr)
21277 unknown_symbol_resolver_ = usr;
21278 else
21279 unknown_symbol_resolver_ = &default_usr_;
21280 }
21281
21283 {
21284 enable_unknown_symbol_resolver(&usr);
21285 }
21286
21288 {
21289 resolve_unknown_symbol_ = false;
21290 unknown_symbol_resolver_ = &default_usr_;
21291 }
21292
21294 {
21295 loop_runtime_check_ = &lrtchk;
21296 }
21297
21299 {
21300 loop_runtime_check_ = loop_runtime_check_ptr(0);
21301 }
21302
21303 private:
21304
21305 inline bool valid_base_operation(const std::string& symbol) const
21306 {
21307 const std::size_t length = symbol.size();
21308
21309 if (
21310 (length < 3) || // Shortest base op symbol length
21311 (length > 9) // Longest base op symbol length
21312 )
21313 return false;
21314 else
21315 return settings_.function_enabled(symbol) &&
21316 (base_ops_map_.end() != base_ops_map_.find(symbol));
21317 }
21318
21319 inline bool valid_vararg_operation(const std::string& symbol) const
21320 {
21321 static const std::string s_sum = "sum" ;
21322 static const std::string s_mul = "mul" ;
21323 static const std::string s_avg = "avg" ;
21324 static const std::string s_min = "min" ;
21325 static const std::string s_max = "max" ;
21326 static const std::string s_mand = "mand";
21327 static const std::string s_mor = "mor" ;
21328 static const std::string s_multi = "~" ;
21329 static const std::string s_mswitch = "[*]" ;
21330
21331 return
21332 (
21333 details::imatch(symbol,s_sum ) ||
21334 details::imatch(symbol,s_mul ) ||
21335 details::imatch(symbol,s_avg ) ||
21336 details::imatch(symbol,s_min ) ||
21337 details::imatch(symbol,s_max ) ||
21338 details::imatch(symbol,s_mand ) ||
21339 details::imatch(symbol,s_mor ) ||
21340 details::imatch(symbol,s_multi ) ||
21341 details::imatch(symbol,s_mswitch)
21342 ) &&
21343 settings_.function_enabled(symbol);
21344 }
21345
21346 bool is_invalid_logic_operation(const details::operator_type operation) const
21347 {
21348 return settings_.logic_disabled(operation);
21349 }
21350
21351 bool is_invalid_arithmetic_operation(const details::operator_type operation) const
21352 {
21353 return settings_.arithmetic_disabled(operation);
21354 }
21355
21356 bool is_invalid_assignment_operation(const details::operator_type operation) const
21357 {
21358 return settings_.assignment_disabled(operation);
21359 }
21360
21361 bool is_invalid_inequality_operation(const details::operator_type operation) const
21362 {
21363 return settings_.inequality_disabled(operation);
21364 }
21365
21366 #ifdef exprtk_enable_debugging
21367 inline void next_token()
21368 {
21369 const std::string ct_str = current_token().value;
21370 const std::size_t ct_pos = current_token().position;
21371 parser_helper::next_token();
21372 const std::string depth(2 * state_.scope_depth,' ');
21373 exprtk_debug(("%s"
21374 "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n",
21375 depth.c_str(),
21376 ct_str.c_str(),
21377 static_cast<unsigned int>(ct_pos),
21378 current_token().value.c_str(),
21379 static_cast<unsigned int>(current_token().position),
21380 static_cast<unsigned int>(state_.stack_depth)));
21381 }
21382 #endif
21383
21384 inline expression_node_ptr parse_corpus()
21385 {
21386 std::vector<expression_node_ptr> arg_list;
21387 std::vector<bool> side_effect_list;
21388
21389 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21390
21391 lexer::token begin_token;
21392 lexer::token end_token;
21393
21394 for ( ; ; )
21395 {
21396 state_.side_effect_present = false;
21397
21398 begin_token = current_token();
21399
21400 expression_node_ptr arg = parse_expression();
21401
21402 if (0 == arg)
21403 {
21404 if (error_list_.empty())
21405 {
21406 set_error(
21408 current_token(),
21409 "ERR009 - Invalid expression encountered",
21411 }
21412
21413 return error_node();
21414 }
21415 else
21416 {
21417 arg_list.push_back(arg);
21418
21419 side_effect_list.push_back(state_.side_effect_present);
21420
21421 end_token = current_token();
21422
21423 const std::string sub_expr = construct_subexpr(begin_token, end_token);
21424
21425 exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
21426 static_cast<int>(arg_list.size() - 1),
21427 sub_expr.c_str()));
21428
21429 exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
21430 static_cast<int>(arg_list.size() - 1),
21431 state_.side_effect_present ? "true" : "false"));
21432
21433 exprtk_debug(("-------------------------------------------------\n"));
21434 }
21435
21436 if (lexer().finished())
21437 break;
21438 else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
21439 {
21440 if (lexer().finished())
21441 break;
21442 else
21443 next_token();
21444 }
21445 }
21446
21447 if (
21448 !arg_list.empty() &&
21449 is_return_node(arg_list.back())
21450 )
21451 {
21452 dec_.final_stmt_return_ = true;
21453 }
21454
21455 const expression_node_ptr result = simplify(arg_list,side_effect_list);
21456
21457 sdd.delete_ptr = (0 == result);
21458
21459 return result;
21460 }
21461
21462 std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
21463 {
21464 std::string result = lexer().substr(begin_token.position,end_token.position);
21465
21466 for (std::size_t i = 0; i < result.size(); ++i)
21467 {
21468 if (details::is_whitespace(result[i])) result[i] = ' ';
21469 }
21470
21471 return result;
21472 }
21473
21474 static const precedence_level default_precedence = e_level00;
21475
21476 struct state_t
21477 {
21478 inline void set(const precedence_level& l,
21479 const precedence_level& r,
21480 const details::operator_type& o)
21481 {
21482 left = l;
21483 right = r;
21484 operation = o;
21485 }
21486
21487 inline void reset()
21488 {
21489 left = e_level00;
21490 right = e_level00;
21491 operation = details::e_default;
21492 }
21493
21494 precedence_level left;
21495 precedence_level right;
21496 details::operator_type operation;
21497 };
21498
21499 inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
21500 {
21501 stack_limit_handler slh(*this);
21502
21503 if (!slh)
21504 {
21505 return error_node();
21506 }
21507
21508 expression_node_ptr expression = parse_branch(precedence);
21509
21510 if (0 == expression)
21511 {
21512 return error_node();
21513 }
21514
21515 bool break_loop = false;
21516
21517 state_t current_state;
21518
21519 for ( ; ; )
21520 {
21521 current_state.reset();
21522
21523 switch (current_token().type)
21524 {
21525 case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
21526 case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
21527 case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
21528 case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
21529 case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
21530 case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
21531 case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break;
21532 case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break;
21533 case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break;
21534 case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break;
21535 case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break;
21536 case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break;
21537 case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break;
21538 case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break;
21539 case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break;
21540 case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break;
21541 case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break;
21542 case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break;
21543 case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break;
21544 default : if (token_t::e_symbol == current_token().type)
21545 {
21546 static const std::string s_and = "and";
21547 static const std::string s_nand = "nand";
21548 static const std::string s_or = "or";
21549 static const std::string s_nor = "nor";
21550 static const std::string s_xor = "xor";
21551 static const std::string s_xnor = "xnor";
21552 static const std::string s_in = "in";
21553 static const std::string s_like = "like";
21554 static const std::string s_ilike = "ilike";
21555 static const std::string s_and1 = "&";
21556 static const std::string s_or1 = "|";
21557 static const std::string s_not = "not";
21558
21559 if (details::imatch(current_token().value,s_and))
21560 {
21561 current_state.set(e_level03, e_level04, details::e_and);
21562 break;
21563 }
21564 else if (details::imatch(current_token().value,s_and1))
21565 {
21566 #ifndef exprtk_disable_sc_andor
21567 current_state.set(e_level03, e_level04, details::e_scand);
21568 #else
21569 current_state.set(e_level03, e_level04, details::e_and);
21570 #endif
21571 break;
21572 }
21573 else if (details::imatch(current_token().value,s_nand))
21574 {
21575 current_state.set(e_level03, e_level04, details::e_nand);
21576 break;
21577 }
21578 else if (details::imatch(current_token().value,s_or))
21579 {
21580 current_state.set(e_level01, e_level02, details::e_or);
21581 break;
21582 }
21583 else if (details::imatch(current_token().value,s_or1))
21584 {
21585 #ifndef exprtk_disable_sc_andor
21586 current_state.set(e_level01, e_level02, details::e_scor);
21587 #else
21588 current_state.set(e_level01, e_level02, details::e_or);
21589 #endif
21590 break;
21591 }
21592 else if (details::imatch(current_token().value,s_nor))
21593 {
21594 current_state.set(e_level01, e_level02, details::e_nor);
21595 break;
21596 }
21597 else if (details::imatch(current_token().value,s_xor))
21598 {
21599 current_state.set(e_level01, e_level02, details::e_xor);
21600 break;
21601 }
21602 else if (details::imatch(current_token().value,s_xnor))
21603 {
21604 current_state.set(e_level01, e_level02, details::e_xnor);
21605 break;
21606 }
21607 else if (details::imatch(current_token().value,s_in))
21608 {
21609 current_state.set(e_level04, e_level04, details::e_in);
21610 break;
21611 }
21612 else if (details::imatch(current_token().value,s_like))
21613 {
21614 current_state.set(e_level04, e_level04, details::e_like);
21615 break;
21616 }
21617 else if (details::imatch(current_token().value,s_ilike))
21618 {
21619 current_state.set(e_level04, e_level04, details::e_ilike);
21620 break;
21621 }
21622 else if (details::imatch(current_token().value,s_not))
21623 {
21624 break;
21625 }
21626 }
21627
21628 break_loop = true;
21629 }
21630
21631 if (break_loop)
21632 {
21633 parse_pending_string_rangesize(expression);
21634 break;
21635 }
21636 else if (current_state.left < precedence)
21637 break;
21638
21639 const lexer::token prev_token = current_token();
21640
21641 next_token();
21642
21643 expression_node_ptr right_branch = error_node();
21644 expression_node_ptr new_expression = error_node();
21645
21646 if (is_invalid_logic_operation(current_state.operation))
21647 {
21648 free_node(node_allocator_,expression);
21649
21650 set_error(
21652 prev_token,
21653 "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
21655
21656 return error_node();
21657 }
21658 else if (is_invalid_arithmetic_operation(current_state.operation))
21659 {
21660 free_node(node_allocator_,expression);
21661
21662 set_error(
21664 prev_token,
21665 "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
21667
21668 return error_node();
21669 }
21670 else if (is_invalid_inequality_operation(current_state.operation))
21671 {
21672 free_node(node_allocator_,expression);
21673
21674 set_error(
21676 prev_token,
21677 "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
21679
21680 return error_node();
21681 }
21682 else if (is_invalid_assignment_operation(current_state.operation))
21683 {
21684 free_node(node_allocator_,expression);
21685
21686 set_error(
21688 prev_token,
21689 "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
21691
21692 return error_node();
21693 }
21694
21695 if (0 != (right_branch = parse_expression(current_state.right)))
21696 {
21697 if (
21698 details::is_return_node( expression) ||
21699 details::is_return_node(right_branch)
21700 )
21701 {
21702 free_node(node_allocator_, expression);
21703 free_node(node_allocator_, right_branch);
21704
21705 set_error(
21707 prev_token,
21708 "ERR014 - Return statements cannot be part of sub-expressions",
21710
21711 return error_node();
21712 }
21713
21714 new_expression = expression_generator_
21715 (
21716 current_state.operation,
21717 expression,
21718 right_branch
21719 );
21720 }
21721
21722 if (0 == new_expression)
21723 {
21724 if (error_list_.empty())
21725 {
21726 set_error(
21728 prev_token,
21729 !synthesis_error_.empty() ?
21730 synthesis_error_ :
21731 "ERR015 - General parsing error at token: '" + prev_token.value + "'",
21733 }
21734
21735 free_node(node_allocator_, expression);
21736 free_node(node_allocator_, right_branch);
21737
21738 return error_node();
21739 }
21740 else
21741 {
21742 if (
21743 token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
21744 (precedence == e_level00)
21745 )
21746 {
21747 expression = parse_ternary_conditional_statement(new_expression);
21748 }
21749 else
21750 expression = new_expression;
21751
21752 parse_pending_string_rangesize(expression);
21753 }
21754 }
21755
21756 if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
21757 {
21758 set_error(
21760 current_token(),
21761 "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
21762 " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
21764
21765 free_node(node_allocator_,expression);
21766
21767 return error_node();
21768 }
21769
21770 return expression;
21771 }
21772
21773 bool simplify_unary_negation_branch(expression_node_ptr& node)
21774 {
21775 {
21776 typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
21777 ubn_t* n = dynamic_cast<ubn_t*>(node);
21778
21779 if (n)
21780 {
21781 expression_node_ptr un_r = n->branch(0);
21782 n->release();
21783 free_node(node_allocator_,node);
21784 node = un_r;
21785
21786 return true;
21787 }
21788 }
21789
21790 {
21791 typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
21792
21793 uvn_t* n = dynamic_cast<uvn_t*>(node);
21794
21795 if (n)
21796 {
21797 const T& v = n->v();
21798 expression_node_ptr return_node = error_node();
21799
21800 if (
21801 (0 != (return_node = symtab_store_.get_variable(v))) ||
21802 (0 != (return_node = sem_ .get_variable(v)))
21803 )
21804 {
21805 free_node(node_allocator_,node);
21806 node = return_node;
21807
21808 return true;
21809 }
21810 else
21811 {
21812 set_error(
21814 current_token(),
21815 "ERR017 - Failed to find variable node in symbol table",
21817
21818 free_node(node_allocator_,node);
21819
21820 return false;
21821 }
21822 }
21823 }
21824
21825 return false;
21826 }
21827
21828 static inline expression_node_ptr error_node()
21829 {
21830 return reinterpret_cast<expression_node_ptr>(0);
21831 }
21832
21833 struct scoped_expression_delete
21834 {
21835 scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
21836 : delete_ptr(true),
21837 parser_(pr),
21838 expression_(expression)
21839 {}
21840
21841 ~scoped_expression_delete()
21842 {
21843 if (delete_ptr)
21844 {
21845 free_node(parser_.node_allocator_, expression_);
21846 }
21847 }
21848
21849 bool delete_ptr;
21850 parser<T>& parser_;
21851 expression_node_ptr& expression_;
21852
21853 private:
21854
21855 scoped_expression_delete& operator=(const scoped_expression_delete&);
21856 };
21857
21858 template <typename Type, std::size_t N>
21859 struct scoped_delete
21860 {
21861 typedef Type* ptr_t;
21862
21863 scoped_delete(parser<T>& pr, ptr_t& p)
21864 : delete_ptr(true),
21865 parser_(pr),
21866 p_(&p)
21867 {}
21868
21869 scoped_delete(parser<T>& pr, ptr_t (&p)[N])
21870 : delete_ptr(true),
21871 parser_(pr),
21872 p_(&p[0])
21873 {}
21874
21875 ~scoped_delete()
21876 {
21877 if (delete_ptr)
21878 {
21879 for (std::size_t i = 0; i < N; ++i)
21880 {
21881 free_node(parser_.node_allocator_, p_[i]);
21882 }
21883 }
21884 }
21885
21886 bool delete_ptr;
21887 parser<T>& parser_;
21888 ptr_t* p_;
21889
21890 private:
21891
21892 scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
21893 };
21894
21895 template <typename Type>
21896 struct scoped_deq_delete
21897 {
21898 typedef Type* ptr_t;
21899
21900 scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
21901 : delete_ptr(true),
21902 parser_(pr),
21903 deq_(deq)
21904 {}
21905
21906 ~scoped_deq_delete()
21907 {
21908 if (delete_ptr && !deq_.empty())
21909 {
21910 for (std::size_t i = 0; i < deq_.size(); ++i)
21911 {
21912 free_node(parser_.node_allocator_,deq_[i]);
21913 }
21914
21915 deq_.clear();
21916 }
21917 }
21918
21919 bool delete_ptr;
21920 parser<T>& parser_;
21921 std::deque<ptr_t>& deq_;
21922
21923 private:
21924
21925 scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
21926 };
21927
21928 template <typename Type>
21929 struct scoped_vec_delete
21930 {
21931 typedef Type* ptr_t;
21932
21933 scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21934 : delete_ptr(true),
21935 parser_(pr),
21936 vec_(vec)
21937 {}
21938
21939 ~scoped_vec_delete()
21940 {
21941 if (delete_ptr && !vec_.empty())
21942 {
21943 for (std::size_t i = 0; i < vec_.size(); ++i)
21944 {
21945 free_node(parser_.node_allocator_,vec_[i]);
21946 }
21947
21948 vec_.clear();
21949 }
21950 }
21951
21952 bool delete_ptr;
21953 parser<T>& parser_;
21954 std::vector<ptr_t>& vec_;
21955
21956 private:
21957
21958 scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
21959 };
21960
21961 struct scoped_bool_negator
21962 {
21963 explicit scoped_bool_negator(bool& bb)
21964 : b(bb)
21965 { b = !b; }
21966
21967 ~scoped_bool_negator()
21968 { b = !b; }
21969
21970 bool& b;
21971 };
21972
21973 struct scoped_bool_or_restorer
21974 {
21975 explicit scoped_bool_or_restorer(bool& bb)
21976 : b(bb),
21977 original_value_(bb)
21978 {}
21979
21980 ~scoped_bool_or_restorer()
21981 {
21982 b = b || original_value_;
21983 }
21984
21985 bool& b;
21986 bool original_value_;
21987 };
21988
21989 struct scoped_inc_dec
21990 {
21991 explicit scoped_inc_dec(std::size_t& v)
21992 : v_(v)
21993 { ++v_; }
21994
21995 ~scoped_inc_dec()
21996 {
21997 assert(v_ > 0);
21998 --v_;
21999 }
22000
22001 std::size_t& v_;
22002 };
22003
22004 inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
22005 {
22006 expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
22007
22008 switch (function->param_count)
22009 {
22010 case 0 : func_node = parse_function_call_0 (function,function_name); break;
22011 case 1 : func_node = parse_function_call< 1>(function,function_name); break;
22012 case 2 : func_node = parse_function_call< 2>(function,function_name); break;
22013 case 3 : func_node = parse_function_call< 3>(function,function_name); break;
22014 case 4 : func_node = parse_function_call< 4>(function,function_name); break;
22015 case 5 : func_node = parse_function_call< 5>(function,function_name); break;
22016 case 6 : func_node = parse_function_call< 6>(function,function_name); break;
22017 case 7 : func_node = parse_function_call< 7>(function,function_name); break;
22018 case 8 : func_node = parse_function_call< 8>(function,function_name); break;
22019 case 9 : func_node = parse_function_call< 9>(function,function_name); break;
22020 case 10 : func_node = parse_function_call<10>(function,function_name); break;
22021 case 11 : func_node = parse_function_call<11>(function,function_name); break;
22022 case 12 : func_node = parse_function_call<12>(function,function_name); break;
22023 case 13 : func_node = parse_function_call<13>(function,function_name); break;
22024 case 14 : func_node = parse_function_call<14>(function,function_name); break;
22025 case 15 : func_node = parse_function_call<15>(function,function_name); break;
22026 case 16 : func_node = parse_function_call<16>(function,function_name); break;
22027 case 17 : func_node = parse_function_call<17>(function,function_name); break;
22028 case 18 : func_node = parse_function_call<18>(function,function_name); break;
22029 case 19 : func_node = parse_function_call<19>(function,function_name); break;
22030 case 20 : func_node = parse_function_call<20>(function,function_name); break;
22031 default : {
22032 set_error(
22034 current_token(),
22035 "ERR018 - Invalid number of parameters for function: '" + function_name + "'",
22037
22038 return error_node();
22039 }
22040 }
22041
22042 if (func_node)
22043 return func_node;
22044 else
22045 {
22046 set_error(
22048 current_token(),
22049 "ERR019 - Failed to generate call to function: '" + function_name + "'",
22051
22052 return error_node();
22053 }
22054 }
22055
22056 template <std::size_t NumberofParameters>
22057 inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
22058 {
22059 #ifdef _MSC_VER
22060 #pragma warning(push)
22061 #pragma warning(disable: 4127)
22062 #endif
22063 if (0 == NumberofParameters)
22064 {
22065 set_error(
22067 current_token(),
22068 "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
22070
22071 return error_node();
22072 }
22073 #ifdef _MSC_VER
22074 #pragma warning(pop)
22075 #endif
22076
22077 expression_node_ptr branch[NumberofParameters];
22078 expression_node_ptr result = error_node();
22079
22080 std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
22081
22082 scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
22083
22084 next_token();
22085
22086 if (!token_is(token_t::e_lbracket))
22087 {
22088 set_error(
22090 current_token(),
22091 "ERR021 - Expecting argument list for function: '" + function_name + "'",
22093
22094 return error_node();
22095 }
22096
22097 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
22098 {
22099 branch[i] = parse_expression();
22100
22101 if (0 == branch[i])
22102 {
22103 set_error(
22105 current_token(),
22106 "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
22108
22109 return error_node();
22110 }
22111 else if (i < static_cast<int>(NumberofParameters - 1))
22112 {
22113 if (!token_is(token_t::e_comma))
22114 {
22115 set_error(
22117 current_token(),
22118 "ERR023 - Invalid number of arguments for function: '" + function_name + "'",
22120
22121 return error_node();
22122 }
22123 }
22124 }
22125
22126 if (!token_is(token_t::e_rbracket))
22127 {
22128 set_error(
22130 current_token(),
22131 "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
22133
22134 return error_node();
22135 }
22136 else
22137 result = expression_generator_.function(function,branch);
22138
22139 sd.delete_ptr = (0 == result);
22140
22141 return result;
22142 }
22143
22144 inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
22145 {
22146 expression_node_ptr result = expression_generator_.function(function);
22147
22148 state_.side_effect_present = function->has_side_effects();
22149
22150 next_token();
22151
22152 if (
22153 token_is(token_t::e_lbracket) &&
22154 !token_is(token_t::e_rbracket)
22155 )
22156 {
22157 set_error(
22159 current_token(),
22160 "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'",
22162
22163 free_node(node_allocator_,result);
22164
22165 return error_node();
22166 }
22167 else
22168 return result;
22169 }
22170
22171 template <std::size_t MaxNumberofParameters>
22172 inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
22173 {
22174 std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
22175
22176 scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
22177
22178 next_token();
22179
22180 if (!token_is(token_t::e_lbracket))
22181 {
22182 set_error(
22184 current_token(),
22185 "ERR026 - Expected a '(' at start of function call to '" + function_name +
22186 "', instead got: '" + current_token().value + "'",
22188
22189 return 0;
22190 }
22191
22192 if (token_is(token_t::e_rbracket, e_hold))
22193 {
22194 set_error(
22196 current_token(),
22197 "ERR027 - Expected at least one input parameter for function call '" + function_name + "'",
22199
22200 return 0;
22201 }
22202
22203 std::size_t param_index = 0;
22204
22205 for (; param_index < MaxNumberofParameters; ++param_index)
22206 {
22207 param_list[param_index] = parse_expression();
22208
22209 if (0 == param_list[param_index])
22210 return 0;
22211 else if (token_is(token_t::e_rbracket))
22212 {
22213 sd.delete_ptr = false;
22214 break;
22215 }
22216 else if (token_is(token_t::e_comma))
22217 continue;
22218 else
22219 {
22220 set_error(
22222 current_token(),
22223 "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
22225
22226 return 0;
22227 }
22228 }
22229
22230 if (sd.delete_ptr)
22231 {
22232 set_error(
22234 current_token(),
22235 "ERR029 - Invalid number of input parameters passed to function '" + function_name + "'",
22237
22238 return 0;
22239 }
22240
22241 return (param_index + 1);
22242 }
22243
22244 inline expression_node_ptr parse_base_operation()
22245 {
22246 typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
22247
22248 const std::string operation_name = current_token().value;
22249 const token_t diagnostic_token = current_token();
22250
22251 map_range_t itr_range = base_ops_map_.equal_range(operation_name);
22252
22253 if (0 == std::distance(itr_range.first,itr_range.second))
22254 {
22255 set_error(
22257 diagnostic_token,
22258 "ERR030 - No entry found for base operation: " + operation_name,
22260
22261 return error_node();
22262 }
22263
22264 static const std::size_t MaxNumberofParameters = 4;
22265 expression_node_ptr param_list[MaxNumberofParameters] = {0};
22266
22267 const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
22268
22269 if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
22270 {
22271 for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
22272 {
22273 const details::base_operation_t& operation = itr->second;
22274
22275 if (operation.num_params == parameter_count)
22276 {
22277 switch (parameter_count)
22278 {
22279 #define base_opr_case(N) \
22280 case N : { \
22281 expression_node_ptr pl##N[N] = {0}; \
22282 std::copy(param_list, param_list + N, pl##N); \
22283 lodge_symbol(operation_name, e_st_function); \
22284 return expression_generator_(operation.type, pl##N); \
22285 } \
22286
22287 base_opr_case(1)
22288 base_opr_case(2)
22289 base_opr_case(3)
22290 base_opr_case(4)
22291 #undef base_opr_case
22292 }
22293 }
22294 }
22295 }
22296
22297 for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
22298 {
22299 free_node(node_allocator_, param_list[i]);
22300 }
22301
22302 set_error(
22304 diagnostic_token,
22305 "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'",
22307
22308 return error_node();
22309 }
22310
22311 inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
22312 {
22313 // Parse: [if][(][condition][,][consequent][,][alternative][)]
22314
22315 expression_node_ptr consequent = error_node();
22316 expression_node_ptr alternative = error_node();
22317
22318 bool result = true;
22319
22320 if (!token_is(token_t::e_comma))
22321 {
22322 set_error(
22324 current_token(),
22325 "ERR032 - Expected ',' between if-statement condition and consequent",
22327 result = false;
22328 }
22329 else if (0 == (consequent = parse_expression()))
22330 {
22331 set_error(
22333 current_token(),
22334 "ERR033 - Failed to parse consequent for if-statement",
22336 result = false;
22337 }
22338 else if (!token_is(token_t::e_comma))
22339 {
22340 set_error(
22342 current_token(),
22343 "ERR034 - Expected ',' between if-statement consequent and alternative",
22345 result = false;
22346 }
22347 else if (0 == (alternative = parse_expression()))
22348 {
22349 set_error(
22351 current_token(),
22352 "ERR035 - Failed to parse alternative for if-statement",
22354 result = false;
22355 }
22356 else if (!token_is(token_t::e_rbracket))
22357 {
22358 set_error(
22360 current_token(),
22361 "ERR036 - Expected ')' at the end of if-statement",
22363 result = false;
22364 }
22365
22366 #ifndef exprtk_disable_string_capabilities
22367 if (result)
22368 {
22369 const bool consq_is_str = is_generally_string_node( consequent);
22370 const bool alter_is_str = is_generally_string_node(alternative);
22371
22372 if (consq_is_str || alter_is_str)
22373 {
22374 if (consq_is_str && alter_is_str)
22375 {
22376 return expression_generator_
22377 .conditional_string(condition, consequent, alternative);
22378 }
22379
22380 set_error(
22382 current_token(),
22383 "ERR037 - Return types of ternary if-statement differ",
22385
22386 result = false;
22387 }
22388 }
22389 #endif
22390
22391 if (!result)
22392 {
22393 free_node(node_allocator_, condition );
22394 free_node(node_allocator_, consequent );
22395 free_node(node_allocator_, alternative);
22396
22397 return error_node();
22398 }
22399 else
22400 return expression_generator_
22401 .conditional(condition, consequent, alternative);
22402 }
22403
22404 inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
22405 {
22406 expression_node_ptr consequent = error_node();
22407 expression_node_ptr alternative = error_node();
22408
22409 bool result = true;
22410
22411 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22412 {
22413 if (0 == (consequent = parse_multi_sequence("if-statement-01")))
22414 {
22415 set_error(
22417 current_token(),
22418 "ERR038 - Failed to parse body of consequent for if-statement",
22420
22421 result = false;
22422 }
22423 }
22424 else
22425 {
22426 if (
22427 settings_.commutative_check_enabled() &&
22428 token_is(token_t::e_mul,prsrhlpr_t::e_hold)
22429 )
22430 {
22431 next_token();
22432 }
22433
22434 if (0 != (consequent = parse_expression()))
22435 {
22436 if (!token_is(token_t::e_eof))
22437 {
22438 set_error(
22440 current_token(),
22441 "ERR039 - Expected ';' at the end of the consequent for if-statement",
22443
22444 result = false;
22445 }
22446 }
22447 else
22448 {
22449 set_error(
22451 current_token(),
22452 "ERR040 - Failed to parse body of consequent for if-statement",
22454
22455 result = false;
22456 }
22457 }
22458
22459 if (result)
22460 {
22461 if (details::imatch(current_token().value,"else"))
22462 {
22463 next_token();
22464
22465 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22466 {
22467 if (0 == (alternative = parse_multi_sequence("else-statement-01")))
22468 {
22469 set_error(
22471 current_token(),
22472 "ERR041 - Failed to parse body of the 'else' for if-statement",
22474
22475 result = false;
22476 }
22477 }
22478 else if (details::imatch(current_token().value,"if"))
22479 {
22480 if (0 == (alternative = parse_conditional_statement()))
22481 {
22482 set_error(
22484 current_token(),
22485 "ERR042 - Failed to parse body of if-else statement",
22487
22488 result = false;
22489 }
22490 }
22491 else if (0 != (alternative = parse_expression()))
22492 {
22493 if (!token_is(token_t::e_eof))
22494 {
22495 set_error(
22497 current_token(),
22498 "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement",
22500
22501 result = false;
22502 }
22503 }
22504 else
22505 {
22506 set_error(
22508 current_token(),
22509 "ERR044 - Failed to parse body of the 'else' for if-statement",
22511
22512 result = false;
22513 }
22514 }
22515 }
22516
22517 #ifndef exprtk_disable_string_capabilities
22518 if (result)
22519 {
22520 const bool consq_is_str = is_generally_string_node( consequent);
22521 const bool alter_is_str = is_generally_string_node(alternative);
22522
22523 if (consq_is_str || alter_is_str)
22524 {
22525 if (consq_is_str && alter_is_str)
22526 {
22527 return expression_generator_
22528 .conditional_string(condition, consequent, alternative);
22529 }
22530
22531 set_error(
22533 current_token(),
22534 "ERR045 - Return types of ternary if-statement differ",
22536
22537 result = false;
22538 }
22539 }
22540 #endif
22541
22542 if (!result)
22543 {
22544 free_node(node_allocator_, condition);
22545 free_node(node_allocator_, consequent);
22546 free_node(node_allocator_, alternative);
22547
22548 return error_node();
22549 }
22550 else
22551 return expression_generator_
22552 .conditional(condition, consequent, alternative);
22553 }
22554
22555 inline expression_node_ptr parse_conditional_statement()
22556 {
22557 expression_node_ptr condition = error_node();
22558
22559 next_token();
22560
22561 if (!token_is(token_t::e_lbracket))
22562 {
22563 set_error(
22565 current_token(),
22566 "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
22568
22569 return error_node();
22570 }
22571 else if (0 == (condition = parse_expression()))
22572 {
22573 set_error(
22575 current_token(),
22576 "ERR047 - Failed to parse condition for if-statement",
22578
22579 return error_node();
22580 }
22581 else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
22582 {
22583 // if (x,y,z)
22584 return parse_conditional_statement_01(condition);
22585 }
22586 else if (token_is(token_t::e_rbracket))
22587 {
22588 // 00. if (x) y;
22589 // 01. if (x) y; else z;
22590 // 02. if (x) y; else {z0; ... zn;}
22591 // 03. if (x) y; else if (z) w;
22592 // 04. if (x) y; else if (z) w; else u;
22593 // 05. if (x) y; else if (z) w; else {u0; ... un;}
22594 // 06. if (x) y; else if (z) {w0; ... wn;}
22595 // 07. if (x) {y0; ... yn;}
22596 // 08. if (x) {y0; ... yn;} else z;
22597 // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
22598 // 10. if (x) {y0; ... yn;} else if (z) w;
22599 // 11. if (x) {y0; ... yn;} else if (z) w; else u;
22600 // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
22601 // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
22602 return parse_conditional_statement_02(condition);
22603 }
22604
22605 set_error(
22607 current_token(),
22608 "ERR048 - Invalid if-statement",
22610
22611 free_node(node_allocator_,condition);
22612
22613 return error_node();
22614 }
22615
22616 inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
22617 {
22618 // Parse: [condition][?][consequent][:][alternative]
22619 expression_node_ptr consequent = error_node();
22620 expression_node_ptr alternative = error_node();
22621
22622 bool result = true;
22623
22624 if (0 == condition)
22625 {
22626 set_error(
22628 current_token(),
22629 "ERR049 - Encountered invalid condition branch for ternary if-statement",
22631
22632 return error_node();
22633 }
22634 else if (!token_is(token_t::e_ternary))
22635 {
22636 set_error(
22638 current_token(),
22639 "ERR050 - Expected '?' after condition of ternary if-statement",
22641
22642 result = false;
22643 }
22644 else if (0 == (consequent = parse_expression()))
22645 {
22646 set_error(
22648 current_token(),
22649 "ERR051 - Failed to parse consequent for ternary if-statement",
22651
22652 result = false;
22653 }
22654 else if (!token_is(token_t::e_colon))
22655 {
22656 set_error(
22658 current_token(),
22659 "ERR052 - Expected ':' between ternary if-statement consequent and alternative",
22661
22662 result = false;
22663 }
22664 else if (0 == (alternative = parse_expression()))
22665 {
22666 set_error(
22668 current_token(),
22669 "ERR053 - Failed to parse alternative for ternary if-statement",
22671
22672 result = false;
22673 }
22674
22675 #ifndef exprtk_disable_string_capabilities
22676 if (result)
22677 {
22678 const bool consq_is_str = is_generally_string_node( consequent);
22679 const bool alter_is_str = is_generally_string_node(alternative);
22680
22681 if (consq_is_str || alter_is_str)
22682 {
22683 if (consq_is_str && alter_is_str)
22684 {
22685 return expression_generator_
22686 .conditional_string(condition, consequent, alternative);
22687 }
22688
22689 set_error(
22691 current_token(),
22692 "ERR054 - Return types of ternary if-statement differ",
22694
22695 result = false;
22696 }
22697 }
22698 #endif
22699
22700 if (!result)
22701 {
22702 free_node(node_allocator_, condition);
22703 free_node(node_allocator_, consequent);
22704 free_node(node_allocator_, alternative);
22705
22706 return error_node();
22707 }
22708 else
22709 return expression_generator_
22710 .conditional(condition, consequent, alternative);
22711 }
22712
22713 inline expression_node_ptr parse_not_statement()
22714 {
22715 if (settings_.logic_disabled("not"))
22716 {
22717 set_error(
22719 current_token(),
22720 "ERR055 - Invalid or disabled logic operation 'not'",
22722
22723 return error_node();
22724 }
22725
22726 return parse_base_operation();
22727 }
22728
22729 inline expression_node_ptr parse_while_loop()
22730 {
22731 // Parse: [while][(][test expr][)][{][expression][}]
22732 expression_node_ptr condition = error_node();
22733 expression_node_ptr branch = error_node();
22734 expression_node_ptr result_node = error_node();
22735
22736 bool result = true;
22737
22738 next_token();
22739
22740 if (!token_is(token_t::e_lbracket))
22741 {
22742 set_error(
22744 current_token(),
22745 "ERR056 - Expected '(' at start of while-loop condition statement",
22747
22748 return error_node();
22749 }
22750 else if (0 == (condition = parse_expression()))
22751 {
22752 set_error(
22754 current_token(),
22755 "ERR057 - Failed to parse condition for while-loop",
22757
22758 return error_node();
22759 }
22760 else if (!token_is(token_t::e_rbracket))
22761 {
22762 set_error(
22764 current_token(),
22765 "ERR058 - Expected ')' at end of while-loop condition statement",
22767
22768 result = false;
22769 }
22770
22771 brkcnt_list_.push_front(false);
22772
22773 if (result)
22774 {
22775 scoped_inc_dec sid(state_.parsing_loop_stmt_count);
22776
22777 if (0 == (branch = parse_multi_sequence("while-loop")))
22778 {
22779 set_error(
22781 current_token(),
22782 "ERR059 - Failed to parse body of while-loop"));
22783 result = false;
22784 }
22785 else if (0 == (result_node = expression_generator_.while_loop(condition,
22786 branch,
22787 brkcnt_list_.front())))
22788 {
22789 set_error(
22791 current_token(),
22792 "ERR060 - Failed to synthesize while-loop",
22794
22795 result = false;
22796 }
22797 }
22798
22799 if (!result)
22800 {
22801 free_node(node_allocator_, branch);
22802 free_node(node_allocator_, condition);
22803 free_node(node_allocator_, result_node);
22804
22805 brkcnt_list_.pop_front();
22806
22807 return error_node();
22808 }
22809 else
22810 return result_node;
22811 }
22812
22813 inline expression_node_ptr parse_repeat_until_loop()
22814 {
22815 // Parse: [repeat][{][expression][}][until][(][test expr][)]
22816 expression_node_ptr condition = error_node();
22817 expression_node_ptr branch = error_node();
22818 next_token();
22819
22820 std::vector<expression_node_ptr> arg_list;
22821 std::vector<bool> side_effect_list;
22822
22823 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22824
22825 brkcnt_list_.push_front(false);
22826
22827 if (details::imatch(current_token().value,"until"))
22828 {
22829 next_token();
22830 branch = node_allocator_.allocate<details::null_node<T> >();
22831 }
22832 else
22833 {
22834 const token_t::token_type seperator = token_t::e_eof;
22835
22836 scope_handler sh(*this);
22837
22838 scoped_bool_or_restorer sbr(state_.side_effect_present);
22839
22840 scoped_inc_dec sid(state_.parsing_loop_stmt_count);
22841
22842 for ( ; ; )
22843 {
22844 state_.side_effect_present = false;
22845
22846 expression_node_ptr arg = parse_expression();
22847
22848 if (0 == arg)
22849 return error_node();
22850 else
22851 {
22852 arg_list.push_back(arg);
22853 side_effect_list.push_back(state_.side_effect_present);
22854 }
22855
22856 if (details::imatch(current_token().value,"until"))
22857 {
22858 next_token();
22859 break;
22860 }
22861
22862 const bool is_next_until = peek_token_is(token_t::e_symbol) &&
22863 peek_token_is("until");
22864
22865 if (!token_is(seperator) && is_next_until)
22866 {
22867 set_error(
22869 current_token(),
22870 "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
22872
22873 return error_node();
22874 }
22875
22876 if (details::imatch(current_token().value,"until"))
22877 {
22878 next_token();
22879 break;
22880 }
22881 }
22882
22883 branch = simplify(arg_list,side_effect_list);
22884
22885 sdd.delete_ptr = (0 == branch);
22886
22887 if (sdd.delete_ptr)
22888 {
22889 brkcnt_list_.pop_front();
22890
22891 set_error(
22893 current_token(),
22894 "ERR062 - Failed to parse body of repeat until loop",
22896
22897 return error_node();
22898 }
22899 }
22900
22901 if (!token_is(token_t::e_lbracket))
22902 {
22903 brkcnt_list_.pop_front();
22904
22905 set_error(
22907 current_token(),
22908 "ERR063 - Expected '(' before condition statement of repeat until loop",
22910
22911 free_node(node_allocator_,branch);
22912
22913 return error_node();
22914 }
22915 else if (0 == (condition = parse_expression()))
22916 {
22917 brkcnt_list_.pop_front();
22918
22919 set_error(
22921 current_token(),
22922 "ERR064 - Failed to parse condition for repeat until loop",
22924
22925 free_node(node_allocator_,branch);
22926
22927 return error_node();
22928 }
22929 else if (!token_is(token_t::e_rbracket))
22930 {
22931 set_error(
22933 current_token(),
22934 "ERR065 - Expected ')' after condition of repeat until loop",
22936
22937 free_node(node_allocator_, branch);
22938 free_node(node_allocator_, condition);
22939
22940 brkcnt_list_.pop_front();
22941
22942 return error_node();
22943 }
22944
22945 expression_node_ptr result;
22946
22947 result = expression_generator_
22948 .repeat_until_loop(condition, branch, brkcnt_list_.front());
22949
22950 if (0 == result)
22951 {
22952 set_error(
22954 current_token(),
22955 "ERR066 - Failed to synthesize repeat until loop",
22957
22958 free_node(node_allocator_,condition);
22959
22960 brkcnt_list_.pop_front();
22961
22962 return error_node();
22963 }
22964 else
22965 {
22966 brkcnt_list_.pop_front();
22967 return result;
22968 }
22969 }
22970
22971 inline expression_node_ptr parse_for_loop()
22972 {
22973 expression_node_ptr initialiser = error_node();
22974 expression_node_ptr condition = error_node();
22975 expression_node_ptr incrementor = error_node();
22976 expression_node_ptr loop_body = error_node();
22977
22978 scope_element* se = 0;
22979 bool result = true;
22980
22981 next_token();
22982
22983 scope_handler sh(*this);
22984
22985 if (!token_is(token_t::e_lbracket))
22986 {
22987 set_error(
22989 current_token(),
22990 "ERR067 - Expected '(' at start of for-loop",
22992
22993 return error_node();
22994 }
22995
22996 if (!token_is(token_t::e_eof))
22997 {
22998 if (
22999 !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
23000 details::imatch(current_token().value,"var")
23001 )
23002 {
23003 next_token();
23004
23005 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
23006 {
23007 set_error(
23009 current_token(),
23010 "ERR068 - Expected a variable at the start of initialiser section of for-loop",
23012
23013 return error_node();
23014 }
23015 else if (!peek_token_is(token_t::e_assign))
23016 {
23017 set_error(
23019 current_token(),
23020 "ERR069 - Expected variable assignment of initialiser section of for-loop",
23022
23023 return error_node();
23024 }
23025
23026 const std::string loop_counter_symbol = current_token().value;
23027
23028 se = &sem_.get_element(loop_counter_symbol);
23029
23030 if ((se->name == loop_counter_symbol) && se->active)
23031 {
23032 set_error(
23034 current_token(),
23035 "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
23037
23038 return error_node();
23039 }
23040 else if (!symtab_store_.is_variable(loop_counter_symbol))
23041 {
23042 if (
23043 !se->active &&
23044 (se->name == loop_counter_symbol) &&
23045 (se->type == scope_element::e_variable)
23046 )
23047 {
23048 se->active = true;
23049 se->ref_count++;
23050 }
23051 else
23052 {
23053 scope_element nse;
23054 nse.name = loop_counter_symbol;
23055 nse.active = true;
23056 nse.ref_count = 1;
23057 nse.type = scope_element::e_variable;
23058 nse.depth = state_.scope_depth;
23059 nse.data = new T(T(0));
23060 nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
23061
23062 if (!sem_.add_element(nse))
23063 {
23064 set_error(
23066 current_token(),
23067 "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
23069
23070 sem_.free_element(nse);
23071
23072 result = false;
23073 }
23074 else
23075 {
23076 exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
23077
23078 state_.activate_side_effect("parse_for_loop()");
23079 }
23080 }
23081 }
23082 }
23083
23084 if (0 == (initialiser = parse_expression()))
23085 {
23086 set_error(
23088 current_token(),
23089 "ERR072 - Failed to parse initialiser of for-loop",
23091
23092 result = false;
23093 }
23094 else if (!token_is(token_t::e_eof))
23095 {
23096 set_error(
23098 current_token(),
23099 "ERR073 - Expected ';' after initialiser of for-loop",
23101
23102 result = false;
23103 }
23104 }
23105
23106 if (!token_is(token_t::e_eof))
23107 {
23108 if (0 == (condition = parse_expression()))
23109 {
23110 set_error(
23112 current_token(),
23113 "ERR074 - Failed to parse condition of for-loop",
23115
23116 result = false;
23117 }
23118 else if (!token_is(token_t::e_eof))
23119 {
23120 set_error(
23122 current_token(),
23123 "ERR075 - Expected ';' after condition section of for-loop",
23125
23126 result = false;
23127 }
23128 }
23129
23130 if (!token_is(token_t::e_rbracket))
23131 {
23132 if (0 == (incrementor = parse_expression()))
23133 {
23134 set_error(
23136 current_token(),
23137 "ERR076 - Failed to parse incrementor of for-loop",
23139
23140 result = false;
23141 }
23142 else if (!token_is(token_t::e_rbracket))
23143 {
23144 set_error(
23146 current_token(),
23147 "ERR077 - Expected ')' after incrementor section of for-loop",
23149
23150 result = false;
23151 }
23152 }
23153
23154 if (result)
23155 {
23156 brkcnt_list_.push_front(false);
23157
23158 scoped_inc_dec sid(state_.parsing_loop_stmt_count);
23159
23160 if (0 == (loop_body = parse_multi_sequence("for-loop")))
23161 {
23162 set_error(
23164 current_token(),
23165 "ERR078 - Failed to parse body of for-loop",
23167
23168 result = false;
23169 }
23170 }
23171
23172 if (!result)
23173 {
23174 if (se)
23175 {
23176 se->ref_count--;
23177 }
23178
23179 free_node(node_allocator_, initialiser);
23180 free_node(node_allocator_, condition);
23181 free_node(node_allocator_, incrementor);
23182 free_node(node_allocator_, loop_body);
23183
23184 if (!brkcnt_list_.empty())
23185 {
23186 brkcnt_list_.pop_front();
23187 }
23188
23189 return error_node();
23190 }
23191 else
23192 {
23193 expression_node_ptr result_node =
23194 expression_generator_.for_loop(initialiser,
23195 condition,
23196 incrementor,
23197 loop_body,
23198 brkcnt_list_.front());
23199 brkcnt_list_.pop_front();
23200
23201 return result_node;
23202 }
23203 }
23204
23205 inline expression_node_ptr parse_switch_statement()
23206 {
23207 std::vector<expression_node_ptr> arg_list;
23208 expression_node_ptr result = error_node();
23209
23210 if (!details::imatch(current_token().value,"switch"))
23211 {
23212 set_error(
23214 current_token(),
23215 "ERR079 - Expected keyword 'switch'",
23217
23218 return error_node();
23219 }
23220
23221 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
23222
23223 next_token();
23224
23225 if (!token_is(token_t::e_lcrlbracket))
23226 {
23227 set_error(
23229 current_token(),
23230 "ERR080 - Expected '{' for call to switch statement",
23232
23233 return error_node();
23234 }
23235
23236 expression_node_ptr default_statement = error_node();
23237
23238 scoped_expression_delete defstmt_delete((*this), default_statement);
23239
23240 for ( ; ; )
23241 {
23242 if (details::imatch("case",current_token().value))
23243 {
23244 next_token();
23245
23246 expression_node_ptr condition = parse_expression();
23247
23248 if (0 == condition)
23249 return error_node();
23250 else if (!token_is(token_t::e_colon))
23251 {
23252 set_error(
23254 current_token(),
23255 "ERR081 - Expected ':' for case of switch statement",
23257
23258 free_node(node_allocator_, condition);
23259
23260 return error_node();
23261 }
23262
23263 expression_node_ptr consequent = parse_expression();
23264
23265 if (0 == consequent)
23266 {
23267 free_node(node_allocator_, condition);
23268
23269 return error_node();
23270 }
23271 else if (!token_is(token_t::e_eof))
23272 {
23273 set_error(
23275 current_token(),
23276 "ERR082 - Expected ';' at end of case for switch statement",
23278
23279 free_node(node_allocator_, condition);
23280 free_node(node_allocator_, consequent);
23281
23282 return error_node();
23283 }
23284
23285 // Can we optimise away the case statement?
23286 if (is_constant_node(condition) && is_false(condition))
23287 {
23288 free_node(node_allocator_, condition);
23289 free_node(node_allocator_, consequent);
23290 }
23291 else
23292 {
23293 arg_list.push_back( condition);
23294 arg_list.push_back(consequent);
23295 }
23296
23297 }
23298 else if (details::imatch("default",current_token().value))
23299 {
23300 if (0 != default_statement)
23301 {
23302 set_error(
23304 current_token(),
23305 "ERR083 - Multiple default cases for switch statement",
23307
23308 return error_node();
23309 }
23310
23311 next_token();
23312
23313 if (!token_is(token_t::e_colon))
23314 {
23315 set_error(
23317 current_token(),
23318 "ERR084 - Expected ':' for default of switch statement",
23320
23321 return error_node();
23322 }
23323
23324 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
23325 default_statement = parse_multi_sequence("switch-default");
23326 else
23327 default_statement = parse_expression();
23328
23329 if (0 == default_statement)
23330 return error_node();
23331 else if (!token_is(token_t::e_eof))
23332 {
23333 set_error(
23335 current_token(),
23336 "ERR085 - Expected ';' at end of default for switch statement",
23338
23339 return error_node();
23340 }
23341 }
23342 else if (token_is(token_t::e_rcrlbracket))
23343 break;
23344 else
23345 {
23346 set_error(
23348 current_token(),
23349 "ERR086 - Expected '}' at end of switch statement",
23351
23352 return error_node();
23353 }
23354 }
23355
23356 const bool default_statement_present = (0 != default_statement);
23357
23358 if (default_statement_present)
23359 {
23360 arg_list.push_back(default_statement);
23361 }
23362
23363 result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
23364
23365 svd.delete_ptr = (0 == result);
23366 defstmt_delete.delete_ptr = (0 == result);
23367
23368 return result;
23369 }
23370
23371 inline expression_node_ptr parse_multi_switch_statement()
23372 {
23373 std::vector<expression_node_ptr> arg_list;
23374
23375 if (!details::imatch(current_token().value,"[*]"))
23376 {
23377 set_error(
23379 current_token(),
23380 "ERR087 - Expected token '[*]'",
23382
23383 return error_node();
23384 }
23385
23386 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
23387
23388 next_token();
23389
23390 if (!token_is(token_t::e_lcrlbracket))
23391 {
23392 set_error(
23394 current_token(),
23395 "ERR088 - Expected '{' for call to [*] statement",
23397
23398 return error_node();
23399 }
23400
23401 for ( ; ; )
23402 {
23403 if (!details::imatch("case",current_token().value))
23404 {
23405 set_error(
23407 current_token(),
23408 "ERR089 - Expected a 'case' statement for multi-switch",
23410
23411 return error_node();
23412 }
23413
23414 next_token();
23415
23416 expression_node_ptr condition = parse_expression();
23417
23418 if (0 == condition)
23419 return error_node();
23420
23421 if (!token_is(token_t::e_colon))
23422 {
23423 set_error(
23425 current_token(),
23426 "ERR090 - Expected ':' for case of [*] statement",
23428
23429 return error_node();
23430 }
23431
23432 expression_node_ptr consequent = parse_expression();
23433
23434 if (0 == consequent)
23435 return error_node();
23436
23437 if (!token_is(token_t::e_eof))
23438 {
23439 set_error(
23441 current_token(),
23442 "ERR091 - Expected ';' at end of case for [*] statement",
23444
23445 return error_node();
23446 }
23447
23448 // Can we optimise away the case statement?
23449 if (is_constant_node(condition) && is_false(condition))
23450 {
23451 free_node(node_allocator_, condition);
23452 free_node(node_allocator_, consequent);
23453 }
23454 else
23455 {
23456 arg_list.push_back( condition);
23457 arg_list.push_back(consequent);
23458 }
23459
23460 if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
23461 {
23462 break;
23463 }
23464 }
23465
23466 if (!token_is(token_t::e_rcrlbracket))
23467 {
23468 set_error(
23470 current_token(),
23471 "ERR092 - Expected '}' at end of [*] statement",
23473
23474 return error_node();
23475 }
23476
23477 const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
23478
23479 svd.delete_ptr = (0 == result);
23480
23481 return result;
23482 }
23483
23484 inline expression_node_ptr parse_vararg_function()
23485 {
23486 std::vector<expression_node_ptr> arg_list;
23487
23489 const std::string symbol = current_token().value;
23490
23491 if (details::imatch(symbol,"~"))
23492 {
23493 next_token();
23494 return parse_multi_sequence();
23495 }
23496 else if (details::imatch(symbol,"[*]"))
23497 {
23498 return parse_multi_switch_statement();
23499 }
23500 else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
23501 else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
23502 else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
23503 else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
23504 else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
23505 else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
23506 else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
23507 else
23508 {
23509 set_error(
23511 current_token(),
23512 "ERR093 - Unsupported vararg function: " + symbol,
23514
23515 return error_node();
23516 }
23517
23518 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23519
23520 lodge_symbol(symbol, e_st_function);
23521
23522 next_token();
23523
23524 if (!token_is(token_t::e_lbracket))
23525 {
23526 set_error(
23528 current_token(),
23529 "ERR094 - Expected '(' for call to vararg function: " + symbol,
23531
23532 return error_node();
23533 }
23534
23535 for ( ; ; )
23536 {
23537 expression_node_ptr arg = parse_expression();
23538
23539 if (0 == arg)
23540 return error_node();
23541 else
23542 arg_list.push_back(arg);
23543
23544 if (token_is(token_t::e_rbracket))
23545 break;
23546 else if (!token_is(token_t::e_comma))
23547 {
23548 set_error(
23550 current_token(),
23551 "ERR095 - Expected ',' for call to vararg function: " + symbol,
23553
23554 return error_node();
23555 }
23556 }
23557
23558 const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
23559
23560 sdd.delete_ptr = (0 == result);
23561 return result;
23562 }
23563
23564 #ifndef exprtk_disable_string_capabilities
23565 inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
23566 {
23567 if (!token_is(token_t::e_lsqrbracket))
23568 {
23569 set_error(
23571 current_token(),
23572 "ERR096 - Expected '[' as start of string range definition",
23574
23575 free_node(node_allocator_,expression);
23576
23577 return error_node();
23578 }
23579 else if (token_is(token_t::e_rsqrbracket))
23580 {
23581 return node_allocator_.allocate<details::string_size_node<T> >(expression);
23582 }
23583
23584 range_t rp;
23585
23586 if (!parse_range(rp,true))
23587 {
23588 free_node(node_allocator_,expression);
23589
23590 return error_node();
23591 }
23592
23593 expression_node_ptr result = expression_generator_(expression,rp);
23594
23595 if (0 == result)
23596 {
23597 set_error(
23599 current_token(),
23600 "ERR097 - Failed to generate string range node",
23602
23603 free_node(node_allocator_,expression);
23604 rp.free();
23605 }
23606
23607 rp.clear();
23608
23609 return result;
23610 }
23611 #else
23612 inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
23613 {
23614 return error_node();
23615 }
23616 #endif
23617
23618 inline void parse_pending_string_rangesize(expression_node_ptr& expression)
23619 {
23620 // Allow no more than 100 range calls, eg: s[][][]...[][]
23621 const std::size_t max_rangesize_parses = 100;
23622
23623 std::size_t i = 0;
23624
23625 while
23626 (
23627 (0 != expression) &&
23628 (i++ < max_rangesize_parses) &&
23629 error_list_.empty() &&
23630 is_generally_string_node(expression) &&
23631 token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
23632 )
23633 {
23634 expression = parse_string_range_statement(expression);
23635 }
23636 }
23637
23638 template <typename Allocator1,
23639 typename Allocator2,
23640 template <typename, typename> class Sequence>
23641 inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
23642 Sequence<bool,Allocator2>& side_effect_list,
23643 const bool specialise_on_final_type = false)
23644 {
23645 if (expression_list.empty())
23646 return error_node();
23647 else if (1 == expression_list.size())
23648 return expression_list[0];
23649
23650 Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
23651
23652 bool return_node_present = false;
23653
23654 for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
23655 {
23656 if (is_variable_node(expression_list[i]))
23657 continue;
23658 else if (
23659 is_return_node (expression_list[i]) ||
23660 is_break_node (expression_list[i]) ||
23661 is_continue_node(expression_list[i])
23662 )
23663 {
23664 tmp_expression_list.push_back(expression_list[i]);
23665
23666 // Remove all subexpressions after first short-circuit
23667 // node has been encountered.
23668
23669 for (std::size_t j = i + 1; j < expression_list.size(); ++j)
23670 {
23671 free_node(node_allocator_,expression_list[j]);
23672 }
23673
23674 return_node_present = true;
23675
23676 break;
23677 }
23678 else if (
23679 is_constant_node(expression_list[i]) ||
23680 is_null_node (expression_list[i]) ||
23681 !side_effect_list[i]
23682 )
23683 {
23684 free_node(node_allocator_,expression_list[i]);
23685 continue;
23686 }
23687 else
23688 tmp_expression_list.push_back(expression_list[i]);
23689 }
23690
23691 if (!return_node_present)
23692 {
23693 tmp_expression_list.push_back(expression_list.back());
23694 }
23695
23696 expression_list.swap(tmp_expression_list);
23697
23698 if (tmp_expression_list.size() > expression_list.size())
23699 {
23700 exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
23701 static_cast<int>(tmp_expression_list.size()),
23702 static_cast<int>(expression_list .size())));
23703 }
23704
23705 if (
23706 return_node_present ||
23707 side_effect_list.back() ||
23708 (expression_list.size() > 1)
23709 )
23710 state_.activate_side_effect("simplify()");
23711
23712 if (1 == expression_list.size())
23713 return expression_list[0];
23714 else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
23715 return expression_generator_.vararg_function(details::e_smulti,expression_list);
23716 else
23717 return expression_generator_.vararg_function(details::e_multi,expression_list);
23718 }
23719
23720 inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
23721 {
23722 token_t::token_type close_bracket = token_t::e_rcrlbracket;
23723 token_t::token_type seperator = token_t::e_eof;
23724
23725 if (!token_is(token_t::e_lcrlbracket))
23726 {
23727 if (token_is(token_t::e_lbracket))
23728 {
23729 close_bracket = token_t::e_rbracket;
23730 seperator = token_t::e_comma;
23731 }
23732 else
23733 {
23734 set_error(
23736 current_token(),
23737 "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
23738 ((!source.empty()) ? std::string(" section of " + source): ""),
23740
23741 return error_node();
23742 }
23743 }
23744 else if (token_is(token_t::e_rcrlbracket))
23745 {
23746 return node_allocator_.allocate<details::null_node<T> >();
23747 }
23748
23749 std::vector<expression_node_ptr> arg_list;
23750 std::vector<bool> side_effect_list;
23751
23752 expression_node_ptr result = error_node();
23753
23754 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23755
23756 scope_handler sh(*this);
23757
23758 scoped_bool_or_restorer sbr(state_.side_effect_present);
23759
23760 for ( ; ; )
23761 {
23762 state_.side_effect_present = false;
23763
23764 expression_node_ptr arg = parse_expression();
23765
23766 if (0 == arg)
23767 return error_node();
23768 else
23769 {
23770 arg_list.push_back(arg);
23771 side_effect_list.push_back(state_.side_effect_present);
23772 }
23773
23774 if (token_is(close_bracket))
23775 break;
23776
23777 const bool is_next_close = peek_token_is(close_bracket);
23778
23779 if (!token_is(seperator) && is_next_close)
23780 {
23781 set_error(
23783 current_token(),
23784 "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
23786
23787 return error_node();
23788 }
23789
23790 if (token_is(close_bracket))
23791 break;
23792 }
23793
23794 result = simplify(arg_list,side_effect_list,source.empty());
23795
23796 sdd.delete_ptr = (0 == result);
23797 return result;
23798 }
23799
23800 inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
23801 {
23802 // Examples of valid ranges:
23803 // 1. [1:5] -> 1..5
23804 // 2. [ :5] -> 0..5
23805 // 3. [1: ] -> 1..end
23806 // 4. [x:y] -> x..y where x <= y
23807 // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
23808 // 6. [ :y] -> 0..y where 0 <= y
23809 // 7. [x: ] -> x..end where x <= end
23810
23811 rp.clear();
23812
23813 if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
23814 {
23815 set_error(
23817 current_token(),
23818 "ERR100 - Expected '[' for start of range",
23820
23821 return false;
23822 }
23823
23824 if (token_is(token_t::e_colon))
23825 {
23826 rp.n0_c.first = true;
23827 rp.n0_c.second = 0;
23828 rp.cache.first = 0;
23829 }
23830 else
23831 {
23832 expression_node_ptr r0 = parse_expression();
23833
23834 if (0 == r0)
23835 {
23836 set_error(
23838 current_token(),
23839 "ERR101 - Failed parse begin section of range",
23841
23842 return false;
23843 }
23844 else if (is_constant_node(r0))
23845 {
23846 const T r0_value = r0->value();
23847
23848 if (r0_value >= T(0))
23849 {
23850 rp.n0_c.first = true;
23851 rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
23852 rp.cache.first = rp.n0_c.second;
23853 }
23854
23855 free_node(node_allocator_,r0);
23856
23857 if (r0_value < T(0))
23858 {
23859 set_error(
23861 current_token(),
23862 "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0",
23864
23865 return false;
23866 }
23867 }
23868 else
23869 {
23870 rp.n0_e.first = true;
23871 rp.n0_e.second = r0;
23872 }
23873
23874 if (!token_is(token_t::e_colon))
23875 {
23876 set_error(
23878 current_token(),
23879 "ERR103 - Expected ':' for break in range",
23881
23882 rp.free();
23883
23884 return false;
23885 }
23886 }
23887
23888 if (token_is(token_t::e_rsqrbracket))
23889 {
23890 rp.n1_c.first = true;
23891 rp.n1_c.second = std::numeric_limits<std::size_t>::max();
23892 }
23893 else
23894 {
23895 expression_node_ptr r1 = parse_expression();
23896
23897 if (0 == r1)
23898 {
23899 set_error(
23901 current_token(),
23902 "ERR104 - Failed parse end section of range",
23904
23905 rp.free();
23906
23907 return false;
23908 }
23909 else if (is_constant_node(r1))
23910 {
23911 const T r1_value = r1->value();
23912
23913 if (r1_value >= T(0))
23914 {
23915 rp.n1_c.first = true;
23916 rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
23917 rp.cache.second = rp.n1_c.second;
23918 }
23919
23920 free_node(node_allocator_,r1);
23921
23922 if (r1_value < T(0))
23923 {
23924 set_error(
23926 current_token(),
23927 "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0",
23929
23930 rp.free();
23931
23932 return false;
23933 }
23934 }
23935 else
23936 {
23937 rp.n1_e.first = true;
23938 rp.n1_e.second = r1;
23939 }
23940
23941 if (!token_is(token_t::e_rsqrbracket))
23942 {
23943 set_error(
23945 current_token(),
23946 "ERR106 - Expected ']' for start of range",
23948
23949 rp.free();
23950
23951 return false;
23952 }
23953 }
23954
23955 if (rp.const_range())
23956 {
23957 std::size_t r0 = 0;
23958 std::size_t r1 = 0;
23959
23960 bool rp_result = false;
23961
23962 try
23963 {
23964 rp_result = rp(r0, r1);
23965 }
23966 catch (std::runtime_error&)
23967 {}
23968
23969 if (!rp_result || (r0 > r1))
23970 {
23971 set_error(
23973 current_token(),
23974 "ERR107 - Invalid range, Constraint: r0 <= r1",
23976
23977 return false;
23978 }
23979 }
23980
23981 return true;
23982 }
23983
23984 inline void lodge_symbol(const std::string& symbol,
23985 const symbol_type st)
23986 {
23987 dec_.add_symbol(symbol,st);
23988 }
23989
23990 #ifndef exprtk_disable_string_capabilities
23991 inline expression_node_ptr parse_string()
23992 {
23993 const std::string symbol = current_token().value;
23994
23995 typedef details::stringvar_node<T>* strvar_node_t;
23996
23997 expression_node_ptr result = error_node();
23998 strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23999
24000 scope_element& se = sem_.get_active_element(symbol);
24001
24002 if (scope_element::e_string == se.type)
24003 {
24004 se.active = true;
24005 result = se.str_node;
24006 lodge_symbol(symbol, e_st_local_string);
24007 }
24008 else
24009 {
24010 if (!symtab_store_.is_conststr_stringvar(symbol))
24011 {
24012 set_error(
24014 current_token(),
24015 "ERR108 - Unknown string symbol",
24017
24018 return error_node();
24019 }
24020
24021 result = symtab_store_.get_stringvar(symbol);
24022
24023 if (symtab_store_.is_constant_string(symbol))
24024 {
24025 const_str_node = static_cast<strvar_node_t>(result);
24026 result = expression_generator_(const_str_node->str());
24027 }
24028
24029 lodge_symbol(symbol, e_st_string);
24030 }
24031
24032 if (peek_token_is(token_t::e_lsqrbracket))
24033 {
24034 next_token();
24035
24036 if (peek_token_is(token_t::e_rsqrbracket))
24037 {
24038 next_token();
24039 next_token();
24040
24041 if (const_str_node)
24042 {
24043 free_node(node_allocator_,result);
24044
24045 return expression_generator_(T(const_str_node->size()));
24046 }
24047 else
24048 return node_allocator_.allocate<details::stringvar_size_node<T> >
24049 (static_cast<details::stringvar_node<T>*>(result)->ref());
24050 }
24051
24052 range_t rp;
24053
24054 if (!parse_range(rp))
24055 {
24056 free_node(node_allocator_,result);
24057
24058 return error_node();
24059 }
24060 else if (const_str_node)
24061 {
24062 free_node(node_allocator_,result);
24063 result = expression_generator_(const_str_node->ref(),rp);
24064 }
24065 else
24066 result = expression_generator_(static_cast<details::stringvar_node<T>*>
24067 (result)->ref(), rp);
24068
24069 if (result)
24070 rp.clear();
24071 }
24072 else
24073 next_token();
24074
24075 return result;
24076 }
24077 #else
24078 inline expression_node_ptr parse_string()
24079 {
24080 return error_node();
24081 }
24082 #endif
24083
24084 #ifndef exprtk_disable_string_capabilities
24085 inline expression_node_ptr parse_const_string()
24086 {
24087 const std::string const_str = current_token().value;
24088 expression_node_ptr result = expression_generator_(const_str);
24089
24090 if (peek_token_is(token_t::e_lsqrbracket))
24091 {
24092 next_token();
24093
24094 if (peek_token_is(token_t::e_rsqrbracket))
24095 {
24096 next_token();
24097 next_token();
24098
24099 free_node(node_allocator_,result);
24100
24101 return expression_generator_(T(const_str.size()));
24102 }
24103
24104 range_t rp;
24105
24106 if (!parse_range(rp))
24107 {
24108 free_node(node_allocator_,result);
24109 rp.free();
24110
24111 return error_node();
24112 }
24113
24114 free_node(node_allocator_,result);
24115
24116 if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
24117 {
24118 rp.n1_c.second = const_str.size() - 1;
24119 rp.cache.second = rp.n1_c.second;
24120 }
24121
24122 if (
24123 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
24124 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
24125 )
24126 {
24127 set_error(
24129 current_token(),
24130 "ERR109 - Overflow in range for string: '" + const_str + "'[" +
24131 (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
24132 (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
24134
24135 rp.free();
24136
24137 return error_node();
24138 }
24139
24140 result = expression_generator_(const_str,rp);
24141
24142 if (result)
24143 rp.clear();
24144 }
24145 else
24146 next_token();
24147
24148 return result;
24149 }
24150 #else
24151 inline expression_node_ptr parse_const_string()
24152 {
24153 return error_node();
24154 }
24155 #endif
24156
24157 inline expression_node_ptr parse_vector()
24158 {
24159 const std::string symbol = current_token().value;
24160
24161 vector_holder_ptr vec = vector_holder_ptr(0);
24162
24163 const scope_element& se = sem_.get_active_element(symbol);
24164
24165 if (
24166 !details::imatch(se.name, symbol) ||
24167 (se.depth > state_.scope_depth) ||
24168 (scope_element::e_vector != se.type)
24169 )
24170 {
24171 if (0 == (vec = symtab_store_.get_vector(symbol)))
24172 {
24173 set_error(
24175 current_token(),
24176 "ERR110 - Symbol '" + symbol+ " not a vector",
24178
24179 return error_node();
24180 }
24181 }
24182 else
24183 vec = se.vec_node;
24184
24185 expression_node_ptr index_expr = error_node();
24186
24187 next_token();
24188
24189 if (!token_is(token_t::e_lsqrbracket))
24190 {
24191 return node_allocator_.allocate<vector_node_t>(vec);
24192 }
24193 else if (token_is(token_t::e_rsqrbracket))
24194 {
24195 return expression_generator_(T(vec->size()));
24196 }
24197 else if (0 == (index_expr = parse_expression()))
24198 {
24199 set_error(
24201 current_token(),
24202 "ERR111 - Failed to parse index for vector: '" + symbol + "'",
24204
24205 return error_node();
24206 }
24207 else if (!token_is(token_t::e_rsqrbracket))
24208 {
24209 set_error(
24211 current_token(),
24212 "ERR112 - Expected ']' for index of vector: '" + symbol + "'",
24214
24215 free_node(node_allocator_,index_expr);
24216
24217 return error_node();
24218 }
24219
24220 // Perform compile-time range check
24221 if (details::is_constant_node(index_expr))
24222 {
24223 const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
24224 const std::size_t vec_size = vec->size();
24225
24226 if (index >= vec_size)
24227 {
24228 set_error(
24230 current_token(),
24231 "ERR113 - Index of " + details::to_str(index) + " out of range for "
24232 "vector '" + symbol + "' of size " + details::to_str(vec_size),
24234
24235 free_node(node_allocator_,index_expr);
24236
24237 return error_node();
24238 }
24239 }
24240
24241 return expression_generator_.vector_element(symbol, vec, index_expr);
24242 }
24243
24244 inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
24245 {
24246 std::vector<expression_node_ptr> arg_list;
24247
24248 expression_node_ptr result = error_node();
24249
24250 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24251
24252 next_token();
24253
24254 if (token_is(token_t::e_lbracket))
24255 {
24256 if (token_is(token_t::e_rbracket))
24257 {
24258 if (!vararg_function->allow_zero_parameters())
24259 {
24260 set_error(
24262 current_token(),
24263 "ERR114 - Zero parameter call to vararg function: "
24264 + vararg_function_name + " not allowed",
24266
24267 return error_node();
24268 }
24269 }
24270 else
24271 {
24272 for ( ; ; )
24273 {
24274 expression_node_ptr arg = parse_expression();
24275
24276 if (0 == arg)
24277 return error_node();
24278 else
24279 arg_list.push_back(arg);
24280
24281 if (token_is(token_t::e_rbracket))
24282 break;
24283 else if (!token_is(token_t::e_comma))
24284 {
24285 set_error(
24287 current_token(),
24288 "ERR115 - Expected ',' for call to vararg function: "
24289 + vararg_function_name,
24291
24292 return error_node();
24293 }
24294 }
24295 }
24296 }
24297 else if (!vararg_function->allow_zero_parameters())
24298 {
24299 set_error(
24301 current_token(),
24302 "ERR116 - Zero parameter call to vararg function: "
24303 + vararg_function_name + " not allowed",
24305
24306 return error_node();
24307 }
24308
24309 if (arg_list.size() < vararg_function->min_num_args())
24310 {
24311 set_error(
24313 current_token(),
24314 "ERR117 - Invalid number of parameters to call to vararg function: "
24315 + vararg_function_name + ", require at least "
24316 + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
24318
24319 return error_node();
24320 }
24321 else if (arg_list.size() > vararg_function->max_num_args())
24322 {
24323 set_error(
24325 current_token(),
24326 "ERR118 - Invalid number of parameters to call to vararg function: "
24327 + vararg_function_name + ", require no more than "
24328 + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
24330
24331 return error_node();
24332 }
24333
24334 result = expression_generator_.vararg_function_call(vararg_function,arg_list);
24335
24336 sdd.delete_ptr = (0 == result);
24337
24338 return result;
24339 }
24340
24341 class type_checker
24342 {
24343 public:
24344
24345 enum return_type_t
24346 {
24347 e_overload = ' ',
24348 e_numeric = 'T',
24349 e_string = 'S'
24350 };
24351
24353 {
24354 return_type_t return_type;
24356 };
24357
24358 typedef parser<T> parser_t;
24359 typedef std::vector<function_prototype_t> function_definition_list_t;
24360
24361 type_checker(parser_t& p,
24362 const std::string& func_name,
24363 const std::string& func_prototypes,
24364 const return_type_t default_return_type)
24365 : invalid_state_(true),
24366 parser_(p),
24367 function_name_(func_name),
24368 default_return_type_(default_return_type)
24369 {
24370 parse_function_prototypes(func_prototypes);
24371 }
24372
24373 bool verify(const std::string& param_seq, std::size_t& pseq_index)
24374 {
24375 if (function_definition_list_.empty())
24376 return true;
24377
24378 std::vector<std::pair<std::size_t,char> > error_list;
24379
24380 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
24381 {
24382 details::char_t diff_value = 0;
24383 std::size_t diff_index = 0;
24384
24385 const bool result = details::sequence_match(function_definition_list_[i].param_seq,
24386 param_seq,
24387 diff_index, diff_value);
24388
24389 if (result)
24390 {
24391 pseq_index = i;
24392 return true;
24393 }
24394 else
24395 error_list.push_back(std::make_pair(diff_index, diff_value));
24396 }
24397
24398 if (1 == error_list.size())
24399 {
24400 parser_.
24401 set_error(
24403 parser_.current_token(),
24404 "ERR119 - Failed parameter type check for function '" + function_name_ + "', "
24405 "Expected '" + function_definition_list_[0].param_seq +
24406 "' call set: '" + param_seq + "'",
24408 }
24409 else
24410 {
24411 // find first with largest diff_index;
24412 std::size_t max_diff_index = 0;
24413
24414 for (std::size_t i = 1; i < error_list.size(); ++i)
24415 {
24416 if (error_list[i].first > error_list[max_diff_index].first)
24417 {
24418 max_diff_index = i;
24419 }
24420 }
24421
24422 parser_.
24423 set_error(
24425 parser_.current_token(),
24426 "ERR120 - Failed parameter type check for function '" + function_name_ + "', "
24427 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
24428 "' call set: '" + param_seq + "'",
24430 }
24431
24432 return false;
24433 }
24434
24435 std::size_t paramseq_count() const
24436 {
24437 return function_definition_list_.size();
24438 }
24439
24440 std::string paramseq(const std::size_t& index) const
24441 {
24442 return function_definition_list_[index].param_seq;
24443 }
24444
24445 return_type_t return_type(const std::size_t& index) const
24446 {
24447 return function_definition_list_[index].return_type;
24448 }
24449
24450 bool invalid() const
24451 {
24452 return !invalid_state_;
24453 }
24454
24455 bool allow_zero_parameters() const
24456 {
24457
24458 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
24459 {
24460 if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
24461 {
24462 return true;
24463 }
24464 }
24465
24466 return false;
24467 }
24468
24469 private:
24470
24471 std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
24472 {
24473 std::string::const_iterator current_begin = param_seq.begin();
24474 std::string::const_iterator iter = param_seq.begin();
24475
24476 std::vector<std::string> result;
24477
24478 while (iter != param_seq.end())
24479 {
24480 if (*iter == delimiter)
24481 {
24482 result.push_back(std::string(current_begin, iter));
24483 current_begin = ++iter;
24484 }
24485 else
24486 ++iter;
24487 }
24488
24489 if (current_begin != iter)
24490 {
24491 result.push_back(std::string(current_begin, iter));
24492 }
24493
24494 return result;
24495 }
24496
24497 inline bool is_valid_token(std::string param_seq,
24498 function_prototype_t& funcproto) const
24499 {
24500 // Determine return type
24501 funcproto.return_type = default_return_type_;
24502
24503 if (param_seq.size() > 2)
24504 {
24505 if (':' == param_seq[1])
24506 {
24507 // Note: Only overloaded igeneric functions can have return
24508 // type definitions.
24509 if (type_checker::e_overload != default_return_type_)
24510 return false;
24511
24512 switch (param_seq[0])
24513 {
24514 case 'T' : funcproto.return_type = type_checker::e_numeric;
24515 break;
24516
24517 case 'S' : funcproto.return_type = type_checker::e_string;
24518 break;
24519
24520 default : return false;
24521 }
24522
24523 param_seq.erase(0,2);
24524 }
24525 }
24526
24527 if (
24528 (std::string::npos != param_seq.find("?*")) ||
24529 (std::string::npos != param_seq.find("**"))
24530 )
24531 {
24532 return false;
24533 }
24534 else if (
24535 (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
24536 ("Z" == param_seq)
24537 )
24538 {
24539 funcproto.param_seq = param_seq;
24540 return true;
24541 }
24542
24543 return false;
24544 }
24545
24546 void parse_function_prototypes(const std::string& func_prototypes)
24547 {
24548 if (func_prototypes.empty())
24549 return;
24550
24551 std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
24552
24553 typedef std::map<std::string,std::size_t> param_seq_map_t;
24554 param_seq_map_t param_seq_map;
24555
24556 for (std::size_t i = 0; i < param_seq_list.size(); ++i)
24557 {
24558 function_prototype_t func_proto;
24559
24560 if (!is_valid_token(param_seq_list[i], func_proto))
24561 {
24562 invalid_state_ = false;
24563
24564 parser_.
24565 set_error(
24567 parser_.current_token(),
24568 "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] +
24569 "' for function: " + function_name_,
24571 return;
24572 }
24573
24574 param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
24575
24576 if (param_seq_map.end() != seq_itr)
24577 {
24578 invalid_state_ = false;
24579
24580 parser_.
24581 set_error(
24583 parser_.current_token(),
24584 "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
24585 "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
24586 "pseq_idx[" + details::to_str(i) + "] " +
24587 "param seq: " + param_seq_list[i],
24589 return;
24590 }
24591
24592 function_definition_list_.push_back(func_proto);
24593 }
24594 }
24595
24596 type_checker(const type_checker&);
24597 type_checker& operator=(const type_checker&);
24598
24599 bool invalid_state_;
24600 parser_t& parser_;
24601 std::string function_name_;
24602 const return_type_t default_return_type_;
24603 function_definition_list_t function_definition_list_;
24604 };
24605
24606 inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
24607 {
24608 std::vector<expression_node_ptr> arg_list;
24609
24610 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24611
24612 next_token();
24613
24614 std::string param_type_list;
24615
24616 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
24617
24618 if (tc.invalid())
24619 {
24620 set_error(
24622 current_token(),
24623 "ERR123 - Type checker instantiation failure for generic function: " + function_name,
24625
24626 return error_node();
24627 }
24628
24629 if (token_is(token_t::e_lbracket))
24630 {
24631 if (token_is(token_t::e_rbracket))
24632 {
24633 if (
24634 !function->allow_zero_parameters() &&
24635 !tc .allow_zero_parameters()
24636 )
24637 {
24638 set_error(
24640 current_token(),
24641 "ERR124 - Zero parameter call to generic function: "
24642 + function_name + " not allowed",
24644
24645 return error_node();
24646 }
24647 }
24648 else
24649 {
24650 for ( ; ; )
24651 {
24652 expression_node_ptr arg = parse_expression();
24653
24654 if (0 == arg)
24655 return error_node();
24656
24657 if (is_ivector_node(arg))
24658 param_type_list += 'V';
24659 else if (is_generally_string_node(arg))
24660 param_type_list += 'S';
24661 else // Everything else is assumed to be a scalar returning expression
24662 param_type_list += 'T';
24663
24664 arg_list.push_back(arg);
24665
24666 if (token_is(token_t::e_rbracket))
24667 break;
24668 else if (!token_is(token_t::e_comma))
24669 {
24670 set_error(
24672 current_token(),
24673 "ERR125 - Expected ',' for call to generic function: " + function_name,
24675
24676 return error_node();
24677 }
24678 }
24679 }
24680 }
24681 else if (
24682 !function->parameter_sequence.empty() &&
24683 function->allow_zero_parameters () &&
24684 !tc .allow_zero_parameters ()
24685 )
24686 {
24687 set_error(
24689 current_token(),
24690 "ERR126 - Zero parameter call to generic function: "
24691 + function_name + " not allowed",
24693
24694 return error_node();
24695 }
24696
24697 std::size_t param_seq_index = 0;
24698
24699 if (
24700 state_.type_check_enabled &&
24701 !tc.verify(param_type_list, param_seq_index)
24702 )
24703 {
24704 set_error(
24706 current_token(),
24707 "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name,
24709
24710 return error_node();
24711 }
24712
24713 expression_node_ptr result = error_node();
24714
24715 if (tc.paramseq_count() <= 1)
24716 result = expression_generator_
24717 .generic_function_call(function, arg_list);
24718 else
24719 result = expression_generator_
24720 .generic_function_call(function, arg_list, param_seq_index);
24721
24722 sdd.delete_ptr = (0 == result);
24723
24724 return result;
24725 }
24726
24727 inline bool parse_igeneric_function_params(std::string& param_type_list,
24728 std::vector<expression_node_ptr>& arg_list,
24729 const std::string& function_name,
24730 igeneric_function<T>* function,
24731 const type_checker& tc)
24732 {
24733 if (token_is(token_t::e_lbracket))
24734 {
24735 if (token_is(token_t::e_rbracket))
24736 {
24737 if (
24738 !function->allow_zero_parameters() &&
24739 !tc .allow_zero_parameters()
24740 )
24741 {
24742 set_error(
24744 current_token(),
24745 "ERR128 - Zero parameter call to generic function: "
24746 + function_name + " not allowed",
24748
24749 return false;
24750 }
24751 }
24752 else
24753 {
24754 for ( ; ; )
24755 {
24756 expression_node_ptr arg = parse_expression();
24757
24758 if (0 == arg)
24759 return false;
24760
24761 if (is_ivector_node(arg))
24762 param_type_list += 'V';
24763 else if (is_generally_string_node(arg))
24764 param_type_list += 'S';
24765 else // Everything else is a scalar returning expression
24766 param_type_list += 'T';
24767
24768 arg_list.push_back(arg);
24769
24770 if (token_is(token_t::e_rbracket))
24771 break;
24772 else if (!token_is(token_t::e_comma))
24773 {
24774 set_error(
24776 current_token(),
24777 "ERR129 - Expected ',' for call to string function: " + function_name,
24779
24780 return false;
24781 }
24782 }
24783 }
24784
24785 return true;
24786 }
24787 else
24788 return false;
24789 }
24790
24791 #ifndef exprtk_disable_string_capabilities
24792 inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
24793 {
24794 // Move pass the function name
24795 next_token();
24796
24797 std::string param_type_list;
24798
24799 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
24800
24801 if (
24802 (!function->parameter_sequence.empty()) &&
24803 (0 == tc.paramseq_count())
24804 )
24805 {
24806 return error_node();
24807 }
24808
24809 std::vector<expression_node_ptr> arg_list;
24810 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24811
24812 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
24813 {
24814 return error_node();
24815 }
24816
24817 std::size_t param_seq_index = 0;
24818
24819 if (!tc.verify(param_type_list, param_seq_index))
24820 {
24821 set_error(
24823 current_token(),
24824 "ERR130 - Invalid input parameter sequence for call to string function: " + function_name,
24826
24827 return error_node();
24828 }
24829
24830 expression_node_ptr result = error_node();
24831
24832 if (tc.paramseq_count() <= 1)
24833 result = expression_generator_
24834 .string_function_call(function, arg_list);
24835 else
24836 result = expression_generator_
24837 .string_function_call(function, arg_list, param_seq_index);
24838
24839 sdd.delete_ptr = (0 == result);
24840
24841 return result;
24842 }
24843
24844 inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
24845 {
24846 // Move pass the function name
24847 next_token();
24848
24849 std::string param_type_list;
24850
24851 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
24852
24853 if (
24854 (!function->parameter_sequence.empty()) &&
24855 (0 == tc.paramseq_count())
24856 )
24857 {
24858 return error_node();
24859 }
24860
24861 std::vector<expression_node_ptr> arg_list;
24862 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24863
24864 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
24865 {
24866 return error_node();
24867 }
24868
24869 std::size_t param_seq_index = 0;
24870
24871 if (!tc.verify(param_type_list, param_seq_index))
24872 {
24873 set_error(
24875 current_token(),
24876 "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name,
24878
24879 return error_node();
24880 }
24881
24882 expression_node_ptr result = error_node();
24883
24884 if (type_checker::e_numeric == tc.return_type(param_seq_index))
24885 {
24886 if (tc.paramseq_count() <= 1)
24887 result = expression_generator_
24888 .generic_function_call(function, arg_list);
24889 else
24890 result = expression_generator_
24891 .generic_function_call(function, arg_list, param_seq_index);
24892 }
24893 else if (type_checker::e_string == tc.return_type(param_seq_index))
24894 {
24895 if (tc.paramseq_count() <= 1)
24896 result = expression_generator_
24897 .string_function_call(function, arg_list);
24898 else
24899 result = expression_generator_
24900 .string_function_call(function, arg_list, param_seq_index);
24901 }
24902 else
24903 {
24904 set_error(
24906 current_token(),
24907 "ERR132 - Invalid return type for call to overloaded function: " + function_name,
24909 }
24910
24911 sdd.delete_ptr = (0 == result);
24912 return result;
24913 }
24914 #endif
24915
24916 template <typename Type, std::size_t NumberOfParameters>
24917 struct parse_special_function_impl
24918 {
24919 static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
24920 {
24921 expression_node_ptr branch[NumberOfParameters];
24922 expression_node_ptr result = error_node();
24923
24924 std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
24925
24926 scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
24927
24928 p.next_token();
24929
24930 if (!p.token_is(token_t::e_lbracket))
24931 {
24932 p.set_error(
24934 p.current_token(),
24935 "ERR133 - Expected '(' for special function '" + sf_name + "'",
24937
24938 return error_node();
24939 }
24940
24941 for (std::size_t i = 0; i < NumberOfParameters; ++i)
24942 {
24943 branch[i] = p.parse_expression();
24944
24945 if (0 == branch[i])
24946 {
24947 return p.error_node();
24948 }
24949 else if (i < (NumberOfParameters - 1))
24950 {
24951 if (!p.token_is(token_t::e_comma))
24952 {
24953 p.set_error(
24955 p.current_token(),
24956 "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'",
24958
24959 return p.error_node();
24960 }
24961 }
24962 }
24963
24964 if (!p.token_is(token_t::e_rbracket))
24965 {
24966 p.set_error(
24968 p.current_token(),
24969 "ERR135 - Invalid number of parameters for special function '" + sf_name + "'",
24971
24972 return p.error_node();
24973 }
24974 else
24975 result = p.expression_generator_.special_function(opt_type,branch);
24976
24977 sd.delete_ptr = (0 == result);
24978
24979 return result;
24980 }
24981 };
24982
24983 inline expression_node_ptr parse_special_function()
24984 {
24985 const std::string sf_name = current_token().value;
24986
24987 // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24988 if (
24989 !details::is_digit(sf_name[2]) ||
24990 !details::is_digit(sf_name[3])
24991 )
24992 {
24993 set_error(
24995 current_token(),
24996 "ERR136 - Invalid special function[1]: " + sf_name,
24998
24999 return error_node();
25000 }
25001
25002 const int id = (sf_name[2] - '0') * 10 +
25003 (sf_name[3] - '0');
25004
25005 if (id >= details::e_sffinal)
25006 {
25007 set_error(
25009 current_token(),
25010 "ERR137 - Invalid special function[2]: " + sf_name,
25012
25013 return error_node();
25014 }
25015
25016 const int sf_3_to_4 = details::e_sf48;
25017 const details::operator_type opt_type = details::operator_type(id + 1000);
25018 const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
25019
25020 switch (NumberOfParameters)
25021 {
25022 case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
25023 case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
25024 default : return error_node();
25025 }
25026 }
25027
25028 inline expression_node_ptr parse_null_statement()
25029 {
25030 next_token();
25031 return node_allocator_.allocate<details::null_node<T> >();
25032 }
25033
25034 #ifndef exprtk_disable_break_continue
25035 inline expression_node_ptr parse_break_statement()
25036 {
25037 if (state_.parsing_break_stmt)
25038 {
25039 set_error(
25041 current_token(),
25042 "ERR138 - Invoking 'break' within a break call is not allowed",
25044
25045 return error_node();
25046 }
25047 else if (0 == state_.parsing_loop_stmt_count)
25048 {
25049 set_error(
25051 current_token(),
25052 "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
25054
25055 return error_node();
25056 }
25057
25058 scoped_bool_negator sbn(state_.parsing_break_stmt);
25059
25060 if (!brkcnt_list_.empty())
25061 {
25062 next_token();
25063
25064 brkcnt_list_.front() = true;
25065
25066 expression_node_ptr return_expr = error_node();
25067
25068 if (token_is(token_t::e_lsqrbracket))
25069 {
25070 if (0 == (return_expr = parse_expression()))
25071 {
25072 set_error(
25074 current_token(),
25075 "ERR140 - Failed to parse return expression for 'break' statement",
25077
25078 return error_node();
25079 }
25080 else if (!token_is(token_t::e_rsqrbracket))
25081 {
25082 set_error(
25084 current_token(),
25085 "ERR141 - Expected ']' at the completion of break's return expression",
25087
25088 free_node(node_allocator_,return_expr);
25089
25090 return error_node();
25091 }
25092 }
25093
25094 state_.activate_side_effect("parse_break_statement()");
25095
25096 return node_allocator_.allocate<details::break_node<T> >(return_expr);
25097 }
25098 else
25099 {
25100 set_error(
25102 current_token(),
25103 "ERR142 - Invalid use of 'break', allowed only in the scope of a loop",
25105 }
25106
25107 return error_node();
25108 }
25109
25110 inline expression_node_ptr parse_continue_statement()
25111 {
25112 if (0 == state_.parsing_loop_stmt_count)
25113 {
25114 set_error(
25116 current_token(),
25117 "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop",
25119
25120 return error_node();
25121 }
25122 else
25123 {
25124 next_token();
25125
25126 brkcnt_list_.front() = true;
25127 state_.activate_side_effect("parse_continue_statement()");
25128
25129 return node_allocator_.allocate<details::continue_node<T> >();
25130 }
25131 }
25132 #endif
25133
25134 inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
25135 {
25136 expression_node_ptr size_expr = error_node();
25137
25138 if (!token_is(token_t::e_lsqrbracket))
25139 {
25140 set_error(
25142 current_token(),
25143 "ERR144 - Expected '[' as part of vector size definition",
25145
25146 return error_node();
25147 }
25148 else if (0 == (size_expr = parse_expression()))
25149 {
25150 set_error(
25152 current_token(),
25153 "ERR145 - Failed to determine size of vector '" + vec_name + "'",
25155
25156 return error_node();
25157 }
25158 else if (!is_constant_node(size_expr))
25159 {
25160 free_node(node_allocator_,size_expr);
25161
25162 set_error(
25164 current_token(),
25165 "ERR146 - Expected a literal number as size of vector '" + vec_name + "'",
25167
25168 return error_node();
25169 }
25170
25171 const T vector_size = size_expr->value();
25172
25173 free_node(node_allocator_,size_expr);
25174
25175 const T max_vector_size = T(2000000000.0);
25176
25177 if (
25178 (vector_size <= T(0)) ||
25179 std::not_equal_to<T>()
25180 (T(0),vector_size - details::numeric::trunc(vector_size)) ||
25181 (vector_size > max_vector_size)
25182 )
25183 {
25184 set_error(
25186 current_token(),
25187 "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
25190
25191 return error_node();
25192 }
25193
25194 std::vector<expression_node_ptr> vec_initilizer_list;
25195
25196 scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
25197
25198 bool single_value_initialiser = false;
25199 bool vec_to_vec_initialiser = false;
25200 bool null_initialisation = false;
25201
25202 if (!token_is(token_t::e_rsqrbracket))
25203 {
25204 set_error(
25206 current_token(),
25207 "ERR148 - Expected ']' as part of vector size definition",
25209
25210 return error_node();
25211 }
25212 else if (!token_is(token_t::e_eof))
25213 {
25214 if (!token_is(token_t::e_assign))
25215 {
25216 set_error(
25218 current_token(),
25219 "ERR149 - Expected ':=' as part of vector definition",
25221
25222 return error_node();
25223 }
25224 else if (token_is(token_t::e_lsqrbracket))
25225 {
25226 expression_node_ptr initialiser = parse_expression();
25227
25228 if (0 == initialiser)
25229 {
25230 set_error(
25232 current_token(),
25233 "ERR150 - Failed to parse single vector initialiser",
25235
25236 return error_node();
25237 }
25238
25239 vec_initilizer_list.push_back(initialiser);
25240
25241 if (!token_is(token_t::e_rsqrbracket))
25242 {
25243 set_error(
25245 current_token(),
25246 "ERR151 - Expected ']' to close single value vector initialiser",
25248
25249 return error_node();
25250 }
25251
25252 single_value_initialiser = true;
25253 }
25254 else if (!token_is(token_t::e_lcrlbracket))
25255 {
25256 expression_node_ptr initialiser = error_node();
25257
25258 // Is this a vector to vector assignment and initialisation?
25259 if (token_t::e_symbol == current_token().type)
25260 {
25261 // Is it a locally defined vector?
25262 const scope_element& se = sem_.get_active_element(current_token().value);
25263
25264 if (scope_element::e_vector == se.type)
25265 {
25266 if (0 != (initialiser = parse_expression()))
25267 vec_initilizer_list.push_back(initialiser);
25268 else
25269 return error_node();
25270 }
25271 // Are we dealing with a user defined vector?
25272 else if (symtab_store_.is_vector(current_token().value))
25273 {
25274 lodge_symbol(current_token().value, e_st_vector);
25275
25276 if (0 != (initialiser = parse_expression()))
25277 vec_initilizer_list.push_back(initialiser);
25278 else
25279 return error_node();
25280 }
25281 // Are we dealing with a null initialisation vector definition?
25282 else if (token_is(token_t::e_symbol,"null"))
25283 null_initialisation = true;
25284 }
25285
25286 if (!null_initialisation)
25287 {
25288 if (0 == initialiser)
25289 {
25290 set_error(
25292 current_token(),
25293 "ERR152 - Expected '{' as part of vector initialiser list",
25295
25296 return error_node();
25297 }
25298 else
25299 vec_to_vec_initialiser = true;
25300 }
25301 }
25302 else if (!token_is(token_t::e_rcrlbracket))
25303 {
25304 for ( ; ; )
25305 {
25306 expression_node_ptr initialiser = parse_expression();
25307
25308 if (0 == initialiser)
25309 {
25310 set_error(
25312 current_token(),
25313 "ERR153 - Expected '{' as part of vector initialiser list",
25315
25316 return error_node();
25317 }
25318 else
25319 vec_initilizer_list.push_back(initialiser);
25320
25321 if (token_is(token_t::e_rcrlbracket))
25322 break;
25323
25324 const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
25325
25326 if (!token_is(token_t::e_comma) && is_next_close)
25327 {
25328 set_error(
25330 current_token(),
25331 "ERR154 - Expected ',' between vector initialisers",
25333
25334 return error_node();
25335 }
25336
25337 if (token_is(token_t::e_rcrlbracket))
25338 break;
25339 }
25340 }
25341
25342 if (
25343 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
25344 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
25345 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
25346 )
25347 {
25348 if (!token_is(token_t::e_eof))
25349 {
25350 set_error(
25352 current_token(),
25353 "ERR155 - Expected ';' at end of vector definition",
25355
25356 return error_node();
25357 }
25358 }
25359
25360 if (vec_initilizer_list.size() > vector_size)
25361 {
25362 set_error(
25364 current_token(),
25365 "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
25367
25368 return error_node();
25369 }
25370 }
25371
25372 typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
25373
25374 const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
25375
25376 scope_element& se = sem_.get_element(vec_name);
25377
25378 if (se.name == vec_name)
25379 {
25380 if (se.active)
25381 {
25382 set_error(
25384 current_token(),
25385 "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'",
25387
25388 return error_node();
25389 }
25390 else if (
25391 (se.size == vec_size) &&
25392 (scope_element::e_vector == se.type)
25393 )
25394 {
25395 vec_holder = se.vec_node;
25396 se.active = true;
25397 se.depth = state_.scope_depth;
25398 se.ref_count++;
25399 }
25400 }
25401
25402 if (0 == vec_holder)
25403 {
25404 scope_element nse;
25405 nse.name = vec_name;
25406 nse.active = true;
25407 nse.ref_count = 1;
25408 nse.type = scope_element::e_vector;
25409 nse.depth = state_.scope_depth;
25410 nse.size = vec_size;
25411 nse.data = new T[vec_size];
25412 nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
25413
25414 if (!sem_.add_element(nse))
25415 {
25416 set_error(
25418 current_token(),
25419 "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM",
25421
25422 sem_.free_element(nse);
25423
25424 return error_node();
25425 }
25426
25427 vec_holder = nse.vec_node;
25428
25429 exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
25430 nse.name.c_str(),
25431 static_cast<int>(nse.size)));
25432 }
25433
25434 state_.activate_side_effect("parse_define_vector_statement()");
25435
25436 lodge_symbol(vec_name, e_st_local_vector);
25437
25438 expression_node_ptr result = error_node();
25439
25440 if (null_initialisation)
25441 result = expression_generator_(T(0.0));
25442 else if (vec_to_vec_initialiser)
25443 {
25444 expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
25445
25446 result = expression_generator_(
25448 vec_node,
25449 vec_initilizer_list[0]);
25450 }
25451 else
25452 result = node_allocator_
25453 .allocate<details::vector_assignment_node<T> >(
25454 (*vec_holder)[0],
25455 vec_size,
25456 vec_initilizer_list,
25457 single_value_initialiser);
25458
25459 svd.delete_ptr = (0 == result);
25460
25461 return result;
25462 }
25463
25464 #ifndef exprtk_disable_string_capabilities
25465 inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
25466 {
25467 stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
25468
25469 scope_element& se = sem_.get_element(str_name);
25470
25471 if (se.name == str_name)
25472 {
25473 if (se.active)
25474 {
25475 set_error(
25477 current_token(),
25478 "ERR159 - Illegal redefinition of local variable: '" + str_name + "'",
25480
25481 free_node(node_allocator_,initialisation_expression);
25482
25483 return error_node();
25484 }
25485 else if (scope_element::e_string == se.type)
25486 {
25487 str_node = se.str_node;
25488 se.active = true;
25489 se.depth = state_.scope_depth;
25490 se.ref_count++;
25491 }
25492 }
25493
25494 if (0 == str_node)
25495 {
25496 scope_element nse;
25497 nse.name = str_name;
25498 nse.active = true;
25499 nse.ref_count = 1;
25500 nse.type = scope_element::e_string;
25501 nse.depth = state_.scope_depth;
25502 nse.data = new std::string;
25503 nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data));
25504
25505 if (!sem_.add_element(nse))
25506 {
25507 set_error(
25509 current_token(),
25510 "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM",
25512
25513 free_node(node_allocator_,initialisation_expression);
25514
25515 sem_.free_element(nse);
25516
25517 return error_node();
25518 }
25519
25520 str_node = nse.str_node;
25521
25522 exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
25523 }
25524
25525 lodge_symbol(str_name, e_st_local_string);
25526
25527 state_.activate_side_effect("parse_define_string_statement()");
25528
25529 expression_node_ptr branch[2] = {0};
25530
25531 branch[0] = str_node;
25532 branch[1] = initialisation_expression;
25533
25534 return expression_generator_(details::e_assign,branch);
25535 }
25536 #else
25537 inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
25538 {
25539 return error_node();
25540 }
25541 #endif
25542
25543 inline bool local_variable_is_shadowed(const std::string& symbol)
25544 {
25545 const scope_element& se = sem_.get_element(symbol);
25546 return (se.name == symbol) && se.active;
25547 }
25548
25549 inline expression_node_ptr parse_define_var_statement()
25550 {
25551 if (settings_.vardef_disabled())
25552 {
25553 set_error(
25555 current_token(),
25556 "ERR161 - Illegal variable definition",
25558
25559 return error_node();
25560 }
25561 else if (!details::imatch(current_token().value,"var"))
25562 {
25563 return error_node();
25564 }
25565 else
25566 next_token();
25567
25568 const std::string var_name = current_token().value;
25569
25570 expression_node_ptr initialisation_expression = error_node();
25571
25572 if (!token_is(token_t::e_symbol))
25573 {
25574 set_error(
25576 current_token(),
25577 "ERR162 - Expected a symbol for variable definition",
25579
25580 return error_node();
25581 }
25582 else if (details::is_reserved_symbol(var_name))
25583 {
25584 set_error(
25586 current_token(),
25587 "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'",
25589
25590 return error_node();
25591 }
25592 else if (symtab_store_.symbol_exists(var_name))
25593 {
25594 set_error(
25596 current_token(),
25597 "ERR164 - Illegal redefinition of variable '" + var_name + "'",
25599
25600 return error_node();
25601 }
25602 else if (local_variable_is_shadowed(var_name))
25603 {
25604 set_error(
25606 current_token(),
25607 "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
25609
25610 return error_node();
25611 }
25612 else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
25613 {
25614 return parse_define_vector_statement(var_name);
25615 }
25616 else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
25617 {
25618 return parse_uninitialised_var_statement(var_name);
25619 }
25620 else if (token_is(token_t::e_assign))
25621 {
25622 if (0 == (initialisation_expression = parse_expression()))
25623 {
25624 set_error(
25626 current_token(),
25627 "ERR166 - Failed to parse initialisation expression",
25629
25630 return error_node();
25631 }
25632 }
25633
25634 if (
25635 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
25636 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
25637 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
25638 )
25639 {
25640 if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
25641 {
25642 set_error(
25644 current_token(),
25645 "ERR167 - Expected ';' after variable definition",
25647
25648 free_node(node_allocator_,initialisation_expression);
25649
25650 return error_node();
25651 }
25652 }
25653
25654 if (
25655 (0 != initialisation_expression) &&
25656 details::is_generally_string_node(initialisation_expression)
25657 )
25658 {
25659 return parse_define_string_statement(var_name,initialisation_expression);
25660 }
25661
25662 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
25663
25664 scope_element& se = sem_.get_element(var_name);
25665
25666 if (se.name == var_name)
25667 {
25668 if (se.active)
25669 {
25670 set_error(
25672 current_token(),
25673 "ERR168 - Illegal redefinition of local variable: '" + var_name + "'",
25675
25676 free_node(node_allocator_, initialisation_expression);
25677
25678 return error_node();
25679 }
25680 else if (scope_element::e_variable == se.type)
25681 {
25682 var_node = se.var_node;
25683 se.active = true;
25684 se.depth = state_.scope_depth;
25685 se.ref_count++;
25686 }
25687 }
25688
25689 if (0 == var_node)
25690 {
25691 scope_element nse;
25692 nse.name = var_name;
25693 nse.active = true;
25694 nse.ref_count = 1;
25695 nse.type = scope_element::e_variable;
25696 nse.depth = state_.scope_depth;
25697 nse.data = new T(T(0));
25698 nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
25699
25700 if (!sem_.add_element(nse))
25701 {
25702 set_error(
25704 current_token(),
25705 "ERR169 - Failed to add new local variable '" + var_name + "' to SEM",
25707
25708 free_node(node_allocator_, initialisation_expression);
25709
25710 sem_.free_element(nse);
25711
25712 return error_node();
25713 }
25714
25715 var_node = nse.var_node;
25716
25717 exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
25718 }
25719
25720 state_.activate_side_effect("parse_define_var_statement()");
25721
25722 lodge_symbol(var_name, e_st_local_variable);
25723
25724 expression_node_ptr branch[2] = {0};
25725
25726 branch[0] = var_node;
25727 branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
25728
25729 return expression_generator_(details::e_assign,branch);
25730 }
25731
25732 inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
25733 {
25734 if (
25735 !token_is(token_t::e_lcrlbracket) ||
25736 !token_is(token_t::e_rcrlbracket)
25737 )
25738 {
25739 set_error(
25741 current_token(),
25742 "ERR170 - Expected a '{}' for uninitialised var definition",
25744
25745 return error_node();
25746 }
25747 else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
25748 {
25749 set_error(
25751 current_token(),
25752 "ERR171 - Expected ';' after uninitialised variable definition",
25754
25755 return error_node();
25756 }
25757
25758 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
25759
25760 scope_element& se = sem_.get_element(var_name);
25761
25762 if (se.name == var_name)
25763 {
25764 if (se.active)
25765 {
25766 set_error(
25768 current_token(),
25769 "ERR172 - Illegal redefinition of local variable: '" + var_name + "'",
25771
25772 return error_node();
25773 }
25774 else if (scope_element::e_variable == se.type)
25775 {
25776 var_node = se.var_node;
25777 se.active = true;
25778 se.ref_count++;
25779 }
25780 }
25781
25782 if (0 == var_node)
25783 {
25784 scope_element nse;
25785 nse.name = var_name;
25786 nse.active = true;
25787 nse.ref_count = 1;
25788 nse.type = scope_element::e_variable;
25789 nse.depth = state_.scope_depth;
25790 nse.ip_index = sem_.next_ip_index();
25791 nse.data = new T(T(0));
25792 nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
25793
25794 if (!sem_.add_element(nse))
25795 {
25796 set_error(
25798 current_token(),
25799 "ERR173 - Failed to add new local variable '" + var_name + "' to SEM",
25801
25802 sem_.free_element(nse);
25803
25804 return error_node();
25805 }
25806
25807 exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
25808 nse.name.c_str()));
25809 }
25810
25811 lodge_symbol(var_name, e_st_local_variable);
25812
25813 state_.activate_side_effect("parse_uninitialised_var_statement()");
25814
25815 return expression_generator_(T(0));
25816 }
25817
25818 inline expression_node_ptr parse_swap_statement()
25819 {
25820 if (!details::imatch(current_token().value,"swap"))
25821 {
25822 return error_node();
25823 }
25824 else
25825 next_token();
25826
25827 if (!token_is(token_t::e_lbracket))
25828 {
25829 set_error(
25831 current_token(),
25832 "ERR174 - Expected '(' at start of swap statement",
25834
25835 return error_node();
25836 }
25837
25838 expression_node_ptr variable0 = error_node();
25839 expression_node_ptr variable1 = error_node();
25840
25841 bool variable0_generated = false;
25842 bool variable1_generated = false;
25843
25844 const std::string var0_name = current_token().value;
25845
25846 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25847 {
25848 set_error(
25850 current_token(),
25851 "ERR175 - Expected a symbol for variable or vector element definition",
25853
25854 return error_node();
25855 }
25856 else if (peek_token_is(token_t::e_lsqrbracket))
25857 {
25858 if (0 == (variable0 = parse_vector()))
25859 {
25860 set_error(
25862 current_token(),
25863 "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
25865
25866 return error_node();
25867 }
25868
25869 variable0_generated = true;
25870 }
25871 else
25872 {
25873 if (symtab_store_.is_variable(var0_name))
25874 {
25875 variable0 = symtab_store_.get_variable(var0_name);
25876 }
25877
25878 const scope_element& se = sem_.get_element(var0_name);
25879
25880 if (
25881 (se.active) &&
25882 (se.name == var0_name) &&
25883 (scope_element::e_variable == se.type)
25884 )
25885 {
25886 variable0 = se.var_node;
25887 }
25888
25889 lodge_symbol(var0_name, e_st_variable);
25890
25891 if (0 == variable0)
25892 {
25893 set_error(
25895 current_token(),
25896 "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'",
25898
25899 return error_node();
25900 }
25901 else
25902 next_token();
25903 }
25904
25905 if (!token_is(token_t::e_comma))
25906 {
25907 set_error(
25909 current_token(),
25910 "ERR178 - Expected ',' between parameters to swap",
25912
25913 if (variable0_generated)
25914 {
25915 free_node(node_allocator_,variable0);
25916 }
25917
25918 return error_node();
25919 }
25920
25921 const std::string var1_name = current_token().value;
25922
25923 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25924 {
25925 set_error(
25927 current_token(),
25928 "ERR179 - Expected a symbol for variable or vector element definition",
25930
25931 if (variable0_generated)
25932 {
25933 free_node(node_allocator_,variable0);
25934 }
25935
25936 return error_node();
25937 }
25938 else if (peek_token_is(token_t::e_lsqrbracket))
25939 {
25940 if (0 == (variable1 = parse_vector()))
25941 {
25942 set_error(
25944 current_token(),
25945 "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
25947
25948 if (variable0_generated)
25949 {
25950 free_node(node_allocator_,variable0);
25951 }
25952
25953 return error_node();
25954 }
25955
25956 variable1_generated = true;
25957 }
25958 else
25959 {
25960 if (symtab_store_.is_variable(var1_name))
25961 {
25962 variable1 = symtab_store_.get_variable(var1_name);
25963 }
25964
25965 const scope_element& se = sem_.get_element(var1_name);
25966
25967 if (
25968 (se.active) &&
25969 (se.name == var1_name) &&
25970 (scope_element::e_variable == se.type)
25971 )
25972 {
25973 variable1 = se.var_node;
25974 }
25975
25976 lodge_symbol(var1_name, e_st_variable);
25977
25978 if (0 == variable1)
25979 {
25980 set_error(
25982 current_token(),
25983 "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25985
25986 if (variable0_generated)
25987 {
25988 free_node(node_allocator_,variable0);
25989 }
25990
25991 return error_node();
25992 }
25993 else
25994 next_token();
25995 }
25996
25997 if (!token_is(token_t::e_rbracket))
25998 {
25999 set_error(
26001 current_token(),
26002 "ERR182 - Expected ')' at end of swap statement",
26004
26005 if (variable0_generated)
26006 {
26007 free_node(node_allocator_,variable0);
26008 }
26009
26010 if (variable1_generated)
26011 {
26012 free_node(node_allocator_,variable1);
26013 }
26014
26015 return error_node();
26016 }
26017
26018 typedef details::variable_node<T>* variable_node_ptr;
26019
26020 variable_node_ptr v0 = variable_node_ptr(0);
26021 variable_node_ptr v1 = variable_node_ptr(0);
26022
26023 expression_node_ptr result = error_node();
26024
26025 if (
26026 (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
26027 (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
26028 )
26029 {
26030 result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
26031
26032 if (variable0_generated)
26033 {
26034 free_node(node_allocator_,variable0);
26035 }
26036
26037 if (variable1_generated)
26038 {
26039 free_node(node_allocator_,variable1);
26040 }
26041 }
26042 else
26043 result = node_allocator_.allocate<details::swap_generic_node<T> >
26044 (variable0, variable1);
26045
26046 state_.activate_side_effect("parse_swap_statement()");
26047
26048 return result;
26049 }
26050
26051 #ifndef exprtk_disable_return_statement
26052 inline expression_node_ptr parse_return_statement()
26053 {
26054 if (state_.parsing_return_stmt)
26055 {
26056 set_error(
26058 current_token(),
26059 "ERR183 - Return call within a return call is not allowed",
26061
26062 return error_node();
26063 }
26064
26065 scoped_bool_negator sbn(state_.parsing_return_stmt);
26066
26067 std::vector<expression_node_ptr> arg_list;
26068
26069 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
26070
26071 if (!details::imatch(current_token().value,"return"))
26072 {
26073 return error_node();
26074 }
26075 else
26076 next_token();
26077
26078 if (!token_is(token_t::e_lsqrbracket))
26079 {
26080 set_error(
26082 current_token(),
26083 "ERR184 - Expected '[' at start of return statement",
26085
26086 return error_node();
26087 }
26088 else if (!token_is(token_t::e_rsqrbracket))
26089 {
26090 for ( ; ; )
26091 {
26092 expression_node_ptr arg = parse_expression();
26093
26094 if (0 == arg)
26095 return error_node();
26096
26097 arg_list.push_back(arg);
26098
26099 if (token_is(token_t::e_rsqrbracket))
26100 break;
26101 else if (!token_is(token_t::e_comma))
26102 {
26103 set_error(
26105 current_token(),
26106 "ERR185 - Expected ',' between values during call to return",
26108
26109 return error_node();
26110 }
26111 }
26112 }
26113 else if (settings_.zero_return_disabled())
26114 {
26115 set_error(
26117 current_token(),
26118 "ERR186 - Zero parameter return statement not allowed",
26120
26121 return error_node();
26122 }
26123
26124 const lexer::token prev_token = current_token();
26125
26126 if (token_is(token_t::e_rsqrbracket))
26127 {
26128 if (!arg_list.empty())
26129 {
26130 set_error(
26132 prev_token,
26133 "ERR187 - Invalid ']' found during return call",
26135
26136 return error_node();
26137 }
26138 }
26139
26140 std::string ret_param_type_list;
26141
26142 for (std::size_t i = 0; i < arg_list.size(); ++i)
26143 {
26144 if (0 == arg_list[i])
26145 return error_node();
26146 else if (is_ivector_node(arg_list[i]))
26147 ret_param_type_list += 'V';
26148 else if (is_generally_string_node(arg_list[i]))
26149 ret_param_type_list += 'S';
26150 else
26151 ret_param_type_list += 'T';
26152 }
26153
26154 dec_.retparam_list_.push_back(ret_param_type_list);
26155
26156 expression_node_ptr result = expression_generator_.return_call(arg_list);
26157
26158 sdd.delete_ptr = (0 == result);
26159
26160 state_.return_stmt_present = true;
26161
26162 state_.activate_side_effect("parse_return_statement()");
26163
26164 return result;
26165 }
26166 #else
26167 inline expression_node_ptr parse_return_statement()
26168 {
26169 return error_node();
26170 }
26171 #endif
26172
26173 inline bool post_variable_process(const std::string& symbol)
26174 {
26175 if (
26176 peek_token_is(token_t::e_lbracket ) ||
26177 peek_token_is(token_t::e_lcrlbracket) ||
26178 peek_token_is(token_t::e_lsqrbracket)
26179 )
26180 {
26181 if (!settings_.commutative_check_enabled())
26182 {
26183 set_error(
26185 current_token(),
26186 "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket",
26188
26189 return false;
26190 }
26191
26192 lexer().insert_front(token_t::e_mul);
26193 }
26194
26195 return true;
26196 }
26197
26198 inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
26199 {
26200 bool implied_mul = false;
26201
26202 if (is_generally_string_node(branch))
26203 return true;
26204
26205 const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
26206
26207 switch (token)
26208 {
26209 case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
26210 token_is(token_t::e_lcrlbracket,hold) ||
26211 token_is(token_t::e_lsqrbracket,hold) ;
26212 break;
26213
26214 case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
26215 token_is(token_t::e_lcrlbracket,hold) ||
26216 token_is(token_t::e_lsqrbracket,hold) ;
26217 break;
26218
26219 case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
26220 token_is(token_t::e_lcrlbracket,hold) ||
26221 token_is(token_t::e_lsqrbracket,hold) ;
26222 break;
26223
26224 default : return true;
26225 }
26226
26227 if (implied_mul)
26228 {
26229 if (!settings_.commutative_check_enabled())
26230 {
26231 set_error(
26233 current_token(),
26234 "ERR189 - Invalid sequence of brackets",
26236
26237 return false;
26238 }
26239 else if (token_t::e_eof != current_token().type)
26240 {
26241 lexer().insert_front(current_token().type);
26242 lexer().insert_front(token_t::e_mul);
26243 next_token();
26244 }
26245 }
26246
26247 return true;
26248 }
26249
26250 inline expression_node_ptr parse_symtab_symbol()
26251 {
26252 const std::string symbol = current_token().value;
26253
26254 // Are we dealing with a variable or a special constant?
26255 expression_node_ptr variable = symtab_store_.get_variable(symbol);
26256
26257 if (variable)
26258 {
26259 if (symtab_store_.is_constant_node(symbol))
26260 {
26261 variable = expression_generator_(variable->value());
26262 }
26263
26264 if (!post_variable_process(symbol))
26265 return error_node();
26266
26267 lodge_symbol(symbol, e_st_variable);
26268 next_token();
26269
26270 return variable;
26271 }
26272
26273 // Are we dealing with a locally defined variable, vector or string?
26274 if (!sem_.empty())
26275 {
26276 scope_element& se = sem_.get_active_element(symbol);
26277
26278 if (se.active && details::imatch(se.name, symbol))
26279 {
26280 if (scope_element::e_variable == se.type)
26281 {
26282 se.active = true;
26283 lodge_symbol(symbol, e_st_local_variable);
26284
26285 if (!post_variable_process(symbol))
26286 return error_node();
26287
26288 next_token();
26289
26290 return se.var_node;
26291 }
26292 else if (scope_element::e_vector == se.type)
26293 {
26294 return parse_vector();
26295 }
26296 #ifndef exprtk_disable_string_capabilities
26297 else if (scope_element::e_string == se.type)
26298 {
26299 return parse_string();
26300 }
26301 #endif
26302 }
26303 }
26304
26305 #ifndef exprtk_disable_string_capabilities
26306 // Are we dealing with a string variable?
26307 if (symtab_store_.is_stringvar(symbol))
26308 {
26309 return parse_string();
26310 }
26311 #endif
26312
26313 {
26314 // Are we dealing with a function?
26315 ifunction<T>* function = symtab_store_.get_function(symbol);
26316
26317 if (function)
26318 {
26319 lodge_symbol(symbol, e_st_function);
26320
26321 expression_node_ptr func_node =
26322 parse_function_invocation(function,symbol);
26323
26324 if (func_node)
26325 return func_node;
26326 else
26327 {
26328 set_error(
26330 current_token(),
26331 "ERR190 - Failed to generate node for function: '" + symbol + "'",
26333
26334 return error_node();
26335 }
26336 }
26337 }
26338
26339 {
26340 // Are we dealing with a vararg function?
26341 ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
26342
26343 if (vararg_function)
26344 {
26345 lodge_symbol(symbol, e_st_function);
26346
26347 expression_node_ptr vararg_func_node =
26348 parse_vararg_function_call(vararg_function, symbol);
26349
26350 if (vararg_func_node)
26351 return vararg_func_node;
26352 else
26353 {
26354 set_error(
26356 current_token(),
26357 "ERR191 - Failed to generate node for vararg function: '" + symbol + "'",
26359
26360 return error_node();
26361 }
26362 }
26363 }
26364
26365 {
26366 // Are we dealing with a vararg generic function?
26367 igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
26368
26369 if (generic_function)
26370 {
26371 lodge_symbol(symbol, e_st_function);
26372
26373 expression_node_ptr genericfunc_node =
26374 parse_generic_function_call(generic_function, symbol);
26375
26376 if (genericfunc_node)
26377 return genericfunc_node;
26378 else
26379 {
26380 set_error(
26382 current_token(),
26383 "ERR192 - Failed to generate node for generic function: '" + symbol + "'",
26385
26386 return error_node();
26387 }
26388 }
26389 }
26390
26391 #ifndef exprtk_disable_string_capabilities
26392 {
26393 // Are we dealing with a vararg string returning function?
26394 igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
26395
26396 if (string_function)
26397 {
26398 lodge_symbol(symbol, e_st_function);
26399
26400 expression_node_ptr stringfunc_node =
26401 parse_string_function_call(string_function, symbol);
26402
26403 if (stringfunc_node)
26404 return stringfunc_node;
26405 else
26406 {
26407 set_error(
26409 current_token(),
26410 "ERR193 - Failed to generate node for string function: '" + symbol + "'",
26412
26413 return error_node();
26414 }
26415 }
26416 }
26417
26418 {
26419 // Are we dealing with a vararg overloaded scalar/string returning function?
26420 igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
26421
26422 if (overload_function)
26423 {
26424 lodge_symbol(symbol, e_st_function);
26425
26426 expression_node_ptr overloadfunc_node =
26427 parse_overload_function_call(overload_function, symbol);
26428
26429 if (overloadfunc_node)
26430 return overloadfunc_node;
26431 else
26432 {
26433 set_error(
26435 current_token(),
26436 "ERR194 - Failed to generate node for overload function: '" + symbol + "'",
26438
26439 return error_node();
26440 }
26441 }
26442 }
26443 #endif
26444
26445 // Are we dealing with a vector?
26446 if (symtab_store_.is_vector(symbol))
26447 {
26448 lodge_symbol(symbol, e_st_vector);
26449 return parse_vector();
26450 }
26451
26452 if (details::is_reserved_symbol(symbol))
26453 {
26454 if (
26455 settings_.function_enabled(symbol) ||
26457 )
26458 {
26459 set_error(
26461 current_token(),
26462 "ERR195 - Invalid use of reserved symbol '" + symbol + "'",
26464
26465 return error_node();
26466 }
26467 }
26468
26469 // Should we handle unknown symbols?
26470 if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
26471 {
26472 if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
26473 {
26474 symbol_table_t& symtab = symtab_store_.get_symbol_table();
26475
26476 std::string error_message;
26477
26478 if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
26479 {
26480 T default_value = T(0);
26481
26482 typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
26483
26484 if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
26485 {
26486 bool create_result = false;
26487
26488 switch (usr_symbol_type)
26489 {
26490 case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
26491 break;
26492
26493 case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
26494 break;
26495
26496 default : create_result = false;
26497 }
26498
26499 if (create_result)
26500 {
26501 expression_node_ptr var = symtab_store_.get_variable(symbol);
26502
26503 if (var)
26504 {
26505 if (symtab_store_.is_constant_node(symbol))
26506 {
26507 var = expression_generator_(var->value());
26508 }
26509
26510 lodge_symbol(symbol, e_st_variable);
26511
26512 if (!post_variable_process(symbol))
26513 return error_node();
26514
26515 next_token();
26516
26517 return var;
26518 }
26519 }
26520 }
26521
26522 set_error(
26524 current_token(),
26525 "ERR196 - Failed to create variable: '" + symbol + "'" +
26526 (error_message.empty() ? "" : " - " + error_message),
26528
26529 }
26530 else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
26531 {
26532 if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
26533 {
26534 expression_node_ptr result = parse_symtab_symbol();
26535
26536 if (result)
26537 {
26538 return result;
26539 }
26540 }
26541
26542 set_error(
26544 current_token(),
26545 "ERR197 - Failed to resolve symbol: '" + symbol + "'" +
26546 (error_message.empty() ? "" : " - " + error_message),
26548 }
26549
26550 return error_node();
26551 }
26552 }
26553
26554 set_error(
26556 current_token(),
26557 "ERR198 - Undefined symbol: '" + symbol + "'",
26559
26560 return error_node();
26561 }
26562
26563 inline expression_node_ptr parse_symbol()
26564 {
26565 static const std::string symbol_if = "if" ;
26566 static const std::string symbol_while = "while" ;
26567 static const std::string symbol_repeat = "repeat" ;
26568 static const std::string symbol_for = "for" ;
26569 static const std::string symbol_switch = "switch" ;
26570 static const std::string symbol_null = "null" ;
26571 static const std::string symbol_break = "break" ;
26572 static const std::string symbol_continue = "continue";
26573 static const std::string symbol_var = "var" ;
26574 static const std::string symbol_swap = "swap" ;
26575 static const std::string symbol_return = "return" ;
26576 static const std::string symbol_not = "not" ;
26577
26578 if (valid_vararg_operation(current_token().value))
26579 {
26580 return parse_vararg_function();
26581 }
26582 else if (details::imatch(current_token().value, symbol_not))
26583 {
26584 return parse_not_statement();
26585 }
26586 else if (valid_base_operation(current_token().value))
26587 {
26588 return parse_base_operation();
26589 }
26590 else if (
26591 details::imatch(current_token().value, symbol_if) &&
26592 settings_.control_struct_enabled(current_token().value)
26593 )
26594 {
26595 return parse_conditional_statement();
26596 }
26597 else if (
26598 details::imatch(current_token().value, symbol_while) &&
26599 settings_.control_struct_enabled(current_token().value)
26600 )
26601 {
26602 return parse_while_loop();
26603 }
26604 else if (
26605 details::imatch(current_token().value, symbol_repeat) &&
26606 settings_.control_struct_enabled(current_token().value)
26607 )
26608 {
26609 return parse_repeat_until_loop();
26610 }
26611 else if (
26612 details::imatch(current_token().value, symbol_for) &&
26613 settings_.control_struct_enabled(current_token().value)
26614 )
26615 {
26616 return parse_for_loop();
26617 }
26618 else if (
26619 details::imatch(current_token().value, symbol_switch) &&
26620 settings_.control_struct_enabled(current_token().value)
26621 )
26622 {
26623 return parse_switch_statement();
26624 }
26625 else if (details::is_valid_sf_symbol(current_token().value))
26626 {
26627 return parse_special_function();
26628 }
26629 else if (details::imatch(current_token().value, symbol_null))
26630 {
26631 return parse_null_statement();
26632 }
26633 #ifndef exprtk_disable_break_continue
26634 else if (details::imatch(current_token().value, symbol_break))
26635 {
26636 return parse_break_statement();
26637 }
26638 else if (details::imatch(current_token().value, symbol_continue))
26639 {
26640 return parse_continue_statement();
26641 }
26642 #endif
26643 else if (details::imatch(current_token().value, symbol_var))
26644 {
26645 return parse_define_var_statement();
26646 }
26647 else if (details::imatch(current_token().value, symbol_swap))
26648 {
26649 return parse_swap_statement();
26650 }
26651 #ifndef exprtk_disable_return_statement
26652 else if (
26653 details::imatch(current_token().value, symbol_return) &&
26654 settings_.control_struct_enabled(current_token().value)
26655 )
26656 {
26657 return parse_return_statement();
26658 }
26659 #endif
26660 else if (symtab_store_.valid() || !sem_.empty())
26661 {
26662 return parse_symtab_symbol();
26663 }
26664 else
26665 {
26666 set_error(
26668 current_token(),
26669 "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
26671
26672 return error_node();
26673 }
26674 }
26675
26676 inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
26677 {
26678 stack_limit_handler slh(*this);
26679
26680 if (!slh)
26681 {
26682 return error_node();
26683 }
26684
26685 expression_node_ptr branch = error_node();
26686
26687 if (token_t::e_number == current_token().type)
26688 {
26689 T numeric_value = T(0);
26690
26691 if (details::string_to_real(current_token().value, numeric_value))
26692 {
26693 expression_node_ptr literal_exp = expression_generator_(numeric_value);
26694
26695 if (0 == literal_exp)
26696 {
26697 set_error(
26699 current_token(),
26700 "ERR200 - Failed generate node for scalar: '" + current_token().value + "'",
26702
26703 return error_node();
26704 }
26705
26706 next_token();
26707 branch = literal_exp;
26708 }
26709 else
26710 {
26711 set_error(
26713 current_token(),
26714 "ERR201 - Failed to convert '" + current_token().value + "' to a number",
26716
26717 return error_node();
26718 }
26719 }
26720 else if (token_t::e_symbol == current_token().type)
26721 {
26722 branch = parse_symbol();
26723 }
26724 #ifndef exprtk_disable_string_capabilities
26725 else if (token_t::e_string == current_token().type)
26726 {
26727 branch = parse_const_string();
26728 }
26729 #endif
26730 else if (token_t::e_lbracket == current_token().type)
26731 {
26732 next_token();
26733
26734 if (0 == (branch = parse_expression()))
26735 return error_node();
26736 else if (!token_is(token_t::e_rbracket))
26737 {
26738 set_error(
26740 current_token(),
26741 "ERR202 - Expected ')' instead of: '" + current_token().value + "'",
26743
26744 free_node(node_allocator_,branch);
26745
26746 return error_node();
26747 }
26748 else if (!post_bracket_process(token_t::e_lbracket,branch))
26749 {
26750 free_node(node_allocator_,branch);
26751
26752 return error_node();
26753 }
26754 }
26755 else if (token_t::e_lsqrbracket == current_token().type)
26756 {
26757 next_token();
26758
26759 if (0 == (branch = parse_expression()))
26760 return error_node();
26761 else if (!token_is(token_t::e_rsqrbracket))
26762 {
26763 set_error(
26765 current_token(),
26766 "ERR203 - Expected ']' instead of: '" + current_token().value + "'",
26768
26769 free_node(node_allocator_,branch);
26770
26771 return error_node();
26772 }
26773 else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
26774 {
26775 free_node(node_allocator_,branch);
26776
26777 return error_node();
26778 }
26779 }
26780 else if (token_t::e_lcrlbracket == current_token().type)
26781 {
26782 next_token();
26783
26784 if (0 == (branch = parse_expression()))
26785 return error_node();
26786 else if (!token_is(token_t::e_rcrlbracket))
26787 {
26788 set_error(
26790 current_token(),
26791 "ERR204 - Expected '}' instead of: '" + current_token().value + "'",
26793
26794 free_node(node_allocator_,branch);
26795
26796 return error_node();
26797 }
26798 else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
26799 {
26800 free_node(node_allocator_,branch);
26801
26802 return error_node();
26803 }
26804 }
26805 else if (token_t::e_sub == current_token().type)
26806 {
26807 next_token();
26808 branch = parse_expression(e_level11);
26809
26810 if (
26811 branch &&
26812 !(
26813 details::is_neg_unary_node (branch) &&
26814 simplify_unary_negation_branch(branch)
26815 )
26816 )
26817 {
26818 expression_node_ptr result = expression_generator_(details::e_neg,branch);
26819
26820 if (0 == result)
26821 {
26822 free_node(node_allocator_,branch);
26823
26824 return error_node();
26825 }
26826 else
26827 branch = result;
26828 }
26829 }
26830 else if (token_t::e_add == current_token().type)
26831 {
26832 next_token();
26833 branch = parse_expression(e_level13);
26834 }
26835 else if (token_t::e_eof == current_token().type)
26836 {
26837 set_error(
26839 current_token(),
26840 "ERR205 - Premature end of expression[1]",
26842
26843 return error_node();
26844 }
26845 else
26846 {
26847 set_error(
26849 current_token(),
26850 "ERR206 - Premature end of expression[2]",
26852
26853 return error_node();
26854 }
26855
26856 if (
26857 branch &&
26858 (e_level00 == precedence) &&
26859 token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
26860 )
26861 {
26862 branch = parse_ternary_conditional_statement(branch);
26863 }
26864
26865 parse_pending_string_rangesize(branch);
26866
26867 return branch;
26868 }
26869
26870 template <typename Type>
26871 class expression_generator
26872 {
26873 public:
26874
26875 typedef details::expression_node<Type>* expression_node_ptr;
26876 typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
26877 typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
26878 typedef typename exprtk::parser<Type> parser_t;
26879 typedef const Type& vtype;
26880 typedef const Type ctype;
26881
26882 inline void init_synthesize_map()
26883 {
26884 #ifndef exprtk_disable_enhanced_features
26885 synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
26886 synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
26887 synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
26888
26889 #define register_synthezier(S) \
26890 synthesize_map_[S ::node_type::id()] = S ::process; \
26891
26892 register_synthezier(synthesize_vovov_expression0)
26893 register_synthezier(synthesize_vovov_expression1)
26894 register_synthezier(synthesize_vovoc_expression0)
26895 register_synthezier(synthesize_vovoc_expression1)
26896 register_synthezier(synthesize_vocov_expression0)
26897 register_synthezier(synthesize_vocov_expression1)
26898 register_synthezier(synthesize_covov_expression0)
26899 register_synthezier(synthesize_covov_expression1)
26900 register_synthezier(synthesize_covoc_expression0)
26901 register_synthezier(synthesize_covoc_expression1)
26902 register_synthezier(synthesize_cocov_expression1)
26903 register_synthezier(synthesize_vococ_expression0)
26904
26905 register_synthezier(synthesize_vovovov_expression0)
26906 register_synthezier(synthesize_vovovoc_expression0)
26907 register_synthezier(synthesize_vovocov_expression0)
26908 register_synthezier(synthesize_vocovov_expression0)
26909 register_synthezier(synthesize_covovov_expression0)
26910 register_synthezier(synthesize_covocov_expression0)
26911 register_synthezier(synthesize_vocovoc_expression0)
26912 register_synthezier(synthesize_covovoc_expression0)
26913 register_synthezier(synthesize_vococov_expression0)
26914
26915 register_synthezier(synthesize_vovovov_expression1)
26916 register_synthezier(synthesize_vovovoc_expression1)
26917 register_synthezier(synthesize_vovocov_expression1)
26918 register_synthezier(synthesize_vocovov_expression1)
26919 register_synthezier(synthesize_covovov_expression1)
26920 register_synthezier(synthesize_covocov_expression1)
26921 register_synthezier(synthesize_vocovoc_expression1)
26922 register_synthezier(synthesize_covovoc_expression1)
26923 register_synthezier(synthesize_vococov_expression1)
26924
26925 register_synthezier(synthesize_vovovov_expression2)
26926 register_synthezier(synthesize_vovovoc_expression2)
26927 register_synthezier(synthesize_vovocov_expression2)
26928 register_synthezier(synthesize_vocovov_expression2)
26929 register_synthezier(synthesize_covovov_expression2)
26930 register_synthezier(synthesize_covocov_expression2)
26931 register_synthezier(synthesize_vocovoc_expression2)
26932 register_synthezier(synthesize_covovoc_expression2)
26933
26934 register_synthezier(synthesize_vovovov_expression3)
26935 register_synthezier(synthesize_vovovoc_expression3)
26936 register_synthezier(synthesize_vovocov_expression3)
26937 register_synthezier(synthesize_vocovov_expression3)
26938 register_synthezier(synthesize_covovov_expression3)
26939 register_synthezier(synthesize_covocov_expression3)
26940 register_synthezier(synthesize_vocovoc_expression3)
26941 register_synthezier(synthesize_covovoc_expression3)
26942 register_synthezier(synthesize_vococov_expression3)
26943
26944 register_synthezier(synthesize_vovovov_expression4)
26945 register_synthezier(synthesize_vovovoc_expression4)
26946 register_synthezier(synthesize_vovocov_expression4)
26947 register_synthezier(synthesize_vocovov_expression4)
26948 register_synthezier(synthesize_covovov_expression4)
26949 register_synthezier(synthesize_covocov_expression4)
26950 register_synthezier(synthesize_vocovoc_expression4)
26951 register_synthezier(synthesize_covovoc_expression4)
26952 #endif
26953 }
26954
26955 inline void set_parser(parser_t& p)
26956 {
26957 parser_ = &p;
26958 }
26959
26960 inline void set_uom(unary_op_map_t& unary_op_map)
26961 {
26962 unary_op_map_ = &unary_op_map;
26963 }
26964
26965 inline void set_bom(binary_op_map_t& binary_op_map)
26966 {
26967 binary_op_map_ = &binary_op_map;
26968 }
26969
26970 inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
26971 {
26972 inv_binary_op_map_ = &inv_binary_op_map;
26973 }
26974
26975 inline void set_sf3m(sf3_map_t& sf3_map)
26976 {
26977 sf3_map_ = &sf3_map;
26978 }
26979
26980 inline void set_sf4m(sf4_map_t& sf4_map)
26981 {
26982 sf4_map_ = &sf4_map;
26983 }
26984
26985 inline void set_allocator(details::node_allocator& na)
26986 {
26987 node_allocator_ = &na;
26988 }
26989
26990 inline void set_strength_reduction_state(const bool enabled)
26991 {
26992 strength_reduction_enabled_ = enabled;
26993 }
26994
26995 inline bool strength_reduction_enabled() const
26996 {
26997 return strength_reduction_enabled_;
26998 }
26999
27000 inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
27001 {
27002 typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
27003
27004 if ((*binary_op_map_).end() == bop_itr)
27005 return false;
27006
27007 bop = bop_itr->second;
27008
27009 return true;
27010 }
27011
27012 inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
27013 {
27014 typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
27015
27016 if ((*unary_op_map_).end() == uop_itr)
27017 return false;
27018
27019 uop = uop_itr->second;
27020
27021 return true;
27022 }
27023
27024 inline details::operator_type get_operator(const binary_functor_t& bop) const
27025 {
27026 return (*inv_binary_op_map_).find(bop)->second;
27027 }
27028
27029 inline expression_node_ptr operator() (const Type& v) const
27030 {
27031 return node_allocator_->allocate<literal_node_t>(v);
27032 }
27033
27034 #ifndef exprtk_disable_string_capabilities
27035 inline expression_node_ptr operator() (const std::string& s) const
27036 {
27037 return node_allocator_->allocate<string_literal_node_t>(s);
27038 }
27039
27040 inline expression_node_ptr operator() (std::string& s, range_t& rp) const
27041 {
27042 return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
27043 }
27044
27045 inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
27046 {
27047 return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
27048 }
27049
27050 inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
27051 {
27052 if (is_generally_string_node(branch))
27053 return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
27054 else
27055 return error_node();
27056 }
27057 #endif
27058
27059 inline bool unary_optimisable(const details::operator_type& operation) const
27060 {
27061 return (details::e_abs == operation) || (details::e_acos == operation) ||
27062 (details::e_acosh == operation) || (details::e_asin == operation) ||
27063 (details::e_asinh == operation) || (details::e_atan == operation) ||
27064 (details::e_atanh == operation) || (details::e_ceil == operation) ||
27065 (details::e_cos == operation) || (details::e_cosh == operation) ||
27066 (details::e_exp == operation) || (details::e_expm1 == operation) ||
27067 (details::e_floor == operation) || (details::e_log == operation) ||
27068 (details::e_log10 == operation) || (details::e_log2 == operation) ||
27069 (details::e_log1p == operation) || (details::e_neg == operation) ||
27070 (details::e_pos == operation) || (details::e_round == operation) ||
27071 (details::e_sin == operation) || (details::e_sinc == operation) ||
27072 (details::e_sinh == operation) || (details::e_sqrt == operation) ||
27073 (details::e_tan == operation) || (details::e_tanh == operation) ||
27074 (details::e_cot == operation) || (details::e_sec == operation) ||
27075 (details::e_csc == operation) || (details::e_r2d == operation) ||
27076 (details::e_d2r == operation) || (details::e_d2g == operation) ||
27077 (details::e_g2d == operation) || (details::e_notl == operation) ||
27078 (details::e_sgn == operation) || (details::e_erf == operation) ||
27079 (details::e_erfc == operation) || (details::e_ncdf == operation) ||
27080 (details::e_frac == operation) || (details::e_trunc == operation) ;
27081 }
27082
27083 inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
27084 {
27085 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
27086
27087 if (sf3_map_->end() == itr)
27088 return false;
27089 else
27090 tfunc = itr->second.first;
27091
27092 return true;
27093 }
27094
27095 inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
27096 {
27097 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
27098
27099 if (sf4_map_->end() == itr)
27100 return false;
27101 else
27102 qfunc = itr->second.first;
27103
27104 return true;
27105 }
27106
27107 inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
27108 {
27109 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
27110
27111 if (sf3_map_->end() == itr)
27112 return false;
27113 else
27114 operation = itr->second.second;
27115
27116 return true;
27117 }
27118
27119 inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
27120 {
27121 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
27122
27123 if (sf4_map_->end() == itr)
27124 return false;
27125 else
27126 operation = itr->second.second;
27127
27128 return true;
27129 }
27130
27131 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
27132 {
27133 if (0 == branch[0])
27134 {
27135 return error_node();
27136 }
27137 else if (details::is_null_node(branch[0]))
27138 {
27139 return branch[0];
27140 }
27141 else if (details::is_break_node(branch[0]))
27142 {
27143 return error_node();
27144 }
27145 else if (details::is_continue_node(branch[0]))
27146 {
27147 return error_node();
27148 }
27149 else if (details::is_constant_node(branch[0]))
27150 {
27151 return synthesize_expression<unary_node_t,1>(operation,branch);
27152 }
27153 else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
27154 {
27155 return synthesize_uv_expression(operation,branch);
27156 }
27157 else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
27158 {
27159 return synthesize_uvec_expression(operation,branch);
27160 }
27161 else
27162 return synthesize_unary_expression(operation,branch);
27163 }
27164
27165 inline bool is_assignment_operation(const details::operator_type& operation) const
27166 {
27167 return (
27168 (details::e_addass == operation) ||
27169 (details::e_subass == operation) ||
27170 (details::e_mulass == operation) ||
27171 (details::e_divass == operation) ||
27172 (details::e_modass == operation)
27173 ) &&
27174 parser_->settings_.assignment_enabled(operation);
27175 }
27176
27177 #ifndef exprtk_disable_string_capabilities
27178 inline bool valid_string_operation(const details::operator_type& operation) const
27179 {
27180 return (details::e_add == operation) ||
27181 (details::e_lt == operation) ||
27182 (details::e_lte == operation) ||
27183 (details::e_gt == operation) ||
27184 (details::e_gte == operation) ||
27185 (details::e_eq == operation) ||
27186 (details::e_ne == operation) ||
27187 (details::e_in == operation) ||
27188 (details::e_like == operation) ||
27189 (details::e_ilike == operation) ||
27190 (details::e_assign == operation) ||
27191 (details::e_addass == operation) ||
27192 (details::e_swap == operation) ;
27193 }
27194 #else
27195 inline bool valid_string_operation(const details::operator_type&) const
27196 {
27197 return false;
27198 }
27199 #endif
27200
27201 inline std::string to_str(const details::operator_type& operation) const
27202 {
27203 switch (operation)
27204 {
27205 case details::e_add : return "+" ;
27206 case details::e_sub : return "-" ;
27207 case details::e_mul : return "*" ;
27208 case details::e_div : return "/" ;
27209 case details::e_mod : return "%" ;
27210 case details::e_pow : return "^" ;
27211 case details::e_lt : return "<" ;
27212 case details::e_lte : return "<=" ;
27213 case details::e_gt : return ">" ;
27214 case details::e_gte : return ">=" ;
27215 case details::e_eq : return "==" ;
27216 case details::e_ne : return "!=" ;
27217 case details::e_and : return "and" ;
27218 case details::e_nand : return "nand" ;
27219 case details::e_or : return "or" ;
27220 case details::e_nor : return "nor" ;
27221 case details::e_xor : return "xor" ;
27222 case details::e_xnor : return "xnor" ;
27223 default : return "UNKNOWN";
27224 }
27225 }
27226
27227 inline bool operation_optimisable(const details::operator_type& operation) const
27228 {
27229 return (details::e_add == operation) ||
27230 (details::e_sub == operation) ||
27231 (details::e_mul == operation) ||
27232 (details::e_div == operation) ||
27233 (details::e_mod == operation) ||
27234 (details::e_pow == operation) ||
27235 (details::e_lt == operation) ||
27236 (details::e_lte == operation) ||
27237 (details::e_gt == operation) ||
27238 (details::e_gte == operation) ||
27239 (details::e_eq == operation) ||
27240 (details::e_ne == operation) ||
27241 (details::e_and == operation) ||
27242 (details::e_nand == operation) ||
27243 (details::e_or == operation) ||
27244 (details::e_nor == operation) ||
27245 (details::e_xor == operation) ||
27246 (details::e_xnor == operation) ;
27247 }
27248
27249 inline std::string branch_to_id(expression_node_ptr branch) const
27250 {
27251 static const std::string null_str ("(null)" );
27252 static const std::string const_str ("(c)" );
27253 static const std::string var_str ("(v)" );
27254 static const std::string vov_str ("(vov)" );
27255 static const std::string cov_str ("(cov)" );
27256 static const std::string voc_str ("(voc)" );
27257 static const std::string str_str ("(s)" );
27258 static const std::string strrng_str ("(rngs)" );
27259 static const std::string cs_str ("(cs)" );
27260 static const std::string cstrrng_str("(crngs)");
27261
27262 if (details::is_null_node(branch))
27263 return null_str;
27264 else if (details::is_constant_node(branch))
27265 return const_str;
27266 else if (details::is_variable_node(branch))
27267 return var_str;
27268 else if (details::is_vov_node(branch))
27269 return vov_str;
27270 else if (details::is_cov_node(branch))
27271 return cov_str;
27272 else if (details::is_voc_node(branch))
27273 return voc_str;
27274 else if (details::is_string_node(branch))
27275 return str_str;
27276 else if (details::is_const_string_node(branch))
27277 return cs_str;
27278 else if (details::is_string_range_node(branch))
27279 return strrng_str;
27280 else if (details::is_const_string_range_node(branch))
27281 return cstrrng_str;
27282 else if (details::is_t0ot1ot2_node(branch))
27283 return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
27284 else if (details::is_t0ot1ot2ot3_node(branch))
27285 return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
27286 else
27287 return "ERROR";
27288 }
27289
27290 inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
27291 {
27292 return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
27293 }
27294
27295 inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27296 {
27297 if (!operation_optimisable(operation))
27298 return false;
27299 else
27300 return details::is_constant_node(branch[0]) &&
27301 details::is_variable_node(branch[1]) ;
27302 }
27303
27304 inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27305 {
27306 if (!operation_optimisable(operation))
27307 return false;
27308 else
27309 return details::is_variable_node(branch[0]) &&
27310 details::is_constant_node(branch[1]) ;
27311 }
27312
27313 inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27314 {
27315 if (!operation_optimisable(operation))
27316 return false;
27317 else
27318 return details::is_variable_node(branch[0]) &&
27319 details::is_variable_node(branch[1]) ;
27320 }
27321
27322 inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27323 {
27324 if (!operation_optimisable(operation))
27325 return false;
27326 else
27327 return details::is_constant_node(branch[0]) &&
27328 !details::is_constant_node(branch[1]) ;
27329 }
27330
27331 inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27332 {
27333 if (!operation_optimisable(operation))
27334 return false;
27335 else
27336 return !details::is_constant_node(branch[0]) &&
27337 details::is_constant_node(branch[1]) ;
27338 }
27339
27340 inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27341 {
27342 if (
27343 (details::e_add == operation) ||
27344 (details::e_sub == operation) ||
27345 (details::e_mul == operation) ||
27346 (details::e_div == operation)
27347 )
27348 {
27349 return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
27350 (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
27351 }
27352 else
27353 return false;
27354 }
27355
27356 inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27357 {
27358 if (
27359 (details::e_add == operation) ||
27360 (details::e_sub == operation) ||
27361 (details::e_mul == operation) ||
27362 (details::e_div == operation)
27363 )
27364 {
27365 return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
27366 (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
27367 }
27368 else
27369 return false;
27370 }
27371
27372 inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27373 {
27374 if (!operation_optimisable(operation))
27375 return false;
27376 else
27377 return details::is_uv_node(branch[0]) &&
27378 details::is_uv_node(branch[1]) ;
27379 }
27380
27381 inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27382 {
27383 if (!operation_optimisable(operation))
27384 return false;
27385 else
27386 return details::is_variable_node(branch[0]) &&
27387 !details::is_variable_node(branch[1]) ;
27388 }
27389
27390 inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27391 {
27392 if (!operation_optimisable(operation))
27393 return false;
27394 else
27395 return !details::is_variable_node(branch[0]) &&
27396 details::is_variable_node(branch[1]) ;
27397 }
27398
27399 inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27400 {
27401 if (!operation_optimisable(operation))
27402 return false;
27403 else
27404 return !details::is_constant_node(branch[0]) ||
27405 !details::is_constant_node(branch[1]) ;
27406 }
27407
27408 inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27409 {
27410 if (is_assignment_operation(operation))
27411 {
27412 const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
27413
27414 if (details::is_string_node(branch[0]))
27415 return !b1_is_genstring;
27416 else
27417 return (
27418 !details::is_variable_node (branch[0]) &&
27419 !details::is_vector_elem_node (branch[0]) &&
27422 !details::is_vector_node (branch[0])
27423 )
27424 || b1_is_genstring;
27425 }
27426 else
27427 return false;
27428 }
27429
27430 inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
27431 {
27432 if (
27433 !details::is_constant_node(branch[1]) ||
27434 details::is_constant_node(branch[0]) ||
27435 details::is_variable_node(branch[0]) ||
27436 details::is_vector_node (branch[0]) ||
27438 )
27439 return false;
27440
27441 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
27442
27443 return cardinal_pow_optimisable(operation, c);
27444 }
27445
27446 inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
27447 {
27448 return (
27449 details::is_break_node (branch[0]) ||
27450 details::is_break_node (branch[1]) ||
27451 details::is_continue_node(branch[0]) ||
27452 details::is_continue_node(branch[1])
27453 );
27454 }
27455
27456 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27457 {
27458 const bool b0_string = is_generally_string_node(branch[0]);
27459 const bool b1_string = is_generally_string_node(branch[1]);
27460
27461 bool result = false;
27462
27463 if (b0_string != b1_string)
27464 result = true;
27465 else if (!valid_string_operation(operation) && b0_string && b1_string)
27466 result = true;
27467
27468 if (result)
27469 {
27470 parser_->set_synthesis_error("Invalid string operation");
27471 }
27472
27473 return result;
27474 }
27475
27476 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
27477 {
27478 const bool b0_string = is_generally_string_node(branch[0]);
27479 const bool b1_string = is_generally_string_node(branch[1]);
27480 const bool b2_string = is_generally_string_node(branch[2]);
27481
27482 bool result = false;
27483
27484 if ((b0_string != b1_string) || (b1_string != b2_string))
27485 result = true;
27486 else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
27487 result = true;
27488
27489 if (result)
27490 {
27491 parser_->set_synthesis_error("Invalid string operation");
27492 }
27493
27494 return result;
27495 }
27496
27497 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27498 {
27499 const bool b0_string = is_generally_string_node(branch[0]);
27500 const bool b1_string = is_generally_string_node(branch[1]);
27501
27502 return (b0_string && b1_string && valid_string_operation(operation));
27503 }
27504
27505 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
27506 {
27507 const bool b0_string = is_generally_string_node(branch[0]);
27508 const bool b1_string = is_generally_string_node(branch[1]);
27509 const bool b2_string = is_generally_string_node(branch[2]);
27510
27511 return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
27512 }
27513
27514 #ifndef exprtk_disable_sc_andor
27515 inline bool is_shortcircuit_expression(const details::operator_type& operation) const
27516 {
27517 return (
27518 (details::e_scand == operation) ||
27519 (details::e_scor == operation)
27520 );
27521 }
27522 #else
27523 inline bool is_shortcircuit_expression(const details::operator_type&) const
27524 {
27525 return false;
27526 }
27527 #endif
27528
27529 inline bool is_null_present(expression_node_ptr (&branch)[2]) const
27530 {
27531 return (
27532 details::is_null_node(branch[0]) ||
27533 details::is_null_node(branch[1])
27534 );
27535 }
27536
27537 inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27538 {
27539 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
27540 return false;
27541 else
27542 return (
27543 (details::e_lt == operation) ||
27544 (details::e_lte == operation) ||
27545 (details::e_gt == operation) ||
27546 (details::e_gte == operation) ||
27547 (details::e_eq == operation) ||
27548 (details::e_ne == operation) ||
27549 (details::e_equal == operation) ||
27550 (details::e_and == operation) ||
27551 (details::e_nand == operation) ||
27552 (details:: e_or == operation) ||
27553 (details:: e_nor == operation) ||
27554 (details:: e_xor == operation) ||
27555 (details::e_xnor == operation)
27556 );
27557 }
27558
27559 inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27560 {
27561 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
27562 return false;
27563 else
27564 return (
27565 (details::e_add == operation) ||
27566 (details::e_sub == operation) ||
27567 (details::e_mul == operation) ||
27568 (details::e_div == operation) ||
27569 (details::e_pow == operation)
27570 );
27571 }
27572
27573 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
27574 {
27575 if ((0 == branch[0]) || (0 == branch[1]))
27576 {
27577 return error_node();
27578 }
27579 else if (is_invalid_string_op(operation,branch))
27580 {
27581 return error_node();
27582 }
27583 else if (is_invalid_assignment_op(operation,branch))
27584 {
27585 return error_node();
27586 }
27587 else if (is_invalid_break_continue_op(branch))
27588 {
27589 return error_node();
27590 }
27591 else if (details::e_assign == operation)
27592 {
27593 return synthesize_assignment_expression(operation, branch);
27594 }
27595 else if (details::e_swap == operation)
27596 {
27597 return synthesize_swap_expression(branch);
27598 }
27599 else if (is_assignment_operation(operation))
27600 {
27601 return synthesize_assignment_operation_expression(operation, branch);
27602 }
27603 else if (is_vector_eqineq_logic_operation(operation, branch))
27604 {
27605 return synthesize_veceqineqlogic_operation_expression(operation, branch);
27606 }
27607 else if (is_vector_arithmetic_operation(operation, branch))
27608 {
27609 return synthesize_vecarithmetic_operation_expression(operation, branch);
27610 }
27611 else if (is_shortcircuit_expression(operation))
27612 {
27613 return synthesize_shortcircuit_expression(operation, branch);
27614 }
27615 else if (is_string_operation(operation, branch))
27616 {
27617 return synthesize_string_expression(operation, branch);
27618 }
27619 else if (is_null_present(branch))
27620 {
27621 return synthesize_null_expression(operation, branch);
27622 }
27623 #ifndef exprtk_disable_cardinal_pow_optimisation
27624 else if (is_constpow_operation(operation, branch))
27625 {
27626 return cardinal_pow_optimisation(branch);
27627 }
27628 #endif
27629
27630 expression_node_ptr result = error_node();
27631
27632 #ifndef exprtk_disable_enhanced_features
27633 if (synthesize_expression(operation, branch, result))
27634 {
27635 return result;
27636 }
27637 else
27638 #endif
27639
27640 {
27641 /*
27642 Possible reductions:
27643 1. c o cob -> cob
27644 2. cob o c -> cob
27645 3. c o boc -> boc
27646 4. boc o c -> boc
27647 */
27648 result = error_node();
27649
27650 if (cocob_optimisable(operation, branch))
27651 {
27652 result = synthesize_cocob_expression::process((*this), operation, branch);
27653 }
27654 else if (coboc_optimisable(operation, branch) && (0 == result))
27655 {
27656 result = synthesize_coboc_expression::process((*this), operation, branch);
27657 }
27658
27659 if (result)
27660 return result;
27661 }
27662
27663 if (uvouv_optimisable(operation, branch))
27664 {
27665 return synthesize_uvouv_expression(operation, branch);
27666 }
27667 else if (vob_optimisable(operation, branch))
27668 {
27669 return synthesize_vob_expression::process((*this), operation, branch);
27670 }
27671 else if (bov_optimisable(operation, branch))
27672 {
27673 return synthesize_bov_expression::process((*this), operation, branch);
27674 }
27675 else if (cob_optimisable(operation, branch))
27676 {
27677 return synthesize_cob_expression::process((*this), operation, branch);
27678 }
27679 else if (boc_optimisable(operation, branch))
27680 {
27681 return synthesize_boc_expression::process((*this), operation, branch);
27682 }
27683 #ifndef exprtk_disable_enhanced_features
27684 else if (cov_optimisable(operation, branch))
27685 {
27686 return synthesize_cov_expression::process((*this), operation, branch);
27687 }
27688 #endif
27689 else if (binext_optimisable(operation, branch))
27690 {
27691 return synthesize_binary_ext_expression::process((*this), operation, branch);
27692 }
27693 else
27694 return synthesize_expression<binary_node_t,2>(operation, branch);
27695 }
27696
27697 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
27698 {
27699 if (
27700 (0 == branch[0]) ||
27701 (0 == branch[1]) ||
27702 (0 == branch[2])
27703 )
27704 {
27705 details::free_all_nodes(*node_allocator_,branch);
27706
27707 return error_node();
27708 }
27709 else if (is_invalid_string_op(operation, branch))
27710 {
27711 return error_node();
27712 }
27713 else if (is_string_operation(operation, branch))
27714 {
27715 return synthesize_string_expression(operation, branch);
27716 }
27717 else
27718 return synthesize_expression<trinary_node_t,3>(operation, branch);
27719 }
27720
27721 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
27722 {
27723 return synthesize_expression<quaternary_node_t,4>(operation,branch);
27724 }
27725
27726 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
27727 {
27728 expression_node_ptr branch[1] = { b0 };
27729 return (*this)(operation,branch);
27730 }
27731
27732 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
27733 {
27734 expression_node_ptr result = error_node();
27735
27736 if ((0 != b0) && (0 != b1))
27737 {
27738 expression_node_ptr branch[2] = { b0, b1 };
27739 result = expression_generator<Type>::operator()(operation, branch);
27740 b0 = branch[0];
27741 b1 = branch[1];
27742 }
27743
27744 return result;
27745 }
27746
27747 inline expression_node_ptr conditional(expression_node_ptr condition,
27748 expression_node_ptr consequent,
27749 expression_node_ptr alternative) const
27750 {
27751 if ((0 == condition) || (0 == consequent))
27752 {
27753 free_node(*node_allocator_, condition);
27754 free_node(*node_allocator_, consequent);
27755 free_node(*node_allocator_, alternative);
27756
27757 return error_node();
27758 }
27759 // Can the condition be immediately evaluated? if so optimise.
27760 else if (details::is_constant_node(condition))
27761 {
27762 // True branch
27763 if (details::is_true(condition))
27764 {
27765 free_node(*node_allocator_, condition);
27766 free_node(*node_allocator_, alternative);
27767
27768 return consequent;
27769 }
27770 // False branch
27771 else
27772 {
27773 free_node(*node_allocator_, condition);
27774 free_node(*node_allocator_, consequent);
27775
27776 if (alternative)
27777 return alternative;
27778 else
27779 return node_allocator_->allocate<details::null_node<T> >();
27780 }
27781 }
27782 else if ((0 != consequent) && (0 != alternative))
27783 {
27784 return node_allocator_->
27785 allocate<conditional_node_t>(condition, consequent, alternative);
27786 }
27787 else
27788 return node_allocator_->
27789 allocate<cons_conditional_node_t>(condition, consequent);
27790 }
27791
27792 #ifndef exprtk_disable_string_capabilities
27793 inline expression_node_ptr conditional_string(expression_node_ptr condition,
27794 expression_node_ptr consequent,
27795 expression_node_ptr alternative) const
27796 {
27797 if ((0 == condition) || (0 == consequent))
27798 {
27799 free_node(*node_allocator_, condition);
27800 free_node(*node_allocator_, consequent);
27801 free_node(*node_allocator_, alternative);
27802
27803 return error_node();
27804 }
27805 // Can the condition be immediately evaluated? if so optimise.
27806 else if (details::is_constant_node(condition))
27807 {
27808 // True branch
27809 if (details::is_true(condition))
27810 {
27811 free_node(*node_allocator_, condition);
27812 free_node(*node_allocator_, alternative);
27813
27814 return consequent;
27815 }
27816 // False branch
27817 else
27818 {
27819 free_node(*node_allocator_, condition);
27820 free_node(*node_allocator_, consequent);
27821
27822 if (alternative)
27823 return alternative;
27824 else
27825 return node_allocator_->
27826 allocate_c<details::string_literal_node<Type> >("");
27827 }
27828 }
27829 else if ((0 != consequent) && (0 != alternative))
27830 return node_allocator_->
27831 allocate<conditional_string_node_t>(condition, consequent, alternative);
27832 else
27833 return error_node();
27834 }
27835 #else
27836 inline expression_node_ptr conditional_string(expression_node_ptr,
27837 expression_node_ptr,
27838 expression_node_ptr) const
27839 {
27840 return error_node();
27841 }
27842 #endif
27843
27844 inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
27845 {
27846 if (
27847 parser_->loop_runtime_check_ &&
27848 (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
27849 )
27850 {
27851 return parser_->loop_runtime_check_;
27852 }
27853
27854 return loop_runtime_check_ptr(0);
27855 }
27856
27857 inline expression_node_ptr while_loop(expression_node_ptr& condition,
27858 expression_node_ptr& branch,
27859 const bool brkcont = false) const
27860 {
27861 if (!brkcont && details::is_constant_node(condition))
27862 {
27863 expression_node_ptr result = error_node();
27864 if (details::is_true(condition))
27865 // Infinite loops are not allowed.
27866 result = error_node();
27867 else
27868 result = node_allocator_->allocate<details::null_node<Type> >();
27869
27870 free_node(*node_allocator_, condition);
27871 free_node(*node_allocator_, branch);
27872
27873 return result;
27874 }
27875 else if (details::is_null_node(condition))
27876 {
27877 free_node(*node_allocator_,condition);
27878
27879 return branch;
27880 }
27881 else if (!brkcont)
27882 return node_allocator_->allocate<while_loop_node_t>
27883 (
27884 condition,
27885 branch,
27886 get_loop_runtime_check(loop_runtime_check::e_while_loop)
27887 );
27888 #ifndef exprtk_disable_break_continue
27889 else
27890 return node_allocator_->allocate<while_loop_bc_node_t>
27891 (
27892 condition,
27893 branch,
27894 get_loop_runtime_check(loop_runtime_check::e_while_loop)
27895 );
27896 #else
27897 return error_node();
27898 #endif
27899 }
27900
27901 inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
27902 expression_node_ptr& branch,
27903 const bool brkcont = false) const
27904 {
27905 if (!brkcont && details::is_constant_node(condition))
27906 {
27907 if (
27908 details::is_true(condition) &&
27910 )
27911 {
27912 free_node(*node_allocator_,condition);
27913
27914 return branch;
27915 }
27916
27917 free_node(*node_allocator_, condition);
27918 free_node(*node_allocator_, branch);
27919
27920 return error_node();
27921 }
27922 else if (details::is_null_node(condition))
27923 {
27924 free_node(*node_allocator_,condition);
27925
27926 return branch;
27927 }
27928 else if (!brkcont)
27929 return node_allocator_->allocate<repeat_until_loop_node_t>
27930 (
27931 condition,
27932 branch,
27933 get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
27934 );
27935 #ifndef exprtk_disable_break_continue
27936 else
27937 return node_allocator_->allocate<repeat_until_loop_bc_node_t>
27938 (
27939 condition,
27940 branch,
27941 get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
27942 );
27943 #else
27944 return error_node();
27945 #endif
27946 }
27947
27948 inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
27949 expression_node_ptr& condition,
27950 expression_node_ptr& incrementor,
27951 expression_node_ptr& loop_body,
27952 bool brkcont = false) const
27953 {
27954 if (!brkcont && details::is_constant_node(condition))
27955 {
27956 expression_node_ptr result = error_node();
27957
27958 if (details::is_true(condition))
27959 // Infinite loops are not allowed.
27960 result = error_node();
27961 else
27962 result = node_allocator_->allocate<details::null_node<Type> >();
27963
27964 free_node(*node_allocator_, initialiser);
27965 free_node(*node_allocator_, condition);
27966 free_node(*node_allocator_, incrementor);
27967 free_node(*node_allocator_, loop_body);
27968
27969 return result;
27970 }
27971 else if (details::is_null_node(condition) || (0 == condition))
27972 {
27973 free_node(*node_allocator_, initialiser);
27974 free_node(*node_allocator_, condition);
27975 free_node(*node_allocator_, incrementor);
27976
27977 return loop_body;
27978 }
27979 else if (!brkcont)
27980 return node_allocator_->allocate<for_loop_node_t>
27981 (
27982 initialiser,
27983 condition,
27984 incrementor,
27985 loop_body,
27986 get_loop_runtime_check(loop_runtime_check::e_for_loop)
27987 );
27988
27989 #ifndef exprtk_disable_break_continue
27990 else
27991 return node_allocator_->allocate<for_loop_bc_node_t>
27992 (
27993 initialiser,
27994 condition,
27995 incrementor,
27996 loop_body,
27997 get_loop_runtime_check(loop_runtime_check::e_for_loop)
27998 );
27999 #else
28000 return error_node();
28001 #endif
28002 }
28003
28004 template <typename Allocator,
28005 template <typename, typename> class Sequence>
28006 inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
28007 {
28008 expression_node_ptr result = error_node();
28009
28010 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
28011 {
28012 expression_node_ptr condition = arg_list[(2 * i) ];
28013 expression_node_ptr consequent = arg_list[(2 * i) + 1];
28014
28015 if ((0 == result) && details::is_true(condition))
28016 {
28017 result = consequent;
28018 break;
28019 }
28020 }
28021
28022 if (0 == result)
28023 {
28024 result = arg_list.back();
28025 }
28026
28027 for (std::size_t i = 0; i < arg_list.size(); ++i)
28028 {
28029 expression_node_ptr current_expr = arg_list[i];
28030
28031 if (current_expr && (current_expr != result))
28032 {
28033 free_node(*node_allocator_,current_expr);
28034 }
28035 }
28036
28037 return result;
28038 }
28039
28040 template <typename Allocator,
28041 template <typename, typename> class Sequence>
28042 inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
28043 {
28044 expression_node_ptr result = error_node();
28045
28046 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
28047 {
28048 expression_node_ptr condition = arg_list[(2 * i) ];
28049 expression_node_ptr consequent = arg_list[(2 * i) + 1];
28050
28051 if (details::is_true(condition))
28052 {
28053 result = consequent;
28054 }
28055 }
28056
28057 if (0 == result)
28058 {
28059 T zero = T(0);
28060 result = node_allocator_->allocate<literal_node_t>(zero);
28061 }
28062
28063 for (std::size_t i = 0; i < arg_list.size(); ++i)
28064 {
28065 expression_node_ptr& current_expr = arg_list[i];
28066
28067 if (current_expr && (current_expr != result))
28068 {
28069 free_node(*node_allocator_,current_expr);
28070 }
28071 }
28072
28073 return result;
28074 }
28075
28077 {
28078 typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
28079
28080 #define case_stmt(N) \
28081 if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
28082
28084 {
28085 static inline T process(const arg_list_t& arg)
28086 {
28087 case_stmt(0)
28088
28089 return arg.back().first->value();
28090 }
28091 };
28092
28094 {
28095 static inline T process(const arg_list_t& arg)
28096 {
28097 case_stmt(0) case_stmt(1)
28098
28099 return arg.back().first->value();
28100 }
28101 };
28102
28104 {
28105 static inline T process(const arg_list_t& arg)
28106 {
28107 case_stmt(0) case_stmt(1)
28108 case_stmt(2)
28109
28110 return arg.back().first->value();
28111 }
28112 };
28113
28115 {
28116 static inline T process(const arg_list_t& arg)
28117 {
28118 case_stmt(0) case_stmt(1)
28119 case_stmt(2) case_stmt(3)
28120
28121 return arg.back().first->value();
28122 }
28123 };
28124
28126 {
28127 static inline T process(const arg_list_t& arg)
28128 {
28129 case_stmt(0) case_stmt(1)
28130 case_stmt(2) case_stmt(3)
28131 case_stmt(4)
28132
28133 return arg.back().first->value();
28134 }
28135 };
28136
28138 {
28139 static inline T process(const arg_list_t& arg)
28140 {
28141 case_stmt(0) case_stmt(1)
28142 case_stmt(2) case_stmt(3)
28143 case_stmt(4) case_stmt(5)
28144
28145 return arg.back().first->value();
28146 }
28147 };
28148
28150 {
28151 static inline T process(const arg_list_t& arg)
28152 {
28153 case_stmt(0) case_stmt(1)
28154 case_stmt(2) case_stmt(3)
28155 case_stmt(4) case_stmt(5)
28156 case_stmt(6)
28157
28158 return arg.back().first->value();
28159 }
28160 };
28161
28162 #undef case_stmt
28163 };
28164
28165 template <typename Allocator,
28166 template <typename, typename> class Sequence>
28167 inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
28168 {
28169 if (arg_list.empty())
28170 return error_node();
28171 else if (
28172 !all_nodes_valid(arg_list) ||
28173 (!default_statement_present && (arg_list.size() < 2))
28174 )
28175 {
28176 details::free_all_nodes(*node_allocator_,arg_list);
28177
28178 return error_node();
28179 }
28180 else if (is_constant_foldable(arg_list))
28181 return const_optimise_switch(arg_list);
28182
28183 switch ((arg_list.size() - 1) / 2)
28184 {
28185 #define case_stmt(N) \
28186 case N : \
28187 return node_allocator_-> \
28188 allocate<details::switch_n_node \
28189 <Type,typename switch_nodes::switch_##N> >(arg_list); \
28190
28191 case_stmt(1)
28192 case_stmt(2)
28193 case_stmt(3)
28194 case_stmt(4)
28195 case_stmt(5)
28196 case_stmt(6)
28197 case_stmt(7)
28198 #undef case_stmt
28199
28200 default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
28201 }
28202 }
28203
28204 template <typename Allocator,
28205 template <typename, typename> class Sequence>
28206 inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
28207 {
28208 if (!all_nodes_valid(arg_list))
28209 {
28210 details::free_all_nodes(*node_allocator_,arg_list);
28211
28212 return error_node();
28213 }
28214 else if (is_constant_foldable(arg_list))
28215 return const_optimise_mswitch(arg_list);
28216 else
28217 return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
28218 }
28219
28220 #define unary_opr_switch_statements \
28221 case_stmt(details:: e_abs, details:: abs_op) \
28222 case_stmt(details:: e_acos, details:: acos_op) \
28223 case_stmt(details::e_acosh, details::acosh_op) \
28224 case_stmt(details:: e_asin, details:: asin_op) \
28225 case_stmt(details::e_asinh, details::asinh_op) \
28226 case_stmt(details:: e_atan, details:: atan_op) \
28227 case_stmt(details::e_atanh, details::atanh_op) \
28228 case_stmt(details:: e_ceil, details:: ceil_op) \
28229 case_stmt(details:: e_cos, details:: cos_op) \
28230 case_stmt(details:: e_cosh, details:: cosh_op) \
28231 case_stmt(details:: e_exp, details:: exp_op) \
28232 case_stmt(details::e_expm1, details::expm1_op) \
28233 case_stmt(details::e_floor, details::floor_op) \
28234 case_stmt(details:: e_log, details:: log_op) \
28235 case_stmt(details::e_log10, details::log10_op) \
28236 case_stmt(details:: e_log2, details:: log2_op) \
28237 case_stmt(details::e_log1p, details::log1p_op) \
28238 case_stmt(details:: e_neg, details:: neg_op) \
28239 case_stmt(details:: e_pos, details:: pos_op) \
28240 case_stmt(details::e_round, details::round_op) \
28241 case_stmt(details:: e_sin, details:: sin_op) \
28242 case_stmt(details:: e_sinc, details:: sinc_op) \
28243 case_stmt(details:: e_sinh, details:: sinh_op) \
28244 case_stmt(details:: e_sqrt, details:: sqrt_op) \
28245 case_stmt(details:: e_tan, details:: tan_op) \
28246 case_stmt(details:: e_tanh, details:: tanh_op) \
28247 case_stmt(details:: e_cot, details:: cot_op) \
28248 case_stmt(details:: e_sec, details:: sec_op) \
28249 case_stmt(details:: e_csc, details:: csc_op) \
28250 case_stmt(details:: e_r2d, details:: r2d_op) \
28251 case_stmt(details:: e_d2r, details:: d2r_op) \
28252 case_stmt(details:: e_d2g, details:: d2g_op) \
28253 case_stmt(details:: e_g2d, details:: g2d_op) \
28254 case_stmt(details:: e_notl, details:: notl_op) \
28255 case_stmt(details:: e_sgn, details:: sgn_op) \
28256 case_stmt(details:: e_erf, details:: erf_op) \
28257 case_stmt(details:: e_erfc, details:: erfc_op) \
28258 case_stmt(details:: e_ncdf, details:: ncdf_op) \
28259 case_stmt(details:: e_frac, details:: frac_op) \
28260 case_stmt(details::e_trunc, details::trunc_op) \
28261
28262 inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
28263 expression_node_ptr (&branch)[1])
28264 {
28265 T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
28266
28267 switch (operation)
28268 {
28269 #define case_stmt(op0,op1) \
28270 case op0 : return node_allocator_-> \
28271 allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
28272
28274 #undef case_stmt
28275 default : return error_node();
28276 }
28277 }
28278
28279 inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
28280 expression_node_ptr (&branch)[1])
28281 {
28282 switch (operation)
28283 {
28284 #define case_stmt(op0,op1) \
28285 case op0 : return node_allocator_-> \
28286 allocate<typename details::unary_vector_node<Type,op1<Type> > > \
28287 (operation, branch[0]); \
28288
28290 #undef case_stmt
28291 default : return error_node();
28292 }
28293 }
28294
28295 inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
28296 expression_node_ptr (&branch)[1])
28297 {
28298 switch (operation)
28299 {
28300 #define case_stmt(op0,op1) \
28301 case op0 : return node_allocator_-> \
28302 allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
28303
28305 #undef case_stmt
28306 default : return error_node();
28307 }
28308 }
28309
28310 inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
28311 expression_node_ptr (&branch)[3])
28312 {
28313 expression_node_ptr temp_node = error_node();
28314
28315 switch (operation)
28316 {
28317 #define case_stmt(op) \
28318 case details::e_sf##op : temp_node = node_allocator_-> \
28319 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
28320 (operation, branch); \
28321 break; \
28322
28323 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28324 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28325 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28326 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28327 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28328 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28329 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28330 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28331 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28332 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28333 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28334 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28335 #undef case_stmt
28336 default : return error_node();
28337 }
28338
28339 const T v = temp_node->value();
28340
28341 details::free_node(*node_allocator_,temp_node);
28342
28343 return node_allocator_->allocate<literal_node_t>(v);
28344 }
28345
28346 inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
28347 {
28348 typedef details::variable_node<Type>* variable_ptr;
28349
28350 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
28351 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
28352 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
28353
28354 switch (operation)
28355 {
28356 #define case_stmt(op) \
28357 case details::e_sf##op : return node_allocator_-> \
28358 allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
28359 (v0, v1, v2); \
28360
28361 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28362 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28363 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28364 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28365 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28366 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28367 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28368 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28369 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28370 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28371 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28372 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28373 #undef case_stmt
28374 default : return error_node();
28375 }
28376 }
28377
28378 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
28379 {
28380 if (!all_nodes_valid(branch))
28381 return error_node();
28382 else if (is_constant_foldable(branch))
28383 return const_optimise_sf3(operation,branch);
28384 else if (all_nodes_variables(branch))
28385 return varnode_optimise_sf3(operation,branch);
28386 else
28387 {
28388 switch (operation)
28389 {
28390 #define case_stmt(op) \
28391 case details::e_sf##op : return node_allocator_-> \
28392 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
28393 (operation, branch); \
28394
28395 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28396 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28397 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28398 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28399 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28400 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28401 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28402 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28403 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28404 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28405 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28406 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28407 #undef case_stmt
28408 default : return error_node();
28409 }
28410 }
28411 }
28412
28413 inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28414 {
28415 expression_node_ptr temp_node = error_node();
28416
28417 switch (operation)
28418 {
28419 #define case_stmt(op) \
28420 case details::e_sf##op : temp_node = node_allocator_-> \
28421 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
28422 (operation, branch); \
28423 break; \
28424
28425 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28426 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28427 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28428 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28429 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28430 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28431 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28432 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28433 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28434 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28435 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28436 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28437 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28438 #undef case_stmt
28439 default : return error_node();
28440 }
28441
28442 const T v = temp_node->value();
28443
28444 details::free_node(*node_allocator_,temp_node);
28445
28446 return node_allocator_->allocate<literal_node_t>(v);
28447 }
28448
28449 inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28450 {
28451 typedef details::variable_node<Type>* variable_ptr;
28452
28453 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
28454 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
28455 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
28456 const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
28457
28458 switch (operation)
28459 {
28460 #define case_stmt(op) \
28461 case details::e_sf##op : return node_allocator_-> \
28462 allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
28463 (v0, v1, v2, v3); \
28464
28465 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28466 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28467 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28468 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28469 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28470 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28471 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28472 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28473 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28474 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28475 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28476 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28477 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28478 #undef case_stmt
28479 default : return error_node();
28480 }
28481 }
28482
28483 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28484 {
28485 if (!all_nodes_valid(branch))
28486 return error_node();
28487 else if (is_constant_foldable(branch))
28488 return const_optimise_sf4(operation,branch);
28489 else if (all_nodes_variables(branch))
28490 return varnode_optimise_sf4(operation,branch);
28491 switch (operation)
28492 {
28493 #define case_stmt(op) \
28494 case details::e_sf##op : return node_allocator_-> \
28495 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
28496 (operation, branch); \
28497
28498 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28499 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28500 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28501 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28502 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28503 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28504 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28505 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28506 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28507 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28508 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28509 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28510 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28511 #undef case_stmt
28512 default : return error_node();
28513 }
28514 }
28515
28516 template <typename Allocator,
28517 template <typename, typename> class Sequence>
28518 inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28519 {
28520 expression_node_ptr temp_node = error_node();
28521
28522 switch (operation)
28523 {
28524 #define case_stmt(op0,op1) \
28525 case op0 : temp_node = node_allocator_-> \
28526 allocate<details::vararg_node<Type,op1<Type> > > \
28527 (arg_list); \
28528 break; \
28529
28530 case_stmt(details::e_sum , details::vararg_add_op )
28531 case_stmt(details::e_prod , details::vararg_mul_op )
28532 case_stmt(details::e_avg , details::vararg_avg_op )
28533 case_stmt(details::e_min , details::vararg_min_op )
28534 case_stmt(details::e_max , details::vararg_max_op )
28535 case_stmt(details::e_mand , details::vararg_mand_op )
28536 case_stmt(details::e_mor , details::vararg_mor_op )
28537 case_stmt(details::e_multi , details::vararg_multi_op)
28538 #undef case_stmt
28539 default : return error_node();
28540 }
28541
28542 const T v = temp_node->value();
28543
28544 details::free_node(*node_allocator_,temp_node);
28545
28546 return node_allocator_->allocate<literal_node_t>(v);
28547 }
28548
28549 inline bool special_one_parameter_vararg(const details::operator_type& operation) const
28550 {
28551 return (
28552 (details::e_sum == operation) ||
28553 (details::e_prod == operation) ||
28554 (details::e_avg == operation) ||
28555 (details::e_min == operation) ||
28556 (details::e_max == operation)
28557 );
28558 }
28559
28560 template <typename Allocator,
28561 template <typename, typename> class Sequence>
28562 inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28563 {
28564 switch (operation)
28565 {
28566 #define case_stmt(op0,op1) \
28567 case op0 : return node_allocator_-> \
28568 allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
28569
28570 case_stmt(details::e_sum , details::vararg_add_op )
28571 case_stmt(details::e_prod , details::vararg_mul_op )
28572 case_stmt(details::e_avg , details::vararg_avg_op )
28573 case_stmt(details::e_min , details::vararg_min_op )
28574 case_stmt(details::e_max , details::vararg_max_op )
28575 case_stmt(details::e_mand , details::vararg_mand_op )
28576 case_stmt(details::e_mor , details::vararg_mor_op )
28577 case_stmt(details::e_multi , details::vararg_multi_op)
28578 #undef case_stmt
28579 default : return error_node();
28580 }
28581 }
28582
28583 template <typename Allocator,
28584 template <typename, typename> class Sequence>
28585 inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28586 {
28587 if (1 == arg_list.size())
28588 {
28589 switch (operation)
28590 {
28591 #define case_stmt(op0,op1) \
28592 case op0 : return node_allocator_-> \
28593 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
28594
28595 case_stmt(details::e_sum , details::vec_add_op)
28596 case_stmt(details::e_prod , details::vec_mul_op)
28597 case_stmt(details::e_avg , details::vec_avg_op)
28598 case_stmt(details::e_min , details::vec_min_op)
28599 case_stmt(details::e_max , details::vec_max_op)
28600 #undef case_stmt
28601 default : return error_node();
28602 }
28603 }
28604 else
28605 return error_node();
28606 }
28607
28608 template <typename Allocator,
28609 template <typename, typename> class Sequence>
28610 inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28611 {
28612 if (!all_nodes_valid(arg_list))
28613 {
28614 details::free_all_nodes(*node_allocator_,arg_list);
28615
28616 return error_node();
28617 }
28618 else if (is_constant_foldable(arg_list))
28619 return const_optimise_varargfunc(operation,arg_list);
28620 else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
28621 return vectorize_func(operation,arg_list);
28622 else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
28623 return arg_list[0];
28624 else if (all_nodes_variables(arg_list))
28625 return varnode_optimise_varargfunc(operation,arg_list);
28626
28627 #ifndef exprtk_disable_string_capabilities
28628 if (details::e_smulti == operation)
28629 {
28630 return node_allocator_->
28631 allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
28632 }
28633 else
28634 #endif
28635 {
28636 switch (operation)
28637 {
28638 #define case_stmt(op0,op1) \
28639 case op0 : return node_allocator_-> \
28640 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
28641
28642 case_stmt(details::e_sum , details::vararg_add_op )
28643 case_stmt(details::e_prod , details::vararg_mul_op )
28644 case_stmt(details::e_avg , details::vararg_avg_op )
28645 case_stmt(details::e_min , details::vararg_min_op )
28646 case_stmt(details::e_max , details::vararg_max_op )
28647 case_stmt(details::e_mand , details::vararg_mand_op )
28648 case_stmt(details::e_mor , details::vararg_mor_op )
28649 case_stmt(details::e_multi , details::vararg_multi_op)
28650 #undef case_stmt
28651 default : return error_node();
28652 }
28653 }
28654 }
28655
28656 template <std::size_t N>
28657 inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
28658 {
28659 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
28660 expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
28661
28662 if (0 == result)
28663 return error_node();
28664 else
28665 {
28666 // Can the function call be completely optimised?
28667 if (details::is_constant_node(result))
28668 return result;
28669 else if (!all_nodes_valid(b))
28670 {
28671 details::free_node(*node_allocator_,result);
28672 std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28673
28674 return error_node();
28675 }
28676 else if (N != f->param_count)
28677 {
28678 details::free_node(*node_allocator_,result);
28679 std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28680
28681 return error_node();
28682 }
28683
28684 function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result);
28685
28686 if (!func_node_ptr->init_branches(b))
28687 {
28688 details::free_node(*node_allocator_,result);
28689 std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28690
28691 return error_node();
28692 }
28693
28694 return result;
28695 }
28696 }
28697
28698 inline expression_node_ptr function(ifunction_t* f)
28699 {
28700 typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
28701 return node_allocator_->allocate<function_N_node_t>(f);
28702 }
28703
28704 inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
28705 std::vector<expression_node_ptr>& arg_list)
28706 {
28707 if (!all_nodes_valid(arg_list))
28708 {
28709 details::free_all_nodes(*node_allocator_,arg_list);
28710
28711 return error_node();
28712 }
28713
28714 typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
28715
28716 expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
28717
28718 if (
28719 !arg_list.empty() &&
28720 !vaf->has_side_effects() &&
28721 is_constant_foldable(arg_list)
28722 )
28723 {
28724 const Type v = result->value();
28725 details::free_node(*node_allocator_,result);
28726 result = node_allocator_->allocate<literal_node_t>(v);
28727 }
28728
28729 parser_->state_.activate_side_effect("vararg_function_call()");
28730
28731 return result;
28732 }
28733
28734 inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
28735 std::vector<expression_node_ptr>& arg_list,
28736 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
28737 {
28738 if (!all_nodes_valid(arg_list))
28739 {
28740 details::free_all_nodes(*node_allocator_,arg_list);
28741 return error_node();
28742 }
28743
28744 typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1;
28745 typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
28746
28747 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
28748
28749 expression_node_ptr result = error_node();
28750
28751 if (no_psi == param_seq_index)
28752 result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
28753 else
28754 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
28755
28756 alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
28757
28758 if (
28759 !arg_list.empty() &&
28760 !gf->has_side_effects() &&
28761 parser_->state_.type_check_enabled &&
28762 is_constant_foldable(arg_list)
28763 )
28764 {
28765 genfunc_node_ptr->init_branches();
28766
28767 const Type v = result->value();
28768
28769 details::free_node(*node_allocator_,result);
28770
28771 return node_allocator_->allocate<literal_node_t>(v);
28772 }
28773 else if (genfunc_node_ptr->init_branches())
28774 {
28775 parser_->state_.activate_side_effect("generic_function_call()");
28776
28777 return result;
28778 }
28779 else
28780 {
28781 details::free_node(*node_allocator_, result);
28782 details::free_all_nodes(*node_allocator_, arg_list);
28783
28784 return error_node();
28785 }
28786 }
28787
28788 #ifndef exprtk_disable_string_capabilities
28789 inline expression_node_ptr string_function_call(igeneric_function_t* gf,
28790 std::vector<expression_node_ptr>& arg_list,
28791 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
28792 {
28793 if (!all_nodes_valid(arg_list))
28794 {
28795 details::free_all_nodes(*node_allocator_,arg_list);
28796 return error_node();
28797 }
28798
28799 typedef details::string_function_node <Type,igeneric_function_t> alloc_type1;
28800 typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
28801
28802 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
28803
28804 expression_node_ptr result = error_node();
28805
28806 if (no_psi == param_seq_index)
28807 result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
28808 else
28809 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
28810
28811 alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
28812
28813 if (
28814 !arg_list.empty() &&
28815 !gf->has_side_effects() &&
28816 is_constant_foldable(arg_list)
28817 )
28818 {
28819 strfunc_node_ptr->init_branches();
28820
28821 const Type v = result->value();
28822
28823 details::free_node(*node_allocator_,result);
28824
28825 return node_allocator_->allocate<literal_node_t>(v);
28826 }
28827 else if (strfunc_node_ptr->init_branches())
28828 {
28829 parser_->state_.activate_side_effect("string_function_call()");
28830
28831 return result;
28832 }
28833 else
28834 {
28835 details::free_node (*node_allocator_,result );
28836 details::free_all_nodes(*node_allocator_,arg_list);
28837
28838 return error_node();
28839 }
28840 }
28841 #endif
28842
28843 #ifndef exprtk_disable_return_statement
28844 inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
28845 {
28846 if (!all_nodes_valid(arg_list))
28847 {
28848 details::free_all_nodes(*node_allocator_,arg_list);
28849 return error_node();
28850 }
28851
28852 typedef details::return_node<Type> alloc_type;
28853
28854 expression_node_ptr result = node_allocator_->
28855 allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
28856
28857 alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
28858
28859 if (return_node_ptr->init_branches())
28860 {
28861 parser_->state_.activate_side_effect("return_call()");
28862
28863 return result;
28864 }
28865 else
28866 {
28867 details::free_node (*node_allocator_,result );
28868 details::free_all_nodes(*node_allocator_,arg_list);
28869
28870 return error_node();
28871 }
28872 }
28873
28874 inline expression_node_ptr return_envelope(expression_node_ptr body,
28875 results_context_t* rc,
28876 bool*& return_invoked)
28877 {
28878 typedef details::return_envelope_node<Type> alloc_type;
28879
28880 expression_node_ptr result = node_allocator_->
28881 allocate_cr<alloc_type>(body,(*rc));
28882
28883 return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
28884
28885 return result;
28886 }
28887 #else
28888 inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
28889 {
28890 return error_node();
28891 }
28892
28893 inline expression_node_ptr return_envelope(expression_node_ptr,
28894 results_context_t*,
28895 bool*&)
28896 {
28897 return error_node();
28898 }
28899 #endif
28900
28901 inline expression_node_ptr vector_element(const std::string& symbol,
28902 vector_holder_ptr vector_base,
28903 expression_node_ptr index)
28904 {
28905 expression_node_ptr result = error_node();
28906
28908 {
28909 std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
28910
28911 details::free_node(*node_allocator_,index);
28912
28913 if (vector_base->rebaseable())
28914 {
28915 return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
28916 }
28917
28918 const scope_element& se = parser_->sem_.get_element(symbol,i);
28919
28920 if (se.index == i)
28921 {
28922 result = se.var_node;
28923 }
28924 else
28925 {
28926 scope_element nse;
28927 nse.name = symbol;
28928 nse.active = true;
28929 nse.ref_count = 1;
28930 nse.type = scope_element::e_vecelem;
28931 nse.index = i;
28932 nse.depth = parser_->state_.scope_depth;
28933 nse.data = 0;
28934 nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
28935
28936 if (!parser_->sem_.add_element(nse))
28937 {
28938 parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
28939
28940 parser_->sem_.free_element(nse);
28941
28942 result = error_node();
28943 }
28944
28945 exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
28946
28947 parser_->state_.activate_side_effect("vector_element()");
28948
28949 result = nse.var_node;
28950 }
28951 }
28952 else if (vector_base->rebaseable())
28953 result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
28954 else
28955 result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
28956
28957 return result;
28958 }
28959
28960 private:
28961
28962 template <std::size_t N, typename NodePtr>
28963 inline bool is_constant_foldable(NodePtr (&b)[N]) const
28964 {
28965 for (std::size_t i = 0; i < N; ++i)
28966 {
28967 if (0 == b[i])
28968 return false;
28969 else if (!details::is_constant_node(b[i]))
28970 return false;
28971 }
28972
28973 return true;
28974 }
28975
28976 template <typename NodePtr,
28977 typename Allocator,
28978 template <typename, typename> class Sequence>
28979 inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
28980 {
28981 for (std::size_t i = 0; i < b.size(); ++i)
28982 {
28983 if (0 == b[i])
28984 return false;
28985 else if (!details::is_constant_node(b[i]))
28986 return false;
28987 }
28988
28989 return true;
28990 }
28991
28992 void lodge_assignment(symbol_type cst, expression_node_ptr node)
28993 {
28994 parser_->state_.activate_side_effect("lodge_assignment()");
28995
28996 if (!parser_->dec_.collect_assignments())
28997 return;
28998
28999 std::string symbol_name;
29000
29001 switch (cst)
29002 {
29003 case e_st_variable : symbol_name = parser_->symtab_store_
29004 .get_variable_name(node);
29005 break;
29006
29007 #ifndef exprtk_disable_string_capabilities
29008 case e_st_string : symbol_name = parser_->symtab_store_
29009 .get_stringvar_name(node);
29010 break;
29011 #endif
29012
29013 case e_st_vector : {
29014 typedef details::vector_holder<T> vector_holder_t;
29015
29016 vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
29017
29018 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
29019 }
29020 break;
29021
29022 case e_st_vecelem : {
29023 typedef details::vector_holder<T> vector_holder_t;
29024
29025 vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
29026
29027 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
29028
29029 cst = e_st_vector;
29030 }
29031 break;
29032
29033 default : return;
29034 }
29035
29036 if (!symbol_name.empty())
29037 {
29038 parser_->dec_.add_assignment(symbol_name,cst);
29039 }
29040 }
29041
29042 inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
29043 {
29044 if (details::is_variable_node(branch[0]))
29045 {
29046 lodge_assignment(e_st_variable,branch[0]);
29047
29048 return synthesize_expression<assignment_node_t,2>(operation,branch);
29049 }
29050 else if (details::is_vector_elem_node(branch[0]))
29051 {
29052 lodge_assignment(e_st_vecelem,branch[0]);
29053
29054 return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
29055 }
29056 else if (details::is_rebasevector_elem_node(branch[0]))
29057 {
29058 lodge_assignment(e_st_vecelem,branch[0]);
29059
29060 return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
29061 }
29062 else if (details::is_rebasevector_celem_node(branch[0]))
29063 {
29064 lodge_assignment(e_st_vecelem,branch[0]);
29065
29066 return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
29067 }
29068 #ifndef exprtk_disable_string_capabilities
29069 else if (details::is_string_node(branch[0]))
29070 {
29071 lodge_assignment(e_st_string,branch[0]);
29072
29073 return synthesize_expression<assignment_string_node_t,2>(operation, branch);
29074 }
29075 else if (details::is_string_range_node(branch[0]))
29076 {
29077 lodge_assignment(e_st_string,branch[0]);
29078
29079 return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
29080 }
29081 #endif
29082 else if (details::is_vector_node(branch[0]))
29083 {
29084 lodge_assignment(e_st_vector,branch[0]);
29085
29086 if (details::is_ivector_node(branch[1]))
29087 return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
29088 else
29089 return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
29090 }
29091 else
29092 {
29093 parser_->set_synthesis_error("Invalid assignment operation.[1]");
29094
29095 return error_node();
29096 }
29097 }
29098
29099 inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
29100 expression_node_ptr (&branch)[2])
29101 {
29102 if (details::is_variable_node(branch[0]))
29103 {
29104 lodge_assignment(e_st_variable,branch[0]);
29105
29106 switch (operation)
29107 {
29108 #define case_stmt(op0,op1) \
29109 case op0 : return node_allocator_-> \
29110 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
29111 (operation, branch[0], branch[1]); \
29112
29113 case_stmt(details::e_addass,details::add_op)
29114 case_stmt(details::e_subass,details::sub_op)
29115 case_stmt(details::e_mulass,details::mul_op)
29116 case_stmt(details::e_divass,details::div_op)
29117 case_stmt(details::e_modass,details::mod_op)
29118 #undef case_stmt
29119 default : return error_node();
29120 }
29121 }
29122 else if (details::is_vector_elem_node(branch[0]))
29123 {
29124 lodge_assignment(e_st_vecelem,branch[0]);
29125
29126 switch (operation)
29127 {
29128 #define case_stmt(op0,op1) \
29129 case op0 : return node_allocator_-> \
29130 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
29131 (operation, branch[0], branch[1]); \
29132
29133 case_stmt(details::e_addass,details::add_op)
29134 case_stmt(details::e_subass,details::sub_op)
29135 case_stmt(details::e_mulass,details::mul_op)
29136 case_stmt(details::e_divass,details::div_op)
29137 case_stmt(details::e_modass,details::mod_op)
29138 #undef case_stmt
29139 default : return error_node();
29140 }
29141 }
29142 else if (details::is_rebasevector_elem_node(branch[0]))
29143 {
29144 lodge_assignment(e_st_vecelem,branch[0]);
29145
29146 switch (operation)
29147 {
29148 #define case_stmt(op0,op1) \
29149 case op0 : return node_allocator_-> \
29150 template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
29151 (operation, branch[0], branch[1]); \
29152
29153 case_stmt(details::e_addass,details::add_op)
29154 case_stmt(details::e_subass,details::sub_op)
29155 case_stmt(details::e_mulass,details::mul_op)
29156 case_stmt(details::e_divass,details::div_op)
29157 case_stmt(details::e_modass,details::mod_op)
29158 #undef case_stmt
29159 default : return error_node();
29160 }
29161 }
29162 else if (details::is_rebasevector_celem_node(branch[0]))
29163 {
29164 lodge_assignment(e_st_vecelem,branch[0]);
29165
29166 switch (operation)
29167 {
29168 #define case_stmt(op0,op1) \
29169 case op0 : return node_allocator_-> \
29170 template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
29171 (operation, branch[0], branch[1]); \
29172
29173 case_stmt(details::e_addass,details::add_op)
29174 case_stmt(details::e_subass,details::sub_op)
29175 case_stmt(details::e_mulass,details::mul_op)
29176 case_stmt(details::e_divass,details::div_op)
29177 case_stmt(details::e_modass,details::mod_op)
29178 #undef case_stmt
29179 default : return error_node();
29180 }
29181 }
29182 else if (details::is_vector_node(branch[0]))
29183 {
29184 lodge_assignment(e_st_vector,branch[0]);
29185
29186 if (details::is_ivector_node(branch[1]))
29187 {
29188 switch (operation)
29189 {
29190 #define case_stmt(op0,op1) \
29191 case op0 : return node_allocator_-> \
29192 template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
29193 (operation, branch[0], branch[1]); \
29194
29195 case_stmt(details::e_addass,details::add_op)
29196 case_stmt(details::e_subass,details::sub_op)
29197 case_stmt(details::e_mulass,details::mul_op)
29198 case_stmt(details::e_divass,details::div_op)
29199 case_stmt(details::e_modass,details::mod_op)
29200 #undef case_stmt
29201 default : return error_node();
29202 }
29203 }
29204 else
29205 {
29206 switch (operation)
29207 {
29208 #define case_stmt(op0,op1) \
29209 case op0 : return node_allocator_-> \
29210 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
29211 (operation, branch[0], branch[1]); \
29212
29213 case_stmt(details::e_addass,details::add_op)
29214 case_stmt(details::e_subass,details::sub_op)
29215 case_stmt(details::e_mulass,details::mul_op)
29216 case_stmt(details::e_divass,details::div_op)
29217 case_stmt(details::e_modass,details::mod_op)
29218 #undef case_stmt
29219 default : return error_node();
29220 }
29221 }
29222 }
29223 #ifndef exprtk_disable_string_capabilities
29224 else if (
29225 (details::e_addass == operation) &&
29226 details::is_string_node(branch[0])
29227 )
29228 {
29229 typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
29230
29231 lodge_assignment(e_st_string,branch[0]);
29232
29233 return synthesize_expression<addass_t,2>(operation,branch);
29234 }
29235 #endif
29236 else
29237 {
29238 parser_->set_synthesis_error("Invalid assignment operation[2]");
29239
29240 return error_node();
29241 }
29242 }
29243
29244 inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
29245 expression_node_ptr (&branch)[2])
29246 {
29247 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
29248 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
29249
29250 #define batch_eqineq_logic_case \
29251 case_stmt(details:: e_lt, details:: lt_op) \
29252 case_stmt(details:: e_lte, details:: lte_op) \
29253 case_stmt(details:: e_gt, details:: gt_op) \
29254 case_stmt(details:: e_gte, details:: gte_op) \
29255 case_stmt(details:: e_eq, details:: eq_op) \
29256 case_stmt(details:: e_ne, details:: ne_op) \
29257 case_stmt(details::e_equal, details::equal_op) \
29258 case_stmt(details:: e_and, details:: and_op) \
29259 case_stmt(details:: e_nand, details:: nand_op) \
29260 case_stmt(details:: e_or, details:: or_op) \
29261 case_stmt(details:: e_nor, details:: nor_op) \
29262 case_stmt(details:: e_xor, details:: xor_op) \
29263 case_stmt(details:: e_xnor, details:: xnor_op) \
29264
29265 if (is_b0_ivec && is_b1_ivec)
29266 {
29267 switch (operation)
29268 {
29269 #define case_stmt(op0,op1) \
29270 case op0 : return node_allocator_-> \
29271 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
29272 (operation, branch[0], branch[1]); \
29273
29275 #undef case_stmt
29276 default : return error_node();
29277 }
29278 }
29279 else if (is_b0_ivec && !is_b1_ivec)
29280 {
29281 switch (operation)
29282 {
29283 #define case_stmt(op0,op1) \
29284 case op0 : return node_allocator_-> \
29285 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
29286 (operation, branch[0], branch[1]); \
29287
29289 #undef case_stmt
29290 default : return error_node();
29291 }
29292 }
29293 else if (!is_b0_ivec && is_b1_ivec)
29294 {
29295 switch (operation)
29296 {
29297 #define case_stmt(op0,op1) \
29298 case op0 : return node_allocator_-> \
29299 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
29300 (operation, branch[0], branch[1]); \
29301
29303 #undef case_stmt
29304 default : return error_node();
29305 }
29306 }
29307 else
29308 return error_node();
29309
29310 #undef batch_eqineq_logic_case
29311 }
29312
29313 inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
29314 expression_node_ptr (&branch)[2])
29315 {
29316 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
29317 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
29318
29319 #define vector_ops \
29320 case_stmt(details::e_add,details::add_op) \
29321 case_stmt(details::e_sub,details::sub_op) \
29322 case_stmt(details::e_mul,details::mul_op) \
29323 case_stmt(details::e_div,details::div_op) \
29324 case_stmt(details::e_mod,details::mod_op) \
29325
29326 if (is_b0_ivec && is_b1_ivec)
29327 {
29328 switch (operation)
29329 {
29330 #define case_stmt(op0,op1) \
29331 case op0 : return node_allocator_-> \
29332 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
29333 (operation, branch[0], branch[1]); \
29334
29336 case_stmt(details::e_pow,details:: pow_op)
29337 #undef case_stmt
29338 default : return error_node();
29339 }
29340 }
29341 else if (is_b0_ivec && !is_b1_ivec)
29342 {
29343 switch (operation)
29344 {
29345 #define case_stmt(op0,op1) \
29346 case op0 : return node_allocator_-> \
29347 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
29348 (operation, branch[0], branch[1]); \
29349
29351 case_stmt(details::e_pow,details:: pow_op)
29352 #undef case_stmt
29353 default : return error_node();
29354 }
29355 }
29356 else if (!is_b0_ivec && is_b1_ivec)
29357 {
29358 switch (operation)
29359 {
29360 #define case_stmt(op0,op1) \
29361 case op0 : return node_allocator_-> \
29362 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
29363 (operation, branch[0], branch[1]); \
29364
29366 #undef case_stmt
29367 default : return error_node();
29368 }
29369 }
29370 else
29371 return error_node();
29372
29373 #undef vector_ops
29374 }
29375
29376 inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
29377 {
29378 const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
29379 const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
29380
29381 const bool v0_is_ivec = details::is_ivector_node (branch[0]);
29382 const bool v1_is_ivec = details::is_ivector_node (branch[1]);
29383
29384 #ifndef exprtk_disable_string_capabilities
29385 const bool v0_is_str = details::is_generally_string_node(branch[0]);
29386 const bool v1_is_str = details::is_generally_string_node(branch[1]);
29387 #endif
29388
29389 expression_node_ptr result = error_node();
29390
29391 if (v0_is_ivar && v1_is_ivar)
29392 {
29393 typedef details::variable_node<T>* variable_node_ptr;
29394
29395 variable_node_ptr v0 = variable_node_ptr(0);
29396 variable_node_ptr v1 = variable_node_ptr(0);
29397
29398 if (
29399 (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
29400 (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
29401 )
29402 {
29403 result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
29404 }
29405 else
29406 result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
29407 }
29408 else if (v0_is_ivec && v1_is_ivec)
29409 {
29410 result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
29411 }
29412 #ifndef exprtk_disable_string_capabilities
29413 else if (v0_is_str && v1_is_str)
29414 {
29415 if (is_string_node(branch[0]) && is_string_node(branch[1]))
29416 result = node_allocator_->allocate<details::swap_string_node<T> >
29417 (branch[0], branch[1]);
29418 else
29419 result = node_allocator_->allocate<details::swap_genstrings_node<T> >
29420 (branch[0], branch[1]);
29421 }
29422 #endif
29423 else
29424 {
29425 parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
29426
29427 return error_node();
29428 }
29429
29430 parser_->state_.activate_side_effect("synthesize_swap_expression()");
29431
29432 return result;
29433 }
29434
29435 #ifndef exprtk_disable_sc_andor
29436 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
29437 {
29438 expression_node_ptr result = error_node();
29439
29440 if (details::is_constant_node(branch[0]))
29441 {
29442 if (
29443 (details::e_scand == operation) &&
29444 std::equal_to<T>()(T(0),branch[0]->value())
29445 )
29446 result = node_allocator_->allocate_c<literal_node_t>(T(0));
29447 else if (
29448 (details::e_scor == operation) &&
29449 std::not_equal_to<T>()(T(0),branch[0]->value())
29450 )
29451 result = node_allocator_->allocate_c<literal_node_t>(T(1));
29452 }
29453
29454 if (details::is_constant_node(branch[1]) && (0 == result))
29455 {
29456 if (
29457 (details::e_scand == operation) &&
29458 std::equal_to<T>()(T(0),branch[1]->value())
29459 )
29460 result = node_allocator_->allocate_c<literal_node_t>(T(0));
29461 else if (
29462 (details::e_scor == operation) &&
29463 std::not_equal_to<T>()(T(0),branch[1]->value())
29464 )
29465 result = node_allocator_->allocate_c<literal_node_t>(T(1));
29466 }
29467
29468 if (result)
29469 {
29470 free_node(*node_allocator_, branch[0]);
29471 free_node(*node_allocator_, branch[1]);
29472
29473 return result;
29474 }
29475 else if (details::e_scand == operation)
29476 {
29477 return synthesize_expression<scand_node_t,2>(operation, branch);
29478 }
29479 else if (details::e_scor == operation)
29480 {
29481 return synthesize_expression<scor_node_t,2>(operation, branch);
29482 }
29483 else
29484 return error_node();
29485 }
29486 #else
29487 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
29488 {
29489 return error_node();
29490 }
29491 #endif
29492
29493 #define basic_opr_switch_statements \
29494 case_stmt(details::e_add, details::add_op) \
29495 case_stmt(details::e_sub, details::sub_op) \
29496 case_stmt(details::e_mul, details::mul_op) \
29497 case_stmt(details::e_div, details::div_op) \
29498 case_stmt(details::e_mod, details::mod_op) \
29499 case_stmt(details::e_pow, details::pow_op) \
29500
29501 #define extended_opr_switch_statements \
29502 case_stmt(details:: e_lt, details:: lt_op) \
29503 case_stmt(details:: e_lte, details:: lte_op) \
29504 case_stmt(details:: e_gt, details:: gt_op) \
29505 case_stmt(details:: e_gte, details:: gte_op) \
29506 case_stmt(details:: e_eq, details:: eq_op) \
29507 case_stmt(details:: e_ne, details:: ne_op) \
29508 case_stmt(details:: e_and, details:: and_op) \
29509 case_stmt(details::e_nand, details::nand_op) \
29510 case_stmt(details:: e_or, details:: or_op) \
29511 case_stmt(details:: e_nor, details:: nor_op) \
29512 case_stmt(details:: e_xor, details:: xor_op) \
29513 case_stmt(details::e_xnor, details::xnor_op) \
29514
29515 #ifndef exprtk_disable_cardinal_pow_optimisation
29516 template <typename TType, template <typename, typename> class IPowNode>
29517 inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
29518 {
29519 switch (p)
29520 {
29521 #define case_stmt(cp) \
29522 case cp : return node_allocator_-> \
29523 allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
29524
29525 case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
29526 case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
29527 case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
29528 case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
29529 case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
29530 case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
29531 case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
29532 case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
29533 case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
29534 case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
29535 case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
29536 case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
29537 case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
29538 case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
29539 case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
29540 #undef case_stmt
29541 default : return error_node();
29542 }
29543 }
29544
29545 inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
29546 {
29547 const bool not_recipricol = (c >= T(0));
29548 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
29549
29550 if (0 == p)
29551 return node_allocator_->allocate_c<literal_node_t>(T(1));
29552 else if (std::equal_to<T>()(T(2),c))
29553 {
29554 return node_allocator_->
29555 template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
29556 }
29557 else
29558 {
29559 if (not_recipricol)
29560 return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
29561 else
29562 return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
29563 }
29564 }
29565
29566 inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
29567 {
29568 return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
29569 }
29570
29571 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
29572 {
29573 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29574 const bool not_recipricol = (c >= T(0));
29575 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
29576
29577 node_allocator_->free(branch[1]);
29578
29579 if (0 == p)
29580 {
29581 details::free_all_nodes(*node_allocator_, branch);
29582
29583 return node_allocator_->allocate_c<literal_node_t>(T(1));
29584 }
29585 else if (not_recipricol)
29586 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
29587 else
29588 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
29589 }
29590 #else
29591 inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
29592 {
29593 return error_node();
29594 }
29595
29596 inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
29597 {
29598 return false;
29599 }
29600
29601 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
29602 {
29603 return error_node();
29604 }
29605 #endif
29606
29607 struct synthesize_binary_ext_expression
29608 {
29609 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29610 const details::operator_type& operation,
29611 expression_node_ptr (&branch)[2])
29612 {
29613 const bool left_neg = is_neg_unary_node(branch[0]);
29614 const bool right_neg = is_neg_unary_node(branch[1]);
29615
29616 if (left_neg && right_neg)
29617 {
29618 if (
29619 (details::e_add == operation) ||
29620 (details::e_sub == operation) ||
29621 (details::e_mul == operation) ||
29622 (details::e_div == operation)
29623 )
29624 {
29625 if (
29626 !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
29627 !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
29628 )
29629 {
29630 details::free_all_nodes(*expr_gen.node_allocator_,branch);
29631
29632 return error_node();
29633 }
29634 }
29635
29636 switch (operation)
29637 {
29638 // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
29639 case details::e_add : return expr_gen(details::e_neg,
29640 expr_gen.node_allocator_->
29641 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29642 (branch[0],branch[1]));
29643
29644 // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
29645 case details::e_sub : return expr_gen.node_allocator_->
29646 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29647 (branch[1],branch[0]);
29648
29649 default : break;
29650 }
29651 }
29652 else if (left_neg && !right_neg)
29653 {
29654 if (
29655 (details::e_add == operation) ||
29656 (details::e_sub == operation) ||
29657 (details::e_mul == operation) ||
29658 (details::e_div == operation)
29659 )
29660 {
29661 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
29662 {
29663 details::free_all_nodes(*expr_gen.node_allocator_,branch);
29664
29665 return error_node();
29666 }
29667
29668 switch (operation)
29669 {
29670 // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
29671 case details::e_add : return expr_gen.node_allocator_->
29672 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29673 (branch[1], branch[0]);
29674
29675 // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
29676 case details::e_sub : return expr_gen(details::e_neg,
29677 expr_gen.node_allocator_->
29678 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29679 (branch[0], branch[1]));
29680
29681 // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
29682 case details::e_mul : return expr_gen(details::e_neg,
29683 expr_gen.node_allocator_->
29684 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
29685 (branch[0], branch[1]));
29686
29687 // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
29688 case details::e_div : return expr_gen(details::e_neg,
29689 expr_gen.node_allocator_->
29690 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
29691 (branch[0], branch[1]));
29692
29693 default : return error_node();
29694 }
29695 }
29696 }
29697 else if (!left_neg && right_neg)
29698 {
29699 if (
29700 (details::e_add == operation) ||
29701 (details::e_sub == operation) ||
29702 (details::e_mul == operation) ||
29703 (details::e_div == operation)
29704 )
29705 {
29706 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
29707 {
29708 details::free_all_nodes(*expr_gen.node_allocator_,branch);
29709
29710 return error_node();
29711 }
29712
29713 switch (operation)
29714 {
29715 // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
29716 case details::e_add : return expr_gen.node_allocator_->
29717 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29718 (branch[0], branch[1]);
29719
29720 // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
29721 case details::e_sub : return expr_gen.node_allocator_->
29722 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29723 (branch[0], branch[1]);
29724
29725 // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
29726 case details::e_mul : return expr_gen(details::e_neg,
29727 expr_gen.node_allocator_->
29728 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
29729 (branch[0], branch[1]));
29730
29731 // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
29732 case details::e_div : return expr_gen(details::e_neg,
29733 expr_gen.node_allocator_->
29734 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
29735 (branch[0], branch[1]));
29736
29737 default : return error_node();
29738 }
29739 }
29740 }
29741
29742 switch (operation)
29743 {
29744 #define case_stmt(op0,op1) \
29745 case op0 : return expr_gen.node_allocator_-> \
29746 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
29747 (branch[0], branch[1]); \
29748
29751 #undef case_stmt
29752 default : return error_node();
29753 }
29754 }
29755 };
29756
29757 struct synthesize_vob_expression
29758 {
29759 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29760 const details::operator_type& operation,
29761 expression_node_ptr (&branch)[2])
29762 {
29763 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29764
29765 #ifndef exprtk_disable_enhanced_features
29766 if (details::is_sf3ext_node(branch[1]))
29767 {
29768 expression_node_ptr result = error_node();
29769
29770 const bool synthesis_result =
29771 synthesize_sf4ext_expression::template compile_right<vtype>
29772 (expr_gen, v, operation, branch[1], result);
29773
29774 if (synthesis_result)
29775 {
29776 free_node(*expr_gen.node_allocator_,branch[1]);
29777 return result;
29778 }
29779 }
29780 #endif
29781
29782 if (
29783 (details::e_mul == operation) ||
29784 (details::e_div == operation)
29785 )
29786 {
29787 if (details::is_uv_node(branch[1]))
29788 {
29789 typedef details::uv_base_node<Type>* uvbn_ptr_t;
29790
29791 details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
29792
29793 if (details::e_neg == o)
29794 {
29795 const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
29796
29797 free_node(*expr_gen.node_allocator_,branch[1]);
29798
29799 switch (operation)
29800 {
29801 case details::e_mul : return expr_gen(details::e_neg,
29802 expr_gen.node_allocator_->
29803 template allocate_rr<typename details::
29804 vov_node<Type,details::mul_op<Type> > >(v,v1));
29805
29806 case details::e_div : return expr_gen(details::e_neg,
29807 expr_gen.node_allocator_->
29808 template allocate_rr<typename details::
29809 vov_node<Type,details::div_op<Type> > >(v,v1));
29810
29811 default : break;
29812 }
29813 }
29814 }
29815 }
29816
29817 switch (operation)
29818 {
29819 #define case_stmt(op0,op1) \
29820 case op0 : return expr_gen.node_allocator_-> \
29821 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
29822 (v, branch[1]); \
29823
29826 #undef case_stmt
29827 default : return error_node();
29828 }
29829 }
29830 };
29831
29832 struct synthesize_bov_expression
29833 {
29834 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29835 const details::operator_type& operation,
29836 expression_node_ptr (&branch)[2])
29837 {
29838 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29839
29840 #ifndef exprtk_disable_enhanced_features
29841 if (details::is_sf3ext_node(branch[0]))
29842 {
29843 expression_node_ptr result = error_node();
29844
29845 const bool synthesis_result =
29846 synthesize_sf4ext_expression::template compile_left<vtype>
29847 (expr_gen, v, operation, branch[0], result);
29848
29849 if (synthesis_result)
29850 {
29851 free_node(*expr_gen.node_allocator_, branch[0]);
29852
29853 return result;
29854 }
29855 }
29856 #endif
29857
29858 if (
29859 (details::e_add == operation) ||
29860 (details::e_sub == operation) ||
29861 (details::e_mul == operation) ||
29862 (details::e_div == operation)
29863 )
29864 {
29865 if (details::is_uv_node(branch[0]))
29866 {
29867 typedef details::uv_base_node<Type>* uvbn_ptr_t;
29868
29869 details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
29870
29871 if (details::e_neg == o)
29872 {
29873 const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
29874
29875 free_node(*expr_gen.node_allocator_,branch[0]);
29876
29877 switch (operation)
29878 {
29879 case details::e_add : return expr_gen.node_allocator_->
29880 template allocate_rr<typename details::
29881 vov_node<Type,details::sub_op<Type> > >(v,v0);
29882
29883 case details::e_sub : return expr_gen(details::e_neg,
29884 expr_gen.node_allocator_->
29885 template allocate_rr<typename details::
29886 vov_node<Type,details::add_op<Type> > >(v0,v));
29887
29888 case details::e_mul : return expr_gen(details::e_neg,
29889 expr_gen.node_allocator_->
29890 template allocate_rr<typename details::
29891 vov_node<Type,details::mul_op<Type> > >(v0,v));
29892
29893 case details::e_div : return expr_gen(details::e_neg,
29894 expr_gen.node_allocator_->
29895 template allocate_rr<typename details::
29896 vov_node<Type,details::div_op<Type> > >(v0,v));
29897 default : break;
29898 }
29899 }
29900 }
29901 }
29902
29903 switch (operation)
29904 {
29905 #define case_stmt(op0,op1) \
29906 case op0 : return expr_gen.node_allocator_-> \
29907 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
29908 (branch[0], v); \
29909
29912 #undef case_stmt
29913 default : return error_node();
29914 }
29915 }
29916 };
29917
29918 struct synthesize_cob_expression
29919 {
29920 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29921 const details::operator_type& operation,
29922 expression_node_ptr (&branch)[2])
29923 {
29924 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29925
29926 free_node(*expr_gen.node_allocator_,branch[0]);
29927
29928 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29929 {
29930 free_node(*expr_gen.node_allocator_,branch[1]);
29931
29932 return expr_gen(T(0));
29933 }
29934 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29935 {
29936 free_node(*expr_gen.node_allocator_, branch[1]);
29937
29938 return expr_gen(T(0));
29939 }
29940 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29941 return branch[1];
29942 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29943 return branch[1];
29944
29945 if (details::is_cob_node(branch[1]))
29946 {
29947 // Simplify expressions of the form:
29948 // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
29949 // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
29950 if (
29951 (operation == details::e_mul) ||
29952 (operation == details::e_add)
29953 )
29954 {
29955 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29956
29957 if (operation == cobnode->operation())
29958 {
29959 switch (operation)
29960 {
29961 case details::e_add : cobnode->set_c(c + cobnode->c()); break;
29962 case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
29963 default : return error_node();
29964 }
29965
29966 return cobnode;
29967 }
29968 }
29969
29970 if (operation == details::e_mul)
29971 {
29972 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29973 details::operator_type cob_opr = cobnode->operation();
29974
29975 if (
29976 (details::e_div == cob_opr) ||
29977 (details::e_mul == cob_opr)
29978 )
29979 {
29980 switch (cob_opr)
29981 {
29982 case details::e_div : cobnode->set_c(c * cobnode->c()); break;
29983 case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
29984 default : return error_node();
29985 }
29986
29987 return cobnode;
29988 }
29989 }
29990 else if (operation == details::e_div)
29991 {
29992 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29993 details::operator_type cob_opr = cobnode->operation();
29994
29995 if (
29996 (details::e_div == cob_opr) ||
29997 (details::e_mul == cob_opr)
29998 )
29999 {
30000 details::expression_node<Type>* new_cobnode = error_node();
30001
30002 switch (cob_opr)
30003 {
30004 case details::e_div : new_cobnode = expr_gen.node_allocator_->
30005 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
30006 (c / cobnode->c(), cobnode->move_branch(0));
30007 break;
30008
30009 case details::e_mul : new_cobnode = expr_gen.node_allocator_->
30010 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30011 (c / cobnode->c(), cobnode->move_branch(0));
30012 break;
30013
30014 default : return error_node();
30015 }
30016
30017 free_node(*expr_gen.node_allocator_,branch[1]);
30018
30019 return new_cobnode;
30020 }
30021 }
30022 }
30023 #ifndef exprtk_disable_enhanced_features
30024 else if (details::is_sf3ext_node(branch[1]))
30025 {
30026 expression_node_ptr result = error_node();
30027
30028 const bool synthesis_result =
30029 synthesize_sf4ext_expression::template compile_right<ctype>
30030 (expr_gen, c, operation, branch[1], result);
30031
30032 if (synthesis_result)
30033 {
30034 free_node(*expr_gen.node_allocator_,branch[1]);
30035
30036 return result;
30037 }
30038 }
30039 #endif
30040
30041 switch (operation)
30042 {
30043 #define case_stmt(op0,op1) \
30044 case op0 : return expr_gen.node_allocator_-> \
30045 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
30046 (c, branch[1]); \
30047
30050 #undef case_stmt
30051 default : return error_node();
30052 }
30053 }
30054 };
30055
30056 struct synthesize_boc_expression
30057 {
30058 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30059 const details::operator_type& operation,
30060 expression_node_ptr (&branch)[2])
30061 {
30062 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30063
30064 details::free_node(*(expr_gen.node_allocator_), branch[1]);
30065
30066 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30067 {
30068 free_node(*expr_gen.node_allocator_, branch[0]);
30069
30070 return expr_gen(T(0));
30071 }
30072 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30073 {
30074 free_node(*expr_gen.node_allocator_, branch[0]);
30075
30076 return expr_gen(std::numeric_limits<T>::quiet_NaN());
30077 }
30078 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30079 return branch[0];
30080 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30081 return branch[0];
30082
30083 if (details::is_boc_node(branch[0]))
30084 {
30085 // Simplify expressions of the form:
30086 // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
30087 // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
30088 if (
30089 (operation == details::e_mul) ||
30090 (operation == details::e_add)
30091 )
30092 {
30093 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30094
30095 if (operation == bocnode->operation())
30096 {
30097 switch (operation)
30098 {
30099 case details::e_add : bocnode->set_c(c + bocnode->c()); break;
30100 case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
30101 default : return error_node();
30102 }
30103
30104 return bocnode;
30105 }
30106 }
30107 else if (operation == details::e_div)
30108 {
30109 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30110 details::operator_type boc_opr = bocnode->operation();
30111
30112 if (
30113 (details::e_div == boc_opr) ||
30114 (details::e_mul == boc_opr)
30115 )
30116 {
30117 switch (boc_opr)
30118 {
30119 case details::e_div : bocnode->set_c(c * bocnode->c()); break;
30120 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
30121 default : return error_node();
30122 }
30123
30124 return bocnode;
30125 }
30126 }
30127 else if (operation == details::e_pow)
30128 {
30129 // (v ^ c0) ^ c1 --> v ^(c0 * c1)
30130 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30131 details::operator_type boc_opr = bocnode->operation();
30132
30133 if (details::e_pow == boc_opr)
30134 {
30135 bocnode->set_c(bocnode->c() * c);
30136
30137 return bocnode;
30138 }
30139 }
30140 }
30141
30142 #ifndef exprtk_disable_enhanced_features
30143 if (details::is_sf3ext_node(branch[0]))
30144 {
30145 expression_node_ptr result = error_node();
30146
30147 const bool synthesis_result =
30148 synthesize_sf4ext_expression::template compile_left<ctype>
30149 (expr_gen, c, operation, branch[0], result);
30150
30151 if (synthesis_result)
30152 {
30153 free_node(*expr_gen.node_allocator_, branch[0]);
30154
30155 return result;
30156 }
30157 }
30158 #endif
30159
30160 switch (operation)
30161 {
30162 #define case_stmt(op0,op1) \
30163 case op0 : return expr_gen.node_allocator_-> \
30164 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
30165 (branch[0], c); \
30166
30169 #undef case_stmt
30170 default : return error_node();
30171 }
30172 }
30173 };
30174
30175 struct synthesize_cocob_expression
30176 {
30177 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30178 const details::operator_type& operation,
30179 expression_node_ptr (&branch)[2])
30180 {
30181 expression_node_ptr result = error_node();
30182
30183 // (cob) o c --> cob
30184 if (details::is_cob_node(branch[0]))
30185 {
30186 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
30187
30188 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30189
30190 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30191 {
30192 free_node(*expr_gen.node_allocator_, branch[0]);
30193 free_node(*expr_gen.node_allocator_, branch[1]);
30194
30195 return expr_gen(T(0));
30196 }
30197 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30198 {
30199 free_node(*expr_gen.node_allocator_, branch[0]);
30200 free_node(*expr_gen.node_allocator_, branch[1]);
30201
30202 return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
30203 }
30204 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30205 {
30206 free_node(*expr_gen.node_allocator_, branch[1]);
30207
30208 return branch[0];
30209 }
30210 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30211 {
30212 free_node(*expr_gen.node_allocator_, branch[1]);
30213
30214 return branch[0];
30215 }
30216 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
30217 {
30218 free_node(*expr_gen.node_allocator_, branch[1]);
30219
30220 return branch[0];
30221 }
30222
30223 const bool op_addsub = (details::e_add == cobnode->operation()) ||
30224 (details::e_sub == cobnode->operation()) ;
30225
30226 if (op_addsub)
30227 {
30228 switch (operation)
30229 {
30230 case details::e_add : cobnode->set_c(cobnode->c() + c); break;
30231 case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
30232 default : return error_node();
30233 }
30234
30235 result = cobnode;
30236 }
30237 else if (details::e_mul == cobnode->operation())
30238 {
30239 switch (operation)
30240 {
30241 case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
30242 case details::e_div : cobnode->set_c(cobnode->c() / c); break;
30243 default : return error_node();
30244 }
30245
30246 result = cobnode;
30247 }
30248 else if (details::e_div == cobnode->operation())
30249 {
30250 if (details::e_mul == operation)
30251 {
30252 cobnode->set_c(cobnode->c() * c);
30253 result = cobnode;
30254 }
30255 else if (details::e_div == operation)
30256 {
30257 result = expr_gen.node_allocator_->
30258 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30259 (cobnode->c() / c, cobnode->move_branch(0));
30260
30261 free_node(*expr_gen.node_allocator_, branch[0]);
30262 }
30263 }
30264
30265 if (result)
30266 {
30267 free_node(*expr_gen.node_allocator_,branch[1]);
30268 }
30269 }
30270
30271 // c o (cob) --> cob
30272 else if (details::is_cob_node(branch[1]))
30273 {
30274 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
30275
30276 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30277
30278 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30279 {
30280 free_node(*expr_gen.node_allocator_, branch[0]);
30281 free_node(*expr_gen.node_allocator_, branch[1]);
30282
30283 return expr_gen(T(0));
30284 }
30285 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30286 {
30287 free_node(*expr_gen.node_allocator_, branch[0]);
30288 free_node(*expr_gen.node_allocator_, branch[1]);
30289
30290 return expr_gen(T(0));
30291 }
30292 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30293 {
30294 free_node(*expr_gen.node_allocator_, branch[0]);
30295
30296 return branch[1];
30297 }
30298 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30299 {
30300 free_node(*expr_gen.node_allocator_, branch[0]);
30301
30302 return branch[1];
30303 }
30304
30305 if (details::e_add == cobnode->operation())
30306 {
30307 if (details::e_add == operation)
30308 {
30309 cobnode->set_c(c + cobnode->c());
30310 result = cobnode;
30311 }
30312 else if (details::e_sub == operation)
30313 {
30314 result = expr_gen.node_allocator_->
30315 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30316 (c - cobnode->c(), cobnode->move_branch(0));
30317
30318 free_node(*expr_gen.node_allocator_,branch[1]);
30319 }
30320 }
30321 else if (details::e_sub == cobnode->operation())
30322 {
30323 if (details::e_add == operation)
30324 {
30325 cobnode->set_c(c + cobnode->c());
30326 result = cobnode;
30327 }
30328 else if (details::e_sub == operation)
30329 {
30330 result = expr_gen.node_allocator_->
30331 template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
30332 (c - cobnode->c(), cobnode->move_branch(0));
30333
30334 free_node(*expr_gen.node_allocator_,branch[1]);
30335 }
30336 }
30337 else if (details::e_mul == cobnode->operation())
30338 {
30339 if (details::e_mul == operation)
30340 {
30341 cobnode->set_c(c * cobnode->c());
30342 result = cobnode;
30343 }
30344 else if (details::e_div == operation)
30345 {
30346 result = expr_gen.node_allocator_->
30347 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30348 (c / cobnode->c(), cobnode->move_branch(0));
30349
30350 free_node(*expr_gen.node_allocator_,branch[1]);
30351 }
30352 }
30353 else if (details::e_div == cobnode->operation())
30354 {
30355 if (details::e_mul == operation)
30356 {
30357 cobnode->set_c(c * cobnode->c());
30358 result = cobnode;
30359 }
30360 else if (details::e_div == operation)
30361 {
30362 result = expr_gen.node_allocator_->
30363 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
30364 (c / cobnode->c(), cobnode->move_branch(0));
30365
30366 free_node(*expr_gen.node_allocator_,branch[1]);
30367 }
30368 }
30369
30370 if (result)
30371 {
30372 free_node(*expr_gen.node_allocator_,branch[0]);
30373 }
30374 }
30375
30376 return result;
30377 }
30378 };
30379
30380 struct synthesize_coboc_expression
30381 {
30382 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30383 const details::operator_type& operation,
30384 expression_node_ptr (&branch)[2])
30385 {
30386 expression_node_ptr result = error_node();
30387
30388 // (boc) o c --> boc
30389 if (details::is_boc_node(branch[0]))
30390 {
30391 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30392
30393 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30394
30395 if (details::e_add == bocnode->operation())
30396 {
30397 switch (operation)
30398 {
30399 case details::e_add : bocnode->set_c(bocnode->c() + c); break;
30400 case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
30401 default : return error_node();
30402 }
30403
30404 result = bocnode;
30405 }
30406 else if (details::e_mul == bocnode->operation())
30407 {
30408 switch (operation)
30409 {
30410 case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
30411 case details::e_div : bocnode->set_c(bocnode->c() / c); break;
30412 default : return error_node();
30413 }
30414
30415 result = bocnode;
30416 }
30417 else if (details::e_sub == bocnode->operation())
30418 {
30419 if (details::e_add == operation)
30420 {
30421 result = expr_gen.node_allocator_->
30422 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
30423 (bocnode->move_branch(0), c - bocnode->c());
30424
30425 free_node(*expr_gen.node_allocator_,branch[0]);
30426 }
30427 else if (details::e_sub == operation)
30428 {
30429 bocnode->set_c(bocnode->c() + c);
30430 result = bocnode;
30431 }
30432 }
30433 else if (details::e_div == bocnode->operation())
30434 {
30435 switch (operation)
30436 {
30437 case details::e_div : bocnode->set_c(bocnode->c() * c); break;
30438 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
30439 default : return error_node();
30440 }
30441
30442 result = bocnode;
30443 }
30444
30445 if (result)
30446 {
30447 free_node(*expr_gen.node_allocator_, branch[1]);
30448 }
30449 }
30450
30451 // c o (boc) --> boc
30452 else if (details::is_boc_node(branch[1]))
30453 {
30454 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
30455
30456 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30457
30458 if (details::e_add == bocnode->operation())
30459 {
30460 if (details::e_add == operation)
30461 {
30462 bocnode->set_c(c + bocnode->c());
30463 result = bocnode;
30464 }
30465 else if (details::e_sub == operation)
30466 {
30467 result = expr_gen.node_allocator_->
30468 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30469 (c - bocnode->c(), bocnode->move_branch(0));
30470
30471 free_node(*expr_gen.node_allocator_,branch[1]);
30472 }
30473 }
30474 else if (details::e_sub == bocnode->operation())
30475 {
30476 if (details::e_add == operation)
30477 {
30478 result = expr_gen.node_allocator_->
30479 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
30480 (bocnode->move_branch(0), c - bocnode->c());
30481
30482 free_node(*expr_gen.node_allocator_,branch[1]);
30483 }
30484 else if (details::e_sub == operation)
30485 {
30486 result = expr_gen.node_allocator_->
30487 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30488 (c + bocnode->c(), bocnode->move_branch(0));
30489
30490 free_node(*expr_gen.node_allocator_,branch[1]);
30491 }
30492 }
30493 else if (details::e_mul == bocnode->operation())
30494 {
30495 if (details::e_mul == operation)
30496 {
30497 bocnode->set_c(c * bocnode->c());
30498 result = bocnode;
30499 }
30500 else if (details::e_div == operation)
30501 {
30502 result = expr_gen.node_allocator_->
30503 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30504 (c / bocnode->c(), bocnode->move_branch(0));
30505
30506 free_node(*expr_gen.node_allocator_,branch[1]);
30507 }
30508 }
30509 else if (details::e_div == bocnode->operation())
30510 {
30511 if (details::e_mul == operation)
30512 {
30513 bocnode->set_c(bocnode->c() / c);
30514 result = bocnode;
30515 }
30516 else if (details::e_div == operation)
30517 {
30518 result = expr_gen.node_allocator_->
30519 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30520 (c * bocnode->c(), bocnode->move_branch(0));
30521
30522 free_node(*expr_gen.node_allocator_,branch[1]);
30523 }
30524 }
30525
30526 if (result)
30527 {
30528 free_node(*expr_gen.node_allocator_,branch[0]);
30529 }
30530 }
30531
30532 return result;
30533 }
30534 };
30535
30536 #ifndef exprtk_disable_enhanced_features
30537 inline bool synthesize_expression(const details::operator_type& operation,
30538 expression_node_ptr (&branch)[2],
30539 expression_node_ptr& result)
30540 {
30541 result = error_node();
30542
30543 if (!operation_optimisable(operation))
30544 return false;
30545
30546 const std::string node_id = branch_to_id(branch);
30547
30548 const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
30549
30550 if (synthesize_map_.end() != itr)
30551 {
30552 result = itr->second((*this), operation, branch);
30553
30554 return true;
30555 }
30556 else
30557 return false;
30558 }
30559
30560 struct synthesize_vov_expression
30561 {
30562 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30563 const details::operator_type& operation,
30564 expression_node_ptr (&branch)[2])
30565 {
30566 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30567 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30568
30569 switch (operation)
30570 {
30571 #define case_stmt(op0,op1) \
30572 case op0 : return expr_gen.node_allocator_-> \
30573 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
30574 (v1, v2); \
30575
30578 #undef case_stmt
30579 default : return error_node();
30580 }
30581 }
30582 };
30583
30584 struct synthesize_cov_expression
30585 {
30586 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30587 const details::operator_type& operation,
30588 expression_node_ptr (&branch)[2])
30589 {
30590 const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
30591 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
30592
30593 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30594
30595 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30596 return expr_gen(T(0));
30597 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30598 return expr_gen(T(0));
30599 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30600 return static_cast<details::variable_node<Type>*>(branch[1]);
30601 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30602 return static_cast<details::variable_node<Type>*>(branch[1]);
30603
30604 switch (operation)
30605 {
30606 #define case_stmt(op0,op1) \
30607 case op0 : return expr_gen.node_allocator_-> \
30608 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
30609 (c, v); \
30610
30613 #undef case_stmt
30614 default : return error_node();
30615 }
30616 }
30617 };
30618
30619 struct synthesize_voc_expression
30620 {
30621 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30622 const details::operator_type& operation,
30623 expression_node_ptr (&branch)[2])
30624 {
30625 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
30626 const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
30627
30628 details::free_node(*(expr_gen.node_allocator_), branch[1]);
30629
30630 if (expr_gen.cardinal_pow_optimisable(operation,c))
30631 {
30632 if (std::equal_to<T>()(T(1),c))
30633 return branch[0];
30634 else
30635 return expr_gen.cardinal_pow_optimisation(v,c);
30636 }
30637 else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30638 return expr_gen(T(0));
30639 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30640 return expr_gen(std::numeric_limits<T>::quiet_NaN());
30641 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30642 return static_cast<details::variable_node<Type>*>(branch[0]);
30643 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30644 return static_cast<details::variable_node<Type>*>(branch[0]);
30645 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
30646 return static_cast<details::variable_node<Type>*>(branch[0]);
30647
30648 switch (operation)
30649 {
30650 #define case_stmt(op0,op1) \
30651 case op0 : return expr_gen.node_allocator_-> \
30652 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
30653 (v, c); \
30654
30657 #undef case_stmt
30658 default : return error_node();
30659 }
30660 }
30661 };
30662
30663 struct synthesize_sf3ext_expression
30664 {
30665 template <typename T0, typename T1, typename T2>
30666 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30667 const details::operator_type& sf3opr,
30668 T0 t0, T1 t1, T2 t2)
30669 {
30670 switch (sf3opr)
30671 {
30672 #define case_stmt(op) \
30673 case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
30674 allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
30675
30676 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
30677 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
30678 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
30679 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
30680 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
30681 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
30682 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
30683 case_stmt(28) case_stmt(29) case_stmt(30)
30684 #undef case_stmt
30685 default : return error_node();
30686 }
30687 }
30688
30689 template <typename T0, typename T1, typename T2>
30690 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
30691 T0 t0, T1 t1, T2 t2,
30692 expression_node_ptr& result)
30693 {
30695
30696 if (!expr_gen.sf3_optimisable(id,sf3opr))
30697 return false;
30698 else
30699 result = synthesize_sf3ext_expression::template process<T0, T1, T2>
30700 (expr_gen, sf3opr, t0, t1, t2);
30701
30702 return true;
30703 }
30704 };
30705
30706 struct synthesize_sf4ext_expression
30707 {
30708 template <typename T0, typename T1, typename T2, typename T3>
30709 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30710 const details::operator_type& sf4opr,
30711 T0 t0, T1 t1, T2 t2, T3 t3)
30712 {
30713 switch (sf4opr)
30714 {
30715 #define case_stmt0(op) \
30716 case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
30717 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
30718
30719
30720 #define case_stmt1(op) \
30721 case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
30722 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
30723
30733
30749 case_stmt1(60) case_stmt1(61)
30750
30751 #undef case_stmt0
30752 #undef case_stmt1
30753 default : return error_node();
30754 }
30755 }
30756
30757 template <typename T0, typename T1, typename T2, typename T3>
30758 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
30759 T0 t0, T1 t1, T2 t2, T3 t3,
30760 expression_node_ptr& result)
30761 {
30763
30764 if (!expr_gen.sf4_optimisable(id,sf4opr))
30765 return false;
30766 else
30767 result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
30768 (expr_gen, sf4opr, t0, t1, t2, t3);
30769
30770 return true;
30771 }
30772
30773 // T o (sf3ext)
30774 template <typename ExternalType>
30775 static inline bool compile_right(expression_generator<Type>& expr_gen,
30776 ExternalType t,
30777 const details::operator_type& operation,
30778 expression_node_ptr& sf3node,
30779 expression_node_ptr& result)
30780 {
30781 if (!details::is_sf3ext_node(sf3node))
30782 return false;
30783
30784 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
30785
30786 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
30787 const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
30788
30789 switch (n->type())
30790 {
30791 case details::expression_node<Type>::e_covoc : return compile_right_impl
30792 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
30793 (expr_gen, id, t, sf3node, result);
30794
30795 case details::expression_node<Type>::e_covov : return compile_right_impl
30796 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
30797 (expr_gen, id, t, sf3node, result);
30798
30799 case details::expression_node<Type>::e_vocov : return compile_right_impl
30800 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
30801 (expr_gen, id, t, sf3node, result);
30802
30803 case details::expression_node<Type>::e_vovoc : return compile_right_impl
30804 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
30805 (expr_gen, id, t, sf3node, result);
30806
30807 case details::expression_node<Type>::e_vovov : return compile_right_impl
30808 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
30809 (expr_gen, id, t, sf3node, result);
30810
30811 default : return false;
30812 }
30813 }
30814
30815 // (sf3ext) o T
30816 template <typename ExternalType>
30817 static inline bool compile_left(expression_generator<Type>& expr_gen,
30818 ExternalType t,
30819 const details::operator_type& operation,
30820 expression_node_ptr& sf3node,
30821 expression_node_ptr& result)
30822 {
30823 if (!details::is_sf3ext_node(sf3node))
30824 return false;
30825
30826 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
30827
30828 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
30829
30830 const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
30831
30832 switch (n->type())
30833 {
30834 case details::expression_node<Type>::e_covoc : return compile_left_impl
30835 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
30836 (expr_gen, id, t, sf3node, result);
30837
30838 case details::expression_node<Type>::e_covov : return compile_left_impl
30839 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
30840 (expr_gen, id, t, sf3node, result);
30841
30842 case details::expression_node<Type>::e_vocov : return compile_left_impl
30843 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
30844 (expr_gen, id, t, sf3node, result);
30845
30846 case details::expression_node<Type>::e_vovoc : return compile_left_impl
30847 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
30848 (expr_gen, id, t, sf3node, result);
30849
30850 case details::expression_node<Type>::e_vovov : return compile_left_impl
30851 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
30852 (expr_gen, id, t, sf3node, result);
30853
30854 default : return false;
30855 }
30856 }
30857
30858 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
30859 static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
30860 const std::string& id,
30861 ExternalType t,
30862 expression_node_ptr& node,
30863 expression_node_ptr& result)
30864 {
30865 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
30866
30867 if (n)
30868 {
30869 T0 t0 = n->t0();
30870 T1 t1 = n->t1();
30871 T2 t2 = n->t2();
30872
30873 return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
30874 (expr_gen, id, t, t0, t1, t2, result);
30875 }
30876 else
30877 return false;
30878 }
30879
30880 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
30881 static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
30882 const std::string& id,
30883 ExternalType t,
30884 expression_node_ptr& node,
30885 expression_node_ptr& result)
30886 {
30887 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
30888
30889 if (n)
30890 {
30891 T0 t0 = n->t0();
30892 T1 t1 = n->t1();
30893 T2 t2 = n->t2();
30894
30895 return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
30896 (expr_gen, id, t0, t1, t2, t, result);
30897 }
30898 else
30899 return false;
30900 }
30901 };
30902
30903 struct synthesize_vovov_expression0
30904 {
30905 typedef typename vovov_t::type0 node_type;
30906 typedef typename vovov_t::sf3_type sf3_type;
30907
30908 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30909 const details::operator_type& operation,
30910 expression_node_ptr (&branch)[2])
30911 {
30912 // (v0 o0 v1) o1 (v2)
30913 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30914 const Type& v0 = vov->v0();
30915 const Type& v1 = vov->v1();
30916 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30917 const details::operator_type o0 = vov->operation();
30918 const details::operator_type o1 = operation;
30919
30920 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30921 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30922
30923 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30924
30925 expression_node_ptr result = error_node();
30926
30927 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30928 {
30929 // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
30930 if ((details::e_div == o0) && (details::e_div == o1))
30931 {
30932 const bool synthesis_result =
30933 synthesize_sf3ext_expression::
30934 template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
30935
30936 exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
30937
30938 return (synthesis_result) ? result : error_node();
30939 }
30940 }
30941
30942 const bool synthesis_result =
30943 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
30944 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
30945
30946 if (synthesis_result)
30947 return result;
30948 else if (!expr_gen.valid_operator(o0,f0))
30949 return error_node();
30950 else if (!expr_gen.valid_operator(o1,f1))
30951 return error_node();
30952 else
30953 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
30954 }
30955
30956 static inline std::string id(expression_generator<Type>& expr_gen,
30958 {
30959 return details::build_string()
30960 << "(t" << expr_gen.to_str(o0)
30961 << "t)" << expr_gen.to_str(o1)
30962 << "t";
30963 }
30964 };
30965
30966 struct synthesize_vovov_expression1
30967 {
30968 typedef typename vovov_t::type1 node_type;
30969 typedef typename vovov_t::sf3_type sf3_type;
30970
30971 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30972 const details::operator_type& operation,
30973 expression_node_ptr (&branch)[2])
30974 {
30975 // (v0) o0 (v1 o1 v2)
30976 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30977 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30978 const Type& v1 = vov->v0();
30979 const Type& v2 = vov->v1();
30980 const details::operator_type o0 = operation;
30981 const details::operator_type o1 = vov->operation();
30982
30983 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30984 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30985
30986 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30987
30988 expression_node_ptr result = error_node();
30989
30990 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30991 {
30992 // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
30993 if ((details::e_div == o0) && (details::e_div == o1))
30994 {
30995 const bool synthesis_result =
30996 synthesize_sf3ext_expression::
30997 template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
30998
30999 exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
31000
31001 return (synthesis_result) ? result : error_node();
31002 }
31003 }
31004
31005 const bool synthesis_result =
31006 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
31007 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
31008
31009 if (synthesis_result)
31010 return result;
31011 else if (!expr_gen.valid_operator(o0,f0))
31012 return error_node();
31013 else if (!expr_gen.valid_operator(o1,f1))
31014 return error_node();
31015 else
31016 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
31017 }
31018
31019 static inline std::string id(expression_generator<Type>& expr_gen,
31021 {
31022 return details::build_string()
31023 << "t" << expr_gen.to_str(o0)
31024 << "(t" << expr_gen.to_str(o1)
31025 << "t)";
31026 }
31027 };
31028
31029 struct synthesize_vovoc_expression0
31030 {
31031 typedef typename vovoc_t::type0 node_type;
31032 typedef typename vovoc_t::sf3_type sf3_type;
31033
31034 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31035 const details::operator_type& operation,
31036 expression_node_ptr (&branch)[2])
31037 {
31038 // (v0 o0 v1) o1 (c)
31039 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31040 const Type& v0 = vov->v0();
31041 const Type& v1 = vov->v1();
31042 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
31043 const details::operator_type o0 = vov->operation();
31044 const details::operator_type o1 = operation;
31045
31046 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31047 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31048
31049 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31050 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31051
31052 expression_node_ptr result = error_node();
31053
31054 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31055 {
31056 // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
31057 if ((details::e_div == o0) && (details::e_div == o1))
31058 {
31059 const bool synthesis_result =
31060 synthesize_sf3ext_expression::
31061 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
31062
31063 exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
31064
31065 return (synthesis_result) ? result : error_node();
31066 }
31067 }
31068
31069 const bool synthesis_result =
31070 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
31071 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
31072
31073 if (synthesis_result)
31074 return result;
31075 else if (!expr_gen.valid_operator(o0,f0))
31076 return error_node();
31077 else if (!expr_gen.valid_operator(o1,f1))
31078 return error_node();
31079 else
31080 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
31081 }
31082
31083 static inline std::string id(expression_generator<Type>& expr_gen,
31085 {
31086 return details::build_string()
31087 << "(t" << expr_gen.to_str(o0)
31088 << "t)" << expr_gen.to_str(o1)
31089 << "t";
31090 }
31091 };
31092
31093 struct synthesize_vovoc_expression1
31094 {
31095 typedef typename vovoc_t::type1 node_type;
31096 typedef typename vovoc_t::sf3_type sf3_type;
31097
31098 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31099 const details::operator_type& operation,
31100 expression_node_ptr (&branch)[2])
31101 {
31102 // (v0) o0 (v1 o1 c)
31103 const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
31104 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
31105 const Type& v1 = voc->v();
31106 const Type c = voc->c();
31107 const details::operator_type o0 = operation;
31108 const details::operator_type o1 = voc->operation();
31109
31110 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31111 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31112
31113 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31114
31115 expression_node_ptr result = error_node();
31116
31117 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31118 {
31119 // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
31120 if ((details::e_div == o0) && (details::e_div == o1))
31121 {
31122 const bool synthesis_result =
31123 synthesize_sf3ext_expression::
31124 template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
31125
31126 exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
31127
31128 return (synthesis_result) ? result : error_node();
31129 }
31130 }
31131
31132 const bool synthesis_result =
31133 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
31134 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
31135
31136 if (synthesis_result)
31137 return result;
31138 else if (!expr_gen.valid_operator(o0,f0))
31139 return error_node();
31140 else if (!expr_gen.valid_operator(o1,f1))
31141 return error_node();
31142 else
31143 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
31144 }
31145
31146 static inline std::string id(expression_generator<Type>& expr_gen,
31148 {
31149 return details::build_string()
31150 << "t" << expr_gen.to_str(o0)
31151 << "(t" << expr_gen.to_str(o1)
31152 << "t)";
31153 }
31154 };
31155
31156 struct synthesize_vocov_expression0
31157 {
31158 typedef typename vocov_t::type0 node_type;
31159 typedef typename vocov_t::sf3_type sf3_type;
31160
31161 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31162 const details::operator_type& operation,
31163 expression_node_ptr (&branch)[2])
31164 {
31165 // (v0 o0 c) o1 (v1)
31166 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31167 const Type& v0 = voc->v();
31168 const Type c = voc->c();
31169 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
31170 const details::operator_type o0 = voc->operation();
31171 const details::operator_type o1 = operation;
31172
31173 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31174 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31175
31176 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31177
31178 expression_node_ptr result = error_node();
31179
31180 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31181 {
31182 // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
31183 if ((details::e_div == o0) && (details::e_div == o1))
31184 {
31185 const bool synthesis_result =
31186 synthesize_sf3ext_expression::
31187 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
31188
31189 exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
31190
31191 return (synthesis_result) ? result : error_node();
31192 }
31193 }
31194
31195 const bool synthesis_result =
31196 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
31197 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
31198
31199 if (synthesis_result)
31200 return result;
31201 else if (!expr_gen.valid_operator(o0,f0))
31202 return error_node();
31203 else if (!expr_gen.valid_operator(o1,f1))
31204 return error_node();
31205 else
31206 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
31207 }
31208
31209 static inline std::string id(expression_generator<Type>& expr_gen,
31211 {
31212 return details::build_string()
31213 << "(t" << expr_gen.to_str(o0)
31214 << "t)" << expr_gen.to_str(o1)
31215 << "t";
31216 }
31217 };
31218
31219 struct synthesize_vocov_expression1
31220 {
31221 typedef typename vocov_t::type1 node_type;
31222 typedef typename vocov_t::sf3_type sf3_type;
31223
31224 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31225 const details::operator_type& operation,
31226 expression_node_ptr (&branch)[2])
31227 {
31228 // (v0) o0 (c o1 v1)
31229 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31230 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
31231 const Type c = cov->c();
31232 const Type& v1 = cov->v();
31233 const details::operator_type o0 = operation;
31234 const details::operator_type o1 = cov->operation();
31235
31236 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31237 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31238
31239 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31240
31241 expression_node_ptr result = error_node();
31242
31243 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31244 {
31245 // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
31246 if ((details::e_div == o0) && (details::e_div == o1))
31247 {
31248 const bool synthesis_result =
31249 synthesize_sf3ext_expression::
31250 template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
31251
31252 exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
31253
31254 return (synthesis_result) ? result : error_node();
31255 }
31256 }
31257
31258 const bool synthesis_result =
31259 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
31260 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
31261
31262 if (synthesis_result)
31263 return result;
31264 else if (!expr_gen.valid_operator(o0,f0))
31265 return error_node();
31266 else if (!expr_gen.valid_operator(o1,f1))
31267 return error_node();
31268 else
31269 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
31270 }
31271
31272 static inline std::string id(expression_generator<Type>& expr_gen,
31274 {
31275 return details::build_string()
31276 << "t" << expr_gen.to_str(o0)
31277 << "(t" << expr_gen.to_str(o1)
31278 << "t)";
31279 }
31280 };
31281
31282 struct synthesize_covov_expression0
31283 {
31284 typedef typename covov_t::type0 node_type;
31285 typedef typename covov_t::sf3_type sf3_type;
31286
31287 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31288 const details::operator_type& operation,
31289 expression_node_ptr (&branch)[2])
31290 {
31291 // (c o0 v0) o1 (v1)
31292 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31293 const Type c = cov->c();
31294 const Type& v0 = cov->v();
31295 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
31296 const details::operator_type o0 = cov->operation();
31297 const details::operator_type o1 = operation;
31298
31299 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31300 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31301
31302 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31303
31304 expression_node_ptr result = error_node();
31305
31306 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31307 {
31308 // (c / v0) / v1 --> (covov) c / (v0 * v1)
31309 if ((details::e_div == o0) && (details::e_div == o1))
31310 {
31311 const bool synthesis_result =
31312 synthesize_sf3ext_expression::
31313 template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
31314
31315 exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
31316
31317 return (synthesis_result) ? result : error_node();
31318 }
31319 }
31320
31321 const bool synthesis_result =
31322 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
31323 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
31324
31325 if (synthesis_result)
31326 return result;
31327 else if (!expr_gen.valid_operator(o0,f0))
31328 return error_node();
31329 else if (!expr_gen.valid_operator(o1,f1))
31330 return error_node();
31331 else
31332 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
31333 }
31334
31335 static inline std::string id(expression_generator<Type>& expr_gen,
31337 {
31338 return details::build_string()
31339 << "(t" << expr_gen.to_str(o0)
31340 << "t)" << expr_gen.to_str(o1)
31341 << "t";
31342 }
31343 };
31344
31345 struct synthesize_covov_expression1
31346 {
31347 typedef typename covov_t::type1 node_type;
31348 typedef typename covov_t::sf3_type sf3_type;
31349
31350 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31351 const details::operator_type& operation,
31352 expression_node_ptr (&branch)[2])
31353 {
31354 // (c) o0 (v0 o1 v1)
31355 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31356 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
31357 const Type& v0 = vov->v0();
31358 const Type& v1 = vov->v1();
31359 const details::operator_type o0 = operation;
31360 const details::operator_type o1 = vov->operation();
31361
31362 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31363 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31364
31365 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31366 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31367
31368 expression_node_ptr result = error_node();
31369
31370 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31371 {
31372 // c / (v0 / v1) --> (covov) (c * v1) / v0
31373 if ((details::e_div == o0) && (details::e_div == o1))
31374 {
31375 const bool synthesis_result =
31376 synthesize_sf3ext_expression::
31377 template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
31378
31379 exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
31380
31381 return (synthesis_result) ? result : error_node();
31382 }
31383 }
31384
31385 const bool synthesis_result =
31386 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
31387 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
31388
31389 if (synthesis_result)
31390 return result;
31391 else if (!expr_gen.valid_operator(o0,f0))
31392 return error_node();
31393 else if (!expr_gen.valid_operator(o1,f1))
31394 return error_node();
31395 else
31396 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
31397 }
31398
31399 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
31400 {
31401 return details::build_string()
31402 << "t" << expr_gen.to_str(o0)
31403 << "(t" << expr_gen.to_str(o1)
31404 << "t)";
31405 }
31406 };
31407
31408 struct synthesize_covoc_expression0
31409 {
31410 typedef typename covoc_t::type0 node_type;
31411 typedef typename covoc_t::sf3_type sf3_type;
31412
31413 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31414 const details::operator_type& operation,
31415 expression_node_ptr (&branch)[2])
31416 {
31417 // (c0 o0 v) o1 (c1)
31418 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31419 const Type c0 = cov->c();
31420 const Type& v = cov->v();
31421 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
31422 const details::operator_type o0 = cov->operation();
31423 const details::operator_type o1 = operation;
31424
31425 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31426 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31427
31428 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31429 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31430
31431 expression_node_ptr result = error_node();
31432
31433 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31434 {
31435 // (c0 + v) + c1 --> (cov) (c0 + c1) + v
31436 if ((details::e_add == o0) && (details::e_add == o1))
31437 {
31438 exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
31439
31440 return expr_gen.node_allocator_->
31441 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31442 }
31443 // (c0 + v) - c1 --> (cov) (c0 - c1) + v
31444 else if ((details::e_add == o0) && (details::e_sub == o1))
31445 {
31446 exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
31447
31448 return expr_gen.node_allocator_->
31449 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31450 }
31451 // (c0 - v) + c1 --> (cov) (c0 + c1) - v
31452 else if ((details::e_sub == o0) && (details::e_add == o1))
31453 {
31454 exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
31455
31456 return expr_gen.node_allocator_->
31457 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31458 }
31459 // (c0 - v) - c1 --> (cov) (c0 - c1) - v
31460 else if ((details::e_sub == o0) && (details::e_sub == o1))
31461 {
31462 exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
31463
31464 return expr_gen.node_allocator_->
31465 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31466 }
31467 // (c0 * v) * c1 --> (cov) (c0 * c1) * v
31468 else if ((details::e_mul == o0) && (details::e_mul == o1))
31469 {
31470 exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
31471
31472 return expr_gen.node_allocator_->
31473 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31474 }
31475 // (c0 * v) / c1 --> (cov) (c0 / c1) * v
31476 else if ((details::e_mul == o0) && (details::e_div == o1))
31477 {
31478 exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
31479
31480 return expr_gen.node_allocator_->
31481 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31482 }
31483 // (c0 / v) * c1 --> (cov) (c0 * c1) / v
31484 else if ((details::e_div == o0) && (details::e_mul == o1))
31485 {
31486 exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
31487
31488 return expr_gen.node_allocator_->
31489 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31490 }
31491 // (c0 / v) / c1 --> (cov) (c0 / c1) / v
31492 else if ((details::e_div == o0) && (details::e_div == o1))
31493 {
31494 exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
31495
31496 return expr_gen.node_allocator_->
31497 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31498 }
31499 }
31500
31501 const bool synthesis_result =
31502 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
31503 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
31504
31505 if (synthesis_result)
31506 return result;
31507 else if (!expr_gen.valid_operator(o0,f0))
31508 return error_node();
31509 else if (!expr_gen.valid_operator(o1,f1))
31510 return error_node();
31511 else
31512 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
31513 }
31514
31515 static inline std::string id(expression_generator<Type>& expr_gen,
31517 {
31518 return details::build_string()
31519 << "(t" << expr_gen.to_str(o0)
31520 << "t)" << expr_gen.to_str(o1)
31521 << "t";
31522 }
31523 };
31524
31525 struct synthesize_covoc_expression1
31526 {
31527 typedef typename covoc_t::type1 node_type;
31528 typedef typename covoc_t::sf3_type sf3_type;
31529
31530 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31531 const details::operator_type& operation,
31532 expression_node_ptr (&branch)[2])
31533 {
31534 // (c0) o0 (v o1 c1)
31535 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31536 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
31537 const Type& v = voc->v();
31538 const Type c1 = voc->c();
31539 const details::operator_type o0 = operation;
31540 const details::operator_type o1 = voc->operation();
31541
31542 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31543 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31544
31545 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31546 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31547
31548 expression_node_ptr result = error_node();
31549
31550 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31551 {
31552 // (c0) + (v + c1) --> (cov) (c0 + c1) + v
31553 if ((details::e_add == o0) && (details::e_add == o1))
31554 {
31555 exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
31556
31557 return expr_gen.node_allocator_->
31558 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31559 }
31560 // (c0) + (v - c1) --> (cov) (c0 - c1) + v
31561 else if ((details::e_add == o0) && (details::e_sub == o1))
31562 {
31563 exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
31564
31565 return expr_gen.node_allocator_->
31566 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31567 }
31568 // (c0) - (v + c1) --> (cov) (c0 - c1) - v
31569 else if ((details::e_sub == o0) && (details::e_add == o1))
31570 {
31571 exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
31572
31573 return expr_gen.node_allocator_->
31574 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31575 }
31576 // (c0) - (v - c1) --> (cov) (c0 + c1) - v
31577 else if ((details::e_sub == o0) && (details::e_sub == o1))
31578 {
31579 exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
31580
31581 return expr_gen.node_allocator_->
31582 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31583 }
31584 // (c0) * (v * c1) --> (voc) v * (c0 * c1)
31585 else if ((details::e_mul == o0) && (details::e_mul == o1))
31586 {
31587 exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
31588
31589 return expr_gen.node_allocator_->
31590 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31591 }
31592 // (c0) * (v / c1) --> (cov) (c0 / c1) * v
31593 else if ((details::e_mul == o0) && (details::e_div == o1))
31594 {
31595 exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
31596
31597 return expr_gen.node_allocator_->
31598 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31599 }
31600 // (c0) / (v * c1) --> (cov) (c0 / c1) / v
31601 else if ((details::e_div == o0) && (details::e_mul == o1))
31602 {
31603 exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
31604
31605 return expr_gen.node_allocator_->
31606 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31607 }
31608 // (c0) / (v / c1) --> (cov) (c0 * c1) / v
31609 else if ((details::e_div == o0) && (details::e_div == o1))
31610 {
31611 exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
31612
31613 return expr_gen.node_allocator_->
31614 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31615 }
31616 }
31617
31618 const bool synthesis_result =
31619 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
31620 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
31621
31622 if (synthesis_result)
31623 return result;
31624 else if (!expr_gen.valid_operator(o0,f0))
31625 return error_node();
31626 else if (!expr_gen.valid_operator(o1,f1))
31627 return error_node();
31628 else
31629 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
31630 }
31631
31632 static inline std::string id(expression_generator<Type>& expr_gen,
31634 {
31635 return details::build_string()
31636 << "t" << expr_gen.to_str(o0)
31637 << "(t" << expr_gen.to_str(o1)
31638 << "t)";
31639 }
31640 };
31641
31642 struct synthesize_cocov_expression0
31643 {
31644 typedef typename cocov_t::type0 node_type;
31645 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
31646 {
31647 // (c0 o0 c1) o1 (v) - Not possible.
31648 return error_node();
31649 }
31650 };
31651
31652 struct synthesize_cocov_expression1
31653 {
31654 typedef typename cocov_t::type1 node_type;
31655 typedef typename cocov_t::sf3_type sf3_type;
31656
31657 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31658 const details::operator_type& operation,
31659 expression_node_ptr (&branch)[2])
31660 {
31661 // (c0) o0 (c1 o1 v)
31662 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31663 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
31664 const Type c1 = cov->c();
31665 const Type& v = cov->v();
31666 const details::operator_type o0 = operation;
31667 const details::operator_type o1 = cov->operation();
31668
31669 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31670 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31671
31672 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31673 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31674
31675 expression_node_ptr result = error_node();
31676
31677 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31678 {
31679 // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
31680 if ((details::e_add == o0) && (details::e_add == o1))
31681 {
31682 exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
31683
31684 return expr_gen.node_allocator_->
31685 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31686 }
31687 // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
31688 else if ((details::e_add == o0) && (details::e_sub == o1))
31689 {
31690 exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
31691
31692 return expr_gen.node_allocator_->
31693 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31694 }
31695 // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
31696 else if ((details::e_sub == o0) && (details::e_add == o1))
31697 {
31698 exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
31699
31700 return expr_gen.node_allocator_->
31701 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31702 }
31703 // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
31704 else if ((details::e_sub == o0) && (details::e_sub == o1))
31705 {
31706 exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
31707
31708 return expr_gen.node_allocator_->
31709 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31710 }
31711 // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
31712 else if ((details::e_mul == o0) && (details::e_mul == o1))
31713 {
31714 exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
31715
31716 return expr_gen.node_allocator_->
31717 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31718 }
31719 // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
31720 else if ((details::e_mul == o0) && (details::e_div == o1))
31721 {
31722 exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
31723
31724 return expr_gen.node_allocator_->
31725 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31726 }
31727 // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
31728 else if ((details::e_div == o0) && (details::e_mul == o1))
31729 {
31730 exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
31731
31732 return expr_gen.node_allocator_->
31733 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31734 }
31735 // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
31736 else if ((details::e_div == o0) && (details::e_div == o1))
31737 {
31738 exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
31739
31740 return expr_gen.node_allocator_->
31741 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31742 }
31743 }
31744
31745 const bool synthesis_result =
31746 synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
31747 (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
31748
31749 if (synthesis_result)
31750 return result;
31751 else if (!expr_gen.valid_operator(o0,f0))
31752 return error_node();
31753 else if (!expr_gen.valid_operator(o1,f1))
31754 return error_node();
31755 else
31756 return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
31757 }
31758
31759 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
31760 {
31761 return details::build_string()
31762 << "t" << expr_gen.to_str(o0)
31763 << "(t" << expr_gen.to_str(o1)
31764 << "t)";
31765 }
31766 };
31767
31768 struct synthesize_vococ_expression0
31769 {
31770 typedef typename vococ_t::type0 node_type;
31771 typedef typename vococ_t::sf3_type sf3_type;
31772
31773 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31774 const details::operator_type& operation,
31775 expression_node_ptr (&branch)[2])
31776 {
31777 // (v o0 c0) o1 (c1)
31778 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31779 const Type& v = voc->v();
31780 const Type& c0 = voc->c();
31781 const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
31782 const details::operator_type o0 = voc->operation();
31783 const details::operator_type o1 = operation;
31784
31785 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31786 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31787
31788 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31789 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31790
31791 expression_node_ptr result = error_node();
31792
31793 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31794 {
31795 // (v + c0) + c1 --> (voc) v + (c0 + c1)
31796 if ((details::e_add == o0) && (details::e_add == o1))
31797 {
31798 exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
31799
31800 return expr_gen.node_allocator_->
31801 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
31802 }
31803 // (v + c0) - c1 --> (voc) v + (c0 - c1)
31804 else if ((details::e_add == o0) && (details::e_sub == o1))
31805 {
31806 exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
31807
31808 return expr_gen.node_allocator_->
31809 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
31810 }
31811 // (v - c0) + c1 --> (voc) v - (c0 + c1)
31812 else if ((details::e_sub == o0) && (details::e_add == o1))
31813 {
31814 exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
31815
31816 return expr_gen.node_allocator_->
31817 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
31818 }
31819 // (v - c0) - c1 --> (voc) v - (c0 + c1)
31820 else if ((details::e_sub == o0) && (details::e_sub == o1))
31821 {
31822 exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
31823
31824 return expr_gen.node_allocator_->
31825 template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
31826 }
31827 // (v * c0) * c1 --> (voc) v * (c0 * c1)
31828 else if ((details::e_mul == o0) && (details::e_mul == o1))
31829 {
31830 exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
31831
31832 return expr_gen.node_allocator_->
31833 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
31834 }
31835 // (v * c0) / c1 --> (voc) v * (c0 / c1)
31836 else if ((details::e_mul == o0) && (details::e_div == o1))
31837 {
31838 exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
31839
31840 return expr_gen.node_allocator_->
31841 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
31842 }
31843 // (v / c0) * c1 --> (voc) v * (c1 / c0)
31844 else if ((details::e_div == o0) && (details::e_mul == o1))
31845 {
31846 exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
31847
31848 return expr_gen.node_allocator_->
31849 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
31850 }
31851 // (v / c0) / c1 --> (voc) v / (c0 * c1)
31852 else if ((details::e_div == o0) && (details::e_div == o1))
31853 {
31854 exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
31855
31856 return expr_gen.node_allocator_->
31857 template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
31858 }
31859 // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
31860 else if ((details::e_pow == o0) && (details::e_pow == o1))
31861 {
31862 exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
31863
31864 return expr_gen.node_allocator_->
31865 template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
31866 }
31867 }
31868
31869 const bool synthesis_result =
31870 synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
31871 (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
31872
31873 if (synthesis_result)
31874 return result;
31875 else if (!expr_gen.valid_operator(o0,f0))
31876 return error_node();
31877 else if (!expr_gen.valid_operator(o1,f1))
31878 return error_node();
31879 else
31880 return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
31881 }
31882
31883 static inline std::string id(expression_generator<Type>& expr_gen,
31885 {
31886 return details::build_string()
31887 << "(t" << expr_gen.to_str(o0)
31888 << "t)" << expr_gen.to_str(o1)
31889 << "t";
31890 }
31891 };
31892
31893 struct synthesize_vococ_expression1
31894 {
31895 typedef typename vococ_t::type0 node_type;
31896
31897 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
31898 {
31899 // (v) o0 (c0 o1 c1) - Not possible.
31900 exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
31901 return error_node();
31902 }
31903 };
31904
31905 struct synthesize_vovovov_expression0
31906 {
31907 typedef typename vovovov_t::type0 node_type;
31908 typedef typename vovovov_t::sf4_type sf4_type;
31909 typedef typename node_type::T0 T0;
31910 typedef typename node_type::T1 T1;
31911 typedef typename node_type::T2 T2;
31912 typedef typename node_type::T3 T3;
31913
31914 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31915 const details::operator_type& operation,
31916 expression_node_ptr (&branch)[2])
31917 {
31918 // (v0 o0 v1) o1 (v2 o2 v3)
31919 const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
31920 const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
31921 const Type& v0 = vov0->v0();
31922 const Type& v1 = vov0->v1();
31923 const Type& v2 = vov1->v0();
31924 const Type& v3 = vov1->v1();
31925 const details::operator_type o0 = vov0->operation();
31926 const details::operator_type o1 = operation;
31927 const details::operator_type o2 = vov1->operation();
31928
31929 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31930 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31931 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31932
31933 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31934 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31935
31936 expression_node_ptr result = error_node();
31937
31938 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31939 {
31940 // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
31941 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31942 {
31943 const bool synthesis_result =
31944 synthesize_sf4ext_expression::
31945 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
31946
31947 exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
31948
31949 return (synthesis_result) ? result : error_node();
31950 }
31951 // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
31952 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31953 {
31954 const bool synthesis_result =
31955 synthesize_sf4ext_expression::
31956 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
31957
31958 exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
31959
31960 return (synthesis_result) ? result : error_node();
31961 }
31962 // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31963 else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
31964 {
31965 const bool synthesis_result =
31966 synthesize_sf4ext_expression::
31967 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
31968
31969 exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
31970
31971 return (synthesis_result) ? result : error_node();
31972 }
31973 // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31974 else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
31975 {
31976 const bool synthesis_result =
31977 synthesize_sf4ext_expression::
31978 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
31979
31980 exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
31981
31982 return (synthesis_result) ? result : error_node();
31983 }
31984 // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
31985 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31986 {
31987 const bool synthesis_result =
31988 synthesize_sf4ext_expression::
31989 template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
31990
31991 exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
31992
31993 return (synthesis_result) ? result : error_node();
31994 }
31995 }
31996
31997 const bool synthesis_result =
31998 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31999 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32000
32001 if (synthesis_result)
32002 return result;
32003 else if (!expr_gen.valid_operator(o0,f0))
32004 return error_node();
32005 else if (!expr_gen.valid_operator(o1,f1))
32006 return error_node();
32007 else if (!expr_gen.valid_operator(o2,f2))
32008 return error_node();
32009 else
32010 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32011 }
32012
32013 static inline std::string id(expression_generator<Type>& expr_gen,
32014 const details::operator_type o0,
32015 const details::operator_type o1,
32016 const details::operator_type o2)
32017 {
32018 return details::build_string()
32019 << "(t" << expr_gen.to_str(o0)
32020 << "t)" << expr_gen.to_str(o1)
32021 << "(t" << expr_gen.to_str(o2)
32022 << "t)";
32023 }
32024 };
32025
32026 struct synthesize_vovovoc_expression0
32027 {
32028 typedef typename vovovoc_t::type0 node_type;
32029 typedef typename vovovoc_t::sf4_type sf4_type;
32030 typedef typename node_type::T0 T0;
32031 typedef typename node_type::T1 T1;
32032 typedef typename node_type::T2 T2;
32033 typedef typename node_type::T3 T3;
32034
32035 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32036 const details::operator_type& operation,
32037 expression_node_ptr (&branch)[2])
32038 {
32039 // (v0 o0 v1) o1 (v2 o2 c)
32040 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
32041 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
32042 const Type& v0 = vov->v0();
32043 const Type& v1 = vov->v1();
32044 const Type& v2 = voc->v ();
32045 const Type c = voc->c ();
32046 const details::operator_type o0 = vov->operation();
32047 const details::operator_type o1 = operation;
32048 const details::operator_type o2 = voc->operation();
32049
32050 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32051 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32052 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32053
32054 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32055 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32056
32057 expression_node_ptr result = error_node();
32058
32059 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32060 {
32061 // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
32062 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32063 {
32064 const bool synthesis_result =
32065 synthesize_sf4ext_expression::
32066 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
32067
32068 exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
32069
32070 return (synthesis_result) ? result : error_node();
32071 }
32072 // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
32073 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32074 {
32075 const bool synthesis_result =
32076 synthesize_sf4ext_expression::
32077 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
32078
32079 exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
32080
32081 return (synthesis_result) ? result : error_node();
32082 }
32083 }
32084
32085 const bool synthesis_result =
32086 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32087 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32088
32089 if (synthesis_result)
32090 return result;
32091 else if (!expr_gen.valid_operator(o0,f0))
32092 return error_node();
32093 else if (!expr_gen.valid_operator(o1,f1))
32094 return error_node();
32095 else if (!expr_gen.valid_operator(o2,f2))
32096 return error_node();
32097 else
32098 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32099 }
32100
32101 static inline std::string id(expression_generator<Type>& expr_gen,
32102 const details::operator_type o0,
32103 const details::operator_type o1,
32104 const details::operator_type o2)
32105 {
32106 return details::build_string()
32107 << "(t" << expr_gen.to_str(o0)
32108 << "t)" << expr_gen.to_str(o1)
32109 << "(t" << expr_gen.to_str(o2)
32110 << "t)";
32111 }
32112 };
32113
32114 struct synthesize_vovocov_expression0
32115 {
32116 typedef typename vovocov_t::type0 node_type;
32117 typedef typename vovocov_t::sf4_type sf4_type;
32118 typedef typename node_type::T0 T0;
32119 typedef typename node_type::T1 T1;
32120 typedef typename node_type::T2 T2;
32121 typedef typename node_type::T3 T3;
32122
32123 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32124 const details::operator_type& operation,
32125 expression_node_ptr (&branch)[2])
32126 {
32127 // (v0 o0 v1) o1 (c o2 v2)
32128 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
32129 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
32130 const Type& v0 = vov->v0();
32131 const Type& v1 = vov->v1();
32132 const Type& v2 = cov->v ();
32133 const Type c = cov->c ();
32134 const details::operator_type o0 = vov->operation();
32135 const details::operator_type o1 = operation;
32136 const details::operator_type o2 = cov->operation();
32137
32138 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32139 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32140 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32141
32142 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32143 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32144
32145 expression_node_ptr result = error_node();
32146
32147 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32148 {
32149 // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
32150 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32151 {
32152 const bool synthesis_result =
32153 synthesize_sf4ext_expression::
32154 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
32155
32156 exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
32157
32158 return (synthesis_result) ? result : error_node();
32159 }
32160 // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
32161 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32162 {
32163 const bool synthesis_result =
32164 synthesize_sf4ext_expression::
32165 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
32166
32167 exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
32168
32169 return (synthesis_result) ? result : error_node();
32170 }
32171 }
32172
32173 const bool synthesis_result =
32174 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32175 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32176
32177 if (synthesis_result)
32178 return result;
32179 else if (!expr_gen.valid_operator(o0,f0))
32180 return error_node();
32181 else if (!expr_gen.valid_operator(o1,f1))
32182 return error_node();
32183 else if (!expr_gen.valid_operator(o2,f2))
32184 return error_node();
32185 else
32186 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32187 }
32188
32189 static inline std::string id(expression_generator<Type>& expr_gen,
32190 const details::operator_type o0,
32191 const details::operator_type o1,
32192 const details::operator_type o2)
32193 {
32194 return details::build_string()
32195 << "(t" << expr_gen.to_str(o0)
32196 << "t)" << expr_gen.to_str(o1)
32197 << "(t" << expr_gen.to_str(o2)
32198 << "t)";
32199 }
32200 };
32201
32202 struct synthesize_vocovov_expression0
32203 {
32204 typedef typename vocovov_t::type0 node_type;
32205 typedef typename vocovov_t::sf4_type sf4_type;
32206 typedef typename node_type::T0 T0;
32207 typedef typename node_type::T1 T1;
32208 typedef typename node_type::T2 T2;
32209 typedef typename node_type::T3 T3;
32210
32211 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32212 const details::operator_type& operation,
32213 expression_node_ptr (&branch)[2])
32214 {
32215 // (v0 o0 c) o1 (v1 o2 v2)
32216 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
32217 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
32218 const Type c = voc->c ();
32219 const Type& v0 = voc->v ();
32220 const Type& v1 = vov->v0();
32221 const Type& v2 = vov->v1();
32222 const details::operator_type o0 = voc->operation();
32223 const details::operator_type o1 = operation;
32224 const details::operator_type o2 = vov->operation();
32225
32226 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32227 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32228 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32229
32230 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32231 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32232
32233 expression_node_ptr result = error_node();
32234
32235 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32236 {
32237 // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
32238 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32239 {
32240 const bool synthesis_result =
32241 synthesize_sf4ext_expression::
32242 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
32243
32244 exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
32245
32246 return (synthesis_result) ? result : error_node();
32247 }
32248 // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
32249 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32250 {
32251 const bool synthesis_result =
32252 synthesize_sf4ext_expression::
32253 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
32254
32255 exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
32256
32257 return (synthesis_result) ? result : error_node();
32258 }
32259 }
32260
32261 const bool synthesis_result =
32262 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32263 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32264
32265 if (synthesis_result)
32266 return result;
32267 else if (!expr_gen.valid_operator(o0,f0))
32268 return error_node();
32269 else if (!expr_gen.valid_operator(o1,f1))
32270 return error_node();
32271 else if (!expr_gen.valid_operator(o2,f2))
32272 return error_node();
32273 else
32274 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32275 }
32276
32277 static inline std::string id(expression_generator<Type>& expr_gen,
32278 const details::operator_type o0,
32279 const details::operator_type o1,
32280 const details::operator_type o2)
32281 {
32282 return details::build_string()
32283 << "(t" << expr_gen.to_str(o0)
32284 << "t)" << expr_gen.to_str(o1)
32285 << "(t" << expr_gen.to_str(o2)
32286 << "t)";
32287 }
32288 };
32289
32290 struct synthesize_covovov_expression0
32291 {
32292 typedef typename covovov_t::type0 node_type;
32293 typedef typename covovov_t::sf4_type sf4_type;
32294 typedef typename node_type::T0 T0;
32295 typedef typename node_type::T1 T1;
32296 typedef typename node_type::T2 T2;
32297 typedef typename node_type::T3 T3;
32298
32299 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32300 const details::operator_type& operation,
32301 expression_node_ptr (&branch)[2])
32302 {
32303 // (c o0 v0) o1 (v1 o2 v2)
32304 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
32305 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
32306 const Type c = cov->c ();
32307 const Type& v0 = cov->v ();
32308 const Type& v1 = vov->v0();
32309 const Type& v2 = vov->v1();
32310 const details::operator_type o0 = cov->operation();
32311 const details::operator_type o1 = operation;
32312 const details::operator_type o2 = vov->operation();
32313
32314 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32315 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32316 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32317
32318 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32319 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32320
32321 expression_node_ptr result = error_node();
32322
32323 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32324 {
32325 // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
32326 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32327 {
32328 const bool synthesis_result =
32329 synthesize_sf4ext_expression::
32330 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
32331
32332 exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
32333
32334 return (synthesis_result) ? result : error_node();
32335 }
32336 // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
32337 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32338 {
32339 const bool synthesis_result =
32340 synthesize_sf4ext_expression::
32341 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
32342
32343 exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
32344
32345 return (synthesis_result) ? result : error_node();
32346 }
32347 }
32348
32349 const bool synthesis_result =
32350 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32351 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32352
32353 if (synthesis_result)
32354 return result;
32355 else if (!expr_gen.valid_operator(o0,f0))
32356 return error_node();
32357 else if (!expr_gen.valid_operator(o1,f1))
32358 return error_node();
32359 else if (!expr_gen.valid_operator(o2,f2))
32360 return error_node();
32361 else
32362 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32363 }
32364
32365 static inline std::string id(expression_generator<Type>& expr_gen,
32366 const details::operator_type o0,
32367 const details::operator_type o1,
32368 const details::operator_type o2)
32369 {
32370 return details::build_string()
32371 << "(t" << expr_gen.to_str(o0)
32372 << "t)" << expr_gen.to_str(o1)
32373 << "(t" << expr_gen.to_str(o2)
32374 << "t)";
32375 }
32376 };
32377
32378 struct synthesize_covocov_expression0
32379 {
32380 typedef typename covocov_t::type0 node_type;
32381 typedef typename covocov_t::sf4_type sf4_type;
32382 typedef typename node_type::T0 T0;
32383 typedef typename node_type::T1 T1;
32384 typedef typename node_type::T2 T2;
32385 typedef typename node_type::T3 T3;
32386
32387 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32388 const details::operator_type& operation,
32389 expression_node_ptr (&branch)[2])
32390 {
32391 // (c0 o0 v0) o1 (c1 o2 v1)
32392 const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
32393 const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
32394 const Type c0 = cov0->c();
32395 const Type& v0 = cov0->v();
32396 const Type c1 = cov1->c();
32397 const Type& v1 = cov1->v();
32398 const details::operator_type o0 = cov0->operation();
32399 const details::operator_type o1 = operation;
32400 const details::operator_type o2 = cov1->operation();
32401
32402 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32403 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32404 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32405
32406 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32407 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32408
32409 expression_node_ptr result = error_node();
32410
32411 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32412 {
32413 // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
32414 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32415 {
32416 const bool synthesis_result =
32417 synthesize_sf3ext_expression::
32418 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32419
32420 exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
32421
32422 return (synthesis_result) ? result : error_node();
32423 }
32424 // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32425 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32426 {
32427 const bool synthesis_result =
32428 synthesize_sf3ext_expression::
32429 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32430
32431 exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32432
32433 return (synthesis_result) ? result : error_node();
32434 }
32435 // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
32436 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32437 {
32438 const bool synthesis_result =
32439 synthesize_sf3ext_expression::
32440 template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
32441
32442 exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
32443
32444 return (synthesis_result) ? result : error_node();
32445 }
32446 // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32447 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32448 {
32449 const bool synthesis_result =
32450 synthesize_sf3ext_expression::
32451 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32452
32453 exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32454
32455 return (synthesis_result) ? result : error_node();
32456 }
32457 // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
32458 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32459 {
32460 const bool synthesis_result =
32461 synthesize_sf3ext_expression::
32462 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32463
32464 exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32465
32466 return (synthesis_result) ? result : error_node();
32467 }
32468 // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
32469 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32470 {
32471 const bool synthesis_result =
32472 synthesize_sf3ext_expression::
32473 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
32474
32475 exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
32476
32477 return (synthesis_result) ? result : error_node();
32478 }
32479 // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
32480 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32481 {
32482 const bool synthesis_result =
32483 synthesize_sf3ext_expression::
32484 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
32485
32486 exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
32487
32488 return (synthesis_result) ? result : error_node();
32489 }
32490 // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32491 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32492 {
32493 const bool synthesis_result =
32494 synthesize_sf3ext_expression::
32495 template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
32496
32497 exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32498
32499 return (synthesis_result) ? result : error_node();
32500 }
32501 // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
32502 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32503 {
32504 const bool synthesis_result =
32505 synthesize_sf3ext_expression::
32506 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
32507
32508 exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
32509
32510 return (synthesis_result) ? result : error_node();
32511 }
32512 // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32513 else if (
32514 (std::equal_to<T>()(c0,c1)) &&
32515 (details::e_mul == o0) &&
32516 (details::e_mul == o2) &&
32517 (
32518 (details::e_add == o1) ||
32519 (details::e_sub == o1)
32520 )
32521 )
32522 {
32523 std::string specfunc;
32524
32525 switch (o1)
32526 {
32527 case details::e_add : specfunc = "t*(t+t)"; break;
32528 case details::e_sub : specfunc = "t*(t-t)"; break;
32529 default : return error_node();
32530 }
32531
32532 const bool synthesis_result =
32533 synthesize_sf3ext_expression::
32534 template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
32535
32536 exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32537
32538 return (synthesis_result) ? result : error_node();
32539 }
32540 }
32541
32542 const bool synthesis_result =
32543 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32544 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32545
32546 if (synthesis_result)
32547 return result;
32548 else if (!expr_gen.valid_operator(o0,f0))
32549 return error_node();
32550 else if (!expr_gen.valid_operator(o1,f1))
32551 return error_node();
32552 else if (!expr_gen.valid_operator(o2,f2))
32553 return error_node();
32554 else
32555 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32556 }
32557
32558 static inline std::string id(expression_generator<Type>& expr_gen,
32559 const details::operator_type o0,
32560 const details::operator_type o1,
32561 const details::operator_type o2)
32562 {
32563 return details::build_string()
32564 << "(t" << expr_gen.to_str(o0)
32565 << "t)" << expr_gen.to_str(o1)
32566 << "(t" << expr_gen.to_str(o2)
32567 << "t)";
32568 }
32569 };
32570
32571 struct synthesize_vocovoc_expression0
32572 {
32573 typedef typename vocovoc_t::type0 node_type;
32574 typedef typename vocovoc_t::sf4_type sf4_type;
32575 typedef typename node_type::T0 T0;
32576 typedef typename node_type::T1 T1;
32577 typedef typename node_type::T2 T2;
32578 typedef typename node_type::T3 T3;
32579
32580 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32581 const details::operator_type& operation,
32582 expression_node_ptr (&branch)[2])
32583 {
32584 // (v0 o0 c0) o1 (v1 o2 c1)
32585 const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
32586 const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
32587 const Type c0 = voc0->c();
32588 const Type& v0 = voc0->v();
32589 const Type c1 = voc1->c();
32590 const Type& v1 = voc1->v();
32591 const details::operator_type o0 = voc0->operation();
32592 const details::operator_type o1 = operation;
32593 const details::operator_type o2 = voc1->operation();
32594
32595 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32596 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32597 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32598
32599 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32600 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32601
32602 expression_node_ptr result = error_node();
32603
32604 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32605 {
32606 // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
32607 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32608 {
32609 const bool synthesis_result =
32610 synthesize_sf3ext_expression::
32611 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32612
32613 exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
32614
32615 return (synthesis_result) ? result : error_node();
32616 }
32617 // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
32618 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32619 {
32620 const bool synthesis_result =
32621 synthesize_sf3ext_expression::
32622 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32623
32624 exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
32625
32626 return (synthesis_result) ? result : error_node();
32627 }
32628 // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
32629 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32630 {
32631 const bool synthesis_result =
32632 synthesize_sf3ext_expression::
32633 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
32634
32635 exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
32636
32637 return (synthesis_result) ? result : error_node();
32638 }
32639 // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
32640 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32641 {
32642 const bool synthesis_result =
32643 synthesize_sf3ext_expression::
32644 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32645
32646 exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
32647
32648 return (synthesis_result) ? result : error_node();
32649 }
32650 // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
32651 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32652 {
32653 const bool synthesis_result =
32654 synthesize_sf3ext_expression::
32655 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32656
32657 exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32658
32659 return (synthesis_result) ? result : error_node();
32660 }
32661 // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
32662 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32663 {
32664 const bool synthesis_result =
32665 synthesize_sf3ext_expression::
32666 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
32667
32668 exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
32669
32670 return (synthesis_result) ? result : error_node();
32671 }
32672 // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
32673 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32674 {
32675 const bool synthesis_result =
32676 synthesize_sf3ext_expression::
32677 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32678
32679 exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
32680
32681 return (synthesis_result) ? result : error_node();
32682 }
32683 // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
32684 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32685 {
32686 const bool synthesis_result =
32687 synthesize_sf3ext_expression::
32688 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
32689
32690 exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
32691
32692 return (synthesis_result) ? result : error_node();
32693 }
32694 // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
32695 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32696 {
32697 const bool synthesis_result =
32698 synthesize_sf3ext_expression::
32699 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
32700
32701 exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
32702
32703 return (synthesis_result) ? result : error_node();
32704 }
32705 // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
32706 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
32707 {
32708 const bool synthesis_result =
32709 synthesize_sf4ext_expression::
32710 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
32711
32712 exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
32713
32714 return (synthesis_result) ? result : error_node();
32715 }
32716 // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
32717 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
32718 {
32719 const bool synthesis_result =
32720 synthesize_sf4ext_expression::
32721 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
32722
32723 exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
32724
32725 return (synthesis_result) ? result : error_node();
32726 }
32727 // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
32728 else if (
32729 (std::equal_to<T>()(c0,c1)) &&
32730 (details::e_mul == o0) &&
32731 (details::e_mul == o2) &&
32732 (
32733 (details::e_add == o1) ||
32734 (details::e_sub == o1)
32735 )
32736 )
32737 {
32738 std::string specfunc;
32739
32740 switch (o1)
32741 {
32742 case details::e_add : specfunc = "t*(t+t)"; break;
32743 case details::e_sub : specfunc = "t*(t-t)"; break;
32744 default : return error_node();
32745 }
32746
32747 const bool synthesis_result =
32748 synthesize_sf3ext_expression::
32749 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32750
32751 exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32752
32753 return (synthesis_result) ? result : error_node();
32754 }
32755 // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
32756 else if (
32757 (std::equal_to<T>()(c0,c1)) &&
32758 (details::e_div == o0) &&
32759 (details::e_div == o2) &&
32760 (
32761 (details::e_add == o1) ||
32762 (details::e_sub == o1)
32763 )
32764 )
32765 {
32766 std::string specfunc;
32767
32768 switch (o1)
32769 {
32770 case details::e_add : specfunc = "(t+t)/t"; break;
32771 case details::e_sub : specfunc = "(t-t)/t"; break;
32772 default : return error_node();
32773 }
32774
32775 const bool synthesis_result =
32776 synthesize_sf3ext_expression::
32777 template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
32778
32779 exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
32780
32781 return (synthesis_result) ? result : error_node();
32782 }
32783 }
32784
32785 const bool synthesis_result =
32786 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32787 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32788
32789 if (synthesis_result)
32790 return result;
32791 else if (!expr_gen.valid_operator(o0,f0))
32792 return error_node();
32793 else if (!expr_gen.valid_operator(o1,f1))
32794 return error_node();
32795 else if (!expr_gen.valid_operator(o2,f2))
32796 return error_node();
32797 else
32798 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32799 }
32800
32801 static inline std::string id(expression_generator<Type>& expr_gen,
32802 const details::operator_type o0,
32803 const details::operator_type o1,
32804 const details::operator_type o2)
32805 {
32806 return details::build_string()
32807 << "(t" << expr_gen.to_str(o0)
32808 << "t)" << expr_gen.to_str(o1)
32809 << "(t" << expr_gen.to_str(o2)
32810 << "t)";
32811 }
32812 };
32813
32814 struct synthesize_covovoc_expression0
32815 {
32816 typedef typename covovoc_t::type0 node_type;
32817 typedef typename covovoc_t::sf4_type sf4_type;
32818 typedef typename node_type::T0 T0;
32819 typedef typename node_type::T1 T1;
32820 typedef typename node_type::T2 T2;
32821 typedef typename node_type::T3 T3;
32822
32823 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32824 const details::operator_type& operation,
32825 expression_node_ptr (&branch)[2])
32826 {
32827 // (c0 o0 v0) o1 (v1 o2 c1)
32828 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
32829 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
32830 const Type c0 = cov->c();
32831 const Type& v0 = cov->v();
32832 const Type c1 = voc->c();
32833 const Type& v1 = voc->v();
32834 const details::operator_type o0 = cov->operation();
32835 const details::operator_type o1 = operation;
32836 const details::operator_type o2 = voc->operation();
32837
32838 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32839 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32840 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32841
32842 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32843 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32844
32845 expression_node_ptr result = error_node();
32846
32847 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32848 {
32849 // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
32850 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32851 {
32852 const bool synthesis_result =
32853 synthesize_sf3ext_expression::
32854 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32855
32856 exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
32857
32858 return (synthesis_result) ? result : error_node();
32859 }
32860 // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
32861 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32862 {
32863 const bool synthesis_result =
32864 synthesize_sf3ext_expression::
32865 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32866
32867 exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
32868
32869 return (synthesis_result) ? result : error_node();
32870 }
32871 // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
32872 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32873 {
32874 const bool synthesis_result =
32875 synthesize_sf3ext_expression::
32876 template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
32877
32878 exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
32879
32880 return (synthesis_result) ? result : error_node();
32881 }
32882 // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
32883 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32884 {
32885 const bool synthesis_result =
32886 synthesize_sf3ext_expression::
32887 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32888
32889 exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
32890
32891 return (synthesis_result) ? result : error_node();
32892 }
32893 // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
32894 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32895 {
32896 const bool synthesis_result =
32897 synthesize_sf3ext_expression::
32898 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32899
32900 exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32901
32902 return (synthesis_result) ? result : error_node();
32903 }
32904 // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
32905 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32906 {
32907 const bool synthesis_result =
32908 synthesize_sf3ext_expression::
32909 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
32910
32911 exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
32912
32913 return (synthesis_result) ? result : error_node();
32914 }
32915 // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
32916 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32917 {
32918 const bool synthesis_result =
32919 synthesize_sf3ext_expression::
32920 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
32921
32922 exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
32923
32924 return (synthesis_result) ? result : error_node();
32925 }
32926 // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
32927 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32928 {
32929 const bool synthesis_result =
32930 synthesize_sf3ext_expression::
32931 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
32932
32933 exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
32934
32935 return (synthesis_result) ? result : error_node();
32936 }
32937 // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
32938 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32939 {
32940 const bool synthesis_result =
32941 synthesize_sf3ext_expression::
32942 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
32943
32944 exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
32945
32946 return (synthesis_result) ? result : error_node();
32947 }
32948 // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
32949 else if (
32950 (std::equal_to<T>()(c0,c1)) &&
32951 (details::e_mul == o0) &&
32952 (details::e_mul == o2) &&
32953 (
32954 (details::e_add == o1) ||
32955 (details::e_sub == o1)
32956 )
32957 )
32958 {
32959 std::string specfunc;
32960
32961 switch (o1)
32962 {
32963 case details::e_add : specfunc = "t*(t+t)"; break;
32964 case details::e_sub : specfunc = "t*(t-t)"; break;
32965 default : return error_node();
32966 }
32967
32968 const bool synthesis_result =
32969 synthesize_sf3ext_expression::
32970 template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
32971
32972 exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32973
32974 return (synthesis_result) ? result : error_node();
32975 }
32976 }
32977
32978 const bool synthesis_result =
32979 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32980 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32981
32982 if (synthesis_result)
32983 return result;
32984 else if (!expr_gen.valid_operator(o0,f0))
32985 return error_node();
32986 else if (!expr_gen.valid_operator(o1,f1))
32987 return error_node();
32988 else if (!expr_gen.valid_operator(o2,f2))
32989 return error_node();
32990 else
32991 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32992 }
32993
32994 static inline std::string id(expression_generator<Type>& expr_gen,
32995 const details::operator_type o0,
32996 const details::operator_type o1,
32997 const details::operator_type o2)
32998 {
32999 return details::build_string()
33000 << "(t" << expr_gen.to_str(o0)
33001 << "t)" << expr_gen.to_str(o1)
33002 << "(t" << expr_gen.to_str(o2)
33003 << "t)";
33004 }
33005 };
33006
33007 struct synthesize_vococov_expression0
33008 {
33009 typedef typename vococov_t::type0 node_type;
33010 typedef typename vococov_t::sf4_type sf4_type;
33011 typedef typename node_type::T0 T0;
33012 typedef typename node_type::T1 T1;
33013 typedef typename node_type::T2 T2;
33014 typedef typename node_type::T3 T3;
33015
33016 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33017 const details::operator_type& operation,
33018 expression_node_ptr (&branch)[2])
33019 {
33020 // (v0 o0 c0) o1 (c1 o2 v1)
33021 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
33022 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
33023 const Type c0 = voc->c();
33024 const Type& v0 = voc->v();
33025 const Type c1 = cov->c();
33026 const Type& v1 = cov->v();
33027 const details::operator_type o0 = voc->operation();
33028 const details::operator_type o1 = operation;
33029 const details::operator_type o2 = cov->operation();
33030
33031 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33032 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
33033 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33034
33035 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33036 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33037
33038 expression_node_ptr result = error_node();
33039
33040 if (expr_gen.parser_->settings_.strength_reduction_enabled())
33041 {
33042 // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
33043 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
33044 {
33045 const bool synthesis_result =
33046 synthesize_sf3ext_expression::
33047 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
33048
33049 exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
33050
33051 return (synthesis_result) ? result : error_node();
33052 }
33053 // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
33054 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
33055 {
33056 const bool synthesis_result =
33057 synthesize_sf3ext_expression::
33058 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
33059
33060 exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
33061
33062 return (synthesis_result) ? result : error_node();
33063 }
33064 // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
33065 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
33066 {
33067 const bool synthesis_result =
33068 synthesize_sf3ext_expression::
33069 template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
33070
33071 exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
33072
33073 return (synthesis_result) ? result : error_node();
33074 }
33075 // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
33076 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
33077 {
33078 const bool synthesis_result =
33079 synthesize_sf3ext_expression::
33080 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
33081
33082 exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
33083
33084 return (synthesis_result) ? result : error_node();
33085 }
33086 // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
33087 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
33088 {
33089 const bool synthesis_result =
33090 synthesize_sf3ext_expression::
33091 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
33092
33093 exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
33094
33095 return (synthesis_result) ? result : error_node();
33096 }
33097 // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
33098 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
33099 {
33100 const bool synthesis_result =
33101 synthesize_sf3ext_expression::
33102 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
33103
33104 exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
33105
33106 return (synthesis_result) ? result : error_node();
33107 }
33108 // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
33109 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
33110 {
33111 const bool synthesis_result =
33112 synthesize_sf3ext_expression::
33113 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
33114
33115 exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
33116
33117 return (synthesis_result) ? result : error_node();
33118 }
33119 // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
33120 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
33121 {
33122 const bool synthesis_result =
33123 synthesize_sf3ext_expression::
33124 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
33125
33126 exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
33127
33128 return (synthesis_result) ? result : error_node();
33129 }
33130 // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
33131 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
33132 {
33133 const bool synthesis_result =
33134 synthesize_sf3ext_expression::
33135 template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
33136
33137 exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
33138
33139 return (synthesis_result) ? result : error_node();
33140 }
33141 // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
33142 else if (
33143 (std::equal_to<T>()(c0,c1)) &&
33144 (details::e_mul == o0) &&
33145 (details::e_mul == o2) &&
33146 (
33147 (details::e_add == o1) || (details::e_sub == o1)
33148 )
33149 )
33150 {
33151 std::string specfunc;
33152
33153 switch (o1)
33154 {
33155 case details::e_add : specfunc = "t*(t+t)"; break;
33156 case details::e_sub : specfunc = "t*(t-t)"; break;
33157 default : return error_node();
33158 }
33159
33160 const bool synthesis_result =
33161 synthesize_sf3ext_expression::
33162 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
33163
33164 exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
33165
33166 return (synthesis_result) ? result : error_node();
33167 }
33168 }
33169
33170 const bool synthesis_result =
33171 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33172 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33173
33174 if (synthesis_result)
33175 return result;
33176 else if (!expr_gen.valid_operator(o0,f0))
33177 return error_node();
33178 else if (!expr_gen.valid_operator(o1,f1))
33179 return error_node();
33180 else if (!expr_gen.valid_operator(o2,f2))
33181 return error_node();
33182 else
33183 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33184 }
33185
33186 static inline std::string id(expression_generator<Type>& expr_gen,
33187 const details::operator_type o0,
33188 const details::operator_type o1,
33189 const details::operator_type o2)
33190 {
33191 return details::build_string()
33192 << "(t" << expr_gen.to_str(o0)
33193 << "t)" << expr_gen.to_str(o1)
33194 << "(t" << expr_gen.to_str(o2)
33195 << "t)";
33196 }
33197 };
33198
33199 struct synthesize_vovovov_expression1
33200 {
33201 typedef typename vovovov_t::type1 node_type;
33202 typedef typename vovovov_t::sf4_type sf4_type;
33203 typedef typename node_type::T0 T0;
33204 typedef typename node_type::T1 T1;
33205 typedef typename node_type::T2 T2;
33206 typedef typename node_type::T3 T3;
33207
33208 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33209 const details::operator_type& operation,
33210 expression_node_ptr (&branch)[2])
33211 {
33212 // v0 o0 (v1 o1 (v2 o2 v3))
33213 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33214
33215 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33216 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33217 const Type& v1 = vovov->t0();
33218 const Type& v2 = vovov->t1();
33219 const Type& v3 = vovov->t2();
33220 const details::operator_type o0 = operation;
33221 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33222 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33223
33224 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33225 binary_functor_t f1 = vovov->f0();
33226 binary_functor_t f2 = vovov->f1();
33227
33228 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33229
33230 expression_node_ptr result = error_node();
33231
33232 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
33233 return result;
33234 else if (!expr_gen.valid_operator(o0,f0))
33235 return error_node();
33236
33237 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
33238
33239 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
33240 }
33241
33242 static inline std::string id(expression_generator<Type>& expr_gen,
33243 const details::operator_type o0,
33244 const details::operator_type o1,
33245 const details::operator_type o2)
33246 {
33247 return details::build_string()
33248 << "t" << expr_gen.to_str(o0)
33249 << "(t" << expr_gen.to_str(o1)
33250 << "(t" << expr_gen.to_str(o2)
33251 << "t))";
33252 }
33253 };
33254
33255 struct synthesize_vovovoc_expression1
33256 {
33257 typedef typename vovovoc_t::type1 node_type;
33258 typedef typename vovovoc_t::sf4_type sf4_type;
33259 typedef typename node_type::T0 T0;
33260 typedef typename node_type::T1 T1;
33261 typedef typename node_type::T2 T2;
33262 typedef typename node_type::T3 T3;
33263
33264 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33265 const details::operator_type& operation,
33266 expression_node_ptr (&branch)[2])
33267 {
33268 // v0 o0 (v1 o1 (v2 o2 c))
33269 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33270
33271 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33272 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33273 const Type& v1 = vovoc->t0();
33274 const Type& v2 = vovoc->t1();
33275 const Type c = vovoc->t2();
33276 const details::operator_type o0 = operation;
33277 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33278 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33279
33280 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33281 binary_functor_t f1 = vovoc->f0();
33282 binary_functor_t f2 = vovoc->f1();
33283
33284 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33285
33286 expression_node_ptr result = error_node();
33287
33288 const bool synthesis_result =
33289 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33290 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33291
33292 if (synthesis_result)
33293 return result;
33294 else if (!expr_gen.valid_operator(o0,f0))
33295 return error_node();
33296
33297 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
33298
33299 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33300 }
33301
33302 static inline std::string id(expression_generator<Type>& expr_gen,
33303 const details::operator_type o0,
33304 const details::operator_type o1,
33305 const details::operator_type o2)
33306 {
33307 return details::build_string()
33308 << "t" << expr_gen.to_str(o0)
33309 << "(t" << expr_gen.to_str(o1)
33310 << "(t" << expr_gen.to_str(o2)
33311 << "t))";
33312 }
33313 };
33314
33315 struct synthesize_vovocov_expression1
33316 {
33317 typedef typename vovocov_t::type1 node_type;
33318 typedef typename vovocov_t::sf4_type sf4_type;
33319 typedef typename node_type::T0 T0;
33320 typedef typename node_type::T1 T1;
33321 typedef typename node_type::T2 T2;
33322 typedef typename node_type::T3 T3;
33323
33324 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33325 const details::operator_type& operation,
33326 expression_node_ptr (&branch)[2])
33327 {
33328 // v0 o0 (v1 o1 (c o2 v2))
33329 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
33330
33331 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33332 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33333 const Type& v1 = vocov->t0();
33334 const Type c = vocov->t1();
33335 const Type& v2 = vocov->t2();
33336 const details::operator_type o0 = operation;
33337 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33338 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33339
33340 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33341 binary_functor_t f1 = vocov->f0();
33342 binary_functor_t f2 = vocov->f1();
33343
33344 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33345
33346 expression_node_ptr result = error_node();
33347
33348 const bool synthesis_result =
33349 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33350 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33351
33352 if (synthesis_result)
33353 return result;
33354 if (!expr_gen.valid_operator(o0,f0))
33355 return error_node();
33356
33357 exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
33358
33359 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33360 }
33361
33362 static inline std::string id(expression_generator<Type>& expr_gen,
33363 const details::operator_type o0,
33364 const details::operator_type o1,
33365 const details::operator_type o2)
33366 {
33367 return details::build_string()
33368 << "t" << expr_gen.to_str(o0)
33369 << "(t" << expr_gen.to_str(o1)
33370 << "(t" << expr_gen.to_str(o2)
33371 << "t))";
33372 }
33373 };
33374
33375 struct synthesize_vocovov_expression1
33376 {
33377 typedef typename vocovov_t::type1 node_type;
33378 typedef typename vocovov_t::sf4_type sf4_type;
33379 typedef typename node_type::T0 T0;
33380 typedef typename node_type::T1 T1;
33381 typedef typename node_type::T2 T2;
33382 typedef typename node_type::T3 T3;
33383
33384 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33385 const details::operator_type& operation,
33386 expression_node_ptr (&branch)[2])
33387 {
33388 // v0 o0 (c o1 (v1 o2 v2))
33389 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
33390
33391 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
33392 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33393 const Type c = covov->t0();
33394 const Type& v1 = covov->t1();
33395 const Type& v2 = covov->t2();
33396 const details::operator_type o0 = operation;
33397 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
33398 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
33399
33400 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33401 binary_functor_t f1 = covov->f0();
33402 binary_functor_t f2 = covov->f1();
33403
33404 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33405
33406 expression_node_ptr result = error_node();
33407
33408 const bool synthesis_result =
33409 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33410 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33411
33412 if (synthesis_result)
33413 return result;
33414 else if (!expr_gen.valid_operator(o0,f0))
33415 return error_node();
33416
33417 exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
33418
33419 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33420 }
33421
33422 static inline std::string id(expression_generator<Type>& expr_gen,
33423 const details::operator_type o0,
33424 const details::operator_type o1,
33425 const details::operator_type o2)
33426 {
33427 return details::build_string()
33428 << "t" << expr_gen.to_str(o0)
33429 << "(t" << expr_gen.to_str(o1)
33430 << "(t" << expr_gen.to_str(o2)
33431 << "t))";
33432 }
33433 };
33434
33435 struct synthesize_covovov_expression1
33436 {
33437 typedef typename covovov_t::type1 node_type;
33438 typedef typename covovov_t::sf4_type sf4_type;
33439 typedef typename node_type::T0 T0;
33440 typedef typename node_type::T1 T1;
33441 typedef typename node_type::T2 T2;
33442 typedef typename node_type::T3 T3;
33443
33444 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33445 const details::operator_type& operation,
33446 expression_node_ptr (&branch)[2])
33447 {
33448 // c o0 (v0 o1 (v1 o2 v2))
33449 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33450
33451 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33452 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33453 const Type& v0 = vovov->t0();
33454 const Type& v1 = vovov->t1();
33455 const Type& v2 = vovov->t2();
33456 const details::operator_type o0 = operation;
33457 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33458 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33459
33460 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33461 binary_functor_t f1 = vovov->f0();
33462 binary_functor_t f2 = vovov->f1();
33463
33464 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33465 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33466
33467 expression_node_ptr result = error_node();
33468
33469 const bool synthesis_result =
33470 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33471 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33472
33473 if (synthesis_result)
33474 return result;
33475 if (!expr_gen.valid_operator(o0,f0))
33476 return error_node();
33477
33478 exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
33479
33480 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33481 }
33482
33483 static inline std::string id(expression_generator<Type>& expr_gen,
33484 const details::operator_type o0,
33485 const details::operator_type o1,
33486 const details::operator_type o2)
33487 {
33488 return details::build_string()
33489 << "t" << expr_gen.to_str(o0)
33490 << "(t" << expr_gen.to_str(o1)
33491 << "(t" << expr_gen.to_str(o2)
33492 << "t))";
33493 }
33494 };
33495
33496 struct synthesize_covocov_expression1
33497 {
33498 typedef typename covocov_t::type1 node_type;
33499 typedef typename covocov_t::sf4_type sf4_type;
33500 typedef typename node_type::T0 T0;
33501 typedef typename node_type::T1 T1;
33502 typedef typename node_type::T2 T2;
33503 typedef typename node_type::T3 T3;
33504
33505 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33506 const details::operator_type& operation,
33507 expression_node_ptr (&branch)[2])
33508 {
33509 // c0 o0 (v0 o1 (c1 o2 v1))
33510 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
33511
33512 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33513 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33514 const Type& v0 = vocov->t0();
33515 const Type c1 = vocov->t1();
33516 const Type& v1 = vocov->t2();
33517 const details::operator_type o0 = operation;
33518 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33519 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33520
33521 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33522 binary_functor_t f1 = vocov->f0();
33523 binary_functor_t f2 = vocov->f1();
33524
33525 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33526 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33527
33528 expression_node_ptr result = error_node();
33529
33530 const bool synthesis_result =
33531 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33532 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33533
33534 if (synthesis_result)
33535 return result;
33536 else if (!expr_gen.valid_operator(o0,f0))
33537 return error_node();
33538
33539 exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
33540
33541 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33542 }
33543
33544 static inline std::string id(expression_generator<Type>& expr_gen,
33545 const details::operator_type o0,
33546 const details::operator_type o1,
33547 const details::operator_type o2)
33548 {
33549 return details::build_string()
33550 << "t" << expr_gen.to_str(o0)
33551 << "(t" << expr_gen.to_str(o1)
33552 << "(t" << expr_gen.to_str(o2)
33553 << "t))";
33554 }
33555 };
33556
33557 struct synthesize_vocovoc_expression1
33558 {
33559 typedef typename vocovoc_t::type1 node_type;
33560 typedef typename vocovoc_t::sf4_type sf4_type;
33561 typedef typename node_type::T0 T0;
33562 typedef typename node_type::T1 T1;
33563 typedef typename node_type::T2 T2;
33564 typedef typename node_type::T3 T3;
33565
33566 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33567 const details::operator_type& operation,
33568 expression_node_ptr (&branch)[2])
33569 {
33570 // v0 o0 (c0 o1 (v1 o2 c2))
33571 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
33572
33573 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33574 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33575 const Type c0 = covoc->t0();
33576 const Type& v1 = covoc->t1();
33577 const Type c1 = covoc->t2();
33578 const details::operator_type o0 = operation;
33579 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33580 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33581
33582 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33583 binary_functor_t f1 = covoc->f0();
33584 binary_functor_t f2 = covoc->f1();
33585
33586 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33587
33588 expression_node_ptr result = error_node();
33589
33590 const bool synthesis_result =
33591 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33592 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33593
33594 if (synthesis_result)
33595 return result;
33596 else if (!expr_gen.valid_operator(o0,f0))
33597 return error_node();
33598
33599 exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
33600
33601 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33602 }
33603
33604 static inline std::string id(expression_generator<Type>& expr_gen,
33605 const details::operator_type o0,
33606 const details::operator_type o1,
33607 const details::operator_type o2)
33608 {
33609 return details::build_string()
33610 << "t" << expr_gen.to_str(o0)
33611 << "(t" << expr_gen.to_str(o1)
33612 << "(t" << expr_gen.to_str(o2)
33613 << "t))";
33614 }
33615 };
33616
33617 struct synthesize_covovoc_expression1
33618 {
33619 typedef typename covovoc_t::type1 node_type;
33620 typedef typename covovoc_t::sf4_type sf4_type;
33621 typedef typename node_type::T0 T0;
33622 typedef typename node_type::T1 T1;
33623 typedef typename node_type::T2 T2;
33624 typedef typename node_type::T3 T3;
33625 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33626 const details::operator_type& operation,
33627 expression_node_ptr (&branch)[2])
33628 {
33629 // c0 o0 (v0 o1 (v1 o2 c1))
33630 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33631
33632 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33633 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33634 const Type& v0 = vovoc->t0();
33635 const Type& v1 = vovoc->t1();
33636 const Type c1 = vovoc->t2();
33637 const details::operator_type o0 = operation;
33638 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33639 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33640
33641 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33642 binary_functor_t f1 = vovoc->f0();
33643 binary_functor_t f2 = vovoc->f1();
33644
33645 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33646 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33647
33648 expression_node_ptr result = error_node();
33649
33650 const bool synthesis_result =
33651 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33652 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33653
33654 if (synthesis_result)
33655 return result;
33656 else if (!expr_gen.valid_operator(o0,f0))
33657 return error_node();
33658
33659 exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
33660
33661 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33662 }
33663
33664 static inline std::string id(expression_generator<Type>& expr_gen,
33665 const details::operator_type o0,
33666 const details::operator_type o1,
33667 const details::operator_type o2)
33668 {
33669 return details::build_string()
33670 << "t" << expr_gen.to_str(o0)
33671 << "(t" << expr_gen.to_str(o1)
33672 << "(t" << expr_gen.to_str(o2)
33673 << "t))";
33674 }
33675 };
33676
33677 struct synthesize_vococov_expression1
33678 {
33679 typedef typename vococov_t::type1 node_type;
33680 typedef typename vococov_t::sf4_type sf4_type;
33681 typedef typename node_type::T0 T0;
33682 typedef typename node_type::T1 T1;
33683 typedef typename node_type::T2 T2;
33684 typedef typename node_type::T3 T3;
33685
33686 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33687 const details::operator_type& operation,
33688 expression_node_ptr (&branch)[2])
33689 {
33690 // v0 o0 (c0 o1 (c1 o2 v1))
33691 typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
33692
33693 const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
33694 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33695 const Type c0 = cocov->t0();
33696 const Type c1 = cocov->t1();
33697 const Type& v1 = cocov->t2();
33698 const details::operator_type o0 = operation;
33699 const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
33700 const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
33701
33702 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33703 binary_functor_t f1 = cocov->f0();
33704 binary_functor_t f2 = cocov->f1();
33705
33706 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33707
33708 expression_node_ptr result = error_node();
33709
33710 const bool synthesis_result =
33711 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33712 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33713
33714 if (synthesis_result)
33715 return result;
33716 else if (!expr_gen.valid_operator(o0,f0))
33717 return error_node();
33718
33719 exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
33720
33721 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33722 }
33723
33724 static inline std::string id(expression_generator<Type>& expr_gen,
33725 const details::operator_type o0,
33726 const details::operator_type o1,
33727 const details::operator_type o2)
33728 {
33729 return details::build_string()
33730 << "t" << expr_gen.to_str(o0)
33731 << "(t" << expr_gen.to_str(o1)
33732 << "(t" << expr_gen.to_str(o2)
33733 << "t))";
33734 }
33735 };
33736
33737 struct synthesize_vovovov_expression2
33738 {
33739 typedef typename vovovov_t::type2 node_type;
33740 typedef typename vovovov_t::sf4_type sf4_type;
33741 typedef typename node_type::T0 T0;
33742 typedef typename node_type::T1 T1;
33743 typedef typename node_type::T2 T2;
33744 typedef typename node_type::T3 T3;
33745
33746 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33747 const details::operator_type& operation,
33748 expression_node_ptr (&branch)[2])
33749 {
33750 // v0 o0 ((v1 o1 v2) o2 v3)
33751 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33752
33753 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33754 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33755 const Type& v1 = vovov->t0();
33756 const Type& v2 = vovov->t1();
33757 const Type& v3 = vovov->t2();
33758 const details::operator_type o0 = operation;
33759 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33760 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33761
33762 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33763 binary_functor_t f1 = vovov->f0();
33764 binary_functor_t f2 = vovov->f1();
33765
33766 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33767
33768 expression_node_ptr result = error_node();
33769
33770 const bool synthesis_result =
33771 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33772 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33773
33774 if (synthesis_result)
33775 return result;
33776 else if (!expr_gen.valid_operator(o0,f0))
33777 return error_node();
33778
33779 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
33780
33781 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33782 }
33783
33784 static inline std::string id(expression_generator<Type>& expr_gen,
33785 const details::operator_type o0,
33786 const details::operator_type o1,
33787 const details::operator_type o2)
33788 {
33789 return details::build_string()
33790 << "t" << expr_gen.to_str(o0)
33791 << "((t" << expr_gen.to_str(o1)
33792 << "t)" << expr_gen.to_str(o2)
33793 << "t)";
33794 }
33795 };
33796
33797 struct synthesize_vovovoc_expression2
33798 {
33799 typedef typename vovovoc_t::type2 node_type;
33800 typedef typename vovovoc_t::sf4_type sf4_type;
33801 typedef typename node_type::T0 T0;
33802 typedef typename node_type::T1 T1;
33803 typedef typename node_type::T2 T2;
33804 typedef typename node_type::T3 T3;
33805
33806 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33807 const details::operator_type& operation,
33808 expression_node_ptr (&branch)[2])
33809 {
33810 // v0 o0 ((v1 o1 v2) o2 c)
33811 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33812
33813 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33814 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33815 const Type& v1 = vovoc->t0();
33816 const Type& v2 = vovoc->t1();
33817 const Type c = vovoc->t2();
33818 const details::operator_type o0 = operation;
33819 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33820 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33821
33822 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33823 binary_functor_t f1 = vovoc->f0();
33824 binary_functor_t f2 = vovoc->f1();
33825
33826 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33827
33828 expression_node_ptr result = error_node();
33829
33830 const bool synthesis_result =
33831 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33832 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33833
33834 if (synthesis_result)
33835 return result;
33836 else if (!expr_gen.valid_operator(o0,f0))
33837 return error_node();
33838
33839 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
33840
33841 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33842 }
33843
33844 static inline std::string id(expression_generator<Type>& expr_gen,
33845 const details::operator_type o0,
33846 const details::operator_type o1,
33847 const details::operator_type o2)
33848 {
33849 return details::build_string()
33850 << "t" << expr_gen.to_str(o0)
33851 << "((t" << expr_gen.to_str(o1)
33852 << "t)" << expr_gen.to_str(o2)
33853 << "t)";
33854 }
33855 };
33856
33857 struct synthesize_vovocov_expression2
33858 {
33859 typedef typename vovocov_t::type2 node_type;
33860 typedef typename vovocov_t::sf4_type sf4_type;
33861 typedef typename node_type::T0 T0;
33862 typedef typename node_type::T1 T1;
33863 typedef typename node_type::T2 T2;
33864 typedef typename node_type::T3 T3;
33865
33866 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33867 const details::operator_type& operation,
33868 expression_node_ptr (&branch)[2])
33869 {
33870 // v0 o0 ((v1 o1 c) o2 v2)
33871 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33872
33873 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33874 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33875 const Type& v1 = vocov->t0();
33876 const Type c = vocov->t1();
33877 const Type& v2 = vocov->t2();
33878 const details::operator_type o0 = operation;
33879 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33880 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33881
33882 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33883 binary_functor_t f1 = vocov->f0();
33884 binary_functor_t f2 = vocov->f1();
33885
33886 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33887
33888 expression_node_ptr result = error_node();
33889
33890 const bool synthesis_result =
33891 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33892 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33893
33894 if (synthesis_result)
33895 return result;
33896 else if (!expr_gen.valid_operator(o0,f0))
33897 return error_node();
33898
33899 exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
33900
33901 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33902 }
33903
33904 static inline std::string id(expression_generator<Type>& expr_gen,
33905 const details::operator_type o0,
33906 const details::operator_type o1,
33907 const details::operator_type o2)
33908 {
33909 return details::build_string()
33910 << "t" << expr_gen.to_str(o0)
33911 << "((t" << expr_gen.to_str(o1)
33912 << "t)" << expr_gen.to_str(o2)
33913 << "t)";
33914 }
33915 };
33916
33917 struct synthesize_vocovov_expression2
33918 {
33919 typedef typename vocovov_t::type2 node_type;
33920 typedef typename vocovov_t::sf4_type sf4_type;
33921 typedef typename node_type::T0 T0;
33922 typedef typename node_type::T1 T1;
33923 typedef typename node_type::T2 T2;
33924 typedef typename node_type::T3 T3;
33925
33926 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33927 const details::operator_type& operation,
33928 expression_node_ptr (&branch)[2])
33929 {
33930 // v0 o0 ((c o1 v1) o2 v2)
33931 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33932
33933 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
33934 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33935 const Type c = covov->t0();
33936 const Type& v1 = covov->t1();
33937 const Type& v2 = covov->t2();
33938 const details::operator_type o0 = operation;
33939 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
33940 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
33941
33942 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33943 binary_functor_t f1 = covov->f0();
33944 binary_functor_t f2 = covov->f1();
33945
33946 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33947
33948 expression_node_ptr result = error_node();
33949
33950 const bool synthesis_result =
33951 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33952 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33953
33954 if (synthesis_result)
33955 return result;
33956 else if (!expr_gen.valid_operator(o0,f0))
33957 return error_node();
33958
33959 exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
33960
33961 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33962 }
33963
33964 static inline std::string id(expression_generator<Type>& expr_gen,
33965 const details::operator_type o0,
33966 const details::operator_type o1,
33967 const details::operator_type o2)
33968 {
33969 return details::build_string()
33970 << "t" << expr_gen.to_str(o0)
33971 << "((t" << expr_gen.to_str(o1)
33972 << "t)" << expr_gen.to_str(o2)
33973 << "t)";
33974 }
33975 };
33976
33977 struct synthesize_covovov_expression2
33978 {
33979 typedef typename covovov_t::type2 node_type;
33980 typedef typename covovov_t::sf4_type sf4_type;
33981 typedef typename node_type::T0 T0;
33982 typedef typename node_type::T1 T1;
33983 typedef typename node_type::T2 T2;
33984 typedef typename node_type::T3 T3;
33985
33986 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33987 const details::operator_type& operation,
33988 expression_node_ptr (&branch)[2])
33989 {
33990 // c o0 ((v1 o1 v2) o2 v3)
33991 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33992
33993 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33994 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33995 const Type& v0 = vovov->t0();
33996 const Type& v1 = vovov->t1();
33997 const Type& v2 = vovov->t2();
33998 const details::operator_type o0 = operation;
33999 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
34000 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
34001
34002 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34003 binary_functor_t f1 = vovov->f0();
34004 binary_functor_t f2 = vovov->f1();
34005
34006 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34007 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34008
34009 expression_node_ptr result = error_node();
34010
34011 const bool synthesis_result =
34012 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34013 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34014
34015 if (synthesis_result)
34016 return result;
34017 else if (!expr_gen.valid_operator(o0,f0))
34018 return error_node();
34019
34020 exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
34021
34022 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34023 }
34024
34025 static inline std::string id(expression_generator<Type>& expr_gen,
34026 const details::operator_type o0,
34027 const details::operator_type o1,
34028 const details::operator_type o2)
34029 {
34030 return details::build_string()
34031 << "t" << expr_gen.to_str(o0)
34032 << "((t" << expr_gen.to_str(o1)
34033 << "t)" << expr_gen.to_str(o2)
34034 << "t)";
34035 }
34036 };
34037
34038 struct synthesize_covocov_expression2
34039 {
34040 typedef typename covocov_t::type2 node_type;
34041 typedef typename covocov_t::sf4_type sf4_type;
34042 typedef typename node_type::T0 T0;
34043 typedef typename node_type::T1 T1;
34044 typedef typename node_type::T2 T2;
34045 typedef typename node_type::T3 T3;
34046
34047 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34048 const details::operator_type& operation,
34049 expression_node_ptr (&branch)[2])
34050 {
34051 // c0 o0 ((v0 o1 c1) o2 v1)
34052 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34053
34054 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
34055 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
34056 const Type& v0 = vocov->t0();
34057 const Type c1 = vocov->t1();
34058 const Type& v1 = vocov->t2();
34059 const details::operator_type o0 = operation;
34060 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
34061 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
34062
34063 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34064 binary_functor_t f1 = vocov->f0();
34065 binary_functor_t f2 = vocov->f1();
34066
34067 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34068 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34069
34070 expression_node_ptr result = error_node();
34071
34072 const bool synthesis_result =
34073 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34074 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34075
34076 if (synthesis_result)
34077 return result;
34078 else if (!expr_gen.valid_operator(o0,f0))
34079 return error_node();
34080
34081 exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
34082
34083 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34084 }
34085
34086 static inline std::string id(expression_generator<Type>& expr_gen,
34087 const details::operator_type o0,
34088 const details::operator_type o1,
34089 const details::operator_type o2)
34090 {
34091 return details::build_string()
34092 << "t" << expr_gen.to_str(o0)
34093 << "((t" << expr_gen.to_str(o1)
34094 << "t)" << expr_gen.to_str(o2)
34095 << "t)";
34096 }
34097 };
34098
34099 struct synthesize_vocovoc_expression2
34100 {
34101 typedef typename vocovoc_t::type2 node_type;
34102 typedef typename vocovoc_t::sf4_type sf4_type;
34103 typedef typename node_type::T0 T0;
34104 typedef typename node_type::T1 T1;
34105 typedef typename node_type::T2 T2;
34106 typedef typename node_type::T3 T3;
34107
34108 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34109 const details::operator_type& operation,
34110 expression_node_ptr (&branch)[2])
34111 {
34112 // v0 o0 ((c0 o1 v1) o2 c1)
34113 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
34114
34115 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
34116 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
34117 const Type c0 = covoc->t0();
34118 const Type& v1 = covoc->t1();
34119 const Type c1 = covoc->t2();
34120 const details::operator_type o0 = operation;
34121 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
34122 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
34123
34124 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34125 binary_functor_t f1 = covoc->f0();
34126 binary_functor_t f2 = covoc->f1();
34127
34128 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34129
34130 expression_node_ptr result = error_node();
34131
34132 const bool synthesis_result =
34133 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34134 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34135
34136 if (synthesis_result)
34137 return result;
34138 else if (!expr_gen.valid_operator(o0,f0))
34139 return error_node();
34140
34141 exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
34142
34143 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34144 }
34145
34146 static inline std::string id(expression_generator<Type>& expr_gen,
34147 const details::operator_type o0,
34148 const details::operator_type o1,
34149 const details::operator_type o2)
34150 {
34151 return details::build_string()
34152 << "t" << expr_gen.to_str(o0)
34153 << "((t" << expr_gen.to_str(o1)
34154 << "t)" << expr_gen.to_str(o2)
34155 << "t)";
34156 }
34157 };
34158
34159 struct synthesize_covovoc_expression2
34160 {
34161 typedef typename covovoc_t::type2 node_type;
34162 typedef typename covovoc_t::sf4_type sf4_type;
34163 typedef typename node_type::T0 T0;
34164 typedef typename node_type::T1 T1;
34165 typedef typename node_type::T2 T2;
34166 typedef typename node_type::T3 T3;
34167
34168 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34169 const details::operator_type& operation,
34170 expression_node_ptr (&branch)[2])
34171 {
34172 // c0 o0 ((v0 o1 v1) o2 c1)
34173 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
34174
34175 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
34176 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
34177 const Type& v0 = vovoc->t0();
34178 const Type& v1 = vovoc->t1();
34179 const Type c1 = vovoc->t2();
34180 const details::operator_type o0 = operation;
34181 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
34182 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
34183
34184 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34185 binary_functor_t f1 = vovoc->f0();
34186 binary_functor_t f2 = vovoc->f1();
34187
34188 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34189 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34190
34191 expression_node_ptr result = error_node();
34192
34193 const bool synthesis_result =
34194 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34195 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34196
34197 if (synthesis_result)
34198 return result;
34199 else if (!expr_gen.valid_operator(o0,f0))
34200 return error_node();
34201
34202 exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
34203
34204 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34205 }
34206
34207 static inline std::string id(expression_generator<Type>& expr_gen,
34208 const details::operator_type o0,
34209 const details::operator_type o1,
34210 const details::operator_type o2)
34211 {
34212 return details::build_string()
34213 << "t" << expr_gen.to_str(o0)
34214 << "((t" << expr_gen.to_str(o1)
34215 << "t)" << expr_gen.to_str(o2)
34216 << "t)";
34217 }
34218 };
34219
34220 struct synthesize_vococov_expression2
34221 {
34222 typedef typename vococov_t::type2 node_type;
34223 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
34224 {
34225 // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
34226 exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
34227 return error_node();
34228 }
34229
34230 static inline std::string id(expression_generator<Type>&,
34232 {
34233 return "INVALID";
34234 }
34235 };
34236
34237 struct synthesize_vovovov_expression3
34238 {
34239 typedef typename vovovov_t::type3 node_type;
34240 typedef typename vovovov_t::sf4_type sf4_type;
34241 typedef typename node_type::T0 T0;
34242 typedef typename node_type::T1 T1;
34243 typedef typename node_type::T2 T2;
34244 typedef typename node_type::T3 T3;
34245
34246 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34247 const details::operator_type& operation,
34248 expression_node_ptr (&branch)[2])
34249 {
34250 // ((v0 o0 v1) o1 v2) o2 v3
34251 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
34252
34253 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34254 const Type& v0 = vovov->t0();
34255 const Type& v1 = vovov->t1();
34256 const Type& v2 = vovov->t2();
34257 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34258 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34259 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34260 const details::operator_type o2 = operation;
34261
34262 binary_functor_t f0 = vovov->f0();
34263 binary_functor_t f1 = vovov->f1();
34264 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34265
34266 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34267
34268 expression_node_ptr result = error_node();
34269
34270 const bool synthesis_result =
34271 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34272 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
34273
34274 if (synthesis_result)
34275 return result;
34276 else if (!expr_gen.valid_operator(o2,f2))
34277 return error_node();
34278
34279 exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
34280
34281 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
34282 }
34283
34284 static inline std::string id(expression_generator<Type>& expr_gen,
34285 const details::operator_type o0,
34286 const details::operator_type o1,
34287 const details::operator_type o2)
34288 {
34289 return details::build_string()
34290 << "((t" << expr_gen.to_str(o0)
34291 << "t)" << expr_gen.to_str(o1)
34292 << "t)" << expr_gen.to_str(o2)
34293 << "t";
34294 }
34295 };
34296
34297 struct synthesize_vovovoc_expression3
34298 {
34299 typedef typename vovovoc_t::type3 node_type;
34300 typedef typename vovovoc_t::sf4_type sf4_type;
34301 typedef typename node_type::T0 T0;
34302 typedef typename node_type::T1 T1;
34303 typedef typename node_type::T2 T2;
34304 typedef typename node_type::T3 T3;
34305
34306 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34307 const details::operator_type& operation,
34308 expression_node_ptr (&branch)[2])
34309 {
34310 // ((v0 o0 v1) o1 v2) o2 c
34311 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
34312
34313 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34314 const Type& v0 = vovov->t0();
34315 const Type& v1 = vovov->t1();
34316 const Type& v2 = vovov->t2();
34317 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
34318 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34319 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34320 const details::operator_type o2 = operation;
34321
34322 binary_functor_t f0 = vovov->f0();
34323 binary_functor_t f1 = vovov->f1();
34324 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34325
34326 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34327 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34328
34329 expression_node_ptr result = error_node();
34330
34331 const bool synthesis_result =
34332 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34333 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
34334
34335 if (synthesis_result)
34336 return result;
34337 else if (!expr_gen.valid_operator(o2,f2))
34338 return error_node();
34339
34340 exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
34341
34342 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
34343 }
34344
34345 static inline std::string id(expression_generator<Type>& expr_gen,
34346 const details::operator_type o0,
34347 const details::operator_type o1,
34348 const details::operator_type o2)
34349 {
34350 return details::build_string()
34351 << "((t" << expr_gen.to_str(o0)
34352 << "t)" << expr_gen.to_str(o1)
34353 << "t)" << expr_gen.to_str(o2)
34354 << "t";
34355 }
34356 };
34357
34358 struct synthesize_vovocov_expression3
34359 {
34360 typedef typename vovocov_t::type3 node_type;
34361 typedef typename vovocov_t::sf4_type sf4_type;
34362 typedef typename node_type::T0 T0;
34363 typedef typename node_type::T1 T1;
34364 typedef typename node_type::T2 T2;
34365 typedef typename node_type::T3 T3;
34366
34367 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34368 const details::operator_type& operation,
34369 expression_node_ptr (&branch)[2])
34370 {
34371 // ((v0 o0 v1) o1 c) o2 v2
34372 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
34373
34374 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
34375 const Type& v0 = vovoc->t0();
34376 const Type& v1 = vovoc->t1();
34377 const Type c = vovoc->t2();
34378 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34379 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
34380 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
34381 const details::operator_type o2 = operation;
34382
34383 binary_functor_t f0 = vovoc->f0();
34384 binary_functor_t f1 = vovoc->f1();
34385 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34386
34387 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34388
34389 expression_node_ptr result = error_node();
34390
34391 const bool synthesis_result =
34392 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34393 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
34394
34395 if (synthesis_result)
34396 return result;
34397 else if (!expr_gen.valid_operator(o2,f2))
34398 return error_node();
34399
34400 exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
34401
34402 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
34403 }
34404
34405 static inline std::string id(expression_generator<Type>& expr_gen,
34406 const details::operator_type o0,
34407 const details::operator_type o1,
34408 const details::operator_type o2)
34409 {
34410 return details::build_string()
34411 << "((t" << expr_gen.to_str(o0)
34412 << "t)" << expr_gen.to_str(o1)
34413 << "t)" << expr_gen.to_str(o2)
34414 << "t";
34415 }
34416 };
34417
34418 struct synthesize_vocovov_expression3
34419 {
34420 typedef typename vocovov_t::type3 node_type;
34421 typedef typename vocovov_t::sf4_type sf4_type;
34422 typedef typename node_type::T0 T0;
34423 typedef typename node_type::T1 T1;
34424 typedef typename node_type::T2 T2;
34425 typedef typename node_type::T3 T3;
34426
34427 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34428 const details::operator_type& operation,
34429 expression_node_ptr (&branch)[2])
34430 {
34431 // ((v0 o0 c) o1 v1) o2 v2
34432 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34433
34434 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34435 const Type& v0 = vocov->t0();
34436 const Type c = vocov->t1();
34437 const Type& v1 = vocov->t2();
34438 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34439 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34440 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34441 const details::operator_type o2 = operation;
34442
34443 binary_functor_t f0 = vocov->f0();
34444 binary_functor_t f1 = vocov->f1();
34445 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34446
34447 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34448
34449 expression_node_ptr result = error_node();
34450
34451 const bool synthesis_result =
34452 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34453 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34454
34455 if (synthesis_result)
34456 return result;
34457 else if (!expr_gen.valid_operator(o2,f2))
34458 return error_node();
34459
34460 exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
34461
34462 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
34463 }
34464
34465 static inline std::string id(expression_generator<Type>& expr_gen,
34466 const details::operator_type o0,
34467 const details::operator_type o1,
34468 const details::operator_type o2)
34469 {
34470 return details::build_string()
34471 << "((t" << expr_gen.to_str(o0)
34472 << "t)" << expr_gen.to_str(o1)
34473 << "t)" << expr_gen.to_str(o2)
34474 << "t";
34475 }
34476 };
34477
34478 struct synthesize_covovov_expression3
34479 {
34480 typedef typename covovov_t::type3 node_type;
34481 typedef typename covovov_t::sf4_type sf4_type;
34482 typedef typename node_type::T0 T0;
34483 typedef typename node_type::T1 T1;
34484 typedef typename node_type::T2 T2;
34485 typedef typename node_type::T3 T3;
34486
34487 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34488 const details::operator_type& operation,
34489 expression_node_ptr (&branch)[2])
34490 {
34491 // ((c o0 v0) o1 v1) o2 v2
34492 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
34493
34494 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34495 const Type c = covov->t0();
34496 const Type& v0 = covov->t1();
34497 const Type& v1 = covov->t2();
34498 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34499 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34500 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34501 const details::operator_type o2 = operation;
34502
34503 binary_functor_t f0 = covov->f0();
34504 binary_functor_t f1 = covov->f1();
34505 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34506
34507 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34508
34509 expression_node_ptr result = error_node();
34510
34511 const bool synthesis_result =
34512 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34513 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34514
34515 if (synthesis_result)
34516 return result;
34517 else if (!expr_gen.valid_operator(o2,f2))
34518 return error_node();
34519
34520 exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
34521
34522 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34523 }
34524
34525 static inline std::string id(expression_generator<Type>& expr_gen,
34526 const details::operator_type o0,
34527 const details::operator_type o1,
34528 const details::operator_type o2)
34529 {
34530 return details::build_string()
34531 << "((t" << expr_gen.to_str(o0)
34532 << "t)" << expr_gen.to_str(o1)
34533 << "t)" << expr_gen.to_str(o2)
34534 << "t";
34535 }
34536 };
34537
34538 struct synthesize_covocov_expression3
34539 {
34540 typedef typename covocov_t::type3 node_type;
34541 typedef typename covocov_t::sf4_type sf4_type;
34542 typedef typename node_type::T0 T0;
34543 typedef typename node_type::T1 T1;
34544 typedef typename node_type::T2 T2;
34545 typedef typename node_type::T3 T3;
34546
34547 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34548 const details::operator_type& operation,
34549 expression_node_ptr (&branch)[2])
34550 {
34551 // ((c0 o0 v0) o1 c1) o2 v1
34552 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
34553
34554 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34555 const Type c0 = covoc->t0();
34556 const Type& v0 = covoc->t1();
34557 const Type c1 = covoc->t2();
34558 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34559 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34560 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34561 const details::operator_type o2 = operation;
34562
34563 binary_functor_t f0 = covoc->f0();
34564 binary_functor_t f1 = covoc->f1();
34565 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34566
34567 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34568
34569 expression_node_ptr result = error_node();
34570
34571 const bool synthesis_result =
34572 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34573 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34574
34575 if (synthesis_result)
34576 return result;
34577 else if (!expr_gen.valid_operator(o2,f2))
34578 return error_node();
34579
34580 exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
34581
34582 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34583 }
34584
34585 static inline std::string id(expression_generator<Type>& expr_gen,
34586 const details::operator_type o0,
34587 const details::operator_type o1,
34588 const details::operator_type o2)
34589 {
34590 return details::build_string()
34591 << "((t" << expr_gen.to_str(o0)
34592 << "t)" << expr_gen.to_str(o1)
34593 << "t)" << expr_gen.to_str(o2)
34594 << "t";
34595 }
34596 };
34597
34598 struct synthesize_vocovoc_expression3
34599 {
34600 typedef typename vocovoc_t::type3 node_type;
34601 typedef typename vocovoc_t::sf4_type sf4_type;
34602 typedef typename node_type::T0 T0;
34603 typedef typename node_type::T1 T1;
34604 typedef typename node_type::T2 T2;
34605 typedef typename node_type::T3 T3;
34606
34607 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34608 const details::operator_type& operation,
34609 expression_node_ptr (&branch)[2])
34610 {
34611 // ((v0 o0 c0) o1 v1) o2 c1
34612 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34613
34614 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34615 const Type& v0 = vocov->t0();
34616 const Type c0 = vocov->t1();
34617 const Type& v1 = vocov->t2();
34618 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34619 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34620 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34621 const details::operator_type o2 = operation;
34622
34623 binary_functor_t f0 = vocov->f0();
34624 binary_functor_t f1 = vocov->f1();
34625 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34626
34627 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34628 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34629
34630 expression_node_ptr result = error_node();
34631
34632 const bool synthesis_result =
34633 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34634 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34635
34636 if (synthesis_result)
34637 return result;
34638 else if (!expr_gen.valid_operator(o2,f2))
34639 return error_node();
34640
34641 exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
34642
34643 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34644 }
34645
34646 static inline std::string id(expression_generator<Type>& expr_gen,
34647 const details::operator_type o0,
34648 const details::operator_type o1,
34649 const details::operator_type o2)
34650 {
34651 return details::build_string()
34652 << "((t" << expr_gen.to_str(o0)
34653 << "t)" << expr_gen.to_str(o1)
34654 << "t)" << expr_gen.to_str(o2)
34655 << "t";
34656 }
34657 };
34658
34659 struct synthesize_covovoc_expression3
34660 {
34661 typedef typename covovoc_t::type3 node_type;
34662 typedef typename covovoc_t::sf4_type sf4_type;
34663 typedef typename node_type::T0 T0;
34664 typedef typename node_type::T1 T1;
34665 typedef typename node_type::T2 T2;
34666 typedef typename node_type::T3 T3;
34667
34668 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34669 const details::operator_type& operation,
34670 expression_node_ptr (&branch)[2])
34671 {
34672 // ((c0 o0 v0) o1 v1) o2 c1
34673 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
34674
34675 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34676 const Type c0 = covov->t0();
34677 const Type& v0 = covov->t1();
34678 const Type& v1 = covov->t2();
34679 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34680 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34681 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34682 const details::operator_type o2 = operation;
34683
34684 binary_functor_t f0 = covov->f0();
34685 binary_functor_t f1 = covov->f1();
34686 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34687
34688 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34689 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34690
34691 expression_node_ptr result = error_node();
34692
34693 const bool synthesis_result =
34694 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34695 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34696
34697 if (synthesis_result)
34698 return result;
34699 else if (!expr_gen.valid_operator(o2,f2))
34700 return error_node();
34701
34702 exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
34703
34704 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34705 }
34706
34707 static inline std::string id(expression_generator<Type>& expr_gen,
34708 const details::operator_type o0,
34709 const details::operator_type o1,
34710 const details::operator_type o2)
34711 {
34712 return details::build_string()
34713 << "((t" << expr_gen.to_str(o0)
34714 << "t)" << expr_gen.to_str(o1)
34715 << "t)" << expr_gen.to_str(o2)
34716 << "t";
34717 }
34718 };
34719
34720 struct synthesize_vococov_expression3
34721 {
34722 typedef typename vococov_t::type3 node_type;
34723 typedef typename vococov_t::sf4_type sf4_type;
34724 typedef typename node_type::T0 T0;
34725 typedef typename node_type::T1 T1;
34726 typedef typename node_type::T2 T2;
34727 typedef typename node_type::T3 T3;
34728
34729 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34730 const details::operator_type& operation,
34731 expression_node_ptr (&branch)[2])
34732 {
34733 // ((v0 o0 c0) o1 c1) o2 v1
34734 typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
34735
34736 const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
34737 const Type& v0 = vococ->t0();
34738 const Type c0 = vococ->t1();
34739 const Type c1 = vococ->t2();
34740 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34741 const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
34742 const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
34743 const details::operator_type o2 = operation;
34744
34745 binary_functor_t f0 = vococ->f0();
34746 binary_functor_t f1 = vococ->f1();
34747 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34748
34749 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34750
34751 expression_node_ptr result = error_node();
34752
34753 const bool synthesis_result =
34754 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34755 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
34756
34757 if (synthesis_result)
34758 return result;
34759 else if (!expr_gen.valid_operator(o2,f2))
34760 return error_node();
34761
34762 exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
34763
34764 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
34765 }
34766
34767 static inline std::string id(expression_generator<Type>& expr_gen,
34768 const details::operator_type o0,
34769 const details::operator_type o1,
34770 const details::operator_type o2)
34771 {
34772 return details::build_string()
34773 << "((t" << expr_gen.to_str(o0)
34774 << "t)" << expr_gen.to_str(o1)
34775 << "t)" << expr_gen.to_str(o2)
34776 << "t";
34777 }
34778 };
34779
34780 struct synthesize_vovovov_expression4
34781 {
34782 typedef typename vovovov_t::type4 node_type;
34783 typedef typename vovovov_t::sf4_type sf4_type;
34784 typedef typename node_type::T0 T0;
34785 typedef typename node_type::T1 T1;
34786 typedef typename node_type::T2 T2;
34787 typedef typename node_type::T3 T3;
34788
34789 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34790 const details::operator_type& operation,
34791 expression_node_ptr (&branch)[2])
34792 {
34793 // (v0 o0 (v1 o1 v2)) o2 v3
34794 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
34795
34796 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34797 const Type& v0 = vovov->t0();
34798 const Type& v1 = vovov->t1();
34799 const Type& v2 = vovov->t2();
34800 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34801 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34802 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34803 const details::operator_type o2 = operation;
34804
34805 binary_functor_t f0 = vovov->f0();
34806 binary_functor_t f1 = vovov->f1();
34807 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34808
34809 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34810
34811 expression_node_ptr result = error_node();
34812
34813 const bool synthesis_result =
34814 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34815 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
34816
34817 if (synthesis_result)
34818 return result;
34819 else if (!expr_gen.valid_operator(o2,f2))
34820 return error_node();
34821
34822 exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
34823
34824 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
34825 }
34826
34827 static inline std::string id(expression_generator<Type>& expr_gen,
34828 const details::operator_type o0,
34829 const details::operator_type o1,
34830 const details::operator_type o2)
34831 {
34832 return details::build_string()
34833 << "(t" << expr_gen.to_str(o0)
34834 << "(t" << expr_gen.to_str(o1)
34835 << "t)" << expr_gen.to_str(o2)
34836 << "t";
34837 }
34838 };
34839
34840 struct synthesize_vovovoc_expression4
34841 {
34842 typedef typename vovovoc_t::type4 node_type;
34843 typedef typename vovovoc_t::sf4_type sf4_type;
34844 typedef typename node_type::T0 T0;
34845 typedef typename node_type::T1 T1;
34846 typedef typename node_type::T2 T2;
34847 typedef typename node_type::T3 T3;
34848
34849 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34850 const details::operator_type& operation,
34851 expression_node_ptr (&branch)[2])
34852 {
34853 // ((v0 o0 (v1 o1 v2)) o2 c)
34854 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
34855
34856 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34857 const Type& v0 = vovov->t0();
34858 const Type& v1 = vovov->t1();
34859 const Type& v2 = vovov->t2();
34860 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
34861 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34862 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34863 const details::operator_type o2 = operation;
34864
34865 binary_functor_t f0 = vovov->f0();
34866 binary_functor_t f1 = vovov->f1();
34867 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34868
34869 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34870 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34871
34872 expression_node_ptr result = error_node();
34873
34874 const bool synthesis_result =
34875 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34876 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
34877
34878 if (synthesis_result)
34879 return result;
34880 else if (!expr_gen.valid_operator(o2,f2))
34881 return error_node();
34882
34883 exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
34884
34885 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
34886 }
34887
34888 static inline std::string id(expression_generator<Type>& expr_gen,
34889 const details::operator_type o0,
34890 const details::operator_type o1,
34891 const details::operator_type o2)
34892 {
34893 return details::build_string()
34894 << "(t" << expr_gen.to_str(o0)
34895 << "(t" << expr_gen.to_str(o1)
34896 << "t)" << expr_gen.to_str(o2)
34897 << "t";
34898 }
34899 };
34900
34901 struct synthesize_vovocov_expression4
34902 {
34903 typedef typename vovocov_t::type4 node_type;
34904 typedef typename vovocov_t::sf4_type sf4_type;
34905 typedef typename node_type::T0 T0;
34906 typedef typename node_type::T1 T1;
34907 typedef typename node_type::T2 T2;
34908 typedef typename node_type::T3 T3;
34909
34910 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34911 const details::operator_type& operation,
34912 expression_node_ptr (&branch)[2])
34913 {
34914 // ((v0 o0 (v1 o1 c)) o2 v1)
34915 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
34916
34917 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
34918 const Type& v0 = vovoc->t0();
34919 const Type& v1 = vovoc->t1();
34920 const Type c = vovoc->t2();
34921 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34922 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
34923 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
34924 const details::operator_type o2 = operation;
34925
34926 binary_functor_t f0 = vovoc->f0();
34927 binary_functor_t f1 = vovoc->f1();
34928 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34929
34930 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34931
34932 expression_node_ptr result = error_node();
34933
34934 const bool synthesis_result =
34935 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34936 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
34937
34938 if (synthesis_result)
34939 return result;
34940 else if (!expr_gen.valid_operator(o2,f2))
34941 return error_node();
34942
34943 exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
34944
34945 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
34946 }
34947
34948 static inline std::string id(expression_generator<Type>& expr_gen,
34949 const details::operator_type o0,
34950 const details::operator_type o1,
34951 const details::operator_type o2)
34952 {
34953 return details::build_string()
34954 << "(t" << expr_gen.to_str(o0)
34955 << "(t" << expr_gen.to_str(o1)
34956 << "t)" << expr_gen.to_str(o2)
34957 << "t";
34958 }
34959 };
34960
34961 struct synthesize_vocovov_expression4
34962 {
34963 typedef typename vocovov_t::type4 node_type;
34964 typedef typename vocovov_t::sf4_type sf4_type;
34965 typedef typename node_type::T0 T0;
34966 typedef typename node_type::T1 T1;
34967 typedef typename node_type::T2 T2;
34968 typedef typename node_type::T3 T3;
34969
34970 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34971 const details::operator_type& operation,
34972 expression_node_ptr (&branch)[2])
34973 {
34974 // ((v0 o0 (c o1 v1)) o2 v2)
34975 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34976
34977 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34978 const Type& v0 = vocov->t0();
34979 const Type c = vocov->t1();
34980 const Type& v1 = vocov->t2();
34981 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34982 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34983 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34984 const details::operator_type o2 = operation;
34985
34986 binary_functor_t f0 = vocov->f0();
34987 binary_functor_t f1 = vocov->f1();
34988 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34989
34990 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34991 expression_node_ptr result = error_node();
34992
34993 const bool synthesis_result =
34994 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34995 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34996
34997 if (synthesis_result)
34998 return result;
34999 else if (!expr_gen.valid_operator(o2,f2))
35000 return error_node();
35001
35002 exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
35003
35004 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
35005 }
35006
35007 static inline std::string id(expression_generator<Type>& expr_gen,
35008 const details::operator_type o0,
35009 const details::operator_type o1,
35010 const details::operator_type o2)
35011 {
35012 return details::build_string()
35013 << "(t" << expr_gen.to_str(o0)
35014 << "(t" << expr_gen.to_str(o1)
35015 << "t)" << expr_gen.to_str(o2)
35016 << "t";
35017 }
35018 };
35019
35020 struct synthesize_covovov_expression4
35021 {
35022 typedef typename covovov_t::type4 node_type;
35023 typedef typename covovov_t::sf4_type sf4_type;
35024 typedef typename node_type::T0 T0;
35025 typedef typename node_type::T1 T1;
35026 typedef typename node_type::T2 T2;
35027 typedef typename node_type::T3 T3;
35028
35029 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35030 const details::operator_type& operation,
35031 expression_node_ptr (&branch)[2])
35032 {
35033 // ((c o0 (v0 o1 v1)) o2 v2)
35034 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
35035
35036 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
35037 const Type c = covov->t0();
35038 const Type& v0 = covov->t1();
35039 const Type& v1 = covov->t2();
35040 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35041 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
35042 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
35043 const details::operator_type o2 = operation;
35044
35045 binary_functor_t f0 = covov->f0();
35046 binary_functor_t f1 = covov->f1();
35047 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35048
35049 details::free_node(*(expr_gen.node_allocator_),branch[0]);
35050
35051 expression_node_ptr result = error_node();
35052
35053 const bool synthesis_result =
35054 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35055 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
35056
35057 if (synthesis_result)
35058 return result;
35059 else if (!expr_gen.valid_operator(o2,f2))
35060 return error_node();
35061
35062 exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
35063
35064 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
35065 }
35066
35067 static inline std::string id(expression_generator<Type>& expr_gen,
35068 const details::operator_type o0,
35069 const details::operator_type o1,
35070 const details::operator_type o2)
35071 {
35072 return details::build_string()
35073 << "(t" << expr_gen.to_str(o0)
35074 << "(t" << expr_gen.to_str(o1)
35075 << "t)" << expr_gen.to_str(o2)
35076 << "t";
35077 }
35078 };
35079
35080 struct synthesize_covocov_expression4
35081 {
35082 typedef typename covocov_t::type4 node_type;
35083 typedef typename covocov_t::sf4_type sf4_type;
35084 typedef typename node_type::T0 T0;
35085 typedef typename node_type::T1 T1;
35086 typedef typename node_type::T2 T2;
35087 typedef typename node_type::T3 T3;
35088
35089 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35090 const details::operator_type& operation,
35091 expression_node_ptr (&branch)[2])
35092 {
35093 // ((c0 o0 (v0 o1 c1)) o2 v1)
35094 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
35095
35096 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
35097 const Type c0 = covoc->t0();
35098 const Type& v0 = covoc->t1();
35099 const Type c1 = covoc->t2();
35100 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35101 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
35102 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
35103 const details::operator_type o2 = operation;
35104
35105 binary_functor_t f0 = covoc->f0();
35106 binary_functor_t f1 = covoc->f1();
35107 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35108
35109 details::free_node(*(expr_gen.node_allocator_),branch[0]);
35110
35111 expression_node_ptr result = error_node();
35112
35113 const bool synthesis_result =
35114 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35115 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
35116
35117 if (synthesis_result)
35118 return result;
35119 else if (!expr_gen.valid_operator(o2,f2))
35120 return error_node();
35121
35122 exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
35123
35124 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
35125 }
35126
35127 static inline std::string id(expression_generator<Type>& expr_gen,
35128 const details::operator_type o0,
35129 const details::operator_type o1,
35130 const details::operator_type o2)
35131 {
35132 return details::build_string()
35133 << "(t" << expr_gen.to_str(o0)
35134 << "(t" << expr_gen.to_str(o1)
35135 << "t)" << expr_gen.to_str(o2)
35136 << "t";
35137 }
35138 };
35139
35140 struct synthesize_vocovoc_expression4
35141 {
35142 typedef typename vocovoc_t::type4 node_type;
35143 typedef typename vocovoc_t::sf4_type sf4_type;
35144 typedef typename node_type::T0 T0;
35145 typedef typename node_type::T1 T1;
35146 typedef typename node_type::T2 T2;
35147 typedef typename node_type::T3 T3;
35148
35149 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35150 const details::operator_type& operation,
35151 expression_node_ptr (&branch)[2])
35152 {
35153 // ((v0 o0 (c0 o1 v1)) o2 c1)
35154 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
35155
35156 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
35157 const Type& v0 = vocov->t0();
35158 const Type c0 = vocov->t1();
35159 const Type& v1 = vocov->t2();
35160 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
35161 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
35162 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
35163 const details::operator_type o2 = operation;
35164
35165 binary_functor_t f0 = vocov->f0();
35166 binary_functor_t f1 = vocov->f1();
35167 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35168
35169 details::free_node(*(expr_gen.node_allocator_),branch[0]);
35170 details::free_node(*(expr_gen.node_allocator_),branch[1]);
35171
35172 expression_node_ptr result = error_node();
35173
35174 const bool synthesis_result =
35175 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35176 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
35177
35178 if (synthesis_result)
35179 return result;
35180 else if (!expr_gen.valid_operator(o2,f2))
35181 return error_node();
35182
35183 exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
35184
35185 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
35186 }
35187
35188 static inline std::string id(expression_generator<Type>& expr_gen,
35189 const details::operator_type o0,
35190 const details::operator_type o1,
35191 const details::operator_type o2)
35192 {
35193 return details::build_string()
35194 << "(t" << expr_gen.to_str(o0)
35195 << "(t" << expr_gen.to_str(o1)
35196 << "t)" << expr_gen.to_str(o2)
35197 << "t";
35198 }
35199 };
35200
35201 struct synthesize_covovoc_expression4
35202 {
35203 typedef typename covovoc_t::type4 node_type;
35204 typedef typename covovoc_t::sf4_type sf4_type;
35205 typedef typename node_type::T0 T0;
35206 typedef typename node_type::T1 T1;
35207 typedef typename node_type::T2 T2;
35208 typedef typename node_type::T3 T3;
35209
35210 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35211 const details::operator_type& operation,
35212 expression_node_ptr (&branch)[2])
35213 {
35214 // ((c0 o0 (v0 o1 v1)) o2 c1)
35215 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
35216
35217 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
35218 const Type c0 = covov->t0();
35219 const Type& v0 = covov->t1();
35220 const Type& v1 = covov->t2();
35221 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
35222 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
35223 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
35224 const details::operator_type o2 = operation;
35225
35226 binary_functor_t f0 = covov->f0();
35227 binary_functor_t f1 = covov->f1();
35228 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35229
35230 details::free_node(*(expr_gen.node_allocator_),branch[0]);
35231 details::free_node(*(expr_gen.node_allocator_),branch[1]);
35232
35233 expression_node_ptr result = error_node();
35234
35235 const bool synthesis_result =
35236 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35237 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
35238
35239 if (synthesis_result)
35240 return result;
35241 else if (!expr_gen.valid_operator(o2,f2))
35242 return error_node();
35243
35244 exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
35245
35246 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
35247 }
35248
35249 static inline std::string id(expression_generator<Type>& expr_gen,
35250 const details::operator_type o0,
35251 const details::operator_type o1,
35252 const details::operator_type o2)
35253 {
35254 return details::build_string()
35255 << "(t" << expr_gen.to_str(o0)
35256 << "(t" << expr_gen.to_str(o1)
35257 << "t)" << expr_gen.to_str(o2)
35258 << "t";
35259 }
35260 };
35261
35262 struct synthesize_vococov_expression4
35263 {
35264 typedef typename vococov_t::type4 node_type;
35265 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
35266 {
35267 // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
35268 exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
35269 return error_node();
35270 }
35271
35272 static inline std::string id(expression_generator<Type>&,
35274 {
35275 return "INVALID";
35276 }
35277 };
35278 #endif
35279
35280 inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
35281 {
35282 // Definition: uv o uv
35283 details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
35284 details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
35285 const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
35286 const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
35287 unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
35288 unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
35289 binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
35290
35291 if (!valid_operator(o0,u0))
35292 return error_node();
35293 else if (!valid_operator(o1,u1))
35294 return error_node();
35295 else if (!valid_operator(operation,f))
35296 return error_node();
35297
35298 expression_node_ptr result = error_node();
35299
35300 if (
35301 (details::e_neg == o0) &&
35302 (details::e_neg == o1)
35303 )
35304 {
35305 switch (operation)
35306 {
35307 // (-v0 + -v1) --> -(v0 + v1)
35308 case details::e_add : result = (*this)(details::e_neg,
35309 node_allocator_->
35310 allocate_rr<typename details::
35311 vov_node<Type,details::add_op<Type> > >(v0, v1));
35312 exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
35313 break;
35314
35315 // (-v0 - -v1) --> (v1 - v0)
35316 case details::e_sub : result = node_allocator_->
35317 allocate_rr<typename details::
35318 vov_node<Type,details::sub_op<Type> > >(v1, v0);
35319 exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
35320 break;
35321
35322 // (-v0 * -v1) --> (v0 * v1)
35323 case details::e_mul : result = node_allocator_->
35324 allocate_rr<typename details::
35325 vov_node<Type,details::mul_op<Type> > >(v0, v1);
35326 exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
35327 break;
35328
35329 // (-v0 / -v1) --> (v0 / v1)
35330 case details::e_div : result = node_allocator_->
35331 allocate_rr<typename details::
35332 vov_node<Type,details::div_op<Type> > >(v0, v1);
35333 exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
35334 break;
35335
35336 default : break;
35337 }
35338 }
35339
35340 if (0 == result)
35341 {
35342 result = node_allocator_->
35343 allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
35344 }
35345
35346 details::free_all_nodes(*node_allocator_,branch);
35347 return result;
35348 }
35349
35350 #undef basic_opr_switch_statements
35351 #undef extended_opr_switch_statements
35352 #undef unary_opr_switch_statements
35353
35354 #ifndef exprtk_disable_string_capabilities
35356 #define string_opr_switch_statements \
35357 case_stmt(details:: e_lt ,details:: lt_op) \
35358 case_stmt(details:: e_lte ,details:: lte_op) \
35359 case_stmt(details:: e_gt ,details:: gt_op) \
35360 case_stmt(details:: e_gte ,details:: gte_op) \
35361 case_stmt(details:: e_eq ,details:: eq_op) \
35362 case_stmt(details:: e_ne ,details:: ne_op) \
35363 case_stmt(details::e_in ,details:: in_op) \
35364 case_stmt(details::e_like ,details:: like_op) \
35365 case_stmt(details::e_ilike,details::ilike_op) \
35366
35367 template <typename T0, typename T1>
35368 inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
35369 T0 s0, T1 s1,
35370 range_t rp0)
35371 {
35372 switch (opr)
35373 {
35374 #define case_stmt(op0,op1) \
35375 case op0 : return node_allocator_-> \
35376 allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35377 (s0, s1, rp0); \
35378
35380 #undef case_stmt
35381 default : return error_node();
35382 }
35383 }
35384
35385 template <typename T0, typename T1>
35386 inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
35387 T0 s0, T1 s1,
35388 range_t rp1)
35389 {
35390 switch (opr)
35391 {
35392 #define case_stmt(op0,op1) \
35393 case op0 : return node_allocator_-> \
35394 allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35395 (s0, s1, rp1); \
35396
35398 #undef case_stmt
35399 default : return error_node();
35400 }
35401 }
35402
35403 template <typename T0, typename T1>
35404 inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
35405 T0 s0, T1 s1,
35406 range_t rp0, range_t rp1)
35407 {
35408 switch (opr)
35409 {
35410 #define case_stmt(op0,op1) \
35411 case op0 : return node_allocator_-> \
35412 allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35413 (s0, s1, rp0, rp1); \
35414
35416 #undef case_stmt
35417 default : return error_node();
35418 }
35419 }
35420
35421 template <typename T0, typename T1>
35422 inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
35423 {
35424 switch (opr)
35425 {
35426 #define case_stmt(op0,op1) \
35427 case op0 : return node_allocator_-> \
35428 allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
35429
35431 #undef case_stmt
35432 default : return error_node();
35433 }
35434 }
35435
35436 inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35437 {
35438 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
35439 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
35440
35441 return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
35442 }
35443
35444 inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35445 {
35446 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
35447 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
35448 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
35449
35450 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35451
35452 free_node(*node_allocator_,branch[0]);
35453
35454 return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
35455 }
35456
35457 inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35458 {
35459 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
35460 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
35461 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
35462
35463 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35464
35465 free_node(*node_allocator_,branch[1]);
35466
35467 return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
35468 }
35469
35470 inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35471 {
35472 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
35473 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
35474 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35475
35476 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35477
35478 free_node(*node_allocator_,branch[1]);
35479
35480 return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
35481 }
35482
35483 inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35484 {
35485 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
35486 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
35487 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
35488 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
35489
35490 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35491 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35492
35493 details::free_node(*node_allocator_,branch[0]);
35494 details::free_node(*node_allocator_,branch[1]);
35495
35496 return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
35497 }
35498
35499 inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35500 {
35501 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
35502 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35503
35504 details::free_node(*node_allocator_,branch[1]);
35505
35506 return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
35507 }
35508
35509 inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35510 {
35511 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35512 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
35513
35514 details::free_node(*node_allocator_,branch[0]);
35515
35516 return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
35517 }
35518
35519 inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35520 {
35521 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
35522 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
35523 range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
35524
35525 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35526
35527 details::free_node(*node_allocator_,branch[0]);
35528 details::free_node(*node_allocator_,branch[1]);
35529
35530 return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
35531 }
35532
35533 inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35534 {
35535 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
35536 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
35537 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
35538
35539 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35540
35541 details::free_node(*node_allocator_,branch[0]);
35542 details::free_node(*node_allocator_,branch[1]);
35543
35544 return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
35545 }
35546
35547 inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35548 {
35549 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
35550 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
35551 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
35552 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35553
35554 static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
35555 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35556
35557 details::free_node(*node_allocator_,branch[0]);
35558 details::free_node(*node_allocator_,branch[1]);
35559
35560 return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
35561 }
35562
35563 inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35564 {
35565 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35566 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35567
35568 expression_node_ptr result = error_node();
35569
35570 if (details::e_add == opr)
35571 result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
35572 else if (details::e_in == opr)
35573 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
35574 else if (details::e_like == opr)
35575 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
35576 else if (details::e_ilike == opr)
35577 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
35578 else
35579 {
35580 expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
35581
35582 const Type v = temp->value();
35583
35584 details::free_node(*node_allocator_,temp);
35585
35586 result = node_allocator_->allocate<literal_node_t>(v);
35587 }
35588
35589 details::free_all_nodes(*node_allocator_,branch);
35590
35591 return result;
35592 }
35593
35594 inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35595 {
35596 const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str ();
35597 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
35598 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35599
35600 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35601
35602 free_node(*node_allocator_,branch[0]);
35603 free_node(*node_allocator_,branch[1]);
35604
35605 return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
35606 }
35607
35608 inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35609 {
35610 std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
35611 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
35612 range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35613
35614 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35615
35616 free_node(*node_allocator_,branch[0]);
35617
35618 return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
35619 }
35620
35621 inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35622 {
35623 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
35624 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
35625 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35626 const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
35627
35628 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35629 static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
35630
35631 free_node(*node_allocator_,branch[0]);
35632 free_node(*node_allocator_,branch[1]);
35633
35634 return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
35635 }
35636
35637 inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35638 {
35639 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
35640 const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str ();
35641 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35642
35643 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35644
35645 details::free_all_nodes(*node_allocator_,branch);
35646
35647 return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
35648 }
35649
35650 inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35651 {
35652 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
35653 const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
35654 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35655 const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35656
35657 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35658 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35659
35660 details::free_all_nodes(*node_allocator_,branch);
35661
35662 return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
35663 }
35664
35665 inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35666 {
35667 switch (opr)
35668 {
35669 #define case_stmt(op0,op1) \
35670 case op0 : return node_allocator_-> \
35671 allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
35672 (opr, branch[0], branch[1]); \
35673
35675 #undef case_stmt
35676 default : return error_node();
35677 }
35678 }
35679 #endif
35680
35681 #ifndef exprtk_disable_string_capabilities
35682 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35683 {
35684 if ((0 == branch[0]) || (0 == branch[1]))
35685 {
35686 details::free_all_nodes(*node_allocator_,branch);
35687
35688 return error_node();
35689 }
35690
35691 const bool b0_is_s = details::is_string_node (branch[0]);
35692 const bool b0_is_cs = details::is_const_string_node (branch[0]);
35693 const bool b0_is_sr = details::is_string_range_node (branch[0]);
35694 const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
35695
35696 const bool b1_is_s = details::is_string_node (branch[1]);
35697 const bool b1_is_cs = details::is_const_string_node (branch[1]);
35698 const bool b1_is_sr = details::is_string_range_node (branch[1]);
35699 const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
35700
35701 const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
35703 details::is_string_concat_node (branch[0]) ||
35707 details::is_string_vararg_node (branch[0]) ;
35708
35709 const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
35711 details::is_string_concat_node (branch[1]) ||
35715 details::is_string_vararg_node (branch[1]) ;
35716
35717 if (details::e_add == opr)
35718 {
35719 if (!b0_is_cs || !b1_is_cs)
35720 {
35721 return synthesize_expression<string_concat_node_t,2>(opr,branch);
35722 }
35723 }
35724
35725 if (b0_is_gen || b1_is_gen)
35726 {
35727 return synthesize_strogen_expression(opr,branch);
35728 }
35729 else if (b0_is_s)
35730 {
35731 if (b1_is_s ) return synthesize_sos_expression (opr,branch);
35732 else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
35733 else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
35734 else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
35735 }
35736 else if (b0_is_cs)
35737 {
35738 if (b1_is_s ) return synthesize_csos_expression (opr,branch);
35739 else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
35740 else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
35741 else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
35742 }
35743 else if (b0_is_sr)
35744 {
35745 if (b1_is_s ) return synthesize_sros_expression (opr,branch);
35746 else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
35747 else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
35748 else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
35749 }
35750 else if (b0_is_csr)
35751 {
35752 if (b1_is_s ) return synthesize_csros_expression (opr,branch);
35753 else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
35754 else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
35755 else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
35756 }
35757
35758 return error_node();
35759 }
35760 #else
35761 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
35762 {
35763 details::free_all_nodes(*node_allocator_,branch);
35764 return error_node();
35765 }
35766 #endif
35767
35768 #ifndef exprtk_disable_string_capabilities
35769 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
35770 {
35771 if (details::e_inrange != opr)
35772 return error_node();
35773 else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
35774 {
35775 details::free_all_nodes(*node_allocator_,branch);
35776
35777 return error_node();
35778 }
35779 else if (
35780 details::is_const_string_node(branch[0]) &&
35781 details::is_const_string_node(branch[1]) &&
35783 )
35784 {
35785 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35786 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35787 const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35788
35789 const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
35790
35791 details::free_all_nodes(*node_allocator_,branch);
35792
35793 return node_allocator_->allocate_c<details::literal_node<Type> >(v);
35794 }
35795 else if (
35796 details::is_string_node(branch[0]) &&
35797 details::is_string_node(branch[1]) &&
35798 details::is_string_node(branch[2])
35799 )
35800 {
35801 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
35802 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
35803 std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
35804
35805 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
35806
35807 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
35808 }
35809 else if (
35810 details::is_const_string_node(branch[0]) &&
35811 details::is_string_node(branch[1]) &&
35813 )
35814 {
35815 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35816 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
35817 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35818
35819 typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
35820
35821 details::free_node(*node_allocator_,branch[0]);
35822 details::free_node(*node_allocator_,branch[2]);
35823
35824 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
35825 }
35826 else if (
35827 details::is_string_node(branch[0]) &&
35828 details::is_const_string_node(branch[1]) &&
35829 details::is_string_node(branch[2])
35830 )
35831 {
35832 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
35833 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35834 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
35835
35836 typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
35837
35838 details::free_node(*node_allocator_,branch[1]);
35839
35840 return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
35841 }
35842 else if (
35843 details::is_string_node(branch[0]) &&
35844 details::is_string_node(branch[1]) &&
35846 )
35847 {
35848 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
35849 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
35850 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35851
35852 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
35853
35854 details::free_node(*node_allocator_,branch[2]);
35855
35856 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
35857 }
35858 else if (
35859 details::is_const_string_node(branch[0]) &&
35860 details:: is_string_node(branch[1]) &&
35861 details:: is_string_node(branch[2])
35862 )
35863 {
35864 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35865 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
35866 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
35867
35868 typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
35869
35870 details::free_node(*node_allocator_,branch[0]);
35871
35872 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
35873 }
35874 else
35875 return error_node();
35876 }
35877 #else
35878 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
35879 {
35880 details::free_all_nodes(*node_allocator_,branch);
35881 return error_node();
35882 }
35883 #endif
35884
35885 inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
35886 {
35887 /*
35888 Note: The following are the type promotion rules
35889 that relate to operations that include 'null':
35890 0. null ==/!= null --> true false
35891 1. null operation null --> null
35892 2. x ==/!= null --> true/false
35893 3. null ==/!= x --> true/false
35894 4. x operation null --> x
35895 5. null operation x --> x
35896 */
35897
35898 typedef typename details::null_eq_node<T> nulleq_node_t;
35899
35900 const bool b0_null = details::is_null_node(branch[0]);
35901 const bool b1_null = details::is_null_node(branch[1]);
35902
35903 if (b0_null && b1_null)
35904 {
35905 expression_node_ptr result = error_node();
35906
35907 if (details::e_eq == operation)
35908 result = node_allocator_->allocate_c<literal_node_t>(T(1));
35909 else if (details::e_ne == operation)
35910 result = node_allocator_->allocate_c<literal_node_t>(T(0));
35911
35912 if (result)
35913 {
35914 details::free_node(*node_allocator_,branch[0]);
35915 details::free_node(*node_allocator_,branch[1]);
35916
35917 return result;
35918 }
35919
35920 details::free_node(*node_allocator_,branch[1]);
35921
35922 return branch[0];
35923 }
35924 else if (details::e_eq == operation)
35925 {
35926 expression_node_ptr result = node_allocator_->
35927 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
35928
35929 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
35930
35931 return result;
35932 }
35933 else if (details::e_ne == operation)
35934 {
35935 expression_node_ptr result = node_allocator_->
35936 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
35937
35938 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
35939
35940 return result;
35941 }
35942 else if (b0_null)
35943 {
35944 details::free_node(*node_allocator_,branch[0]);
35945 branch[0] = branch[1];
35946 branch[1] = error_node();
35947 }
35948 else if (b1_null)
35949 {
35950 details::free_node(*node_allocator_,branch[1]);
35951 branch[1] = error_node();
35952 }
35953
35954 if (
35955 (details::e_add == operation) || (details::e_sub == operation) ||
35956 (details::e_mul == operation) || (details::e_div == operation) ||
35957 (details::e_mod == operation) || (details::e_pow == operation)
35958 )
35959 {
35960 return branch[0];
35961 }
35962
35963 details::free_node(*node_allocator_, branch[0]);
35964
35965 if (
35966 (details::e_lt == operation) || (details::e_lte == operation) ||
35967 (details::e_gt == operation) || (details::e_gte == operation) ||
35968 (details::e_and == operation) || (details::e_nand == operation) ||
35969 (details::e_or == operation) || (details::e_nor == operation) ||
35970 (details::e_xor == operation) || (details::e_xnor == operation) ||
35971 (details::e_in == operation) || (details::e_like == operation) ||
35972 (details::e_ilike == operation)
35973 )
35974 {
35975 return node_allocator_->allocate_c<literal_node_t>(T(0));
35976 }
35977
35978 return node_allocator_->allocate<details::null_node<Type> >();
35979 }
35980
35981 template <typename NodeType, std::size_t N>
35982 inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
35983 {
35984 if (
35985 (details::e_in == operation) ||
35986 (details::e_like == operation) ||
35987 (details::e_ilike == operation)
35988 )
35989 {
35990 free_all_nodes(*node_allocator_,branch);
35991
35992 return error_node();
35993 }
35994 else if (!details::all_nodes_valid<N>(branch))
35995 {
35996 free_all_nodes(*node_allocator_,branch);
35997
35998 return error_node();
35999 }
36000 else if ((details::e_default != operation))
36001 {
36002 // Attempt simple constant folding optimisation.
36003 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
36004
36005 if (is_constant_foldable<N>(branch))
36006 {
36007 const Type v = expression_point->value();
36008 details::free_node(*node_allocator_,expression_point);
36009
36010 return node_allocator_->allocate<literal_node_t>(v);
36011 }
36012 else
36013 return expression_point;
36014 }
36015 else
36016 return error_node();
36017 }
36018
36019 template <typename NodeType, std::size_t N>
36020 inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
36021 {
36022 if (!details::all_nodes_valid<N>(branch))
36023 {
36024 free_all_nodes(*node_allocator_,branch);
36025
36026 return error_node();
36027 }
36028
36029 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
36030
36031 // Attempt simple constant folding optimisation.
36032
36033 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
36034 function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
36035
36036 if (0 == func_node_ptr)
36037 {
36038 free_all_nodes(*node_allocator_,branch);
36039
36040 return error_node();
36041 }
36042 else
36043 func_node_ptr->init_branches(branch);
36044
36045 if (is_constant_foldable<N>(branch) && !f->has_side_effects())
36046 {
36047 Type v = expression_point->value();
36048 details::free_node(*node_allocator_,expression_point);
36049
36050 return node_allocator_->allocate<literal_node_t>(v);
36051 }
36052
36053 parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
36054
36055 return expression_point;
36056 }
36057
36058 bool strength_reduction_enabled_;
36059 details::node_allocator* node_allocator_;
36060 synthesize_map_t synthesize_map_;
36061 unary_op_map_t* unary_op_map_;
36062 binary_op_map_t* binary_op_map_;
36063 inv_binary_op_map_t* inv_binary_op_map_;
36064 sf3_map_t* sf3_map_;
36065 sf4_map_t* sf4_map_;
36066 parser_t* parser_;
36067 };
36068
36069 inline void set_error(const parser_error::type& error_type)
36070 {
36071 error_list_.push_back(error_type);
36072 }
36073
36074 inline void remove_last_error()
36075 {
36076 if (!error_list_.empty())
36077 {
36078 error_list_.pop_back();
36079 }
36080 }
36081
36082 inline void set_synthesis_error(const std::string& synthesis_error_message)
36083 {
36084 if (synthesis_error_.empty())
36085 {
36086 synthesis_error_ = synthesis_error_message;
36087 }
36088 }
36089
36090 inline void register_local_vars(expression<T>& e)
36091 {
36092 for (std::size_t i = 0; i < sem_.size(); ++i)
36093 {
36094 scope_element& se = sem_.get_element(i);
36095
36096 if (
36097 (scope_element::e_variable == se.type) ||
36098 (scope_element::e_vecelem == se.type)
36099 )
36100 {
36101 if (se.var_node)
36102 {
36103 e.register_local_var(se.var_node);
36104 }
36105
36106 if (se.data)
36107 {
36108 e.register_local_data(se.data, 1, 0);
36109 }
36110 }
36111 else if (scope_element::e_vector == se.type)
36112 {
36113 if (se.vec_node)
36114 {
36115 e.register_local_var(se.vec_node);
36116 }
36117
36118 if (se.data)
36119 {
36120 e.register_local_data(se.data, se.size, 1);
36121 }
36122 }
36123 #ifndef exprtk_disable_string_capabilities
36124 else if (scope_element::e_string == se.type)
36125 {
36126 if (se.str_node)
36127 {
36128 e.register_local_var(se.str_node);
36129 }
36130
36131 if (se.data)
36132 {
36133 e.register_local_data(se.data, se.size, 2);
36134 }
36135 }
36136 #endif
36137
36138 se.var_node = 0;
36139 se.vec_node = 0;
36140 #ifndef exprtk_disable_string_capabilities
36141 se.str_node = 0;
36142 #endif
36143 se.data = 0;
36144 se.ref_count = 0;
36145 se.active = false;
36146 }
36147 }
36148
36149 inline void register_return_results(expression<T>& e)
36150 {
36151 e.register_return_results(results_context_);
36152 results_context_ = 0;
36153 }
36154
36155 inline void load_unary_operations_map(unary_op_map_t& m)
36156 {
36157 #define register_unary_op(Op,UnaryFunctor) \
36158 m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
36159
36160 register_unary_op(details:: e_abs, details:: abs_op)
36161 register_unary_op(details:: e_acos, details:: acos_op)
36162 register_unary_op(details::e_acosh, details::acosh_op)
36163 register_unary_op(details:: e_asin, details:: asin_op)
36164 register_unary_op(details::e_asinh, details::asinh_op)
36165 register_unary_op(details::e_atanh, details::atanh_op)
36166 register_unary_op(details:: e_ceil, details:: ceil_op)
36167 register_unary_op(details:: e_cos, details:: cos_op)
36168 register_unary_op(details:: e_cosh, details:: cosh_op)
36169 register_unary_op(details:: e_exp, details:: exp_op)
36170 register_unary_op(details::e_expm1, details::expm1_op)
36171 register_unary_op(details::e_floor, details::floor_op)
36172 register_unary_op(details:: e_log, details:: log_op)
36173 register_unary_op(details::e_log10, details::log10_op)
36174 register_unary_op(details:: e_log2, details:: log2_op)
36175 register_unary_op(details::e_log1p, details::log1p_op)
36176 register_unary_op(details:: e_neg, details:: neg_op)
36177 register_unary_op(details:: e_pos, details:: pos_op)
36178 register_unary_op(details::e_round, details::round_op)
36179 register_unary_op(details:: e_sin, details:: sin_op)
36180 register_unary_op(details:: e_sinc, details:: sinc_op)
36181 register_unary_op(details:: e_sinh, details:: sinh_op)
36182 register_unary_op(details:: e_sqrt, details:: sqrt_op)
36183 register_unary_op(details:: e_tan, details:: tan_op)
36184 register_unary_op(details:: e_tanh, details:: tanh_op)
36185 register_unary_op(details:: e_cot, details:: cot_op)
36186 register_unary_op(details:: e_sec, details:: sec_op)
36187 register_unary_op(details:: e_csc, details:: csc_op)
36188 register_unary_op(details:: e_r2d, details:: r2d_op)
36189 register_unary_op(details:: e_d2r, details:: d2r_op)
36190 register_unary_op(details:: e_d2g, details:: d2g_op)
36191 register_unary_op(details:: e_g2d, details:: g2d_op)
36192 register_unary_op(details:: e_notl, details:: notl_op)
36193 register_unary_op(details:: e_sgn, details:: sgn_op)
36194 register_unary_op(details:: e_erf, details:: erf_op)
36195 register_unary_op(details:: e_erfc, details:: erfc_op)
36196 register_unary_op(details:: e_ncdf, details:: ncdf_op)
36197 register_unary_op(details:: e_frac, details:: frac_op)
36198 register_unary_op(details::e_trunc, details::trunc_op)
36199 #undef register_unary_op
36200 }
36201
36202 inline void load_binary_operations_map(binary_op_map_t& m)
36203 {
36204 typedef typename binary_op_map_t::value_type value_type;
36205
36206 #define register_binary_op(Op,BinaryFunctor) \
36207 m.insert(value_type(Op,BinaryFunctor<T>::process)); \
36208
36209 register_binary_op(details:: e_add, details:: add_op)
36210 register_binary_op(details:: e_sub, details:: sub_op)
36211 register_binary_op(details:: e_mul, details:: mul_op)
36212 register_binary_op(details:: e_div, details:: div_op)
36213 register_binary_op(details:: e_mod, details:: mod_op)
36214 register_binary_op(details:: e_pow, details:: pow_op)
36215 register_binary_op(details:: e_lt, details:: lt_op)
36216 register_binary_op(details:: e_lte, details:: lte_op)
36217 register_binary_op(details:: e_gt, details:: gt_op)
36218 register_binary_op(details:: e_gte, details:: gte_op)
36219 register_binary_op(details:: e_eq, details:: eq_op)
36220 register_binary_op(details:: e_ne, details:: ne_op)
36221 register_binary_op(details:: e_and, details:: and_op)
36222 register_binary_op(details::e_nand, details::nand_op)
36223 register_binary_op(details:: e_or, details:: or_op)
36224 register_binary_op(details:: e_nor, details:: nor_op)
36225 register_binary_op(details:: e_xor, details:: xor_op)
36226 register_binary_op(details::e_xnor, details::xnor_op)
36227 #undef register_binary_op
36228 }
36229
36230 inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
36231 {
36232 typedef typename inv_binary_op_map_t::value_type value_type;
36233
36234 #define register_binary_op(Op,BinaryFunctor) \
36235 m.insert(value_type(BinaryFunctor<T>::process,Op)); \
36236
36237 register_binary_op(details:: e_add, details:: add_op)
36238 register_binary_op(details:: e_sub, details:: sub_op)
36239 register_binary_op(details:: e_mul, details:: mul_op)
36240 register_binary_op(details:: e_div, details:: div_op)
36241 register_binary_op(details:: e_mod, details:: mod_op)
36242 register_binary_op(details:: e_pow, details:: pow_op)
36243 register_binary_op(details:: e_lt, details:: lt_op)
36244 register_binary_op(details:: e_lte, details:: lte_op)
36245 register_binary_op(details:: e_gt, details:: gt_op)
36246 register_binary_op(details:: e_gte, details:: gte_op)
36247 register_binary_op(details:: e_eq, details:: eq_op)
36248 register_binary_op(details:: e_ne, details:: ne_op)
36249 register_binary_op(details:: e_and, details:: and_op)
36250 register_binary_op(details::e_nand, details::nand_op)
36251 register_binary_op(details:: e_or, details:: or_op)
36252 register_binary_op(details:: e_nor, details:: nor_op)
36253 register_binary_op(details:: e_xor, details:: xor_op)
36254 register_binary_op(details::e_xnor, details::xnor_op)
36255 #undef register_binary_op
36256 }
36257
36258 inline void load_sf3_map(sf3_map_t& sf3_map)
36259 {
36260 typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
36261
36262 #define register_sf3(Op) \
36263 sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36264
36273 #undef register_sf3
36274
36275 #define register_sf3_extid(Id, Op) \
36276 sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36277
36278 register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
36279 #undef register_sf3_extid
36280 }
36281
36282 inline void load_sf4_map(sf4_map_t& sf4_map)
36283 {
36284 typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
36285
36286 #define register_sf4(Op) \
36287 sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36288
36298 #undef register_sf4
36299
36300 #define register_sf4ext(Op) \
36301 sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
36302
36319 #undef register_sf4ext
36320 }
36321
36322 inline results_context_t& results_ctx()
36323 {
36324 if (0 == results_context_)
36325 {
36326 results_context_ = new results_context_t();
36327 }
36328
36329 return (*results_context_);
36330 }
36331
36332 inline void return_cleanup()
36333 {
36334 #ifndef exprtk_disable_return_statement
36335 if (results_context_)
36336 {
36337 delete results_context_;
36338 results_context_ = 0;
36339 }
36340
36341 state_.return_stmt_present = false;
36342 #endif
36343 }
36344
36345 private:
36346
36347 parser(const parser<T>&);
36348 parser<T>& operator=(const parser<T>&);
36349
36350 settings_store settings_;
36351 expression_generator<T> expression_generator_;
36352 details::node_allocator node_allocator_;
36353 symtab_store symtab_store_;
36354 dependent_entity_collector dec_;
36355 std::deque<parser_error::type> error_list_;
36356 std::deque<bool> brkcnt_list_;
36357 parser_state state_;
36358 bool resolve_unknown_symbol_;
36359 results_context_t* results_context_;
36360 unknown_symbol_resolver* unknown_symbol_resolver_;
36361 unknown_symbol_resolver default_usr_;
36362 base_ops_map_t base_ops_map_;
36363 unary_op_map_t unary_op_map_;
36364 binary_op_map_t binary_op_map_;
36365 inv_binary_op_map_t inv_binary_op_map_;
36366 sf3_map_t sf3_map_;
36367 sf4_map_t sf4_map_;
36368 std::string synthesis_error_;
36369 scope_element_manager sem_;
36370
36371 lexer::helper::helper_assembly helper_assembly_;
36372
36373 lexer::helper::commutative_inserter commutative_inserter_;
36374 lexer::helper::operator_joiner operator_joiner_2_;
36375 lexer::helper::operator_joiner operator_joiner_3_;
36376 lexer::helper::symbol_replacer symbol_replacer_;
36377 lexer::helper::bracket_checker bracket_checker_;
36378 lexer::helper::numeric_checker numeric_checker_;
36379 lexer::helper::sequence_validator sequence_validator_;
36380 lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
36381
36382 loop_runtime_check_ptr loop_runtime_check_;
36383
36384 template <typename ParserType>
36385 friend void details::disable_type_checking(ParserType& p);
36386 };
36387
36388 namespace details
36389 {
36390 template <typename T>
36391 struct collector_helper
36396 typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
36404 : usr_t(usr_t::e_usrmode_extended)
36405 {}
36407 virtual bool process(const std::string& unknown_symbol,
36409 std::string&)
36410 {
36411 static T v[1];
36412 symbol_table.add_vector(unknown_symbol,v);
36413 return true;
36414 }
36415 };
36417 static inline bool collection_pass(const std::string& expression_string,
36418 std::set<std::string>& symbol_set,
36419 const bool collect_variables,
36420 const bool collect_functions,
36421 const bool vector_pass,
36422 symbol_table_t& ext_symbol_table)
36423 {
36427
36428 resolve_as_vector vect_resolver;
36429
36431 expression.register_symbol_table(ext_symbol_table);
36432
36433 if (vector_pass)
36434 parser.enable_unknown_symbol_resolver(&vect_resolver);
36435 else
36437
36439 parser.dec().collect_variables() = true;
36440
36442 parser.dec().collect_functions() = true;
36443
36444 bool pass_result = false;
36445
36447
36448 if (parser.compile(expression_string, expression))
36449 {
36450 pass_result = true;
36451
36452 std::deque<symbol_t> symb_list;
36453 parser.dec().symbols(symb_list);
36454
36455 for (std::size_t i = 0; i < symb_list.size(); ++i)
36456 {
36457 symbol_set.insert(symb_list[i].first);
36458 }
36459 }
36460
36461 return pass_result;
36462 }
36463 };
36464 }
36465
36466 template <typename Allocator,
36467 template <typename, typename> class Sequence>
36468 inline bool collect_variables(const std::string& expression,
36469 Sequence<std::string, Allocator>& symbol_list)
36470 {
36471 typedef double T;
36472 typedef details::collector_helper<T> collect_t;
36473
36474 collect_t::symbol_table_t null_symbol_table;
36475
36476 std::set<std::string> symbol_set;
36477
36478 const bool variable_pass = collect_t::collection_pass
36479 (expression, symbol_set, true, false, false, null_symbol_table);
36480 const bool vector_pass = collect_t::collection_pass
36481 (expression, symbol_set, true, false, true, null_symbol_table);
36482
36483 if (!variable_pass && !vector_pass)
36484 return false;
36485
36486 std::set<std::string>::iterator itr = symbol_set.begin();
36487
36488 while (symbol_set.end() != itr)
36489 {
36490 symbol_list.push_back(*itr);
36491 ++itr;
36492 }
36493
36494 return true;
36495 }
36496
36497 template <typename T,
36498 typename Allocator,
36499 template <typename, typename> class Sequence>
36500 inline bool collect_variables(const std::string& expression,
36501 exprtk::symbol_table<T>& extrnl_symbol_table,
36502 Sequence<std::string, Allocator>& symbol_list)
36503 {
36504 typedef details::collector_helper<T> collect_t;
36505
36506 std::set<std::string> symbol_set;
36507
36508 const bool variable_pass = collect_t::collection_pass
36509 (expression, symbol_set, true, false, false, extrnl_symbol_table);
36510 const bool vector_pass = collect_t::collection_pass
36511 (expression, symbol_set, true, false, true, extrnl_symbol_table);
36512
36513 if (!variable_pass && !vector_pass)
36514 return false;
36515
36516 std::set<std::string>::iterator itr = symbol_set.begin();
36517
36518 while (symbol_set.end() != itr)
36519 {
36520 symbol_list.push_back(*itr);
36521 ++itr;
36522 }
36523
36524 return true;
36525 }
36526
36527 template <typename Allocator,
36528 template <typename, typename> class Sequence>
36529 inline bool collect_functions(const std::string& expression,
36530 Sequence<std::string, Allocator>& symbol_list)
36531 {
36532 typedef double T;
36533 typedef details::collector_helper<T> collect_t;
36534
36535 collect_t::symbol_table_t null_symbol_table;
36536
36537 std::set<std::string> symbol_set;
36538
36539 const bool variable_pass = collect_t::collection_pass
36540 (expression, symbol_set, false, true, false, null_symbol_table);
36541 const bool vector_pass = collect_t::collection_pass
36542 (expression, symbol_set, false, true, true, null_symbol_table);
36543
36544 if (!variable_pass && !vector_pass)
36545 return false;
36546
36547 std::set<std::string>::iterator itr = symbol_set.begin();
36548
36549 while (symbol_set.end() != itr)
36550 {
36551 symbol_list.push_back(*itr);
36552 ++itr;
36553 }
36554
36555 return true;
36556 }
36557
36558 template <typename T,
36559 typename Allocator,
36560 template <typename, typename> class Sequence>
36561 inline bool collect_functions(const std::string& expression,
36562 exprtk::symbol_table<T>& extrnl_symbol_table,
36563 Sequence<std::string, Allocator>& symbol_list)
36564 {
36565 typedef details::collector_helper<T> collect_t;
36566
36567 std::set<std::string> symbol_set;
36568
36569 const bool variable_pass = collect_t::collection_pass
36570 (expression, symbol_set, false, true, false, extrnl_symbol_table);
36571 const bool vector_pass = collect_t::collection_pass
36572 (expression, symbol_set, false, true, true, extrnl_symbol_table);
36573
36574 if (!variable_pass && !vector_pass)
36575 return false;
36576
36577 std::set<std::string>::iterator itr = symbol_set.begin();
36578
36579 while (symbol_set.end() != itr)
36580 {
36581 symbol_list.push_back(*itr);
36582 ++itr;
36583 }
36584
36585 return true;
36586 }
36587
36588 template <typename T>
36589 inline T integrate(const expression<T>& e,
36590 T& x,
36591 const T& r0, const T& r1,
36592 const std::size_t number_of_intervals = 1000000)
36593 {
36594 if (r0 > r1)
36595 return T(0);
36596
36597 const T h = (r1 - r0) / (T(2) * number_of_intervals);
36598 T total_area = T(0);
36599
36600 for (std::size_t i = 0; i < number_of_intervals; ++i)
36601 {
36602 x = r0 + T(2) * i * h;
36603 const T y0 = e.value(); x += h;
36604 const T y1 = e.value(); x += h;
36605 const T y2 = e.value(); x += h;
36606 total_area += h * (y0 + T(4) * y1 + y2) / T(3);
36607 }
36608
36609 return total_area;
36610 }
36611
36612 template <typename T>
36613 inline T integrate(const expression<T>& e,
36614 const std::string& variable_name,
36615 const T& r0, const T& r1,
36616 const std::size_t number_of_intervals = 1000000)
36617 {
36618 const symbol_table<T>& sym_table = e.get_symbol_table();
36619
36620 if (!sym_table.valid())
36621 return std::numeric_limits<T>::quiet_NaN();
36622
36623 details::variable_node<T>* var = sym_table.get_variable(variable_name);
36624
36625 if (var)
36626 {
36627 T& x = var->ref();
36628 const T x_original = x;
36629 const T result = integrate(e, x, r0, r1, number_of_intervals);
36630 x = x_original;
36631
36632 return result;
36633 }
36634 else
36635 return std::numeric_limits<T>::quiet_NaN();
36636 }
36637
36638 template <typename T>
36639 inline T derivative(const expression<T>& e,
36640 T& x,
36641 const T& h = T(0.00000001))
36642 {
36643 const T x_init = x;
36644 const T _2h = T(2) * h;
36645
36646 x = x_init + _2h;
36647 const T y0 = e.value();
36648 x = x_init + h;
36649 const T y1 = e.value();
36650 x = x_init - h;
36651 const T y2 = e.value();
36652 x = x_init - _2h;
36653 const T y3 = e.value();
36654 x = x_init;
36655
36656 return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
36657 }
36658
36659 template <typename T>
36660 inline T second_derivative(const expression<T>& e,
36661 T& x,
36662 const T& h = T(0.00001))
36663 {
36664 const T x_init = x;
36665 const T _2h = T(2) * h;
36666
36667 const T y = e.value();
36668 x = x_init + _2h;
36669 const T y0 = e.value();
36670 x = x_init + h;
36671 const T y1 = e.value();
36672 x = x_init - h;
36673 const T y2 = e.value();
36674 x = x_init - _2h;
36675 const T y3 = e.value();
36676 x = x_init;
36677
36678 return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
36679 }
36680
36681 template <typename T>
36682 inline T third_derivative(const expression<T>& e,
36683 T& x,
36684 const T& h = T(0.0001))
36685 {
36686 const T x_init = x;
36687 const T _2h = T(2) * h;
36688
36689 x = x_init + _2h;
36690 const T y0 = e.value();
36691 x = x_init + h;
36692 const T y1 = e.value();
36693 x = x_init - h;
36694 const T y2 = e.value();
36695 x = x_init - _2h;
36696 const T y3 = e.value();
36697 x = x_init;
36698
36699 return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
36700 }
36701
36702 template <typename T>
36703 inline T derivative(const expression<T>& e,
36704 const std::string& variable_name,
36705 const T& h = T(0.00000001))
36706 {
36707 const symbol_table<T>& sym_table = e.get_symbol_table();
36708
36709 if (!sym_table.valid())
36710 {
36711 return std::numeric_limits<T>::quiet_NaN();
36712 }
36713
36714 details::variable_node<T>* var = sym_table.get_variable(variable_name);
36715
36716 if (var)
36717 {
36718 T& x = var->ref();
36719 const T x_original = x;
36720 const T result = derivative(e, x, h);
36721 x = x_original;
36722
36723 return result;
36724 }
36725 else
36726 return std::numeric_limits<T>::quiet_NaN();
36727 }
36728
36729 template <typename T>
36730 inline T second_derivative(const expression<T>& e,
36731 const std::string& variable_name,
36732 const T& h = T(0.00001))
36733 {
36734 const symbol_table<T>& sym_table = e.get_symbol_table();
36735
36736 if (!sym_table.valid())
36737 {
36738 return std::numeric_limits<T>::quiet_NaN();
36739 }
36740
36741 details::variable_node<T>* var = sym_table.get_variable(variable_name);
36742
36743 if (var)
36744 {
36745 T& x = var->ref();
36746 const T x_original = x;
36747 const T result = second_derivative(e, x, h);
36748 x = x_original;
36749
36750 return result;
36751 }
36752 else
36753 return std::numeric_limits<T>::quiet_NaN();
36754 }
36755
36756 template <typename T>
36757 inline T third_derivative(const expression<T>& e,
36758 const std::string& variable_name,
36759 const T& h = T(0.0001))
36760 {
36761 const symbol_table<T>& sym_table = e.get_symbol_table();
36762
36763 if (!sym_table.valid())
36764 {
36765 return std::numeric_limits<T>::quiet_NaN();
36766 }
36767
36768 details::variable_node<T>* var = sym_table.get_variable(variable_name);
36769
36770 if (var)
36771 {
36772 T& x = var->ref();
36773 const T x_original = x;
36774 const T result = third_derivative(e, x, h);
36775 x = x_original;
36776
36777 return result;
36778 }
36779 else
36780 return std::numeric_limits<T>::quiet_NaN();
36781 }
36782
36783 /*
36784 Note: The following 'compute' routines are simple helpers,
36785 for quickly setting up the required pieces of code in order
36786 to evaluate an expression. By virtue of how they operate
36787 there will be an overhead with regards to their setup and
36788 teardown and hence should not be used in time critical
36789 sections of code.
36790 Furthermore they only assume a small sub set of variables,
36791 no string variables or user defined functions.
36792 */
36793 template <typename T>
36794 inline bool compute(const std::string& expression_string, T& result)
36795 {
36796 // No variables
36799
36802
36804
36805 if (parser.compile(expression_string,expression))
36806 {
36807 result = expression.value();
36808
36809 return true;
36810 }
36811 else
36812 return false;
36813 }
36814
36815 template <typename T>
36816 inline bool compute(const std::string& expression_string,
36817 const T& x,
36818 T& result)
36819 {
36820 // Only 'x'
36821 static const std::string x_var("x");
36822
36826
36829
36831
36832 if (parser.compile(expression_string,expression))
36833 {
36834 result = expression.value();
36835
36836 return true;
36837 }
36838 else
36839 return false;
36840 }
36841
36842 template <typename T>
36843 inline bool compute(const std::string& expression_string,
36844 const T&x, const T& y,
36845 T& result)
36846 {
36847 // Only 'x' and 'y'
36848 static const std::string x_var("x");
36849 static const std::string y_var("y");
36850
36854 symbol_table.add_constant(y_var,y);
36855
36858
36860
36861 if (parser.compile(expression_string,expression))
36862 {
36863 result = expression.value();
36864
36865 return true;
36866 }
36867 else
36868 return false;
36869 }
36870
36871 template <typename T>
36872 inline bool compute(const std::string& expression_string,
36873 const T& x, const T& y, const T& z,
36874 T& result)
36875 {
36876 // Only 'x', 'y' or 'z'
36877 static const std::string x_var("x");
36878 static const std::string y_var("y");
36879 static const std::string z_var("z");
36880
36884 symbol_table.add_constant(y_var,y);
36886
36889
36891
36892 if (parser.compile(expression_string,expression))
36893 {
36894 result = expression.value();
36895
36896 return true;
36897 }
36898 else
36899 return false;
36900 }
36901
36902 template <typename T, std::size_t N>
36903 class polynomial : public ifunction<T>
36904 {
36905 private:
36906
36907 template <typename Type, std::size_t NumberOfCoefficients>
36908 struct poly_impl { };
36909
36910 template <typename Type>
36911 struct poly_impl <Type,12>
36912 {
36913 static inline T evaluate(const Type x,
36914 const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
36915 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36916 const Type c2, const Type c1, const Type c0)
36917 {
36918 // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36919 return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36920 }
36921 };
36922
36923 template <typename Type>
36924 struct poly_impl <Type,11>
36925 {
36926 static inline T evaluate(const Type x,
36927 const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
36928 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36929 const Type c1, const Type c0)
36930 {
36931 // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36932 return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36933 }
36934 };
36935
36936 template <typename Type>
36937 struct poly_impl <Type,10>
36938 {
36939 static inline T evaluate(const Type x,
36940 const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
36941 const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
36942 const Type c0)
36943 {
36944 // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36945 return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36946 }
36947 };
36948
36949 template <typename Type>
36950 struct poly_impl <Type,9>
36951 {
36952 static inline T evaluate(const Type x,
36953 const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
36954 const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
36955 {
36956 // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36957 return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36958 }
36959 };
36960
36961 template <typename Type>
36962 struct poly_impl <Type,8>
36963 {
36964 static inline T evaluate(const Type x,
36965 const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
36966 const Type c3, const Type c2, const Type c1, const Type c0)
36967 {
36968 // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36969 return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36970 }
36971 };
36972
36973 template <typename Type>
36974 struct poly_impl <Type,7>
36975 {
36976 static inline T evaluate(const Type x,
36977 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36978 const Type c2, const Type c1, const Type c0)
36979 {
36980 // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36981 return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36982 }
36983 };
36984
36985 template <typename Type>
36986 struct poly_impl <Type,6>
36987 {
36988 static inline T evaluate(const Type x,
36989 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36990 const Type c1, const Type c0)
36991 {
36992 // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36993 return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36994 }
36995 };
36996
36997 template <typename Type>
36998 struct poly_impl <Type,5>
36999 {
37000 static inline T evaluate(const Type x,
37001 const Type c5, const Type c4, const Type c3, const Type c2,
37002 const Type c1, const Type c0)
37003 {
37004 // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37005 return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
37006 }
37007 };
37008
37009 template <typename Type>
37010 struct poly_impl <Type,4>
37011 {
37012 static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
37013 {
37014 // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37015 return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
37016 }
37017 };
37018
37019 template <typename Type>
37020 struct poly_impl <Type,3>
37021 {
37022 static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
37023 {
37024 // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37025 return (((c3 * x + c2) * x + c1) * x + c0);
37026 }
37027 };
37028
37029 template <typename Type>
37030 struct poly_impl <Type,2>
37031 {
37032 static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
37033 {
37034 // p(x) = c_2x^2 + c_1x^1 + c_0x^0
37035 return ((c2 * x + c1) * x + c0);
37036 }
37037 };
37038
37039 template <typename Type>
37040 struct poly_impl <Type,1>
37041 {
37042 static inline T evaluate(const Type x, const Type c1, const Type c0)
37043 {
37044 // p(x) = c_1x^1 + c_0x^0
37045 return (c1 * x + c0);
37046 }
37047 };
37048
37049 public:
37050
37051 using ifunction<T>::operator();
37053 polynomial()
37054 : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
37055 {
37057 }
37059 virtual ~polynomial()
37060 {}
37062 #define poly_rtrn(NN) \
37063 return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
37065 inline virtual T operator() (const T& x, const T& c1, const T& c0)
37066 {
37067 poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
37068 }
37070 inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
37071 {
37072 poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
37073 }
37075 inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
37076 {
37077 poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
37078 }
37080 inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37081 {
37082 poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
37083 }
37085 inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37086 {
37087 poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
37088 }
37090 inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37091 {
37092 poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
37093 }
37095 inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37096 {
37097 poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
37098 }
37100 inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37101 {
37102 poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37103 }
37105 inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37106 {
37107 poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37108 }
37110 inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37111 {
37112 poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37113 }
37115 inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37116 {
37117 poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37118 }
37120 inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37121 {
37122 poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37123 }
37124
37125 #undef poly_rtrn
37127 inline virtual T operator() ()
37128 {
37129 return std::numeric_limits<T>::quiet_NaN();
37130 }
37132 inline virtual T operator() (const T&)
37133 {
37134 return std::numeric_limits<T>::quiet_NaN();
37135 }
37137 inline virtual T operator() (const T&, const T&)
37138 {
37139 return std::numeric_limits<T>::quiet_NaN();
37140 }
37141 };
37142
37143 template <typename T>
37145 {
37146 public:
37151 typedef typename parser_t::settings_store settings_t;
37153 struct function
37155 function()
37156 {}
37158 function(const std::string& n)
37159 : name_(n)
37160 {}
37162 function(const std::string& name,
37163 const std::string& expression)
37164 : name_(name),
37165 expression_(expression)
37166 {}
37168 function(const std::string& name,
37169 const std::string& expression,
37170 const std::string& v0)
37171 : name_(name),
37172 expression_(expression)
37173 {
37174 v_.push_back(v0);
37175 }
37177 function(const std::string& name,
37178 const std::string& expression,
37179 const std::string& v0, const std::string& v1)
37180 : name_(name),
37181 expression_(expression)
37182 {
37183 v_.push_back(v0); v_.push_back(v1);
37184 }
37186 function(const std::string& name,
37187 const std::string& expression,
37188 const std::string& v0, const std::string& v1,
37189 const std::string& v2)
37190 : name_(name),
37191 expression_(expression)
37192 {
37193 v_.push_back(v0); v_.push_back(v1);
37194 v_.push_back(v2);
37195 }
37197 function(const std::string& name,
37198 const std::string& expression,
37199 const std::string& v0, const std::string& v1,
37200 const std::string& v2, const std::string& v3)
37201 : name_(name),
37202 expression_(expression)
37203 {
37204 v_.push_back(v0); v_.push_back(v1);
37205 v_.push_back(v2); v_.push_back(v3);
37206 }
37208 function(const std::string& name,
37209 const std::string& expression,
37210 const std::string& v0, const std::string& v1,
37211 const std::string& v2, const std::string& v3,
37212 const std::string& v4)
37213 : name_(name),
37214 expression_(expression)
37215 {
37216 v_.push_back(v0); v_.push_back(v1);
37217 v_.push_back(v2); v_.push_back(v3);
37218 v_.push_back(v4);
37219 }
37221 inline function& name(const std::string& n)
37222 {
37223 name_ = n;
37224 return (*this);
37225 }
37227 inline function& expression(const std::string& e)
37228 {
37229 expression_ = e;
37230 return (*this);
37231 }
37233 inline function& var(const std::string& v)
37234 {
37235 v_.push_back(v);
37236 return (*this);
37237 }
37240 std::string expression_;
37241 std::deque<std::string> v_;
37242 };
37243
37244 private:
37245
37246 struct base_func : public exprtk::ifunction<T>
37247 {
37248 typedef const T& type;
37249 typedef exprtk::ifunction<T> function_t;
37250 typedef std::vector<T*> varref_t;
37251 typedef std::vector<T> var_t;
37252 typedef std::pair<T*,std::size_t> lvarref_t;
37253 typedef std::vector<lvarref_t> lvr_vec_t;
37254
37255 using exprtk::ifunction<T>::operator();
37256
37257 base_func(const std::size_t& pc = 0)
37259 local_var_stack_size(0),
37260 stack_depth(0)
37261 {
37262 v.resize(pc);
37263 }
37264
37265 virtual ~base_func()
37266 {}
37267
37268 inline void update(const T& v0)
37269 {
37270 (*v[0]) = v0;
37271 }
37272
37273 inline void update(const T& v0, const T& v1)
37274 {
37275 (*v[0]) = v0; (*v[1]) = v1;
37276 }
37277
37278 inline void update(const T& v0, const T& v1, const T& v2)
37279 {
37280 (*v[0]) = v0; (*v[1]) = v1;
37281 (*v[2]) = v2;
37282 }
37283
37284 inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
37285 {
37286 (*v[0]) = v0; (*v[1]) = v1;
37287 (*v[2]) = v2; (*v[3]) = v3;
37288 }
37289
37290 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
37291 {
37292 (*v[0]) = v0; (*v[1]) = v1;
37293 (*v[2]) = v2; (*v[3]) = v3;
37294 (*v[4]) = v4;
37295 }
37296
37297 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
37298 {
37299 (*v[0]) = v0; (*v[1]) = v1;
37300 (*v[2]) = v2; (*v[3]) = v3;
37301 (*v[4]) = v4; (*v[5]) = v5;
37302 }
37303
37304 inline function_t& setup(expression_t& expr)
37305 {
37306 expression = expr;
37307
37308 typedef typename expression_t::control_block::local_data_list_t ldl_t;
37309
37310 const ldl_t ldl = expr.local_data_list();
37311
37312 std::vector<std::size_t> index_list;
37313
37314 for (std::size_t i = 0; i < ldl.size(); ++i)
37315 {
37316 if (ldl[i].size)
37317 {
37318 index_list.push_back(i);
37319 }
37320 }
37321
37322 std::size_t input_param_count = 0;
37323
37324 for (std::size_t i = 0; i < index_list.size(); ++i)
37325 {
37326 const std::size_t index = index_list[i];
37327
37328 if (i < (index_list.size() - v.size()))
37329 {
37330 lv.push_back(
37331 std::make_pair(
37332 reinterpret_cast<T*>(ldl[index].pointer),
37333 ldl[index].size));
37334
37335 local_var_stack_size += ldl[index].size;
37336 }
37337 else
37338 v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
37339 }
37340
37341 clear_stack();
37342
37343 return (*this);
37344 }
37345
37346 inline void pre()
37347 {
37348 if (stack_depth++)
37349 {
37350 if (!v.empty())
37351 {
37352 var_t var_stack(v.size(),T(0));
37353 copy(v,var_stack);
37354 param_stack.push_back(var_stack);
37355 }
37356
37357 if (!lv.empty())
37358 {
37359 var_t local_var_stack(local_var_stack_size,T(0));
37360 copy(lv,local_var_stack);
37361 local_stack.push_back(local_var_stack);
37362 }
37363 }
37364 }
37365
37366 inline void post()
37367 {
37368 if (--stack_depth)
37369 {
37370 if (!v.empty())
37371 {
37372 copy(param_stack.back(),v);
37373 param_stack.pop_back();
37374 }
37375
37376 if (!lv.empty())
37377 {
37378 copy(local_stack.back(),lv);
37379 local_stack.pop_back();
37380 }
37381 }
37382 }
37383
37384 void copy(const varref_t& src_v, var_t& dest_v)
37385 {
37386 for (std::size_t i = 0; i < src_v.size(); ++i)
37387 {
37388 dest_v[i] = (*src_v[i]);
37389 }
37390 }
37391
37392 void copy(const var_t& src_v, varref_t& dest_v)
37393 {
37394 for (std::size_t i = 0; i < src_v.size(); ++i)
37395 {
37396 (*dest_v[i]) = src_v[i];
37397 }
37398 }
37399
37400 void copy(const lvr_vec_t& src_v, var_t& dest_v)
37401 {
37402 typename var_t::iterator itr = dest_v.begin();
37403 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
37404
37405 for (std::size_t i = 0; i < src_v.size(); ++i)
37406 {
37407 lvarref_t vr = src_v[i];
37408
37409 if (1 == vr.second)
37410 *itr++ = (*vr.first);
37411 else
37412 {
37413 std::copy(vr.first, vr.first + vr.second, itr);
37414 itr += static_cast<diff_t>(vr.second);
37415 }
37416 }
37417 }
37418
37419 void copy(const var_t& src_v, lvr_vec_t& dest_v)
37420 {
37421 typename var_t::const_iterator itr = src_v.begin();
37422 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
37423
37424 for (std::size_t i = 0; i < src_v.size(); ++i)
37425 {
37426 lvarref_t vr = dest_v[i];
37427
37428 if (1 == vr.second)
37429 (*vr.first) = *itr++;
37430 else
37431 {
37432 std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
37433 itr += static_cast<diff_t>(vr.second);
37434 }
37435 }
37436 }
37437
37438 inline void clear_stack()
37439 {
37440 for (std::size_t i = 0; i < v.size(); ++i)
37441 {
37442 (*v[i]) = 0;
37443 }
37444 }
37445
37446 inline virtual T value(expression_t& e)
37447 {
37448 return e.value();
37449 }
37450
37451 expression_t expression;
37452 varref_t v;
37453 lvr_vec_t lv;
37454 std::size_t local_var_stack_size;
37455 std::size_t stack_depth;
37456 std::deque<var_t> param_stack;
37457 std::deque<var_t> local_stack;
37458 };
37459
37460 typedef std::map<std::string,base_func*> funcparam_t;
37461
37462 struct func_0param : public base_func
37463 {
37464 using exprtk::ifunction<T>::operator();
37465
37466 func_0param() : base_func(0) {}
37467
37468 inline T operator() ()
37469 {
37470 return this->value(base_func::expression);
37471 }
37472 };
37473
37474 typedef const T& type;
37475
37476 template <typename BaseFuncType>
37477 struct scoped_bft
37478 {
37479 explicit scoped_bft(BaseFuncType& bft)
37480 : bft_(bft)
37481 {
37482 bft_.pre ();
37483 }
37484
37485 ~scoped_bft()
37486 {
37487 bft_.post();
37488 }
37489
37490 BaseFuncType& bft_;
37491
37492 private:
37493
37494 scoped_bft(scoped_bft&);
37495 scoped_bft& operator=(scoped_bft&);
37496 };
37497
37498 struct func_1param : public base_func
37499 {
37500 using exprtk::ifunction<T>::operator();
37501
37502 func_1param() : base_func(1) {}
37503
37504 inline T operator() (type v0)
37505 {
37506 scoped_bft<func_1param> sb(*this);
37507 base_func::update(v0);
37508 return this->value(base_func::expression);
37509 }
37510 };
37511
37512 struct func_2param : public base_func
37513 {
37514 using exprtk::ifunction<T>::operator();
37515
37516 func_2param() : base_func(2) {}
37517
37518 inline T operator() (type v0, type v1)
37519 {
37520 scoped_bft<func_2param> sb(*this);
37521 base_func::update(v0, v1);
37522 return this->value(base_func::expression);
37523 }
37524 };
37525
37526 struct func_3param : public base_func
37527 {
37528 using exprtk::ifunction<T>::operator();
37529
37530 func_3param() : base_func(3) {}
37531
37532 inline T operator() (type v0, type v1, type v2)
37533 {
37534 scoped_bft<func_3param> sb(*this);
37535 base_func::update(v0, v1, v2);
37536 return this->value(base_func::expression);
37537 }
37538 };
37539
37540 struct func_4param : public base_func
37541 {
37542 using exprtk::ifunction<T>::operator();
37543
37544 func_4param() : base_func(4) {}
37545
37546 inline T operator() (type v0, type v1, type v2, type v3)
37547 {
37548 scoped_bft<func_4param> sb(*this);
37549 base_func::update(v0, v1, v2, v3);
37550 return this->value(base_func::expression);
37551 }
37552 };
37553
37554 struct func_5param : public base_func
37555 {
37556 using exprtk::ifunction<T>::operator();
37557
37558 func_5param() : base_func(5) {}
37559
37560 inline T operator() (type v0, type v1, type v2, type v3, type v4)
37561 {
37562 scoped_bft<func_5param> sb(*this);
37563 base_func::update(v0, v1, v2, v3, v4);
37564 return this->value(base_func::expression);
37565 }
37566 };
37567
37568 struct func_6param : public base_func
37569 {
37570 using exprtk::ifunction<T>::operator();
37571
37572 func_6param() : base_func(6) {}
37573
37574 inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
37575 {
37576 scoped_bft<func_6param> sb(*this);
37577 base_func::update(v0, v1, v2, v3, v4, v5);
37578 return this->value(base_func::expression);
37579 }
37580 };
37581
37582 static T return_value(expression_t& e)
37583 {
37584 typedef exprtk::results_context<T> results_context_t;
37585 typedef typename results_context_t::type_store_t type_t;
37586 typedef typename type_t::scalar_view scalar_t;
37587
37588 const T result = e.value();
37589
37590 if (e.return_invoked())
37591 {
37592 // Due to the post compilation checks, it can be safely
37593 // assumed that there will be at least one parameter
37594 // and that the first parameter will always be scalar.
37595 return scalar_t(e.results()[0])();
37596 }
37597
37598 return result;
37599 }
37601 #define def_fp_retval(N) \
37602 struct func_##N##param_retval : public func_##N##param \
37603 { \
37604 inline T value(expression_t& e) \
37605 { \
37606 return return_value(e); \
37607 } \
37608 }; \
37609
37610 def_fp_retval(0)
37611 def_fp_retval(1)
37612 def_fp_retval(2)
37613 def_fp_retval(3)
37614 def_fp_retval(4)
37615 def_fp_retval(5)
37616 def_fp_retval(6)
37617
37618 template <typename Allocator,
37619 template <typename, typename> class Sequence>
37620 inline bool add(const std::string& name,
37621 const std::string& expression,
37622 const Sequence<std::string,Allocator>& var_list,
37623 const bool override = false)
37624 {
37625 const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
37626
37627 if (expr_map_.end() != itr)
37628 {
37629 if (!override)
37630 {
37631 exprtk_debug(("Compositor error(add): function '%s' already defined\n",
37632 name.c_str()));
37633
37634 return false;
37635 }
37636
37637 remove(name, var_list.size());
37638 }
37639
37640 if (compile_expression(name,expression,var_list))
37641 {
37642 const std::size_t n = var_list.size();
37643
37644 fp_map_[n][name]->setup(expr_map_[name]);
37645
37646 return true;
37647 }
37648 else
37649 {
37650 exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
37651 name.c_str()));
37652
37653 return false;
37654 }
37655 }
37656
37657 public:
37660 : parser_(settings_t::compile_all_opts +
37661 settings_t::e_disable_zero_return),
37662 fp_map_(7)
37663 {}
37666 : symbol_table_(st),
37667 parser_(settings_t::compile_all_opts +
37668 settings_t::e_disable_zero_return),
37669 fp_map_(7)
37670 {}
37673 {
37674 clear();
37675 }
37678 {
37679 return symbol_table_;
37680 }
37682 inline const symbol_table_t& symbol_table() const
37683 {
37684 return symbol_table_;
37685 }
37687 inline void add_auxiliary_symtab(symbol_table_t& symtab)
37688 {
37689 auxiliary_symtab_list_.push_back(&symtab);
37690 }
37692 void clear()
37693 {
37694 symbol_table_.clear();
37695 expr_map_ .clear();
37696
37697 for (std::size_t i = 0; i < fp_map_.size(); ++i)
37698 {
37699 typename funcparam_t::iterator itr = fp_map_[i].begin();
37700 typename funcparam_t::iterator end = fp_map_[i].end ();
37701
37702 while (itr != end)
37703 {
37704 delete itr->second;
37705 ++itr;
37706 }
37707
37708 fp_map_[i].clear();
37709 }
37710 }
37712 inline bool add(const function& f, const bool override = false)
37713 {
37714 return add(f.name_, f.expression_, f.v_,override);
37715 }
37716
37717 private:
37718
37719 template <typename Allocator,
37720 template <typename, typename> class Sequence>
37721 bool compile_expression(const std::string& name,
37722 const std::string& expression,
37723 const Sequence<std::string,Allocator>& input_var_list,
37724 bool return_present = false)
37725 {
37726 expression_t compiled_expression;
37727 symbol_table_t local_symbol_table;
37728
37729 local_symbol_table.load_from(symbol_table_);
37730 local_symbol_table.add_constants();
37731
37732 if (!valid(name,input_var_list.size()))
37733 return false;
37734
37735 if (!forward(name,
37736 input_var_list.size(),
37737 local_symbol_table,
37738 return_present))
37739 return false;
37740
37741 compiled_expression.register_symbol_table(local_symbol_table);
37742
37743 for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
37744 {
37745 compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
37746 }
37747
37748 std::string mod_expression;
37749
37750 for (std::size_t i = 0; i < input_var_list.size(); ++i)
37751 {
37752 mod_expression += " var " + input_var_list[i] + "{};\n";
37753 }
37754
37755 if (
37756 ('{' == details::front(expression)) &&
37757 ('}' == details::back (expression))
37758 )
37759 mod_expression += "~" + expression + ";";
37760 else
37761 mod_expression += "~{" + expression + "};";
37762
37763 if (!parser_.compile(mod_expression,compiled_expression))
37764 {
37765 exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
37766 exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
37767
37768 remove(name,input_var_list.size());
37769
37770 return false;
37771 }
37772
37773 if (!return_present && parser_.dec().return_present())
37774 {
37775 remove(name,input_var_list.size());
37776
37777 return compile_expression(name, expression, input_var_list, true);
37778 }
37779
37780 // Make sure every return point has a scalar as its first parameter
37781 if (parser_.dec().return_present())
37782 {
37783 typedef std::vector<std::string> str_list_t;
37784
37785 str_list_t ret_param_list = parser_.dec().return_param_type_list();
37786
37787 for (std::size_t i = 0; i < ret_param_list.size(); ++i)
37788 {
37789 const std::string& params = ret_param_list[i];
37790
37791 if (params.empty() || ('T' != params[0]))
37792 {
37793 exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
37794 name.c_str()));
37795
37796 remove(name,input_var_list.size());
37797
37798 return false;
37799 }
37800 }
37801 }
37802
37803 expr_map_[name] = compiled_expression;
37804
37805 exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
37806
37807 if (symbol_table_.add_function(name,ifunc))
37808 return true;
37809 else
37810 {
37811 exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
37812 name.c_str()));
37813 return false;
37814 }
37815 }
37816
37817 inline bool symbol_used(const std::string& symbol) const
37818 {
37819 return (
37820 symbol_table_.is_variable (symbol) ||
37821 symbol_table_.is_stringvar (symbol) ||
37822 symbol_table_.is_function (symbol) ||
37823 symbol_table_.is_vector (symbol) ||
37824 symbol_table_.is_vararg_function(symbol)
37825 );
37826 }
37827
37828 inline bool valid(const std::string& name,
37829 const std::size_t& arg_count) const
37830 {
37831 if (arg_count > 6)
37832 return false;
37833 else if (symbol_used(name))
37834 return false;
37835 else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
37836 return false;
37837 else
37838 return true;
37839 }
37840
37841 inline bool forward(const std::string& name,
37842 const std::size_t& arg_count,
37843 symbol_table_t& sym_table,
37844 const bool ret_present = false)
37845 {
37846 switch (arg_count)
37847 {
37848 #define case_stmt(N) \
37849 case N : (fp_map_[arg_count])[name] = \
37850 (!ret_present) ? static_cast<base_func*> \
37851 (new func_##N##param) : \
37852 static_cast<base_func*> \
37853 (new func_##N##param_retval) ; \
37854 break; \
37855
37858 case_stmt(6)
37859 #undef case_stmt
37860 }
37861
37862 exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
37863
37864 return sym_table.add_function(name,ifunc);
37865 }
37866
37867 inline void remove(const std::string& name, const std::size_t& arg_count)
37868 {
37869 if (arg_count > 6)
37870 return;
37871
37872 const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
37873
37874 if (expr_map_.end() != em_itr)
37875 {
37876 expr_map_.erase(em_itr);
37877 }
37878
37879 const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
37880
37881 if (fp_map_[arg_count].end() != fp_itr)
37882 {
37883 delete fp_itr->second;
37884 fp_map_[arg_count].erase(fp_itr);
37885 }
37886
37887 symbol_table_.remove_function(name);
37888 }
37889
37890 private:
37891
37892 symbol_table_t symbol_table_;
37893 parser_t parser_;
37894 std::map<std::string,expression_t> expr_map_;
37895 std::vector<funcparam_t> fp_map_;
37896 std::vector<symbol_table_t*> auxiliary_symtab_list_;
37897 };
37898
37899 template <typename T>
37900 inline bool pgo_primer()
37901 {
37902 static const std::string expression_list[] =
37903 {
37904 "(y + x)",
37905 "2 * (y + x)",
37906 "(2 * y + 2 * x)",
37907 "(y + x / y) * (x - y / x)",
37908 "x / ((x + y) * (x - y)) / y",
37909 "1 - ((x * y) + (y / x)) - 3",
37910 "sin(2 * x) + cos(pi / y)",
37911 "1 - sin(2 * x) + cos(pi / y)",
37912 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
37913 "(x^2 / sin(2 * pi / y)) -x / 2",
37914 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
37915 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
37916 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
37917 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
37918 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
37919 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
37920 "(yy + xx)",
37921 "2 * (yy + xx)",
37922 "(2 * yy + 2 * xx)",
37923 "(yy + xx / yy) * (xx - yy / xx)",
37924 "xx / ((xx + yy) * (xx - yy)) / yy",
37925 "1 - ((xx * yy) + (yy / xx)) - 3",
37926 "sin(2 * xx) + cos(pi / yy)",
37927 "1 - sin(2 * xx) + cos(pi / yy)",
37928 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
37929 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
37930 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
37931 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
37932 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
37933 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
37934 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
37935 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
37936 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
37937 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
37938 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
37939 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
37940 "(x + 2) * 3", "x + (2 * 3)",
37941 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
37942 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
37943 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
37944 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
37945 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
37946 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
37947 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
37948 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
37949 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
37950 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
37951 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
37952 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
37953 "((x + (2 * 3)) / y)",
37954 "(xx + yy) * zz", "xx + (yy * zz)",
37955 "(xx + yy) * 7", "xx + (yy * 7)",
37956 "(xx + 7) * yy", "xx + (7 * yy)",
37957 "(7 + xx) * yy", "7 + (xx * yy)",
37958 "(2 + x) * 3", "2 + (x * 3)",
37959 "(2 + 3) * x", "2 + (3 * x)",
37960 "(x + 2) * 3", "x + (2 * 3)",
37961 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
37962 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
37963 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
37964 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
37965 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
37966 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
37967 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
37968 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
37969 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
37970 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
37971 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
37972 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
37973 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
37974 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
37975 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
37976 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
37977 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
37978 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
37979 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
37980 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
37981 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
37982 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
37983 "((xx + (2 * 3)) / yy)"
37984 };
37985
37986 static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
37987
37988 T x = T(0);
37989 T y = T(0);
37990 T z = T(0);
37991 T w = T(0);
37992 T xx = T(0);
37993 T yy = T(0);
37994 T zz = T(0);
37995 T ww = T(0);
37996
38000 symbol_table.add_variable( "y", y);
38002 symbol_table.add_variable( "w", w);
38003 symbol_table.add_variable("xx",xx);
38004 symbol_table.add_variable("yy",yy);
38005 symbol_table.add_variable("zz",zz);
38006 symbol_table.add_variable("ww",ww);
38007
38008 typedef typename std::deque<exprtk::expression<T> > expr_list_t;
38009 expr_list_t expr_list;
38010
38011 const std::size_t rounds = 50;
38012
38013 {
38014 for (std::size_t r = 0; r < rounds; ++r)
38015 {
38016 expr_list.clear();
38018
38019 for (std::size_t i = 0; i < expression_list_size; ++i)
38020 {
38023
38024 if (!parser.compile(expression_list[i],expression))
38025 {
38026 return false;
38027 }
38028
38029 expr_list.push_back(expression);
38030 }
38031 }
38032 }
38033
38034 struct execute
38035 {
38036 static inline T process(T& x, T& y, expression<T>& expression)
38037 {
38038 static const T lower_bound = T(-20);
38039 static const T upper_bound = T(+20);
38040 static const T delta = T(0.1);
38041
38042 T total = T(0);
38043
38044 for (x = lower_bound; x <= upper_bound; x += delta)
38045 {
38046 for (y = lower_bound; y <= upper_bound; y += delta)
38047 {
38048 total += expression.value();
38049 }
38050 }
38051
38052 return total;
38053 }
38054 };
38055
38056 for (std::size_t i = 0; i < expr_list.size(); ++i)
38057 {
38058 execute::process( x, y, expr_list[i]);
38059 execute::process(xx, yy, expr_list[i]);
38060 }
38061
38062 {
38063 for (std::size_t i = 0; i < 10000; ++i)
38064 {
38065 const T v = T(123.456 + i);
38066
38068 return false;
38069
38070 #define else_stmt(N) \
38071 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
38072 return false; \
38073
38074 else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
38075 else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
38076 else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
38077 else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
38078 else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
38079 else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
38080 else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
38081 else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
38082 else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
38083 else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
38084 else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
38085 else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
38086 else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
38087 else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
38088 else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
38089 }
38090 }
38091
38092 return true;
38093 }
38094}
38095
38096#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
38097# ifndef NOMINMAX
38098# define NOMINMAX
38099# endif
38100# ifndef WIN32_LEAN_AND_MEAN
38101# define WIN32_LEAN_AND_MEAN
38102# endif
38103# include <windows.h>
38104# include <ctime>
38105#else
38106# include <ctime>
38107# include <sys/time.h>
38108# include <sys/types.h>
38109#endif
38110
38111namespace exprtk
38112{
38113 class timer
38114 {
38115 public:
38116
38117 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
38118 timer()
38119 : in_use_(false)
38120 {
38121 QueryPerformanceFrequency(&clock_frequency_);
38122 }
38123
38124 inline void start()
38125 {
38126 in_use_ = true;
38127 QueryPerformanceCounter(&start_time_);
38128 }
38129
38130 inline void stop()
38131 {
38132 QueryPerformanceCounter(&stop_time_);
38133 in_use_ = false;
38134 }
38135
38136 inline double time() const
38137 {
38138 return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
38139 }
38140
38141 #else
38142
38144 : in_use_(false)
38145 {
38146 start_time_.tv_sec = 0;
38147 start_time_.tv_usec = 0;
38148 stop_time_.tv_sec = 0;
38149 stop_time_.tv_usec = 0;
38150 }
38151
38152 inline void start()
38153 {
38154 in_use_ = true;
38155 gettimeofday(&start_time_,0);
38156 }
38157
38158 inline void stop()
38159 {
38160 gettimeofday(&stop_time_, 0);
38161 in_use_ = false;
38162 }
38163
38164 inline unsigned long long int usec_time() const
38165 {
38166 if (!in_use_)
38167 {
38168 if (stop_time_.tv_sec >= start_time_.tv_sec)
38169 {
38170 return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) +
38171 static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
38172 }
38173 else
38175 }
38176 else
38178 }
38179
38180 inline double time() const
38181 {
38182 return usec_time() * 0.000001;
38183 }
38184
38185 #endif
38186
38187 inline bool in_use() const
38188 {
38189 return in_use_;
38190 }
38191
38192 private:
38193
38194 bool in_use_;
38195
38196 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
38197 LARGE_INTEGER start_time_;
38198 LARGE_INTEGER stop_time_;
38199 LARGE_INTEGER clock_frequency_;
38200 #else
38201 struct timeval start_time_;
38202 struct timeval stop_time_;
38203 #endif
38204 };
38205
38206} // namespace exprtk
38207
38208#ifndef exprtk_disable_rtl_io
38209namespace exprtk
38210{
38211 namespace rtl { namespace io { namespace details
38212 {
38213 template <typename T>
38214 inline void print_type(const std::string& fmt,
38215 const T v,
38217 {
38218 printf(fmt.c_str(),v);
38219 }
38220
38221 template <typename T>
38223 {
38230
38231 static void process(const std::string& scalar_format, parameter_list_t parameters)
38232 {
38233 for (std::size_t i = 0; i < parameters.size(); ++i)
38234 {
38235 generic_type& gt = parameters[i];
38236
38237 switch (gt.type)
38238 {
38239 case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
38240 break;
38241
38242 case generic_type::e_vector : print(scalar_format,vector_t(gt));
38243 break;
38244
38246 break;
38247
38248 default : continue;
38249 }
38250 }
38251 }
38252
38253 static inline void print(const std::string& scalar_format, const scalar_t& s)
38254 {
38255 print_type(scalar_format,s(),num_type());
38256 }
38257
38258 static inline void print(const std::string& scalar_format, const vector_t& v)
38259 {
38260 for (std::size_t i = 0; i < v.size(); ++i)
38261 {
38262 print_type(scalar_format,v[i],num_type());
38263
38264 if ((i + 1) < v.size())
38265 printf(" ");
38266 }
38267 }
38268
38269 static inline void print(const string_t& s)
38270 {
38271 printf("%s",to_str(s).c_str());
38272 }
38273 };
38274
38275 } // namespace exprtk::rtl::io::details
38276
38277 template <typename T>
38279 {
38281
38282 using exprtk::igeneric_function<T>::operator();
38283
38284 print(const std::string& scalar_format = "%10.5f")
38285 : scalar_format_(scalar_format)
38286 {
38288 }
38289
38290 inline T operator() (parameter_list_t parameters)
38291 {
38293 return T(0);
38294 }
38295
38297 };
38298
38299 template <typename T>
38301 {
38303
38304 using exprtk::igeneric_function<T>::operator();
38305
38306 println(const std::string& scalar_format = "%10.5f")
38307 : scalar_format_(scalar_format)
38308 {
38310 }
38311
38312 inline T operator() (parameter_list_t parameters)
38313 {
38315 printf("\n");
38316 return T(0);
38317 }
38318
38320 };
38321
38322 template <typename T>
38323 struct package
38324 {
38327
38329 {
38330 #define exprtk_register_function(FunctionName,FunctionType) \
38331 if (!symtab.add_function(FunctionName,FunctionType)) \
38332 { \
38333 exprtk_debug(( \
38334 "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
38335 FunctionName)); \
38336 return false; \
38337 } \
38338
38339 exprtk_register_function("print" , p)
38340 exprtk_register_function("println", pl)
38341 #undef exprtk_register_function
38342
38343 return true;
38344 }
38345 };
38346
38347 } // namespace exprtk::rtl::io
38348 } // namespace exprtk::rtl
38349} // namespace exprtk
38350#endif
38351
38352#ifndef exprtk_disable_rtl_io_file
38353#include <fstream>
38354namespace exprtk
38355{
38356 namespace rtl { namespace io { namespace file { namespace details
38357 {
38359 {
38363 e_rdwrt = 4
38365
38367 {
38368 file_descriptor(const std::string& fname, const std::string& access)
38369 : stream_ptr(0),
38370 mode(get_file_mode(access)),
38371 file_name(fname)
38372 {}
38373
38377
38378 bool open()
38379 {
38380 if (e_read == mode)
38381 {
38382 std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
38383
38384 if (!(*stream))
38385 {
38386 file_name.clear();
38387 delete stream;
38388
38389 return false;
38390 }
38391 else
38392 stream_ptr = stream;
38393
38394 return true;
38395 }
38396 else if (e_write == mode)
38397 {
38398 std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
38399
38400 if (!(*stream))
38401 {
38402 file_name.clear();
38403 delete stream;
38404
38405 return false;
38406 }
38407 else
38408 stream_ptr = stream;
38409
38410 return true;
38411 }
38412 else if (e_rdwrt == mode)
38413 {
38414 std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
38415
38416 if (!(*stream))
38417 {
38418 file_name.clear();
38419 delete stream;
38420
38421 return false;
38422 }
38423 else
38424 stream_ptr = stream;
38425
38426 return true;
38427 }
38428 else
38429 return false;
38430 }
38431
38432 template <typename Stream, typename Ptr>
38433 void close(Ptr& p)
38434 {
38435 Stream* stream = reinterpret_cast<Stream*>(p);
38436 stream->close();
38437 delete stream;
38438 p = reinterpret_cast<Ptr>(0);
38439 }
38440
38441 bool close()
38442 {
38443 switch (mode)
38444 {
38446 break;
38447
38449 break;
38450
38452 break;
38453
38454 default : return false;
38455 }
38456
38457 return true;
38458 }
38459
38460 template <typename View>
38461 bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
38462 {
38463 switch (mode)
38464 {
38465 case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
38466 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
38467 break;
38468
38469 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
38470 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
38471 break;
38472
38473 default : return false;
38474 }
38475
38476 return true;
38477 }
38478
38479 template <typename View>
38480 bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
38481 {
38482 switch (mode)
38483 {
38484 case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
38485 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
38486 break;
38487
38488 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
38489 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
38490 break;
38491
38492 default : return false;
38493 }
38494
38495 return true;
38496 }
38497
38499 {
38500 switch (mode)
38501 {
38502 case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
38503 case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
38504 default : return false;
38505 }
38506 }
38507
38508 bool eof() const
38509 {
38510 switch (mode)
38511 {
38512 case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
38513 case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
38514 case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
38515 default : return true;
38516 }
38517 }
38518
38520 {
38521 if (access.empty() || access.size() > 2)
38522 return e_error;
38523
38524 std::size_t w_cnt = 0;
38525 std::size_t r_cnt = 0;
38526
38527 for (std::size_t i = 0; i < access.size(); ++i)
38528 {
38529 switch (std::tolower(access[i]))
38530 {
38531 case 'r' : r_cnt++; break;
38532 case 'w' : w_cnt++; break;
38533 default : return e_error;
38534 }
38535 }
38536
38537 if ((0 == r_cnt) && (0 == w_cnt))
38538 return e_error;
38539 else if ((r_cnt > 1) || (w_cnt > 1))
38540 return e_error;
38541 else if ((1 == r_cnt) && (1 == w_cnt))
38542 return e_rdwrt;
38543 else if (1 == r_cnt)
38544 return e_read;
38545 else
38546 return e_write;
38547 }
38548 };
38549
38550 template <typename T>
38552 {
38553 file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
38554
38555 std::memcpy(reinterpret_cast<char*>(&fd),
38556 reinterpret_cast<const char*>(&v),
38557 sizeof(fd));
38558 return fd;
38559 }
38560
38561 template <typename T>
38563 {
38564 #ifdef _MSC_VER
38565 #pragma warning(push)
38566 #pragma warning(disable: 4127)
38567 #endif
38568 if (sizeof(T) < sizeof(void*))
38569 {
38570 throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
38571 }
38572 #ifdef _MSC_VER
38573 #pragma warning(pop)
38574 #endif
38575 }
38576
38577 } // namespace exprtk::rtl::io::file::details
38578
38579 template <typename T>
38581 {
38582 public:
38583
38588
38589 using exprtk::igeneric_function<T>::operator();
38590
38592 : exprtk::igeneric_function<T>("S|SS")
38593 { details::perform_check<T>(); }
38594
38595 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38596 {
38597 std::string file_name = to_str(string_t(parameters[0]));
38598 std::string access;
38599
38600 if (file_name.empty())
38601 return T(0);
38602
38603 if (0 == ps_index)
38604 access = "r";
38605 else if (0 == string_t(parameters[1]).size())
38606 return T(0);
38607 else
38608 access = to_str(string_t(parameters[1]));
38609
38610 details::file_descriptor* fd = new details::file_descriptor(file_name,access);
38611
38612 if (fd->open())
38613 {
38614 T t = T(0);
38615
38616 std::memcpy(reinterpret_cast<char*>(&t ),
38617 reinterpret_cast<char*>(&fd),
38618 sizeof(fd));
38619 return t;
38620 }
38621 else
38622 {
38623 delete fd;
38624 return T(0);
38625 }
38626 }
38627 };
38628
38629 template <typename T>
38630 struct close : public exprtk::ifunction<T>
38631 {
38632 using exprtk::ifunction<T>::operator();
38633
38635 : exprtk::ifunction<T>(1)
38636 { details::perform_check<T>(); }
38637
38638 inline T operator() (const T& v)
38639 {
38641
38642 if (!fd->close())
38643 return T(0);
38644
38645 delete fd;
38646
38647 return T(1);
38648 }
38649 };
38650
38651 template <typename T>
38653 {
38654 public:
38655
38662
38663 using exprtk::igeneric_function<T>::operator();
38664
38666 : igfun_t("TS|TST|TV|TVT")
38667 { details::perform_check<T>(); }
38668
38669 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38670 {
38672
38673 std::size_t amount = 0;
38674
38675 switch (ps_index)
38676 {
38677 case 0 : {
38678 const string_t buffer(parameters[1]);
38679 amount = buffer.size();
38680 return T(fd->write(buffer, amount) ? 1 : 0);
38681 }
38682
38683 case 1 : {
38684 const string_t buffer(parameters[1]);
38685 amount = std::min(buffer.size(),
38686 static_cast<std::size_t>(scalar_t(parameters[2])()));
38687 return T(fd->write(buffer, amount) ? 1 : 0);
38688 }
38689
38690 case 2 : {
38691 const vector_t vec(parameters[1]);
38692 amount = vec.size();
38693 return T(fd->write(vec, amount) ? 1 : 0);
38694 }
38695
38696 case 3 : {
38697 const vector_t vec(parameters[1]);
38698 amount = std::min(vec.size(),
38699 static_cast<std::size_t>(scalar_t(parameters[2])()));
38700 return T(fd->write(vec, amount) ? 1 : 0);
38701 }
38702 }
38703
38704 return T(0);
38705 }
38706 };
38707
38708 template <typename T>
38710 {
38711 public:
38712
38719
38720 using exprtk::igeneric_function<T>::operator();
38721
38723 : igfun_t("TS|TST|TV|TVT")
38724 { details::perform_check<T>(); }
38725
38726 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38727 {
38729
38730 std::size_t amount = 0;
38731
38732 switch (ps_index)
38733 {
38734 case 0 : {
38735 string_t buffer(parameters[1]);
38736 amount = buffer.size();
38737 return T(fd->read(buffer,amount) ? 1 : 0);
38738 }
38739
38740 case 1 : {
38741 string_t buffer(parameters[1]);
38742 amount = std::min(buffer.size(),
38743 static_cast<std::size_t>(scalar_t(parameters[2])()));
38744 return T(fd->read(buffer,amount) ? 1 : 0);
38745 }
38746
38747 case 2 : {
38748 vector_t vec(parameters[1]);
38749 amount = vec.size();
38750 return T(fd->read(vec,amount) ? 1 : 0);
38751 }
38752
38753 case 3 : {
38754 vector_t vec(parameters[1]);
38755 amount = std::min(vec.size(),
38756 static_cast<std::size_t>(scalar_t(parameters[2])()));
38757 return T(fd->read(vec,amount) ? 1 : 0);
38758 }
38759 }
38760
38761 return T(0);
38762 }
38763 };
38764
38765 template <typename T>
38767 {
38768 public:
38769
38775
38776 using exprtk::igeneric_function<T>::operator();
38777
38780 { details::perform_check<T>(); }
38781
38782 inline T operator() (std::string& result,
38783 parameter_list_t parameters)
38784 {
38786 return T(fd->getline(result) ? 1 : 0);
38787 }
38788 };
38789
38790 template <typename T>
38791 struct eof : public exprtk::ifunction<T>
38792 {
38793 using exprtk::ifunction<T>::operator();
38794
38796 : exprtk::ifunction<T>(1)
38797 { details::perform_check<T>(); }
38798
38799 inline T operator() (const T& v)
38800 {
38802
38803 return (fd->eof() ? T(1) : T(0));
38804 }
38805 };
38806
38807 template <typename T>
38808 struct package
38809 {
38816
38818 {
38819 #define exprtk_register_function(FunctionName,FunctionType) \
38820 if (!symtab.add_function(FunctionName,FunctionType)) \
38821 { \
38822 exprtk_debug(( \
38823 "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
38824 FunctionName)); \
38825 return false; \
38826 } \
38827
38829 exprtk_register_function("close" ,c)
38830 exprtk_register_function("write" ,w)
38832 exprtk_register_function("getline",g)
38834 #undef exprtk_register_function
38835
38836 return true;
38837 }
38838 };
38839
38840 } // namespace exprtk::rtl::io::file
38841 } // namespace exprtk::rtl::io
38842 } // namespace exprtk::rtl
38843} // namespace exprtk
38844#endif
38845
38846#ifndef exprtk_disable_rtl_vecops
38847namespace exprtk
38848{
38849 namespace rtl { namespace vecops {
38850
38851 namespace helper
38852 {
38853 template <typename Vector>
38854 inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
38855 {
38856 if (r0 > (v.size() - 1))
38857 return true;
38858 else if (r1 > (v.size() - 1))
38859 return true;
38860 else if (r1 < r0)
38861 return true;
38862 else
38863 return false;
38864 }
38865
38866 template <typename T>
38868 {
38874
38875 static inline bool process(parameter_list_t& parameters,
38876 std::size_t& r0, std::size_t& r1,
38877 const std::size_t& r0_prmidx,
38878 const std::size_t& r1_prmidx,
38879 const std::size_t vec_idx = 0)
38880 {
38881 if (r0_prmidx >= parameters.size())
38882 return false;
38883
38884 if (r1_prmidx >= parameters.size())
38885 return false;
38886
38887 if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
38888 return false;
38889
38890 if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
38891 return false;
38892
38893 return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
38894 }
38895 };
38896 }
38897
38898 namespace details
38899 {
38900 template <typename T>
38901 inline void kahan_sum(T& sum, T& error, const T v)
38902 {
38903 const T x = v - error;
38904 const T y = sum + x;
38905 error = (y - sum) - x;
38906 sum = y;
38907 }
38908
38909 } // namespace exprtk::rtl::details
38910
38911 template <typename T>
38913 {
38914 public:
38915
38920
38921 using exprtk::igeneric_function<T>::operator();
38922
38924 : exprtk::igeneric_function<T>("V|VTT")
38925 /*
38926 Overloads:
38927 0. V - vector
38928 1. VTT - vector, r0, r1
38929 */
38930 {}
38931
38932 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38933 {
38934 const vector_t vec(parameters[0]);
38935
38936 std::size_t r0 = 0;
38937 std::size_t r1 = vec.size() - 1;
38938
38939 if (
38940 (1 == ps_index) &&
38941 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38942 )
38943 return std::numeric_limits<T>::quiet_NaN();
38944
38945 for (std::size_t i = r0; i <= r1; ++i)
38946 {
38947 if (vec[i] == T(0))
38948 {
38949 return T(0);
38950 }
38951 }
38952
38953 return T(1);
38954 }
38955 };
38956
38957 template <typename T>
38959 {
38960 public:
38961
38966
38967 using exprtk::igeneric_function<T>::operator();
38968
38970 : exprtk::igeneric_function<T>("V|VTT")
38971 /*
38972 Overloads:
38973 0. V - vector
38974 1. VTT - vector, r0, r1
38975 */
38976 {}
38977
38978 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38979 {
38980 const vector_t vec(parameters[0]);
38981
38982 std::size_t r0 = 0;
38983 std::size_t r1 = vec.size() - 1;
38984
38985 if (
38986 (1 == ps_index) &&
38987 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38988 )
38989 return std::numeric_limits<T>::quiet_NaN();
38990
38991 for (std::size_t i = r0; i <= r1; ++i)
38992 {
38993 if (vec[i] != T(0))
38994 {
38995 return T(0);
38996 }
38997 }
38998
38999 return T(1);
39000 }
39001 };
39002
39003 template <typename T>
39005 {
39006 public:
39007
39012
39013 using exprtk::igeneric_function<T>::operator();
39014
39016 : exprtk::igeneric_function<T>("V|VTT")
39017 /*
39018 Overloads:
39019 0. V - vector
39020 1. VTT - vector, r0, r1
39021 */
39022 {}
39023
39024 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39025 {
39026 const vector_t vec(parameters[0]);
39027
39028 std::size_t r0 = 0;
39029 std::size_t r1 = vec.size() - 1;
39030
39031 if (
39032 (1 == ps_index) &&
39033 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39034 )
39035 return std::numeric_limits<T>::quiet_NaN();
39036
39037 for (std::size_t i = r0; i <= r1; ++i)
39038 {
39039 if (vec[i] != T(0))
39040 {
39041 return T(1);
39042 }
39043 }
39044
39045 return T(0);
39046 }
39047 };
39048
39049 template <typename T>
39051 {
39052 public:
39053
39058
39059 using exprtk::igeneric_function<T>::operator();
39060
39062 : exprtk::igeneric_function<T>("V|VTT")
39063 /*
39064 Overloads:
39065 0. V - vector
39066 1. VTT - vector, r0, r1
39067 */
39068 {}
39069
39070 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39071 {
39072 const vector_t vec(parameters[0]);
39073
39074 std::size_t r0 = 0;
39075 std::size_t r1 = vec.size() - 1;
39076
39077 if (
39078 (1 == ps_index) &&
39079 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39080 )
39081 return std::numeric_limits<T>::quiet_NaN();
39082
39083 for (std::size_t i = r0; i <= r1; ++i)
39084 {
39085 if (vec[i] == T(0))
39086 {
39087 return T(1);
39088 }
39089 }
39090
39091 return T(0);
39092 }
39093 };
39094
39095 template <typename T>
39097 {
39098 public:
39099
39104
39105 using exprtk::igeneric_function<T>::operator();
39106
39108 : exprtk::igeneric_function<T>("V|VTT")
39109 /*
39110 Overloads:
39111 0. V - vector
39112 1. VTT - vector, r0, r1
39113 */
39114 {}
39115
39116 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39117 {
39118 const vector_t vec(parameters[0]);
39119
39120 std::size_t r0 = 0;
39121 std::size_t r1 = vec.size() - 1;
39122
39123 if (
39124 (1 == ps_index) &&
39125 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39126 )
39127 return std::numeric_limits<T>::quiet_NaN();
39128
39129 std::size_t cnt = 0;
39130
39131 for (std::size_t i = r0; i <= r1; ++i)
39132 {
39133 if (vec[i] != T(0)) ++cnt;
39134 }
39135
39136 return T(cnt);
39137 }
39138 };
39139
39140 template <typename T>
39142 {
39143 public:
39144
39150
39151 using exprtk::igeneric_function<T>::operator();
39152
39154 : exprtk::igeneric_function<T>("VV|VTTVTT")
39155 /*
39156 Overloads:
39157 0. VV - x(vector), y(vector)
39158 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
39159 */
39160 {}
39161
39162 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39163 {
39164 const vector_t x(parameters[0]);
39165 vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
39166
39167 std::size_t xr0 = 0;
39168 std::size_t xr1 = x.size() - 1;
39169
39170 std::size_t yr0 = 0;
39171 std::size_t yr1 = y.size() - 1;
39172
39173 if (1 == ps_index)
39174 {
39175 if (
39176 !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
39177 !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
39178 )
39179 return T(0);
39180 }
39181
39182 const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
39183
39184 std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
39185
39186 return T(n);
39187 }
39188 };
39189
39190 template <typename T>
39192 {
39193 public:
39194
39200
39201 using exprtk::igeneric_function<T>::operator();
39202
39204 : exprtk::igeneric_function<T>("VT|VTTT")
39205 /*
39206 Overloads:
39207 0. VT - vector, N
39208 1. VTTT - vector, N, r0, r1
39209 */
39210 {}
39211
39212 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39213 {
39214 vector_t vec(parameters[0]);
39215
39216 std::size_t n = 0;
39217 std::size_t r0 = 0;
39218 std::size_t r1 = vec.size() - 1;
39219
39220 if (!scalar_t(parameters[1]).to_uint(n))
39221 return T(0);
39222
39223 if (
39224 (1 == ps_index) &&
39225 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39226 )
39227 return T(0);
39228
39229 const std::size_t dist = r1 - r0 + 1;
39230 const std::size_t shift = n % dist;
39231
39232 std::rotate(
39233 vec.begin() + r0,
39234 vec.begin() + r0 + shift,
39235 vec.begin() + r1 + 1);
39236
39237 return T(1);
39238 }
39239 };
39240
39241 template <typename T>
39243 {
39244 public:
39245
39251
39252 using exprtk::igeneric_function<T>::operator();
39253
39255 : exprtk::igeneric_function<T>("VT|VTTT")
39256 /*
39257 Overloads:
39258 0. VT - vector, N
39259 1. VTTT - vector, N, r0, r1
39260 */
39261 {}
39262
39263 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39264 {
39265 vector_t vec(parameters[0]);
39266
39267 std::size_t n = 0;
39268 std::size_t r0 = 0;
39269 std::size_t r1 = vec.size() - 1;
39270
39271 if (!scalar_t(parameters[1]).to_uint(n))
39272 return T(0);
39273
39274 if (
39275 (1 == ps_index) &&
39276 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39277 )
39278 return T(0);
39279
39280 std::size_t dist = r1 - r0 + 1;
39281 std::size_t shift = (dist - (n % dist)) % dist;
39282
39283 std::rotate(
39284 vec.begin() + r0,
39285 vec.begin() + r0 + shift,
39286 vec.begin() + r1 + 1);
39287
39288 return T(1);
39289 }
39290 };
39291
39292 template <typename T>
39294 {
39295 public:
39296
39302
39303 using exprtk::igeneric_function<T>::operator();
39304
39306 : exprtk::igeneric_function<T>("VT|VTTT")
39307 /*
39308 Overloads:
39309 0. VT - vector, N
39310 1. VTTT - vector, N, r0, r1
39311 */
39312 {}
39313
39314 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39315 {
39316 vector_t vec(parameters[0]);
39317
39318 std::size_t n = 0;
39319 std::size_t r0 = 0;
39320 std::size_t r1 = vec.size() - 1;
39321
39322 if (!scalar_t(parameters[1]).to_uint(n))
39323 return T(0);
39324
39325 if (
39326 (1 == ps_index) &&
39327 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39328 )
39329 return T(0);
39330
39331 const std::size_t dist = r1 - r0 + 1;
39332
39333 if (n > dist)
39334 return T(0);
39335
39336 std::rotate(
39337 vec.begin() + r0,
39338 vec.begin() + r0 + n,
39339 vec.begin() + r1 + 1);
39340
39341 for (std::size_t i = r1 - n + 1; i <= r1; ++i)
39342 {
39343 vec[i] = T(0);
39344 }
39345
39346 return T(1);
39347 }
39348 };
39349
39350 template <typename T>
39352 {
39353 public:
39354
39360
39361 using exprtk::igeneric_function<T>::operator();
39362
39364 : exprtk::igeneric_function<T>("VT|VTTT")
39365 /*
39366 Overloads:
39367 0. VT - vector, N
39368 1. VTTT - vector, N, r0, r1
39369 */
39370 {}
39371
39372 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39373 {
39374 vector_t vec(parameters[0]);
39375
39376 std::size_t n = 0;
39377 std::size_t r0 = 0;
39378 std::size_t r1 = vec.size() - 1;
39379
39380 if (!scalar_t(parameters[1]).to_uint(n))
39381 return T(0);
39382
39383 if (
39384 (1 == ps_index) &&
39385 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39386 )
39387 return T(0);
39388
39389 const std::size_t dist = r1 - r0 + 1;
39390
39391 if (n > dist)
39392 return T(0);
39393
39394 const std::size_t shift = (dist - (n % dist)) % dist;
39395
39396 std::rotate(
39397 vec.begin() + r0,
39398 vec.begin() + r0 + shift,
39399 vec.begin() + r1 + 1);
39400
39401 for (std::size_t i = r0; i < r0 + n; ++i)
39402 {
39403 vec[i] = T(0);
39404 }
39405
39406 return T(1);
39407 }
39408 };
39409
39410 template <typename T>
39412 {
39413 public:
39414
39420
39421 using exprtk::igeneric_function<T>::operator();
39422
39424 : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
39425 /*
39426 Overloads:
39427 0. V - vector
39428 1. VTT - vector, r0, r1
39429 2. VS - vector, string
39430 3. VSTT - vector, string, r0, r1
39431 */
39432 {}
39433
39434 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39435 {
39436 vector_t vec(parameters[0]);
39437
39438 std::size_t r0 = 0;
39439 std::size_t r1 = vec.size() - 1;
39440
39441 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
39442 return T(0);
39443 if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39444 return T(0);
39445
39446 bool ascending = true;
39447
39448 if ((2 == ps_index) || (3 == ps_index))
39449 {
39450 if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
39451 ascending = true;
39452 else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
39453 ascending = false;
39454 else
39455 return T(0);
39456 }
39457
39458 if (ascending)
39459 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ());
39460 else
39461 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
39462
39463 return T(1);
39464 }
39465 };
39466
39467 template <typename T>
39469 {
39470 public:
39471
39477
39478 using exprtk::igeneric_function<T>::operator();
39479
39481 : exprtk::igeneric_function<T>("VT|VTTT")
39482 /*
39483 Overloads:
39484 0. VT - vector, nth-element
39485 1. VTTT - vector, nth-element, r0, r1
39486 */
39487 {}
39488
39489 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39490 {
39491 vector_t vec(parameters[0]);
39492
39493 std::size_t n = 0;
39494 std::size_t r0 = 0;
39495 std::size_t r1 = vec.size() - 1;
39496
39497 if (!scalar_t(parameters[1]).to_uint(n))
39498 return T(0);
39499
39500 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39501 return std::numeric_limits<T>::quiet_NaN();
39502
39503 std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
39504
39505 return T(1);
39506 }
39507 };
39508
39509 template <typename T>
39511 {
39512 public:
39513
39519
39520 using exprtk::igeneric_function<T>::operator();
39521
39523 : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
39524 /*
39525 Overloads:
39526 0. VT - vector, increment
39527 1. VTT - vector, increment, base
39528 2. VTTTT - vector, increment, r0, r1
39529 3. VTTTT - vector, increment, base, r0, r1
39530 */
39531 {}
39532
39533 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39534 {
39535 vector_t vec(parameters[0]);
39536
39537 T increment = scalar_t(parameters[1])();
39538 T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
39539
39540 std::size_t r0 = 0;
39541 std::size_t r1 = vec.size() - 1;
39542
39543 if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39544 return std::numeric_limits<T>::quiet_NaN();
39545 else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
39546 return std::numeric_limits<T>::quiet_NaN();
39547 else
39548 {
39549 long long j = 0;
39550
39551 for (std::size_t i = r0; i <= r1; ++i, ++j)
39552 {
39553 vec[i] = base + (increment * j);
39554 }
39555 }
39556
39557 return T(1);
39558 }
39559 };
39560
39561 template <typename T>
39563 {
39564 public:
39565
39570
39571 using exprtk::igeneric_function<T>::operator();
39572
39574 : exprtk::igeneric_function<T>("V|VTT")
39575 /*
39576 Overloads:
39577 0. V - vector
39578 1. VTT - vector, r0, r1
39579 */
39580 {}
39581
39582 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39583 {
39584 const vector_t vec(parameters[0]);
39585
39586 std::size_t r0 = 0;
39587 std::size_t r1 = vec.size() - 1;
39588
39589 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
39590 return std::numeric_limits<T>::quiet_NaN();
39591
39592 T result = T(0);
39593 T error = T(0);
39594
39595 for (std::size_t i = r0; i <= r1; ++i)
39596 {
39597 details::kahan_sum(result, error, vec[i]);
39598 }
39599
39600 return result;
39601 }
39602 };
39603
39604 template <typename T>
39606 {
39607 public:
39608
39614
39615 using exprtk::igeneric_function<T>::operator();
39616
39618 : exprtk::igeneric_function<T>("TVV|TVVTT")
39619 /*
39620 y <- ax + y
39621 Overloads:
39622 0. TVV - a, x(vector), y(vector)
39623 1. TVVTT - a, x(vector), y(vector), r0, r1
39624 */
39625 {}
39626
39627 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39628 {
39629 const vector_t x(parameters[1]);
39630 vector_t y(parameters[2]);
39631
39632 std::size_t r0 = 0;
39633 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39634
39635 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
39636 return std::numeric_limits<T>::quiet_NaN();
39637 else if (helper::invalid_range(y, r0, r1))
39638 return std::numeric_limits<T>::quiet_NaN();
39639
39640 const T a = scalar_t(parameters[0])();
39641
39642 for (std::size_t i = r0; i <= r1; ++i)
39643 {
39644 y[i] = (a * x[i]) + y[i];
39645 }
39646
39647 return T(1);
39648 }
39649 };
39650
39651 template <typename T>
39653 {
39654 public:
39655
39661
39662 using exprtk::igeneric_function<T>::operator();
39663
39665 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
39666 /*
39667 y <- ax + by
39668 Overloads:
39669 0. TVTV - a, x(vector), b, y(vector)
39670 1. TVTVTT - a, x(vector), b, y(vector), r0, r1
39671 */
39672 {}
39673
39674 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39675 {
39676 const vector_t x(parameters[1]);
39677 vector_t y(parameters[3]);
39678
39679 std::size_t r0 = 0;
39680 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39681
39682 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39683 return std::numeric_limits<T>::quiet_NaN();
39684 else if (helper::invalid_range(y, r0, r1))
39685 return std::numeric_limits<T>::quiet_NaN();
39686
39687 const T a = scalar_t(parameters[0])();
39688 const T b = scalar_t(parameters[2])();
39689
39690 for (std::size_t i = r0; i <= r1; ++i)
39691 {
39692 y[i] = (a * x[i]) + (b * y[i]);
39693 }
39694
39695 return T(1);
39696 }
39697 };
39698
39699 template <typename T>
39701 {
39702 public:
39703
39709
39710 using exprtk::igeneric_function<T>::operator();
39711
39713 : exprtk::igeneric_function<T>("TVVV|TVVVTT")
39714 /*
39715 z <- ax + y
39716 Overloads:
39717 0. TVVV - a, x(vector), y(vector), z(vector)
39718 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
39719 */
39720 {}
39721
39722 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39723 {
39724 const vector_t x(parameters[1]);
39725 const vector_t y(parameters[2]);
39726 vector_t z(parameters[3]);
39727
39728 std::size_t r0 = 0;
39729 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39730
39731 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
39732 return std::numeric_limits<T>::quiet_NaN();
39733 else if (helper::invalid_range(y, r0, r1))
39734 return std::numeric_limits<T>::quiet_NaN();
39735 else if (helper::invalid_range(z, r0, r1))
39736 return std::numeric_limits<T>::quiet_NaN();
39737
39738 const T a = scalar_t(parameters[0])();
39739
39740 for (std::size_t i = r0; i <= r1; ++i)
39741 {
39742 z[i] = (a * x[i]) + y[i];
39743 }
39744
39745 return T(1);
39746 }
39747 };
39748
39749 template <typename T>
39751 {
39752 public:
39753
39759
39760 using exprtk::igeneric_function<T>::operator();
39761
39763 : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
39764 /*
39765 z <- ax + by
39766 Overloads:
39767 0. TVTVV - a, x(vector), b, y(vector), z(vector)
39768 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
39769 */
39770 {}
39771
39772 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39773 {
39774 const vector_t x(parameters[1]);
39775 const vector_t y(parameters[3]);
39776 vector_t z(parameters[4]);
39777
39778 std::size_t r0 = 0;
39779 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39780
39781 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39782 return std::numeric_limits<T>::quiet_NaN();
39783 else if (helper::invalid_range(y, r0, r1))
39784 return std::numeric_limits<T>::quiet_NaN();
39785 else if (helper::invalid_range(z, r0, r1))
39786 return std::numeric_limits<T>::quiet_NaN();
39787
39788 const T a = scalar_t(parameters[0])();
39789 const T b = scalar_t(parameters[2])();
39790
39791 for (std::size_t i = r0; i <= r1; ++i)
39792 {
39793 z[i] = (a * x[i]) + (b * y[i]);
39794 }
39795
39796 return T(1);
39797 }
39798 };
39799
39800 template <typename T>
39802 {
39803 public:
39804
39810
39811 using exprtk::igeneric_function<T>::operator();
39812
39814 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
39815 /*
39816 z <- ax + b
39817 Overloads:
39818 0. TVTV - a, x(vector), b, z(vector)
39819 1. TVTVTT - a, x(vector), b, z(vector), r0, r1
39820 */
39821 {}
39822
39823 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39824 {
39825 const vector_t x(parameters[1]);
39826 vector_t z(parameters[3]);
39827
39828 std::size_t r0 = 0;
39829 std::size_t r1 = x.size() - 1;
39830
39831 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39832 return std::numeric_limits<T>::quiet_NaN();
39833 else if (helper::invalid_range(z, r0, r1))
39834 return std::numeric_limits<T>::quiet_NaN();
39835
39836 const T a = scalar_t(parameters[0])();
39837 const T b = scalar_t(parameters[2])();
39838
39839 for (std::size_t i = r0; i <= r1; ++i)
39840 {
39841 z[i] = (a * x[i]) + b;
39842 }
39843
39844 return T(1);
39845 }
39846 };
39847
39848 template <typename T>
39850 {
39851 public:
39852
39858
39859 using exprtk::igeneric_function<T>::operator();
39860
39862 : exprtk::igeneric_function<T>("VV|VVTT")
39863 /*
39864 Overloads:
39865 0. VV - x(vector), y(vector)
39866 1. VVTT - x(vector), y(vector), r0, r1
39867 */
39868 {}
39869
39870 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39871 {
39872 const vector_t x(parameters[0]);
39873 const vector_t y(parameters[1]);
39874
39875 std::size_t r0 = 0;
39876 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39877
39878 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39879 return std::numeric_limits<T>::quiet_NaN();
39880 else if (helper::invalid_range(y, r0, r1))
39881 return std::numeric_limits<T>::quiet_NaN();
39882
39883 T result = T(0);
39884
39885 for (std::size_t i = r0; i <= r1; ++i)
39886 {
39887 result += (x[i] * y[i]);
39888 }
39889
39890 return result;
39891 }
39892 };
39893
39894 template <typename T>
39896 {
39897 public:
39898
39904
39905 using exprtk::igeneric_function<T>::operator();
39906
39908 : exprtk::igeneric_function<T>("VV|VVTT")
39909 /*
39910 Overloads:
39911 0. VV - x(vector), y(vector)
39912 1. VVTT - x(vector), y(vector), r0, r1
39913 */
39914 {}
39915
39916 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39917 {
39918 const vector_t x(parameters[0]);
39919 const vector_t y(parameters[1]);
39920
39921 std::size_t r0 = 0;
39922 std::size_t r1 = std::min(x.size(),y.size()) - 1;
39923
39924 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39925 return std::numeric_limits<T>::quiet_NaN();
39926 else if (helper::invalid_range(y, r0, r1))
39927 return std::numeric_limits<T>::quiet_NaN();
39928
39929 T result = T(0);
39930 T error = T(0);
39931
39932 for (std::size_t i = r0; i <= r1; ++i)
39933 {
39934 details::kahan_sum(result, error, (x[i] * y[i]));
39935 }
39936
39937 return result;
39938 }
39939 };
39940
39941 template <typename T>
39942 struct package
39943 {
39965
39967 {
39968 #define exprtk_register_function(FunctionName,FunctionType) \
39969 if (!symtab.add_function(FunctionName,FunctionType)) \
39970 { \
39971 exprtk_debug(( \
39972 "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
39973 FunctionName)); \
39974 return false; \
39975 } \
39976
39977 exprtk_register_function("all_true" ,at)
39978 exprtk_register_function("all_false" ,af)
39979 exprtk_register_function("any_true" ,nt)
39980 exprtk_register_function("any_false" ,nf)
39981 exprtk_register_function("count" , c)
39983 exprtk_register_function("rotate_left" ,rl)
39985 exprtk_register_function("rotate_right" ,rr)
39990 exprtk_register_function("nth_element" ,ne)
40000 #undef exprtk_register_function
40001
40002 return true;
40003 }
40004 };
40005
40006 } // namespace exprtk::rtl::vecops
40007 } // namespace exprtk::rtl
40008} // namespace exprtk
40009#endif
40010
40011namespace exprtk
40012{
40013 namespace information
40014 {
40015 static const char* library = "Mathematical Expression Toolkit";
40016 static const char* version = "2.718281828459045235360287471352"
40017 "66249775724709369995957496696762"
40018 "77240766303535475945713821785251"
40019 "66427427466391932003059921817413";
40020 static const char* date = "20210101";
40021
40022 static inline std::string data()
40023 {
40024 static const std::string info_str = std::string(library) +
40026 std::string(" (") + date + std::string(")");
40027 return info_str;
40028 }
40029
40030 } // namespace information
40031
40032 #ifdef exprtk_debug
40033 #undef exprtk_debug
40034 #endif
40035
40036 #ifdef exprtk_error_location
40037 #undef exprtk_error_location
40038 #endif
40039
40040 #ifdef exprtk_disable_fallthrough_begin
40041 #undef exprtk_disable_fallthrough_begin
40042 #endif
40043
40044 #ifdef exprtk_disable_fallthrough_end
40045 #undef exprtk_disable_fallthrough_end
40046 #endif
40047
40048} // namespace exprtk
40049
40050#endif
char const int length
Definition: cJSON.h:161
const cJSON *const b
Definition: cJSON.h:251
const char *const name
Definition: cJSON.h:258
int index
Definition: cJSON.h:168
int cJSON_bool fmt
Definition: cJSON.h:158
int count
Definition: cJSON.h:212
const char *const string
Definition: cJSON.h:170
char * buffer
Definition: cJSON.h:161
Definition: exprtk.hpp:14443
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, bfunc_t p2)
Definition: exprtk.hpp:14489
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14457
details::functor_t< T > functor_t
Definition: exprtk.hpp:14446
T0 t0() const
Definition: exprtk.hpp:14473
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14447
T0oT1(T0 p0, T1 p1, const bfunc_t p2)
Definition: exprtk.hpp:14451
operator_type operation() const
Definition: exprtk.hpp:14463
T1 t1() const
Definition: exprtk.hpp:14478
bfunc_t f() const
Definition: exprtk.hpp:14483
T value_type
Definition: exprtk.hpp:14448
T value() const
Definition: exprtk.hpp:14468
T0oT1< T, T0, T1 > node_type
Definition: exprtk.hpp:14449
Definition: exprtk.hpp:14005
virtual std::string type_id() const =0
virtual ~T0oT1oT2_base_node()
Definition: exprtk.hpp:14008
Definition: exprtk.hpp:14699
functor_t::tfunc_t tfunc_t
Definition: exprtk.hpp:14703
T0oT1oT2_sf3< T, T0, T1, T2 > node_type
Definition: exprtk.hpp:14705
operator_type operation() const
Definition: exprtk.hpp:14720
tfunc_t f() const
Definition: exprtk.hpp:14745
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
Definition: exprtk.hpp:14761
std::string type_id() const
Definition: exprtk.hpp:14750
T value_type
Definition: exprtk.hpp:14704
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14714
details::functor_t< T > functor_t
Definition: exprtk.hpp:14702
static std::string id()
Definition: exprtk.hpp:14755
T1 t1() const
Definition: exprtk.hpp:14735
T2 t2() const
Definition: exprtk.hpp:14740
T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
Definition: exprtk.hpp:14707
T value() const
Definition: exprtk.hpp:14725
T0 t0() const
Definition: exprtk.hpp:14730
Definition: exprtk.hpp:14796
T1 t1() const
Definition: exprtk.hpp:14831
functor_t::tfunc_t tfunc_t
Definition: exprtk.hpp:14800
T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
Definition: exprtk.hpp:14804
T2 t2() const
Definition: exprtk.hpp:14836
details::functor_t< T > functor_t
Definition: exprtk.hpp:14799
T0oT1oT2_sf3ext< T, T0, T1, T2, SF3Operation > node_type
Definition: exprtk.hpp:14802
operator_type operation() const
Definition: exprtk.hpp:14816
T value() const
Definition: exprtk.hpp:14821
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2)
Definition: exprtk.hpp:14852
T0 t0() const
Definition: exprtk.hpp:14826
std::string type_id() const
Definition: exprtk.hpp:14841
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14810
static std::string id()
Definition: exprtk.hpp:14846
T value_type
Definition: exprtk.hpp:14801
Definition: exprtk.hpp:14510
T value_type
Definition: exprtk.hpp:14515
operator_type operation() const
Definition: exprtk.hpp:14533
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
Definition: exprtk.hpp:14579
T0oT1oT2< T, T0, T1, T2, ProcessMode > node_type
Definition: exprtk.hpp:14516
T1 t1() const
Definition: exprtk.hpp:14548
T value() const
Definition: exprtk.hpp:14538
details::functor_t< T > functor_t
Definition: exprtk.hpp:14513
static std::string id()
Definition: exprtk.hpp:14573
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14514
std::string type_id() const
Definition: exprtk.hpp:14568
T2 t2() const
Definition: exprtk.hpp:14553
ProcessMode process_mode_t
Definition: exprtk.hpp:14517
T0 t0() const
Definition: exprtk.hpp:14543
bfunc_t f0() const
Definition: exprtk.hpp:14558
T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
Definition: exprtk.hpp:14519
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14527
bfunc_t f1() const
Definition: exprtk.hpp:14563
Definition: exprtk.hpp:14016
virtual std::string type_id() const =0
virtual ~T0oT1oT2oT3_base_node()
Definition: exprtk.hpp:14019
Definition: exprtk.hpp:14885
T0 t0() const
Definition: exprtk.hpp:14917
T2 t2() const
Definition: exprtk.hpp:14927
T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
Definition: exprtk.hpp:14893
T1 t1() const
Definition: exprtk.hpp:14922
T0oT1oT2oT3_sf4< T, T0, T1, T2, T3 > node_type
Definition: exprtk.hpp:14891
T3 t3() const
Definition: exprtk.hpp:14932
T value() const
Definition: exprtk.hpp:14912
T value_type
Definition: exprtk.hpp:14890
operator_type operation() const
Definition: exprtk.hpp:14907
functor_t::qfunc_t qfunc_t
Definition: exprtk.hpp:14889
static std::string id()
Definition: exprtk.hpp:14947
details::functor_t< T > functor_t
Definition: exprtk.hpp:14888
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14901
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
Definition: exprtk.hpp:14953
std::string type_id() const
Definition: exprtk.hpp:14942
qfunc_t f() const
Definition: exprtk.hpp:14937
Definition: exprtk.hpp:14974
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14989
T0oT1oT2oT3_sf4ext< T, T0, T1, T2, T3, SF4Operation > node_type
Definition: exprtk.hpp:14980
T value_type
Definition: exprtk.hpp:14979
T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
Definition: exprtk.hpp:14982
static std::string id()
Definition: exprtk.hpp:15030
T value() const
Definition: exprtk.hpp:15000
std::string type_id() const
Definition: exprtk.hpp:15025
details::functor_t< T > functor_t
Definition: exprtk.hpp:14977
functor_t::tfunc_t tfunc_t
Definition: exprtk.hpp:14978
T3 t3() const
Definition: exprtk.hpp:15020
operator_type operation() const
Definition: exprtk.hpp:14995
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3)
Definition: exprtk.hpp:15036
T2 t2() const
Definition: exprtk.hpp:15015
T0 t0() const
Definition: exprtk.hpp:15005
T1 t1() const
Definition: exprtk.hpp:15010
Definition: exprtk.hpp:14600
T0oT1oT2oT3< T, T0, T1, T2, T3, ProcessMode > node_type
Definition: exprtk.hpp:14610
bfunc_t f0() const
Definition: exprtk.hpp:14648
ProcessMode process_mode_t
Definition: exprtk.hpp:14611
T0 t0() const
Definition: exprtk.hpp:14628
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
Definition: exprtk.hpp:14674
T0_ T0
Definition: exprtk.hpp:14606
bfunc_t f1() const
Definition: exprtk.hpp:14653
std::string type_id() const
Definition: exprtk.hpp:14663
T value_type
Definition: exprtk.hpp:14605
T value() const
Definition: exprtk.hpp:14623
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14604
T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
Definition: exprtk.hpp:14613
T1 t1() const
Definition: exprtk.hpp:14633
T2 t2() const
Definition: exprtk.hpp:14638
details::functor_t< T > functor_t
Definition: exprtk.hpp:14603
T3 t3() const
Definition: exprtk.hpp:14643
T2_ T2
Definition: exprtk.hpp:14608
bfunc_t f2() const
Definition: exprtk.hpp:14658
T3_ T3
Definition: exprtk.hpp:14609
static std::string id()
Definition: exprtk.hpp:14668
T1_ T1
Definition: exprtk.hpp:14607
Definition: exprtk.hpp:10130
assignment_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10135
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10133
T value() const
Definition: exprtk.hpp:10147
Definition: exprtk.hpp:10564
T value() const
Definition: exprtk.hpp:10581
assignment_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10569
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10567
assignment_rebasevec_celem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10255
T value() const
Definition: exprtk.hpp:10267
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10253
T value() const
Definition: exprtk.hpp:10698
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10684
assignment_rebasevec_celem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10686
T value() const
Definition: exprtk.hpp:10227
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10213
assignment_rebasevec_elem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10215
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10645
assignment_rebasevec_elem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10647
T value() const
Definition: exprtk.hpp:10659
Definition: exprtk.hpp:8959
std::size_t size() const
Definition: exprtk.hpp:9045
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:8963
std::string str() const
Definition: exprtk.hpp:9035
T value() const
Definition: exprtk.hpp:9008
range_pack< T > range_t
Definition: exprtk.hpp:8965
range_t & range_ref()
Definition: exprtk.hpp:9050
char_cptr base() const
Definition: exprtk.hpp:9040
range_interface< T > irange_t
Definition: exprtk.hpp:8967
assignment_string_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8970
const range_t & range_ref() const
Definition: exprtk.hpp:9055
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9060
irange_t * irange_ptr
Definition: exprtk.hpp:8968
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8964
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8962
range_t * range_ptr
Definition: exprtk.hpp:8966
range_interface< T > irange_t
Definition: exprtk.hpp:9087
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:9084
std::size_t size() const
Definition: exprtk.hpp:9182
range_pack< T > range_t
Definition: exprtk.hpp:9085
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9081
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9197
std::string str() const
Definition: exprtk.hpp:9172
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:9082
T value() const
Definition: exprtk.hpp:9137
const range_t & range_ref() const
Definition: exprtk.hpp:9192
assignment_string_range_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9090
range_t * range_ptr
Definition: exprtk.hpp:9086
char_cptr base() const
Definition: exprtk.hpp:9177
irange_t * irange_ptr
Definition: exprtk.hpp:9088
range_t & range_ref()
Definition: exprtk.hpp:9187
string_range_node< T > * str_rng_node_ptr
Definition: exprtk.hpp:9083
Definition: exprtk.hpp:10170
T value() const
Definition: exprtk.hpp:10187
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10173
assignment_vec_elem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10175
assignment_vec_elem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10608
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10606
T value() const
Definition: exprtk.hpp:10620
Definition: exprtk.hpp:10291
assignment_vec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10298
vds_t & vds()
Definition: exprtk.hpp:10391
T value() const
Definition: exprtk.hpp:10311
const vds_t & vds() const
Definition: exprtk.hpp:10396
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:10295
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10381
vec_data_store< T > vds_t
Definition: exprtk.hpp:10296
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10294
std::size_t size() const
Definition: exprtk.hpp:10386
vector_node_ptr vec()
Definition: exprtk.hpp:10376
vector_node_ptr vec() const
Definition: exprtk.hpp:10371
Definition: exprtk.hpp:10721
const vds_t & vds() const
Definition: exprtk.hpp:10827
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10812
vec_data_store< T > vds_t
Definition: exprtk.hpp:10726
vds_t & vds()
Definition: exprtk.hpp:10822
assignment_vec_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10728
vector_node_ptr vec()
Definition: exprtk.hpp:10807
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:10725
bool side_effect() const
Definition: exprtk.hpp:10832
T value() const
Definition: exprtk.hpp:10741
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10724
std::size_t size() const
Definition: exprtk.hpp:10817
vector_node_ptr vec() const
Definition: exprtk.hpp:10802
Definition: exprtk.hpp:10410
std::size_t size() const
Definition: exprtk.hpp:10538
vds_t & vds()
Definition: exprtk.hpp:10543
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10533
vector_node_ptr vec() const
Definition: exprtk.hpp:10523
T value() const
Definition: exprtk.hpp:10458
vector_node_ptr vec()
Definition: exprtk.hpp:10528
vec_data_store< T > vds_t
Definition: exprtk.hpp:10415
assignment_vecvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10417
const vds_t & vds() const
Definition: exprtk.hpp:10548
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10413
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:10414
Definition: exprtk.hpp:10846
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10964
vector_node_ptr vec()
Definition: exprtk.hpp:10959
vds_t & vds()
Definition: exprtk.hpp:10974
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10849
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:10850
assignment_vecvec_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10853
std::size_t size() const
Definition: exprtk.hpp:10969
bool side_effect() const
Definition: exprtk.hpp:10984
vector_node_ptr vec() const
Definition: exprtk.hpp:10954
vec_data_store< T > vds_t
Definition: exprtk.hpp:10851
T value() const
Definition: exprtk.hpp:10888
const vds_t & vds() const
Definition: exprtk.hpp:10979
Definition: exprtk.hpp:6355
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6359
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6397
operator_type operation()
Definition: exprtk.hpp:6382
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6358
expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:6387
binary_ext_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:6361
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6377
T value() const
Definition: exprtk.hpp:6366
branch_t branch_[2]
Definition: exprtk.hpp:6409
std::size_t node_depth() const
Definition: exprtk.hpp:6402
Definition: exprtk.hpp:6292
operator_type operation_
Definition: exprtk.hpp:6349
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6317
binary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:6298
expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:6327
branch_t branch_[2]
Definition: exprtk.hpp:6350
operator_type operation()
Definition: exprtk.hpp:6322
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6337
std::size_t node_depth() const
Definition: exprtk.hpp:6342
T value() const
Definition: exprtk.hpp:6306
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6295
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6296
Definition: exprtk.hpp:15941
PowOp operation_t
Definition: exprtk.hpp:15946
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15959
T value() const
Definition: exprtk.hpp:15953
std::size_t node_depth() const
Definition: exprtk.hpp:15969
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:15964
bipow_node(expression_ptr branch)
Definition: exprtk.hpp:15948
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15945
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15944
Definition: exprtk.hpp:16014
bipowninv_node(expression_ptr branch)
Definition: exprtk.hpp:16021
T value() const
Definition: exprtk.hpp:16026
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:16018
expression_node< T > * expression_ptr
Definition: exprtk.hpp:16017
PowOp operation_t
Definition: exprtk.hpp:16019
expression_node< T >::node_type type() const
Definition: exprtk.hpp:16032
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:16037
std::size_t node_depth() const
Definition: exprtk.hpp:16042
Definition: exprtk.hpp:13941
virtual ~boc_base_node()
Definition: exprtk.hpp:13944
virtual operator_type operation() const
Definition: exprtk.hpp:13947
virtual void set_c(const T)=0
virtual expression_node< T > * move_branch(const std::size_t &index)=0
virtual const T c() const =0
Definition: exprtk.hpp:15424
boc_node(const expression_ptr branch, const T const_var)
Definition: exprtk.hpp:15432
std::size_t node_depth() const
Definition: exprtk.hpp:15475
operator_type operation() const
Definition: exprtk.hpp:15444
expression_node< T > * move_branch(const std::size_t &)
Definition: exprtk.hpp:15464
void set_c(const T new_c)
Definition: exprtk.hpp:15454
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:15459
Operation operation_t
Definition: exprtk.hpp:15429
T value() const
Definition: exprtk.hpp:15438
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15428
const T c() const
Definition: exprtk.hpp:15449
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:15470
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15427
Definition: exprtk.hpp:13910
virtual ~bov_base_node()
Definition: exprtk.hpp:13913
virtual const T & v() const =0
Definition: exprtk.hpp:15301
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15305
bov_node(const expression_ptr branch, const T &var)
Definition: exprtk.hpp:15309
std::size_t node_depth() const
Definition: exprtk.hpp:15341
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:15331
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:15336
operator_type operation() const
Definition: exprtk.hpp:15321
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15304
Operation operation_t
Definition: exprtk.hpp:15306
T value() const
Definition: exprtk.hpp:15315
const T & v() const
Definition: exprtk.hpp:15326
Definition: exprtk.hpp:6627
T value
Definition: exprtk.hpp:6634
break_exception(const T &v)
Definition: exprtk.hpp:6630
Definition: exprtk.hpp:6642
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6645
std::size_t node_depth() const
Definition: exprtk.hpp:6671
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6661
T value() const
Definition: exprtk.hpp:6653
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6666
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6646
break_node(expression_ptr ret=expression_ptr(0))
Definition: exprtk.hpp:6648
Definition: exprtk.hpp:395
build_string & operator<<(const std::string &s)
Definition: exprtk.hpp:403
build_string(const std::size_t &initial_size=64)
Definition: exprtk.hpp:398
std::string as_string() const
Definition: exprtk.hpp:420
Definition: exprtk.hpp:13921
virtual const T c() const =0
virtual ~cob_base_node()
Definition: exprtk.hpp:13924
virtual operator_type operation() const
Definition: exprtk.hpp:13927
virtual void set_c(const T)=0
virtual expression_node< T > * move_branch(const std::size_t &index)=0
Definition: exprtk.hpp:15357
const T c() const
Definition: exprtk.hpp:15382
std::size_t node_depth() const
Definition: exprtk.hpp:15408
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:15392
Operation operation_t
Definition: exprtk.hpp:15362
expression_node< T > * move_branch(const std::size_t &)
Definition: exprtk.hpp:15397
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15361
T value() const
Definition: exprtk.hpp:15371
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:15403
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15360
cob_node(const T const_var, const expression_ptr branch)
Definition: exprtk.hpp:15365
void set_c(const T new_c)
Definition: exprtk.hpp:15387
operator_type operation() const
Definition: exprtk.hpp:15377
Definition: exprtk.hpp:6522
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6526
conditional_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative)
Definition: exprtk.hpp:6528
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6549
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6525
std::size_t node_depth() const
Definition: exprtk.hpp:6561
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6554
T value() const
Definition: exprtk.hpp:6537
Definition: exprtk.hpp:9216
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:9220
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9355
char_cptr base() const
Definition: exprtk.hpp:9335
range_interface< T > irange_t
Definition: exprtk.hpp:9223
range_t * range_ptr
Definition: exprtk.hpp:9222
conditional_string_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative)
Definition: exprtk.hpp:9226
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9219
irange_t * irange_ptr
Definition: exprtk.hpp:9224
T value() const
Definition: exprtk.hpp:9278
std::string str() const
Definition: exprtk.hpp:9330
const range_t & range_ref() const
Definition: exprtk.hpp:9350
range_t & range_ref()
Definition: exprtk.hpp:9345
std::size_t size() const
Definition: exprtk.hpp:9340
range_pack< T > range_t
Definition: exprtk.hpp:9221
Definition: exprtk.hpp:6576
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6580
cons_conditional_node(expression_ptr condition, expression_ptr consequent)
Definition: exprtk.hpp:6583
std::size_t node_depth() const
Definition: exprtk.hpp:6612
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6581
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6606
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6601
T value() const
Definition: exprtk.hpp:6590
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:9383
T value() const
Definition: exprtk.hpp:9420
range_interface< T > irange_t
Definition: exprtk.hpp:9386
char_cptr base() const
Definition: exprtk.hpp:9458
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9478
irange_t * irange_ptr
Definition: exprtk.hpp:9387
range_t * range_ptr
Definition: exprtk.hpp:9385
std::string str() const
Definition: exprtk.hpp:9453
std::size_t size() const
Definition: exprtk.hpp:9463
range_pack< T > range_t
Definition: exprtk.hpp:9384
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9382
range_t & range_ref()
Definition: exprtk.hpp:9468
const range_t & range_ref() const
Definition: exprtk.hpp:9473
cons_conditional_str_node(expression_ptr condition, expression_ptr consequent)
Definition: exprtk.hpp:9389
Definition: exprtk.hpp:8267
range_pack< T > range_t
Definition: exprtk.hpp:8270
range_t & range_ref()
Definition: exprtk.hpp:8307
std::string str() const
Definition: exprtk.hpp:8287
std::size_t size() const
Definition: exprtk.hpp:8297
const_string_range_node(const std::string &v, const range_t &rp)
Definition: exprtk.hpp:8272
~const_string_range_node()
Definition: exprtk.hpp:8277
char_cptr base() const
Definition: exprtk.hpp:8292
T value() const
Definition: exprtk.hpp:8282
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8317
const range_t & range_ref() const
Definition: exprtk.hpp:8312
range_t range() const
Definition: exprtk.hpp:8302
Definition: exprtk.hpp:6638
Definition: exprtk.hpp:6683
T value() const
Definition: exprtk.hpp:6686
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6694
Definition: exprtk.hpp:13863
virtual const T c() const =0
virtual const T & v() const =0
virtual operator_type operation() const
Definition: exprtk.hpp:13869
virtual ~cov_base_node()
Definition: exprtk.hpp:13866
Definition: exprtk.hpp:15150
const T & v_
Definition: exprtk.hpp:15190
cov_node(const T &const_var, const T &var)
Definition: exprtk.hpp:15157
const T & v() const
Definition: exprtk.hpp:15182
operator_type operation() const
Definition: exprtk.hpp:15172
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15167
const T c_
Definition: exprtk.hpp:15189
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15153
T value() const
Definition: exprtk.hpp:15162
const T c() const
Definition: exprtk.hpp:15177
Operation operation_t
Definition: exprtk.hpp:15154
Definition: exprtk.hpp:5131
virtual T value() const
Definition: exprtk.hpp:5184
virtual expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:5189
virtual node_type type() const
Definition: exprtk.hpp:5194
nci_t::noderef_list_t noderef_list_t
Definition: exprtk.hpp:5178
node_type
Definition: exprtk.hpp:5135
@ e_bov
Definition: exprtk.hpp:5161
@ e_sf3ext
Definition: exprtk.hpp:5166
@ e_vocovoc
Definition: exprtk.hpp:5165
@ e_constant
Definition: exprtk.hpp:5136
@ e_cstringvarrng
Definition: exprtk.hpp:5141
@ e_vecvecarith
Definition: exprtk.hpp:5170
@ e_vov
Definition: exprtk.hpp:5160
@ e_asin
Definition: exprtk.hpp:5151
@ e_ipow
Definition: exprtk.hpp:5150
@ e_ceil
Definition: exprtk.hpp:5152
@ e_sin
Definition: exprtk.hpp:5155
@ e_or
Definition: exprtk.hpp:5148
@ e_tan
Definition: exprtk.hpp:5156
@ e_vecunaryop
Definition: exprtk.hpp:5171
@ e_rbvecelem
Definition: exprtk.hpp:5167
@ e_switch
Definition: exprtk.hpp:5139
@ e_expm1
Definition: exprtk.hpp:5153
@ e_cot
Definition: exprtk.hpp:5157
@ e_lte
Definition: exprtk.hpp:5146
@ e_mod
Definition: exprtk.hpp:5145
@ e_gte
Definition: exprtk.hpp:5146
@ e_g2d
Definition: exprtk.hpp:5158
@ e_exp
Definition: exprtk.hpp:5153
@ e_nor
Definition: exprtk.hpp:5148
@ e_vecvalarith
Definition: exprtk.hpp:5170
@ e_stringvararg
Definition: exprtk.hpp:5142
@ e_covocov
Definition: exprtk.hpp:5165
@ e_vocov
Definition: exprtk.hpp:5163
@ e_sgn
Definition: exprtk.hpp:5159
@ e_covov
Definition: exprtk.hpp:5163
@ e_cosh
Definition: exprtk.hpp:5152
@ e_vecvecineq
Definition: exprtk.hpp:5169
@ e_mul
Definition: exprtk.hpp:5145
@ e_vob
Definition: exprtk.hpp:5161
@ e_stringconst
Definition: exprtk.hpp:5140
@ e_frac
Definition: exprtk.hpp:5160
@ e_abs
Definition: exprtk.hpp:5150
@ e_r2d
Definition: exprtk.hpp:5157
@ e_for
Definition: exprtk.hpp:5139
@ e_inranges
Definition: exprtk.hpp:5149
@ e_log10
Definition: exprtk.hpp:5154
@ e_ilike
Definition: exprtk.hpp:5149
@ e_cov
Definition: exprtk.hpp:5161
@ e_mswitch
Definition: exprtk.hpp:5139
@ e_rbveccelem
Definition: exprtk.hpp:5167
@ e_null
Definition: exprtk.hpp:5136
@ e_vecopvecass
Definition: exprtk.hpp:5169
@ e_ne
Definition: exprtk.hpp:5147
@ e_vovocov
Definition: exprtk.hpp:5164
@ e_round
Definition: exprtk.hpp:5155
@ e_vecvalineq
Definition: exprtk.hpp:5170
@ e_strfunction
Definition: exprtk.hpp:5143
@ e_asinh
Definition: exprtk.hpp:5151
@ e_sec
Definition: exprtk.hpp:5157
@ e_erf
Definition: exprtk.hpp:5159
@ e_quaternary
Definition: exprtk.hpp:5137
@ e_erfc
Definition: exprtk.hpp:5159
@ e_csc
Definition: exprtk.hpp:5157
@ e_function
Definition: exprtk.hpp:5143
@ e_vococov
Definition: exprtk.hpp:5165
@ e_sqrt
Definition: exprtk.hpp:5156
@ e_vecvecswap
Definition: exprtk.hpp:5169
@ e_vecfunc
Definition: exprtk.hpp:5169
@ e_while
Definition: exprtk.hpp:5138
@ e_strswap
Definition: exprtk.hpp:5142
@ e_continue
Definition: exprtk.hpp:5171
@ e_return
Definition: exprtk.hpp:5139
@ e_nand
Definition: exprtk.hpp:5147
@ e_cob
Definition: exprtk.hpp:5162
@ e_covoc
Definition: exprtk.hpp:5163
@ e_vecdefass
Definition: exprtk.hpp:5168
@ e_tanh
Definition: exprtk.hpp:5156
@ e_sf4ext
Definition: exprtk.hpp:5166
@ e_ncdf
Definition: exprtk.hpp:5159
@ e_binary
Definition: exprtk.hpp:5137
@ e_vecelem
Definition: exprtk.hpp:5167
@ e_vector
Definition: exprtk.hpp:5167
@ e_strgenrange
Definition: exprtk.hpp:5141
@ e_log
Definition: exprtk.hpp:5153
@ e_d2g
Definition: exprtk.hpp:5158
@ e_valvecineq
Definition: exprtk.hpp:5170
@ e_pos
Definition: exprtk.hpp:5155
@ e_stringvarrng
Definition: exprtk.hpp:5141
@ e_boc
Definition: exprtk.hpp:5162
@ e_pow
Definition: exprtk.hpp:5145
@ e_variable
Definition: exprtk.hpp:5140
@ e_add
Definition: exprtk.hpp:5144
@ e_gt
Definition: exprtk.hpp:5146
@ e_d2r
Definition: exprtk.hpp:5158
@ e_strcondition
Definition: exprtk.hpp:5144
@ e_swap
Definition: exprtk.hpp:5172
@ e_voc
Definition: exprtk.hpp:5161
@ e_xnor
Definition: exprtk.hpp:5148
@ e_vovovov
Definition: exprtk.hpp:5163
@ e_acos
Definition: exprtk.hpp:5150
@ e_lt
Definition: exprtk.hpp:5146
@ e_strconcat
Definition: exprtk.hpp:5141
@ e_neg
Definition: exprtk.hpp:5154
@ e_and
Definition: exprtk.hpp:5147
@ e_log1p
Definition: exprtk.hpp:5154
@ e_eq
Definition: exprtk.hpp:5147
@ e_none
Definition: exprtk.hpp:5136
@ e_in
Definition: exprtk.hpp:5149
@ e_acosh
Definition: exprtk.hpp:5151
@ e_ipowinv
Definition: exprtk.hpp:5150
@ e_xor
Definition: exprtk.hpp:5148
@ e_trunc
Definition: exprtk.hpp:5160
@ e_atanh
Definition: exprtk.hpp:5152
@ e_sub
Definition: exprtk.hpp:5144
@ e_conditional
Definition: exprtk.hpp:5138
@ e_vecopvalass
Definition: exprtk.hpp:5168
@ e_sinc
Definition: exprtk.hpp:5155
@ e_stringsize
Definition: exprtk.hpp:5142
@ e_uvouv
Definition: exprtk.hpp:5160
@ e_binary_ext
Definition: exprtk.hpp:5137
@ e_retenv
Definition: exprtk.hpp:5140
@ e_log2
Definition: exprtk.hpp:5154
@ e_covovov
Definition: exprtk.hpp:5164
@ e_covovoc
Definition: exprtk.hpp:5165
@ e_vecvecass
Definition: exprtk.hpp:5168
@ e_cos
Definition: exprtk.hpp:5152
@ e_atan
Definition: exprtk.hpp:5151
@ e_vafunction
Definition: exprtk.hpp:5143
@ e_like
Definition: exprtk.hpp:5149
@ e_repeat
Definition: exprtk.hpp:5138
@ e_stringvarsize
Definition: exprtk.hpp:5142
@ e_sinh
Definition: exprtk.hpp:5156
@ e_div
Definition: exprtk.hpp:5145
@ e_vovovoc
Definition: exprtk.hpp:5164
@ e_vecvalass
Definition: exprtk.hpp:5168
@ e_unary
Definition: exprtk.hpp:5136
@ e_floor
Definition: exprtk.hpp:5153
@ e_trinary
Definition: exprtk.hpp:5137
@ e_stringvar
Definition: exprtk.hpp:5140
@ e_vararg
Definition: exprtk.hpp:5138
@ e_break
Definition: exprtk.hpp:5171
@ e_vovov
Definition: exprtk.hpp:5162
@ e_valvecarith
Definition: exprtk.hpp:5171
@ e_vocovov
Definition: exprtk.hpp:5164
@ e_vovoc
Definition: exprtk.hpp:5162
@ e_strccondition
Definition: exprtk.hpp:5144
@ e_genfunction
Definition: exprtk.hpp:5143
@ e_nulleq
Definition: exprtk.hpp:5166
@ e_strass
Definition: exprtk.hpp:5166
@ e_notl
Definition: exprtk.hpp:5158
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5176
node_depth_base< expression_node< T > > ndb_t
Definition: exprtk.hpp:5179
node_collector_interface< expression_node< T > > nci_t
Definition: exprtk.hpp:5177
T value_type
Definition: exprtk.hpp:5175
virtual ~expression_node()
Definition: exprtk.hpp:5181
Definition: exprtk.hpp:7087
T value() const
Definition: exprtk.hpp:7106
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7161
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7091
std::size_t node_depth() const
Definition: exprtk.hpp:7169
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7090
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7156
for_loop_bc_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:7093
Definition: exprtk.hpp:6873
for_loop_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:6879
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6877
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6923
T value() const
Definition: exprtk.hpp:6892
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6876
std::size_t node_depth() const
Definition: exprtk.hpp:6936
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6928
T value() const
Definition: exprtk.hpp:12023
IFunction ifunction
Definition: exprtk.hpp:12012
expression_node< T > * expression_ptr
Definition: exprtk.hpp:12011
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12031
function_N_node(ifunction *func)
Definition: exprtk.hpp:12014
Definition: exprtk.hpp:11710
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:11715
T value() const
Definition: exprtk.hpp:11754
std::size_t node_depth() const
Definition: exprtk.hpp:11994
IFunction ifunction
Definition: exprtk.hpp:11716
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:11989
bool init_branches(expression_ptr(&b)[NumBranches])
Definition: exprtk.hpp:11724
function_N_node(ifunction *func)
Definition: exprtk.hpp:11718
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11984
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11714
bool operator<(const function_N_node< T, IFunction, N > &fn) const
Definition: exprtk.hpp:11749
Definition: exprtk.hpp:12110
std::pair< void *, std::size_t > void_t
Definition: exprtk.hpp:12123
std::vector< range_data_type_t > range_list_t
Definition: exprtk.hpp:12126
variable_node_t * variable_node_ptr_t
Definition: exprtk.hpp:12117
range_interface< T > range_interface_t
Definition: exprtk.hpp:12119
GenericFunction * function_
Definition: exprtk.hpp:12297
virtual ~generic_function_node()
Definition: exprtk.hpp:12134
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:12122
vector_node< T > vector_node_t
Definition: exprtk.hpp:12116
std::vector< type_store_t > typestore_list_t
Definition: exprtk.hpp:12125
std::vector< T > tmp_vs_t
Definition: exprtk.hpp:12124
range_data_type< T > range_data_type_t
Definition: exprtk.hpp:12120
T value() const
Definition: exprtk.hpp:12238
vector_node_t * vector_node_ptr_t
Definition: exprtk.hpp:12118
std::size_t node_depth() const
Definition: exprtk.hpp:12142
typestore_list_t typestore_list_
Definition: exprtk.hpp:12298
range_pack< T > range_t
Definition: exprtk.hpp:12121
virtual bool populate_value_list() const
Definition: exprtk.hpp:12260
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:12137
bool operator<(const generic_function_node< T, GenericFunction > &fn) const
Definition: exprtk.hpp:12233
variable_node< T > variable_node_t
Definition: exprtk.hpp:12115
type_store< T > type_store_t
Definition: exprtk.hpp:12113
expression_node< T > * expression_ptr
Definition: exprtk.hpp:12114
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12253
virtual bool init_branches()
Definition: exprtk.hpp:12147
generic_function_node(const std::vector< expression_ptr > &arg_list, GenericFunction *func=reinterpret_cast< GenericFunction * >(0))
Definition: exprtk.hpp:12128
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:8338
range_t * range_ptr
Definition: exprtk.hpp:8341
char_cptr base() const
Definition: exprtk.hpp:8421
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:8344
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8339
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:8446
generic_string_range_node(expression_ptr str_branch, const range_t &brange)
Definition: exprtk.hpp:8347
std::size_t size() const
Definition: exprtk.hpp:8426
T value() const
Definition: exprtk.hpp:8381
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8441
irange_t * irange_ptr
Definition: exprtk.hpp:8343
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8337
range_t & range_ref()
Definition: exprtk.hpp:8431
range_pack< T > range_t
Definition: exprtk.hpp:8340
std::string str() const
Definition: exprtk.hpp:8416
std::size_t node_depth() const
Definition: exprtk.hpp:8451
range_interface< T > irange_t
Definition: exprtk.hpp:8342
~generic_string_range_node()
Definition: exprtk.hpp:8376
const range_t & range_ref() const
Definition: exprtk.hpp:8436
Definition: exprtk.hpp:15911
T value() const
Definition: exprtk.hpp:15921
ipow_node(const T &v)
Definition: exprtk.hpp:15917
PowOp operation_t
Definition: exprtk.hpp:15915
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15914
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15926
Definition: exprtk.hpp:15984
PowOp operation_t
Definition: exprtk.hpp:15988
ipowinv_node(const T &v)
Definition: exprtk.hpp:15990
T value() const
Definition: exprtk.hpp:15994
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15999
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15987
Definition: exprtk.hpp:7355
virtual ~ivariable()
Definition: exprtk.hpp:7358
virtual const T & ref() const =0
Definition: exprtk.hpp:6094
T value() const
Definition: exprtk.hpp:6101
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6106
literal_node(const T &v)
Definition: exprtk.hpp:6097
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:6111
Definition: exprtk.hpp:7279
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7333
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7283
std::size_t node_depth() const
Definition: exprtk.hpp:7343
multi_switch_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:7287
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7282
T value() const
Definition: exprtk.hpp:7308
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7338
range_pack< T > range_t
Definition: exprtk.hpp:12401
generic_function_node< T, GenericFunction > gen_function_t
Definition: exprtk.hpp:12400
multimode_genfunction_node(GenericFunction *func, const std::size_t &param_seq_index, const std::vector< typename gen_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:12403
T value() const
Definition: exprtk.hpp:12410
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12429
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12480
T value() const
Definition: exprtk.hpp:12455
multimode_strfunction_node(StringFunction *func, const std::size_t &param_seq_index, const std::vector< typename str_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:12448
range_pack< T > range_t
Definition: exprtk.hpp:12446
string_function_node< T, StringFunction > str_function_t
Definition: exprtk.hpp:12445
Definition: exprtk.hpp:16195
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9, const T10 &t10) const
Definition: exprtk.hpp:16491
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3) const
Definition: exprtk.hpp:16505
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[1])
Definition: exprtk.hpp:16199
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4) const
Definition: exprtk.hpp:16516
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[6])
Definition: exprtk.hpp:16244
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[5])
Definition: exprtk.hpp:16235
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[4])
Definition: exprtk.hpp:16226
expression_node< typename node_type::value_type > * allocate_tt(T1 t1, T2 t2) const
Definition: exprtk.hpp:16330
expression_node< typename node_type::value_type > * allocate(const Sequence< Type, Allocator > &seq) const
Definition: exprtk.hpp:16262
expression_node< typename node_type::value_type > * allocate_c(const T1 &t1) const
Definition: exprtk.hpp:16280
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) const
Definition: exprtk.hpp:16402
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[3])
Definition: exprtk.hpp:16217
expression_node< typename node_type::value_type > * allocate_rrrr(T1 &t1, T2 &t2, T3 &t3, T4 &t4) const
Definition: exprtk.hpp:16370
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[2])
Definition: exprtk.hpp:16208
expression_node< typename node_type::value_type > * allocate_rr(T1 &t1, T2 &t2) const
Definition: exprtk.hpp:16320
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9) const
Definition: exprtk.hpp:16473
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7) const
Definition: exprtk.hpp:16441
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) const
Definition: exprtk.hpp:16529
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8) const
Definition: exprtk.hpp:16457
expression_node< typename node_type::value_type > * allocate_cr(const T1 &t1, T2 &t2) const
Definition: exprtk.hpp:16300
expression_node< typename node_type::value_type > * allocate(T1 &t1) const
Definition: exprtk.hpp:16271
expression_node< typename node_type::value_type > * allocate_rc(T1 &t1, const T2 &t2) const
Definition: exprtk.hpp:16310
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5) const
Definition: exprtk.hpp:16414
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) const
Definition: exprtk.hpp:16557
expression_node< typename node_type::value_type > * allocate_ttt(T1 t1, T2 t2, T3 t3) const
Definition: exprtk.hpp:16340
expression_node< typename node_type::value_type > * allocate_rrrrr(T1 &t1, T2 &t2, T3 &t3, T4 &t4, T5 &t5) const
Definition: exprtk.hpp:16380
void free(expression_node< T > *&e) const
Definition: exprtk.hpp:16569
expression_node< typename node_type::value_type > * allocate() const
Definition: exprtk.hpp:16253
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3) const
Definition: exprtk.hpp:16390
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6) const
Definition: exprtk.hpp:16427
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) const
Definition: exprtk.hpp:16543
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2) const
Definition: exprtk.hpp:16290
expression_node< typename node_type::value_type > * allocate_rrr(T1 &t1, T2 &t2, T3 &t3) const
Definition: exprtk.hpp:16360
expression_node< typename node_type::value_type > * allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
Definition: exprtk.hpp:16350
nci_t::node_pp_t node_pp_t
Definition: exprtk.hpp:5457
nci_t::node_ptr_t node_ptr_t
Definition: exprtk.hpp:5456
static void delete_nodes(node_ptr_t &root)
Definition: exprtk.hpp:5460
node_collector_interface< Node > nci_t
Definition: exprtk.hpp:5454
nci_t::noderef_list_t noderef_list_t
Definition: exprtk.hpp:5458
Definition: exprtk.hpp:6036
null_eq_node(expression_ptr branch, const bool equality=true)
Definition: exprtk.hpp:6042
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6076
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6039
operator_type operation() const
Definition: exprtk.hpp:6066
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6061
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6040
T value() const
Definition: exprtk.hpp:6048
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:6071
std::size_t node_depth() const
Definition: exprtk.hpp:6081
Definition: exprtk.hpp:12496
virtual T operator()(parameter_list_t)
Definition: exprtk.hpp:12505
virtual ~null_igenfunc()
Definition: exprtk.hpp:12499
type_store< T > generic_type
Definition: exprtk.hpp:12502
generic_type::parameter_list parameter_list_t
Definition: exprtk.hpp:12503
Definition: exprtk.hpp:5975
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5983
T value() const
Definition: exprtk.hpp:5978
Definition: exprtk.hpp:6478
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6481
operator_type operation_
Definition: exprtk.hpp:6516
branch_t branch_[4]
Definition: exprtk.hpp:6517
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6504
quaternary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3)
Definition: exprtk.hpp:6484
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6482
T value() const
Definition: exprtk.hpp:6494
std::size_t node_depth() const
Definition: exprtk.hpp:6509
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6499
Definition: exprtk.hpp:6132
range_pack< T > range_t
Definition: exprtk.hpp:6135
virtual const range_t & range_ref() const =0
virtual range_t & range_ref()=0
virtual ~range_interface()
Definition: exprtk.hpp:6137
Definition: exprtk.hpp:7799
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7802
T & ref()
Definition: exprtk.hpp:7820
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7803
const T & ref() const
Definition: exprtk.hpp:7825
rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7807
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7830
T value() const
Definition: exprtk.hpp:7815
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7835
vec_data_store< T > vds_t
Definition: exprtk.hpp:7805
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:7804
Definition: exprtk.hpp:7737
T & ref()
Definition: exprtk.hpp:7759
std::size_t node_depth() const
Definition: exprtk.hpp:7784
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7769
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7774
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7740
rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7746
vec_data_store< T > vds_t
Definition: exprtk.hpp:7743
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7741
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:7742
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7779
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7744
const T & ref() const
Definition: exprtk.hpp:7764
T value() const
Definition: exprtk.hpp:7754
std::size_t node_depth() const
Definition: exprtk.hpp:7073
T value() const
Definition: exprtk.hpp:7035
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7023
repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:7026
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7024
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7067
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7062
Definition: exprtk.hpp:6815
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6848
std::size_t node_depth() const
Definition: exprtk.hpp:6859
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6819
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6853
T value() const
Definition: exprtk.hpp:6830
repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:6821
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6818
Definition: exprtk.hpp:12558
expression_node< T > * expression_ptr
Definition: exprtk.hpp:12561
bool * retinvk_ptr()
Definition: exprtk.hpp:12595
T value() const
Definition: exprtk.hpp:12572
results_context< T > results_context_t
Definition: exprtk.hpp:12562
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:12563
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:12600
return_envelope_node(expression_ptr body, results_context_t &rc)
Definition: exprtk.hpp:12565
std::size_t node_depth() const
Definition: exprtk.hpp:12605
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12590
Definition: exprtk.hpp:12492
Definition: exprtk.hpp:12514
results_context< T > results_context_t
Definition: exprtk.hpp:12520
null_igenfunc< T > igeneric_function_t
Definition: exprtk.hpp:12517
generic_function_node< T, igeneric_function_t > gen_function_t
Definition: exprtk.hpp:12519
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12546
igeneric_function_t * igeneric_function_ptr
Definition: exprtk.hpp:12518
T value() const
Definition: exprtk.hpp:12528
return_node(const std::vector< typename gen_function_t::expression_ptr > &arg_list, results_context_t &rc)
Definition: exprtk.hpp:12522
Definition: exprtk.hpp:11656
scand_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11661
T value() const
Definition: exprtk.hpp:11667
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11659
Definition: exprtk.hpp:11683
scor_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11688
T value() const
Definition: exprtk.hpp:11694
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11686
Definition: exprtk.hpp:9907
T value() const
Definition: exprtk.hpp:9918
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9923
sf3_var_node(const T &v0, const T &v1, const T &v2)
Definition: exprtk.hpp:9912
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9910
Definition: exprtk.hpp:14781
virtual ~sf3ext_type_node()
Definition: exprtk.hpp:14784
Definition: exprtk.hpp:9876
T value() const
Definition: exprtk.hpp:9889
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9879
sf4_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3)
Definition: exprtk.hpp:9881
Definition: exprtk.hpp:9940
T value() const
Definition: exprtk.hpp:9952
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9943
sf4_var_node(const T &v0, const T &v1, const T &v2, const T &v3)
Definition: exprtk.hpp:9945
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9957
Definition: exprtk.hpp:13977
virtual ~sos_base_node()
Definition: exprtk.hpp:13980
virtual operator_type operation() const
Definition: exprtk.hpp:13983
Definition: exprtk.hpp:15492
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15495
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15509
sos_node(SType0 p0, SType1 p1)
Definition: exprtk.hpp:15499
Operation operation_t
Definition: exprtk.hpp:15496
operator_type operation() const
Definition: exprtk.hpp:15514
T value() const
Definition: exprtk.hpp:15504
std::string & s1()
Definition: exprtk.hpp:15524
SType0 s0_
Definition: exprtk.hpp:15531
SType1 s1_
Definition: exprtk.hpp:15532
std::string & s0()
Definition: exprtk.hpp:15519
Definition: exprtk.hpp:13991
virtual operator_type operation() const
Definition: exprtk.hpp:13997
virtual ~sosos_base_node()
Definition: exprtk.hpp:13994
Definition: exprtk.hpp:15853
sosos_node(SType0 p0, SType1 p1, SType2 p2)
Definition: exprtk.hpp:15860
std::string & s2()
Definition: exprtk.hpp:15891
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15856
std::string & s0()
Definition: exprtk.hpp:15881
std::string & s1()
Definition: exprtk.hpp:15886
T value() const
Definition: exprtk.hpp:15866
SType1 s1_
Definition: exprtk.hpp:15899
SType0 s0_
Definition: exprtk.hpp:15898
SType2 s2_
Definition: exprtk.hpp:15900
operator_type operation() const
Definition: exprtk.hpp:15876
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15871
Operation operation_t
Definition: exprtk.hpp:15857
Definition: exprtk.hpp:15744
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:15748
str_sogens_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:15754
range_pack< T > range_t
Definition: exprtk.hpp:15749
irange_t * irange_ptr
Definition: exprtk.hpp:15752
T value() const
Definition: exprtk.hpp:15794
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15747
operator_type operation() const
Definition: exprtk.hpp:15835
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15830
range_t * range_ptr
Definition: exprtk.hpp:15750
range_interface< T > irange_t
Definition: exprtk.hpp:15751
Definition: exprtk.hpp:9499
std::size_t size() const
Definition: exprtk.hpp:9579
str_vararg_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:9512
const range_t & range_ref() const
Definition: exprtk.hpp:9589
std::size_t node_depth() const
Definition: exprtk.hpp:9605
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:9503
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9594
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:9599
irange_t * irange_ptr
Definition: exprtk.hpp:9507
range_pack< T > range_t
Definition: exprtk.hpp:9504
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9502
char_cptr base() const
Definition: exprtk.hpp:9574
std::string str() const
Definition: exprtk.hpp:9569
range_t & range_ref()
Definition: exprtk.hpp:9584
range_interface< T > irange_t
Definition: exprtk.hpp:9506
T value() const
Definition: exprtk.hpp:9557
range_t * range_ptr
Definition: exprtk.hpp:9505
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:9508
Definition: exprtk.hpp:15605
RangePack rp1_
Definition: exprtk.hpp:15658
Operation operation_t
Definition: exprtk.hpp:15609
SType1 s1_
Definition: exprtk.hpp:15657
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15634
std::string & s0()
Definition: exprtk.hpp:15644
str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
Definition: exprtk.hpp:15612
~str_xoxr_node()
Definition: exprtk.hpp:15618
std::string & s1()
Definition: exprtk.hpp:15649
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15608
operator_type operation() const
Definition: exprtk.hpp:15639
SType0 s0_
Definition: exprtk.hpp:15656
T value() const
Definition: exprtk.hpp:15623
Definition: exprtk.hpp:15542
SType0 s0_
Definition: exprtk.hpp:15593
SType1 s1_
Definition: exprtk.hpp:15594
std::string & s1()
Definition: exprtk.hpp:15586
std::string & s0()
Definition: exprtk.hpp:15581
str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
Definition: exprtk.hpp:15549
operator_type operation() const
Definition: exprtk.hpp:15576
RangePack rp0_
Definition: exprtk.hpp:15595
~str_xrox_node()
Definition: exprtk.hpp:15555
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15571
Operation operation_t
Definition: exprtk.hpp:15546
T value() const
Definition: exprtk.hpp:15560
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15545
Definition: exprtk.hpp:15668
str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
Definition: exprtk.hpp:15675
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15671
SType1 s1_
Definition: exprtk.hpp:15732
std::string & s1()
Definition: exprtk.hpp:15724
RangePack rp0_
Definition: exprtk.hpp:15733
SType0 s0_
Definition: exprtk.hpp:15731
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15709
Operation operation_t
Definition: exprtk.hpp:15672
std::string & s0()
Definition: exprtk.hpp:15719
operator_type operation() const
Definition: exprtk.hpp:15714
~str_xroxr_node()
Definition: exprtk.hpp:15682
T value() const
Definition: exprtk.hpp:15688
RangePack rp1_
Definition: exprtk.hpp:15734
Definition: exprtk.hpp:6148
virtual ~string_base_node()
Definition: exprtk.hpp:6153
virtual std::string str() const =0
virtual char_cptr base() const =0
range_data_type< T > range_data_type_t
Definition: exprtk.hpp:6151
virtual std::size_t size() const =0
Definition: exprtk.hpp:8471
std::string str() const
Definition: exprtk.hpp:8567
irange_t * irange_ptr
Definition: exprtk.hpp:8479
std::size_t size() const
Definition: exprtk.hpp:8577
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8475
range_t & range_ref()
Definition: exprtk.hpp:8582
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8592
char_cptr base() const
Definition: exprtk.hpp:8572
string_concat_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8481
T value() const
Definition: exprtk.hpp:8529
const range_t & range_ref() const
Definition: exprtk.hpp:8587
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8474
range_interface< T > irange_t
Definition: exprtk.hpp:8478
range_t * range_ptr
Definition: exprtk.hpp:8477
range_pack< T > range_t
Definition: exprtk.hpp:8476
Definition: exprtk.hpp:12313
std::string ret_string_
Definition: exprtk.hpp:12391
string_function_node(StringFunction *func, const std::vector< typename gen_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:12319
T value() const
Definition: exprtk.hpp:12334
bool operator<(const string_function_node< T, StringFunction > &fn) const
Definition: exprtk.hpp:12329
const range_t & range_ref() const
Definition: exprtk.hpp:12383
range_t & range_ref()
Definition: exprtk.hpp:12378
range_t range_
Definition: exprtk.hpp:12390
std::size_t size() const
Definition: exprtk.hpp:12373
std::string str() const
Definition: exprtk.hpp:12363
range_pack< T > range_t
Definition: exprtk.hpp:12317
char_cptr base() const
Definition: exprtk.hpp:12368
generic_function_node< T, StringFunction > gen_function_t
Definition: exprtk.hpp:12316
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12358
Definition: exprtk.hpp:6167
char_cptr base() const
Definition: exprtk.hpp:6201
string_literal_node(const std::string &v)
Definition: exprtk.hpp:6172
const range_t & range_ref() const
Definition: exprtk.hpp:6216
range_pack< T > range_t
Definition: exprtk.hpp:6170
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:6191
T value() const
Definition: exprtk.hpp:6181
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6186
range_t & range_ref()
Definition: exprtk.hpp:6211
std::size_t size() const
Definition: exprtk.hpp:6206
std::string str() const
Definition: exprtk.hpp:6196
Definition: exprtk.hpp:8182
virtual ~string_range_node()
Definition: exprtk.hpp:8194
range_t range() const
Definition: exprtk.hpp:8224
virtual std::string & ref()
Definition: exprtk.hpp:8229
std::string str() const
Definition: exprtk.hpp:8209
std::size_t size() const
Definition: exprtk.hpp:8219
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8249
const range_t & range_ref() const
Definition: exprtk.hpp:8244
range_t & range_ref()
Definition: exprtk.hpp:8239
char_cptr base() const
Definition: exprtk.hpp:8214
range_pack< T > range_t
Definition: exprtk.hpp:8185
virtual const std::string & ref() const
Definition: exprtk.hpp:8234
T value() const
Definition: exprtk.hpp:8204
string_range_node(std::string &v, const range_t &rp)
Definition: exprtk.hpp:8189
static std::string null_value
Definition: exprtk.hpp:8187
bool operator<(const string_range_node< T > &v) const
Definition: exprtk.hpp:8199
Definition: exprtk.hpp:8887
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8890
std::size_t node_depth() const
Definition: exprtk.hpp:8932
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:8892
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8922
T value() const
Definition: exprtk.hpp:8909
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:8927
string_size_node(expression_ptr branch)
Definition: exprtk.hpp:8895
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8891
Definition: exprtk.hpp:8096
T value() const
Definition: exprtk.hpp:8121
bool operator<(const stringvar_node< T > &v) const
Definition: exprtk.hpp:8116
std::size_t size() const
Definition: exprtk.hpp:8139
std::string & ref()
Definition: exprtk.hpp:8144
char_cptr base() const
Definition: exprtk.hpp:8134
std::string str() const
Definition: exprtk.hpp:8129
const range_t & range_ref() const
Definition: exprtk.hpp:8159
const std::string & ref() const
Definition: exprtk.hpp:8149
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8164
range_pack< T > range_t
Definition: exprtk.hpp:8099
range_t & range_ref()
Definition: exprtk.hpp:8154
stringvar_node(std::string &v)
Definition: exprtk.hpp:8107
static std::string null_value
Definition: exprtk.hpp:8101
stringvar_node()
Definition: exprtk.hpp:8103
Definition: exprtk.hpp:8854
static std::string null_value
Definition: exprtk.hpp:8857
stringvar_size_node()
Definition: exprtk.hpp:8859
stringvar_size_node(std::string &v)
Definition: exprtk.hpp:8863
T value() const
Definition: exprtk.hpp:8867
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8872
Definition: exprtk.hpp:7951
swap_generic_node(expression_ptr var0, expression_ptr var1)
Definition: exprtk.hpp:7957
ivariable< T > * ivariable_ptr
Definition: exprtk.hpp:7955
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7954
T value() const
Definition: exprtk.hpp:7963
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7969
Definition: exprtk.hpp:8697
range_interface< T > irange_t
Definition: exprtk.hpp:8704
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8700
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8835
irange_t * irange_ptr
Definition: exprtk.hpp:8705
T value() const
Definition: exprtk.hpp:8752
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8701
swap_genstrings_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8707
range_t * range_ptr
Definition: exprtk.hpp:8703
range_pack< T > range_t
Definition: exprtk.hpp:8702
Definition: exprtk.hpp:7921
T value() const
Definition: exprtk.hpp:7932
swap_node(variable_node_ptr var0, variable_node_ptr var1)
Definition: exprtk.hpp:7927
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7938
variable_node< T > * variable_node_ptr
Definition: exprtk.hpp:7925
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7924
Definition: exprtk.hpp:8612
swap_string_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8623
irange_t * irange_ptr
Definition: exprtk.hpp:8621
const range_t & range_ref() const
Definition: exprtk.hpp:8678
std::string str() const
Definition: exprtk.hpp:8658
std::size_t size() const
Definition: exprtk.hpp:8668
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8615
range_pack< T > range_t
Definition: exprtk.hpp:8618
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:8616
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8683
char_cptr base() const
Definition: exprtk.hpp:8663
range_t & range_ref()
Definition: exprtk.hpp:8673
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8617
range_t * range_ptr
Definition: exprtk.hpp:8619
range_interface< T > irange_t
Definition: exprtk.hpp:8620
T value() const
Definition: exprtk.hpp:8642
Definition: exprtk.hpp:7983
vec_data_store< T > vds_t
Definition: exprtk.hpp:7988
const vds_t & vds() const
Definition: exprtk.hpp:8077
vector_node_ptr vec()
Definition: exprtk.hpp:8057
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8062
std::size_t size() const
Definition: exprtk.hpp:8067
vector_node_ptr vec() const
Definition: exprtk.hpp:8052
swap_vecvec_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:7990
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7987
T value() const
Definition: exprtk.hpp:8028
vds_t & vds()
Definition: exprtk.hpp:8072
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7986
Definition: exprtk.hpp:7260
T value() const
Definition: exprtk.hpp:7271
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7263
switch_n_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:7267
Definition: exprtk.hpp:7186
std::size_t node_depth() const
Definition: exprtk.hpp:7248
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7189
T value() const
Definition: exprtk.hpp:7215
switch_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:7194
std::vector< branch_t > arg_list_
Definition: exprtk.hpp:7255
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7238
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7243
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7190
Definition: exprtk.hpp:6414
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6417
operator_type operation_
Definition: exprtk.hpp:6472
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6460
trinary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2)
Definition: exprtk.hpp:6420
std::size_t node_depth() const
Definition: exprtk.hpp:6465
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6455
T value() const
Definition: exprtk.hpp:6429
branch_t branch_[3]
Definition: exprtk.hpp:6473
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6418
Definition: exprtk.hpp:14140
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:14144
std::size_t node_depth() const
Definition: exprtk.hpp:14182
void release()
Definition: exprtk.hpp:14172
Operation operation_t
Definition: exprtk.hpp:14145
operator_type operation() const
Definition: exprtk.hpp:14162
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:14177
T value() const
Definition: exprtk.hpp:14152
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14143
unary_branch_node(expression_ptr branch)
Definition: exprtk.hpp:14147
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:14167
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14157
Definition: exprtk.hpp:6233
branch_t branch_
Definition: exprtk.hpp:6287
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:6264
std::size_t node_depth() const
Definition: exprtk.hpp:6279
unary_node(const operator_type &opr, expression_ptr branch)
Definition: exprtk.hpp:6239
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6236
operator_type operation_
Definition: exprtk.hpp:6286
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6274
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6254
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6237
void release()
Definition: exprtk.hpp:6269
operator_type operation() const
Definition: exprtk.hpp:6259
T value() const
Definition: exprtk.hpp:6245
Definition: exprtk.hpp:14027
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14042
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14030
const T & v() const
Definition: exprtk.hpp:14052
Operation operation_t
Definition: exprtk.hpp:14031
T value() const
Definition: exprtk.hpp:14037
operator_type operation() const
Definition: exprtk.hpp:14047
unary_variable_node(const T &var)
Definition: exprtk.hpp:14033
Definition: exprtk.hpp:11503
unary_vector_node(const operator_type &opr, expression_ptr branch0)
Definition: exprtk.hpp:11511
vec_data_store< T > vds_t
Definition: exprtk.hpp:11509
T value() const
Definition: exprtk.hpp:11552
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:11508
std::size_t size() const
Definition: exprtk.hpp:11631
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11506
vector_node_ptr vec()
Definition: exprtk.hpp:11621
vds_t & vds()
Definition: exprtk.hpp:11636
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11626
const vds_t & vds() const
Definition: exprtk.hpp:11641
~unary_vector_node()
Definition: exprtk.hpp:11546
vector_node_ptr vec() const
Definition: exprtk.hpp:11616
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:11507
Definition: exprtk.hpp:13961
virtual operator_type operation() const
Definition: exprtk.hpp:13967
virtual ~uv_base_node()
Definition: exprtk.hpp:13964
virtual const T & v() const =0
Definition: exprtk.hpp:14067
T value() const
Definition: exprtk.hpp:14086
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14091
ufunc_t f()
Definition: exprtk.hpp:14121
uvouv_node(const T &var0, const T &var1, ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
Definition: exprtk.hpp:14077
operator_type operation() const
Definition: exprtk.hpp:14096
const T & v0()
Definition: exprtk.hpp:14101
functor_t::ufunc_t ufunc_t
Definition: exprtk.hpp:14075
ufunc_t u1()
Definition: exprtk.hpp:14116
const T & v1()
Definition: exprtk.hpp:14106
ufunc_t u0()
Definition: exprtk.hpp:14111
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14074
details::functor_t< T > functor_t
Definition: exprtk.hpp:14073
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14072
Definition: exprtk.hpp:12043
bool operator<(const vararg_function_node< T, VarArgFunction > &fn) const
Definition: exprtk.hpp:12056
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:12077
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12072
vararg_function_node(VarArgFunction *func, const std::vector< expression_ptr > &arg_list)
Definition: exprtk.hpp:12048
expression_node< T > * expression_ptr
Definition: exprtk.hpp:12046
T value() const
Definition: exprtk.hpp:12061
std::size_t node_depth() const
Definition: exprtk.hpp:12088
Definition: exprtk.hpp:9975
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:9979
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10006
vararg_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:9983
T value() const
Definition: exprtk.hpp:10001
std::size_t node_depth() const
Definition: exprtk.hpp:10016
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:10011
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9978
Definition: exprtk.hpp:10028
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10062
T value() const
Definition: exprtk.hpp:10054
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10031
vararg_varnode(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:10035
Definition: exprtk.hpp:7368
T value() const
Definition: exprtk.hpp:7386
variable_node()
Definition: exprtk.hpp:7373
bool operator<(const variable_node< T > &v) const
Definition: exprtk.hpp:7381
static T null_value
Definition: exprtk.hpp:7371
const T & ref() const
Definition: exprtk.hpp:7396
T & ref()
Definition: exprtk.hpp:7391
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7401
variable_node(T &v)
Definition: exprtk.hpp:7377
Definition: exprtk.hpp:11345
std::size_t size() const
Definition: exprtk.hpp:11477
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11472
vector_node_ptr vec()
Definition: exprtk.hpp:11467
vec_data_store< T > vds_t
Definition: exprtk.hpp:11351
~vec_binop_valvec_node()
Definition: exprtk.hpp:11390
vector_node_ptr vec() const
Definition: exprtk.hpp:11462
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:11349
vds_t & vds()
Definition: exprtk.hpp:11482
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:11350
vec_binop_valvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11353
const vds_t & vds() const
Definition: exprtk.hpp:11487
T value() const
Definition: exprtk.hpp:11396
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11348
Definition: exprtk.hpp:11187
T value() const
Definition: exprtk.hpp:11238
~vec_binop_vecval_node()
Definition: exprtk.hpp:11232
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11314
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11190
vector_node_ptr vec()
Definition: exprtk.hpp:11309
vec_data_store< T > vds_t
Definition: exprtk.hpp:11193
const vds_t & vds() const
Definition: exprtk.hpp:11329
vds_t & vds()
Definition: exprtk.hpp:11324
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:11191
vector_node_ptr vec() const
Definition: exprtk.hpp:11304
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:11192
vec_binop_vecval_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11195
std::size_t size() const
Definition: exprtk.hpp:11319
Definition: exprtk.hpp:11000
T value() const
Definition: exprtk.hpp:11076
std::size_t size() const
Definition: exprtk.hpp:11159
vec_binop_vecvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11008
const vds_t & vds() const
Definition: exprtk.hpp:11169
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:11004
vector_node_ptr vec()
Definition: exprtk.hpp:11149
vds_t & vds()
Definition: exprtk.hpp:11164
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11154
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11003
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:11005
vector_node_ptr vec() const
Definition: exprtk.hpp:11144
~vec_binop_vecvec_node()
Definition: exprtk.hpp:11070
vec_data_store< T > vds_t
Definition: exprtk.hpp:11006
Definition: exprtk.hpp:4764
~vec_data_store()
Definition: exprtk.hpp:4873
type & operator=(const type &vds)
Definition: exprtk.hpp:4878
std::size_t size()
Definition: exprtk.hpp:4909
vec_data_store(const std::size_t &size)
Definition: exprtk.hpp:4859
data_t data()
Definition: exprtk.hpp:4899
data_t & ref()
Definition: exprtk.hpp:4919
void dump() const
Definition: exprtk.hpp:4924
vec_data_store(const std::size_t &size, data_t data, bool dstrct=false)
Definition: exprtk.hpp:4863
vec_data_store(const type &vds)
Definition: exprtk.hpp:4867
T * data_t
Definition: exprtk.hpp:4768
vec_data_store()
Definition: exprtk.hpp:4855
std::size_t size() const
Definition: exprtk.hpp:4914
static void match_sizes(type &vds0, type &vds1)
Definition: exprtk.hpp:4943
vec_data_store< T > type
Definition: exprtk.hpp:4767
data_t data() const
Definition: exprtk.hpp:4904
Definition: exprtk.hpp:7849
std::size_t node_depth() const
Definition: exprtk.hpp:7904
T value() const
Definition: exprtk.hpp:7864
vector_assignment_node(T *vector_base, const std::size_t &size, const std::vector< expression_ptr > &initialiser_list, const bool single_value_initialse)
Definition: exprtk.hpp:7854
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7899
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7852
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7894
Definition: exprtk.hpp:7677
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:7682
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7681
const T & ref() const
Definition: exprtk.hpp:7702
T value() const
Definition: exprtk.hpp:7692
std::size_t node_depth() const
Definition: exprtk.hpp:7722
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7712
T & ref()
Definition: exprtk.hpp:7697
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7717
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7707
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:7683
vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7685
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7680
Definition: exprtk.hpp:5778
vector_holder(Type *vec, const std::size_t &vec_size)
Definition: exprtk.hpp:5925
vector_holder(std::vector< Type, Allocator > &vec)
Definition: exprtk.hpp:5934
details::vec_data_store< Type > vds_t
Definition: exprtk.hpp:5923
vector_holder(exprtk::vector_view< Type > &vec)
Definition: exprtk.hpp:5938
std::size_t size() const
Definition: exprtk.hpp:5947
vector_holder(const vds_t &vds)
Definition: exprtk.hpp:5929
value_ptr data() const
Definition: exprtk.hpp:5952
value_ptr operator[](const std::size_t &index) const
Definition: exprtk.hpp:5942
void set_ref(value_ptr *ref)
Definition: exprtk.hpp:5957
bool rebaseable() const
Definition: exprtk.hpp:5962
Definition: exprtk.hpp:7583
virtual vector_node_ptr vec() const =0
virtual bool side_effect() const
Definition: exprtk.hpp:7602
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7586
virtual vector_node_ptr vec()=0
virtual std::size_t size() const =0
virtual ~vector_interface()
Definition: exprtk.hpp:7589
virtual const vds_t & vds() const =0
vec_data_store< T > vds_t
Definition: exprtk.hpp:7587
Definition: exprtk.hpp:7608
vector_node(const vds_t &vds, vector_holder_t *vh)
Definition: exprtk.hpp:7623
vector_node_ptr vec() const
Definition: exprtk.hpp:7633
vec_data_store< T > vds_t
Definition: exprtk.hpp:7614
vector_node(vector_holder_t *vh)
Definition: exprtk.hpp:7616
std::size_t size() const
Definition: exprtk.hpp:7648
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7613
vds_t & vds()
Definition: exprtk.hpp:7653
vector_node_ptr vec()
Definition: exprtk.hpp:7638
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7611
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7643
T value() const
Definition: exprtk.hpp:7628
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7663
const vds_t & vds() const
Definition: exprtk.hpp:7658
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7612
Definition: exprtk.hpp:10074
T value() const
Definition: exprtk.hpp:10093
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10077
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:10078
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:10112
std::size_t node_depth() const
Definition: exprtk.hpp:10117
vectorize_node(const expression_ptr v)
Definition: exprtk.hpp:10080
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10107
Definition: exprtk.hpp:13899
virtual ~vob_base_node()
Definition: exprtk.hpp:13902
virtual const T & v() const =0
Definition: exprtk.hpp:15245
const T & v() const
Definition: exprtk.hpp:15270
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15248
vob_node(const T &var, const expression_ptr branch)
Definition: exprtk.hpp:15253
Operation operation_t
Definition: exprtk.hpp:15250
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:15275
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15249
std::size_t node_depth() const
Definition: exprtk.hpp:15285
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:15280
T value() const
Definition: exprtk.hpp:15259
operator_type operation() const
Definition: exprtk.hpp:15265
Definition: exprtk.hpp:13881
virtual const T & v() const =0
virtual ~voc_base_node()
Definition: exprtk.hpp:13884
virtual const T c() const =0
virtual operator_type operation() const
Definition: exprtk.hpp:13887
Definition: exprtk.hpp:15200
Operation operation_t
Definition: exprtk.hpp:15204
const T & v() const
Definition: exprtk.hpp:15227
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15203
T value() const
Definition: exprtk.hpp:15212
voc_node(const T &var, const T &const_var)
Definition: exprtk.hpp:15207
const T c_
Definition: exprtk.hpp:15235
const T & v_
Definition: exprtk.hpp:15234
const T c() const
Definition: exprtk.hpp:15222
operator_type operation() const
Definition: exprtk.hpp:15217
Definition: exprtk.hpp:13845
virtual const T & v0() const =0
virtual const T & v1() const =0
virtual operator_type operation() const
Definition: exprtk.hpp:13851
virtual ~vov_base_node()
Definition: exprtk.hpp:13848
Definition: exprtk.hpp:15100
const T & v0_
Definition: exprtk.hpp:15139
Operation operation_t
Definition: exprtk.hpp:15104
vov_node(const T &var0, const T &var1)
Definition: exprtk.hpp:15107
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15103
operator_type operation() const
Definition: exprtk.hpp:15122
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15117
const T & v0() const
Definition: exprtk.hpp:15127
T value() const
Definition: exprtk.hpp:15112
const T & v1_
Definition: exprtk.hpp:15140
const T & v1() const
Definition: exprtk.hpp:15132
Definition: exprtk.hpp:6954
while_loop_bc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:6960
std::size_t node_depth() const
Definition: exprtk.hpp:7006
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6957
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6995
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:7000
T value() const
Definition: exprtk.hpp:6969
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6958
Definition: exprtk.hpp:6758
while_loop_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr(0))
Definition: exprtk.hpp:6764
std::size_t node_depth() const
Definition: exprtk.hpp:6801
T value() const
Definition: exprtk.hpp:6773
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6762
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6790
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6761
void collect_nodes(typename expression_node< T >::noderef_list_t &node_delete_list)
Definition: exprtk.hpp:6795
Definition: exprtk.hpp:18867
static bool is_variable(const expression< T > &expr)
Definition: exprtk.hpp:18875
static bool is_binary(const expression< T > &expr)
Definition: exprtk.hpp:18885
static bool is_constant(const expression< T > &expr)
Definition: exprtk.hpp:18870
static bool is_function(const expression< T > &expr)
Definition: exprtk.hpp:18890
static bool is_unary(const expression< T > &expr)
Definition: exprtk.hpp:18880
static bool is_null(const expression< T > &expr)
Definition: exprtk.hpp:18895
Definition: exprtk.hpp:18497
expression()
Definition: exprtk.hpp:18626
const symbol_table< T > & get_symbol_table(const std::size_t &index=0) const
Definition: exprtk.hpp:18724
symbol_table< T > & get_symbol_table(const std::size_t &index=0)
Definition: exprtk.hpp:18729
expression< T > & release()
Definition: exprtk.hpp:18684
expression(const expression< T > &e)
Definition: exprtk.hpp:18632
bool operator!() const
Definition: exprtk.hpp:18676
void register_symbol_table(symbol_table< T > &st)
Definition: exprtk.hpp:18719
bool operator==(const expression< T > &e) const
Definition: exprtk.hpp:18671
const results_context_t & results() const
Definition: exprtk.hpp:18736
expression(const symbol_table< T > &symbol_table)
Definition: exprtk.hpp:18639
bool return_invoked() const
Definition: exprtk.hpp:18747
results_context< T > results_context_t
Definition: exprtk.hpp:18734
~expression()
Definition: exprtk.hpp:18691
expression< T > & operator=(const expression< T > &e)
Definition: exprtk.hpp:18646
T value() const
Definition: exprtk.hpp:18696
Definition: exprtk.hpp:37144
Definition: exprtk.hpp:16643
function_traits()
Definition: exprtk.hpp:16646
std::size_t & max_num_args()
Definition: exprtk.hpp:16668
bool & allow_zero_parameters()
Definition: exprtk.hpp:16653
std::size_t & min_num_args()
Definition: exprtk.hpp:16663
bool & has_side_effects()
Definition: exprtk.hpp:16658
Definition: exprtk.hpp:16727
virtual T operator()() empty_method_body(0) inline virtual T operator()(const T &) empty_method_body(1) inline virtual T operator()(const T &
virtual T const T & empty_method_body(2) inline virtual T operator()(const T &
virtual ~ifunction()
Definition: exprtk.hpp:16734
ifunction(const std::size_t &pc)
Definition: exprtk.hpp:16730
Definition: exprtk.hpp:16838
generic_type::parameter_list parameter_list_t
Definition: exprtk.hpp:16850
T type
Definition: exprtk.hpp:16848
igeneric_function(const std::string &param_seq="", const return_type rtr_type=e_rtrn_scalar)
Definition: exprtk.hpp:16852
type_store< T > generic_type
Definition: exprtk.hpp:16849
virtual ~igeneric_function()
Definition: exprtk.hpp:16857
return_type
Definition: exprtk.hpp:16842
@ e_rtrn_scalar
Definition: exprtk.hpp:16843
@ e_rtrn_string
Definition: exprtk.hpp:16844
@ e_rtrn_overload
Definition: exprtk.hpp:16845
virtual T operator()(parameter_list_t) igeneric_function_empty_body(1) inline virtual T operator()(std return_type rtrn_type
Definition: exprtk.hpp:16867
Definition: exprtk.hpp:16823
virtual ~ivararg_function()
Definition: exprtk.hpp:16826
virtual T operator()(const std::vector< T > &)
Definition: exprtk.hpp:16829
Definition: exprtk.hpp:2242
token_t & operator[](const std::size_t &index)
Definition: exprtk.hpp:2334
token_t & peek_next_token()
Definition: exprtk.hpp:2324
token_t operator[](const std::size_t &index) const
Definition: exprtk.hpp:2342
token_t & next_token()
Definition: exprtk.hpp:2314
bool finished() const
Definition: exprtk.hpp:2350
void insert_front(token_t::token_type tk_type)
Definition: exprtk.hpp:2355
std::string substr(const std::size_t &begin, const std::size_t &end)
Definition: exprtk.hpp:2369
void begin()
Definition: exprtk.hpp:2298
bool process(const std::string &str)
Definition: exprtk.hpp:2268
bool empty() const
Definition: exprtk.hpp:2288
token_list_t::iterator token_list_itr_t
Definition: exprtk.hpp:2247
details::char_t char_t
Definition: exprtk.hpp:2248
void store()
Definition: exprtk.hpp:2304
void restore()
Definition: exprtk.hpp:2309
generator()
Definition: exprtk.hpp:2250
token token_t
Definition: exprtk.hpp:2245
void clear()
Definition: exprtk.hpp:2258
std::size_t size() const
Definition: exprtk.hpp:2293
std::vector< token_t > token_list_t
Definition: exprtk.hpp:2246
std::string remaining() const
Definition: exprtk.hpp:2377
Definition: exprtk.hpp:3530
bool result()
Definition: exprtk.hpp:3540
bool operator()(const lexer::token &t)
Definition: exprtk.hpp:3569
bracket_checker()
Definition: exprtk.hpp:3535
lexer::token error_token()
Definition: exprtk.hpp:3556
void reset()
Definition: exprtk.hpp:3561
void ignore_symbol(const std::string &symbol)
Definition: exprtk.hpp:3304
int insert(const lexer::token &t0, const lexer::token &t1, lexer::token &new_token)
Definition: exprtk.hpp:3309
commutative_inserter()
Definition: exprtk.hpp:3300
Definition: exprtk.hpp:3615
void reset()
Definition: exprtk.hpp:3630
void clear_errors()
Definition: exprtk.hpp:3666
std::size_t error_count() const
Definition: exprtk.hpp:3653
bool operator()(const lexer::token &t)
Definition: exprtk.hpp:3636
std::size_t error_index(const std::size_t &i)
Definition: exprtk.hpp:3658
bool result()
Definition: exprtk.hpp:3625
numeric_checker()
Definition: exprtk.hpp:3620
Definition: exprtk.hpp:3357
operator_joiner(const std::size_t &stride)
Definition: exprtk.hpp:3360
bool join(const lexer::token &t0, const lexer::token &t1, lexer::token &t)
Definition: exprtk.hpp:3364
bool join(const lexer::token &t0, const lexer::token &t1, const lexer::token &t2, lexer::token &t)
Definition: exprtk.hpp:3509
std::pair< lexer::token, lexer::token > error(const std::size_t index)
Definition: exprtk.hpp:3972
sequence_validator_3tokens()
Definition: exprtk.hpp:3928
void clear_errors()
Definition: exprtk.hpp:3985
std::size_t error_count() const
Definition: exprtk.hpp:3967
bool operator()(const lexer::token &t0, const lexer::token &t1, const lexer::token &t2)
Definition: exprtk.hpp:3955
bool result()
Definition: exprtk.hpp:3950
bool result()
Definition: exprtk.hpp:3783
std::pair< lexer::token, lexer::token > error(const std::size_t index)
Definition: exprtk.hpp:3809
std::size_t error_count() const
Definition: exprtk.hpp:3804
sequence_validator()
Definition: exprtk.hpp:3755
void clear_errors()
Definition: exprtk.hpp:3822
bool operator()(const lexer::token &t0, const lexer::token &t1)
Definition: exprtk.hpp:3788
Definition: exprtk.hpp:3678
bool remove(const std::string &target_symbol)
Definition: exprtk.hpp:3685
void clear()
Definition: exprtk.hpp:3713
bool add_replace(const std::string &target_symbol, const std::string &replace_symbol, const lexer::token::token_type token_type=lexer::token::e_symbol)
Definition: exprtk.hpp:3697
Definition: exprtk.hpp:2923
virtual bool result()
Definition: exprtk.hpp:2928
virtual void init()
Definition: exprtk.hpp:2926
virtual std::size_t process(generator &)
Definition: exprtk.hpp:2929
virtual ~helper_interface()
Definition: exprtk.hpp:2930
virtual void reset()
Definition: exprtk.hpp:2927
Definition: exprtk.hpp:4160
void advance_token(const token_advance_mode mode)
Definition: exprtk.hpp:4218
token_advance_mode
Definition: exprtk.hpp:4213
@ e_hold
Definition: exprtk.hpp:4214
@ e_advance
Definition: exprtk.hpp:4215
const generator_t & lexer() const
Definition: exprtk.hpp:4185
bool peek_token_is(const token_t::token_type &ttype)
Definition: exprtk.hpp:4255
void next_token()
Definition: exprtk.hpp:4202
void restore_token()
Definition: exprtk.hpp:4196
bool peek_token_is(const std::string &s)
Definition: exprtk.hpp:4260
token token_t
Definition: exprtk.hpp:4163
generator_t & lexer()
Definition: exprtk.hpp:4180
bool init(const std::string &str)
Definition: exprtk.hpp:4166
generator generator_t
Definition: exprtk.hpp:4164
bool token_is(const token_t::token_type &ttype, const std::string &value, const token_advance_mode mode=e_advance)
Definition: exprtk.hpp:4238
void store_token()
Definition: exprtk.hpp:4190
const token_t & current_token() const
Definition: exprtk.hpp:4207
bool token_is(const token_t::token_type &ttype, const token_advance_mode mode=e_advance)
Definition: exprtk.hpp:4226
Definition: exprtk.hpp:3060
virtual int const token token &virtual token_inserter_empty_body int insert(const token &, const token &, const token &, token &) token_inserter_empty_body inline virtual int insert(const token &
virtual int insert(const token &, token &) token_inserter_empty_body inline virtual int insert(const token &
std::size_t process(generator &g)
Definition: exprtk.hpp:3072
token_inserter(const std::size_t &stride)
Definition: exprtk.hpp:3063
Definition: exprtk.hpp:3169
virtual bool join(const token &, const token &, token &)
Definition: exprtk.hpp:3189
token_joiner(const std::size_t &stride)
Definition: exprtk.hpp:3172
std::size_t process(generator &g)
Definition: exprtk.hpp:3176
virtual bool join(const token &, const token &, const token &, token &)
Definition: exprtk.hpp:3190
Definition: exprtk.hpp:3041
std::size_t process(generator &g)
Definition: exprtk.hpp:3044
virtual bool modify(token &t)=0
Definition: exprtk.hpp:2934
token_scanner(const std::size_t &stride)
Definition: exprtk.hpp:2940
virtual bool operator()(const token &)
Definition: exprtk.hpp:3015
std::size_t process(generator &g)
Definition: exprtk.hpp:2949
virtual ~token_scanner()
Definition: exprtk.hpp:2937
Definition: exprtk.hpp:20078
std::pair< std::string, symbol_type > symbol_t
Definition: exprtk.hpp:20081
bool & collect_variables()
Definition: exprtk.hpp:20148
void clear()
Definition: exprtk.hpp:20139
std::vector< std::string > retparam_list_t
Definition: exprtk.hpp:20173
bool & collect_assignments()
Definition: exprtk.hpp:20158
bool final_stmt_return() const
Definition: exprtk.hpp:20168
bool return_present() const
Definition: exprtk.hpp:20163
std::vector< symbol_t > symbol_list_t
Definition: exprtk.hpp:20082
bool & collect_functions()
Definition: exprtk.hpp:20153
std::size_t assignment_symbols(Sequence< symbol_t, Allocator > &assignment_list)
Definition: exprtk.hpp:20118
retparam_list_t return_param_type_list() const
Definition: exprtk.hpp:20175
dependent_entity_collector(const std::size_t options=e_ct_none)
Definition: exprtk.hpp:20084
std::size_t symbols(Sequence< symbol_t, Allocator > &symbols_list)
Definition: exprtk.hpp:20095
Definition: exprtk.hpp:20234
settings_store & disable_all_arithmetic_ops()
Definition: exprtk.hpp:20405
bool collect_functions_enabled() const
Definition: exprtk.hpp:20446
settings_store & disable_base_function(settings_base_funcs bf)
Definition: exprtk.hpp:20563
settings_store & enable_all_control_structures()
Definition: exprtk.hpp:20342
settings_store & disable_all_inequality_ops()
Definition: exprtk.hpp:20423
settings_store & enable_all_arithmetic_ops()
Definition: exprtk.hpp:20354
bool control_struct_disabled(const std::string &control_struct) const
Definition: exprtk.hpp:20511
bool function_disabled(const std::string &function_name) const
Definition: exprtk.hpp:20503
void set_max_stack_depth(const std::size_t mx_stack_depth)
Definition: exprtk.hpp:20749
bool collect_variables_enabled() const
Definition: exprtk.hpp:20445
settings_store & disable_inequality_operation(settings_inequality_opr inequality)
Definition: exprtk.hpp:20628
bool assignment_enabled(const details::operator_type &assignment) const
Definition: exprtk.hpp:20485
bool vardef_disabled() const
Definition: exprtk.hpp:20448
settings_store & disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
Definition: exprtk.hpp:20602
settings_store & enable_all_inequality_ops()
Definition: exprtk.hpp:20366
settings_store & disable_all_base_functions()
Definition: exprtk.hpp:20378
settings_store & enable_logic_operation(settings_logic_opr logic)
Definition: exprtk.hpp:20677
settings_assignment_opr
Definition: exprtk.hpp:20307
@ e_assign_addass
Definition: exprtk.hpp:20309
@ e_assign_divass
Definition: exprtk.hpp:20310
settings_store & enable_base_function(settings_base_funcs bf)
Definition: exprtk.hpp:20641
settings_control_structs
Definition: exprtk.hpp:20281
@ e_ctrl_repeat_loop
Definition: exprtk.hpp:20287
@ e_ctrl_switch
Definition: exprtk.hpp:20284
@ e_ctrl_for_loop
Definition: exprtk.hpp:20285
@ e_ctrl_while_loop
Definition: exprtk.hpp:20286
@ e_ctrl_ifelse
Definition: exprtk.hpp:20283
settings_compilation_options
Definition: exprtk.hpp:20243
settings_store & disable_assignment_operation(settings_assignment_opr assignment)
Definition: exprtk.hpp:20615
settings_store & disable_all_logic_ops()
Definition: exprtk.hpp:20396
bool assignment_disabled(const details::operator_type assignment_operation) const
Definition: exprtk.hpp:20527
settings_inequality_opr
Definition: exprtk.hpp:20314
@ e_ineq_equal
Definition: exprtk.hpp:20317
@ e_ineq_gte
Definition: exprtk.hpp:20318
@ e_ineq_eq
Definition: exprtk.hpp:20316
bool bracket_check_enabled() const
Definition: exprtk.hpp:20442
settings_store(const std::size_t compile_options=compile_all_opts)
Definition: exprtk.hpp:20329
bool logic_enabled(const std::string &logic_operation) const
Definition: exprtk.hpp:20468
bool rsrvd_sym_usr_disabled() const
Definition: exprtk.hpp:20449
settings_store & disable_all_assignment_ops()
Definition: exprtk.hpp:20414
settings_base_funcs
Definition: exprtk.hpp:20261
@ e_bf_rad2deg
Definition: exprtk.hpp:20277
@ e_bf_min
Definition: exprtk.hpp:20271
@ e_bf_avg
Definition: exprtk.hpp:20265
@ e_bf_swap
Definition: exprtk.hpp:20275
@ e_bf_erf
Definition: exprtk.hpp:20267
@ e_bf_asinh
Definition: exprtk.hpp:20264
@ e_bf_like
Definition: exprtk.hpp:20269
@ e_bf_abs
Definition: exprtk.hpp:20263
@ e_bf_ncdf
Definition: exprtk.hpp:20272
@ e_bf_roundn
Definition: exprtk.hpp:20273
@ e_bf_deg2grad
Definition: exprtk.hpp:20276
@ e_bf_sinc
Definition: exprtk.hpp:20274
@ e_bf_log2
Definition: exprtk.hpp:20270
@ e_bf_cosh
Definition: exprtk.hpp:20266
@ e_bf_floor
Definition: exprtk.hpp:20268
settings_store & disable_control_structure(settings_control_structs ctrl_struct)
Definition: exprtk.hpp:20576
bool zero_return_disabled() const
Definition: exprtk.hpp:20450
settings_store & enable_control_structure(settings_control_structs ctrl_struct)
Definition: exprtk.hpp:20659
bool control_struct_enabled(const std::string &control_struct) const
Definition: exprtk.hpp:20460
settings_store & disable_local_vardef()
Definition: exprtk.hpp:20432
void set_max_node_depth(const std::size_t max_node_depth)
Definition: exprtk.hpp:20754
bool commutative_check_enabled() const
Definition: exprtk.hpp:20439
settings_arithmetic_opr
Definition: exprtk.hpp:20300
@ e_arith_add
Definition: exprtk.hpp:20302
@ e_arith_div
Definition: exprtk.hpp:20303
settings_store & disable_logic_operation(settings_logic_opr logic)
Definition: exprtk.hpp:20589
settings_store & enable_all_logic_ops()
Definition: exprtk.hpp:20348
settings_store & enable_inequality_operation(settings_inequality_opr inequality)
Definition: exprtk.hpp:20731
bool inequality_enabled(const details::operator_type &inequality) const
Definition: exprtk.hpp:20494
bool inequality_disabled(const details::operator_type &inequality) const
Definition: exprtk.hpp:20554
settings_store & enable_assignment_operation(settings_assignment_opr assignment)
Definition: exprtk.hpp:20713
settings_store & enable_local_vardef()
Definition: exprtk.hpp:20372
bool logic_disabled(const std::string &logic_operation) const
Definition: exprtk.hpp:20519
bool joiner_enabled() const
Definition: exprtk.hpp:20440
bool collect_assignments_enabled() const
Definition: exprtk.hpp:20447
bool numeric_check_enabled() const
Definition: exprtk.hpp:20441
settings_store & enable_all_base_functions()
Definition: exprtk.hpp:20336
bool arithmetic_enabled(const details::operator_type &arithmetic_operation) const
Definition: exprtk.hpp:20476
settings_logic_opr
Definition: exprtk.hpp:20292
@ e_logic_scand
Definition: exprtk.hpp:20296
@ e_logic_and
Definition: exprtk.hpp:20294
@ e_logic_not
Definition: exprtk.hpp:20295
bool replacer_enabled() const
Definition: exprtk.hpp:20438
settings_store & disable_all_control_structures()
Definition: exprtk.hpp:20387
bool strength_reduction_enabled() const
Definition: exprtk.hpp:20444
bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
Definition: exprtk.hpp:20545
bool function_enabled(const std::string &function_name) const
Definition: exprtk.hpp:20452
bool logic_disabled(const details::operator_type logic_operation) const
Definition: exprtk.hpp:20536
bool sequence_check_enabled() const
Definition: exprtk.hpp:20443
settings_store & enable_all_assignment_ops()
Definition: exprtk.hpp:20360
settings_store & enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
Definition: exprtk.hpp:20695
Definition: exprtk.hpp:19043
void enable_unknown_symbol_resolver(unknown_symbol_resolver &usr)
Definition: exprtk.hpp:21282
void init_precompilation()
Definition: exprtk.hpp:20904
expression_t compile(const std::string &expression_string, symbol_table_t &symtab)
Definition: exprtk.hpp:21064
bool compile(const std::string &expression_string, expression< T > &expr)
Definition: exprtk.hpp:20968
parser(const settings_t &settings=settings_t())
Definition: exprtk.hpp:20865
symbol_type
Definition: exprtk.hpp:20065
settings_store settings_t
Definition: exprtk.hpp:20863
void process_lexer_errors()
Definition: exprtk.hpp:21075
void enable_unknown_symbol_resolver(unknown_symbol_resolver *usr=reinterpret_cast< unknown_symbol_resolver * >(0))
Definition: exprtk.hpp:21272
dependent_entity_collector & dec()
Definition: exprtk.hpp:21247
bool remove_replace_symbol(const std::string &symbol)
Definition: exprtk.hpp:21262
~parser()
Definition: exprtk.hpp:20901
bool run_assemblies()
Definition: exprtk.hpp:21112
void register_loop_runtime_check(loop_runtime_check &lrtchk)
Definition: exprtk.hpp:21293
parser_error::type get_error(const std::size_t &index) const
Definition: exprtk.hpp:21224
std::string error() const
Definition: exprtk.hpp:21232
bool replace_symbol(const std::string &old_symbol, const std::string &new_symbol)
Definition: exprtk.hpp:21252
std::size_t error_count() const
Definition: exprtk.hpp:21242
void clear_loop_runtime_check()
Definition: exprtk.hpp:21298
void disable_unknown_symbol_resolver()
Definition: exprtk.hpp:21287
settings_store & settings()
Definition: exprtk.hpp:21219
collect_type
Definition: exprtk.hpp:20057
Definition: exprtk.hpp:36903
Definition: exprtk.hpp:4552
const type_store_t & operator[](const std::size_t &index) const
Definition: exprtk.hpp:4574
std::size_t count() const
Definition: exprtk.hpp:4561
results_context()
Definition: exprtk.hpp:4557
type_store_t & operator[](const std::size_t &index)
Definition: exprtk.hpp:4569
type_store< T > type_store_t
Definition: exprtk.hpp:4555
Definition: exprtk.hpp:38767
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38774
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38772
T operator()(std::string &result, parameter_list_t parameters)
Definition: exprtk.hpp:38782
getline()
Definition: exprtk.hpp:38778
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38770
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38771
generic_type::string_view string_t
Definition: exprtk.hpp:38773
Definition: exprtk.hpp:38581
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:38595
generic_type::string_view string_t
Definition: exprtk.hpp:38587
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38584
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38586
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38585
open()
Definition: exprtk.hpp:38591
Definition: exprtk.hpp:38710
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38715
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:38726
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38713
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38717
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38714
read()
Definition: exprtk.hpp:38722
generic_type::vector_view vector_t
Definition: exprtk.hpp:38718
generic_type::string_view string_t
Definition: exprtk.hpp:38716
Definition: exprtk.hpp:38653
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38656
generic_type::vector_view vector_t
Definition: exprtk.hpp:38661
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:38669
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38660
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38658
generic_type::string_view string_t
Definition: exprtk.hpp:38659
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38657
write()
Definition: exprtk.hpp:38665
Definition: exprtk.hpp:38959
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:38978
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38964
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38962
all_false()
Definition: exprtk.hpp:38969
generic_type::vector_view vector_t
Definition: exprtk.hpp:38965
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38963
Definition: exprtk.hpp:38913
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38917
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38916
generic_type::vector_view vector_t
Definition: exprtk.hpp:38919
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38918
all_true()
Definition: exprtk.hpp:38923
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:38932
Definition: exprtk.hpp:39051
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39070
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39054
any_false()
Definition: exprtk.hpp:39061
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39056
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39055
generic_type::vector_view vector_t
Definition: exprtk.hpp:39057
Definition: exprtk.hpp:39005
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39009
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39024
generic_type::vector_view vector_t
Definition: exprtk.hpp:39011
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39008
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39010
any_true()
Definition: exprtk.hpp:39015
Definition: exprtk.hpp:39653
generic_type::vector_view vector_t
Definition: exprtk.hpp:39660
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39659
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39656
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39657
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39658
axpby()
Definition: exprtk.hpp:39664
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39674
Definition: exprtk.hpp:39751
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39754
axpbyz()
Definition: exprtk.hpp:39762
generic_type::vector_view vector_t
Definition: exprtk.hpp:39758
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39772
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39757
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39755
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39756
Definition: exprtk.hpp:39802
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39805
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39806
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39808
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39807
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39823
generic_type::vector_view vector_t
Definition: exprtk.hpp:39809
axpbz()
Definition: exprtk.hpp:39813
Definition: exprtk.hpp:39606
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39611
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39612
generic_type::vector_view vector_t
Definition: exprtk.hpp:39613
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39610
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39627
axpy()
Definition: exprtk.hpp:39617
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39609
Definition: exprtk.hpp:39701
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39722
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39705
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39707
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39704
generic_type::vector_view vector_t
Definition: exprtk.hpp:39708
axpyz()
Definition: exprtk.hpp:39712
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39706
Definition: exprtk.hpp:39142
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39145
generic_type::vector_view vector_t
Definition: exprtk.hpp:39149
copy()
Definition: exprtk.hpp:39153
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39162
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39148
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39147
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39146
Definition: exprtk.hpp:39097
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39101
count()
Definition: exprtk.hpp:39107
generic_type::vector_view vector_t
Definition: exprtk.hpp:39103
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39116
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39102
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39100
Definition: exprtk.hpp:39850
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39870
generic_type::vector_view vector_t
Definition: exprtk.hpp:39857
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39854
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39853
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39856
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39855
dot()
Definition: exprtk.hpp:39861
Definition: exprtk.hpp:39896
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39899
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39902
dotk()
Definition: exprtk.hpp:39907
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39901
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39916
generic_type::vector_view vector_t
Definition: exprtk.hpp:39903
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39900
Definition: exprtk.hpp:39511
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39517
iota()
Definition: exprtk.hpp:39522
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39533
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39515
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39516
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39514
generic_type::vector_view vector_t
Definition: exprtk.hpp:39518
Definition: exprtk.hpp:39469
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39474
nthelement()
Definition: exprtk.hpp:39480
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39475
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39473
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39472
generic_type::vector_view vector_t
Definition: exprtk.hpp:39476
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39489
Definition: exprtk.hpp:39192
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39196
generic_type::vector_view vector_t
Definition: exprtk.hpp:39199
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39198
rol()
Definition: exprtk.hpp:39203
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39197
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39195
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39212
Definition: exprtk.hpp:39243
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39249
ror()
Definition: exprtk.hpp:39254
generic_type::vector_view vector_t
Definition: exprtk.hpp:39250
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39247
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39246
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39248
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39263
Definition: exprtk.hpp:39294
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39314
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39297
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39298
shift_left()
Definition: exprtk.hpp:39305
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39299
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39300
generic_type::vector_view vector_t
Definition: exprtk.hpp:39301
Definition: exprtk.hpp:39352
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39356
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39357
generic_type::vector_view vector_t
Definition: exprtk.hpp:39359
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39372
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39355
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:39358
shift_right()
Definition: exprtk.hpp:39363
Definition: exprtk.hpp:39412
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39434
sort()
Definition: exprtk.hpp:39423
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39417
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39415
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39416
generic_type::vector_view vector_t
Definition: exprtk.hpp:39419
generic_type::string_view string_t
Definition: exprtk.hpp:39418
Definition: exprtk.hpp:39563
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:39566
generic_type::vector_view vector_t
Definition: exprtk.hpp:39569
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:39567
igfun_t::generic_type generic_type
Definition: exprtk.hpp:39568
sumk()
Definition: exprtk.hpp:39573
T operator()(const std::size_t &ps_index, parameter_list_t parameters)
Definition: exprtk.hpp:39582
Definition: exprtk.hpp:16891
void clear_local_constants()
Definition: exprtk.hpp:17654
bool add_package(Package &package)
Definition: exprtk.hpp:18176
bool remove_vararg_function(const std::string &vararg_function_name)
Definition: exprtk.hpp:18133
bool add_constant(const std::string &constant_name, const T &value)
Definition: exprtk.hpp:17888
variable_ptr get_variable(const T &var_ref) const
Definition: exprtk.hpp:17713
std::size_t function_count() const
Definition: exprtk.hpp:17687
generic_function_ptr get_string_function(const std::string &function_name) const
Definition: exprtk.hpp:17764
bool add_epsilon()
Definition: exprtk.hpp:18163
variable_t * variable_ptr
Definition: exprtk.hpp:17475
bool is_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:18299
bool remove_variable(const std::string &variable_name, const bool delete_node=true)
Definition: exprtk.hpp:18107
void clear_variables(const bool delete_node=true)
Definition: exprtk.hpp:17632
std::string & stringvar_ref(const std::string &symbol_name)
Definition: exprtk.hpp:17808
void clear_functions()
Definition: exprtk.hpp:17637
bool add_vector(const std::string &vector_name, std::vector< T, Allocator > &v)
Definition: exprtk.hpp:18079
bool is_function(const std::string &function_name) const
Definition: exprtk.hpp:18291
std::string get_variable_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:18315
bool add_function(const std::string &vararg_function_name, vararg_function_t &vararg_function)
Definition: exprtk.hpp:17929
bool add_function(const std::string &function_name, function_t &function)
Definition: exprtk.hpp:17917
bool is_stringvar(const std::string &stringvar_name) const
Definition: exprtk.hpp:18267
void clear_strings()
Definition: exprtk.hpp:17642
bool add_infinity()
Definition: exprtk.hpp:18169
details::vector_holder< T > vector_holder_t
Definition: exprtk.hpp:17474
bool remove_vector(const std::string &vector_name)
Definition: exprtk.hpp:18141
bool is_constant_node(const std::string &symbol_name) const
Definition: exprtk.hpp:17820
stringvar_t * stringvar_ptr
Definition: exprtk.hpp:17478
std::size_t get_variable_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:18193
bool is_vector(const std::string &vector_name) const
Definition: exprtk.hpp:18307
std::string get_stringvar_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:18326
ivararg_function< T > vararg_function_t
Definition: exprtk.hpp:17481
vararg_function_t * vararg_function_ptr
Definition: exprtk.hpp:17484
bool add_reserved_function(const std::string &vararg_function_name, vararg_function_t &vararg_function)
Definition: exprtk.hpp:18010
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:17784
function_ptr get_function(const std::string &function_name) const
Definition: exprtk.hpp:17734
void load_from(const symbol_table< T > &st)
Definition: exprtk.hpp:18343
details::expression_node< T > * expression_ptr
Definition: exprtk.hpp:17472
igeneric_function< T > generic_function_t
Definition: exprtk.hpp:17482
std::size_t get_variable_list(Sequence< std::pair< std::string, T >, Allocator > &vlist) const
Definition: exprtk.hpp:18183
stringvar_ptr get_stringvar(const std::string &string_name) const
Definition: exprtk.hpp:17723
std::string get_conststr_stringvar_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:18331
void clear_vectors()
Definition: exprtk.hpp:17649
bool add_vector(const std::string &vector_name, T *v, const std::size_t &v_size)
Definition: exprtk.hpp:18064
generic_function_t * generic_function_ptr
Definition: exprtk.hpp:17485
std::size_t variable_count() const
Definition: exprtk.hpp:17669
bool create_stringvar(const std::string &stringvar_name, const std::string &value=std::string(""))
Definition: exprtk.hpp:17860
bool remove_stringvar(const std::string &string_name)
Definition: exprtk.hpp:18116
std::string get_vector_name(const vector_holder_ptr &ptr) const
Definition: exprtk.hpp:18320
exprtk_define_freefunction(00) exprtk_define_freefunction(01) exprtk_define_freefunction(02) exprtk_define_freefunction(03) exprtk_define_freefunction(04) exprtk_define_freefunction(05) exprtk_define_freefunction(06) exprtk_define_freefunction(07) exprtk_define_freefunction(08) exprtk_define_freefunction(09) exprtk_define_freefunction(10) exprtk_define_freefunction(11) exprtk_define_freefunction(12) exprtk_define_freefunction(13) exprtk_define_freefunction(14) exprtk_define_freefunction(15) inline bool add_reserved_function(const std
Definition: exprtk.hpp:17987
bool add_constants()
Definition: exprtk.hpp:18149
variable_ptr get_variable(const std::string &variable_name) const
Definition: exprtk.hpp:17703
symbol_table(const symbol_table< T > &st)
Definition: exprtk.hpp:17608
bool add_function(const std::string &function_name, generic_function_t &function)
Definition: exprtk.hpp:17941
generic_function_ptr get_generic_function(const std::string &function_name) const
Definition: exprtk.hpp:17754
bool create_variable(const std::string &variable_name, const T &value=T(0))
Definition: exprtk.hpp:17844
void clear()
Definition: exprtk.hpp:17659
bool add_pi()
Definition: exprtk.hpp:18156
generic_function_ptr get_overload_function(const std::string &function_name) const
Definition: exprtk.hpp:17774
std::size_t vector_count() const
Definition: exprtk.hpp:17695
bool operator==(const symbol_table< T > &st) const
Definition: exprtk.hpp:17627
bool is_conststr_stringvar(const std::string &symbol_name) const
Definition: exprtk.hpp:18275
bool add_variable(const std::string &variable_name, T &t, const bool is_constant=false)
Definition: exprtk.hpp:17876
bool add_vector(const std::string &vector_name, exprtk::vector_view< T > &v)
Definition: exprtk.hpp:18093
bool is_constant_string(const std::string &symbol_name) const
Definition: exprtk.hpp:17831
bool valid() const
Definition: exprtk.hpp:18337
symbol_table< T > & operator=(const symbol_table< T > &st)
Definition: exprtk.hpp:17614
std::size_t get_vector_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:18225
bool symbol_exists(const std::string &symbol_name, const bool check_reserved_symb=true) const
Definition: exprtk.hpp:18233
bool add_reserved_function(const std::string &function_name, generic_function_t &function)
Definition: exprtk.hpp:18022
details::stringvar_node< T > stringvar_t
Definition: exprtk.hpp:17477
std::size_t get_stringvar_list(Sequence< std::string, Allocator > &svlist) const
Definition: exprtk.hpp:18214
bool add_vector(const std::string &vector_name, T(&v)[N])
Definition: exprtk.hpp:18052
T & variable_ref(const std::string &symbol_name)
Definition: exprtk.hpp:17796
bool add_stringvar(const std::string &stringvar_name, std::string &s, const bool is_constant=false)
Definition: exprtk.hpp:17904
function_t * function_ptr
Definition: exprtk.hpp:17483
ifunction< T > function_t
Definition: exprtk.hpp:17480
std::size_t get_stringvar_list(Sequence< std::pair< std::string, std::string >, Allocator > &svlist) const
Definition: exprtk.hpp:18204
symbol_table()
Definition: exprtk.hpp:17597
std::size_t stringvar_count() const
Definition: exprtk.hpp:17678
details::variable_node< T > variable_t
Definition: exprtk.hpp:17473
vector_holder_ptr get_vector(const std::string &vector_name) const
Definition: exprtk.hpp:17786
vararg_function_ptr get_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:17744
bool remove_function(const std::string &function_name)
Definition: exprtk.hpp:18125
~symbol_table()
Definition: exprtk.hpp:17603
bool is_variable(const std::string &variable_name) const
Definition: exprtk.hpp:18258
Definition: exprtk.hpp:38114
void stop()
Definition: exprtk.hpp:38158
timer()
Definition: exprtk.hpp:38143
double time() const
Definition: exprtk.hpp:38180
unsigned long long int usec_time() const
Definition: exprtk.hpp:38164
void start()
Definition: exprtk.hpp:38152
bool in_use() const
Definition: exprtk.hpp:38187
Definition: exprtk.hpp:4380
type_store & operator[](const std::size_t &index)
Definition: exprtk.hpp:4397
type_store & front()
Definition: exprtk.hpp:4407
parameter_list(std::vector< type_store > &pl)
Definition: exprtk.hpp:4383
const type_store & front() const
Definition: exprtk.hpp:4412
type_store & back()
Definition: exprtk.hpp:4417
std::size_t size() const
Definition: exprtk.hpp:4392
const type_store & back() const
Definition: exprtk.hpp:4422
bool empty() const
Definition: exprtk.hpp:4387
const type_store & operator[](const std::size_t &index) const
Definition: exprtk.hpp:4402
Definition: exprtk.hpp:4275
std::size_t size() const
Definition: exprtk.hpp:4310
vector_view(data_ptr_t data, const std::size_t &size)
Definition: exprtk.hpp:4280
const T & operator[](const std::size_t index) const
Definition: exprtk.hpp:4315
T * data_ptr_t
Definition: exprtk.hpp:4278
void rebase(data_ptr_t data)
Definition: exprtk.hpp:4292
T & operator[](const std::size_t index)
Definition: exprtk.hpp:4320
data_ptr_t data() const
Definition: exprtk.hpp:4305
void set_ref(data_ptr_t *data_ref)
Definition: exprtk.hpp:4325
vector_view(const vector_view< T > &vv)
Definition: exprtk.hpp:4286
#define register_sf4(Op)
#define basic_opr_switch_statements
Definition: exprtk.hpp:29493
#define register_binary_op(Op, BinaryFunctor)
#define define_sfop4(NN, OP0, OP1)
#define case_stmt(N)
Definition: exprtk.hpp:28080
#define base_opr_case(N)
#define exprtk_register_function(FunctionName, FunctionType)
#define exprtk_disable_fallthrough_end
Definition: exprtk.hpp:82
#define exprtk_register_complex_type_tag(T)
Definition: exprtk.hpp:788
#define case_stmt1(op)
#define exprtk_process_digit
#define register_unary_op(Op, UnaryFunctor)
#define exprtk_define_unary_function(FunctionName)
Definition: exprtk.hpp:1575
#define else_stmt(N)
#define register_synthezier(S)
#define exprtk_define_process(Type)
Definition: exprtk.hpp:17117
#define exprtk_crtype(Type)
Definition: exprtk.hpp:14209
#define case_stmt0(op)
#define parse_digit_1(d)
#define poly_rtrn(NN)
Definition: exprtk.hpp:37061
#define parse_digit_2(d)
#define igeneric_function_empty_body(N)
Definition: exprtk.hpp:16860
#define register_sf4ext(Op)
#define vector_ops
#define exprtk_register_int_type_tag(T)
Definition: exprtk.hpp:792
#define def_fp_retval(N)
Definition: exprtk.hpp:37600
#define exprtk_disable_fallthrough_begin
Definition: exprtk.hpp:81
#define extended_opr_switch_statements
#define exprtk_debug(params)
Definition: exprtk.hpp:65
#define exprtk_error_location
Definition: exprtk.hpp:68
#define string_opr_switch_statements
Definition: exprtk.hpp:35355
#define register_op(Symbol, Type, Args)
#define exprtk_define_freefunction(NN)
Definition: exprtk.hpp:17970
#define unary_opr_switch_statements
Definition: exprtk.hpp:28220
#define register_sf3_extid(Id, Op)
#define token_inserter_empty_body
Definition: exprtk.hpp:3141
#define register_sf3(Op)
#define exprtk_loop(N)
#define batch_eqineq_logic_case
#define true
Definition: msvc_stdbool.h:18
#define false
Definition: msvc_stdbool.h:19
char bool
Definition: msvc_stdbool.h:17
not_this_one begin(...)
bool cmp(const ESmry &esmr, const ERsm &ersm)
std::function< double(double, double)> function
Definition: Operate.hpp:28
std::vector< typename std::result_of< F(typename C::const_iterator::value_type &) >::type > map(F f, const C &src)
Definition: Functional.hpp:84
std::vector< double > init(const std::string &kewyord, const TableManager &tables, const Phases &phases, const std::vector< double > &cell_depth, const std::vector< int > &num, const std::vector< int > &endnum)
constexpr const double second
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:104
bool operator<(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
@ end
Definition: ActionValue.hpp:20
const unsigned int global_loop_batch_size
Definition: exprtk.hpp:4726
static const double e
Definition: exprtk.hpp:758
static const double pi
Definition: exprtk.hpp:759
static const double log2
Definition: exprtk.hpp:766
static const double _180_pi
Definition: exprtk.hpp:765
static const double pi_180
Definition: exprtk.hpp:762
static const double _1_pi
Definition: exprtk.hpp:763
static const double _2_pi
Definition: exprtk.hpp:764
static const double pi_2
Definition: exprtk.hpp:760
static const double sqrt2
Definition: exprtk.hpp:767
static const double pi_4
Definition: exprtk.hpp:761
T floor_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1302
bool is_false_impl(const T v)
Definition: exprtk.hpp:858
T xor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1163
T ceil_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1298
T shr_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1069
T atan2_impl(const T, const T, int_type_tag)
Definition: exprtk.hpp:1063
T tanh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1312
T acosh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1293
T nor_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1145
bool is_integer_impl(const T &v, real_type_tag)
Definition: exprtk.hpp:1358
T const_pi_impl(real_type_tag)
Definition: exprtk.hpp:1324
T asin_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1294
T log10_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1304
T hypot_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1051
T r2d_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1316
T shl_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1081
T logn_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:962
exprtk_define_erf(float,::erff) exprtk_define_erf(double
T shl_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1087
T sqrt_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1310
T xnor_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1169
T asinh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1295
T nand_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1127
T const_e_impl(real_type_tag)
Definition: exprtk.hpp:1325
T d2r_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1317
T neg_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1306
T pow_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:956
T process_impl(const operator_type operation, const T arg)
Definition: exprtk.hpp:4971
T root_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1001
T and_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1109
T pos_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1307
T log_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1303
real_type_tag
Definition: exprtk.hpp:835
T csc_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1315
_int64_t to_int64_impl(const T v, real_type_tag)
Definition: exprtk.hpp:846
T log2_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1305
T cot_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1313
exprtk_define_erfc(float,::erfcf) exprtk_define_erfc(double
exprtk_register_real_type_tag(double) exprtk_register_real_type_tag(long double) exprtk_register_real_type_tag(float) exprtk_register_complex_type_tag(double) exprtk_register_complex_type_tag(long double) exprtk_register_complex_type_tag(float) exprtk_register_int_type_tag(short) exprtk_register_int_type_tag(int) exprtk_register_int_type_tag(_int64_t) exprtk_register_int_type_tag(unsigned short) exprtk_register_int_type_tag(unsigned int) exprtk_register_int_type_tag(_uint64_t) template< typename T > struct epsilon_type
Definition: exprtk.hpp:796
T or_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1133
T cos_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1299
T sinh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1309
T nequal_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:932
exprtk_define_epsilon_type(float, 0.000001f) exprtk_define_epsilon_type(double
T roundn_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1027
bool is_integer_impl(const T &, int_type_tag)
Definition: exprtk.hpp:1364
T modulus_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:944
T sec_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1314
T atan2_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1057
T pow_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:950
T modulus_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:938
T log1p_impl(const T v, real_type_tag)
Definition: exprtk.hpp:974
T trunc_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1322
T frac_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1321
T hypot_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1045
T sinc_impl(T v, real_type_tag)
Definition: exprtk.hpp:1278
T nand_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1121
T min_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:870
T erf_impl(T v, int_type_tag)
Definition: exprtk.hpp:1231
T equal_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:882
T ncdf_impl(T v, real_type_tag)
Definition: exprtk.hpp:1263
T nequal_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:917
T g2d_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1319
T max_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:876
T exp_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1301
T erfc_impl(T v, int_type_tag)
Definition: exprtk.hpp:1257
bool is_true_impl(const T v)
Definition: exprtk.hpp:852
T shr_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1075
T logn_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:968
T sin_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1308
T roundn_impl(const T v0, const T, int_type_tag)
Definition: exprtk.hpp:1039
T round_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1021
T abs_impl(const T v, real_type_tag)
Definition: exprtk.hpp:864
T sgn_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1093
T d2g_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1318
T acos_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1292
T tan_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1311
T nor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1151
T xor_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:1157
T expm1_impl(const T v, real_type_tag)
Definition: exprtk.hpp:901
int to_int32_impl(const T v, real_type_tag)
Definition: exprtk.hpp:840
T and_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1115
T root_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1015
T atanh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1297
T xnor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1181
T atan_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1296
T notl_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1320
T or_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1139
T cosh_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1300
T equal_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:895
T logn(const T v0, const T v1)
Definition: exprtk.hpp:1442
T process(const operator_type operation, const T arg0, const T arg1)
Definition: exprtk.hpp:5107
int to_int32(const T v)
Definition: exprtk.hpp:1379
T process(const operator_type operation, const T arg)
Definition: exprtk.hpp:5101
T xor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1519
T hypot(const T v0, const T v1)
Definition: exprtk.hpp:1463
T pow(const T v0, const T v1)
Definition: exprtk.hpp:1435
T nor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1512
bool is_nan(const T v)
Definition: exprtk.hpp:1393
T root(const T v0, const T v1)
Definition: exprtk.hpp:1449
bool is_integer(const T v)
Definition: exprtk.hpp:1533
T nand_opr(const T v0, const T v1)
Definition: exprtk.hpp:1498
T min(const T v0, const T v1)
Definition: exprtk.hpp:1400
T nequal(const T v0, const T v1)
Definition: exprtk.hpp:1421
T or_opr(const T v0, const T v1)
Definition: exprtk.hpp:1505
T roundn(const T v0, const T v1)
Definition: exprtk.hpp:1456
T atan2(const T v0, const T v1)
Definition: exprtk.hpp:1470
T equal(const T v0, const T v1)
Definition: exprtk.hpp:1414
T shl(const T v0, const T v1)
Definition: exprtk.hpp:1484
T and_opr(const T v0, const T v1)
Definition: exprtk.hpp:1491
T xnor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1526
_int64_t to_int64(const T v)
Definition: exprtk.hpp:1386
T modulus(const T v0, const T v1)
Definition: exprtk.hpp:1428
T max(const T v0, const T v1)
Definition: exprtk.hpp:1407
T shr(const T v0, const T v1)
Definition: exprtk.hpp:1477
bool is_string_ccondition_node(const expression_node< T > *node)
Definition: exprtk.hpp:16152
bool is_left_bracket(const char_t c)
Definition: exprtk.hpp:135
static bool parse_nan(Iterator &itr, const Iterator end, T &t)
Definition: exprtk.hpp:1762
bool is_true(const double v)
Definition: exprtk.hpp:5203
static const double pow10[]
Definition: exprtk.hpp:744
bool is_voc_node(const expression_node< T > *node)
Definition: exprtk.hpp:16068
bool string_to_real(Iterator &itr_external, const Iterator end, T &t, numeric::details::real_type_tag)
Definition: exprtk.hpp:1836
bool is_ivector_node(const expression_node< T > *node)
Definition: exprtk.hpp:5309
static const std::string assignment_ops_list[]
Definition: exprtk.hpp:496
bool is_sign(const char_t c)
Definition: exprtk.hpp:150
T compute_pow10(T d, const int exponent)
Definition: exprtk.hpp:1627
bool is_whitespace(const char_t c)
Definition: exprtk.hpp:96
bool is_ivariable_node(const expression_node< T > *node)
Definition: exprtk.hpp:5273
bool imatch(const char_t c1, const char_t c2)
Definition: exprtk.hpp:183
synthesis_node_type_define(const T0 &, const T1 &, e_vov) synthesis_node_type_define(const T0 &
bool is_unary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5249
bool is_invalid(const char_t c)
Definition: exprtk.hpp:155
bool is_false(const expression_node< T > *node)
Definition: exprtk.hpp:5237
bool is_rebasevector_elem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5291
bool is_base_function(const std::string &function_name)
Definition: exprtk.hpp:539
bool is_function(const expression_node< T > *node)
Definition: exprtk.hpp:5363
bool is_t0ot1ot2ot3_node(const expression_node< T > *node)
Definition: exprtk.hpp:16092
long long int _int64_t
Definition: exprtk.hpp:94
void construct_branch_pair(std::pair< expression_node< T > *, bool >(&branch)[N], expression_node< T > *b, const std::size_t &index)
Definition: exprtk.hpp:5990
bool is_reserved_symbol(const std::string &symbol)
Definition: exprtk.hpp:526
static const std::size_t arithmetic_ops_list_size
Definition: exprtk.hpp:494
bool is_operator_char(const char_t c)
Definition: exprtk.hpp:104
bool is_control_struct(const std::string &cntrl_strct)
Definition: exprtk.hpp:552
bool is_bracket(const char_t c)
Definition: exprtk.hpp:145
T axnb(T a, T x, T b)
Definition: exprtk.hpp:9630
static const std::size_t base_function_list_size
Definition: exprtk.hpp:473
bool is_string_assignment_node(const expression_node< T > *node)
Definition: exprtk.hpp:16128
void case_normalise(std::string &s)
Definition: exprtk.hpp:175
bool is_sf4ext_node(const expression_node< T > *n)
Definition: exprtk.hpp:15055
bool is_string_vararg_node(const expression_node< T > *node)
Definition: exprtk.hpp:16158
bool string_to_type_converter_impl_ref(Iterator &itr, const Iterator end, T &result)
Definition: exprtk.hpp:1689
static const std::size_t assignment_ops_list_size
Definition: exprtk.hpp:502
static const std::string arithmetic_ops_list[]
Definition: exprtk.hpp:489
bool is_vov_node(const expression_node< T > *node)
Definition: exprtk.hpp:16056
static const std::string reserved_symbols[]
Definition: exprtk.hpp:441
bool is_uv_node(const expression_node< T > *node)
Definition: exprtk.hpp:16098
exprtk_define_unary_op(abs) exprtk_define_unary_op(acos) exprtk_define_unary_op(acosh) exprtk_define_unary_op(asin) exprtk_define_unary_op(asinh) exprtk_define_unary_op(atan) exprtk_define_unary_op(atanh) exprtk_define_unary_op(ceil) exprtk_define_unary_op(cos) exprtk_define_unary_op(cosh) exprtk_define_unary_op(cot) exprtk_define_unary_op(csc) exprtk_define_unary_op(d2g) exprtk_define_unary_op(d2r) exprtk_define_unary_op(erf) exprtk_define_unary_op(erfc) exprtk_define_unary_op(exp) exprtk_define_unary_op(expm1) exprtk_define_unary_op(floor) exprtk_define_unary_op(frac) exprtk_define_unary_op(g2d) exprtk_define_unary_op(log) exprtk_define_unary_op(log10) exprtk_define_unary_op(log2) exprtk_define_unary_op(log1p) exprtk_define_unary_op(ncdf) exprtk_define_unary_op(neg) exprtk_define_unary_op(notl) exprtk_define_unary_op(pos) exprtk_define_unary_op(r2d) exprtk_define_unary_op(round) exprtk_define_unary_op(sec) exprtk_define_unary_op(sgn) exprtk_define_unary_op(sin) exprtk_define_unary_op(sinc) exprtk_define_unary_op(sinh) exprtk_define_unary_op(sqrt) exprtk_define_unary_op(tan) exprtk_define_unary_op(tanh) exprtk_define_unary_op(trunc) template< typename T > struct opr_base
Definition: exprtk.hpp:12641
bool is_hex_digit(const std::string::value_type digit)
Definition: exprtk.hpp:304
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t/t)") define_sfop3(19
const char_t & back(const std::string &s)
Definition: exprtk.hpp:265
char char_t
Definition: exprtk.hpp:88
bool is_constant_node(const expression_node< T > *node)
Definition: exprtk.hpp:5333
const T1 const T2 const T3
Definition: exprtk.hpp:14424
x y * z
Definition: exprtk.hpp:9663
static const std::string logic_ops_list[]
Definition: exprtk.hpp:475
bool is_valid_sf_symbol(const std::string &symbol)
Definition: exprtk.hpp:250
const T1
Definition: exprtk.hpp:14380
bool is_binary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5261
bool is_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:16104
void dump_ptr(const std::string &, const void *)
Definition: exprtk.hpp:4758
bool is_valid_string_char(const char_t c)
Definition: exprtk.hpp:168
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12955
bool wc_match(const std::string &wild_card, const std::string &str)
Definition: exprtk.hpp:656
bool is_const_string_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:16122
void load_operations_map(std::multimap< std::string, details::base_operation_t, details::ilesscompare > &m)
Definition: exprtk.hpp:16580
static const std::string reserved_words[]
Definition: exprtk.hpp:430
bool is_boc_node(const expression_node< T > *node)
Definition: exprtk.hpp:16080
bool is_string_condition_node(const expression_node< T > *node)
Definition: exprtk.hpp:16146
bool valid_exponent(const int exponent, numeric::details::real_type_tag)
Definition: exprtk.hpp:1829
void disable_type_checking(Parser &p)
Definition: exprtk.hpp:19035
static const std::string inequality_ops_list[]
Definition: exprtk.hpp:504
static const std::size_t cntrl_struct_list_size
Definition: exprtk.hpp:487
bool is_string_function_node(const expression_node< T > *node)
Definition: exprtk.hpp:16140
bool is_letter_or_digit(const char_t c)
Definition: exprtk.hpp:130
void free_all_nodes(NodeAllocator &node_allocator, Sequence< expression_node< T > *, Allocator > &b)
Definition: exprtk.hpp:5532
bool is_cov_node(const expression_node< T > *node)
Definition: exprtk.hpp:16062
bool is_const_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:16116
define_sfop3(00,(x+y)/z,"(t+t)/t") define_sfop3(01
bool is_false(const std::pair< expression_node< T > *, bool > &node)
Definition: exprtk.hpp:5243
bool is_genricstring_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:16164
uchar_t const * uchar_cptr
Definition: exprtk.hpp:91
bool is_null_node(const expression_node< T > *node)
Definition: exprtk.hpp:5339
bool sequence_match(const std::string &pattern, const std::string &str, std::size_t &diff_index, char_t &diff_value)
Definition: exprtk.hpp:674
T value(const T &t)
Definition: exprtk.hpp:12973
static const std::size_t inequality_ops_list_size
Definition: exprtk.hpp:511
std::string to_str(int i)
Definition: exprtk.hpp:270
bool all_nodes_valid(expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5396
operator_type
Definition: exprtk.hpp:4607
@ e_sf4ext08
Definition: exprtk.hpp:4662
@ e_sf07
Definition: exprtk.hpp:4635
@ e_sf4ext14
Definition: exprtk.hpp:4663
@ e_sf16
Definition: exprtk.hpp:4638
@ e_tan
Definition: exprtk.hpp:4623
@ e_sf4ext25
Definition: exprtk.hpp:4666
@ e_sf71
Definition: exprtk.hpp:4651
@ e_sf47
Definition: exprtk.hpp:4645
@ e_root
Definition: exprtk.hpp:4622
@ e_sf4ext38
Definition: exprtk.hpp:4669
@ e_sf26
Definition: exprtk.hpp:4640
@ e_asin
Definition: exprtk.hpp:4617
@ e_sf4ext57
Definition: exprtk.hpp:4674
@ e_sf30
Definition: exprtk.hpp:4641
@ e_sf4ext49
Definition: exprtk.hpp:4672
@ e_sf94
Definition: exprtk.hpp:4657
@ e_sf56
Definition: exprtk.hpp:4648
@ e_sf09
Definition: exprtk.hpp:4636
@ e_sf62
Definition: exprtk.hpp:4649
@ e_eq
Definition: exprtk.hpp:4612
@ e_sffinal
Definition: exprtk.hpp:4659
@ e_sinc
Definition: exprtk.hpp:4622
@ e_sf4ext47
Definition: exprtk.hpp:4671
@ e_sf59
Definition: exprtk.hpp:4648
@ e_expm1
Definition: exprtk.hpp:4619
@ e_sf38
Definition: exprtk.hpp:4643
@ e_like
Definition: exprtk.hpp:4630
@ e_equal
Definition: exprtk.hpp:4612
@ e_sf55
Definition: exprtk.hpp:4647
@ e_sf92
Definition: exprtk.hpp:4657
@ e_cosh
Definition: exprtk.hpp:4618
@ e_sf4ext17
Definition: exprtk.hpp:4664
@ e_sqrt
Definition: exprtk.hpp:4622
@ e_sec
Definition: exprtk.hpp:4623
@ e_sf4ext06
Definition: exprtk.hpp:4661
@ e_sf50
Definition: exprtk.hpp:4646
@ e_acosh
Definition: exprtk.hpp:4617
@ e_or
Definition: exprtk.hpp:4614
@ e_sf49
Definition: exprtk.hpp:4646
@ e_sf90
Definition: exprtk.hpp:4656
@ e_sf53
Definition: exprtk.hpp:4647
@ e_sf63
Definition: exprtk.hpp:4649
@ e_add
Definition: exprtk.hpp:4608
@ e_cos
Definition: exprtk.hpp:4618
@ e_sf37
Definition: exprtk.hpp:4643
@ e_nand
Definition: exprtk.hpp:4613
@ e_sf43
Definition: exprtk.hpp:4644
@ e_sf34
Definition: exprtk.hpp:4642
@ e_divass
Definition: exprtk.hpp:4629
@ e_sf91
Definition: exprtk.hpp:4656
@ e_sf08
Definition: exprtk.hpp:4636
@ e_sf35
Definition: exprtk.hpp:4642
@ e_sf72
Definition: exprtk.hpp:4652
@ e_sf25
Definition: exprtk.hpp:4640
@ e_sf18
Definition: exprtk.hpp:4638
@ e_sf27
Definition: exprtk.hpp:4640
@ e_sf4ext52
Definition: exprtk.hpp:4673
@ e_smulti
Definition: exprtk.hpp:4630
@ e_multi
Definition: exprtk.hpp:4630
@ e_sf01
Definition: exprtk.hpp:4634
@ e_sf11
Definition: exprtk.hpp:4636
@ e_sf98
Definition: exprtk.hpp:4658
@ e_sf44
Definition: exprtk.hpp:4645
@ e_sf4ext05
Definition: exprtk.hpp:4661
@ e_sf88
Definition: exprtk.hpp:4656
@ e_mulass
Definition: exprtk.hpp:4629
@ e_sf4ext10
Definition: exprtk.hpp:4662
@ e_sf4ext15
Definition: exprtk.hpp:4663
@ e_sf4ext36
Definition: exprtk.hpp:4669
@ e_sf61
Definition: exprtk.hpp:4649
@ e_addass
Definition: exprtk.hpp:4628
@ e_sf19
Definition: exprtk.hpp:4638
@ e_atanh
Definition: exprtk.hpp:4618
@ e_sf78
Definition: exprtk.hpp:4653
@ e_sf20
Definition: exprtk.hpp:4639
@ e_lte
Definition: exprtk.hpp:4611
@ e_lt
Definition: exprtk.hpp:4611
@ e_tanh
Definition: exprtk.hpp:4624
@ e_sf57
Definition: exprtk.hpp:4648
@ e_sf4ext22
Definition: exprtk.hpp:4665
@ e_round
Definition: exprtk.hpp:4621
@ e_clamp
Definition: exprtk.hpp:4624
@ e_sf04
Definition: exprtk.hpp:4635
@ e_sf4ext31
Definition: exprtk.hpp:4667
@ e_logn
Definition: exprtk.hpp:4620
@ e_prod
Definition: exprtk.hpp:4611
@ e_sf36
Definition: exprtk.hpp:4643
@ e_sf4ext16
Definition: exprtk.hpp:4664
@ e_sf42
Definition: exprtk.hpp:4644
@ e_sf4ext32
Definition: exprtk.hpp:4668
@ e_sf73
Definition: exprtk.hpp:4652
@ e_min
Definition: exprtk.hpp:4610
@ e_sf4ext03
Definition: exprtk.hpp:4660
@ e_sf45
Definition: exprtk.hpp:4645
@ e_sf93
Definition: exprtk.hpp:4657
@ e_sf54
Definition: exprtk.hpp:4647
@ e_sf4ext33
Definition: exprtk.hpp:4668
@ e_sf03
Definition: exprtk.hpp:4634
@ e_trunc
Definition: exprtk.hpp:4628
@ e_sf4ext48
Definition: exprtk.hpp:4672
@ e_ceil
Definition: exprtk.hpp:4618
@ e_sf4ext01
Definition: exprtk.hpp:4660
@ e_notl
Definition: exprtk.hpp:4626
@ e_avg
Definition: exprtk.hpp:4610
@ e_erfc
Definition: exprtk.hpp:4627
@ e_sgn
Definition: exprtk.hpp:4625
@ e_sf4ext04
Definition: exprtk.hpp:4661
@ e_sf29
Definition: exprtk.hpp:4641
@ e_sf4ext53
Definition: exprtk.hpp:4673
@ e_sf66
Definition: exprtk.hpp:4650
@ e_sf4ext58
Definition: exprtk.hpp:4674
@ e_sf4ext40
Definition: exprtk.hpp:4670
@ e_floor
Definition: exprtk.hpp:4619
@ e_asinh
Definition: exprtk.hpp:4617
@ e_sf10
Definition: exprtk.hpp:4636
@ e_mul
Definition: exprtk.hpp:4609
@ e_acos
Definition: exprtk.hpp:4616
@ e_sf4ext20
Definition: exprtk.hpp:4665
@ e_sf79
Definition: exprtk.hpp:4653
@ e_subass
Definition: exprtk.hpp:4628
@ e_sf41
Definition: exprtk.hpp:4644
@ e_mor
Definition: exprtk.hpp:4615
@ e_sf17
Definition: exprtk.hpp:4638
@ e_nor
Definition: exprtk.hpp:4614
@ e_atan
Definition: exprtk.hpp:4617
@ e_hypot
Definition: exprtk.hpp:4626
@ e_sf46
Definition: exprtk.hpp:4645
@ e_gt
Definition: exprtk.hpp:4613
@ e_sf22
Definition: exprtk.hpp:4639
@ e_pos
Definition: exprtk.hpp:4621
@ e_sf4ext27
Definition: exprtk.hpp:4666
@ e_inrange
Definition: exprtk.hpp:4625
@ e_sin
Definition: exprtk.hpp:4622
@ e_sf21
Definition: exprtk.hpp:4639
@ e_sf06
Definition: exprtk.hpp:4635
@ e_sf33
Definition: exprtk.hpp:4642
@ e_xor
Definition: exprtk.hpp:4614
@ e_sum
Definition: exprtk.hpp:4611
@ e_sf4ext11
Definition: exprtk.hpp:4662
@ e_sf4ext28
Definition: exprtk.hpp:4667
@ e_sf4ext60
Definition: exprtk.hpp:4675
@ e_exp
Definition: exprtk.hpp:4619
@ e_log
Definition: exprtk.hpp:4619
@ e_sf96
Definition: exprtk.hpp:4658
@ e_sf4ext29
Definition: exprtk.hpp:4667
@ e_sf51
Definition: exprtk.hpp:4646
@ e_sf12
Definition: exprtk.hpp:4637
@ e_xnor
Definition: exprtk.hpp:4614
@ e_sf4ext37
Definition: exprtk.hpp:4669
@ e_sf97
Definition: exprtk.hpp:4658
@ e_sf83
Definition: exprtk.hpp:4654
@ e_roundn
Definition: exprtk.hpp:4621
@ e_sf67
Definition: exprtk.hpp:4650
@ e_sf4ext45
Definition: exprtk.hpp:4671
@ e_sf39
Definition: exprtk.hpp:4643
@ e_sf80
Definition: exprtk.hpp:4654
@ e_sf68
Definition: exprtk.hpp:4651
@ e_sf87
Definition: exprtk.hpp:4655
@ e_sf4ext35
Definition: exprtk.hpp:4668
@ e_sf4ext50
Definition: exprtk.hpp:4672
@ e_default
Definition: exprtk.hpp:4608
@ e_ilike
Definition: exprtk.hpp:4630
@ e_sf40
Definition: exprtk.hpp:4644
@ e_sf4ext59
Definition: exprtk.hpp:4674
@ e_sf05
Definition: exprtk.hpp:4635
@ e_sf4ext00
Definition: exprtk.hpp:4660
@ e_nequal
Definition: exprtk.hpp:4612
@ e_sf58
Definition: exprtk.hpp:4648
@ e_sf77
Definition: exprtk.hpp:4653
@ e_scor
Definition: exprtk.hpp:4615
@ e_assign
Definition: exprtk.hpp:4628
@ e_sf4ext46
Definition: exprtk.hpp:4671
@ e_sf4ext54
Definition: exprtk.hpp:4673
@ e_sf48
Definition: exprtk.hpp:4646
@ e_mand
Definition: exprtk.hpp:4615
@ e_null
Definition: exprtk.hpp:4608
@ e_sf13
Definition: exprtk.hpp:4637
@ e_sf4ext13
Definition: exprtk.hpp:4663
@ e_abs
Definition: exprtk.hpp:4616
@ e_sf4ext12
Definition: exprtk.hpp:4663
@ e_sf85
Definition: exprtk.hpp:4655
@ e_sf4ext02
Definition: exprtk.hpp:4660
@ e_shl
Definition: exprtk.hpp:4616
@ e_sf32
Definition: exprtk.hpp:4642
@ e_scand
Definition: exprtk.hpp:4615
@ e_atan2
Definition: exprtk.hpp:4610
@ e_d2g
Definition: exprtk.hpp:4626
@ e_sf76
Definition: exprtk.hpp:4653
@ e_sf02
Definition: exprtk.hpp:4634
@ e_sf4ext51
Definition: exprtk.hpp:4672
@ e_sf4ext41
Definition: exprtk.hpp:4670
@ e_pow
Definition: exprtk.hpp:4609
@ e_sf4ext61
Definition: exprtk.hpp:4675
@ e_ne
Definition: exprtk.hpp:4612
@ e_modass
Definition: exprtk.hpp:4629
@ e_sf4ext19
Definition: exprtk.hpp:4664
@ e_sf84
Definition: exprtk.hpp:4655
@ e_iclamp
Definition: exprtk.hpp:4624
@ e_sf52
Definition: exprtk.hpp:4647
@ e_in
Definition: exprtk.hpp:4629
@ e_sf69
Definition: exprtk.hpp:4651
@ e_erf
Definition: exprtk.hpp:4627
@ e_sf75
Definition: exprtk.hpp:4652
@ e_ncdf
Definition: exprtk.hpp:4627
@ e_sf65
Definition: exprtk.hpp:4650
@ e_log1p
Definition: exprtk.hpp:4620
@ e_sf14
Definition: exprtk.hpp:4637
@ e_sf4ext43
Definition: exprtk.hpp:4670
@ e_sf4ext34
Definition: exprtk.hpp:4668
@ e_and
Definition: exprtk.hpp:4613
@ e_sf95
Definition: exprtk.hpp:4657
@ e_sf4ext23
Definition: exprtk.hpp:4665
@ e_sf4ext44
Definition: exprtk.hpp:4671
@ e_sf70
Definition: exprtk.hpp:4651
@ e_gte
Definition: exprtk.hpp:4613
@ e_cot
Definition: exprtk.hpp:4624
@ e_log10
Definition: exprtk.hpp:4620
@ e_div
Definition: exprtk.hpp:4609
@ e_mod
Definition: exprtk.hpp:4609
@ e_sf4ext26
Definition: exprtk.hpp:4666
@ e_sf4ext56
Definition: exprtk.hpp:4674
@ e_sf28
Definition: exprtk.hpp:4641
@ e_sf00
Definition: exprtk.hpp:4634
@ e_r2d
Definition: exprtk.hpp:4625
@ e_g2d
Definition: exprtk.hpp:4626
@ e_sf4ext07
Definition: exprtk.hpp:4661
@ e_sf4ext21
Definition: exprtk.hpp:4665
@ e_sf74
Definition: exprtk.hpp:4652
@ e_sf64
Definition: exprtk.hpp:4650
@ e_sf4ext24
Definition: exprtk.hpp:4666
@ e_sf4ext42
Definition: exprtk.hpp:4670
@ e_sf15
Definition: exprtk.hpp:4637
@ e_sf89
Definition: exprtk.hpp:4656
@ e_sf99
Definition: exprtk.hpp:4658
@ e_sf86
Definition: exprtk.hpp:4655
@ e_d2r
Definition: exprtk.hpp:4625
@ e_sf4ext39
Definition: exprtk.hpp:4669
@ e_swap
Definition: exprtk.hpp:4631
@ e_sf4ext55
Definition: exprtk.hpp:4673
@ e_sf31
Definition: exprtk.hpp:4641
@ e_sinh
Definition: exprtk.hpp:4623
@ e_sf4ext30
Definition: exprtk.hpp:4667
@ e_neg
Definition: exprtk.hpp:4621
@ e_shr
Definition: exprtk.hpp:4616
@ e_sub
Definition: exprtk.hpp:4608
@ e_sf4ext18
Definition: exprtk.hpp:4664
@ e_frac
Definition: exprtk.hpp:4627
@ e_sf60
Definition: exprtk.hpp:4649
@ e_sf24
Definition: exprtk.hpp:4640
@ e_log2
Definition: exprtk.hpp:4620
@ e_sf23
Definition: exprtk.hpp:4639
@ e_sf82
Definition: exprtk.hpp:4654
@ e_max
Definition: exprtk.hpp:4610
@ e_sf4ext09
Definition: exprtk.hpp:4662
@ e_csc
Definition: exprtk.hpp:4623
@ e_sf81
Definition: exprtk.hpp:4654
bool parse_hex(Iterator &itr, Iterator end, std::string::value_type &result)
Definition: exprtk.hpp:320
unsigned long long int _uint64_t
Definition: exprtk.hpp:93
bool is_variable_node(const expression_node< T > *node)
Definition: exprtk.hpp:5267
bool is_vector_node(const expression_node< T > *node)
Definition: exprtk.hpp:5303
bool all_nodes_variables(expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5420
bool is_negate_node(const expression_node< T > *node)
Definition: exprtk.hpp:5377
bool is_swap_node(const expression_node< T > *node)
Definition: exprtk.hpp:5357
void destroy_node(expression_node< T > *&node)
Definition: exprtk.hpp:5555
bool is_string_concat_node(const expression_node< T > *node)
Definition: exprtk.hpp:16134
bool is_reserved_word(const std::string &symbol)
Definition: exprtk.hpp:513
bool is_letter(const char_t c)
Definition: exprtk.hpp:119
bool is_vector_elem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5285
bool wc_imatch(const std::string &wild_card, const std::string &str)
Definition: exprtk.hpp:665
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t+t)") define_sfop3(16
bool is_return_node(const expression_node< T > *node)
Definition: exprtk.hpp:5369
const e_voc T1 e_none const e_none T1 e_none T0
Definition: exprtk.hpp:14390
static const std::size_t reserved_words_size
Definition: exprtk.hpp:439
static const std::string cntrl_struct_list[]
Definition: exprtk.hpp:482
bool is_cob_node(const expression_node< T > *node)
Definition: exprtk.hpp:16074
unsigned char uchar_t
Definition: exprtk.hpp:87
bool is_generally_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:16170
static const std::string base_function_list[]
Definition: exprtk.hpp:460
uchar_t hex_to_bin(uchar_t h)
Definition: exprtk.hpp:311
bool is_digit(const char_t c)
Definition: exprtk.hpp:125
uchar_t * uchar_ptr
Definition: exprtk.hpp:89
bool is_rebasevector_celem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5297
static const std::size_t reserved_symbols_size
Definition: exprtk.hpp:458
bool match_impl(const Iterator pattern_begin, const Iterator pattern_end, const Iterator data_begin, const Iterator data_end, const typename std::iterator_traits< Iterator >::value_type &zero_or_more, const typename std::iterator_traits< Iterator >::value_type &zero_or_one)
Definition: exprtk.hpp:595
bool is_string_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:16110
void free_node(NodeAllocator &, expression_node< T > *&node)
Definition: exprtk.hpp:5543
bool is_continue_node(const expression_node< T > *node)
Definition: exprtk.hpp:5351
bool is_logic_opr(const std::string &lgc_opr)
Definition: exprtk.hpp:565
const T1 const T2
Definition: exprtk.hpp:14402
T axn(T a, T x)
Definition: exprtk.hpp:9623
bool all_nodes_valid(const Sequence< expression_node< T > *, Allocator > &b)
Definition: exprtk.hpp:5409
char_t const * char_cptr
Definition: exprtk.hpp:92
static const std::size_t pow10_size
Definition: exprtk.hpp:752
const char_t & front(const std::string &s)
Definition: exprtk.hpp:260
char_t * char_ptr
Definition: exprtk.hpp:90
void free_all_nodes(NodeAllocator &node_allocator, expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5520
bool is_sf3ext_node(const expression_node< T > *n)
Definition: exprtk.hpp:14870
static bool parse_inf(Iterator &itr, const Iterator end, T &t, bool negative)
Definition: exprtk.hpp:1795
bool branch_deletable(expression_node< T > *node)
Definition: exprtk.hpp:5388
bool cleanup_escapes(std::string &s)
Definition: exprtk.hpp:343
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y/z)
static const std::size_t logic_ops_list_size
Definition: exprtk.hpp:480
bool is_break_node(const expression_node< T > *node)
Definition: exprtk.hpp:5345
bool all_nodes_variables(Sequence< expression_node< T > *, Allocator > &b)
Definition: exprtk.hpp:5436
bool is_right_bracket(const char_t c)
Definition: exprtk.hpp:140
void init_branches(std::pair< expression_node< T > *, bool >(&branch)[N], expression_node< T > *b0, expression_node< T > *b1=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b2=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b3=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b4=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b5=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b6=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b7=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b8=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b9=reinterpret_cast< expression_node< T > * >(0))
Definition: exprtk.hpp:6010
bool is_neg_unary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5255
bool is_t0ot1ot2_node(const expression_node< T > *node)
Definition: exprtk.hpp:16086
static const char * library
Definition: exprtk.hpp:40015
static const char * version
Definition: exprtk.hpp:40016
static const char * date
Definition: exprtk.hpp:40020
static std::string data()
Definition: exprtk.hpp:40022
void dump(const lexer::generator &generator)
Definition: exprtk.hpp:3281
error_mode
Definition: exprtk.hpp:18910
@ e_helper
Definition: exprtk.hpp:18917
@ e_lexer
Definition: exprtk.hpp:18916
@ e_parser
Definition: exprtk.hpp:18918
@ e_symtab
Definition: exprtk.hpp:18915
@ e_token
Definition: exprtk.hpp:18913
@ e_numeric
Definition: exprtk.hpp:18914
@ e_unknown
Definition: exprtk.hpp:18911
@ e_syntax
Definition: exprtk.hpp:18912
void dump_error(const type &error)
Definition: exprtk.hpp:19023
bool update_error(type &error, const std::string &expression)
Definition: exprtk.hpp:18981
type make_error(const error_mode mode, const lexer::token &tk, const std::string &diagnostic="", const std::string &src_location="")
Definition: exprtk.hpp:18951
std::string to_str(error_mode mode)
Definition: exprtk.hpp:18965
void print_type(const std::string &fmt, const T v, exprtk::details::numeric::details::real_type_tag)
Definition: exprtk.hpp:38214
file_mode
Definition: exprtk.hpp:38359
@ e_write
Definition: exprtk.hpp:38362
@ e_error
Definition: exprtk.hpp:38360
@ e_rdwrt
Definition: exprtk.hpp:38363
@ e_read
Definition: exprtk.hpp:38361
void perform_check()
Definition: exprtk.hpp:38562
file_descriptor * make_handle(T v)
Definition: exprtk.hpp:38551
void kahan_sum(T &sum, T &error, const T v)
Definition: exprtk.hpp:38901
bool invalid_range(const Vector &v, const std::size_t r0, const std::size_t r1)
Definition: exprtk.hpp:38854
Definition: exprtk.hpp:61
void enable_zero_parameters(FunctionType &func)
Definition: exprtk.hpp:16682
bool collect_variables(const std::string &expression, Sequence< std::string, Allocator > &symbol_list)
Definition: exprtk.hpp:36467
void set_max_num_args(FunctionType &func, const std::size_t &num_args)
Definition: exprtk.hpp:16720
bool is_valid(const expression< T > &expr)
Definition: exprtk.hpp:18902
void disable_has_side_effects(FunctionType &func)
Definition: exprtk.hpp:16705
vector_view< T > make_vector_view(T *data, const std::size_t size, const std::size_t offset=0)
Definition: exprtk.hpp:4338
void disable_zero_parameters(FunctionType &func)
Definition: exprtk.hpp:16693
T third_derivative(const expression< T > &e, T &x, const T &h=T(0.0001))
Definition: exprtk.hpp:36681
bool collect_functions(const std::string &expression, Sequence< std::string, Allocator > &symbol_list)
Definition: exprtk.hpp:36528
loop_runtime_check * loop_runtime_check_ptr
Definition: exprtk.hpp:2065
bool compute(const std::string &expression_string, T &result)
Definition: exprtk.hpp:36793
bool pgo_primer()
Definition: exprtk.hpp:37899
T derivative(const expression< T > &e, T &x, const T &h=T(0.00000001))
Definition: exprtk.hpp:36638
T second_derivative(const expression< T > &e, T &x, const T &h=T(0.00001))
Definition: exprtk.hpp:36659
std::string to_str(const StringView &view)
Definition: exprtk.hpp:4537
void set_min_num_args(FunctionType &func, const std::size_t &num_args)
Definition: exprtk.hpp:16711
void enable_has_side_effects(FunctionType &func)
Definition: exprtk.hpp:16699
T integrate(const expression< T > &e, T &x, const T &r0, const T &r1, const std::size_t number_of_intervals=1000000)
Definition: exprtk.hpp:36588
Definition: exprtk.hpp:15074
details::T0oT1< T, T0, T1 > type0
Definition: exprtk.hpp:15075
Definition: exprtk.hpp:14262
static std::string id()
Definition: exprtk.hpp:14272
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:14263
Definition: exprtk.hpp:14283
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:14284
static std::string id()
Definition: exprtk.hpp:14292
Definition: exprtk.hpp:14303
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:14304
static std::string id()
Definition: exprtk.hpp:14313
Definition: exprtk.hpp:14324
static std::string id()
Definition: exprtk.hpp:14334
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:14325
Definition: exprtk.hpp:14345
static std::string id()
Definition: exprtk.hpp:14355
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:14346
Definition: exprtk.hpp:14257
details::functor_t< T > functor_t
Definition: exprtk.hpp:14258
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14259
Definition: exprtk.hpp:15080
details::T0oT1oT2< T, T0, T1, T2, typename T0oT1oT2process< T >::mode0 > type0
Definition: exprtk.hpp:15081
details::T0oT1oT2_sf3< T, T0, T1, T2 > sf3_type
Definition: exprtk.hpp:15083
details::T0oT1oT2< T, T0, T1, T2, typename T0oT1oT2process< T >::mode1 > type1
Definition: exprtk.hpp:15082
details::sf3ext_type_node< T, T0, T1, T2 > sf3_type_node
Definition: exprtk.hpp:15084
Definition: exprtk.hpp:15089
details::T0oT1oT2oT3_sf4< T, T0, T1, T2, T3 > sf4_type
Definition: exprtk.hpp:15095
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode2 > type2
Definition: exprtk.hpp:15092
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode0 > type0
Definition: exprtk.hpp:15090
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode1 > type1
Definition: exprtk.hpp:15091
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode4 > type4
Definition: exprtk.hpp:15094
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode3 > type3
Definition: exprtk.hpp:15093
Definition: exprtk.hpp:14219
static std::string id()
Definition: exprtk.hpp:14227
static T process(const T &t0, const T &t1, const T &t2, const bfunc_t bf0, const bfunc_t bf1)
Definition: exprtk.hpp:14220
Definition: exprtk.hpp:14237
static std::string id()
Definition: exprtk.hpp:14245
static T process(const T &t0, const T &t1, const T &t2, const bfunc_t bf0, const bfunc_t bf1)
Definition: exprtk.hpp:14238
Definition: exprtk.hpp:14214
details::functor_t< T > functor_t
Definition: exprtk.hpp:14215
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:14216
Definition: exprtk.hpp:12697
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12701
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12702
static details::operator_type operation()
Definition: exprtk.hpp:12705
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12703
opr_base< T >::Type Type
Definition: exprtk.hpp:12698
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12699
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12704
Definition: exprtk.hpp:12849
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12853
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12852
static details::operator_type operation()
Definition: exprtk.hpp:12854
opr_base< T >::Type Type
Definition: exprtk.hpp:12850
Definition: exprtk.hpp:8950
static void execute(std::string &s, char_cptr data, const std::size_t size)
Definition: exprtk.hpp:8951
Definition: exprtk.hpp:8944
static void execute(std::string &s, char_cptr data, const std::size_t size)
Definition: exprtk.hpp:8945
Definition: exprtk.hpp:4713
base_operation_t(const operator_type t, const unsigned int &np)
Definition: exprtk.hpp:4714
operator_type type
Definition: exprtk.hpp:4719
unsigned int num_params
Definition: exprtk.hpp:4720
Definition: exprtk.hpp:587
static bool cmp(const char_t c0, const char_t c1)
Definition: exprtk.hpp:588
Definition: exprtk.hpp:36391
parser_t::dependent_entity_collector::symbol_t symbol_t
Definition: exprtk.hpp:36395
Definition: exprtk.hpp:579
static bool cmp(const char_t c0, const char_t c1)
Definition: exprtk.hpp:580
Definition: exprtk.hpp:12736
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12740
static details::operator_type operation()
Definition: exprtk.hpp:12744
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12742
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12738
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12743
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12741
opr_base< T >::Type Type
Definition: exprtk.hpp:12737
Definition: exprtk.hpp:12817
opr_base< T >::Type Type
Definition: exprtk.hpp:12818
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12819
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12821
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12820
static details::operator_type operation()
Definition: exprtk.hpp:12822
Definition: exprtk.hpp:12827
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12832
static details::operator_type operation()
Definition: exprtk.hpp:12833
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12830
opr_base< T >::Type Type
Definition: exprtk.hpp:12828
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12831
static void execute(T_(&v)[1], const branch_t(&b)[1])
Definition: exprtk.hpp:11835
static void execute(T_(&v)[2], const branch_t(&b)[2])
Definition: exprtk.hpp:11825
static void execute(T_(&v)[3], const branch_t(&b)[3])
Definition: exprtk.hpp:11814
static void execute(T_(&v)[4], const branch_t(&b)[4])
Definition: exprtk.hpp:11802
static void execute(T_(&v)[5], const branch_t(&b)[5])
Definition: exprtk.hpp:11789
static void execute(T_(&v)[BranchCount], const branch_t(&b)[BranchCount])
Definition: exprtk.hpp:11777
static T_ execute(ifunction &f, T_(&v)[10])
Definition: exprtk.hpp:11917
static T_ execute(ifunction &f, T_(&v)[11])
Definition: exprtk.hpp:11910
static T_ execute(ifunction &f, T_(&v)[12])
Definition: exprtk.hpp:11903
static T_ execute(ifunction &f, T_(&v)[13])
Definition: exprtk.hpp:11896
static T_ execute(ifunction &f, T_(&v)[14])
Definition: exprtk.hpp:11889
static T_ execute(ifunction &f, T_(&v)[15])
Definition: exprtk.hpp:11882
static T_ execute(ifunction &f, T_(&v)[16])
Definition: exprtk.hpp:11875
static T_ execute(ifunction &f, T_(&v)[17])
Definition: exprtk.hpp:11868
static T_ execute(ifunction &f, T_(&v)[18])
Definition: exprtk.hpp:11861
static T_ execute(ifunction &f, T_(&v)[19])
Definition: exprtk.hpp:11854
static T_ execute(ifunction &f, T_(&v)[1])
Definition: exprtk.hpp:11980
static T_ execute(ifunction &f, T_(&v)[20])
Definition: exprtk.hpp:11847
static T_ execute(ifunction &f, T_(&v)[2])
Definition: exprtk.hpp:11973
static T_ execute(ifunction &f, T_(&v)[3])
Definition: exprtk.hpp:11966
static T_ execute(ifunction &f, T_(&v)[4])
Definition: exprtk.hpp:11959
static T_ execute(ifunction &f, T_(&v)[5])
Definition: exprtk.hpp:11952
static T_ execute(ifunction &f, T_(&v)[6])
Definition: exprtk.hpp:11945
static T_ execute(ifunction &f, T_(&v)[7])
Definition: exprtk.hpp:11938
static T_ execute(ifunction &f, T_(&v)[8])
Definition: exprtk.hpp:11931
static T_ execute(ifunction &f, T_(&v)[9])
Definition: exprtk.hpp:11924
Definition: exprtk.hpp:11842
static T execute(ifunction &, branch_t(&)[ParamCount])
Definition: exprtk.hpp:11842
Definition: exprtk.hpp:2005
const T & Type
Definition: exprtk.hpp:2013
T(* bfunc_t)(Type t0, Type t1)
Definition: exprtk.hpp:2017
T & RefType
Definition: exprtk.hpp:2014
T(* qfunc_t)(Type t0, Type t1, Type t2, Type t3)
Definition: exprtk.hpp:2015
T(* tfunc_t)(Type t0, Type t1, Type t2)
Definition: exprtk.hpp:2016
T(* ufunc_t)(Type t0)
Definition: exprtk.hpp:2018
Definition: exprtk.hpp:12795
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12800
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12798
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12799
opr_base< T >::Type Type
Definition: exprtk.hpp:12796
static details::operator_type operation()
Definition: exprtk.hpp:12801
Definition: exprtk.hpp:12806
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12809
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12811
static details::operator_type operation()
Definition: exprtk.hpp:12812
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12810
opr_base< T >::Type Type
Definition: exprtk.hpp:12807
Definition: exprtk.hpp:207
bool operator()(const std::string &s1, const std::string &s2) const
Definition: exprtk.hpp:208
Definition: exprtk.hpp:12931
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12935
static details::operator_type operation()
Definition: exprtk.hpp:12937
static T process(const T &, const T &)
Definition: exprtk.hpp:12934
opr_base< T >::Type Type
Definition: exprtk.hpp:12932
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12936
Definition: exprtk.hpp:12909
opr_base< T >::Type Type
Definition: exprtk.hpp:12910
static T process(const T &, const T &)
Definition: exprtk.hpp:12912
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12914
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12913
static details::operator_type operation()
Definition: exprtk.hpp:12915
Definition: exprtk.hpp:12942
opr_base< T >::Type Type
Definition: exprtk.hpp:12943
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12950
static details::operator_type operation()
Definition: exprtk.hpp:12951
static T process(const T &t0, const T &t1, const T &t2)
Definition: exprtk.hpp:12945
static T process(const std::string &t0, const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12946
Definition: exprtk.hpp:14197
@ result
Definition: exprtk.hpp:14197
Definition: exprtk.hpp:14195
@ result
Definition: exprtk.hpp:14195
Definition: exprtk.hpp:14199
@ result
Definition: exprtk.hpp:14199
Definition: exprtk.hpp:12920
static details::operator_type operation()
Definition: exprtk.hpp:12926
static T process(const T &, const T &)
Definition: exprtk.hpp:12923
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12925
opr_base< T >::Type Type
Definition: exprtk.hpp:12921
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12924
Definition: exprtk.hpp:6741
loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types)
Definition: exprtk.hpp:6742
bool check() const
Definition: exprtk.hpp:6748
void reset(const _uint64_t=0) const
Definition: exprtk.hpp:6745
Definition: exprtk.hpp:4732
unsigned int batch_size
Definition: exprtk.hpp:4740
int upper_bound
Definition: exprtk.hpp:4742
int remainder
Definition: exprtk.hpp:4741
details(const std::size_t &vsize, const unsigned int loop_batch_size=global_loop_batch_size)
Definition: exprtk.hpp:4733
Definition: exprtk.hpp:12773
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12776
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12778
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12777
static details::operator_type operation()
Definition: exprtk.hpp:12779
opr_base< T >::Type Type
Definition: exprtk.hpp:12774
Definition: exprtk.hpp:12784
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12788
static details::operator_type operation()
Definition: exprtk.hpp:12790
opr_base< T >::Type Type
Definition: exprtk.hpp:12785
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12787
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12789
Definition: exprtk.hpp:12749
opr_base< T >::Type Type
Definition: exprtk.hpp:12750
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12753
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12751
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12755
static details::operator_type operation()
Definition: exprtk.hpp:12756
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12754
Definition: exprtk.hpp:12710
opr_base< T >::Type Type
Definition: exprtk.hpp:12711
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12712
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12717
static details::operator_type operation()
Definition: exprtk.hpp:12718
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12716
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12715
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12714
Definition: exprtk.hpp:12859
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12862
static details::operator_type operation()
Definition: exprtk.hpp:12864
opr_base< T >::Type Type
Definition: exprtk.hpp:12860
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12863
Definition: exprtk.hpp:12838
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12843
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12841
opr_base< T >::Type Type
Definition: exprtk.hpp:12839
static details::operator_type operation()
Definition: exprtk.hpp:12844
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12842
virtual void collect_nodes(noderef_list_t &)
Definition: exprtk.hpp:5122
std::vector< node_pp_t > noderef_list_t
Definition: exprtk.hpp:5118
Node * node_ptr_t
Definition: exprtk.hpp:5116
virtual ~node_collector_interface()
Definition: exprtk.hpp:5120
Node ** node_pp_t
Definition: exprtk.hpp:5117
Definition: exprtk.hpp:5566
bool depth_set
Definition: exprtk.hpp:5698
std::size_t compute_node_depth(const BranchType &n0, const BranchType &n1, const BranchType &n2) const
Definition: exprtk.hpp:5631
virtual ~node_depth_base()
Definition: exprtk.hpp:5572
void collect(const Sequence< Node *, Allocator > &branch_list, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5751
virtual std::size_t node_depth() const
Definition: exprtk.hpp:5574
std::size_t depth
Definition: exprtk.hpp:5699
void collect(Node *const &node, const bool deletable, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5702
void collect(const Sequence< Node *, AllocatorT > &branch_list, const Sequence< Boolean, AllocatorB > &branch_deletable_list, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5765
std::size_t compute_node_depth(const BranchType &n0, const BranchType &n1, const BranchType &n2, const BranchType &n3) const
Definition: exprtk.hpp:5646
node_depth_base()
Definition: exprtk.hpp:5567
void collect(const Sequence< std::pair< Node *, bool >, Allocator > &branch, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5739
void collect(Node *&node, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5720
std::size_t compute_node_depth(const Node *const &node) const
Definition: exprtk.hpp:5576
std::size_t compute_node_depth(const std::pair< Node *, bool >(&branch)[N]) const
Definition: exprtk.hpp:5599
std::size_t compute_node_depth(const std::pair< Node *, bool > &branch) const
Definition: exprtk.hpp:5587
std::size_t compute_node_depth(const BranchType &n0, const BranchType &n1) const
Definition: exprtk.hpp:5619
void collect(const std::pair< Node *, bool >(&branch)[N], NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5727
void collect(const std::pair< Node *, bool > &branch, NodeSequence &delete_node_list) const
Definition: exprtk.hpp:5713
std::size_t compute_node_depth(const Sequence< Node *, Allocator > &branch_list) const
Definition: exprtk.hpp:5662
std::size_t compute_node_depth(const Sequence< std::pair< Node *, bool >, Allocator > &branch_list) const
Definition: exprtk.hpp:5681
Definition: exprtk.hpp:14369
static const expression_node< T >::node_type result
Definition: exprtk.hpp:14369
Definition: exprtk.hpp:14391
static const expression_node< T >::node_type result
Definition: exprtk.hpp:14391
Definition: exprtk.hpp:14413
static const expression_node< T >::node_type result
Definition: exprtk.hpp:14413
Definition: exprtk.hpp:12879
opr_base< T >::Type Type
Definition: exprtk.hpp:12880
static details::operator_type operation()
Definition: exprtk.hpp:12884
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12882
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12883
unknown_type_tag type
Definition: exprtk.hpp:780
static T result(T)
Definition: exprtk.hpp:1573
static T result(T v)
Definition: exprtk.hpp:1563
static T result(T v)
Definition: exprtk.hpp:1572
static T result(T v)
Definition: exprtk.hpp:1571
static T result(T v)
Definition: exprtk.hpp:1570
static T result(T v)
Definition: exprtk.hpp:1569
static T result(T v)
Definition: exprtk.hpp:1568
static T result(T v)
Definition: exprtk.hpp:1567
static T result(T v)
Definition: exprtk.hpp:1566
static T result(T v)
Definition: exprtk.hpp:1565
static T result(T v)
Definition: exprtk.hpp:1564
Definition: exprtk.hpp:1541
static T result(T v)
Definition: exprtk.hpp:1542
Definition: exprtk.hpp:1371
@ bound_length
Definition: exprtk.hpp:1371
@ max_exp
Definition: exprtk.hpp:1371
@ min_exp
Definition: exprtk.hpp:1371
@ length
Definition: exprtk.hpp:1371
@ size
Definition: exprtk.hpp:1371
Definition: exprtk.hpp:12869
static details::operator_type operation()
Definition: exprtk.hpp:12874
opr_base< T >::Type Type
Definition: exprtk.hpp:12870
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12873
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12872
static std::string result()
Definition: exprtk.hpp:14207
Definition: exprtk.hpp:14204
static std::string result()
Definition: exprtk.hpp:14204
Definition: exprtk.hpp:12761
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12767
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12763
opr_base< T >::Type Type
Definition: exprtk.hpp:12762
static details::operator_type operation()
Definition: exprtk.hpp:12768
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12766
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12765
Definition: exprtk.hpp:7560
strbase_ptr_t str_node
Definition: exprtk.hpp:7576
range_pack< T > range_t
Definition: exprtk.hpp:7561
std::size_t type_size
Definition: exprtk.hpp:7575
string_base_node< T > * strbase_ptr_t
Definition: exprtk.hpp:7562
std::size_t size
Definition: exprtk.hpp:7574
range_t * range
Definition: exprtk.hpp:7572
void * data
Definition: exprtk.hpp:7573
range_data_type()
Definition: exprtk.hpp:7564
Definition: exprtk.hpp:7416
std::size_t const_size() const
Definition: exprtk.hpp:7517
cached_range_t cache
Definition: exprtk.hpp:7531
std::size_t cache_size() const
Definition: exprtk.hpp:7522
range_pack()
Definition: exprtk.hpp:7420
std::pair< bool, expression_node_ptr > n1_e
Definition: exprtk.hpp:7528
expression_node< T > * expression_node_ptr
Definition: exprtk.hpp:7417
std::pair< std::size_t, std::size_t > cached_range_t
Definition: exprtk.hpp:7418
std::pair< bool, std::size_t > n0_c
Definition: exprtk.hpp:7529
std::pair< bool, std::size_t > n1_c
Definition: exprtk.hpp:7530
bool operator()(std::size_t &r0, std::size_t &r1, const std::size_t &size=std::numeric_limits< std::size_t >::max()) const
Definition: exprtk.hpp:7478
void free()
Definition: exprtk.hpp:7437
bool var_range() const
Definition: exprtk.hpp:7472
std::pair< bool, expression_node_ptr > n0_e
Definition: exprtk.hpp:7527
bool const_range() const
Definition: exprtk.hpp:7466
void clear()
Definition: exprtk.hpp:7428
Definition: exprtk.hpp:9638
details::functor_t< T >::Type Type
Definition: exprtk.hpp:9639
functor_t::tfunc_t trinary_functor_t
Definition: exprtk.hpp:9642
functor_t::ufunc_t unary_functor_t
Definition: exprtk.hpp:9644
details::functor_t< T > functor_t
Definition: exprtk.hpp:9640
functor_t::bfunc_t binary_functor_t
Definition: exprtk.hpp:9643
functor_t::qfunc_t quaternary_functor_t
Definition: exprtk.hpp:9641
Definition: exprtk.hpp:12723
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12729
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12728
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12727
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12730
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12725
static details::operator_type operation()
Definition: exprtk.hpp:12731
opr_base< T >::Type Type
Definition: exprtk.hpp:12724
Definition: exprtk.hpp:12980
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13037
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13011
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13023
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13017
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13030
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12986
opr_base< T >::Type Type
Definition: exprtk.hpp:12981
Definition: exprtk.hpp:13114
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13160
opr_base< T >::Type Type
Definition: exprtk.hpp:13115
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13135
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13141
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13147
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13153
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13120
Definition: exprtk.hpp:13312
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13378
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13348
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13318
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13367
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13357
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13341
opr_base< T >::Type Type
Definition: exprtk.hpp:13313
Definition: exprtk.hpp:13241
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13275
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13293
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13287
opr_base< T >::Type Type
Definition: exprtk.hpp:13242
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13247
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13301
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13281
Definition: exprtk.hpp:13170
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13222
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13216
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13204
opr_base< T >::Type Type
Definition: exprtk.hpp:13171
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13230
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13210
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13176
Definition: exprtk.hpp:13392
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13447
opr_base< T >::Type Type
Definition: exprtk.hpp:13393
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13428
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13458
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13437
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13398
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13421
Definition: exprtk.hpp:13047
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13053
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13104
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13078
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13097
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13084
opr_base< T >::Type Type
Definition: exprtk.hpp:13048
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13090
Definition: exprtk.hpp:13472
opr_base< T >::Type Type
Definition: exprtk.hpp:13473
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:13525
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:13510
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:13504
static T process_7(const Sequence &arg_list)
Definition: exprtk.hpp:13555
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:13534
static T process_8(const Sequence &arg_list)
Definition: exprtk.hpp:13567
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:13478
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:13517
static T process_6(const Sequence &arg_list)
Definition: exprtk.hpp:13544
Definition: exprtk.hpp:13582
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13583
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13585
Definition: exprtk.hpp:13784
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13787
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13785
Definition: exprtk.hpp:13821
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13822
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13824
Definition: exprtk.hpp:13797
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13798
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13800
Definition: exprtk.hpp:13683
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13684
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13686
Definition: exprtk.hpp:12899
static details::operator_type operation()
Definition: exprtk.hpp:12904
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12903
opr_base< T >::Type Type
Definition: exprtk.hpp:12900
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12902
Definition: exprtk.hpp:12889
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12893
static details::operator_type operation()
Definition: exprtk.hpp:12894
opr_base< T >::Type Type
Definition: exprtk.hpp:12890
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12892
void * pointer
Definition: exprtk.hpp:18530
std::size_t size
Definition: exprtk.hpp:18532
data_pack(void *ptr, const data_type dt, const std::size_t sz=0)
Definition: exprtk.hpp:18524
data_type type
Definition: exprtk.hpp:18531
data_pack()
Definition: exprtk.hpp:18518
Definition: exprtk.hpp:37153
std::deque< std::string > v_
Definition: exprtk.hpp:37240
std::string name_
Definition: exprtk.hpp:37238
std::string expression_
Definition: exprtk.hpp:37239
Definition: exprtk.hpp:4002
std::vector< lexer::token_inserter * > token_inserter_list
Definition: exprtk.hpp:4150
bool register_inserter(lexer::token_inserter *inserter)
Definition: exprtk.hpp:4045
lexer::token_joiner * error_token_joiner
Definition: exprtk.hpp:4154
std::vector< lexer::token_joiner * > token_joiner_list
Definition: exprtk.hpp:4149
bool run_inserters(lexer::generator &g)
Definition: exprtk.hpp:4103
bool register_scanner(lexer::token_scanner *scanner)
Definition: exprtk.hpp:4003
bool run_joiners(lexer::generator &g)
Definition: exprtk.hpp:4081
std::vector< lexer::token_modifier * > token_modifier_list
Definition: exprtk.hpp:4148
bool register_joiner(lexer::token_joiner *joiner)
Definition: exprtk.hpp:4031
bool register_modifier(lexer::token_modifier *modifier)
Definition: exprtk.hpp:4017
lexer::token_modifier * error_token_modifier
Definition: exprtk.hpp:4153
std::vector< lexer::token_scanner * > token_scanner_list
Definition: exprtk.hpp:4147
bool run_scanners(lexer::generator &g)
Definition: exprtk.hpp:4125
lexer::token_scanner * error_token_scanner
Definition: exprtk.hpp:4152
bool run_modifiers(lexer::generator &g)
Definition: exprtk.hpp:4059
lexer::token_inserter * error_token_inserter
Definition: exprtk.hpp:4155
Definition: exprtk.hpp:2070
std::size_t position
Definition: exprtk.hpp:2238
bool is_error() const
Definition: exprtk.hpp:2225
std::string value
Definition: exprtk.hpp:2237
token & set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2125
token & set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2115
token & set_string(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2135
void clear()
Definition: exprtk.hpp:2095
token()
Definition: exprtk.hpp:2089
token & set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2103
token & set_string(const std::string &s, const std::size_t p)
Definition: exprtk.hpp:2144
token & set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2153
static std::string to_str(token_type t)
Definition: exprtk.hpp:2178
token_type type
Definition: exprtk.hpp:2236
token_type
Definition: exprtk.hpp:2072
@ e_divass
Definition: exprtk.hpp:2077
@ e_rbracket
Definition: exprtk.hpp:2081
@ e_addass
Definition: exprtk.hpp:2076
@ e_lte
Definition: exprtk.hpp:2079
@ e_err_number
Definition: exprtk.hpp:2074
@ e_error
Definition: exprtk.hpp:2073
@ e_rsqrbracket
Definition: exprtk.hpp:2082
@ e_assign
Definition: exprtk.hpp:2076
@ e_swap
Definition: exprtk.hpp:2080
@ e_lsqrbracket
Definition: exprtk.hpp:2082
@ e_pow
Definition: exprtk.hpp:2085
@ e_mulass
Definition: exprtk.hpp:2077
@ e_none
Definition: exprtk.hpp:2073
@ e_div
Definition: exprtk.hpp:2084
@ e_shr
Definition: exprtk.hpp:2078
@ e_comma
Definition: exprtk.hpp:2083
@ e_lt
Definition: exprtk.hpp:2080
@ e_symbol
Definition: exprtk.hpp:2075
@ e_string
Definition: exprtk.hpp:2076
@ e_err_sfunc
Definition: exprtk.hpp:2074
@ e_sub
Definition: exprtk.hpp:2084
@ e_lbracket
Definition: exprtk.hpp:2081
@ e_rcrlbracket
Definition: exprtk.hpp:2082
@ e_eof
Definition: exprtk.hpp:2075
@ e_lcrlbracket
Definition: exprtk.hpp:2083
@ e_err_symbol
Definition: exprtk.hpp:2073
@ e_gte
Definition: exprtk.hpp:2079
@ e_eq
Definition: exprtk.hpp:2081
@ e_shl
Definition: exprtk.hpp:2078
@ e_number
Definition: exprtk.hpp:2075
@ e_modass
Definition: exprtk.hpp:2078
@ e_subass
Definition: exprtk.hpp:2077
@ e_mod
Definition: exprtk.hpp:2085
@ e_ternary
Definition: exprtk.hpp:2086
@ e_err_string
Definition: exprtk.hpp:2074
@ e_gt
Definition: exprtk.hpp:2080
@ e_add
Definition: exprtk.hpp:2083
@ e_mul
Definition: exprtk.hpp:2084
@ e_ne
Definition: exprtk.hpp:2079
@ e_colon
Definition: exprtk.hpp:2085
violation_type violation
Definition: exprtk.hpp:2053
loop_types loop
Definition: exprtk.hpp:2052
details::_uint64_t iteration_count
Definition: exprtk.hpp:2054
Definition: exprtk.hpp:2024
virtual void handle_runtime_violation(const violation_context &)
Definition: exprtk.hpp:2057
loop_types loop_set
Definition: exprtk.hpp:2041
loop_types
Definition: exprtk.hpp:2026
@ e_while_loop
Definition: exprtk.hpp:2029
@ e_repeat_until_loop
Definition: exprtk.hpp:2030
@ e_for_loop
Definition: exprtk.hpp:2028
@ e_all_loops
Definition: exprtk.hpp:2031
@ e_invalid
Definition: exprtk.hpp:2027
details::_uint64_t max_loop_iterations
Definition: exprtk.hpp:2048
violation_type
Definition: exprtk.hpp:2035
@ e_iteration_count
Definition: exprtk.hpp:2037
@ e_timeout
Definition: exprtk.hpp:2038
@ e_unknown
Definition: exprtk.hpp:2036
virtual ~loop_runtime_check()
Definition: exprtk.hpp:2062
loop_runtime_check()
Definition: exprtk.hpp:2043
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28085
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28095
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28105
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28116
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28127
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28139
static T process(const arg_list_t &arg)
Definition: exprtk.hpp:28151
std::vector< std::pair< expression_node_ptr, bool > > arg_list_t
Definition: exprtk.hpp:28078
std::string param_seq
Definition: exprtk.hpp:24355
return_type_t return_type
Definition: exprtk.hpp:24354
Definition: exprtk.hpp:20009
usr_mode
Definition: exprtk.hpp:20019
virtual ~unknown_symbol_resolver()
Definition: exprtk.hpp:20030
unknown_symbol_resolver(const usr_mode m=e_usrmode_default)
Definition: exprtk.hpp:20026
virtual bool process(const std::string &, symbol_table_t &, std::string &)
Definition: exprtk.hpp:20048
virtual bool process(const std::string &, usr_symbol_type &st, T &default_value, std::string &error_message)
Definition: exprtk.hpp:20033
usr_symbol_type
Definition: exprtk.hpp:20012
usr_mode mode
Definition: exprtk.hpp:20024
Definition: exprtk.hpp:18922
std::string error_line
Definition: exprtk.hpp:18933
std::size_t line_no
Definition: exprtk.hpp:18934
std::size_t column_no
Definition: exprtk.hpp:18935
std::string diagnostic
Definition: exprtk.hpp:18931
error_mode mode
Definition: exprtk.hpp:18930
std::string src_location
Definition: exprtk.hpp:18932
type()
Definition: exprtk.hpp:18923
lexer::token token
Definition: exprtk.hpp:18929
Definition: exprtk.hpp:38223
generic_type::string_view string_t
Definition: exprtk.hpp:38228
igeneric_function< T >::generic_type generic_type
Definition: exprtk.hpp:38224
static void print(const string_t &s)
Definition: exprtk.hpp:38269
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38225
static void print(const std::string &scalar_format, const scalar_t &s)
Definition: exprtk.hpp:38253
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38226
exprtk::details::numeric::details::number_type< T >::type num_type
Definition: exprtk.hpp:38229
static void print(const std::string &scalar_format, const vector_t &v)
Definition: exprtk.hpp:38258
static void process(const std::string &scalar_format, parameter_list_t parameters)
Definition: exprtk.hpp:38231
generic_type::vector_view vector_t
Definition: exprtk.hpp:38227
Definition: exprtk.hpp:38631
T operator()(const T &v)
Definition: exprtk.hpp:38638
close()
Definition: exprtk.hpp:38634
void close(Ptr &p)
Definition: exprtk.hpp:38433
bool getline(std::string &s)
Definition: exprtk.hpp:38498
file_mode mode
Definition: exprtk.hpp:38375
file_descriptor(const std::string &fname, const std::string &access)
Definition: exprtk.hpp:38368
std::string file_name
Definition: exprtk.hpp:38376
bool write(const View &view, const std::size_t amount, const std::size_t offset=0)
Definition: exprtk.hpp:38461
bool close()
Definition: exprtk.hpp:38441
void * stream_ptr
Definition: exprtk.hpp:38374
bool eof() const
Definition: exprtk.hpp:38508
bool open()
Definition: exprtk.hpp:38378
bool read(View &view, const std::size_t amount, const std::size_t offset=0)
Definition: exprtk.hpp:38480
file_mode get_file_mode(const std::string &access) const
Definition: exprtk.hpp:38519
Definition: exprtk.hpp:38792
eof()
Definition: exprtk.hpp:38795
T operator()(const T &v)
Definition: exprtk.hpp:38799
Definition: exprtk.hpp:38809
read< T > r
Definition: exprtk.hpp:38813
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:38817
close< T > c
Definition: exprtk.hpp:38811
eof< T > e
Definition: exprtk.hpp:38815
write< T > w
Definition: exprtk.hpp:38812
getline< T > g
Definition: exprtk.hpp:38814
open< T > o
Definition: exprtk.hpp:38810
Definition: exprtk.hpp:38324
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:38328
println< T > pl
Definition: exprtk.hpp:38326
print< T > p
Definition: exprtk.hpp:38325
Definition: exprtk.hpp:38279
T operator()(parameter_list_t parameters)
Definition: exprtk.hpp:38290
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38280
std::string scalar_format_
Definition: exprtk.hpp:38296
print(const std::string &scalar_format="%10.5f")
Definition: exprtk.hpp:38284
Definition: exprtk.hpp:38301
std::string scalar_format_
Definition: exprtk.hpp:38319
T operator()(parameter_list_t parameters)
Definition: exprtk.hpp:38312
println(const std::string &scalar_format="%10.5f")
Definition: exprtk.hpp:38306
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38302
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38871
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38869
generic_type::vector_view vector_t
Definition: exprtk.hpp:38873
static bool process(parameter_list_t &parameters, std::size_t &r0, std::size_t &r1, const std::size_t &r0_prmidx, const std::size_t &r1_prmidx, const std::size_t vec_idx=0)
Definition: exprtk.hpp:38875
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38872
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38870
Definition: exprtk.hpp:39943
axpby< T > b1_axpby
Definition: exprtk.hpp:39959
dotk< T > dtk
Definition: exprtk.hpp:39964
nthelement< T > ne
Definition: exprtk.hpp:39955
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:39966
iota< T > ia
Definition: exprtk.hpp:39956
dot< T > dt
Definition: exprtk.hpp:39963
sort< T > st
Definition: exprtk.hpp:39954
any_true< T > nt
Definition: exprtk.hpp:39946
axpy< T > b1_axpy
Definition: exprtk.hpp:39958
copy< T > cp
Definition: exprtk.hpp:39949
count< T > c
Definition: exprtk.hpp:39948
axpbyz< T > b1_axpbyz
Definition: exprtk.hpp:39961
any_false< T > nf
Definition: exprtk.hpp:39947
all_false< T > af
Definition: exprtk.hpp:39945
sumk< T > sk
Definition: exprtk.hpp:39957
all_true< T > at
Definition: exprtk.hpp:39944
rol< T > rl
Definition: exprtk.hpp:39950
ror< T > rr
Definition: exprtk.hpp:39951
axpbz< T > b1_axpbz
Definition: exprtk.hpp:39962
axpyz< T > b1_axpyz
Definition: exprtk.hpp:39960
shift_right< T > sr
Definition: exprtk.hpp:39953
shift_left< T > sl
Definition: exprtk.hpp:39952
type_store< vector_holder_t, vector_holder_t > vector_store
Definition: exprtk.hpp:17500
type_store< function_t, function_t > function_store
Definition: exprtk.hpp:17495
std::list< std::string > local_stringvar_list_
Definition: exprtk.hpp:17543
std::set< std::string > reserved_symbol_table_
Definition: exprtk.hpp:17544
bool is_reserved_symbol(const std::string &symbol) const
Definition: exprtk.hpp:17526
std::list< T > local_symbol_list_
Definition: exprtk.hpp:17542
static void destroy(st_data *&sd)
Definition: exprtk.hpp:17536
type_store< vararg_function_t, vararg_function_t > vararg_function_store
Definition: exprtk.hpp:17496
type_store< generic_function_t, generic_function_t > string_function_store
Definition: exprtk.hpp:17498
std::vector< ifunction< T > * > free_function_list_
Definition: exprtk.hpp:17545
static st_data * create()
Definition: exprtk.hpp:17531
~st_data()
Definition: exprtk.hpp:17518
type_store< generic_function_t, generic_function_t > overload_function_store
Definition: exprtk.hpp:17499
type_store< generic_function_t, generic_function_t > generic_function_store
Definition: exprtk.hpp:17497
type_store< stringvar_t, std::string > stringvar_store
Definition: exprtk.hpp:17502
type_store< variable_t, T > variable_store
Definition: exprtk.hpp:17494
st_data()
Definition: exprtk.hpp:17505
Definition: exprtk.hpp:17491
~control_block()
Definition: exprtk.hpp:17558
control_block()
Definition: exprtk.hpp:17548
std::size_t ref_count
Definition: exprtk.hpp:17591
control_block(st_data *data)
Definition: exprtk.hpp:17553
static void destroy(control_block *&cntrl_blck, SymTab *sym_tab)
Definition: exprtk.hpp:17572
static control_block * create()
Definition: exprtk.hpp:17566
st_data * data_
Definition: exprtk.hpp:17592
Definition: exprtk.hpp:16914
ff00_functor f
Definition: exprtk.hpp:16920
freefunc00(ff00_functor ff)
Definition: exprtk.hpp:16917
Definition: exprtk.hpp:16924
freefunc01(ff01_functor ff)
Definition: exprtk.hpp:16927
ff01_functor f
Definition: exprtk.hpp:16930
Definition: exprtk.hpp:16934
freefunc02(ff02_functor ff)
Definition: exprtk.hpp:16937
ff02_functor f
Definition: exprtk.hpp:16940
Definition: exprtk.hpp:16944
ff03_functor f
Definition: exprtk.hpp:16950
freefunc03(ff03_functor ff)
Definition: exprtk.hpp:16947
Definition: exprtk.hpp:16954
ff04_functor f
Definition: exprtk.hpp:16960
freefunc04(ff04_functor ff)
Definition: exprtk.hpp:16957
Definition: exprtk.hpp:16964
ff05_functor f
Definition: exprtk.hpp:16970
freefunc05(ff05_functor ff)
Definition: exprtk.hpp:16967
Definition: exprtk.hpp:16974
freefunc06(ff06_functor ff)
Definition: exprtk.hpp:16977
ff06_functor f
Definition: exprtk.hpp:16980
Definition: exprtk.hpp:16984
ff07_functor f
Definition: exprtk.hpp:16991
freefunc07(ff07_functor ff)
Definition: exprtk.hpp:16987
Definition: exprtk.hpp:16995
freefunc08(ff08_functor ff)
Definition: exprtk.hpp:16998
ff08_functor f
Definition: exprtk.hpp:17002
Definition: exprtk.hpp:17006
ff09_functor f
Definition: exprtk.hpp:17013
freefunc09(ff09_functor ff)
Definition: exprtk.hpp:17009
Definition: exprtk.hpp:17017
ff10_functor f
Definition: exprtk.hpp:17024
freefunc10(ff10_functor ff)
Definition: exprtk.hpp:17020
Definition: exprtk.hpp:17028
freefunc11(ff11_functor ff)
Definition: exprtk.hpp:17031
ff11_functor f
Definition: exprtk.hpp:17035
Definition: exprtk.hpp:17039
ff12_functor f
Definition: exprtk.hpp:17047
freefunc12(ff12_functor ff)
Definition: exprtk.hpp:17042
Definition: exprtk.hpp:17051
freefunc13(ff13_functor ff)
Definition: exprtk.hpp:17054
ff13_functor f
Definition: exprtk.hpp:17059
Definition: exprtk.hpp:17063
freefunc14(ff14_functor ff)
Definition: exprtk.hpp:17066
ff14_functor f
Definition: exprtk.hpp:17071
Definition: exprtk.hpp:17075
ff15_functor f
Definition: exprtk.hpp:17083
freefunc15(ff15_functor ff)
Definition: exprtk.hpp:17078
Definition: exprtk.hpp:17116
exprtk_define_process(variable_node_t) exprtk_define_process(vector_t) exprtk_define_process(stringvar_node_t) template< typename DeleteType > static inline void process(std
Definition: exprtk.hpp:17123
static bool test(const variable_node_t *p, const void *ptr)
Definition: exprtk.hpp:17339
static bool test(const PtrType, const void *)
Definition: exprtk.hpp:17330
static std::pair< bool, vector_t * > make(std::pair< T *, std::size_t > v, const bool is_const=false)
Definition: exprtk.hpp:17209
static std::pair< bool, vector_t * > make(std::deque< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:17235
static std::pair< bool, vector_t * > make(std::vector< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:17218
static std::pair< bool, vector_t * > make(exprtk::vector_view< T > &v, const bool is_const=false)
Definition: exprtk.hpp:17226
Definition: exprtk.hpp:17088
details::stringvar_node< T > stringvar_node_t
Definition: exprtk.hpp:17096
std::size_t size
Definition: exprtk.hpp:17109
bool remove(const std::string &symbol_name, const bool delete_node=true)
Definition: exprtk.hpp:17365
type_map_t::iterator tm_itr_t
Definition: exprtk.hpp:17103
igeneric_function< T > igeneric_function_t
Definition: exprtk.hpp:17093
bool add(const std::string &symbol_name, RawType &t, const bool is_const=false)
Definition: exprtk.hpp:17274
std::map< std::string, type_pair_t, details::ilesscompare > type_map_t
Definition: exprtk.hpp:17102
type_t * type_ptr
Definition: exprtk.hpp:17100
details::variable_node< T > variable_node_t
Definition: exprtk.hpp:17090
std::size_t get_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:17451
bool add_impl(const std::string &symbol_name, RType t, const bool is_const)
Definition: exprtk.hpp:17183
type_map_t::const_iterator tm_const_itr_t
Definition: exprtk.hpp:17104
type_store()
Definition: exprtk.hpp:17111
type_map_t map
Definition: exprtk.hpp:17108
type_ptr get(const std::string &symbol_name) const
Definition: exprtk.hpp:17317
std::string entity_name(const PtrType &ptr) const
Definition: exprtk.hpp:17147
std::pair< bool, type_ptr > type_pair_t
Definition: exprtk.hpp:17101
bool add(const std::string &symbol_name, std::vector< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:17255
bool is_constant(const std::string &symbol_name) const
Definition: exprtk.hpp:17167
bool symbol_exists(const std::string &symbol_name) const
Definition: exprtk.hpp:17136
bool add(const std::string &symbol_name, T(&v)[v_size], const bool is_const=false)
Definition: exprtk.hpp:17242
ivararg_function< T > ivararg_function_t
Definition: exprtk.hpp:17092
type_ptr get_from_varptr(const void *ptr) const
Definition: exprtk.hpp:17346
bool add(const std::string &symbol_name, std::deque< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:17268
bool add(const std::string &symbol_name, exprtk::vector_view< T > &v, const bool is_const=false)
Definition: exprtk.hpp:17261
ifunction< T > ifunction_t
Definition: exprtk.hpp:17091
void clear(const bool delete_node=true)
Definition: exprtk.hpp:17405
details::expression_node< T > * expression_ptr
Definition: exprtk.hpp:17089
RawType & type_ref(const std::string &symbol_name)
Definition: exprtk.hpp:17385
details::vector_holder< T > vector_t
Definition: exprtk.hpp:17094
std::size_t get_list(Sequence< std::pair< std::string, RawType >, Allocator > &list) const
Definition: exprtk.hpp:17429
bool add(const std::string &symbol_name, T *v, const std::size_t v_size, const bool is_const=false)
Definition: exprtk.hpp:17248
Type type_t
Definition: exprtk.hpp:17099
Definition: exprtk.hpp:4486
value_t & operator()()
Definition: exprtk.hpp:4498
bool to_uint(UIntType &u) const
Definition: exprtk.hpp:4520
scalar_view(type_store_t &ts)
Definition: exprtk.hpp:4490
type_store< T > type_store_t
Definition: exprtk.hpp:4487
scalar_view(const type_store_t &ts)
Definition: exprtk.hpp:4494
T & v_
Definition: exprtk.hpp:4532
bool to_int(IntType &i) const
Definition: exprtk.hpp:4509
T value_t
Definition: exprtk.hpp:4488
Definition: exprtk.hpp:4436
value_t * end()
Definition: exprtk.hpp:4473
type_view(type_store_t &ts)
Definition: exprtk.hpp:4440
ViewType value_t
Definition: exprtk.hpp:4438
value_t & operator[](const std::size_t &i)
Definition: exprtk.hpp:4455
value_t * begin()
Definition: exprtk.hpp:4466
type_view(const type_store_t &ts)
Definition: exprtk.hpp:4445
std::size_t size() const
Definition: exprtk.hpp:4450
value_t * data_
Definition: exprtk.hpp:4479
const value_t & operator[](const std::size_t &i) const
Definition: exprtk.hpp:4460
type_store_t & ts_
Definition: exprtk.hpp:4478
const value_t * end() const
Definition: exprtk.hpp:4468
const value_t * begin() const
Definition: exprtk.hpp:4465
type_store< T > type_store_t
Definition: exprtk.hpp:4437
Definition: exprtk.hpp:4355
type_view< T > vector_view
Definition: exprtk.hpp:4482
store_type
Definition: exprtk.hpp:4357
@ e_vector
Definition: exprtk.hpp:4360
@ e_string
Definition: exprtk.hpp:4361
@ e_scalar
Definition: exprtk.hpp:4359
@ e_unknown
Definition: exprtk.hpp:4358
type_store()
Definition: exprtk.hpp:4364
std::size_t size
Definition: exprtk.hpp:4376
void * data
Definition: exprtk.hpp:4372
T * vec_data
Definition: exprtk.hpp:4373
type_view< char > string_view
Definition: exprtk.hpp:4483
store_type type
Definition: exprtk.hpp:4377