Line data Source code
1 : /*
2 : ******************************************************************
3 : * C++ Mathematical Expression Toolkit Library *
4 : * *
5 : * Author: Arash Partow (1999-2024) *
6 : * URL: https://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 : * https://www.opensource.org/licenses/MIT *
13 : * SPDX-License-Identifier: MIT *
14 : * *
15 : * Example expressions: *
16 : * (00) (y + x / y) * (x - y / x) *
17 : * (01) (x^2 / sin(2 * pi / y)) - x / 2 *
18 : * (02) sqrt(1 - (x^2)) *
19 : * (03) 1 - sin(2 * x) + cos(pi / y) *
20 : * (04) a * exp(2 * t) + c *
21 : * (05) if(((x + 2) == 3) and ((y + 5) <= 9), 1 + w, 2 / z) *
22 : * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
23 : * (07) z := x + sin(2 * pi / y) *
24 : * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
25 : * (09) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1) *
26 : * (10) inrange(-2, m, +2) == if(({-2 <= m} and [m <= +2]), 1, 0) *
27 : * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
28 : * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
29 : * *
30 : ******************************************************************
31 : */
32 :
33 :
34 : #ifndef INCLUDE_EXPRTK_HPP
35 : #define INCLUDE_EXPRTK_HPP
36 :
37 :
38 : #include <algorithm>
39 : #include <cassert>
40 : #include <cctype>
41 : #include <cmath>
42 : #include <cstdio>
43 : #include <cstdlib>
44 : #include <cstring>
45 : #include <deque>
46 : #include <functional>
47 : #include <iterator>
48 : #include <limits>
49 : #include <list>
50 : #include <map>
51 : #include <set>
52 : #include <stack>
53 : #include <stdexcept>
54 : #include <string>
55 : #include <utility>
56 : #include <vector>
57 :
58 :
59 : namespace exprtk
60 : {
61 : #ifdef exprtk_enable_debugging
62 : #define exprtk_debug(params) printf params
63 : #else
64 : #define exprtk_debug(params) (void)0
65 : #endif
66 :
67 : #define exprtk_error_location \
68 : "exprtk.hpp:" + details::to_str(__LINE__) \
69 :
70 : #if __cplusplus >= 201103L
71 : #define exprtk_override override
72 : #define exprtk_final final
73 : #define exprtk_delete = delete
74 : #else
75 : #define exprtk_override
76 : #define exprtk_final
77 : #define exprtk_delete
78 : #endif
79 :
80 : #if __cplusplus >= 201603L
81 : #define exprtk_fallthrough [[fallthrough]];
82 : #else
83 : #define exprtk_fallthrough
84 : #endif
85 :
86 : namespace details
87 : {
88 : typedef char char_t;
89 : typedef char_t* char_ptr;
90 : typedef char_t const* char_cptr;
91 : typedef unsigned char uchar_t;
92 : typedef uchar_t* uchar_ptr;
93 : typedef uchar_t const* uchar_cptr;
94 : typedef unsigned long long int _uint64_t;
95 : typedef long long int _int64_t;
96 :
97 49678579 : inline bool is_whitespace(const char_t c)
98 : {
99 46002143 : return (' ' == c) || ('\n' == c) ||
100 45996315 : ('\r' == c) || ('\t' == c) ||
101 95680722 : ('\b' == c) || ('\v' == c) ||
102 49678579 : ('\f' == c) ;
103 : }
104 :
105 15982123 : inline bool is_operator_char(const char_t c)
106 : {
107 14907277 : return ('+' == c) || ('-' == c) ||
108 13352295 : ('*' == c) || ('/' == c) ||
109 12559482 : ('^' == c) || ('<' == c) ||
110 12539338 : ('>' == c) || ('=' == c) ||
111 11998035 : (',' == c) || ('!' == c) ||
112 8977512 : ('(' == c) || (')' == c) ||
113 5873106 : ('[' == c) || (']' == c) ||
114 5730731 : ('{' == c) || ('}' == c) ||
115 5686659 : ('%' == c) || (':' == c) ||
116 5553912 : ('?' == c) || ('&' == c) ||
117 30889400 : ('|' == c) || (';' == c) ;
118 : }
119 :
120 34242041 : inline bool is_letter(const char_t c)
121 : {
122 34824690 : return (('a' <= c) && (c <= 'z')) ||
123 34824690 : (('A' <= c) && (c <= 'Z')) ;
124 : }
125 :
126 24011547 : inline bool is_digit(const char_t c)
127 : {
128 24011547 : return ('0' <= c) && (c <= '9');
129 : }
130 :
131 11834450 : inline bool is_letter_or_digit(const char_t c)
132 : {
133 11834450 : return is_letter(c) || is_digit(c);
134 : }
135 :
136 34012410 : inline bool is_left_bracket(const char_t c)
137 : {
138 34012410 : return ('(' == c) || ('[' == c) || ('{' == c);
139 : }
140 :
141 38015437 : inline bool is_right_bracket(const char_t c)
142 : {
143 38015437 : return (')' == c) || (']' == c) || ('}' == c);
144 : }
145 :
146 12484572 : inline bool is_bracket(const char_t c)
147 : {
148 12484572 : return is_left_bracket(c) || is_right_bracket(c);
149 : }
150 :
151 2622 : inline bool is_sign(const char_t c)
152 : {
153 2622 : return ('+' == c) || ('-' == c);
154 : }
155 :
156 : inline bool is_invalid(const char_t c)
157 : {
158 : return !is_whitespace (c) &&
159 : !is_operator_char(c) &&
160 : !is_letter (c) &&
161 : !is_digit (c) &&
162 : ('.' != c) &&
163 : ('_' != c) &&
164 : ('$' != c) &&
165 : ('~' != c) &&
166 : ('\'' != c);
167 : }
168 :
169 386183 : inline bool is_valid_string_char(const char_t c)
170 : {
171 386483 : return std::isprint(static_cast<uchar_t>(c)) ||
172 386483 : is_whitespace(c);
173 : }
174 :
175 : #ifndef exprtk_disable_caseinsensitivity
176 24 : inline void case_normalise(std::string& s)
177 : {
178 56 : for (std::size_t i = 0; i < s.size(); ++i)
179 : {
180 32 : s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
181 : }
182 24 : }
183 :
184 8490 : inline bool imatch(const char_t c1, const char_t c2)
185 : {
186 8490 : return std::tolower(c1) == std::tolower(c2);
187 : }
188 :
189 63175754 : inline bool imatch(const std::string& s1, const std::string& s2)
190 : {
191 63175754 : if (s1.size() == s2.size())
192 : {
193 6839715 : for (std::size_t i = 0; i < s1.size(); ++i)
194 : {
195 6151685 : if (std::tolower(s1[i]) != std::tolower(s2[i]))
196 : {
197 4702457 : return false;
198 : }
199 : }
200 :
201 688030 : return true;
202 : }
203 :
204 57785267 : return false;
205 : }
206 :
207 : struct ilesscompare
208 : {
209 173015998 : inline bool operator() (const std::string& s1, const std::string& s2) const
210 : {
211 173015998 : const std::size_t length = std::min(s1.size(),s2.size());
212 :
213 265342376 : for (std::size_t i = 0; i < length; ++i)
214 : {
215 222302178 : const char_t c1 = static_cast<char_t>(std::tolower(s1[i]));
216 222302178 : const char_t c2 = static_cast<char_t>(std::tolower(s2[i]));
217 :
218 222302178 : if (c1 < c2)
219 71663625 : return true;
220 150638553 : else if (c2 < c1)
221 58312175 : return false;
222 : }
223 :
224 43040198 : return s1.size() < s2.size();
225 : }
226 : };
227 :
228 : #else
229 : inline void case_normalise(std::string&)
230 : {}
231 :
232 : inline bool imatch(const char_t c1, const char_t c2)
233 : {
234 : return c1 == c2;
235 : }
236 :
237 : inline bool imatch(const std::string& s1, const std::string& s2)
238 : {
239 : return s1 == s2;
240 : }
241 :
242 : struct ilesscompare
243 : {
244 : inline bool operator() (const std::string& s1, const std::string& s2) const
245 : {
246 : return s1 < s2;
247 : }
248 : };
249 : #endif
250 :
251 2144061 : inline bool is_valid_sf_symbol(const std::string& symbol)
252 : {
253 : // Special function: $f12 or $F34
254 2144061 : return (4 == symbol.size()) &&
255 11692 : ('$' == symbol[0]) &&
256 8490 : imatch('f',symbol[1]) &&
257 2155753 : is_digit(symbol[2]) &&
258 2148306 : is_digit(symbol[3]);
259 : }
260 :
261 727 : inline const char_t& front(const std::string& s)
262 : {
263 727 : return s[0];
264 : }
265 :
266 0 : inline const char_t& back(const std::string& s)
267 : {
268 0 : return s[s.size() - 1];
269 : }
270 :
271 43680 : inline std::string to_str(int i)
272 : {
273 43680 : if (0 == i)
274 0 : return std::string("0");
275 :
276 43680 : std::string result;
277 :
278 43680 : const int sign = (i < 0) ? -1 : 1;
279 :
280 262080 : for ( ; i; i /= 10)
281 : {
282 218400 : result += '0' + static_cast<char_t>(sign * (i % 10));
283 : }
284 :
285 43680 : if (sign < 0)
286 : {
287 0 : result += '-';
288 : }
289 :
290 43680 : std::reverse(result.begin(), result.end());
291 :
292 43680 : return result;
293 43680 : }
294 :
295 0 : inline std::string to_str(std::size_t i)
296 : {
297 0 : return to_str(static_cast<int>(i));
298 : }
299 :
300 8400 : inline bool is_hex_digit(const uchar_t digit)
301 : {
302 8400 : return (('0' <= digit) && (digit <= '9')) ||
303 16800 : (('A' <= digit) && (digit <= 'F')) ||
304 8400 : (('a' <= digit) && (digit <= 'f')) ;
305 : }
306 :
307 4200 : inline uchar_t hex_to_bin(uchar_t h)
308 : {
309 4200 : if (('0' <= h) && (h <= '9'))
310 4200 : return (h - '0');
311 : else
312 0 : return static_cast<uchar_t>(std::toupper(h) - 'A');
313 : }
314 :
315 : template <typename Iterator>
316 3050 : inline bool parse_hex(Iterator& itr, Iterator end,
317 : char_t& result)
318 : {
319 3050 : if (
320 6100 : (end == (itr )) ||
321 6100 : (end == (itr + 1)) ||
322 5900 : (end == (itr + 2)) ||
323 2850 : (end == (itr + 3)) ||
324 2850 : ('0' != *(itr )) ||
325 2100 : ('X' != std::toupper(*(itr + 1))) ||
326 8200 : (!is_hex_digit(*(itr + 2))) ||
327 5150 : (!is_hex_digit(*(itr + 3)))
328 : )
329 : {
330 950 : return false;
331 : }
332 :
333 2100 : result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
334 2100 : hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
335 :
336 2100 : return true;
337 : }
338 :
339 1350 : inline bool cleanup_escapes(std::string& s)
340 : {
341 : typedef std::string::iterator str_itr_t;
342 :
343 1350 : str_itr_t itr1 = s.begin();
344 1350 : str_itr_t itr2 = s.begin();
345 1350 : str_itr_t end = s.end ();
346 :
347 1350 : std::size_t removal_count = 0;
348 :
349 7500 : while (end != itr1)
350 : {
351 6150 : if ('\\' == (*itr1))
352 : {
353 3050 : if (end == ++itr1)
354 : {
355 0 : return false;
356 : }
357 3050 : else if (parse_hex(itr1, end, *itr2))
358 : {
359 2100 : itr1 += 4;
360 2100 : itr2 += 1;
361 2100 : removal_count += 4;
362 : }
363 950 : else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
364 950 : else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
365 950 : else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; }
366 950 : else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; }
367 650 : else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; }
368 650 : else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; }
369 650 : else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; }
370 650 : else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; }
371 : else
372 : {
373 650 : (*itr2++) = (*itr1++);
374 650 : ++removal_count;
375 : }
376 :
377 3050 : continue;
378 : }
379 : else
380 3100 : (*itr2++) = (*itr1++);
381 : }
382 :
383 1350 : if ((removal_count > s.size()) || (0 == removal_count))
384 0 : return false;
385 :
386 1350 : s.resize(s.size() - removal_count);
387 :
388 1350 : return true;
389 : }
390 :
391 : class build_string
392 : {
393 : public:
394 :
395 0 : explicit build_string(const std::size_t& initial_size = 64)
396 396166 : {
397 396166 : data_.reserve(initial_size);
398 396166 : }
399 :
400 853493 : inline build_string& operator << (const std::string& s)
401 : {
402 853493 : data_ += s;
403 853493 : return (*this);
404 : }
405 :
406 1249659 : inline build_string& operator << (char_cptr s)
407 : {
408 1249659 : data_ += std::string(s);
409 1249659 : return (*this);
410 : }
411 :
412 396166 : inline operator std::string () const
413 : {
414 396166 : return data_;
415 : }
416 :
417 : inline std::string as_string() const
418 : {
419 : return data_;
420 : }
421 :
422 : private:
423 :
424 : std::string data_;
425 : };
426 :
427 : static const std::string reserved_words[] =
428 : {
429 : "assert", "break", "case", "continue", "const", "default",
430 : "false", "for", "if", "else", "ilike", "in", "like", "and",
431 : "nand", "nor", "not", "null", "or", "repeat", "return",
432 : "shl", "shr", "swap", "switch", "true", "until", "var",
433 : "while", "xnor", "xor", "&", "|"
434 : };
435 :
436 : static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
437 :
438 : static const std::string reserved_symbols[] =
439 : {
440 : "abs", "acos", "acosh", "and", "asin", "asinh", "assert",
441 : "atan", "atanh", "atan2", "avg", "break", "case", "ceil",
442 : "clamp", "continue", "const", "cos", "cosh", "cot", "csc",
443 : "default", "deg2grad", "deg2rad", "equal", "erf", "erfc",
444 : "exp", "expm1", "false", "floor", "for", "frac", "grad2deg",
445 : "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
446 : "like", "log", "log10", "log2", "logn", "log1p", "mand",
447 : "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
448 : "not", "not_equal", "null", "or", "pow", "rad2deg",
449 : "repeat", "return", "root", "round", "roundn", "sec", "sgn",
450 : "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
451 : "switch", "tan", "tanh", "true", "trunc", "until", "var",
452 : "while", "xnor", "xor", "&", "|"
453 : };
454 :
455 : static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
456 :
457 : static const std::string base_function_list[] =
458 : {
459 : "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
460 : "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
461 : "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
462 : "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
463 : "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
464 : "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
465 : "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
466 : "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
467 : "rad2deg", "grad2deg"
468 : };
469 :
470 : static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
471 :
472 : static const std::string logic_ops_list[] =
473 : {
474 : "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
475 : };
476 :
477 : static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
478 :
479 : static const std::string cntrl_struct_list[] =
480 : {
481 : "if", "switch", "for", "while", "repeat", "return"
482 : };
483 :
484 : static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
485 :
486 : static const std::string arithmetic_ops_list[] =
487 : {
488 : "+", "-", "*", "/", "%", "^"
489 : };
490 :
491 : static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
492 :
493 : static const std::string assignment_ops_list[] =
494 : {
495 : ":=", "+=", "-=",
496 : "*=", "/=", "%="
497 : };
498 :
499 : static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
500 :
501 : static const std::string inequality_ops_list[] =
502 : {
503 : "<", "<=", "==",
504 : "=", "!=", "<>",
505 : ">=", ">"
506 : };
507 :
508 : static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
509 :
510 3200 : inline bool is_reserved_word(const std::string& symbol)
511 : {
512 108800 : for (std::size_t i = 0; i < reserved_words_size; ++i)
513 : {
514 105600 : if (imatch(symbol, reserved_words[i]))
515 : {
516 0 : return true;
517 : }
518 : }
519 :
520 3200 : return false;
521 : }
522 :
523 98139 : inline bool is_reserved_symbol(const std::string& symbol)
524 : {
525 8832464 : for (std::size_t i = 0; i < reserved_symbols_size; ++i)
526 : {
527 8734348 : if (imatch(symbol, reserved_symbols[i]))
528 : {
529 23 : return true;
530 : }
531 : }
532 :
533 98116 : return false;
534 : }
535 :
536 0 : inline bool is_base_function(const std::string& function_name)
537 : {
538 0 : for (std::size_t i = 0; i < base_function_list_size; ++i)
539 : {
540 0 : if (imatch(function_name, base_function_list[i]))
541 : {
542 0 : return true;
543 : }
544 : }
545 :
546 0 : return false;
547 : }
548 :
549 : inline bool is_control_struct(const std::string& cntrl_strct)
550 : {
551 : for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
552 : {
553 : if (imatch(cntrl_strct, cntrl_struct_list[i]))
554 : {
555 : return true;
556 : }
557 : }
558 :
559 : return false;
560 : }
561 :
562 : inline bool is_logic_opr(const std::string& lgc_opr)
563 : {
564 : for (std::size_t i = 0; i < logic_ops_list_size; ++i)
565 : {
566 : if (imatch(lgc_opr, logic_ops_list[i]))
567 : {
568 : return true;
569 : }
570 : }
571 :
572 : return false;
573 : }
574 :
575 : struct cs_match
576 : {
577 16290 : static inline bool cmp(const char_t c0, const char_t c1)
578 : {
579 16290 : return (c0 == c1);
580 : }
581 : };
582 :
583 : struct cis_match
584 : {
585 17340 : static inline bool cmp(const char_t c0, const char_t c1)
586 : {
587 17340 : return (std::tolower(c0) == std::tolower(c1));
588 : }
589 : };
590 :
591 : template <typename Iterator, typename Compare>
592 6315 : inline bool match_impl(const Iterator pattern_begin,
593 : const Iterator pattern_end ,
594 : const Iterator data_begin ,
595 : const Iterator data_end ,
596 : const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
597 : const typename std::iterator_traits<Iterator>::value_type& exactly_one )
598 : {
599 : typedef typename std::iterator_traits<Iterator>::value_type type;
600 :
601 6315 : const Iterator null_itr(0);
602 :
603 6315 : Iterator p_itr = pattern_begin;
604 6315 : Iterator d_itr = data_begin;
605 6315 : Iterator np_itr = null_itr;
606 6315 : Iterator nd_itr = null_itr;
607 :
608 26020 : for ( ; ; )
609 : {
610 32335 : if (p_itr != pattern_end)
611 : {
612 25970 : const type c = *(p_itr);
613 :
614 25970 : if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c)))
615 : {
616 20800 : ++d_itr;
617 20800 : ++p_itr;
618 20800 : continue;
619 : }
620 5170 : else if (zero_or_more == c)
621 : {
622 10280 : while ((pattern_end != p_itr) && (zero_or_more == *(p_itr)))
623 : {
624 5470 : ++p_itr;
625 : }
626 :
627 4810 : const type d = *(p_itr);
628 :
629 9420 : while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d)))
630 : {
631 4610 : ++d_itr;
632 : }
633 :
634 : // set backtrack iterators
635 4810 : np_itr = p_itr - 1;
636 4810 : nd_itr = d_itr + 1;
637 :
638 4810 : continue;
639 4810 : }
640 : }
641 6365 : else if (data_end == d_itr)
642 6205 : break;
643 :
644 520 : if ((data_end == d_itr) || (null_itr == nd_itr))
645 110 : return false;
646 :
647 410 : p_itr = np_itr;
648 410 : d_itr = nd_itr;
649 : }
650 :
651 6205 : return true;
652 : }
653 :
654 3070 : inline bool wc_match(const std::string& wild_card,
655 : const std::string& str)
656 : {
657 : return match_impl<char_cptr,cs_match>
658 6140 : (
659 : wild_card.data(),
660 3070 : wild_card.data() + wild_card.size(),
661 : str.data(),
662 3070 : str.data() + str.size(),
663 6140 : '*', '?'
664 3070 : );
665 : }
666 :
667 3245 : inline bool wc_imatch(const std::string& wild_card,
668 : const std::string& str)
669 : {
670 : return match_impl<char_cptr,cis_match>
671 6490 : (
672 : wild_card.data(),
673 3245 : wild_card.data() + wild_card.size(),
674 : str.data(),
675 3245 : str.data() + str.size(),
676 6490 : '*', '?'
677 3245 : );
678 : }
679 :
680 5662 : inline bool sequence_match(const std::string& pattern,
681 : const std::string& str,
682 : std::size_t& diff_index,
683 : char_t& diff_value)
684 : {
685 5662 : if (str.empty())
686 : {
687 15 : return ("Z" == pattern);
688 : }
689 5647 : else if ('*' == pattern[0])
690 0 : return false;
691 :
692 : typedef std::string::const_iterator itr_t;
693 :
694 5647 : itr_t p_itr = pattern.begin();
695 5647 : itr_t s_itr = str .begin();
696 :
697 5647 : const itr_t p_end = pattern.end();
698 5647 : const itr_t s_end = str .end();
699 :
700 17462 : while ((s_end != s_itr) && (p_end != p_itr))
701 : {
702 12376 : if ('*' == (*p_itr))
703 : {
704 30 : const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1)));
705 :
706 30 : if ('*' == target)
707 : {
708 0 : diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
709 0 : diff_value = static_cast<char_t>(std::toupper(*p_itr));
710 :
711 0 : return false;
712 : }
713 : else
714 30 : ++p_itr;
715 :
716 86 : while (s_itr != s_end)
717 : {
718 64 : if (target != std::toupper(*s_itr))
719 8 : break;
720 : else
721 56 : ++s_itr;
722 : }
723 :
724 30 : continue;
725 30 : }
726 12346 : else if (
727 24692 : ('?' != *p_itr) &&
728 12346 : std::toupper(*p_itr) != std::toupper(*s_itr)
729 : )
730 : {
731 561 : diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
732 561 : diff_value = static_cast<char_t>(std::toupper(*p_itr));
733 :
734 561 : return false;
735 : }
736 :
737 11785 : ++p_itr;
738 11785 : ++s_itr;
739 : }
740 :
741 : return (
742 8716 : (s_end == s_itr) &&
743 : (
744 3603 : (p_end == p_itr) ||
745 27 : ('*' == *p_itr)
746 : )
747 5086 : );
748 : }
749 :
750 : template<typename T>
751 : struct set_zero_value_impl
752 : {
753 : static inline void process(T* base_ptr, const std::size_t size)
754 : {
755 : const T zero = T(0);
756 : for (std::size_t i = 0; i < size; ++i)
757 : {
758 : base_ptr[i] = zero;
759 : }
760 : }
761 : };
762 :
763 : #define pod_set_zero_value(T) \
764 : template <> \
765 : struct set_zero_value_impl<T> \
766 : { \
767 : static inline void process(T* base_ptr, const std::size_t size) \
768 : { std::memset(base_ptr, 0x00, size * sizeof(T)); } \
769 : }; \
770 :
771 : pod_set_zero_value(float )
772 2011 : pod_set_zero_value(double )
773 : pod_set_zero_value(long double)
774 :
775 : #ifdef pod_set_zero_value
776 : #undef pod_set_zero_value
777 : #endif
778 :
779 : template<typename T>
780 2011 : inline void set_zero_value(T* data, const std::size_t size)
781 : {
782 2011 : set_zero_value_impl<T>::process(data,size);
783 2011 : }
784 :
785 : template<typename T>
786 : inline void set_zero_value(std::vector<T>& v)
787 : {
788 : set_zero_value(v.data(),v.size());
789 : }
790 :
791 : static const double pow10[] =
792 : {
793 : 1.0,
794 : 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
795 : 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
796 : 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
797 : 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
798 : };
799 :
800 : static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
801 :
802 : namespace numeric
803 : {
804 : namespace constant
805 : {
806 : static const double e = 2.71828182845904523536028747135266249775724709369996;
807 : static const double pi = 3.14159265358979323846264338327950288419716939937510;
808 : static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
809 : static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
810 : static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
811 : static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
812 : static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
813 : static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
814 : static const double log2 = 0.69314718055994530941723212145817656807550013436026;
815 : static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
816 : }
817 :
818 : namespace details
819 : {
820 : struct unknown_type_tag { unknown_type_tag() {} };
821 317158419 : struct real_type_tag { real_type_tag () {} };
822 : struct int_type_tag { int_type_tag () {} };
823 :
824 : template <typename T>
825 : struct number_type
826 : {
827 : typedef unknown_type_tag type;
828 : number_type() {}
829 : };
830 :
831 : #define exprtk_register_real_type_tag(T) \
832 : template <> struct number_type<T> \
833 : { typedef real_type_tag type; number_type() {} }; \
834 :
835 : #define exprtk_register_int_type_tag(T) \
836 : template <> struct number_type<T> \
837 : { typedef int_type_tag type; number_type() {} }; \
838 :
839 : exprtk_register_real_type_tag(float )
840 : exprtk_register_real_type_tag(double )
841 : exprtk_register_real_type_tag(long double)
842 :
843 : exprtk_register_int_type_tag(short )
844 : exprtk_register_int_type_tag(int )
845 : exprtk_register_int_type_tag(_int64_t )
846 : exprtk_register_int_type_tag(unsigned short)
847 : exprtk_register_int_type_tag(unsigned int )
848 : exprtk_register_int_type_tag(_uint64_t )
849 :
850 : #undef exprtk_register_real_type_tag
851 : #undef exprtk_register_int_type_tag
852 :
853 : template <typename T>
854 : struct epsilon_type {};
855 :
856 : #define exprtk_define_epsilon_type(Type, Epsilon) \
857 : template <> struct epsilon_type<Type> \
858 : { \
859 : static inline Type value() \
860 : { \
861 : const Type epsilon = static_cast<Type>(Epsilon); \
862 : return epsilon; \
863 : } \
864 : }; \
865 :
866 : exprtk_define_epsilon_type(float , 0.00000100000f)
867 267144 : exprtk_define_epsilon_type(double , 0.000000000100)
868 : exprtk_define_epsilon_type(long double, 0.000000000001)
869 :
870 : #undef exprtk_define_epsilon_type
871 :
872 : template <typename T>
873 195 : inline bool is_nan_impl(const T v, real_type_tag)
874 : {
875 195 : return std::not_equal_to<T>()(v,v);
876 : }
877 :
878 : template <typename T>
879 112698 : inline int to_int32_impl(const T v, real_type_tag)
880 : {
881 112698 : return static_cast<int>(v);
882 : }
883 :
884 : template <typename T>
885 57228 : inline _int64_t to_int64_impl(const T v, real_type_tag)
886 : {
887 57228 : return static_cast<_int64_t>(v);
888 : }
889 :
890 : template <typename T>
891 32864168 : inline _uint64_t to_uint64_impl(const T v, real_type_tag)
892 : {
893 32864168 : return static_cast<_uint64_t>(v);
894 : }
895 :
896 : template <typename T>
897 1570 : inline bool is_true_impl(const T v)
898 : {
899 1570 : return std::not_equal_to<T>()(T(0),v);
900 : }
901 :
902 : template <typename T>
903 2330 : inline bool is_false_impl(const T v)
904 : {
905 2330 : return std::equal_to<T>()(T(0),v);
906 : }
907 :
908 : template <typename T>
909 22979206 : inline T abs_impl(const T v, real_type_tag)
910 : {
911 22979206 : return ((v < T(0)) ? -v : v);
912 : }
913 :
914 : template <typename T>
915 : inline T min_impl(const T v0, const T v1, real_type_tag)
916 : {
917 : return std::min<T>(v0,v1);
918 : }
919 :
920 : template <typename T>
921 : inline T max_impl(const T v0, const T v1, real_type_tag)
922 : {
923 : return std::max<T>(v0,v1);
924 : }
925 :
926 : template <typename T>
927 267123 : inline T equal_impl(const T v0, const T v1, real_type_tag)
928 : {
929 267123 : const T epsilon = epsilon_type<T>::value();
930 267123 : 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);
931 : }
932 :
933 : inline float equal_impl(const float v0, const float v1, real_type_tag)
934 : {
935 : const float epsilon = epsilon_type<float>::value();
936 : 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;
937 : }
938 :
939 : template <typename T>
940 : inline T equal_impl(const T v0, const T v1, int_type_tag)
941 : {
942 : return (v0 == v1) ? 1 : 0;
943 : }
944 :
945 : template <typename T>
946 0 : inline T expm1_impl(const T v, real_type_tag)
947 : {
948 : // return std::expm1<T>(v);
949 0 : if (abs_impl(v,real_type_tag()) < T(0.00001))
950 0 : return v + (T(0.5) * v * v);
951 : else
952 0 : return std::exp(v) - T(1);
953 : }
954 :
955 : template <typename T>
956 : inline T expm1_impl(const T v, int_type_tag)
957 : {
958 : return T(std::exp<double>(v)) - T(1);
959 : }
960 :
961 : template <typename T>
962 20 : inline T nequal_impl(const T v0, const T v1, real_type_tag)
963 : {
964 : typedef real_type_tag rtg;
965 20 : const T epsilon = epsilon_type<T>::value();
966 20 : 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);
967 : }
968 :
969 : inline float nequal_impl(const float v0, const float v1, real_type_tag)
970 : {
971 : typedef real_type_tag rtg;
972 : const float epsilon = epsilon_type<float>::value();
973 : 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;
974 : }
975 :
976 : template <typename T>
977 : inline T nequal_impl(const T v0, const T v1, int_type_tag)
978 : {
979 : return (v0 != v1) ? 1 : 0;
980 : }
981 :
982 : template <typename T>
983 118489 : inline T modulus_impl(const T v0, const T v1, real_type_tag)
984 : {
985 118489 : return std::fmod(v0,v1);
986 : }
987 :
988 : template <typename T>
989 : inline T modulus_impl(const T v0, const T v1, int_type_tag)
990 : {
991 : return v0 % v1;
992 : }
993 :
994 : template <typename T>
995 7664 : inline T pow_impl(const T v0, const T v1, real_type_tag)
996 : {
997 7664 : return std::pow(v0,v1);
998 : }
999 :
1000 : template <typename T>
1001 : inline T pow_impl(const T v0, const T v1, int_type_tag)
1002 : {
1003 : return std::pow(static_cast<double>(v0),static_cast<double>(v1));
1004 : }
1005 :
1006 : template <typename T>
1007 0 : inline T logn_impl(const T v0, const T v1, real_type_tag)
1008 : {
1009 0 : return std::log(v0) / std::log(v1);
1010 : }
1011 :
1012 : template <typename T>
1013 : inline T logn_impl(const T v0, const T v1, int_type_tag)
1014 : {
1015 : return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
1016 : }
1017 :
1018 : template <typename T>
1019 0 : inline T log1p_impl(const T v, real_type_tag)
1020 : {
1021 0 : if (v > T(-1))
1022 : {
1023 0 : if (abs_impl(v,real_type_tag()) > T(0.0001))
1024 : {
1025 0 : return std::log(T(1) + v);
1026 : }
1027 : else
1028 0 : return (T(-0.5) * v + T(1)) * v;
1029 : }
1030 :
1031 0 : return std::numeric_limits<T>::quiet_NaN();
1032 : }
1033 :
1034 : template <typename T>
1035 : inline T log1p_impl(const T v, int_type_tag)
1036 : {
1037 : if (v > T(-1))
1038 : {
1039 : return std::log(T(1) + v);
1040 : }
1041 :
1042 : return std::numeric_limits<T>::quiet_NaN();
1043 : }
1044 :
1045 : template <typename T>
1046 160 : inline T root_impl(const T v0, const T v1, real_type_tag)
1047 : {
1048 160 : if (v1 < T(0))
1049 0 : return std::numeric_limits<T>::quiet_NaN();
1050 :
1051 160 : const std::size_t n = static_cast<std::size_t>(v1);
1052 :
1053 160 : if ((v0 < T(0)) && (0 == (n % 2)))
1054 0 : return std::numeric_limits<T>::quiet_NaN();
1055 :
1056 160 : return std::pow(v0, T(1) / n);
1057 : }
1058 :
1059 : template <typename T>
1060 : inline T root_impl(const T v0, const T v1, int_type_tag)
1061 : {
1062 : return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1063 : }
1064 :
1065 : template <typename T>
1066 60 : inline T round_impl(const T v, real_type_tag)
1067 : {
1068 60 : return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1069 : }
1070 :
1071 : template <typename T>
1072 120 : inline T roundn_impl(const T v0, const T v1, real_type_tag)
1073 : {
1074 120 : const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1))));
1075 120 : const T p10 = T(pow10[index]);
1076 :
1077 120 : if (v0 < T(0))
1078 0 : return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1079 : else
1080 120 : return T(std::floor((v0 * p10) + T(0.5)) / p10);
1081 : }
1082 :
1083 : template <typename T>
1084 : inline T roundn_impl(const T v0, const T, int_type_tag)
1085 : {
1086 : return v0;
1087 : }
1088 :
1089 : template <typename T>
1090 30 : inline T hypot_impl(const T v0, const T v1, real_type_tag)
1091 : {
1092 30 : return std::sqrt((v0 * v0) + (v1 * v1));
1093 : }
1094 :
1095 : template <typename T>
1096 : inline T hypot_impl(const T v0, const T v1, int_type_tag)
1097 : {
1098 : return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1099 : }
1100 :
1101 : template <typename T>
1102 0 : inline T atan2_impl(const T v0, const T v1, real_type_tag)
1103 : {
1104 0 : return std::atan2(v0,v1);
1105 : }
1106 :
1107 : template <typename T>
1108 : inline T atan2_impl(const T, const T, int_type_tag)
1109 : {
1110 : return 0;
1111 : }
1112 :
1113 : template <typename T>
1114 0 : inline T shr_impl(const T v0, const T v1, real_type_tag)
1115 : {
1116 0 : return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1117 : }
1118 :
1119 : template <typename T>
1120 : inline T shr_impl(const T v0, const T v1, int_type_tag)
1121 : {
1122 : return v0 >> v1;
1123 : }
1124 :
1125 : template <typename T>
1126 0 : inline T shl_impl(const T v0, const T v1, real_type_tag)
1127 : {
1128 0 : return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1129 : }
1130 :
1131 : template <typename T>
1132 : inline T shl_impl(const T v0, const T v1, int_type_tag)
1133 : {
1134 : return v0 << v1;
1135 : }
1136 :
1137 : template <typename T>
1138 153 : inline T sgn_impl(const T v, real_type_tag)
1139 : {
1140 153 : if (v > T(0)) return T(+1);
1141 30 : else if (v < T(0)) return T(-1);
1142 15 : else return T( 0);
1143 : }
1144 :
1145 : template <typename T>
1146 : inline T sgn_impl(const T v, int_type_tag)
1147 : {
1148 : if (v > T(0)) return T(+1);
1149 : else if (v < T(0)) return T(-1);
1150 : else return T( 0);
1151 : }
1152 :
1153 : template <typename T>
1154 485 : inline T and_impl(const T v0, const T v1, real_type_tag)
1155 : {
1156 485 : return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1157 : }
1158 :
1159 : template <typename T>
1160 : inline T and_impl(const T v0, const T v1, int_type_tag)
1161 : {
1162 : return v0 && v1;
1163 : }
1164 :
1165 : template <typename T>
1166 600 : inline T nand_impl(const T v0, const T v1, real_type_tag)
1167 : {
1168 600 : return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1169 : }
1170 :
1171 : template <typename T>
1172 : inline T nand_impl(const T v0, const T v1, int_type_tag)
1173 : {
1174 : return !(v0 && v1);
1175 : }
1176 :
1177 : template <typename T>
1178 440 : inline T or_impl(const T v0, const T v1, real_type_tag)
1179 : {
1180 440 : return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1181 : }
1182 :
1183 : template <typename T>
1184 : inline T or_impl(const T v0, const T v1, int_type_tag)
1185 : {
1186 : return (v0 || v1);
1187 : }
1188 :
1189 : template <typename T>
1190 600 : inline T nor_impl(const T v0, const T v1, real_type_tag)
1191 : {
1192 600 : return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1193 : }
1194 :
1195 : template <typename T>
1196 : inline T nor_impl(const T v0, const T v1, int_type_tag)
1197 : {
1198 : return !(v0 || v1);
1199 : }
1200 :
1201 : template <typename T>
1202 265 : inline T xor_impl(const T v0, const T v1, real_type_tag)
1203 : {
1204 265 : return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1205 : }
1206 :
1207 : template <typename T>
1208 : inline T xor_impl(const T v0, const T v1, int_type_tag)
1209 : {
1210 : return v0 ^ v1;
1211 : }
1212 :
1213 : template <typename T>
1214 80 : inline T xnor_impl(const T v0, const T v1, real_type_tag)
1215 : {
1216 80 : const bool v0_true = is_true_impl(v0);
1217 80 : const bool v1_true = is_true_impl(v1);
1218 :
1219 80 : if ((v0_true && v1_true) || (!v0_true && !v1_true))
1220 40 : return T(1);
1221 : else
1222 40 : return T(0);
1223 : }
1224 :
1225 : template <typename T>
1226 : inline T xnor_impl(const T v0, const T v1, int_type_tag)
1227 : {
1228 : const bool v0_true = is_true_impl(v0);
1229 : const bool v1_true = is_true_impl(v1);
1230 :
1231 : if ((v0_true && v1_true) || (!v0_true && !v1_true))
1232 : return T(1);
1233 : else
1234 : return T(0);
1235 : }
1236 :
1237 : #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1238 : #define exprtk_define_erf(TT, impl) \
1239 : inline TT erf_impl(const TT v) { return impl(v); } \
1240 :
1241 : exprtk_define_erf(float , ::erff)
1242 30000002 : exprtk_define_erf(double , ::erf )
1243 : exprtk_define_erf(long double, ::erfl)
1244 : #undef exprtk_define_erf
1245 : #endif
1246 :
1247 : template <typename T>
1248 30000002 : inline T erf_impl(const T v, real_type_tag)
1249 : {
1250 : #if defined(_MSC_VER) && (_MSC_VER < 1900)
1251 : // Credits: Abramowitz & Stegun Equations 7.1.25-28
1252 : static const T c[] =
1253 : {
1254 : T( 1.26551223), T(1.00002368),
1255 : T( 0.37409196), T(0.09678418),
1256 : T(-0.18628806), T(0.27886807),
1257 : T(-1.13520398), T(1.48851587),
1258 : T(-0.82215223), T(0.17087277)
1259 : };
1260 :
1261 : const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1262 :
1263 : const T result = T(1) - t * std::exp((-v * v) -
1264 : c[0] + t * (c[1] + t *
1265 : (c[2] + t * (c[3] + t *
1266 : (c[4] + t * (c[5] + t *
1267 : (c[6] + t * (c[7] + t *
1268 : (c[8] + t * (c[9]))))))))));
1269 :
1270 : return (v >= T(0)) ? result : -result;
1271 : #else
1272 30000002 : return erf_impl(v);
1273 : #endif
1274 : }
1275 :
1276 : template <typename T>
1277 : inline T erf_impl(const T v, int_type_tag)
1278 : {
1279 : return erf_impl(static_cast<double>(v),real_type_tag());
1280 : }
1281 :
1282 : #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1283 : #define exprtk_define_erfc(TT, impl) \
1284 : inline TT erfc_impl(const TT v) { return impl(v); } \
1285 :
1286 : exprtk_define_erfc(float ,::erfcf)
1287 30000472 : exprtk_define_erfc(double ,::erfc )
1288 : exprtk_define_erfc(long double,::erfcl)
1289 : #undef exprtk_define_erfc
1290 : #endif
1291 :
1292 : template <typename T>
1293 30000472 : inline T erfc_impl(const T v, real_type_tag)
1294 : {
1295 : #if defined(_MSC_VER) && (_MSC_VER < 1900)
1296 : return T(1) - erf_impl(v,real_type_tag());
1297 : #else
1298 30000472 : return erfc_impl(v);
1299 : #endif
1300 : }
1301 :
1302 : template <typename T>
1303 : inline T erfc_impl(const T v, int_type_tag)
1304 : {
1305 : return erfc_impl(static_cast<double>(v),real_type_tag());
1306 : }
1307 :
1308 : template <typename T>
1309 470 : inline T ncdf_impl(const T v, real_type_tag)
1310 : {
1311 470 : return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag());
1312 : }
1313 :
1314 : template <typename T>
1315 : inline T ncdf_impl(const T v, int_type_tag)
1316 : {
1317 : return ncdf_impl(static_cast<double>(v),real_type_tag());
1318 : }
1319 :
1320 : template <typename T>
1321 10 : inline T sinc_impl(const T v, real_type_tag)
1322 : {
1323 10 : if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1324 10 : return(std::sin(v) / v);
1325 : else
1326 0 : return T(1);
1327 : }
1328 :
1329 : template <typename T>
1330 : inline T sinc_impl(const T v, int_type_tag)
1331 : {
1332 : return sinc_impl(static_cast<double>(v),real_type_tag());
1333 : }
1334 :
1335 : #if __cplusplus >= 201103L
1336 : template <typename T>
1337 80 : inline T acosh_impl(const T v, real_type_tag)
1338 : {
1339 80 : return std::acosh(v);
1340 : }
1341 :
1342 : template <typename T>
1343 210 : inline T asinh_impl(const T v, real_type_tag)
1344 : {
1345 210 : return std::asinh(v);
1346 : }
1347 :
1348 : template <typename T>
1349 80 : inline T atanh_impl(const T v, real_type_tag)
1350 : {
1351 80 : return std::atanh(v);
1352 : }
1353 : #else
1354 : template <typename T>
1355 : inline T acosh_impl(const T v, real_type_tag)
1356 : {
1357 : return std::log(v + std::sqrt((v * v) - T(1)));
1358 : }
1359 :
1360 : template <typename T>
1361 : inline T asinh_impl(const T v, real_type_tag)
1362 : {
1363 : return std::log(v + std::sqrt((v * v) + T(1)));
1364 : }
1365 :
1366 : template <typename T>
1367 : inline T atanh_impl(const T v, real_type_tag)
1368 : {
1369 : return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2);
1370 : }
1371 : #endif
1372 :
1373 10 : template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
1374 10 : template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
1375 10 : template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
1376 60 : template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1377 40000697 : template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
1378 15 : template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1379 32 : template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
1380 110 : template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1381 175 : template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
1382 175 : template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1383 10 : template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1384 98767 : template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
1385 0 : template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
1386 144040751 : template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
1387 15 : template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1388 6002428 : template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1389 242 : template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
1390 15 : template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1391 10 : template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1392 10 : template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1393 10 : template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1394 5 : template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1395 95 : template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
1396 5 : template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); }
1397 5 : template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); }
1398 728 : 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)); }
1399 695 : template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1400 25099 : template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
1401 :
1402 1 : template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1403 : template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); }
1404 : template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1405 :
1406 : template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1407 : template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
1408 : template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
1409 : template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1410 : template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1411 : template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
1412 : template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
1413 : template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
1414 : template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
1415 : template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
1416 : template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
1417 : template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1418 : template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
1419 : template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
1420 : template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1421 : template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1422 : template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1423 : template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1424 : template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1425 : template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1426 : template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1427 : template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1428 : template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1429 : template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1430 : template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1431 : template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1432 : template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1433 : template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1434 : template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1435 :
1436 : template <typename T>
1437 88171 : inline bool is_integer_impl(const T& v, real_type_tag)
1438 : {
1439 88171 : return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1440 : }
1441 :
1442 : template <typename T>
1443 : inline bool is_integer_impl(const T&, int_type_tag)
1444 : {
1445 : return true;
1446 : }
1447 : }
1448 :
1449 : template <typename Type>
1450 : struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1451 :
1452 : template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; };
1453 : template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; };
1454 : template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; };
1455 : template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; };
1456 :
1457 : template <typename T>
1458 112698 : inline int to_int32(const T v)
1459 : {
1460 112698 : const typename details::number_type<T>::type num_type;
1461 112698 : return to_int32_impl(v, num_type);
1462 : }
1463 :
1464 : template <typename T>
1465 57228 : inline _int64_t to_int64(const T v)
1466 : {
1467 57228 : const typename details::number_type<T>::type num_type;
1468 57228 : return to_int64_impl(v, num_type);
1469 : }
1470 :
1471 : template <typename T>
1472 32864168 : inline _uint64_t to_uint64(const T v)
1473 : {
1474 32864168 : const typename details::number_type<T>::type num_type;
1475 32864168 : return to_uint64_impl(v, num_type);
1476 : }
1477 :
1478 : template <typename T>
1479 195 : inline bool is_nan(const T v)
1480 : {
1481 195 : const typename details::number_type<T>::type num_type;
1482 195 : return is_nan_impl(v, num_type);
1483 : }
1484 :
1485 : template <typename T>
1486 : inline T min(const T v0, const T v1)
1487 : {
1488 : const typename details::number_type<T>::type num_type;
1489 : return min_impl(v0, v1, num_type);
1490 : }
1491 :
1492 : template <typename T>
1493 : inline T max(const T v0, const T v1)
1494 : {
1495 : const typename details::number_type<T>::type num_type;
1496 : return max_impl(v0, v1, num_type);
1497 : }
1498 :
1499 : template <typename T>
1500 267123 : inline T equal(const T v0, const T v1)
1501 : {
1502 267123 : const typename details::number_type<T>::type num_type;
1503 267123 : return equal_impl(v0, v1, num_type);
1504 : }
1505 :
1506 : template <typename T>
1507 20 : inline T nequal(const T v0, const T v1)
1508 : {
1509 20 : const typename details::number_type<T>::type num_type;
1510 20 : return nequal_impl(v0, v1, num_type);
1511 : }
1512 :
1513 : template <typename T>
1514 118489 : inline T modulus(const T v0, const T v1)
1515 : {
1516 118489 : const typename details::number_type<T>::type num_type;
1517 118489 : return modulus_impl(v0, v1, num_type);
1518 : }
1519 :
1520 : template <typename T>
1521 7664 : inline T pow(const T v0, const T v1)
1522 : {
1523 7664 : const typename details::number_type<T>::type num_type;
1524 7664 : return pow_impl(v0, v1, num_type);
1525 : }
1526 :
1527 : template <typename T>
1528 0 : inline T logn(const T v0, const T v1)
1529 : {
1530 0 : const typename details::number_type<T>::type num_type;
1531 0 : return logn_impl(v0, v1, num_type);
1532 : }
1533 :
1534 : template <typename T>
1535 160 : inline T root(const T v0, const T v1)
1536 : {
1537 160 : const typename details::number_type<T>::type num_type;
1538 160 : return root_impl(v0, v1, num_type);
1539 : }
1540 :
1541 : template <typename T>
1542 120 : inline T roundn(const T v0, const T v1)
1543 : {
1544 120 : const typename details::number_type<T>::type num_type;
1545 240 : return roundn_impl(v0, v1, num_type);
1546 : }
1547 :
1548 : template <typename T>
1549 30 : inline T hypot(const T v0, const T v1)
1550 : {
1551 30 : const typename details::number_type<T>::type num_type;
1552 30 : return hypot_impl(v0, v1, num_type);
1553 : }
1554 :
1555 : template <typename T>
1556 0 : inline T atan2(const T v0, const T v1)
1557 : {
1558 0 : const typename details::number_type<T>::type num_type;
1559 0 : return atan2_impl(v0, v1, num_type);
1560 : }
1561 :
1562 : template <typename T>
1563 0 : inline T shr(const T v0, const T v1)
1564 : {
1565 0 : const typename details::number_type<T>::type num_type;
1566 0 : return shr_impl(v0, v1, num_type);
1567 : }
1568 :
1569 : template <typename T>
1570 0 : inline T shl(const T v0, const T v1)
1571 : {
1572 0 : const typename details::number_type<T>::type num_type;
1573 0 : return shl_impl(v0, v1, num_type);
1574 : }
1575 :
1576 : template <typename T>
1577 485 : inline T and_opr(const T v0, const T v1)
1578 : {
1579 485 : const typename details::number_type<T>::type num_type;
1580 485 : return and_impl(v0, v1, num_type);
1581 : }
1582 :
1583 : template <typename T>
1584 600 : inline T nand_opr(const T v0, const T v1)
1585 : {
1586 600 : const typename details::number_type<T>::type num_type;
1587 600 : return nand_impl(v0, v1, num_type);
1588 : }
1589 :
1590 : template <typename T>
1591 440 : inline T or_opr(const T v0, const T v1)
1592 : {
1593 440 : const typename details::number_type<T>::type num_type;
1594 440 : return or_impl(v0, v1, num_type);
1595 : }
1596 :
1597 : template <typename T>
1598 600 : inline T nor_opr(const T v0, const T v1)
1599 : {
1600 600 : const typename details::number_type<T>::type num_type;
1601 600 : return nor_impl(v0, v1, num_type);
1602 : }
1603 :
1604 : template <typename T>
1605 265 : inline T xor_opr(const T v0, const T v1)
1606 : {
1607 265 : const typename details::number_type<T>::type num_type;
1608 530 : return xor_impl(v0, v1, num_type);
1609 : }
1610 :
1611 : template <typename T>
1612 80 : inline T xnor_opr(const T v0, const T v1)
1613 : {
1614 80 : const typename details::number_type<T>::type num_type;
1615 160 : return xnor_impl(v0, v1, num_type);
1616 : }
1617 :
1618 : template <typename T>
1619 88171 : inline bool is_integer(const T v)
1620 : {
1621 88171 : const typename details::number_type<T>::type num_type;
1622 88171 : return is_integer_impl(v, num_type);
1623 : }
1624 :
1625 : template <typename T, unsigned int N>
1626 : struct fast_exp
1627 : {
1628 6615 : static inline T result(T v)
1629 : {
1630 6615 : unsigned int k = N;
1631 6615 : T l = T(1);
1632 :
1633 35475 : while (k)
1634 : {
1635 28860 : if (1 == (k % 2))
1636 : {
1637 17640 : l *= v;
1638 17640 : --k;
1639 : }
1640 :
1641 28860 : v *= v;
1642 28860 : k /= 2;
1643 : }
1644 :
1645 6615 : return l;
1646 : }
1647 : };
1648 :
1649 3255 : template <typename T> struct fast_exp<T,10> { static inline T result(const T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
1650 4455 : template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } };
1651 10295 : template <typename T> struct fast_exp<T, 8> { static inline T result(const T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
1652 6465 : template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } };
1653 13935 : template <typename T> struct fast_exp<T, 6> { static inline T result(const T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
1654 11730 : template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } };
1655 31507 : template <typename T> struct fast_exp<T, 4> { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } };
1656 24590 : template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } };
1657 241 : template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } };
1658 120 : template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } };
1659 : template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } };
1660 :
1661 : #define exprtk_define_unary_function(FunctionName) \
1662 : template <typename T> \
1663 : inline T FunctionName (const T v) \
1664 : { \
1665 : const typename details::number_type<T>::type num_type; \
1666 : return FunctionName##_impl(v,num_type); \
1667 : } \
1668 :
1669 22177777 : exprtk_define_unary_function(abs )
1670 10 : exprtk_define_unary_function(acos )
1671 80 : exprtk_define_unary_function(acosh)
1672 10 : exprtk_define_unary_function(asin )
1673 210 : exprtk_define_unary_function(asinh)
1674 10 : exprtk_define_unary_function(atan )
1675 80 : exprtk_define_unary_function(atanh)
1676 60 : exprtk_define_unary_function(ceil )
1677 40000697 : exprtk_define_unary_function(cos )
1678 15 : exprtk_define_unary_function(cosh )
1679 32 : exprtk_define_unary_function(exp )
1680 0 : exprtk_define_unary_function(expm1)
1681 110 : exprtk_define_unary_function(floor)
1682 175 : exprtk_define_unary_function(log )
1683 175 : exprtk_define_unary_function(log10)
1684 10 : exprtk_define_unary_function(log2 )
1685 0 : exprtk_define_unary_function(log1p)
1686 98767 : exprtk_define_unary_function(neg )
1687 0 : exprtk_define_unary_function(pos )
1688 60 : exprtk_define_unary_function(round)
1689 144040751 : exprtk_define_unary_function(sin )
1690 10 : exprtk_define_unary_function(sinc )
1691 15 : exprtk_define_unary_function(sinh )
1692 6002428 : exprtk_define_unary_function(sqrt )
1693 242 : exprtk_define_unary_function(tan )
1694 15 : exprtk_define_unary_function(tanh )
1695 10 : exprtk_define_unary_function(cot )
1696 10 : exprtk_define_unary_function(sec )
1697 10 : exprtk_define_unary_function(csc )
1698 5 : exprtk_define_unary_function(r2d )
1699 95 : exprtk_define_unary_function(d2r )
1700 5 : exprtk_define_unary_function(d2g )
1701 5 : exprtk_define_unary_function(g2d )
1702 728 : exprtk_define_unary_function(notl )
1703 153 : exprtk_define_unary_function(sgn )
1704 30000002 : exprtk_define_unary_function(erf )
1705 30000002 : exprtk_define_unary_function(erfc )
1706 470 : exprtk_define_unary_function(ncdf )
1707 695 : exprtk_define_unary_function(frac )
1708 25099 : exprtk_define_unary_function(trunc)
1709 : #undef exprtk_define_unary_function
1710 : }
1711 :
1712 : template <typename T>
1713 2755603 : inline T compute_pow10(T d, const int exponent)
1714 : {
1715 : static const double fract10[] =
1716 : {
1717 : 0.0,
1718 : 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,
1719 : 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,
1720 : 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,
1721 : 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,
1722 : 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,
1723 : 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,
1724 : 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,
1725 : 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,
1726 : 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,
1727 : 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,
1728 : 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,
1729 : 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,
1730 : 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,
1731 : 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,
1732 : 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,
1733 : 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,
1734 : 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,
1735 : 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,
1736 : 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,
1737 : 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,
1738 : 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,
1739 : 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,
1740 : 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,
1741 : 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,
1742 : 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,
1743 : 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,
1744 : 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,
1745 : 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,
1746 : 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,
1747 : 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,
1748 : 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1749 : };
1750 :
1751 : static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1752 :
1753 2755603 : const int e = std::abs(exponent);
1754 :
1755 2755603 : if (exponent >= std::numeric_limits<T>::min_exponent10)
1756 : {
1757 2755597 : if (e < fract10_size)
1758 : {
1759 2755597 : if (exponent > 0)
1760 1764 : return T(d * fract10[e]);
1761 : else
1762 2753833 : return T(d / fract10[e]);
1763 : }
1764 : else
1765 0 : return T(d * std::pow(10.0, 10.0 * exponent));
1766 : }
1767 : else
1768 : {
1769 6 : d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1770 6 : return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1771 : }
1772 : }
1773 :
1774 : template <typename Iterator, typename T>
1775 2028 : inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1776 : {
1777 2028 : if (itr == end)
1778 0 : return false;
1779 :
1780 2028 : const bool negative = ('-' == (*itr));
1781 :
1782 2028 : if (negative || ('+' == (*itr)))
1783 : {
1784 1706 : if (end == ++itr)
1785 14 : return false;
1786 : }
1787 :
1788 : static const uchar_t zero = static_cast<uchar_t>('0');
1789 :
1790 2340 : while ((end != itr) && (zero == (*itr))) ++itr;
1791 :
1792 2014 : bool return_result = true;
1793 2014 : unsigned int digit = 0;
1794 2014 : const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1795 :
1796 2014 : if (length <= 4)
1797 : {
1798 2014 : switch (length)
1799 : {
1800 : #ifdef exprtk_use_lut
1801 :
1802 : #define exprtk_process_digit \
1803 : if ((digit = details::digit_table[(int)*itr++]) < 10) \
1804 : result = result * 10 + (digit); \
1805 : else \
1806 : { \
1807 : return_result = false; \
1808 : break; \
1809 : } \
1810 : exprtk_fallthrough \
1811 :
1812 : #else
1813 :
1814 : #define exprtk_process_digit \
1815 : if ((digit = (*itr++ - zero)) < 10) \
1816 : result = result * T(10) + digit; \
1817 : else \
1818 : { \
1819 : return_result = false; \
1820 : break; \
1821 : } \
1822 : exprtk_fallthrough \
1823 :
1824 : #endif
1825 :
1826 0 : case 4 : exprtk_process_digit
1827 12 : case 3 : exprtk_process_digit
1828 38 : case 2 : exprtk_process_digit
1829 1850 : case 1 : if ((digit = (*itr - zero))>= 10)
1830 : {
1831 0 : digit = 0;
1832 0 : return_result = false;
1833 : }
1834 :
1835 : #undef exprtk_process_digit
1836 : }
1837 : }
1838 : else
1839 0 : return_result = false;
1840 :
1841 2014 : if (length && return_result)
1842 : {
1843 1850 : result = result * 10 + static_cast<T>(digit);
1844 1850 : ++itr;
1845 : }
1846 :
1847 2014 : result = negative ? -result : result;
1848 2014 : return return_result;
1849 : }
1850 :
1851 : template <typename Iterator, typename T>
1852 0 : static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1853 : {
1854 : typedef typename std::iterator_traits<Iterator>::value_type type;
1855 :
1856 : static const std::size_t nan_length = 3;
1857 :
1858 0 : if (std::distance(itr,end) != static_cast<int>(nan_length))
1859 0 : return false;
1860 :
1861 0 : if (static_cast<type>('n') == (*itr))
1862 : {
1863 0 : if (
1864 0 : (static_cast<type>('a') != *(itr + 1)) ||
1865 0 : (static_cast<type>('n') != *(itr + 2))
1866 : )
1867 : {
1868 0 : return false;
1869 : }
1870 : }
1871 0 : else if (
1872 0 : (static_cast<type>('A') != *(itr + 1)) ||
1873 0 : (static_cast<type>('N') != *(itr + 2))
1874 : )
1875 : {
1876 0 : return false;
1877 : }
1878 :
1879 0 : t = std::numeric_limits<T>::quiet_NaN();
1880 :
1881 0 : return true;
1882 : }
1883 :
1884 : template <typename Iterator, typename T>
1885 0 : static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative)
1886 : {
1887 : static const char_t inf_uc[] = "INFINITY";
1888 : static const char_t inf_lc[] = "infinity";
1889 : static const std::size_t inf_length = 8;
1890 :
1891 0 : const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1892 :
1893 0 : if ((3 != length) && (inf_length != length))
1894 0 : return false;
1895 :
1896 0 : char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1897 :
1898 0 : while (end != itr)
1899 : {
1900 0 : if (*inf_itr == static_cast<char_t>(*itr))
1901 : {
1902 0 : ++itr;
1903 0 : ++inf_itr;
1904 0 : continue;
1905 : }
1906 : else
1907 0 : return false;
1908 : }
1909 :
1910 0 : if (negative)
1911 0 : t = -std::numeric_limits<T>::infinity();
1912 : else
1913 0 : t = std::numeric_limits<T>::infinity();
1914 :
1915 0 : return true;
1916 : }
1917 :
1918 : template <typename T>
1919 6604807 : inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
1920 : {
1921 : using namespace details::numeric;
1922 6604807 : return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
1923 : }
1924 :
1925 : template <typename Iterator, typename T>
1926 3851068 : inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1927 : {
1928 3851068 : if (end == itr_external) return false;
1929 :
1930 3851068 : Iterator itr = itr_external;
1931 :
1932 3851068 : T d = T(0);
1933 :
1934 3851068 : const bool negative = ('-' == (*itr));
1935 :
1936 3851068 : if (negative || '+' == (*itr))
1937 : {
1938 0 : if (end == ++itr)
1939 0 : return false;
1940 : }
1941 :
1942 3851068 : bool instate = false;
1943 :
1944 : static const char_t zero = static_cast<uchar_t>('0');
1945 :
1946 : #define parse_digit_1(d) \
1947 : if ((digit = (*itr - zero)) < 10) \
1948 : { d = d * T(10) + digit; } \
1949 : else \
1950 : { break; } \
1951 : if (end == ++itr) break; \
1952 :
1953 : #define parse_digit_2(d) \
1954 : if ((digit = (*itr - zero)) < 10) \
1955 : { d = d * T(10) + digit; } \
1956 : else \
1957 : { break; } \
1958 : ++itr; \
1959 :
1960 3851068 : if ('.' != (*itr))
1961 : {
1962 3850805 : const Iterator curr = itr;
1963 :
1964 10690401 : while ((end != itr) && (zero == (*itr))) ++itr;
1965 :
1966 4041815 : while (end != itr)
1967 : {
1968 : unsigned int digit;
1969 3971737 : parse_digit_1(d)
1970 2708107 : parse_digit_1(d)
1971 358151 : parse_digit_2(d)
1972 : }
1973 :
1974 3850805 : if (curr != itr) instate = true;
1975 : }
1976 :
1977 3851068 : int exponent = 0;
1978 :
1979 3851068 : if (end != itr)
1980 : {
1981 2755161 : if ('.' == (*itr))
1982 : {
1983 2754947 : const Iterator curr = ++itr;
1984 2754947 : T tmp_d = T(0);
1985 :
1986 8918259 : while (end != itr)
1987 : {
1988 : unsigned int digit;
1989 6846005 : parse_digit_1(tmp_d)
1990 6406994 : parse_digit_1(tmp_d)
1991 6163406 : parse_digit_2(tmp_d)
1992 : }
1993 :
1994 2754947 : if (curr != itr)
1995 : {
1996 2753753 : instate = true;
1997 :
1998 2753753 : const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
1999 :
2000 2753753 : if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
2001 0 : return false;
2002 :
2003 2753753 : d += compute_pow10(tmp_d, frac_exponent);
2004 : }
2005 :
2006 : #undef parse_digit_1
2007 : #undef parse_digit_2
2008 : }
2009 :
2010 2755161 : if (end != itr)
2011 : {
2012 2028 : typename std::iterator_traits<Iterator>::value_type c = (*itr);
2013 :
2014 2028 : if (('e' == c) || ('E' == c))
2015 : {
2016 2028 : int exp = 0;
2017 :
2018 2028 : if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
2019 : {
2020 14 : if (end == itr)
2021 14 : return false;
2022 : else
2023 0 : c = (*itr);
2024 : }
2025 :
2026 2014 : exponent += exp;
2027 : }
2028 :
2029 2014 : if (end != itr)
2030 : {
2031 0 : if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
2032 0 : ++itr;
2033 0 : else if ('#' == c)
2034 : {
2035 0 : if (end == ++itr)
2036 0 : return false;
2037 0 : else if (('I' <= (*itr)) && ((*itr) <= 'n'))
2038 : {
2039 0 : if (('i' == (*itr)) || ('I' == (*itr)))
2040 : {
2041 0 : return parse_inf(itr, end, t, negative);
2042 : }
2043 0 : else if (('n' == (*itr)) || ('N' == (*itr)))
2044 : {
2045 0 : return parse_nan(itr, end, t);
2046 : }
2047 : else
2048 0 : return false;
2049 : }
2050 : else
2051 0 : return false;
2052 : }
2053 0 : else if (('I' <= (*itr)) && ((*itr) <= 'n'))
2054 : {
2055 0 : if (('i' == (*itr)) || ('I' == (*itr)))
2056 : {
2057 0 : return parse_inf(itr, end, t, negative);
2058 : }
2059 0 : else if (('n' == (*itr)) || ('N' == (*itr)))
2060 : {
2061 0 : return parse_nan(itr, end, t);
2062 : }
2063 : else
2064 0 : return false;
2065 : }
2066 : else
2067 0 : return false;
2068 : }
2069 : }
2070 : }
2071 :
2072 3851054 : if ((end != itr) || (!instate))
2073 0 : return false;
2074 3851054 : else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
2075 0 : return false;
2076 3851054 : else if (exponent)
2077 1850 : d = compute_pow10(d,exponent);
2078 :
2079 3851054 : t = static_cast<T>((negative) ? -d : d);
2080 3851054 : return true;
2081 : }
2082 :
2083 : template <typename T>
2084 3851068 : inline bool string_to_real(const std::string& s, T& t)
2085 : {
2086 3851068 : const typename numeric::details::number_type<T>::type num_type;
2087 :
2088 3851068 : char_cptr begin = s.data();
2089 3851068 : char_cptr end = s.data() + s.size();
2090 :
2091 7702136 : return string_to_real(begin, end, t, num_type);
2092 : }
2093 :
2094 : template <typename T>
2095 : struct functor_t
2096 : {
2097 : /*
2098 : Note: The following definitions for Type, may require tweaking
2099 : based on the compiler and target architecture. The benchmark
2100 : should provide enough information to make the right choice.
2101 : */
2102 : //typedef T Type;
2103 : //typedef const T Type;
2104 : typedef const T& Type;
2105 : typedef T& RefType;
2106 : typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2107 : typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2108 : typedef T (*bfunc_t)(Type t0, Type t1);
2109 : typedef T (*ufunc_t)(Type t0);
2110 : };
2111 :
2112 : } // namespace details
2113 :
2114 : struct loop_runtime_check
2115 : {
2116 : enum loop_types
2117 : {
2118 : e_invalid = 0,
2119 : e_for_loop = 1,
2120 : e_while_loop = 2,
2121 : e_repeat_until_loop = 4,
2122 : e_all_loops = 7
2123 : };
2124 :
2125 : enum violation_type
2126 : {
2127 : e_unknown = 0,
2128 : e_iteration_count = 1,
2129 : e_timeout = 2
2130 : };
2131 :
2132 : loop_types loop_set;
2133 :
2134 : loop_runtime_check()
2135 : : loop_set(e_invalid)
2136 : , max_loop_iterations(0)
2137 : {}
2138 :
2139 : details::_uint64_t max_loop_iterations;
2140 :
2141 : struct violation_context
2142 : {
2143 : loop_types loop;
2144 : violation_type violation;
2145 : details::_uint64_t iteration_count;
2146 : };
2147 :
2148 : virtual bool check()
2149 : {
2150 : return true;
2151 : }
2152 :
2153 : virtual void handle_runtime_violation(const violation_context&)
2154 : {
2155 : throw std::runtime_error("ExprTk Loop runtime violation.");
2156 : }
2157 :
2158 : virtual ~loop_runtime_check()
2159 : {}
2160 : };
2161 :
2162 : typedef loop_runtime_check* loop_runtime_check_ptr;
2163 :
2164 : struct vector_access_runtime_check
2165 : {
2166 : struct violation_context
2167 : {
2168 : void* base_ptr;
2169 : void* end_ptr;
2170 : void* access_ptr;
2171 : std::size_t type_size;
2172 : };
2173 :
2174 70 : virtual ~vector_access_runtime_check()
2175 70 : {}
2176 :
2177 0 : virtual bool handle_runtime_violation(violation_context& /*context*/)
2178 : {
2179 0 : throw std::runtime_error("ExprTk runtime vector access violation.");
2180 : #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
2181 : return false;
2182 : #endif
2183 : }
2184 : };
2185 :
2186 : typedef vector_access_runtime_check* vector_access_runtime_check_ptr;
2187 :
2188 : struct assert_check
2189 : {
2190 : struct assert_context
2191 : {
2192 : std::string condition;
2193 : std::string message;
2194 : std::string id;
2195 : std::size_t offet;
2196 : };
2197 :
2198 54 : virtual ~assert_check()
2199 54 : {}
2200 :
2201 0 : virtual void handle_assert(const assert_context& /*context*/)
2202 : {
2203 0 : }
2204 : };
2205 :
2206 : typedef assert_check* assert_check_ptr;
2207 :
2208 : struct compilation_check
2209 : {
2210 : struct compilation_context
2211 : {
2212 : std::string error_message;
2213 : };
2214 :
2215 : virtual bool continue_compilation(compilation_context& /*context*/) = 0;
2216 :
2217 : virtual ~compilation_check()
2218 : {}
2219 : };
2220 :
2221 : typedef compilation_check* compilation_check_ptr;
2222 :
2223 : namespace lexer
2224 : {
2225 : struct token
2226 : {
2227 : enum token_type
2228 : {
2229 : e_none = 0, e_error = 1, e_err_symbol = 2,
2230 : e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
2231 : e_eof = 6, e_number = 7, e_symbol = 8,
2232 : e_string = 9, e_assign = 10, e_addass = 11,
2233 : e_subass = 12, e_mulass = 13, e_divass = 14,
2234 : e_modass = 15, e_shr = 16, e_shl = 17,
2235 : e_lte = 18, e_ne = 19, e_gte = 20,
2236 : e_swap = 21, e_lt = '<', e_gt = '>',
2237 : e_eq = '=', e_rbracket = ')', e_lbracket = '(',
2238 : e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
2239 : e_lcrlbracket = '{', e_comma = ',', e_add = '+',
2240 : e_sub = '-', e_div = '/', e_mul = '*',
2241 : e_mod = '%', e_pow = '^', e_colon = ':',
2242 : e_ternary = '?'
2243 : };
2244 :
2245 129155035 : token()
2246 129155035 : : type(e_none)
2247 258310070 : , value("")
2248 129155035 : , position(std::numeric_limits<std::size_t>::max())
2249 129155035 : {}
2250 :
2251 379883 : void clear()
2252 : {
2253 379883 : type = e_none;
2254 379883 : value = "";
2255 379883 : position = std::numeric_limits<std::size_t>::max();
2256 379883 : }
2257 :
2258 : template <typename Iterator>
2259 10933167 : inline token& set_operator(const token_type tt,
2260 : const Iterator begin, const Iterator end,
2261 : const Iterator base_begin = Iterator(0))
2262 : {
2263 10933167 : type = tt;
2264 10933167 : value.assign(begin,end);
2265 10933167 : if (base_begin)
2266 10933167 : position = static_cast<std::size_t>(std::distance(base_begin,begin));
2267 10933167 : return (*this);
2268 : }
2269 :
2270 : template <typename Iterator>
2271 3335950 : inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2272 : {
2273 3335950 : type = e_symbol;
2274 3335950 : value.assign(begin,end);
2275 3335950 : if (base_begin)
2276 3335950 : position = static_cast<std::size_t>(std::distance(base_begin,begin));
2277 3335950 : return (*this);
2278 : }
2279 :
2280 : template <typename Iterator>
2281 2040016 : inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2282 : {
2283 2040016 : type = e_number;
2284 2040016 : value.assign(begin,end);
2285 2040016 : if (base_begin)
2286 2040016 : position = static_cast<std::size_t>(std::distance(base_begin,begin));
2287 2040016 : return (*this);
2288 : }
2289 :
2290 : template <typename Iterator>
2291 51555 : inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2292 : {
2293 51555 : type = e_string;
2294 51555 : value.assign(begin,end);
2295 51555 : if (base_begin)
2296 51555 : position = static_cast<std::size_t>(std::distance(base_begin,begin));
2297 51555 : return (*this);
2298 : }
2299 :
2300 1350 : inline token& set_string(const std::string& s, const std::size_t p)
2301 : {
2302 1350 : type = e_string;
2303 1350 : value = s;
2304 1350 : position = p;
2305 1350 : return (*this);
2306 : }
2307 :
2308 : template <typename Iterator>
2309 788 : inline token& set_error(const token_type et,
2310 : const Iterator begin, const Iterator end,
2311 : const Iterator base_begin = Iterator(0))
2312 : {
2313 788 : if (
2314 297 : (e_error == et) ||
2315 297 : (e_err_symbol == et) ||
2316 237 : (e_err_number == et) ||
2317 0 : (e_err_string == et) ||
2318 : (e_err_sfunc == et)
2319 : )
2320 : {
2321 788 : type = et;
2322 : }
2323 : else
2324 0 : type = e_error;
2325 :
2326 788 : value.assign(begin,end);
2327 :
2328 788 : if (base_begin)
2329 788 : position = static_cast<std::size_t>(std::distance(base_begin,begin));
2330 :
2331 788 : return (*this);
2332 : }
2333 :
2334 0 : static inline std::string to_str(token_type t)
2335 : {
2336 0 : switch (t)
2337 : {
2338 0 : case e_none : return "NONE";
2339 0 : case e_error : return "ERROR";
2340 0 : case e_err_symbol : return "ERROR_SYMBOL";
2341 0 : case e_err_number : return "ERROR_NUMBER";
2342 0 : case e_err_string : return "ERROR_STRING";
2343 0 : case e_eof : return "EOF";
2344 0 : case e_number : return "NUMBER";
2345 0 : case e_symbol : return "SYMBOL";
2346 0 : case e_string : return "STRING";
2347 0 : case e_assign : return ":=";
2348 0 : case e_addass : return "+=";
2349 0 : case e_subass : return "-=";
2350 0 : case e_mulass : return "*=";
2351 0 : case e_divass : return "/=";
2352 0 : case e_modass : return "%=";
2353 0 : case e_shr : return ">>";
2354 0 : case e_shl : return "<<";
2355 0 : case e_lte : return "<=";
2356 0 : case e_ne : return "!=";
2357 0 : case e_gte : return ">=";
2358 0 : case e_lt : return "<";
2359 0 : case e_gt : return ">";
2360 0 : case e_eq : return "=";
2361 0 : case e_rbracket : return ")";
2362 0 : case e_lbracket : return "(";
2363 0 : case e_rsqrbracket : return "]";
2364 0 : case e_lsqrbracket : return "[";
2365 0 : case e_rcrlbracket : return "}";
2366 0 : case e_lcrlbracket : return "{";
2367 0 : case e_comma : return ",";
2368 0 : case e_add : return "+";
2369 0 : case e_sub : return "-";
2370 0 : case e_div : return "/";
2371 0 : case e_mul : return "*";
2372 0 : case e_mod : return "%";
2373 0 : case e_pow : return "^";
2374 0 : case e_colon : return ":";
2375 0 : case e_ternary : return "?";
2376 0 : case e_swap : return "<=>";
2377 0 : default : return "UNKNOWN";
2378 : }
2379 : }
2380 :
2381 17142531 : inline bool is_error() const
2382 : {
2383 : return (
2384 34284080 : (e_error == type) ||
2385 17141549 : (e_err_symbol == type) ||
2386 17141549 : (e_err_number == type) ||
2387 51425035 : (e_err_string == type) ||
2388 17140955 : (e_err_sfunc == type)
2389 17142531 : );
2390 : }
2391 :
2392 : token_type type;
2393 : std::string value;
2394 : std::size_t position;
2395 : };
2396 :
2397 : class generator
2398 : {
2399 : public:
2400 :
2401 : typedef token token_t;
2402 : typedef std::vector<token_t> token_list_t;
2403 : typedef token_list_t::iterator token_list_itr_t;
2404 : typedef details::char_t char_t;
2405 :
2406 108660 : generator()
2407 217320 : : base_itr_(0)
2408 108660 : , s_itr_ (0)
2409 108660 : , s_end_ (0)
2410 : {
2411 108660 : clear();
2412 108660 : }
2413 :
2414 108660 : inline void clear()
2415 : {
2416 108660 : base_itr_ = 0;
2417 108660 : s_itr_ = 0;
2418 108660 : s_end_ = 0;
2419 108660 : token_list_.clear();
2420 108660 : token_itr_ = token_list_.end();
2421 108660 : store_token_itr_ = token_list_.end();
2422 108660 : }
2423 :
2424 380686 : inline bool process(const std::string& str)
2425 : {
2426 380686 : base_itr_ = str.data();
2427 380686 : s_itr_ = str.data();
2428 380686 : s_end_ = str.data() + str.size();
2429 :
2430 380686 : eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_);
2431 380686 : token_list_.clear();
2432 :
2433 17447223 : while (!is_end(s_itr_))
2434 : {
2435 17067325 : scan_token();
2436 :
2437 17067325 : if (!token_list_.empty() && token_list_.back().is_error())
2438 788 : return false;
2439 : }
2440 :
2441 379898 : return true;
2442 : }
2443 :
2444 379898 : inline bool empty() const
2445 : {
2446 379898 : return token_list_.empty();
2447 : }
2448 :
2449 78215 : inline std::size_t size() const
2450 : {
2451 78215 : return token_list_.size();
2452 : }
2453 :
2454 750056 : inline void begin()
2455 : {
2456 750056 : token_itr_ = token_list_.begin();
2457 750056 : store_token_itr_ = token_list_.begin();
2458 750056 : }
2459 :
2460 : inline void store()
2461 : {
2462 : store_token_itr_ = token_itr_;
2463 : }
2464 :
2465 : inline void restore()
2466 : {
2467 : token_itr_ = store_token_itr_;
2468 : }
2469 :
2470 13552170 : inline token_t& next_token()
2471 : {
2472 13552170 : if (token_list_.end() != token_itr_)
2473 : {
2474 13201971 : return *token_itr_++;
2475 : }
2476 : else
2477 350199 : return eof_token_;
2478 : }
2479 :
2480 5806079 : inline token_t& peek_next_token()
2481 : {
2482 5806079 : if (token_list_.end() != token_itr_)
2483 : {
2484 5772425 : return *token_itr_;
2485 : }
2486 : else
2487 33654 : return eof_token_;
2488 : }
2489 :
2490 108233665 : inline token_t& operator[](const std::size_t& index)
2491 : {
2492 108233665 : if (index < token_list_.size())
2493 : {
2494 108233665 : return token_list_[index];
2495 : }
2496 : else
2497 0 : return eof_token_;
2498 : }
2499 :
2500 : inline token_t operator[](const std::size_t& index) const
2501 : {
2502 : if (index < token_list_.size())
2503 : {
2504 : return token_list_[index];
2505 : }
2506 : else
2507 : return eof_token_;
2508 : }
2509 :
2510 421620 : inline bool finished() const
2511 : {
2512 421620 : return (token_list_.end() == token_itr_);
2513 : }
2514 :
2515 4626 : inline void insert_front(token_t::token_type tk_type)
2516 : {
2517 4626 : if (
2518 9252 : !token_list_.empty() &&
2519 9252 : (token_list_.end() != token_itr_)
2520 : )
2521 : {
2522 4626 : token_t t = *token_itr_;
2523 :
2524 4626 : t.type = tk_type;
2525 4626 : token_itr_ = token_list_.insert(token_itr_,t);
2526 4626 : }
2527 4626 : }
2528 :
2529 434919 : inline std::string substr(const std::size_t& begin, const std::size_t& end) const
2530 : {
2531 434919 : const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2532 434919 : const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_;
2533 :
2534 869838 : return std::string(begin_itr,end_itr);
2535 : }
2536 :
2537 : inline std::string remaining() const
2538 : {
2539 : if (finished())
2540 : return "";
2541 : else if (token_list_.begin() != token_itr_)
2542 : return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2543 : else
2544 : return std::string(base_itr_ + token_itr_->position, s_end_);
2545 : }
2546 :
2547 : private:
2548 :
2549 85253906 : inline bool is_end(details::char_cptr itr) const
2550 : {
2551 85253906 : return (s_end_ == itr);
2552 : }
2553 :
2554 : #ifndef exprtk_disable_comments
2555 15982420 : inline bool is_comment_start(details::char_cptr itr) const
2556 : {
2557 15982420 : const char_t c0 = *(itr + 0);
2558 15982420 : const char_t c1 = *(itr + 1);
2559 :
2560 15982420 : if ('#' == c0)
2561 243 : return true;
2562 15982177 : else if (!is_end(itr + 1))
2563 : {
2564 15634544 : if (('/' == c0) && ('/' == c1)) return true;
2565 15634524 : if (('/' == c0) && ('*' == c1)) return true;
2566 : }
2567 15982123 : return false;
2568 : }
2569 : #else
2570 : inline bool is_comment_start(details::char_cptr) const
2571 : {
2572 : return false;
2573 : }
2574 : #endif
2575 :
2576 1084905 : inline void skip_whitespace()
2577 : {
2578 2420251 : while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2579 : {
2580 1335346 : ++s_itr_;
2581 : }
2582 1084905 : }
2583 :
2584 297 : inline void skip_comments()
2585 : {
2586 : #ifndef exprtk_disable_comments
2587 : // The following comment styles are supported:
2588 : // 1. // .... \n
2589 : // 2. # .... \n
2590 : // 3. /* .... */
2591 : struct test
2592 : {
2593 297 : static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2594 : {
2595 297 : mode = 0;
2596 297 : if ('#' == c0) { mode = 1; incr = 1; }
2597 54 : else if ('/' == c0)
2598 : {
2599 54 : if ('/' == c1) { mode = 1; incr = 2; }
2600 34 : else if ('*' == c1) { mode = 2; incr = 2; }
2601 : }
2602 297 : return (0 != mode);
2603 : }
2604 :
2605 31112 : static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2606 : {
2607 31112 : if (
2608 31112 : ((1 == mode) && ('\n' == c0)) ||
2609 31106 : ((2 == mode) && ( '*' == c0) && ('/' == c1))
2610 : )
2611 : {
2612 23 : mode = 0;
2613 23 : return true;
2614 : }
2615 : else
2616 31089 : return false;
2617 : }
2618 : };
2619 :
2620 297 : int mode = 0;
2621 297 : int increment = 0;
2622 :
2623 297 : if (is_end(s_itr_))
2624 23 : return;
2625 297 : else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2626 0 : return;
2627 :
2628 297 : details::char_cptr cmt_start = s_itr_;
2629 :
2630 297 : s_itr_ += increment;
2631 :
2632 31403 : while (!is_end(s_itr_))
2633 : {
2634 31129 : if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2635 : {
2636 6 : ++s_itr_;
2637 6 : return;
2638 : }
2639 :
2640 31123 : if ((2 == mode))
2641 : {
2642 1664 : if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2643 : {
2644 17 : s_itr_ += 2;
2645 17 : return;
2646 : }
2647 : }
2648 :
2649 31106 : ++s_itr_;
2650 : }
2651 :
2652 274 : if (2 == mode)
2653 : {
2654 17 : token_t t;
2655 17 : t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2656 17 : token_list_.push_back(t);
2657 17 : }
2658 : #endif
2659 : }
2660 :
2661 236 : inline bool next_is_digit(const details::char_cptr itr) const
2662 : {
2663 472 : return ((itr + 1) != s_end_) &&
2664 472 : details::is_digit(*(itr + 1));
2665 : }
2666 :
2667 17067325 : inline void scan_token()
2668 : {
2669 17067325 : const char_t c = *s_itr_;
2670 :
2671 17067325 : if (details::is_whitespace(c))
2672 : {
2673 1084905 : skip_whitespace();
2674 1084905 : return;
2675 : }
2676 15982420 : else if (is_comment_start(s_itr_))
2677 : {
2678 297 : skip_comments();
2679 297 : return;
2680 : }
2681 15982123 : else if (details::is_operator_char(c))
2682 : {
2683 10553558 : scan_operator();
2684 10553558 : return;
2685 : }
2686 5428565 : else if (details::is_letter(c))
2687 : {
2688 3316561 : scan_symbol();
2689 3316561 : return;
2690 : }
2691 2112004 : else if (('.' == c) && !next_is_digit(s_itr_))
2692 : {
2693 0 : scan_operator();
2694 0 : return;
2695 : }
2696 2112004 : else if (details::is_digit(c) || ('.' == c))
2697 : {
2698 2040076 : scan_number();
2699 2040076 : return;
2700 : }
2701 71928 : else if ('$' == c)
2702 : {
2703 4245 : scan_special_function();
2704 4245 : return;
2705 : }
2706 : #ifndef exprtk_disable_string_capabilities
2707 67683 : else if ('\'' == c)
2708 : {
2709 53142 : scan_string();
2710 53142 : return;
2711 : }
2712 : #endif
2713 14541 : else if ('~' == c)
2714 : {
2715 14067 : token_t t;
2716 14067 : t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2717 14067 : token_list_.push_back(t);
2718 14067 : ++s_itr_;
2719 14067 : return;
2720 14067 : }
2721 : else
2722 : {
2723 474 : token_t t;
2724 474 : t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2725 474 : token_list_.push_back(t);
2726 474 : ++s_itr_;
2727 474 : }
2728 : }
2729 :
2730 10553558 : inline void scan_operator()
2731 : {
2732 10553558 : token_t t;
2733 :
2734 10553558 : const char_t c0 = s_itr_[0];
2735 :
2736 10553558 : if (!is_end(s_itr_ + 1))
2737 : {
2738 10229345 : const char_t c1 = s_itr_[1];
2739 :
2740 10229345 : if (!is_end(s_itr_ + 2))
2741 : {
2742 9965063 : const char_t c2 = s_itr_[2];
2743 :
2744 9965063 : if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2745 : {
2746 2728 : t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2747 2728 : token_list_.push_back(t);
2748 2728 : s_itr_ += 3;
2749 2728 : return;
2750 : }
2751 : }
2752 :
2753 10226617 : token_t::token_type ttype = token_t::e_none;
2754 :
2755 10226617 : if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2756 10224401 : else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2757 10223721 : else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2758 10223631 : else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2759 10220676 : else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2760 10158003 : else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2761 10066697 : else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2762 10066697 : else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2763 10066697 : else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2764 10056602 : else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2765 10055550 : else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2766 10055210 : else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2767 10054873 : else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2768 :
2769 10226617 : if (token_t::e_none != ttype)
2770 : {
2771 171819 : t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2772 171819 : token_list_.push_back(t);
2773 171819 : s_itr_ += 2;
2774 171819 : return;
2775 : }
2776 : }
2777 :
2778 10379011 : if ('<' == c0)
2779 7467 : t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2780 10371544 : else if ('>' == c0)
2781 6963 : t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2782 10364581 : else if (';' == c0)
2783 124270 : t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2784 10240311 : else if ('&' == c0)
2785 657 : t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2786 10239654 : else if ('|' == c0)
2787 420 : t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2788 : else
2789 10239234 : t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2790 :
2791 10379011 : token_list_.push_back(t);
2792 10379011 : ++s_itr_;
2793 10553558 : }
2794 :
2795 3316561 : inline void scan_symbol()
2796 : {
2797 3316561 : details::char_cptr initial_itr = s_itr_;
2798 :
2799 9077959 : while (!is_end(s_itr_))
2800 : {
2801 9065759 : if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2802 : {
2803 3305881 : if ('.' != (*s_itr_))
2804 3304361 : break;
2805 : /*
2806 : Permit symbols that contain a 'dot'
2807 : Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2808 : Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2809 : */
2810 1520 : if (
2811 3040 : (s_itr_ != initial_itr) &&
2812 1520 : !is_end(s_itr_ + 1) &&
2813 3040 : !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2814 0 : ('_' != (*(s_itr_ + 1)))
2815 : )
2816 0 : break;
2817 : }
2818 :
2819 5761398 : ++s_itr_;
2820 : }
2821 :
2822 3316561 : token_t t;
2823 3316561 : t.set_symbol(initial_itr, s_itr_, base_itr_);
2824 3316561 : token_list_.push_back(t);
2825 3316561 : }
2826 :
2827 2040076 : inline void scan_number()
2828 : {
2829 : /*
2830 : Attempt to match a valid numeric value in one of the following formats:
2831 : (01) 123456
2832 : (02) 123456.
2833 : (03) 123.456
2834 : (04) 123.456e3
2835 : (05) 123.456E3
2836 : (06) 123.456e+3
2837 : (07) 123.456E+3
2838 : (08) 123.456e-3
2839 : (09) 123.456E-3
2840 : (00) .1234
2841 : (11) .1234e3
2842 : (12) .1234E+3
2843 : (13) .1234e+3
2844 : (14) .1234E-3
2845 : (15) .1234e-3
2846 : */
2847 :
2848 2040076 : details::char_cptr initial_itr = s_itr_;
2849 2040076 : bool dot_found = false;
2850 2040076 : bool e_found = false;
2851 2040076 : bool post_e_sign_found = false;
2852 2040076 : bool post_e_digit_found = false;
2853 2040076 : token_t t;
2854 :
2855 19064804 : while (!is_end(s_itr_))
2856 : {
2857 19049145 : if ('.' == (*s_itr_))
2858 : {
2859 1464717 : if (dot_found)
2860 : {
2861 0 : t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2862 0 : token_list_.push_back(t);
2863 :
2864 0 : return;
2865 : }
2866 :
2867 1464717 : dot_found = true;
2868 1464717 : ++s_itr_;
2869 :
2870 1464717 : continue;
2871 : }
2872 17584428 : else if ('e' == std::tolower(*s_itr_))
2873 : {
2874 1095 : const char_t& c = *(s_itr_ + 1);
2875 :
2876 1095 : if (is_end(s_itr_ + 1))
2877 : {
2878 0 : t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2879 0 : token_list_.push_back(t);
2880 :
2881 0 : return;
2882 : }
2883 1095 : else if (
2884 1383 : ('+' != c) &&
2885 1330 : ('-' != c) &&
2886 235 : !details::is_digit(c)
2887 : )
2888 : {
2889 60 : t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2890 60 : token_list_.push_back(t);
2891 :
2892 60 : return;
2893 : }
2894 :
2895 1035 : e_found = true;
2896 1035 : ++s_itr_;
2897 :
2898 1035 : continue;
2899 1035 : }
2900 17583333 : else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2901 : {
2902 860 : if (post_e_sign_found)
2903 : {
2904 0 : t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2905 0 : token_list_.push_back(t);
2906 :
2907 0 : return;
2908 : }
2909 :
2910 860 : post_e_sign_found = true;
2911 860 : ++s_itr_;
2912 :
2913 860 : continue;
2914 : }
2915 17582473 : else if (e_found && details::is_digit(*s_itr_))
2916 : {
2917 1133 : post_e_digit_found = true;
2918 1133 : ++s_itr_;
2919 :
2920 1133 : continue;
2921 : }
2922 17581340 : else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2923 2024357 : break;
2924 : else
2925 15556983 : ++s_itr_;
2926 : }
2927 :
2928 2040016 : t.set_numeric(initial_itr, s_itr_, base_itr_);
2929 2040016 : token_list_.push_back(t);
2930 :
2931 2040016 : return;
2932 2040076 : }
2933 :
2934 4245 : inline void scan_special_function()
2935 : {
2936 4245 : details::char_cptr initial_itr = s_itr_;
2937 4245 : token_t t;
2938 :
2939 : // $fdd(x,x,x) = at least 11 chars
2940 8490 : if (std::distance(s_itr_,s_end_) < 11)
2941 : {
2942 0 : t.set_error(
2943 : token::e_err_sfunc,
2944 0 : initial_itr, std::min(initial_itr + 11, s_end_),
2945 : base_itr_);
2946 0 : token_list_.push_back(t);
2947 :
2948 0 : return;
2949 : }
2950 :
2951 4245 : if (
2952 8490 : !(('$' == *s_itr_) &&
2953 4245 : (details::imatch ('f',*(s_itr_ + 1))) &&
2954 4245 : (details::is_digit(*(s_itr_ + 2))) &&
2955 4245 : (details::is_digit(*(s_itr_ + 3))))
2956 : )
2957 : {
2958 0 : t.set_error(
2959 : token::e_err_sfunc,
2960 0 : initial_itr, std::min(initial_itr + 4, s_end_),
2961 : base_itr_);
2962 0 : token_list_.push_back(t);
2963 :
2964 0 : return;
2965 : }
2966 :
2967 4245 : s_itr_ += 4; // $fdd = 4chars
2968 :
2969 4245 : t.set_symbol(initial_itr, s_itr_, base_itr_);
2970 4245 : token_list_.push_back(t);
2971 :
2972 4245 : return;
2973 4245 : }
2974 :
2975 : #ifndef exprtk_disable_string_capabilities
2976 53142 : inline void scan_string()
2977 : {
2978 53142 : details::char_cptr initial_itr = s_itr_ + 1;
2979 53142 : token_t t;
2980 :
2981 106284 : if (std::distance(s_itr_,s_end_) < 2)
2982 : {
2983 1 : t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2984 1 : token_list_.push_back(t);
2985 :
2986 1 : return;
2987 : }
2988 :
2989 53141 : ++s_itr_;
2990 :
2991 53141 : bool escaped_found = false;
2992 53141 : bool escaped = false;
2993 :
2994 386419 : while (!is_end(s_itr_))
2995 : {
2996 386183 : if (!details::is_valid_string_char(*s_itr_))
2997 : {
2998 0 : t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2999 0 : token_list_.push_back(t);
3000 :
3001 0 : return;
3002 : }
3003 386183 : else if (!escaped && ('\\' == *s_itr_))
3004 : {
3005 3050 : escaped_found = true;
3006 3050 : escaped = true;
3007 3050 : ++s_itr_;
3008 :
3009 3050 : continue;
3010 : }
3011 383133 : else if (!escaped)
3012 : {
3013 380083 : if ('\'' == *s_itr_)
3014 52905 : break;
3015 : }
3016 3050 : else if (escaped)
3017 : {
3018 3050 : if (
3019 5150 : !is_end(s_itr_) && ('0' == *(s_itr_)) &&
3020 2100 : ((s_itr_ + 4) <= s_end_)
3021 : )
3022 : {
3023 2100 : const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1)));
3024 :
3025 4200 : const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
3026 2100 : details::is_hex_digit(*(s_itr_ + 3)) ;
3027 :
3028 2100 : if (!(x_separator && both_digits))
3029 : {
3030 0 : t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
3031 0 : token_list_.push_back(t);
3032 :
3033 0 : return;
3034 : }
3035 : else
3036 2100 : s_itr_ += 3;
3037 : }
3038 :
3039 3050 : escaped = false;
3040 : }
3041 :
3042 330228 : ++s_itr_;
3043 : }
3044 :
3045 53141 : if (is_end(s_itr_))
3046 : {
3047 236 : t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
3048 236 : token_list_.push_back(t);
3049 :
3050 236 : return;
3051 : }
3052 :
3053 52905 : if (!escaped_found)
3054 51555 : t.set_string(initial_itr, s_itr_, base_itr_);
3055 : else
3056 : {
3057 1350 : std::string parsed_string(initial_itr,s_itr_);
3058 :
3059 1350 : if (!details::cleanup_escapes(parsed_string))
3060 : {
3061 0 : t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
3062 0 : token_list_.push_back(t);
3063 :
3064 0 : return;
3065 : }
3066 :
3067 1350 : t.set_string(
3068 : parsed_string,
3069 2700 : static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
3070 1350 : }
3071 :
3072 52905 : token_list_.push_back(t);
3073 52905 : ++s_itr_;
3074 :
3075 52905 : return;
3076 53142 : }
3077 : #endif
3078 :
3079 : private:
3080 :
3081 : token_list_t token_list_;
3082 : token_list_itr_t token_itr_;
3083 : token_list_itr_t store_token_itr_;
3084 : token_t eof_token_;
3085 : details::char_cptr base_itr_;
3086 : details::char_cptr s_itr_;
3087 : details::char_cptr s_end_;
3088 :
3089 : friend class token_scanner;
3090 : friend class token_modifier;
3091 : friend class token_inserter;
3092 : friend class token_joiner;
3093 : }; // class generator
3094 :
3095 : class helper_interface
3096 : {
3097 : public:
3098 :
3099 0 : virtual void init() { }
3100 2260727 : virtual void reset() { }
3101 1519578 : virtual bool result() { return true; }
3102 0 : virtual std::size_t process(generator&) { return 0; }
3103 869280 : virtual ~helper_interface() { }
3104 : };
3105 :
3106 : class token_scanner : public helper_interface
3107 : {
3108 : public:
3109 :
3110 434640 : virtual ~token_scanner()
3111 434640 : {}
3112 :
3113 434640 : explicit token_scanner(const std::size_t& stride)
3114 434640 : : stride_(stride)
3115 : {
3116 434640 : if (stride > 4)
3117 : {
3118 0 : throw std::invalid_argument("token_scanner() - Invalid stride value");
3119 : }
3120 434640 : }
3121 :
3122 1500929 : inline std::size_t process(generator& g) exprtk_override
3123 : {
3124 1500929 : if (g.token_list_.size() >= stride_)
3125 : {
3126 60774246 : for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3127 : {
3128 59280391 : token t;
3129 :
3130 59280391 : switch (stride_)
3131 : {
3132 31841817 : case 1 :
3133 : {
3134 31841817 : const token& t0 = g.token_list_[i];
3135 :
3136 31841817 : if (!operator()(t0))
3137 : {
3138 4797 : return i;
3139 : }
3140 : }
3141 31837020 : break;
3142 :
3143 13981404 : case 2 :
3144 : {
3145 13981404 : const token& t0 = g.token_list_[i ];
3146 13981404 : const token& t1 = g.token_list_[i + 1];
3147 :
3148 13981404 : if (!operator()(t0, t1))
3149 : {
3150 0 : return i;
3151 : }
3152 : }
3153 13981404 : break;
3154 :
3155 13457170 : case 3 :
3156 : {
3157 13457170 : const token& t0 = g.token_list_[i ];
3158 13457170 : const token& t1 = g.token_list_[i + 1];
3159 13457170 : const token& t2 = g.token_list_[i + 2];
3160 :
3161 13457170 : if (!operator()(t0, t1, t2))
3162 : {
3163 0 : return i;
3164 : }
3165 : }
3166 13457170 : break;
3167 :
3168 0 : case 4 :
3169 : {
3170 0 : const token& t0 = g.token_list_[i ];
3171 0 : const token& t1 = g.token_list_[i + 1];
3172 0 : const token& t2 = g.token_list_[i + 2];
3173 0 : const token& t3 = g.token_list_[i + 3];
3174 :
3175 0 : if (!operator()(t0, t1, t2, t3))
3176 : {
3177 0 : return i;
3178 : }
3179 : }
3180 0 : break;
3181 : }
3182 59280391 : }
3183 : }
3184 :
3185 1496132 : return (g.token_list_.size() - stride_ + 1);
3186 : }
3187 :
3188 0 : virtual bool operator() (const token&)
3189 : {
3190 0 : return false;
3191 : }
3192 :
3193 0 : virtual bool operator() (const token&, const token&)
3194 : {
3195 0 : return false;
3196 : }
3197 :
3198 0 : virtual bool operator() (const token&, const token&, const token&)
3199 : {
3200 0 : return false;
3201 : }
3202 :
3203 0 : virtual bool operator() (const token&, const token&, const token&, const token&)
3204 : {
3205 0 : return false;
3206 : }
3207 :
3208 : private:
3209 :
3210 : const std::size_t stride_;
3211 : }; // class token_scanner
3212 :
3213 : class token_modifier : public helper_interface
3214 : {
3215 : public:
3216 :
3217 379897 : inline std::size_t process(generator& g) exprtk_override
3218 : {
3219 379897 : std::size_t changes = 0;
3220 :
3221 16427929 : for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3222 : {
3223 16048032 : if (modify(g.token_list_[i])) changes++;
3224 : }
3225 :
3226 379897 : return changes;
3227 : }
3228 :
3229 : virtual bool modify(token& t) = 0;
3230 : };
3231 :
3232 : class token_inserter : public helper_interface
3233 : {
3234 : public:
3235 :
3236 108660 : explicit token_inserter(const std::size_t& stride)
3237 108660 : : stride_(stride)
3238 : {
3239 108660 : if (stride > 5)
3240 : {
3241 0 : throw std::invalid_argument("token_inserter() - Invalid stride value");
3242 : }
3243 108660 : }
3244 :
3245 379887 : inline std::size_t process(generator& g) exprtk_override
3246 : {
3247 379887 : if (g.token_list_.empty())
3248 0 : return 0;
3249 379887 : else if (g.token_list_.size() < stride_)
3250 708 : return 0;
3251 :
3252 379179 : std::size_t changes = 0;
3253 :
3254 : typedef std::pair<std::size_t, token> insert_t;
3255 379179 : std::vector<insert_t> insert_list;
3256 379179 : insert_list.reserve(10000);
3257 :
3258 15903698 : for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3259 : {
3260 15524519 : int insert_index = -1;
3261 15524519 : token t;
3262 :
3263 15524519 : switch (stride_)
3264 : {
3265 0 : case 1 : insert_index = insert(g.token_list_[i],t);
3266 0 : break;
3267 :
3268 15524519 : case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3269 15524519 : break;
3270 :
3271 0 : case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3272 0 : break;
3273 :
3274 0 : 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);
3275 0 : break;
3276 :
3277 0 : 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);
3278 0 : break;
3279 : }
3280 :
3281 15524519 : if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3282 : {
3283 151028 : insert_list.push_back(insert_t(i, t));
3284 151028 : changes++;
3285 : }
3286 15524519 : }
3287 :
3288 379179 : if (!insert_list.empty())
3289 : {
3290 37034 : generator::token_list_t token_list;
3291 :
3292 37034 : std::size_t insert_index = 0;
3293 :
3294 4782050 : for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3295 : {
3296 4745016 : token_list.push_back(g.token_list_[i]);
3297 :
3298 4745016 : if (
3299 6350895 : (insert_index < insert_list.size()) &&
3300 1605879 : (insert_list[insert_index].first == i)
3301 : )
3302 : {
3303 151028 : token_list.push_back(insert_list[insert_index].second);
3304 151028 : insert_index++;
3305 : }
3306 : }
3307 :
3308 37034 : std::swap(g.token_list_,token_list);
3309 37034 : }
3310 :
3311 379179 : return changes;
3312 379179 : }
3313 :
3314 : #define token_inserter_empty_body \
3315 : { \
3316 : return -1; \
3317 : } \
3318 :
3319 0 : inline virtual int insert(const token&, token&)
3320 0 : token_inserter_empty_body
3321 :
3322 0 : inline virtual int insert(const token&, const token&, token&)
3323 0 : token_inserter_empty_body
3324 :
3325 0 : inline virtual int insert(const token&, const token&, const token&, token&)
3326 0 : token_inserter_empty_body
3327 :
3328 0 : inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3329 0 : token_inserter_empty_body
3330 :
3331 0 : inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3332 0 : token_inserter_empty_body
3333 :
3334 : #undef token_inserter_empty_body
3335 :
3336 : private:
3337 :
3338 : const std::size_t stride_;
3339 : };
3340 :
3341 : class token_joiner : public helper_interface
3342 : {
3343 : public:
3344 :
3345 217320 : explicit token_joiner(const std::size_t& stride)
3346 217320 : : stride_(stride)
3347 217320 : {}
3348 :
3349 759794 : inline std::size_t process(generator& g) exprtk_override
3350 : {
3351 759794 : if (g.token_list_.empty())
3352 0 : return 0;
3353 :
3354 759794 : switch (stride_)
3355 : {
3356 379897 : case 2 : return process_stride_2(g);
3357 379897 : case 3 : return process_stride_3(g);
3358 0 : default : return 0;
3359 : }
3360 : }
3361 :
3362 0 : virtual bool join(const token&, const token&, token&) { return false; }
3363 0 : virtual bool join(const token&, const token&, const token&, token&) { return false; }
3364 :
3365 : private:
3366 :
3367 379897 : inline std::size_t process_stride_2(generator& g)
3368 : {
3369 379897 : if (g.token_list_.size() < 2)
3370 708 : return 0;
3371 :
3372 379189 : std::size_t changes = 0;
3373 :
3374 379189 : generator::token_list_t token_list;
3375 379189 : token_list.reserve(10000);
3376 :
3377 16041449 : for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3378 : {
3379 15662260 : token t;
3380 :
3381 : for ( ; ; )
3382 : {
3383 15668531 : if (!join(g[i], g[i + 1], t))
3384 : {
3385 15661214 : token_list.push_back(g[i]);
3386 15661214 : break;
3387 : }
3388 :
3389 7317 : token_list.push_back(t);
3390 :
3391 7317 : ++changes;
3392 :
3393 7317 : i += 2;
3394 :
3395 7317 : if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1))
3396 1046 : break;
3397 : }
3398 15662260 : }
3399 :
3400 379189 : token_list.push_back(g.token_list_.back());
3401 :
3402 379189 : assert(token_list.size() <= g.token_list_.size());
3403 :
3404 379189 : std::swap(token_list, g.token_list_);
3405 :
3406 379189 : return changes;
3407 379189 : }
3408 :
3409 379897 : inline std::size_t process_stride_3(generator& g)
3410 : {
3411 379897 : if (g.token_list_.size() < 3)
3412 1577 : return 0;
3413 :
3414 378320 : std::size_t changes = 0;
3415 :
3416 378320 : generator::token_list_t token_list;
3417 378320 : token_list.reserve(10000);
3418 :
3419 15667068 : for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3420 : {
3421 15288748 : token t;
3422 :
3423 : for ( ; ; )
3424 : {
3425 15288946 : if (!join(g[i], g[i + 1], g[i + 2], t))
3426 : {
3427 15288746 : token_list.push_back(g[i]);
3428 15288746 : break;
3429 : }
3430 :
3431 200 : token_list.push_back(t);
3432 :
3433 200 : ++changes;
3434 :
3435 200 : i += 3;
3436 :
3437 200 : if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2))
3438 2 : break;
3439 : }
3440 15288748 : }
3441 :
3442 378320 : token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
3443 378320 : token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
3444 :
3445 378320 : assert(token_list.size() <= g.token_list_.size());
3446 :
3447 378320 : std::swap(token_list, g.token_list_);
3448 :
3449 378320 : return changes;
3450 378320 : }
3451 :
3452 : const std::size_t stride_;
3453 : };
3454 :
3455 : namespace helper
3456 : {
3457 :
3458 : inline void dump(const lexer::generator& generator)
3459 : {
3460 : for (std::size_t i = 0; i < generator.size(); ++i)
3461 : {
3462 : const lexer::token& t = generator[i];
3463 : printf("Token[%02d] @ %03d %6s --> '%s'\n",
3464 : static_cast<int>(i),
3465 : static_cast<int>(t.position),
3466 : t.to_str(t.type).c_str(),
3467 : t.value.c_str());
3468 : }
3469 : }
3470 :
3471 : class commutative_inserter : public lexer::token_inserter
3472 : {
3473 : public:
3474 :
3475 : using lexer::token_inserter::insert;
3476 :
3477 108660 : commutative_inserter()
3478 108660 : : lexer::token_inserter(2)
3479 108660 : {}
3480 :
3481 3585747 : inline void ignore_symbol(const std::string& symbol)
3482 : {
3483 3585747 : ignore_set_.insert(symbol);
3484 3585747 : }
3485 :
3486 15524519 : inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override
3487 : {
3488 15524519 : bool match = false;
3489 15524519 : new_token.type = lexer::token::e_mul;
3490 15524519 : new_token.value = "*";
3491 15524519 : new_token.position = t1.position;
3492 :
3493 15524519 : if (t0.type == lexer::token::e_symbol)
3494 : {
3495 3304699 : if (ignore_set_.end() != ignore_set_.find(t0.value))
3496 : {
3497 136807 : return -1;
3498 : }
3499 3167892 : else if (!t0.value.empty() && ('$' == t0.value[0]))
3500 : {
3501 4245 : return -1;
3502 : }
3503 : }
3504 :
3505 15383467 : if (t1.type == lexer::token::e_symbol)
3506 : {
3507 2909588 : if (ignore_set_.end() != ignore_set_.find(t1.value))
3508 : {
3509 101872 : return -1;
3510 : }
3511 : }
3512 15281595 : if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
3513 15178385 : else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
3514 15136577 : else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3515 15136530 : else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3516 15136483 : else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
3517 15136439 : else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
3518 15135153 : else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
3519 15135107 : else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
3520 15135061 : else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
3521 15130783 : else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3522 15130726 : else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3523 15130671 : else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
3524 :
3525 15281595 : return (match) ? 1 : -1;
3526 : }
3527 :
3528 : private:
3529 :
3530 : std::set<std::string,details::ilesscompare> ignore_set_;
3531 : };
3532 :
3533 : class operator_joiner exprtk_final : public token_joiner
3534 : {
3535 : public:
3536 :
3537 217320 : explicit operator_joiner(const std::size_t& stride)
3538 217320 : : token_joiner(stride)
3539 217320 : {}
3540 :
3541 15668531 : inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override
3542 : {
3543 : // ': =' --> ':='
3544 15668531 : if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3545 : {
3546 0 : t.type = lexer::token::e_assign;
3547 0 : t.value = ":=";
3548 0 : t.position = t0.position;
3549 :
3550 0 : return true;
3551 : }
3552 : // '+ =' --> '+='
3553 15668531 : else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3554 : {
3555 0 : t.type = lexer::token::e_addass;
3556 0 : t.value = "+=";
3557 0 : t.position = t0.position;
3558 :
3559 0 : return true;
3560 : }
3561 : // '- =' --> '-='
3562 15668531 : else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3563 : {
3564 0 : t.type = lexer::token::e_subass;
3565 0 : t.value = "-=";
3566 0 : t.position = t0.position;
3567 :
3568 0 : return true;
3569 : }
3570 : // '* =' --> '*='
3571 15668531 : else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3572 : {
3573 0 : t.type = lexer::token::e_mulass;
3574 0 : t.value = "*=";
3575 0 : t.position = t0.position;
3576 :
3577 0 : return true;
3578 : }
3579 : // '/ =' --> '/='
3580 15668531 : else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3581 : {
3582 0 : t.type = lexer::token::e_divass;
3583 0 : t.value = "/=";
3584 0 : t.position = t0.position;
3585 :
3586 0 : return true;
3587 : }
3588 : // '% =' --> '%='
3589 15668531 : else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3590 : {
3591 0 : t.type = lexer::token::e_modass;
3592 0 : t.value = "%=";
3593 0 : t.position = t0.position;
3594 :
3595 0 : return true;
3596 : }
3597 : // '> =' --> '>='
3598 15668531 : else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3599 : {
3600 0 : t.type = lexer::token::e_gte;
3601 0 : t.value = ">=";
3602 0 : t.position = t0.position;
3603 :
3604 0 : return true;
3605 : }
3606 : // '< =' --> '<='
3607 15668531 : else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3608 : {
3609 0 : t.type = lexer::token::e_lte;
3610 0 : t.value = "<=";
3611 0 : t.position = t0.position;
3612 :
3613 0 : return true;
3614 : }
3615 : // '= =' --> '=='
3616 15668531 : else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3617 : {
3618 4 : t.type = lexer::token::e_eq;
3619 4 : t.value = "==";
3620 4 : t.position = t0.position;
3621 :
3622 4 : return true;
3623 : }
3624 : // '! =' --> '!='
3625 15668527 : else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3626 : {
3627 0 : t.type = lexer::token::e_ne;
3628 0 : t.value = "!=";
3629 0 : t.position = t0.position;
3630 :
3631 0 : return true;
3632 : }
3633 : // '< >' --> '<>'
3634 15668527 : else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3635 : {
3636 0 : t.type = lexer::token::e_ne;
3637 0 : t.value = "<>";
3638 0 : t.position = t0.position;
3639 :
3640 0 : return true;
3641 : }
3642 : // '<= >' --> '<=>'
3643 15668527 : else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3644 : {
3645 0 : t.type = lexer::token::e_swap;
3646 0 : t.value = "<=>";
3647 0 : t.position = t0.position;
3648 :
3649 0 : return true;
3650 : }
3651 : // '+ -' --> '-'
3652 15668527 : else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3653 : {
3654 3618 : t.type = lexer::token::e_sub;
3655 3618 : t.value = "-";
3656 3618 : t.position = t0.position;
3657 :
3658 3618 : return true;
3659 : }
3660 : // '- +' --> '-'
3661 15664909 : else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3662 : {
3663 39 : t.type = lexer::token::e_sub;
3664 39 : t.value = "-";
3665 39 : t.position = t0.position;
3666 :
3667 39 : return true;
3668 : }
3669 : // '- -' --> '+'
3670 15664870 : else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3671 : {
3672 : /*
3673 : Note: May need to reconsider this when wanting to implement
3674 : pre/postfix decrement operator
3675 : */
3676 3656 : t.type = lexer::token::e_add;
3677 3656 : t.value = "+";
3678 3656 : t.position = t0.position;
3679 :
3680 3656 : return true;
3681 : }
3682 : else
3683 15661214 : return false;
3684 : }
3685 :
3686 15288946 : inline bool join(const lexer::token& t0,
3687 : const lexer::token& t1,
3688 : const lexer::token& t2,
3689 : lexer::token& t) exprtk_override
3690 : {
3691 : // '[ * ]' --> '[*]'
3692 15288946 : if (
3693 15288946 : (t0.type == lexer::token::e_lsqrbracket) &&
3694 98801 : (t1.type == lexer::token::e_mul ) &&
3695 210 : (t2.type == lexer::token::e_rsqrbracket)
3696 : )
3697 : {
3698 200 : t.type = lexer::token::e_symbol;
3699 200 : t.value = "[*]";
3700 200 : t.position = t0.position;
3701 :
3702 200 : return true;
3703 : }
3704 : else
3705 15288746 : return false;
3706 : }
3707 : };
3708 :
3709 : class bracket_checker exprtk_final : public lexer::token_scanner
3710 : {
3711 : public:
3712 :
3713 : using lexer::token_scanner::operator();
3714 :
3715 108660 : bracket_checker()
3716 0 : : token_scanner(1)
3717 108660 : , state_(true)
3718 108660 : {}
3719 :
3720 379883 : bool result() exprtk_override
3721 : {
3722 379883 : if (!stack_.empty())
3723 : {
3724 5025 : lexer::token t;
3725 5025 : t.value = stack_.top().first;
3726 5025 : t.position = stack_.top().second;
3727 5025 : error_token_ = t;
3728 5025 : state_ = false;
3729 :
3730 5025 : return false;
3731 5025 : }
3732 : else
3733 374858 : return state_;
3734 : }
3735 :
3736 17788 : lexer::token error_token()
3737 : {
3738 17788 : return error_token_;
3739 : }
3740 :
3741 379883 : void reset() exprtk_override
3742 : {
3743 : // Why? because msvc doesn't support swap properly.
3744 379883 : stack_ = std::stack<std::pair<char,std::size_t> >();
3745 379883 : state_ = true;
3746 379883 : error_token_.clear();
3747 379883 : }
3748 :
3749 15793785 : bool operator() (const lexer::token& t) exprtk_override
3750 : {
3751 15793785 : if (
3752 15793785 : !t.value.empty() &&
3753 15784335 : (lexer::token::e_string != t.type) &&
3754 44062692 : (lexer::token::e_symbol != t.type) &&
3755 12484572 : exprtk::details::is_bracket(t.value[0])
3756 : )
3757 : {
3758 6142767 : details::char_t c = t.value[0];
3759 :
3760 6142767 : if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
3761 3206663 : else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3762 3163373 : else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3763 3064488 : else if (exprtk::details::is_right_bracket(c))
3764 : {
3765 3064488 : if (stack_.empty())
3766 : {
3767 3869 : state_ = false;
3768 3869 : error_token_ = t;
3769 :
3770 3869 : return false;
3771 : }
3772 3060619 : else if (c != stack_.top().first)
3773 : {
3774 928 : state_ = false;
3775 928 : error_token_ = t;
3776 :
3777 928 : return false;
3778 : }
3779 : else
3780 3059691 : stack_.pop();
3781 : }
3782 : }
3783 :
3784 15788988 : return true;
3785 : }
3786 :
3787 : private:
3788 :
3789 : bool state_;
3790 : std::stack<std::pair<char,std::size_t> > stack_;
3791 : lexer::token error_token_;
3792 : };
3793 :
3794 : template <typename T>
3795 : class numeric_checker exprtk_final : public lexer::token_scanner
3796 : {
3797 : public:
3798 :
3799 : using lexer::token_scanner::operator();
3800 :
3801 108660 : numeric_checker()
3802 217320 : : token_scanner (1)
3803 108660 : , current_index_(0)
3804 108660 : {}
3805 :
3806 379897 : bool result() exprtk_override
3807 : {
3808 379897 : return error_list_.empty();
3809 : }
3810 :
3811 379897 : void reset() exprtk_override
3812 : {
3813 379897 : error_list_.clear();
3814 379897 : current_index_ = 0;
3815 379897 : }
3816 :
3817 16048032 : bool operator() (const lexer::token& t) exprtk_override
3818 : {
3819 16048032 : if (token::e_number == t.type)
3820 : {
3821 : T v;
3822 :
3823 2045200 : if (!exprtk::details::string_to_real(t.value,v))
3824 : {
3825 14 : error_list_.push_back(current_index_);
3826 : }
3827 : }
3828 :
3829 16048032 : ++current_index_;
3830 :
3831 16048032 : return true;
3832 : }
3833 :
3834 42 : std::size_t error_count() const
3835 : {
3836 42 : return error_list_.size();
3837 : }
3838 :
3839 14 : std::size_t error_index(const std::size_t& i)
3840 : {
3841 14 : if (i < error_list_.size())
3842 14 : return error_list_[i];
3843 : else
3844 0 : return std::numeric_limits<std::size_t>::max();
3845 : }
3846 :
3847 14 : void clear_errors()
3848 : {
3849 14 : error_list_.clear();
3850 14 : }
3851 :
3852 : private:
3853 :
3854 : std::size_t current_index_;
3855 : std::vector<std::size_t> error_list_;
3856 : };
3857 :
3858 : class symbol_replacer exprtk_final : public lexer::token_modifier
3859 : {
3860 : private:
3861 :
3862 : typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3863 :
3864 : public:
3865 :
3866 : bool remove(const std::string& target_symbol)
3867 : {
3868 : const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3869 :
3870 : if (replace_map_.end() == itr)
3871 : return false;
3872 :
3873 : replace_map_.erase(itr);
3874 :
3875 : return true;
3876 : }
3877 :
3878 220520 : bool add_replace(const std::string& target_symbol,
3879 : const std::string& replace_symbol,
3880 : const lexer::token::token_type token_type = lexer::token::e_symbol)
3881 : {
3882 220520 : const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3883 :
3884 220520 : if (replace_map_.end() != itr)
3885 : {
3886 0 : return false;
3887 : }
3888 :
3889 220520 : replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3890 :
3891 220520 : return true;
3892 : }
3893 :
3894 108660 : void clear()
3895 : {
3896 108660 : replace_map_.clear();
3897 108660 : }
3898 :
3899 : private:
3900 :
3901 16048032 : bool modify(lexer::token& t) exprtk_override
3902 : {
3903 16048032 : if (lexer::token::e_symbol == t.type)
3904 : {
3905 3321359 : if (replace_map_.empty())
3906 15993 : return false;
3907 :
3908 3321359 : const replace_map_t::iterator itr = replace_map_.find(t.value);
3909 :
3910 3321359 : if (replace_map_.end() != itr)
3911 : {
3912 15993 : t.value = itr->second.first;
3913 15993 : t.type = itr->second.second;
3914 :
3915 15993 : return true;
3916 : }
3917 : }
3918 :
3919 16032039 : return false;
3920 : }
3921 :
3922 : replace_map_t replace_map_;
3923 : };
3924 :
3925 : class sequence_validator exprtk_final : public lexer::token_scanner
3926 : {
3927 : private:
3928 :
3929 : typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3930 : typedef std::set<token_pair_t> set_t;
3931 :
3932 : public:
3933 :
3934 : using lexer::token_scanner::operator();
3935 :
3936 108660 : sequence_validator()
3937 108660 : : lexer::token_scanner(2)
3938 : {
3939 108660 : add_invalid(lexer::token::e_number, lexer::token::e_number);
3940 108660 : add_invalid(lexer::token::e_string, lexer::token::e_string);
3941 108660 : add_invalid(lexer::token::e_number, lexer::token::e_string);
3942 108660 : add_invalid(lexer::token::e_string, lexer::token::e_number);
3943 :
3944 108660 : add_invalid_set1(lexer::token::e_assign );
3945 108660 : add_invalid_set1(lexer::token::e_shr );
3946 108660 : add_invalid_set1(lexer::token::e_shl );
3947 108660 : add_invalid_set1(lexer::token::e_lte );
3948 108660 : add_invalid_set1(lexer::token::e_ne );
3949 108660 : add_invalid_set1(lexer::token::e_gte );
3950 108660 : add_invalid_set1(lexer::token::e_lt );
3951 108660 : add_invalid_set1(lexer::token::e_gt );
3952 108660 : add_invalid_set1(lexer::token::e_eq );
3953 108660 : add_invalid_set1(lexer::token::e_comma );
3954 108660 : add_invalid_set1(lexer::token::e_add );
3955 108660 : add_invalid_set1(lexer::token::e_sub );
3956 108660 : add_invalid_set1(lexer::token::e_div );
3957 108660 : add_invalid_set1(lexer::token::e_mul );
3958 108660 : add_invalid_set1(lexer::token::e_mod );
3959 108660 : add_invalid_set1(lexer::token::e_pow );
3960 108660 : add_invalid_set1(lexer::token::e_colon );
3961 108660 : add_invalid_set1(lexer::token::e_ternary);
3962 108660 : }
3963 :
3964 370989 : bool result() exprtk_override
3965 : {
3966 370989 : return error_list_.empty();
3967 : }
3968 :
3969 13981404 : bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override
3970 : {
3971 13981404 : const set_t::value_type p = std::make_pair(t0.type,t1.type);
3972 :
3973 13981404 : if (invalid_bracket_check(t0.type,t1.type))
3974 : {
3975 559 : error_list_.push_back(std::make_pair(t0,t1));
3976 : }
3977 13980845 : else if (invalid_comb_.find(p) != invalid_comb_.end())
3978 : {
3979 443 : error_list_.push_back(std::make_pair(t0,t1));
3980 : }
3981 :
3982 13981404 : return true;
3983 : }
3984 :
3985 2660 : std::size_t error_count() const
3986 : {
3987 2660 : return error_list_.size();
3988 : }
3989 :
3990 1002 : std::pair<lexer::token,lexer::token> error(const std::size_t index)
3991 : {
3992 1002 : if (index < error_list_.size())
3993 : {
3994 1002 : return error_list_[index];
3995 : }
3996 : else
3997 : {
3998 0 : static const lexer::token error_token;
3999 0 : return std::make_pair(error_token,error_token);
4000 : }
4001 : }
4002 :
4003 829 : void clear_errors()
4004 : {
4005 829 : error_list_.clear();
4006 829 : }
4007 :
4008 : private:
4009 :
4010 29772840 : void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t)
4011 : {
4012 29772840 : invalid_comb_.insert(std::make_pair(base,t));
4013 29772840 : }
4014 :
4015 1955880 : void add_invalid_set1(const lexer::token::token_type t)
4016 : {
4017 1955880 : add_invalid(t, lexer::token::e_assign);
4018 1955880 : add_invalid(t, lexer::token::e_shr );
4019 1955880 : add_invalid(t, lexer::token::e_shl );
4020 1955880 : add_invalid(t, lexer::token::e_lte );
4021 1955880 : add_invalid(t, lexer::token::e_ne );
4022 1955880 : add_invalid(t, lexer::token::e_gte );
4023 1955880 : add_invalid(t, lexer::token::e_lt );
4024 1955880 : add_invalid(t, lexer::token::e_gt );
4025 1955880 : add_invalid(t, lexer::token::e_eq );
4026 1955880 : add_invalid(t, lexer::token::e_comma );
4027 1955880 : add_invalid(t, lexer::token::e_div );
4028 1955880 : add_invalid(t, lexer::token::e_mul );
4029 1955880 : add_invalid(t, lexer::token::e_mod );
4030 1955880 : add_invalid(t, lexer::token::e_pow );
4031 1955880 : add_invalid(t, lexer::token::e_colon );
4032 1955880 : }
4033 :
4034 13981404 : bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t)
4035 : {
4036 13981404 : if (details::is_right_bracket(static_cast<details::char_t>(base)))
4037 : {
4038 2418152 : switch (t)
4039 : {
4040 29259 : case lexer::token::e_assign : return (']' != base);
4041 35 : case lexer::token::e_string : return (')' != base);
4042 2388858 : default : return false;
4043 : }
4044 : }
4045 11563252 : else if (details::is_left_bracket(static_cast<details::char_t>(base)))
4046 : {
4047 2734279 : if (details::is_right_bracket(static_cast<details::char_t>(t)))
4048 11677 : return false;
4049 2722602 : else if (details::is_left_bracket(static_cast<details::char_t>(t)))
4050 1217665 : return false;
4051 : else
4052 : {
4053 1504937 : switch (t)
4054 : {
4055 581566 : case lexer::token::e_number : return false;
4056 818586 : case lexer::token::e_symbol : return false;
4057 3362 : case lexer::token::e_string : return false;
4058 2323 : case lexer::token::e_add : return false;
4059 88699 : case lexer::token::e_sub : return false;
4060 10199 : case lexer::token::e_colon : return false;
4061 19 : case lexer::token::e_ternary : return false;
4062 183 : default : return true ;
4063 : }
4064 : }
4065 : }
4066 8828973 : else if (details::is_right_bracket(static_cast<details::char_t>(t)))
4067 : {
4068 1586989 : switch (base)
4069 : {
4070 811878 : case lexer::token::e_number : return false;
4071 747157 : case lexer::token::e_symbol : return false;
4072 9372 : case lexer::token::e_string : return false;
4073 6731 : case lexer::token::e_eof : return false;
4074 11445 : case lexer::token::e_colon : return false;
4075 30 : case lexer::token::e_ternary : return false;
4076 376 : default : return true ;
4077 : }
4078 : }
4079 7241984 : else if (details::is_left_bracket(static_cast<details::char_t>(t)))
4080 : {
4081 1475880 : switch (base)
4082 : {
4083 0 : case lexer::token::e_rbracket : return true;
4084 0 : case lexer::token::e_rsqrbracket : return true;
4085 0 : case lexer::token::e_rcrlbracket : return true;
4086 1475880 : default : return false;
4087 : }
4088 : }
4089 :
4090 5766104 : return false;
4091 : }
4092 :
4093 : set_t invalid_comb_;
4094 : std::vector<std::pair<lexer::token,lexer::token> > error_list_;
4095 : };
4096 :
4097 : class sequence_validator_3tokens exprtk_final : public lexer::token_scanner
4098 : {
4099 : private:
4100 :
4101 : typedef lexer::token::token_type token_t;
4102 : typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
4103 : typedef std::set<token_triplet_t> set_t;
4104 :
4105 : public:
4106 :
4107 : using lexer::token_scanner::operator();
4108 :
4109 108660 : sequence_validator_3tokens()
4110 108660 : : lexer::token_scanner(3)
4111 : {
4112 108660 : add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number);
4113 108660 : add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string);
4114 108660 : add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
4115 :
4116 108660 : add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add );
4117 108660 : add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub );
4118 108660 : add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div );
4119 108660 : add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul );
4120 108660 : add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod );
4121 108660 : add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow );
4122 :
4123 108660 : add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add );
4124 108660 : add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub );
4125 108660 : add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div );
4126 108660 : add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul );
4127 108660 : add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod );
4128 108660 : add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow );
4129 108660 : }
4130 :
4131 370160 : bool result() exprtk_override
4132 : {
4133 370160 : return error_list_.empty();
4134 : }
4135 :
4136 13457170 : bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override
4137 : {
4138 13457170 : const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
4139 :
4140 13457170 : if (invalid_comb_.find(p) != invalid_comb_.end())
4141 : {
4142 4 : error_list_.push_back(std::make_pair(t0,t1));
4143 : }
4144 :
4145 13457170 : return true;
4146 : }
4147 :
4148 8 : std::size_t error_count() const
4149 : {
4150 8 : return error_list_.size();
4151 : }
4152 :
4153 4 : std::pair<lexer::token,lexer::token> error(const std::size_t index)
4154 : {
4155 4 : if (index < error_list_.size())
4156 : {
4157 4 : return error_list_[index];
4158 : }
4159 : else
4160 : {
4161 0 : static const lexer::token error_token;
4162 0 : return std::make_pair(error_token,error_token);
4163 : }
4164 : }
4165 :
4166 2 : void clear_errors()
4167 : {
4168 2 : error_list_.clear();
4169 2 : }
4170 :
4171 : private:
4172 :
4173 1629900 : void add_invalid(const token_t t0, const token_t t1, const token_t t2)
4174 : {
4175 1629900 : invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
4176 1629900 : }
4177 :
4178 : set_t invalid_comb_;
4179 : std::vector<std::pair<lexer::token,lexer::token> > error_list_;
4180 : };
4181 :
4182 : struct helper_assembly
4183 : {
4184 434640 : inline bool register_scanner(lexer::token_scanner* scanner)
4185 : {
4186 434640 : if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
4187 : token_scanner_list.end (),
4188 : scanner))
4189 : {
4190 0 : return false;
4191 : }
4192 :
4193 434640 : token_scanner_list.push_back(scanner);
4194 :
4195 434640 : return true;
4196 : }
4197 :
4198 108660 : inline bool register_modifier(lexer::token_modifier* modifier)
4199 : {
4200 108660 : if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
4201 : token_modifier_list.end (),
4202 : modifier))
4203 : {
4204 0 : return false;
4205 : }
4206 :
4207 108660 : token_modifier_list.push_back(modifier);
4208 :
4209 108660 : return true;
4210 : }
4211 :
4212 217320 : inline bool register_joiner(lexer::token_joiner* joiner)
4213 : {
4214 217320 : if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
4215 : token_joiner_list.end (),
4216 : joiner))
4217 : {
4218 0 : return false;
4219 : }
4220 :
4221 217320 : token_joiner_list.push_back(joiner);
4222 :
4223 217320 : return true;
4224 : }
4225 :
4226 108659 : inline bool register_inserter(lexer::token_inserter* inserter)
4227 : {
4228 108659 : if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
4229 : token_inserter_list.end (),
4230 : inserter))
4231 : {
4232 0 : return false;
4233 : }
4234 :
4235 108659 : token_inserter_list.push_back(inserter);
4236 :
4237 108659 : return true;
4238 : }
4239 :
4240 379897 : inline bool run_modifiers(lexer::generator& g)
4241 : {
4242 379897 : error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
4243 :
4244 759794 : for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
4245 : {
4246 379897 : lexer::token_modifier& modifier = (*token_modifier_list[i]);
4247 :
4248 379897 : modifier.reset();
4249 379897 : modifier.process(g);
4250 :
4251 379897 : if (!modifier.result())
4252 : {
4253 0 : error_token_modifier = token_modifier_list[i];
4254 :
4255 0 : return false;
4256 : }
4257 : }
4258 :
4259 379897 : return true;
4260 : }
4261 :
4262 379897 : inline bool run_joiners(lexer::generator& g)
4263 : {
4264 379897 : error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
4265 :
4266 1139691 : for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
4267 : {
4268 759794 : lexer::token_joiner& joiner = (*token_joiner_list[i]);
4269 :
4270 759794 : joiner.reset();
4271 759794 : joiner.process(g);
4272 :
4273 759794 : if (!joiner.result())
4274 : {
4275 0 : error_token_joiner = token_joiner_list[i];
4276 :
4277 0 : return false;
4278 : }
4279 : }
4280 :
4281 379897 : return true;
4282 : }
4283 :
4284 379887 : inline bool run_inserters(lexer::generator& g)
4285 : {
4286 379887 : error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4287 :
4288 759774 : for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4289 : {
4290 379887 : lexer::token_inserter& inserter = (*token_inserter_list[i]);
4291 :
4292 379887 : inserter.reset();
4293 379887 : inserter.process(g);
4294 :
4295 379887 : if (!inserter.result())
4296 : {
4297 0 : error_token_inserter = token_inserter_list[i];
4298 :
4299 0 : return false;
4300 : }
4301 : }
4302 :
4303 379887 : return true;
4304 : }
4305 :
4306 379897 : inline bool run_scanners(lexer::generator& g)
4307 : {
4308 379897 : error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4309 :
4310 1871087 : for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4311 : {
4312 1500929 : lexer::token_scanner& scanner = (*token_scanner_list[i]);
4313 :
4314 1500929 : scanner.reset();
4315 1500929 : scanner.process(g);
4316 :
4317 1500929 : if (!scanner.result())
4318 : {
4319 9739 : error_token_scanner = token_scanner_list[i];
4320 :
4321 9739 : return false;
4322 : }
4323 : }
4324 :
4325 370158 : return true;
4326 : }
4327 :
4328 : std::vector<lexer::token_scanner*> token_scanner_list;
4329 : std::vector<lexer::token_modifier*> token_modifier_list;
4330 : std::vector<lexer::token_joiner*> token_joiner_list;
4331 : std::vector<lexer::token_inserter*> token_inserter_list;
4332 :
4333 : lexer::token_scanner* error_token_scanner;
4334 : lexer::token_modifier* error_token_modifier;
4335 : lexer::token_joiner* error_token_joiner;
4336 : lexer::token_inserter* error_token_inserter;
4337 : };
4338 : }
4339 :
4340 : class parser_helper
4341 : {
4342 : public:
4343 :
4344 : typedef token token_t;
4345 : typedef generator generator_t;
4346 :
4347 380686 : inline bool init(const std::string& str)
4348 : {
4349 380686 : if (!lexer_.process(str))
4350 : {
4351 788 : return false;
4352 : }
4353 :
4354 379898 : lexer_.begin();
4355 :
4356 379898 : next_token();
4357 :
4358 379898 : return true;
4359 : }
4360 :
4361 3288819 : inline generator_t& lexer()
4362 : {
4363 3288819 : return lexer_;
4364 : }
4365 :
4366 : inline const generator_t& lexer() const
4367 : {
4368 : return lexer_;
4369 : }
4370 :
4371 : inline void store_token()
4372 : {
4373 : lexer_.store();
4374 : store_current_token_ = current_token_;
4375 : }
4376 :
4377 : inline void restore_token()
4378 : {
4379 : lexer_.restore();
4380 : current_token_ = store_current_token_;
4381 : }
4382 :
4383 13552170 : inline void next_token()
4384 : {
4385 13552170 : current_token_ = lexer_.next_token();
4386 13552170 : }
4387 :
4388 63521882 : inline const token_t& current_token() const
4389 : {
4390 63521882 : return current_token_;
4391 : }
4392 :
4393 : inline const token_t& peek_next_token()
4394 : {
4395 : return lexer_.peek_next_token();
4396 : }
4397 :
4398 : enum token_advance_mode
4399 : {
4400 : e_hold = 0,
4401 : e_advance = 1
4402 : };
4403 :
4404 4117643 : inline void advance_token(const token_advance_mode mode)
4405 : {
4406 4117643 : if (e_advance == mode)
4407 : {
4408 3589974 : next_token();
4409 : }
4410 4117643 : }
4411 :
4412 18664985 : inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4413 : {
4414 18664985 : if (current_token().type != ttype)
4415 : {
4416 14552715 : return false;
4417 : }
4418 :
4419 4112270 : advance_token(mode);
4420 :
4421 4112270 : return true;
4422 : }
4423 :
4424 80 : inline bool token_is(const token_t::token_type& ttype,
4425 : const std::string& value,
4426 : const token_advance_mode mode = e_advance)
4427 : {
4428 80 : if (
4429 160 : (current_token().type != ttype) ||
4430 80 : !exprtk::details::imatch(value,current_token().value)
4431 : )
4432 : {
4433 0 : return false;
4434 : }
4435 :
4436 80 : advance_token(mode);
4437 :
4438 80 : return true;
4439 : }
4440 :
4441 5333 : inline bool token_is(const std::string& value,
4442 : const token_advance_mode mode = e_advance)
4443 : {
4444 5333 : if (!exprtk::details::imatch(value,current_token().value))
4445 : {
4446 40 : return false;
4447 : }
4448 :
4449 5293 : advance_token(mode);
4450 :
4451 5293 : return true;
4452 : }
4453 :
4454 10 : inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance)
4455 : {
4456 10 : switch (current_token().type)
4457 : {
4458 0 : case token_t::e_add :
4459 : case token_t::e_sub :
4460 : case token_t::e_div :
4461 : case token_t::e_mul :
4462 : case token_t::e_mod :
4463 0 : case token_t::e_pow : break;
4464 10 : default : return false;
4465 : }
4466 :
4467 0 : advance_token(mode);
4468 :
4469 0 : return true;
4470 : }
4471 :
4472 10 : inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance)
4473 : {
4474 10 : switch (current_token().type)
4475 : {
4476 0 : case token_t::e_eq :
4477 : case token_t::e_lte :
4478 : case token_t::e_ne :
4479 : case token_t::e_gte :
4480 : case token_t::e_lt :
4481 0 : case token_t::e_gt : break;
4482 10 : default : return false;
4483 : }
4484 :
4485 0 : advance_token(mode);
4486 :
4487 0 : return true;
4488 : }
4489 :
4490 : inline bool token_is_left_bracket(const token_advance_mode mode = e_advance)
4491 : {
4492 : switch (current_token().type)
4493 : {
4494 : case token_t::e_lbracket :
4495 : case token_t::e_lcrlbracket :
4496 : case token_t::e_lsqrbracket : break;
4497 : default : return false;
4498 : }
4499 :
4500 : advance_token(mode);
4501 :
4502 : return true;
4503 : }
4504 :
4505 10 : inline bool token_is_right_bracket(const token_advance_mode mode = e_advance)
4506 : {
4507 10 : switch (current_token().type)
4508 : {
4509 0 : case token_t::e_rbracket :
4510 : case token_t::e_rcrlbracket :
4511 0 : case token_t::e_rsqrbracket : break;
4512 10 : default : return false;
4513 : }
4514 :
4515 0 : advance_token(mode);
4516 :
4517 0 : return true;
4518 : }
4519 :
4520 10 : inline bool token_is_loop(const token_advance_mode mode = e_advance)
4521 : {
4522 30 : return token_is("for" , mode) ||
4523 60 : token_is("while" , mode) ||
4524 40 : token_is("repeat", mode) ;
4525 : }
4526 :
4527 5806024 : inline bool peek_token_is(const token_t::token_type& ttype)
4528 : {
4529 5806024 : return (lexer_.peek_next_token().type == ttype);
4530 : }
4531 :
4532 55 : inline bool peek_token_is(const std::string& s)
4533 : {
4534 55 : return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4535 : }
4536 :
4537 : private:
4538 :
4539 : generator_t lexer_;
4540 : token_t current_token_;
4541 : token_t store_current_token_;
4542 : };
4543 : }
4544 :
4545 : template <typename T>
4546 : class vector_view
4547 : {
4548 : public:
4549 :
4550 : typedef T* data_ptr_t;
4551 :
4552 4195 : vector_view(data_ptr_t data, const std::size_t& size)
4553 4195 : : base_size_(size)
4554 4195 : , size_(size)
4555 4195 : , data_(data)
4556 8390 : , data_ref_(0)
4557 : {
4558 4195 : assert(size_ > 0);
4559 4195 : }
4560 :
4561 : vector_view(const vector_view<T>& vv)
4562 : : base_size_(vv.base_size_)
4563 : , size_(vv.size_)
4564 : , data_(vv.data_)
4565 : , data_ref_(0)
4566 : {
4567 : assert(size_ > 0);
4568 : }
4569 :
4570 6800 : inline void rebase(data_ptr_t data)
4571 : {
4572 6800 : data_ = data;
4573 :
4574 6800 : if (!data_ref_.empty())
4575 : {
4576 11027 : for (std::size_t i = 0; i < data_ref_.size(); ++i)
4577 : {
4578 8547 : (*data_ref_[i]) = data;
4579 : }
4580 : }
4581 6800 : }
4582 :
4583 6 : inline data_ptr_t data() const
4584 : {
4585 6 : return data_;
4586 : }
4587 :
4588 4172 : inline std::size_t base_size() const
4589 : {
4590 4172 : return base_size_;
4591 : }
4592 :
4593 32851 : inline std::size_t size() const
4594 : {
4595 32851 : return size_;
4596 : }
4597 :
4598 : inline const T& operator[](const std::size_t index) const
4599 : {
4600 : assert(index < size_);
4601 : return data_[index];
4602 : }
4603 :
4604 7555 : inline T& operator[](const std::size_t index)
4605 : {
4606 7555 : assert(index < size_);
4607 7555 : return data_[index];
4608 : }
4609 :
4610 3670 : void set_ref(data_ptr_t* data_ref)
4611 : {
4612 3670 : data_ref_.push_back(data_ref);
4613 : exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n",
4614 : reinterpret_cast<void*>(data_ref),
4615 : static_cast<int>(data_ref_.size())));
4616 3670 : }
4617 :
4618 3670 : void remove_ref(data_ptr_t* data_ref)
4619 : {
4620 7340 : data_ref_.erase(
4621 3670 : std::remove(data_ref_.begin(), data_ref_.end(), data_ref),
4622 3670 : data_ref_.end());
4623 : exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n",
4624 : reinterpret_cast<void*>(data_ref),
4625 : static_cast<int>(data_ref_.size())));
4626 3670 : }
4627 :
4628 240 : bool set_size(const std::size_t new_size)
4629 : {
4630 240 : if ((new_size > 0) && (new_size <= base_size_))
4631 : {
4632 240 : size_ = new_size;
4633 : exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n",
4634 : reinterpret_cast<void*>(data_),
4635 : size_));
4636 240 : return true;
4637 : }
4638 :
4639 : exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n",
4640 : new_size,
4641 : base_size_));
4642 0 : return false;
4643 : }
4644 :
4645 : private:
4646 :
4647 : const std::size_t base_size_;
4648 : std::size_t size_;
4649 : data_ptr_t data_;
4650 : std::vector<data_ptr_t*> data_ref_;
4651 : };
4652 :
4653 : template <typename T>
4654 4137 : inline vector_view<T> make_vector_view(T* data,
4655 : const std::size_t size, const std::size_t offset = 0)
4656 : {
4657 4137 : return vector_view<T>(data + offset, size);
4658 : }
4659 :
4660 : template <typename T>
4661 58 : inline vector_view<T> make_vector_view(std::vector<T>& v,
4662 : const std::size_t size, const std::size_t offset = 0)
4663 : {
4664 58 : return vector_view<T>(v.data() + offset, size);
4665 : }
4666 :
4667 : template <typename T> class results_context;
4668 :
4669 : template <typename T>
4670 : struct type_store
4671 : {
4672 : enum store_type
4673 : {
4674 : e_unknown,
4675 : e_scalar ,
4676 : e_vector ,
4677 : e_string
4678 : };
4679 :
4680 3724 : type_store()
4681 3724 : : data(0)
4682 3724 : , size(0)
4683 3724 : , type(e_unknown)
4684 3724 : {}
4685 :
4686 : union
4687 : {
4688 : void* data;
4689 : T* vec_data;
4690 : };
4691 :
4692 : std::size_t size;
4693 : store_type type;
4694 :
4695 : class parameter_list
4696 : {
4697 : public:
4698 :
4699 5088 : explicit parameter_list(std::vector<type_store>& pl)
4700 5088 : : parameter_list_(pl)
4701 5088 : {}
4702 :
4703 : inline bool empty() const
4704 : {
4705 : return parameter_list_.empty();
4706 : }
4707 :
4708 2042 : inline std::size_t size() const
4709 : {
4710 2042 : return parameter_list_.size();
4711 : }
4712 :
4713 11043 : inline type_store& operator[](const std::size_t& index)
4714 : {
4715 11043 : return parameter_list_[index];
4716 : }
4717 :
4718 : inline const type_store& operator[](const std::size_t& index) const
4719 : {
4720 : return parameter_list_[index];
4721 : }
4722 :
4723 : inline type_store& front()
4724 : {
4725 : return parameter_list_[0];
4726 : }
4727 :
4728 : inline const type_store& front() const
4729 : {
4730 : return parameter_list_[0];
4731 : }
4732 :
4733 536 : inline type_store& back()
4734 : {
4735 536 : return parameter_list_.back();
4736 : }
4737 :
4738 : inline const type_store& back() const
4739 : {
4740 : return parameter_list_.back();
4741 : }
4742 :
4743 : private:
4744 :
4745 : std::vector<type_store>& parameter_list_;
4746 :
4747 : friend class results_context<T>;
4748 : };
4749 :
4750 : template <typename ViewType>
4751 : struct type_view
4752 : {
4753 : typedef type_store<T> type_store_t;
4754 : typedef ViewType value_t;
4755 :
4756 7947 : explicit type_view(type_store_t& ts)
4757 7947 : : ts_(ts)
4758 7947 : , data_(reinterpret_cast<value_t*>(ts_.data))
4759 7947 : {}
4760 :
4761 2 : explicit type_view(const type_store_t& ts)
4762 2 : : ts_(const_cast<type_store_t&>(ts))
4763 2 : , data_(reinterpret_cast<value_t*>(ts_.data))
4764 2 : {}
4765 :
4766 13454 : inline std::size_t size() const
4767 : {
4768 13454 : return ts_.size;
4769 : }
4770 :
4771 5325 : inline value_t& operator[](const std::size_t& i)
4772 : {
4773 5325 : return data_[i];
4774 : }
4775 :
4776 31371 : inline const value_t& operator[](const std::size_t& i) const
4777 : {
4778 31371 : return data_[i];
4779 : }
4780 :
4781 57 : inline const value_t* begin() const { return data_; }
4782 300 : inline value_t* begin() { return data_; }
4783 :
4784 : inline const value_t* end() const
4785 : {
4786 : return static_cast<value_t*>(data_ + ts_.size);
4787 : }
4788 :
4789 2 : inline value_t* end()
4790 : {
4791 2 : return static_cast<value_t*>(data_ + ts_.size);
4792 : }
4793 :
4794 : type_store_t& ts_;
4795 : value_t* data_;
4796 : };
4797 :
4798 : typedef type_view<T> vector_view;
4799 : typedef type_view<char> string_view;
4800 :
4801 : struct scalar_view
4802 : {
4803 : typedef type_store<T> type_store_t;
4804 : typedef T value_t;
4805 :
4806 3356 : explicit scalar_view(type_store_t& ts)
4807 3356 : : v_(*reinterpret_cast<value_t*>(ts.data))
4808 3356 : {}
4809 :
4810 16 : explicit scalar_view(const type_store_t& ts)
4811 16 : : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4812 16 : {}
4813 :
4814 1026 : inline value_t& operator() ()
4815 : {
4816 1026 : return v_;
4817 : }
4818 :
4819 2 : inline const value_t& operator() () const
4820 : {
4821 2 : return v_;
4822 : }
4823 :
4824 : inline operator value_t() const
4825 : {
4826 : return v_;
4827 : }
4828 :
4829 714 : inline operator value_t()
4830 : {
4831 714 : return v_;
4832 : }
4833 :
4834 : template <typename IntType>
4835 : inline bool to_int(IntType& i) const
4836 : {
4837 : if (!exprtk::details::numeric::is_integer(v_))
4838 : return false;
4839 :
4840 : i = static_cast<IntType>(v_);
4841 :
4842 : return true;
4843 : }
4844 :
4845 : template <typename UIntType>
4846 1630 : inline bool to_uint(UIntType& u) const
4847 : {
4848 1630 : if (v_ < T(0))
4849 0 : return false;
4850 1630 : else if (!exprtk::details::numeric::is_integer(v_))
4851 0 : return false;
4852 :
4853 1630 : u = static_cast<UIntType>(v_);
4854 :
4855 1630 : return true;
4856 : }
4857 :
4858 : T& v_;
4859 : };
4860 : };
4861 :
4862 : template <typename StringView>
4863 48 : inline std::string to_str(const StringView& view)
4864 : {
4865 96 : return std::string(view.begin(),view.size());
4866 : }
4867 :
4868 : #ifndef exprtk_disable_return_statement
4869 : namespace details
4870 : {
4871 : template <typename T> class return_node;
4872 : template <typename T> class return_envelope_node;
4873 : }
4874 : #endif
4875 :
4876 : template <typename T>
4877 : class results_context
4878 : {
4879 : public:
4880 :
4881 : typedef type_store<T> type_store_t;
4882 : typedef typename type_store_t::scalar_view scalar_t;
4883 : typedef typename type_store_t::vector_view vector_t;
4884 : typedef typename type_store_t::string_view string_t;
4885 :
4886 111 : results_context()
4887 111 : : results_available_(false)
4888 111 : {}
4889 :
4890 97 : inline std::size_t count() const
4891 : {
4892 97 : if (results_available_)
4893 97 : return parameter_list_.size();
4894 : else
4895 0 : return 0;
4896 : }
4897 :
4898 : inline type_store_t& operator[](const std::size_t& index)
4899 : {
4900 : return parameter_list_[index];
4901 : }
4902 :
4903 80 : inline const type_store_t& operator[](const std::size_t& index) const
4904 : {
4905 80 : return parameter_list_[index];
4906 : }
4907 :
4908 2 : inline bool get_scalar(const std::size_t& index, T& out) const
4909 : {
4910 2 : if (
4911 4 : (index < parameter_list_.size()) &&
4912 2 : (parameter_list_[index].type == type_store_t::e_scalar)
4913 : )
4914 : {
4915 2 : const scalar_t scalar(parameter_list_[index]);
4916 2 : out = scalar();
4917 2 : return true;
4918 : }
4919 :
4920 0 : return false;
4921 : }
4922 :
4923 : template <typename OutputIterator>
4924 1 : inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const
4925 : {
4926 1 : if (
4927 2 : (index < parameter_list_.size()) &&
4928 1 : (parameter_list_[index].type == type_store_t::e_vector)
4929 : )
4930 : {
4931 1 : const vector_t vector(parameter_list_[index]);
4932 5 : for (std::size_t i = 0; i < vector.size(); ++i)
4933 : {
4934 4 : *(out_itr++) = vector[i];
4935 : }
4936 :
4937 1 : return true;
4938 : }
4939 :
4940 0 : return false;
4941 : }
4942 :
4943 1 : inline bool get_vector(const std::size_t& index, std::vector<T>& out) const
4944 : {
4945 1 : return get_vector(index,std::back_inserter(out));
4946 : }
4947 :
4948 1 : inline bool get_string(const std::size_t& index, std::string& out) const
4949 : {
4950 1 : if (
4951 2 : (index < parameter_list_.size()) &&
4952 1 : (parameter_list_[index].type == type_store_t::e_string)
4953 : )
4954 : {
4955 1 : const string_t str(parameter_list_[index]);
4956 1 : out.assign(str.begin(),str.size());
4957 1 : return true;
4958 : }
4959 :
4960 0 : return false;
4961 : }
4962 :
4963 : private:
4964 :
4965 111 : inline void clear()
4966 : {
4967 111 : results_available_ = false;
4968 111 : }
4969 :
4970 : typedef std::vector<type_store_t> ts_list_t;
4971 : typedef typename type_store_t::parameter_list parameter_list_t;
4972 :
4973 31 : inline void assign(const parameter_list_t& pl)
4974 : {
4975 31 : parameter_list_ = pl.parameter_list_;
4976 31 : results_available_ = true;
4977 31 : }
4978 :
4979 : bool results_available_;
4980 : ts_list_t parameter_list_;
4981 :
4982 : #ifndef exprtk_disable_return_statement
4983 : friend class details::return_node<T>;
4984 : friend class details::return_envelope_node<T>;
4985 : #endif
4986 : };
4987 :
4988 : namespace details
4989 : {
4990 : enum operator_type
4991 : {
4992 : e_default , e_null , e_add , e_sub ,
4993 : e_mul , e_div , e_mod , e_pow ,
4994 : e_atan2 , e_min , e_max , e_avg ,
4995 : e_sum , e_prod , e_lt , e_lte ,
4996 : e_eq , e_equal , e_ne , e_nequal ,
4997 : e_gte , e_gt , e_and , e_nand ,
4998 : e_or , e_nor , e_xor , e_xnor ,
4999 : e_mand , e_mor , e_scand , e_scor ,
5000 : e_shr , e_shl , e_abs , e_acos ,
5001 : e_acosh , e_asin , e_asinh , e_atan ,
5002 : e_atanh , e_ceil , e_cos , e_cosh ,
5003 : e_exp , e_expm1 , e_floor , e_log ,
5004 : e_log10 , e_log2 , e_log1p , e_logn ,
5005 : e_neg , e_pos , e_round , e_roundn ,
5006 : e_root , e_sqrt , e_sin , e_sinc ,
5007 : e_sinh , e_sec , e_csc , e_tan ,
5008 : e_tanh , e_cot , e_clamp , e_iclamp ,
5009 : e_inrange , e_sgn , e_r2d , e_d2r ,
5010 : e_d2g , e_g2d , e_hypot , e_notl ,
5011 : e_erf , e_erfc , e_ncdf , e_frac ,
5012 : e_trunc , e_assign , e_addass , e_subass ,
5013 : e_mulass , e_divass , e_modass , e_in ,
5014 : e_like , e_ilike , e_multi , e_smulti ,
5015 : e_swap ,
5016 :
5017 : // Do not add new functions/operators after this point.
5018 : e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
5019 : e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
5020 : e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
5021 : e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
5022 : e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
5023 : e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
5024 : e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
5025 : e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
5026 : e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
5027 : e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
5028 : e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
5029 : e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
5030 : e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
5031 : e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
5032 : e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
5033 : e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
5034 : e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
5035 : e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
5036 : e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
5037 : e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
5038 : e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
5039 : e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
5040 : e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
5041 : e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
5042 : e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
5043 : e_sffinal = 1100,
5044 : e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
5045 : e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
5046 : e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
5047 : e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
5048 : e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
5049 : e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
5050 : e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
5051 : e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
5052 : e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
5053 : e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
5054 : e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
5055 : e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
5056 : e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
5057 : e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
5058 : e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
5059 : e_sf4ext60 = 2060, e_sf4ext61 = 2061
5060 : };
5061 :
5062 3 : inline std::string to_str(const operator_type opr)
5063 : {
5064 3 : switch (opr)
5065 : {
5066 0 : case e_add : return "+" ;
5067 0 : case e_sub : return "-" ;
5068 0 : case e_mul : return "*" ;
5069 0 : case e_div : return "/" ;
5070 0 : case e_mod : return "%" ;
5071 0 : case e_pow : return "^" ;
5072 0 : case e_assign : return ":=" ;
5073 0 : case e_addass : return "+=" ;
5074 9 : case e_subass : return "-=" ;
5075 0 : case e_mulass : return "*=" ;
5076 0 : case e_divass : return "/=" ;
5077 0 : case e_modass : return "%=" ;
5078 0 : case e_lt : return "<" ;
5079 0 : case e_lte : return "<=" ;
5080 0 : case e_eq : return "==" ;
5081 0 : case e_equal : return "=" ;
5082 0 : case e_ne : return "!=" ;
5083 0 : case e_nequal : return "<>" ;
5084 0 : case e_gte : return ">=" ;
5085 0 : case e_gt : return ">" ;
5086 0 : case e_and : return "and" ;
5087 0 : case e_or : return "or" ;
5088 0 : case e_xor : return "xor" ;
5089 0 : case e_nand : return "nand";
5090 0 : case e_nor : return "nor" ;
5091 0 : case e_xnor : return "xnor";
5092 0 : default : return "N/A" ;
5093 : }
5094 : }
5095 :
5096 : struct base_operation_t
5097 : {
5098 5650320 : base_operation_t(const operator_type t, const unsigned int& np)
5099 5650320 : : type(t)
5100 5650320 : , num_params(np)
5101 5650320 : {}
5102 :
5103 : operator_type type;
5104 : unsigned int num_params;
5105 : };
5106 :
5107 : namespace loop_unroll
5108 : {
5109 : const unsigned int global_loop_batch_size =
5110 : #ifndef exprtk_disable_superscalar_unroll
5111 : 16;
5112 : #else
5113 : 4;
5114 : #endif
5115 :
5116 : struct details
5117 : {
5118 31598 : explicit details(const std::size_t& vsize,
5119 : const unsigned int loop_batch_size = global_loop_batch_size)
5120 31598 : : batch_size(loop_batch_size )
5121 31598 : , remainder (vsize % batch_size)
5122 31598 : , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
5123 31598 : {}
5124 :
5125 : unsigned int batch_size;
5126 : int remainder;
5127 : int upper_bound;
5128 : };
5129 : }
5130 :
5131 : #ifdef exprtk_enable_debugging
5132 : inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
5133 : {
5134 : if (size)
5135 : exprtk_debug(("%s - addr: %p size: %d\n",
5136 : s.c_str(),
5137 : ptr,
5138 : static_cast<unsigned int>(size)));
5139 : else
5140 : exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr));
5141 : }
5142 :
5143 : template <typename T>
5144 : inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size)
5145 : {
5146 : printf("----- %s (%p) -----\n",
5147 : vec_name.c_str(),
5148 : static_cast<const void*>(data));
5149 : printf("[ ");
5150 : for (std::size_t i = 0; i < size; ++i)
5151 : {
5152 : printf("%8.3f\t", data[i]);
5153 : }
5154 : printf(" ]\n");
5155 : printf("---------------------\n");
5156 : }
5157 : #else
5158 1065860 : inline void dump_ptr(const std::string&, const void*) {}
5159 12247 : inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
5160 : template <typename T>
5161 : inline void dump_vector(const std::string&, const T*, const std::size_t) {}
5162 : #endif
5163 :
5164 : template <typename T>
5165 : class vec_data_store
5166 : {
5167 : public:
5168 :
5169 : typedef vec_data_store<T> type;
5170 : typedef T* data_t;
5171 :
5172 : private:
5173 :
5174 : struct control_block
5175 : {
5176 27934 : control_block()
5177 27934 : : ref_count(1)
5178 27934 : , size (0)
5179 27934 : , data (0)
5180 27934 : , destruct (true)
5181 27934 : {}
5182 :
5183 12247 : explicit control_block(const std::size_t& dsize)
5184 12247 : : ref_count(1 )
5185 12247 : , size (dsize)
5186 12247 : , data (0 )
5187 12247 : , destruct (true )
5188 12247 : { create_data(); }
5189 :
5190 49912 : control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
5191 49912 : : ref_count(1 )
5192 49912 : , size (dsize )
5193 49912 : , data (dptr )
5194 49912 : , destruct (dstrct)
5195 49912 : {}
5196 :
5197 90093 : ~control_block()
5198 : {
5199 90093 : if (data && destruct && (0 == ref_count))
5200 : {
5201 24494 : dump_ptr("~vec_data_store::control_block() data",data);
5202 12247 : delete[] data;
5203 12247 : data = reinterpret_cast<data_t>(0);
5204 : }
5205 90093 : }
5206 :
5207 90093 : static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
5208 : {
5209 90093 : if (dsize)
5210 : {
5211 62159 : if (0 == data_ptr)
5212 12247 : return (new control_block(dsize));
5213 : else
5214 49912 : return (new control_block(dsize, data_ptr, dstrct));
5215 : }
5216 : else
5217 27934 : return (new control_block);
5218 : }
5219 :
5220 145120 : static inline void destroy(control_block*& cntrl_blck)
5221 : {
5222 145120 : if (cntrl_blck)
5223 : {
5224 145120 : if (
5225 290240 : (0 != cntrl_blck->ref_count) &&
5226 145120 : (0 == --cntrl_blck->ref_count)
5227 : )
5228 : {
5229 90093 : delete cntrl_blck;
5230 : }
5231 :
5232 145120 : cntrl_blck = 0;
5233 : }
5234 145120 : }
5235 :
5236 : std::size_t ref_count;
5237 : std::size_t size;
5238 : data_t data;
5239 : bool destruct;
5240 :
5241 : private:
5242 :
5243 : control_block(const control_block&) exprtk_delete;
5244 : control_block& operator=(const control_block&) exprtk_delete;
5245 :
5246 12247 : inline void create_data()
5247 : {
5248 12247 : destruct = true;
5249 12247 : data = new T[size];
5250 12247 : std::fill_n(data, size, T(0));
5251 24494 : dump_ptr("control_block::create_data() - data", data, size);
5252 12247 : }
5253 : };
5254 :
5255 : public:
5256 :
5257 27934 : vec_data_store()
5258 27934 : : control_block_(control_block::create(0))
5259 27934 : {}
5260 :
5261 12247 : explicit vec_data_store(const std::size_t& size)
5262 12247 : : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true))
5263 12247 : {}
5264 :
5265 49912 : vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
5266 49912 : : control_block_(control_block::create(size, data, dstrct))
5267 49912 : {}
5268 :
5269 26187 : vec_data_store(const type& vds)
5270 : {
5271 26187 : control_block_ = vds.control_block_;
5272 26187 : control_block_->ref_count++;
5273 26187 : }
5274 :
5275 116280 : ~vec_data_store()
5276 : {
5277 116280 : control_block::destroy(control_block_);
5278 116280 : }
5279 :
5280 29522 : type& operator=(const type& vds)
5281 : {
5282 29522 : if (this != &vds)
5283 : {
5284 29522 : const std::size_t final_size = min_size(control_block_, vds.control_block_);
5285 :
5286 29522 : vds.control_block_->size = final_size;
5287 29522 : control_block_->size = final_size;
5288 :
5289 29522 : if (control_block_->destruct || (0 == control_block_->data))
5290 : {
5291 28840 : control_block::destroy(control_block_);
5292 :
5293 28840 : control_block_ = vds.control_block_;
5294 28840 : control_block_->ref_count++;
5295 : }
5296 : }
5297 :
5298 29522 : return (*this);
5299 : }
5300 :
5301 46015 : inline data_t data()
5302 : {
5303 46015 : return control_block_->data;
5304 : }
5305 :
5306 32972108 : inline data_t data() const
5307 : {
5308 32972108 : return control_block_->data;
5309 : }
5310 :
5311 50017 : inline std::size_t size() const
5312 : {
5313 50017 : return control_block_->size;
5314 : }
5315 :
5316 122163 : inline data_t& ref()
5317 : {
5318 122163 : return control_block_->data;
5319 : }
5320 :
5321 : inline void dump() const
5322 : {
5323 : #ifdef exprtk_enable_debugging
5324 : exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
5325 : size(),
5326 : data(),
5327 : (control_block_->destruct ? 'T' : 'F')));
5328 :
5329 : for (std::size_t i = 0; i < size(); ++i)
5330 : {
5331 : if (5 == i)
5332 : exprtk_debug(("\n"));
5333 :
5334 : exprtk_debug(("%15.10f ", data()[i]));
5335 : }
5336 : exprtk_debug(("\n"));
5337 : #endif
5338 : }
5339 :
5340 649 : static inline void match_sizes(type& vds0, type& vds1)
5341 : {
5342 649 : const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
5343 649 : vds0.control_block_->size = size;
5344 649 : vds1.control_block_->size = size;
5345 649 : }
5346 :
5347 : private:
5348 :
5349 30171 : static inline std::size_t min_size(const control_block* cb0, const control_block* cb1)
5350 : {
5351 30171 : const std::size_t size0 = cb0->size;
5352 30171 : const std::size_t size1 = cb1->size;
5353 :
5354 30171 : if (size0 && size1)
5355 2237 : return std::min(size0,size1);
5356 : else
5357 27934 : return (size0) ? size0 : size1;
5358 : }
5359 :
5360 : control_block* control_block_;
5361 : };
5362 :
5363 : namespace numeric
5364 : {
5365 : namespace details
5366 : {
5367 : template <typename T>
5368 100770 : inline T process_impl(const operator_type operation, const T arg)
5369 : {
5370 100770 : switch (operation)
5371 : {
5372 160 : case e_abs : return numeric::abs (arg);
5373 10 : case e_acos : return numeric::acos (arg);
5374 80 : case e_acosh : return numeric::acosh(arg);
5375 10 : case e_asin : return numeric::asin (arg);
5376 210 : case e_asinh : return numeric::asinh(arg);
5377 5 : case e_atan : return numeric::atan (arg);
5378 80 : case e_atanh : return numeric::atanh(arg);
5379 60 : case e_ceil : return numeric::ceil (arg);
5380 371 : case e_cos : return numeric::cos (arg);
5381 15 : case e_cosh : return numeric::cosh (arg);
5382 32 : case e_exp : return numeric::exp (arg);
5383 0 : case e_expm1 : return numeric::expm1(arg);
5384 110 : case e_floor : return numeric::floor(arg);
5385 45 : case e_log : return numeric::log (arg);
5386 45 : case e_log10 : return numeric::log10(arg);
5387 10 : case e_log2 : return numeric::log2 (arg);
5388 0 : case e_log1p : return numeric::log1p(arg);
5389 95723 : case e_neg : return numeric::neg (arg);
5390 0 : case e_pos : return numeric::pos (arg);
5391 60 : case e_round : return numeric::round(arg);
5392 370 : case e_sin : return numeric::sin (arg);
5393 5 : case e_sinc : return numeric::sinc (arg);
5394 15 : case e_sinh : return numeric::sinh (arg);
5395 1708 : case e_sqrt : return numeric::sqrt (arg);
5396 232 : case e_tan : return numeric::tan (arg);
5397 15 : case e_tanh : return numeric::tanh (arg);
5398 5 : case e_cot : return numeric::cot (arg);
5399 5 : case e_sec : return numeric::sec (arg);
5400 5 : case e_csc : return numeric::csc (arg);
5401 5 : case e_r2d : return numeric::r2d (arg);
5402 95 : case e_d2r : return numeric::d2r (arg);
5403 5 : case e_d2g : return numeric::d2g (arg);
5404 5 : case e_g2d : return numeric::g2d (arg);
5405 720 : case e_notl : return numeric::notl (arg);
5406 45 : case e_sgn : return numeric::sgn (arg);
5407 1 : case e_erf : return numeric::erf (arg);
5408 1 : case e_erfc : return numeric::erfc (arg);
5409 470 : case e_ncdf : return numeric::ncdf (arg);
5410 15 : case e_frac : return numeric::frac (arg);
5411 22 : case e_trunc : return numeric::trunc(arg);
5412 :
5413 0 : default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
5414 0 : return std::numeric_limits<T>::quiet_NaN();
5415 : }
5416 : }
5417 :
5418 : template <typename T>
5419 449085 : inline T process_impl(const operator_type operation, const T arg0, const T arg1)
5420 : {
5421 449085 : switch (operation)
5422 : {
5423 39384 : case e_add : return (arg0 + arg1);
5424 32292 : case e_sub : return (arg0 - arg1);
5425 47651 : case e_mul : return (arg0 * arg1);
5426 48572 : case e_div : return (arg0 / arg1);
5427 86 : case e_mod : return modulus<T>(arg0,arg1);
5428 6284 : case e_pow : return pow<T>(arg0,arg1);
5429 0 : case e_atan2 : return atan2<T>(arg0,arg1);
5430 0 : case e_min : return std::min<T>(arg0,arg1);
5431 0 : case e_max : return std::max<T>(arg0,arg1);
5432 0 : case e_logn : return logn<T>(arg0,arg1);
5433 1126 : case e_lt : return (arg0 < arg1) ? T(1) : T(0);
5434 335 : case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
5435 2477 : case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5436 285 : case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5437 130 : case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
5438 1000 : case e_gt : return (arg0 > arg1) ? T(1) : T(0);
5439 485 : case e_and : return and_opr <T>(arg0,arg1);
5440 600 : case e_nand : return nand_opr<T>(arg0,arg1);
5441 440 : case e_or : return or_opr <T>(arg0,arg1);
5442 600 : case e_nor : return nor_opr <T>(arg0,arg1);
5443 240 : case e_xor : return xor_opr <T>(arg0,arg1);
5444 80 : case e_xnor : return xnor_opr<T>(arg0,arg1);
5445 160 : case e_root : return root <T>(arg0,arg1);
5446 120 : case e_roundn : return roundn <T>(arg0,arg1);
5447 266688 : case e_equal : return equal <T>(arg0,arg1);
5448 20 : case e_nequal : return nequal <T>(arg0,arg1);
5449 30 : case e_hypot : return hypot <T>(arg0,arg1);
5450 0 : case e_shr : return shr <T>(arg0,arg1);
5451 0 : case e_shl : return shl <T>(arg0,arg1);
5452 :
5453 0 : default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
5454 0 : return std::numeric_limits<T>::quiet_NaN();
5455 : }
5456 : }
5457 :
5458 : template <typename T>
5459 : inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
5460 : {
5461 : switch (operation)
5462 : {
5463 : case e_add : return (arg0 + arg1);
5464 : case e_sub : return (arg0 - arg1);
5465 : case e_mul : return (arg0 * arg1);
5466 : case e_div : return (arg0 / arg1);
5467 : case e_mod : return arg0 % arg1;
5468 : case e_pow : return pow<T>(arg0,arg1);
5469 : case e_min : return std::min<T>(arg0,arg1);
5470 : case e_max : return std::max<T>(arg0,arg1);
5471 : case e_logn : return logn<T>(arg0,arg1);
5472 : case e_lt : return (arg0 < arg1) ? T(1) : T(0);
5473 : case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
5474 : case e_eq : return (arg0 == arg1) ? T(1) : T(0);
5475 : case e_ne : return (arg0 != arg1) ? T(1) : T(0);
5476 : case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
5477 : case e_gt : return (arg0 > arg1) ? T(1) : T(0);
5478 : case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
5479 : case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
5480 : case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
5481 : case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
5482 : case e_xor : return arg0 ^ arg1;
5483 : case e_xnor : return !(arg0 ^ arg1);
5484 : case e_root : return root<T>(arg0,arg1);
5485 : case e_equal : return arg0 == arg1;
5486 : case e_nequal : return arg0 != arg1;
5487 : case e_hypot : return hypot<T>(arg0,arg1);
5488 : case e_shr : return arg0 >> arg1;
5489 : case e_shl : return arg0 << arg1;
5490 :
5491 : default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
5492 : return std::numeric_limits<T>::quiet_NaN();
5493 : }
5494 : }
5495 : }
5496 :
5497 : template <typename T>
5498 100770 : inline T process(const operator_type operation, const T arg)
5499 : {
5500 100770 : return exprtk::details::numeric::details::process_impl(operation,arg);
5501 : }
5502 :
5503 : template <typename T>
5504 449085 : inline T process(const operator_type operation, const T arg0, const T arg1)
5505 : {
5506 449085 : return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5507 : }
5508 : }
5509 :
5510 : template <typename Node>
5511 : struct node_collector_interface
5512 : {
5513 : typedef Node* node_ptr_t;
5514 : typedef Node** node_pp_t;
5515 : typedef std::vector<node_pp_t> noderef_list_t;
5516 :
5517 6606989 : virtual ~node_collector_interface()
5518 6606989 : {}
5519 :
5520 4042852 : virtual void collect_nodes(noderef_list_t&)
5521 4042852 : {}
5522 : };
5523 :
5524 : template <typename Node>
5525 : struct node_depth_base;
5526 :
5527 : template <typename T>
5528 : class expression_node : public node_collector_interface<expression_node<T> >
5529 : , public node_depth_base<expression_node<T> >
5530 : {
5531 : public:
5532 :
5533 : enum node_type
5534 : {
5535 : e_none , e_null , e_constant , e_unary ,
5536 : e_binary , e_binary_ext , e_trinary , e_quaternary ,
5537 : e_vararg , e_conditional , e_while , e_repeat ,
5538 : e_for , e_switch , e_mswitch , e_return ,
5539 : e_retenv , e_variable , e_stringvar , e_stringconst ,
5540 : e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat ,
5541 : e_stringvarsize , e_strswap , e_stringsize , e_stringvararg ,
5542 : e_function , e_vafunction , e_genfunction , e_strfunction ,
5543 : e_strcondition , e_strccondition , e_add , e_sub ,
5544 : e_mul , e_div , e_mod , e_pow ,
5545 : e_lt , e_lte , e_gt , e_gte ,
5546 : e_eq , e_ne , e_and , e_nand ,
5547 : e_or , e_nor , e_xor , e_xnor ,
5548 : e_in , e_like , e_ilike , e_inranges ,
5549 : e_ipow , e_ipowinv , e_abs , e_acos ,
5550 : e_acosh , e_asin , e_asinh , e_atan ,
5551 : e_atanh , e_ceil , e_cos , e_cosh ,
5552 : e_exp , e_expm1 , e_floor , e_log ,
5553 : e_log10 , e_log2 , e_log1p , e_neg ,
5554 : e_pos , e_round , e_sin , e_sinc ,
5555 : e_sinh , e_sqrt , e_tan , e_tanh ,
5556 : e_cot , e_sec , e_csc , e_r2d ,
5557 : e_d2r , e_d2g , e_g2d , e_notl ,
5558 : e_sgn , e_erf , e_erfc , e_ncdf ,
5559 : e_frac , e_trunc , e_uvouv , e_vov ,
5560 : e_cov , e_voc , e_vob , e_bov ,
5561 : e_cob , e_boc , e_vovov , e_vovoc ,
5562 : e_vocov , e_covov , e_covoc , e_vovovov ,
5563 : e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
5564 : e_covocov , e_vocovoc , e_covovoc , e_vococov ,
5565 : e_sf3ext , e_sf4ext , e_nulleq , e_strass ,
5566 : e_vector , e_vecsize , e_vecelem , e_veccelem ,
5567 : e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc ,
5568 : e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass ,
5569 : e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc ,
5570 : e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq ,
5571 : e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop ,
5572 : e_vecondition , e_break , e_continue , e_swap ,
5573 : e_assert
5574 : };
5575 :
5576 : typedef T value_type;
5577 : typedef expression_node<T>* expression_ptr;
5578 : typedef node_collector_interface<expression_node<T> > nci_t;
5579 : typedef typename nci_t::noderef_list_t noderef_list_t;
5580 : typedef node_depth_base<expression_node<T> > ndb_t;
5581 :
5582 6606989 : virtual ~expression_node()
5583 6606989 : {}
5584 :
5585 0 : inline virtual T value() const
5586 : {
5587 0 : return std::numeric_limits<T>::quiet_NaN();
5588 : }
5589 :
5590 0 : inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5591 : {
5592 0 : return reinterpret_cast<expression_ptr>(index * 0);
5593 : }
5594 :
5595 23087024 : inline virtual node_type type() const
5596 : {
5597 23087024 : return e_none;
5598 : }
5599 :
5600 5470126 : inline virtual bool valid() const
5601 : {
5602 5470126 : return true;
5603 : }
5604 : }; // class expression_node
5605 :
5606 : template <typename T>
5607 : inline bool is_generally_string_node(const expression_node<T>* node);
5608 :
5609 20653600 : inline bool is_true(const double v)
5610 : {
5611 20653600 : return std::not_equal_to<double>()(0.0,v);
5612 : }
5613 :
5614 : inline bool is_true(const long double v)
5615 : {
5616 : return std::not_equal_to<long double>()(0.0L,v);
5617 : }
5618 :
5619 : inline bool is_true(const float v)
5620 : {
5621 : return std::not_equal_to<float>()(0.0f,v);
5622 : }
5623 :
5624 : template <typename T>
5625 20744571 : inline bool is_true(const expression_node<T>* node)
5626 : {
5627 20744571 : return std::not_equal_to<T>()(T(0),node->value());
5628 : }
5629 :
5630 : template <typename T>
5631 166324875 : inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
5632 : {
5633 166324875 : return std::not_equal_to<T>()(T(0),node.first->value());
5634 : }
5635 :
5636 : template <typename T>
5637 1215 : inline bool is_false(const expression_node<T>* node)
5638 : {
5639 1215 : return std::equal_to<T>()(T(0),node->value());
5640 : }
5641 :
5642 : template <typename T>
5643 : inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
5644 : {
5645 : return std::equal_to<T>()(T(0),node.first->value());
5646 : }
5647 :
5648 : template <typename T>
5649 22688 : inline bool is_literal_node(const expression_node<T>* node)
5650 : {
5651 22688 : return node && (details::expression_node<T>::e_constant == node->type());
5652 : }
5653 :
5654 : template <typename T>
5655 0 : inline bool is_unary_node(const expression_node<T>* node)
5656 : {
5657 0 : return node && (details::expression_node<T>::e_unary == node->type());
5658 : }
5659 :
5660 : template <typename T>
5661 915317 : inline bool is_neg_unary_node(const expression_node<T>* node)
5662 : {
5663 915317 : return node && (details::expression_node<T>::e_neg == node->type());
5664 : }
5665 :
5666 : template <typename T>
5667 0 : inline bool is_binary_node(const expression_node<T>* node)
5668 : {
5669 0 : return node && (details::expression_node<T>::e_binary == node->type());
5670 : }
5671 :
5672 : template <typename T>
5673 15010702 : inline bool is_variable_node(const expression_node<T>* node)
5674 : {
5675 15010702 : return node && (details::expression_node<T>::e_variable == node->type());
5676 : }
5677 :
5678 : template <typename T>
5679 5456 : inline bool is_ivariable_node(const expression_node<T>* node)
5680 : {
5681 10912 : return node &&
5682 : (
5683 5456 : details::expression_node<T>::e_variable == node->type() ||
5684 4816 : details::expression_node<T>::e_vecelem == node->type() ||
5685 4336 : details::expression_node<T>::e_veccelem == node->type() ||
5686 4336 : details::expression_node<T>::e_vecelemrtc == node->type() ||
5687 4324 : details::expression_node<T>::e_veccelemrtc == node->type() ||
5688 4324 : details::expression_node<T>::e_rbvecelem == node->type() ||
5689 4324 : details::expression_node<T>::e_rbveccelem == node->type() ||
5690 4324 : details::expression_node<T>::e_rbvecelemrtc == node->type() ||
5691 4324 : details::expression_node<T>::e_rbveccelemrtc == node->type()
5692 5456 : );
5693 : }
5694 :
5695 : template <typename T>
5696 30549 : inline bool is_vector_elem_node(const expression_node<T>* node)
5697 : {
5698 30549 : return node && (details::expression_node<T>::e_vecelem == node->type());
5699 : }
5700 :
5701 : template <typename T>
5702 22412 : inline bool is_vector_celem_node(const expression_node<T>* node)
5703 : {
5704 22412 : return node && (details::expression_node<T>::e_veccelem == node->type());
5705 : }
5706 :
5707 : template <typename T>
5708 28914 : inline bool is_vector_elem_rtc_node(const expression_node<T>* node)
5709 : {
5710 28914 : return node && (details::expression_node<T>::e_vecelemrtc == node->type());
5711 : }
5712 :
5713 : template <typename T>
5714 28838 : inline bool is_vector_celem_rtc_node(const expression_node<T>* node)
5715 : {
5716 28838 : return node && (details::expression_node<T>::e_veccelemrtc == node->type());
5717 : }
5718 :
5719 : template <typename T>
5720 29138 : inline bool is_rebasevector_elem_node(const expression_node<T>* node)
5721 : {
5722 29138 : return node && (details::expression_node<T>::e_rbvecelem == node->type());
5723 : }
5724 :
5725 : template <typename T>
5726 27638 : inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node)
5727 : {
5728 27638 : return node && (details::expression_node<T>::e_rbvecelemrtc == node->type());
5729 : }
5730 :
5731 : template <typename T>
5732 9122 : inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node)
5733 : {
5734 9122 : return node && (details::expression_node<T>::e_rbveccelemrtc == node->type());
5735 : }
5736 :
5737 : template <typename T>
5738 28538 : inline bool is_rebasevector_celem_node(const expression_node<T>* node)
5739 : {
5740 28538 : return node && (details::expression_node<T>::e_rbveccelem == node->type());
5741 : }
5742 :
5743 : template <typename T>
5744 359673 : inline bool is_vector_node(const expression_node<T>* node)
5745 : {
5746 359673 : return node && (details::expression_node<T>::e_vector == node->type());
5747 : }
5748 :
5749 : template <typename T>
5750 13547496 : inline bool is_ivector_node(const expression_node<T>* node)
5751 : {
5752 13547496 : if (node)
5753 : {
5754 13546044 : switch (node->type())
5755 : {
5756 120148 : case details::expression_node<T>::e_vector :
5757 : case details::expression_node<T>::e_vecvalass :
5758 : case details::expression_node<T>::e_vecvecass :
5759 : case details::expression_node<T>::e_vecopvalass :
5760 : case details::expression_node<T>::e_vecopvecass :
5761 : case details::expression_node<T>::e_vecvecswap :
5762 : case details::expression_node<T>::e_vecvecarith :
5763 : case details::expression_node<T>::e_vecvalarith :
5764 : case details::expression_node<T>::e_valvecarith :
5765 : case details::expression_node<T>::e_vecunaryop :
5766 120148 : case details::expression_node<T>::e_vecondition : return true;
5767 13425896 : default : return false;
5768 : }
5769 : }
5770 : else
5771 1452 : return false;
5772 : }
5773 :
5774 : template <typename T>
5775 19259819 : inline bool is_constant_node(const expression_node<T>* node)
5776 : {
5777 38519638 : return node &&
5778 : (
5779 19259819 : details::expression_node<T>::e_constant == node->type() ||
5780 13337531 : details::expression_node<T>::e_stringconst == node->type()
5781 19259819 : );
5782 : }
5783 :
5784 : template <typename T>
5785 11166625 : inline bool is_null_node(const expression_node<T>* node)
5786 : {
5787 11166625 : return node && (details::expression_node<T>::e_null == node->type());
5788 : }
5789 :
5790 : template <typename T>
5791 6275505 : inline bool is_break_node(const expression_node<T>* node)
5792 : {
5793 6275505 : return node && (details::expression_node<T>::e_break == node->type());
5794 : }
5795 :
5796 : template <typename T>
5797 6275185 : inline bool is_continue_node(const expression_node<T>* node)
5798 : {
5799 6275185 : return node && (details::expression_node<T>::e_continue == node->type());
5800 : }
5801 :
5802 : template <typename T>
5803 : inline bool is_swap_node(const expression_node<T>* node)
5804 : {
5805 : return node && (details::expression_node<T>::e_swap == node->type());
5806 : }
5807 :
5808 : template <typename T>
5809 0 : inline bool is_function(const expression_node<T>* node)
5810 : {
5811 0 : return node && (details::expression_node<T>::e_function == node->type());
5812 : }
5813 :
5814 : template <typename T>
5815 54 : inline bool is_vararg_node(const expression_node<T>* node)
5816 : {
5817 54 : return node && (details::expression_node<T>::e_vararg == node->type());
5818 : }
5819 :
5820 : template <typename T>
5821 5822804 : inline bool is_return_node(const expression_node<T>* node)
5822 : {
5823 5822804 : return node && (details::expression_node<T>::e_return == node->type());
5824 : }
5825 :
5826 : template <typename T> class unary_node;
5827 :
5828 : template <typename T>
5829 : inline bool is_negate_node(const expression_node<T>* node)
5830 : {
5831 : if (node && is_unary_node(node))
5832 : {
5833 : return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5834 : }
5835 : else
5836 : return false;
5837 : }
5838 :
5839 : template <typename T>
5840 84 : inline bool is_assert_node(const expression_node<T>* node)
5841 : {
5842 84 : return node && (details::expression_node<T>::e_assert == node->type());
5843 : }
5844 :
5845 : template <typename T>
5846 4085341 : inline bool branch_deletable(const expression_node<T>* node)
5847 : {
5848 4085341 : return (0 != node) &&
5849 8056685 : !is_variable_node(node) &&
5850 8056685 : !is_string_node (node) ;
5851 : }
5852 :
5853 : template <std::size_t N, typename T>
5854 747115 : inline bool all_nodes_valid(expression_node<T>* const (&b)[N])
5855 : {
5856 2305059 : for (std::size_t i = 0; i < N; ++i)
5857 : {
5858 1557944 : if (0 == b[i]) return false;
5859 : }
5860 :
5861 747115 : return true;
5862 : }
5863 :
5864 : template <typename T,
5865 : typename Allocator,
5866 : template <typename, typename> class Sequence>
5867 54774 : inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5868 : {
5869 213723 : for (std::size_t i = 0; i < b.size(); ++i)
5870 : {
5871 158949 : if (0 == b[i]) return false;
5872 : }
5873 :
5874 54774 : return true;
5875 : }
5876 :
5877 : template <std::size_t N, typename T>
5878 2710 : inline bool all_nodes_variables(expression_node<T>* const (&b)[N])
5879 : {
5880 12350 : for (std::size_t i = 0; i < N; ++i)
5881 : {
5882 9640 : if (0 == b[i])
5883 0 : return false;
5884 9640 : else if (!is_variable_node(b[i]))
5885 0 : return false;
5886 : }
5887 :
5888 2710 : return true;
5889 : }
5890 :
5891 : template <typename T,
5892 : typename Allocator,
5893 : template <typename, typename> class Sequence>
5894 45814 : inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b)
5895 : {
5896 52864 : for (std::size_t i = 0; i < b.size(); ++i)
5897 : {
5898 50556 : if (0 == b[i])
5899 0 : return false;
5900 50556 : else if (!is_variable_node(b[i]))
5901 43506 : return false;
5902 : }
5903 :
5904 2308 : return true;
5905 : }
5906 :
5907 : template <typename Node>
5908 : class node_collection_destructor
5909 : {
5910 : public:
5911 :
5912 : typedef node_collector_interface<Node> nci_t;
5913 :
5914 : typedef typename nci_t::node_ptr_t node_ptr_t;
5915 : typedef typename nci_t::node_pp_t node_pp_t;
5916 : typedef typename nci_t::noderef_list_t noderef_list_t;
5917 :
5918 2886272 : static void delete_nodes(node_ptr_t& root)
5919 : {
5920 2886272 : std::vector<node_pp_t> node_delete_list;
5921 2886272 : node_delete_list.reserve(1000);
5922 :
5923 2886272 : collect_nodes(root, node_delete_list);
5924 :
5925 8836395 : for (std::size_t i = 0; i < node_delete_list.size(); ++i)
5926 : {
5927 5950123 : node_ptr_t& node = *node_delete_list[i];
5928 : exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node)));
5929 5950123 : delete node;
5930 5950123 : node = reinterpret_cast<node_ptr_t>(0);
5931 : }
5932 2886272 : }
5933 :
5934 : private:
5935 :
5936 2886272 : static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
5937 : {
5938 2886272 : std::deque<node_ptr_t> node_list;
5939 2886272 : node_list.push_back(root);
5940 2886272 : node_delete_list.push_back(&root);
5941 :
5942 2886272 : noderef_list_t child_node_delete_list;
5943 2886272 : child_node_delete_list.reserve(1000);
5944 :
5945 8836395 : while (!node_list.empty())
5946 : {
5947 5950123 : node_list.front()->collect_nodes(child_node_delete_list);
5948 :
5949 5950123 : if (!child_node_delete_list.empty())
5950 : {
5951 4957198 : for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
5952 : {
5953 3063851 : node_pp_t& node = child_node_delete_list[i];
5954 :
5955 3063851 : if (0 == (*node))
5956 : {
5957 : exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
5958 : }
5959 :
5960 3063851 : node_list.push_back(*node);
5961 : }
5962 :
5963 3786694 : node_delete_list.insert(
5964 1893347 : node_delete_list.end(),
5965 : child_node_delete_list.begin(), child_node_delete_list.end());
5966 :
5967 1893347 : child_node_delete_list.clear();
5968 : }
5969 :
5970 5950123 : node_list.pop_front();
5971 : }
5972 :
5973 2886272 : std::reverse(node_delete_list.begin(), node_delete_list.end());
5974 2886272 : }
5975 : };
5976 :
5977 : template <typename NodeAllocator, typename T, std::size_t N>
5978 9229 : inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5979 : {
5980 27742 : for (std::size_t i = 0; i < N; ++i)
5981 : {
5982 18513 : free_node(node_allocator,b[i]);
5983 : }
5984 9229 : }
5985 :
5986 : template <typename NodeAllocator,
5987 : typename T,
5988 : typename Allocator,
5989 : template <typename, typename> class Sequence>
5990 0 : inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5991 : {
5992 0 : for (std::size_t i = 0; i < b.size(); ++i)
5993 : {
5994 0 : free_node(node_allocator,b[i]);
5995 : }
5996 :
5997 0 : b.clear();
5998 0 : }
5999 :
6000 : template <typename NodeAllocator, typename T>
6001 2497640 : inline void free_node(NodeAllocator&, expression_node<T>*& node)
6002 : {
6003 2497640 : if ((0 == node) || is_variable_node(node) || is_string_node(node))
6004 : {
6005 321202 : return;
6006 : }
6007 :
6008 : node_collection_destructor<expression_node<T> >
6009 2176438 : ::delete_nodes(node);
6010 : }
6011 :
6012 : template <typename T>
6013 709834 : inline void destroy_node(expression_node<T>*& node)
6014 : {
6015 709834 : if (0 != node)
6016 : {
6017 : node_collection_destructor<expression_node<T> >
6018 709834 : ::delete_nodes(node);
6019 : }
6020 709834 : }
6021 :
6022 : template <typename Node>
6023 : struct node_depth_base
6024 : {
6025 : typedef Node* node_ptr_t;
6026 : typedef std::pair<node_ptr_t,bool> nb_pair_t;
6027 :
6028 6606989 : node_depth_base()
6029 6606989 : : depth_set(false)
6030 6606989 : , depth(0)
6031 6606989 : {}
6032 :
6033 6606989 : virtual ~node_depth_base()
6034 6606989 : {}
6035 :
6036 9991221 : virtual std::size_t node_depth() const { return 1; }
6037 :
6038 209347 : std::size_t compute_node_depth(const Node* const& node) const
6039 : {
6040 209347 : if (!depth_set)
6041 : {
6042 69114 : depth = 1 + (node ? node->node_depth() : 0);
6043 69114 : depth_set = true;
6044 : }
6045 :
6046 209347 : return depth;
6047 : }
6048 :
6049 2162054 : std::size_t compute_node_depth(const nb_pair_t& branch) const
6050 : {
6051 2162054 : if (!depth_set)
6052 : {
6053 806335 : depth = 1 + (branch.first ? branch.first->node_depth() : 0);
6054 806335 : depth_set = true;
6055 : }
6056 :
6057 2162054 : return depth;
6058 : }
6059 :
6060 : template <std::size_t N>
6061 2893682 : std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const
6062 : {
6063 2893682 : if (!depth_set)
6064 : {
6065 1027188 : depth = 0;
6066 :
6067 3164470 : for (std::size_t i = 0; i < N; ++i)
6068 : {
6069 2137282 : if (branch[i].first)
6070 : {
6071 1937233 : depth = std::max(depth,branch[i].first->node_depth());
6072 : }
6073 : }
6074 :
6075 1027188 : depth += 1;
6076 1027188 : depth_set = true;
6077 : }
6078 :
6079 2893682 : return depth;
6080 : }
6081 :
6082 : template <typename BranchType>
6083 5958 : std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const
6084 : {
6085 5958 : return std::max(compute_node_depth(n0), compute_node_depth(n1));
6086 : }
6087 :
6088 : template <typename BranchType>
6089 3740 : std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const
6090 : {
6091 3740 : return std::max(compute_node_depth(n0),
6092 7480 : std::max(compute_node_depth(n1), compute_node_depth(n2)));
6093 : }
6094 :
6095 : template <typename BranchType>
6096 2723 : std::size_t max_node_depth(const BranchType& n0, const BranchType& n1,
6097 : const BranchType& n2, const BranchType& n3) const
6098 : {
6099 2723 : return std::max(
6100 2723 : std::max(compute_node_depth(n0), compute_node_depth(n1)),
6101 5446 : std::max(compute_node_depth(n2), compute_node_depth(n3)));
6102 : }
6103 :
6104 : template <typename BranchType>
6105 13384 : std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
6106 : {
6107 13384 : if (!depth_set)
6108 : {
6109 5958 : depth = 1 + max_node_depth(n0, n1);
6110 5958 : depth_set = true;
6111 : }
6112 :
6113 13384 : return depth;
6114 : }
6115 :
6116 : template <typename BranchType>
6117 9258 : std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
6118 : const BranchType& n2) const
6119 : {
6120 9258 : if (!depth_set)
6121 : {
6122 3740 : depth = 1 + max_node_depth(n0, n1, n2);
6123 3740 : depth_set = true;
6124 : }
6125 :
6126 9258 : return depth;
6127 : }
6128 :
6129 : template <typename BranchType>
6130 6774 : std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
6131 : const BranchType& n2, const BranchType& n3) const
6132 : {
6133 6774 : if (!depth_set)
6134 : {
6135 2723 : depth = 1 + max_node_depth(n0, n1, n2, n3);
6136 2723 : depth_set = true;
6137 : }
6138 :
6139 6774 : return depth;
6140 : }
6141 :
6142 : template <typename Allocator,
6143 : template <typename, typename> class Sequence>
6144 64453 : std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const
6145 : {
6146 64453 : if (!depth_set)
6147 : {
6148 91003 : for (std::size_t i = 0; i < branch_list.size(); ++i)
6149 : {
6150 67047 : if (branch_list[i])
6151 : {
6152 67047 : depth = std::max(depth, compute_node_depth(branch_list[i]));
6153 : }
6154 : }
6155 23956 : depth_set = true;
6156 : }
6157 :
6158 64453 : return depth;
6159 : }
6160 :
6161 : template <typename Allocator,
6162 : template <typename, typename> class Sequence>
6163 72363 : std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const
6164 : {
6165 72363 : if (!depth_set)
6166 : {
6167 192092 : for (std::size_t i = 0; i < branch_list.size(); ++i)
6168 : {
6169 142300 : if (branch_list[i].first)
6170 : {
6171 142300 : depth = std::max(depth, compute_node_depth(branch_list[i].first));
6172 : }
6173 : }
6174 :
6175 49792 : depth_set = true;
6176 : }
6177 :
6178 72363 : return depth;
6179 : }
6180 :
6181 : mutable bool depth_set;
6182 : mutable std::size_t depth;
6183 :
6184 : template <typename NodeSequence>
6185 3182804 : void collect(node_ptr_t const& node,
6186 : const bool deletable,
6187 : NodeSequence& delete_node_list) const
6188 : {
6189 3182804 : if ((0 != node) && deletable)
6190 : {
6191 3063782 : delete_node_list.push_back(const_cast<node_ptr_t*>(&node));
6192 : }
6193 3182804 : }
6194 :
6195 : template <typename NodeSequence>
6196 828027 : void collect(const nb_pair_t& branch,
6197 : NodeSequence& delete_node_list) const
6198 : {
6199 828027 : collect(branch.first, branch.second, delete_node_list);
6200 828027 : }
6201 :
6202 : template <typename NodeSequence>
6203 : void collect(Node*& node,
6204 : NodeSequence& delete_node_list) const
6205 : {
6206 : collect(node, branch_deletable(node), delete_node_list);
6207 : }
6208 :
6209 : template <std::size_t N, typename NodeSequence>
6210 1027188 : void collect(const nb_pair_t(&branch)[N],
6211 : NodeSequence& delete_node_list) const
6212 : {
6213 3164470 : for (std::size_t i = 0; i < N; ++i)
6214 : {
6215 2137282 : collect(branch[i].first, branch[i].second, delete_node_list);
6216 : }
6217 1027188 : }
6218 :
6219 : template <typename Allocator,
6220 : template <typename, typename> class Sequence,
6221 : typename NodeSequence>
6222 49792 : void collect(const Sequence<nb_pair_t, Allocator>& branch,
6223 : NodeSequence& delete_node_list) const
6224 : {
6225 200357 : for (std::size_t i = 0; i < branch.size(); ++i)
6226 : {
6227 150565 : collect(branch[i].first, branch[i].second, delete_node_list);
6228 : }
6229 49792 : }
6230 :
6231 : template <typename Allocator,
6232 : template <typename, typename> class Sequence,
6233 : typename NodeSequence>
6234 23907 : void collect(const Sequence<node_ptr_t, Allocator>& branch_list,
6235 : NodeSequence& delete_node_list) const
6236 : {
6237 90837 : for (std::size_t i = 0; i < branch_list.size(); ++i)
6238 : {
6239 66930 : collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
6240 : }
6241 23907 : }
6242 :
6243 : template <typename Boolean,
6244 : typename AllocatorT,
6245 : typename AllocatorB,
6246 : template <typename, typename> class Sequence,
6247 : typename NodeSequence>
6248 : void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list,
6249 : const Sequence<Boolean, AllocatorB>& branch_deletable_list,
6250 : NodeSequence& delete_node_list) const
6251 : {
6252 : for (std::size_t i = 0; i < branch_list.size(); ++i)
6253 : {
6254 : collect(branch_list[i], branch_deletable_list[i], delete_node_list);
6255 : }
6256 : }
6257 : };
6258 :
6259 : template <typename Type>
6260 : class vector_holder
6261 : {
6262 : private:
6263 :
6264 : typedef Type value_type;
6265 : typedef value_type* value_ptr;
6266 : typedef const value_ptr const_value_ptr;
6267 : typedef vector_holder<Type> vector_holder_t;
6268 :
6269 : class vector_holder_base
6270 : {
6271 : public:
6272 :
6273 0 : virtual ~vector_holder_base()
6274 0 : {}
6275 :
6276 88871 : inline value_ptr operator[](const std::size_t& index) const
6277 : {
6278 88871 : return value_at(index);
6279 : }
6280 :
6281 226115 : inline std::size_t size() const
6282 : {
6283 226115 : return vector_size();
6284 : }
6285 :
6286 151627 : inline std::size_t base_size() const
6287 : {
6288 151627 : return vector_base_size();
6289 : }
6290 :
6291 10391 : inline value_ptr data() const
6292 : {
6293 10391 : return value_at(0);
6294 : }
6295 :
6296 171868 : virtual inline bool rebaseable() const
6297 : {
6298 171868 : return false;
6299 : }
6300 :
6301 0 : virtual void set_ref(value_ptr*)
6302 0 : {}
6303 :
6304 478 : virtual void remove_ref(value_ptr*)
6305 478 : {}
6306 :
6307 0 : virtual vector_view<Type>* rebaseable_instance()
6308 : {
6309 0 : return reinterpret_cast<vector_view<Type>*>(0);
6310 : }
6311 :
6312 : protected:
6313 :
6314 : virtual value_ptr value_at(const std::size_t&) const = 0;
6315 : virtual std::size_t vector_size() const = 0;
6316 : virtual std::size_t vector_base_size() const = 0;
6317 : };
6318 :
6319 : class array_vector_impl exprtk_final : public vector_holder_base
6320 : {
6321 : public:
6322 :
6323 47281 : array_vector_impl(const Type* vec, const std::size_t& vec_size)
6324 47281 : : vec_(vec)
6325 47281 : , size_(vec_size)
6326 47281 : {}
6327 :
6328 : protected:
6329 :
6330 91444 : value_ptr value_at(const std::size_t& index) const exprtk_override
6331 : {
6332 91444 : assert(index < size_);
6333 91444 : return const_cast<const_value_ptr>(vec_ + index);
6334 : }
6335 :
6336 357633 : std::size_t vector_size() const exprtk_override
6337 : {
6338 357633 : return size_;
6339 : }
6340 :
6341 148211 : std::size_t vector_base_size() const exprtk_override
6342 : {
6343 148211 : return vector_size();
6344 : }
6345 :
6346 : private:
6347 :
6348 : array_vector_impl(const array_vector_impl&) exprtk_delete;
6349 : array_vector_impl& operator=(const array_vector_impl&) exprtk_delete;
6350 :
6351 : const Type* vec_;
6352 : const std::size_t size_;
6353 : };
6354 :
6355 : template <typename Allocator,
6356 : template <typename, typename> class Sequence>
6357 : class sequence_vector_impl exprtk_final : public vector_holder_base
6358 : {
6359 : public:
6360 :
6361 : typedef Sequence<Type,Allocator> sequence_t;
6362 :
6363 84 : explicit sequence_vector_impl(sequence_t& seq)
6364 84 : : sequence_(seq)
6365 84 : {}
6366 :
6367 : protected:
6368 :
6369 10 : value_ptr value_at(const std::size_t& index) const exprtk_override
6370 : {
6371 10 : assert(index < sequence_.size());
6372 10 : return (&sequence_[index]);
6373 : }
6374 :
6375 60 : std::size_t vector_size() const exprtk_override
6376 : {
6377 60 : return sequence_.size();
6378 : }
6379 :
6380 20 : std::size_t vector_base_size() const exprtk_override
6381 : {
6382 20 : return vector_size();
6383 : }
6384 :
6385 : private:
6386 :
6387 : sequence_vector_impl(const sequence_vector_impl&) exprtk_delete;
6388 : sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete;
6389 :
6390 : sequence_t& sequence_;
6391 : };
6392 :
6393 : class vector_view_impl exprtk_final : public vector_holder_base
6394 : {
6395 : public:
6396 :
6397 : typedef exprtk::vector_view<Type> vector_view_t;
6398 :
6399 4195 : vector_view_impl(vector_view_t& vec_view)
6400 4195 : : vec_view_(vec_view)
6401 : {
6402 4195 : assert(vec_view_.size() > 0);
6403 4195 : }
6404 :
6405 3559 : void set_ref(value_ptr* ref) exprtk_override
6406 : {
6407 3559 : vec_view_.set_ref(ref);
6408 3559 : }
6409 :
6410 3559 : void remove_ref(value_ptr* ref) exprtk_override
6411 : {
6412 3559 : vec_view_.remove_ref(ref);
6413 3559 : }
6414 :
6415 10649 : bool rebaseable() const exprtk_override
6416 : {
6417 10649 : return true;
6418 : }
6419 :
6420 658 : vector_view<Type>* rebaseable_instance() exprtk_override
6421 : {
6422 658 : return &vec_view_;
6423 : }
6424 :
6425 : protected:
6426 :
6427 7555 : value_ptr value_at(const std::size_t& index) const exprtk_override
6428 : {
6429 7555 : assert(index < vec_view_.size());
6430 7555 : return (&vec_view_[index]);
6431 : }
6432 :
6433 15714 : std::size_t vector_size() const exprtk_override
6434 : {
6435 15714 : return vec_view_.size();
6436 : }
6437 :
6438 2662 : std::size_t vector_base_size() const exprtk_override
6439 : {
6440 2662 : return vec_view_.base_size();
6441 : }
6442 :
6443 : private:
6444 :
6445 : vector_view_impl(const vector_view_impl&) exprtk_delete;
6446 : vector_view_impl& operator=(const vector_view_impl&) exprtk_delete;
6447 :
6448 : vector_view_t& vec_view_;
6449 : };
6450 :
6451 : class resizable_vector_impl exprtk_final : public vector_holder_base
6452 : {
6453 : public:
6454 :
6455 478 : resizable_vector_impl(vector_holder& vec_view_holder,
6456 : const Type* vec,
6457 : const std::size_t& vec_size)
6458 478 : : vec_(vec)
6459 478 : , size_(vec_size)
6460 478 : , vec_view_holder_(*vec_view_holder.rebaseable_instance())
6461 : {
6462 478 : assert(vec_view_holder.rebaseable_instance());
6463 478 : assert(size_ <= vector_base_size());
6464 478 : }
6465 :
6466 0 : virtual ~resizable_vector_impl()
6467 0 : {}
6468 :
6469 : protected:
6470 :
6471 253 : value_ptr value_at(const std::size_t& index) const exprtk_override
6472 : {
6473 253 : assert(index < vector_size());
6474 253 : return const_cast<const_value_ptr>(vec_ + index);
6475 : }
6476 :
6477 1192 : std::size_t vector_size() const exprtk_override
6478 : {
6479 1192 : return vec_view_holder_.size();
6480 : }
6481 :
6482 1212 : std::size_t vector_base_size() const exprtk_override
6483 : {
6484 1212 : return vec_view_holder_.base_size();
6485 : }
6486 :
6487 903 : bool rebaseable() const exprtk_override
6488 : {
6489 903 : return true;
6490 : }
6491 :
6492 520 : virtual vector_view<Type>* rebaseable_instance() exprtk_override
6493 : {
6494 520 : return &vec_view_holder_;
6495 : }
6496 :
6497 : private:
6498 :
6499 : resizable_vector_impl(const resizable_vector_impl&) exprtk_delete;
6500 : resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete;
6501 :
6502 : const Type* vec_;
6503 : const std::size_t size_;
6504 : vector_view<Type>& vec_view_holder_;
6505 : };
6506 :
6507 : public:
6508 :
6509 : typedef typename details::vec_data_store<Type> vds_t;
6510 :
6511 25420 : vector_holder(Type* vec, const std::size_t& vec_size)
6512 25420 : : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
6513 25420 : {}
6514 :
6515 21861 : explicit vector_holder(const vds_t& vds)
6516 21861 : : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
6517 21861 : {}
6518 :
6519 : template <typename Allocator>
6520 84 : explicit vector_holder(std::vector<Type,Allocator>& vec)
6521 84 : : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
6522 84 : {}
6523 :
6524 4195 : explicit vector_holder(exprtk::vector_view<Type>& vec)
6525 4195 : : vector_holder_base_(new(buffer)vector_view_impl(vec))
6526 4195 : {}
6527 :
6528 478 : explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds)
6529 478 : : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size()))
6530 478 : {}
6531 :
6532 88871 : inline value_ptr operator[](const std::size_t& index) const
6533 : {
6534 88871 : return (*vector_holder_base_)[index];
6535 : }
6536 :
6537 226115 : inline std::size_t size() const
6538 : {
6539 226115 : return vector_holder_base_->size();
6540 : }
6541 :
6542 151627 : inline std::size_t base_size() const
6543 : {
6544 151627 : return vector_holder_base_->base_size();
6545 : }
6546 :
6547 10391 : inline value_ptr data() const
6548 : {
6549 10391 : return vector_holder_base_->data();
6550 : }
6551 :
6552 49912 : void set_ref(value_ptr* ref)
6553 : {
6554 49912 : if (rebaseable())
6555 : {
6556 3559 : vector_holder_base_->set_ref(ref);
6557 : }
6558 49912 : }
6559 :
6560 72251 : void remove_ref(value_ptr* ref)
6561 : {
6562 72251 : if (rebaseable())
6563 : {
6564 4037 : vector_holder_base_->remove_ref(ref);
6565 : }
6566 72251 : }
6567 :
6568 183420 : bool rebaseable() const
6569 : {
6570 183420 : return vector_holder_base_->rebaseable();
6571 : }
6572 :
6573 1178 : vector_view<Type>* rebaseable_instance()
6574 : {
6575 1178 : return vector_holder_base_->rebaseable_instance();
6576 : }
6577 :
6578 : private:
6579 :
6580 : vector_holder(const vector_holder<Type>&) exprtk_delete;
6581 : vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete;
6582 :
6583 : mutable vector_holder_base* vector_holder_base_;
6584 : uchar_t buffer[64];
6585 : };
6586 :
6587 : template <typename T>
6588 : class null_node exprtk_final : public expression_node<T>
6589 : {
6590 : public:
6591 :
6592 377 : inline T value() const exprtk_override
6593 : {
6594 377 : return std::numeric_limits<T>::quiet_NaN();
6595 : }
6596 :
6597 693627 : inline typename expression_node<T>::node_type type() const exprtk_override
6598 : {
6599 693627 : return expression_node<T>::e_null;
6600 : }
6601 : };
6602 :
6603 : template <typename T, std::size_t N>
6604 9668080 : inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
6605 : expression_node<T>* b,
6606 : const std::size_t& index)
6607 : {
6608 9668080 : if (b && (index < N))
6609 : {
6610 1937233 : branch[index] = std::make_pair(b,branch_deletable(b));
6611 : }
6612 9668080 : }
6613 :
6614 : template <typename T>
6615 970327 : inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
6616 : {
6617 970327 : if (b)
6618 : {
6619 970112 : branch = std::make_pair(b,branch_deletable(b));
6620 : }
6621 970327 : }
6622 :
6623 : template <std::size_t N, typename T>
6624 966808 : inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
6625 : expression_node<T>* b0,
6626 : expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
6627 : expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
6628 : expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
6629 : expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
6630 : expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
6631 : expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
6632 : expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
6633 : expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
6634 : expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
6635 : {
6636 966808 : construct_branch_pair(branch, b0, 0);
6637 966808 : construct_branch_pair(branch, b1, 1);
6638 966808 : construct_branch_pair(branch, b2, 2);
6639 966808 : construct_branch_pair(branch, b3, 3);
6640 966808 : construct_branch_pair(branch, b4, 4);
6641 966808 : construct_branch_pair(branch, b5, 5);
6642 966808 : construct_branch_pair(branch, b6, 6);
6643 966808 : construct_branch_pair(branch, b7, 7);
6644 966808 : construct_branch_pair(branch, b8, 8);
6645 966808 : construct_branch_pair(branch, b9, 9);
6646 966808 : }
6647 :
6648 : template <typename T>
6649 : class null_eq_node exprtk_final : public expression_node<T>
6650 : {
6651 : public:
6652 :
6653 : typedef expression_node<T>* expression_ptr;
6654 : typedef std::pair<expression_ptr,bool> branch_t;
6655 :
6656 195 : explicit null_eq_node(expression_ptr branch, const bool equality = true)
6657 195 : : equality_(equality)
6658 : {
6659 195 : construct_branch_pair(branch_, branch);
6660 195 : assert(valid());
6661 195 : }
6662 :
6663 195 : inline T value() const exprtk_override
6664 : {
6665 195 : const T v = branch_.first->value();
6666 195 : const bool result = details::numeric::is_nan(v);
6667 :
6668 195 : if (result)
6669 195 : return equality_ ? T(1) : T(0);
6670 : else
6671 0 : return equality_ ? T(0) : T(1);
6672 : }
6673 :
6674 1170 : inline typename expression_node<T>::node_type type() const exprtk_override
6675 : {
6676 1170 : return expression_node<T>::e_nulleq;
6677 : }
6678 :
6679 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
6680 : {
6681 0 : return branch_.first;
6682 : }
6683 :
6684 225 : inline bool valid() const exprtk_override
6685 : {
6686 225 : return branch_.first;
6687 : }
6688 :
6689 195 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
6690 : {
6691 195 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
6692 195 : }
6693 :
6694 405 : std::size_t node_depth() const exprtk_override
6695 : {
6696 405 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
6697 : }
6698 :
6699 : private:
6700 :
6701 : bool equality_;
6702 : branch_t branch_;
6703 : };
6704 :
6705 : template <typename T>
6706 : class literal_node exprtk_final : public expression_node<T>
6707 : {
6708 : public:
6709 :
6710 2174244 : explicit literal_node(const T& v)
6711 2174244 : : value_(v)
6712 2174244 : {}
6713 :
6714 139260863 : inline T value() const exprtk_override
6715 : {
6716 139260863 : return value_;
6717 : }
6718 :
6719 31374113 : inline typename expression_node<T>::node_type type() const exprtk_override
6720 : {
6721 31374113 : return expression_node<T>::e_constant;
6722 : }
6723 :
6724 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
6725 : {
6726 0 : return reinterpret_cast<expression_node<T>*>(0);
6727 : }
6728 :
6729 : private:
6730 :
6731 : literal_node(const literal_node<T>&) exprtk_delete;
6732 : literal_node<T>& operator=(const literal_node<T>&) exprtk_delete;
6733 :
6734 : const T value_;
6735 : };
6736 :
6737 : template <typename T>
6738 : struct range_pack;
6739 :
6740 : template <typename T>
6741 : struct range_data_type;
6742 :
6743 : template <typename T>
6744 : class range_interface
6745 : {
6746 : public:
6747 :
6748 : typedef range_pack<T> range_t;
6749 :
6750 245984 : virtual ~range_interface()
6751 245984 : {}
6752 :
6753 : virtual range_t& range_ref() = 0;
6754 :
6755 : virtual const range_t& range_ref() const = 0;
6756 : };
6757 :
6758 : #ifndef exprtk_disable_string_capabilities
6759 : template <typename T>
6760 : class string_base_node
6761 : {
6762 : public:
6763 :
6764 : typedef range_data_type<T> range_data_type_t;
6765 :
6766 245984 : virtual ~string_base_node()
6767 245984 : {}
6768 :
6769 : virtual std::string str () const = 0;
6770 :
6771 : virtual char_cptr base() const = 0;
6772 :
6773 : virtual std::size_t size() const = 0;
6774 : };
6775 :
6776 : template <typename T>
6777 : class string_literal_node exprtk_final
6778 : : public expression_node <T>
6779 : , public string_base_node<T>
6780 : , public range_interface <T>
6781 : {
6782 : public:
6783 :
6784 : typedef range_pack<T> range_t;
6785 :
6786 55957 : explicit string_literal_node(const std::string& v)
6787 55957 : : value_(v)
6788 : {
6789 55957 : rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0);
6790 55957 : rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size());
6791 55957 : rp_.cache.first = rp_.n0_c.second;
6792 55957 : rp_.cache.second = rp_.n1_c.second;
6793 55957 : }
6794 :
6795 24518 : inline T value() const exprtk_override
6796 : {
6797 24518 : return std::numeric_limits<T>::quiet_NaN();
6798 : }
6799 :
6800 928968 : inline typename expression_node<T>::node_type type() const exprtk_override
6801 : {
6802 928968 : return expression_node<T>::e_stringconst;
6803 : }
6804 :
6805 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
6806 : {
6807 0 : return reinterpret_cast<expression_node<T>*>(0);
6808 : }
6809 :
6810 33183 : std::string str() const exprtk_override
6811 : {
6812 33183 : return value_;
6813 : }
6814 :
6815 21628 : char_cptr base() const exprtk_override
6816 : {
6817 21628 : return value_.data();
6818 : }
6819 :
6820 24478 : std::size_t size() const exprtk_override
6821 : {
6822 24478 : return value_.size();
6823 : }
6824 :
6825 20382 : range_t& range_ref() exprtk_override
6826 : {
6827 20382 : return rp_;
6828 : }
6829 :
6830 0 : const range_t& range_ref() const exprtk_override
6831 : {
6832 0 : return rp_;
6833 : }
6834 :
6835 : private:
6836 :
6837 : string_literal_node(const string_literal_node<T>&) exprtk_delete;
6838 : string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete;
6839 :
6840 : const std::string value_;
6841 : range_t rp_;
6842 : };
6843 : #endif
6844 :
6845 : template <typename T>
6846 : class unary_node : public expression_node<T>
6847 : {
6848 : public:
6849 :
6850 : typedef expression_node<T>* expression_ptr;
6851 : typedef std::pair<expression_ptr,bool> branch_t;
6852 :
6853 103460 : unary_node(const operator_type& opr, expression_ptr branch)
6854 103460 : : operation_(opr)
6855 : {
6856 103460 : construct_branch_pair(branch_,branch);
6857 103460 : assert(valid());
6858 103460 : }
6859 :
6860 100770 : inline T value() const exprtk_override
6861 : {
6862 : return numeric::process<T>
6863 100770 : (operation_,branch_.first->value());
6864 : }
6865 :
6866 201540 : inline typename expression_node<T>::node_type type() const exprtk_override
6867 : {
6868 201540 : return expression_node<T>::e_unary;
6869 : }
6870 :
6871 : inline operator_type operation()
6872 : {
6873 : return operation_;
6874 : }
6875 :
6876 10744 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
6877 : {
6878 10744 : return branch_.first;
6879 : }
6880 :
6881 120624 : inline bool valid() const exprtk_override
6882 : {
6883 120624 : return branch_.first && branch_.first->valid();
6884 : }
6885 :
6886 : inline void release()
6887 : {
6888 : branch_.second = false;
6889 : }
6890 :
6891 103460 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
6892 : {
6893 103460 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
6894 103460 : }
6895 :
6896 208158 : std::size_t node_depth() const exprtk_final
6897 : {
6898 208158 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
6899 : }
6900 :
6901 : private:
6902 :
6903 : operator_type operation_;
6904 : branch_t branch_;
6905 : };
6906 :
6907 : template <typename T>
6908 : class binary_node : public expression_node<T>
6909 : {
6910 : public:
6911 :
6912 : typedef expression_node<T>* expression_ptr;
6913 : typedef std::pair<expression_ptr,bool> branch_t;
6914 :
6915 556999 : binary_node(const operator_type& opr,
6916 : expression_ptr branch0,
6917 : expression_ptr branch1)
6918 556999 : : operation_(opr)
6919 : {
6920 556999 : init_branches<2>(branch_, branch0, branch1);
6921 556999 : assert(valid());
6922 556999 : }
6923 :
6924 449085 : inline T value() const exprtk_override
6925 : {
6926 : return numeric::process<T>
6927 1796340 : (
6928 449085 : operation_,
6929 449085 : branch_[0].first->value(),
6930 449085 : branch_[1].first->value()
6931 449085 : );
6932 : }
6933 :
6934 2290787 : inline typename expression_node<T>::node_type type() const exprtk_override
6935 : {
6936 2290787 : return expression_node<T>::e_binary;
6937 : }
6938 :
6939 : inline operator_type operation()
6940 : {
6941 : return operation_;
6942 : }
6943 :
6944 208795773 : inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
6945 : {
6946 208795773 : assert(index < 2);
6947 208795773 : return branch_[index].first;
6948 : }
6949 :
6950 1080684 : inline bool valid() const exprtk_override
6951 : {
6952 : return
6953 1080684 : branch_[0].first && branch_[0].first->valid() &&
6954 2161368 : branch_[1].first && branch_[1].first->valid() ;
6955 : }
6956 :
6957 556999 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
6958 : {
6959 556999 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
6960 556999 : }
6961 :
6962 1497235 : std::size_t node_depth() const exprtk_final
6963 : {
6964 1497235 : return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
6965 : }
6966 :
6967 : private:
6968 :
6969 : operator_type operation_;
6970 : branch_t branch_[2];
6971 : };
6972 :
6973 : template <typename T, typename Operation>
6974 : class binary_ext_node exprtk_final : public expression_node<T>
6975 : {
6976 : public:
6977 :
6978 : typedef expression_node<T>* expression_ptr;
6979 : typedef std::pair<expression_ptr,bool> branch_t;
6980 :
6981 407007 : binary_ext_node(expression_ptr branch0, expression_ptr branch1)
6982 407007 : {
6983 407007 : init_branches<2>(branch_, branch0, branch1);
6984 407007 : assert(valid());
6985 407007 : }
6986 :
6987 63295748 : inline T value() const exprtk_override
6988 : {
6989 63295748 : const T arg0 = branch_[0].first->value();
6990 63295748 : const T arg1 = branch_[1].first->value();
6991 126591496 : return Operation::process(arg0,arg1);
6992 : }
6993 :
6994 11834392 : inline typename expression_node<T>::node_type type() const exprtk_override
6995 : {
6996 11834392 : return expression_node<T>::e_binary_ext;
6997 : }
6998 :
6999 : inline operator_type operation()
7000 : {
7001 : return Operation::operation();
7002 : }
7003 :
7004 0 : inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override
7005 : {
7006 0 : assert(index < 2);
7007 0 : return branch_[index].first;
7008 : }
7009 :
7010 2723515 : inline bool valid() const exprtk_override
7011 : {
7012 : return
7013 2723515 : branch_[0].first && branch_[0].first->valid() &&
7014 5447030 : branch_[1].first && branch_[1].first->valid() ;
7015 : }
7016 :
7017 407007 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7018 : {
7019 407007 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
7020 407007 : }
7021 :
7022 1213243 : std::size_t node_depth() const exprtk_override
7023 : {
7024 1213243 : return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
7025 : }
7026 :
7027 : protected:
7028 :
7029 : branch_t branch_[2];
7030 : };
7031 :
7032 : template <typename T>
7033 : class trinary_node : public expression_node<T>
7034 : {
7035 : public:
7036 :
7037 : typedef expression_node<T>* expression_ptr;
7038 : typedef std::pair<expression_ptr,bool> branch_t;
7039 :
7040 1987 : trinary_node(const operator_type& opr,
7041 : expression_ptr branch0,
7042 : expression_ptr branch1,
7043 : expression_ptr branch2)
7044 1987 : : operation_(opr)
7045 : {
7046 1987 : init_branches<3>(branch_, branch0, branch1, branch2);
7047 1987 : assert(valid());
7048 1987 : }
7049 :
7050 40000116 : inline T value() const exprtk_override
7051 : {
7052 40000116 : const T arg0 = branch_[0].first->value();
7053 40000116 : const T arg1 = branch_[1].first->value();
7054 40000116 : const T arg2 = branch_[2].first->value();
7055 :
7056 40000116 : switch (operation_)
7057 : {
7058 30 : case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
7059 :
7060 40000086 : case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
7061 :
7062 0 : case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
7063 0 : return arg1;
7064 : else
7065 0 : return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
7066 :
7067 0 : default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
7068 0 : return std::numeric_limits<T>::quiet_NaN();
7069 : }
7070 : }
7071 :
7072 1705 : inline typename expression_node<T>::node_type type() const exprtk_override
7073 : {
7074 1705 : return expression_node<T>::e_trinary;
7075 : }
7076 :
7077 1998 : inline bool valid() const exprtk_override
7078 : {
7079 : return
7080 1998 : branch_[0].first && branch_[0].first->valid() &&
7081 1998 : branch_[1].first && branch_[1].first->valid() &&
7082 3996 : branch_[2].first && branch_[2].first->valid() ;
7083 : }
7084 :
7085 1987 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7086 : {
7087 1987 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
7088 1987 : }
7089 :
7090 5497 : std::size_t node_depth() const exprtk_override exprtk_final
7091 : {
7092 5497 : return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
7093 : }
7094 :
7095 : protected:
7096 :
7097 : operator_type operation_;
7098 : branch_t branch_[3];
7099 : };
7100 :
7101 : template <typename T>
7102 : class quaternary_node : public expression_node<T>
7103 : {
7104 : public:
7105 :
7106 : typedef expression_node<T>* expression_ptr;
7107 : typedef std::pair<expression_ptr,bool> branch_t;
7108 :
7109 815 : quaternary_node(const operator_type& opr,
7110 : expression_ptr branch0,
7111 : expression_ptr branch1,
7112 : expression_ptr branch2,
7113 : expression_ptr branch3)
7114 815 : : operation_(opr)
7115 : {
7116 815 : init_branches<4>(branch_, branch0, branch1, branch2, branch3);
7117 815 : }
7118 :
7119 0 : inline T value() const exprtk_override
7120 : {
7121 0 : return std::numeric_limits<T>::quiet_NaN();
7122 : }
7123 :
7124 1630 : inline typename expression_node<T>::node_type type() const exprtk_override
7125 : {
7126 1630 : return expression_node<T>::e_quaternary;
7127 : }
7128 :
7129 815 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7130 : {
7131 815 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
7132 815 : }
7133 :
7134 1630 : std::size_t node_depth() const exprtk_override exprtk_final
7135 : {
7136 1630 : return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
7137 : }
7138 :
7139 0 : inline bool valid() const exprtk_override
7140 : {
7141 : return
7142 0 : branch_[0].first && branch_[0].first->valid() &&
7143 0 : branch_[1].first && branch_[1].first->valid() &&
7144 0 : branch_[2].first && branch_[2].first->valid() &&
7145 0 : branch_[3].first && branch_[3].first->valid() ;
7146 : }
7147 :
7148 : protected:
7149 :
7150 : operator_type operation_;
7151 : branch_t branch_[4];
7152 : };
7153 :
7154 : template <typename T>
7155 : class conditional_node exprtk_final : public expression_node<T>
7156 : {
7157 : public:
7158 :
7159 : typedef expression_node<T>* expression_ptr;
7160 : typedef std::pair<expression_ptr,bool> branch_t;
7161 :
7162 2847 : conditional_node(expression_ptr condition,
7163 : expression_ptr consequent,
7164 : expression_ptr alternative)
7165 2847 : {
7166 2847 : construct_branch_pair(condition_ , condition );
7167 2847 : construct_branch_pair(consequent_ , consequent );
7168 2847 : construct_branch_pair(alternative_, alternative);
7169 2847 : assert(valid());
7170 2847 : }
7171 :
7172 57799451 : inline T value() const exprtk_override
7173 : {
7174 57799451 : if (is_true(condition_))
7175 21746104 : return consequent_.first->value();
7176 : else
7177 36053347 : return alternative_.first->value();
7178 : }
7179 :
7180 54062 : inline typename expression_node<T>::node_type type() const exprtk_override
7181 : {
7182 54062 : return expression_node<T>::e_conditional;
7183 : }
7184 :
7185 9662 : inline bool valid() const exprtk_override
7186 : {
7187 : return
7188 9662 : condition_ .first && condition_ .first->valid() &&
7189 9662 : consequent_ .first && consequent_ .first->valid() &&
7190 19324 : alternative_.first && alternative_.first->valid() ;
7191 : }
7192 :
7193 2847 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7194 : {
7195 2847 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7196 2847 : expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
7197 2847 : expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
7198 2847 : }
7199 :
7200 6979 : std::size_t node_depth() const exprtk_override
7201 : {
7202 : return expression_node<T>::ndb_t::compute_node_depth
7203 6979 : (condition_, consequent_, alternative_);
7204 : }
7205 :
7206 : private:
7207 :
7208 : branch_t condition_;
7209 : branch_t consequent_;
7210 : branch_t alternative_;
7211 : };
7212 :
7213 : template <typename T>
7214 : class cons_conditional_node exprtk_final : public expression_node<T>
7215 : {
7216 : public:
7217 :
7218 : // Consequent only conditional statement node
7219 : typedef expression_node<T>* expression_ptr;
7220 : typedef std::pair<expression_ptr,bool> branch_t;
7221 :
7222 1031 : cons_conditional_node(expression_ptr condition,
7223 : expression_ptr consequent)
7224 1031 : {
7225 1031 : construct_branch_pair(condition_ , condition );
7226 1031 : construct_branch_pair(consequent_, consequent);
7227 1031 : assert(valid());
7228 1031 : }
7229 :
7230 10006020 : inline T value() const exprtk_override
7231 : {
7232 10006020 : if (is_true(condition_))
7233 666067 : return consequent_.first->value();
7234 : else
7235 9339953 : return std::numeric_limits<T>::quiet_NaN();
7236 : }
7237 :
7238 14489 : inline typename expression_node<T>::node_type type() const exprtk_override
7239 : {
7240 14489 : return expression_node<T>::e_conditional;
7241 : }
7242 :
7243 4738 : inline bool valid() const exprtk_override
7244 : {
7245 : return
7246 4738 : condition_ .first && condition_ .first->valid() &&
7247 9476 : consequent_.first && consequent_.first->valid() ;
7248 : }
7249 :
7250 1031 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7251 : {
7252 1031 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7253 1031 : expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
7254 1031 : }
7255 :
7256 2261 : std::size_t node_depth() const exprtk_override
7257 : {
7258 : return expression_node<T>::ndb_t::
7259 2261 : compute_node_depth(condition_, consequent_);
7260 : }
7261 :
7262 : private:
7263 :
7264 : branch_t condition_;
7265 : branch_t consequent_;
7266 : };
7267 :
7268 : #ifndef exprtk_disable_break_continue
7269 : template <typename T>
7270 : class break_exception
7271 : {
7272 : public:
7273 :
7274 372198 : explicit break_exception(const T& v)
7275 372198 : : value(v)
7276 372198 : {}
7277 :
7278 : T value;
7279 : };
7280 :
7281 : class continue_exception {};
7282 :
7283 : template <typename T>
7284 : class break_node exprtk_final : public expression_node<T>
7285 : {
7286 : public:
7287 :
7288 : typedef expression_node<T>* expression_ptr;
7289 : typedef std::pair<expression_ptr,bool> branch_t;
7290 :
7291 483 : explicit break_node(expression_ptr ret = expression_ptr(0))
7292 483 : {
7293 483 : construct_branch_pair(return_, ret);
7294 483 : }
7295 :
7296 372198 : inline T value() const exprtk_override
7297 : {
7298 372198 : const T result = return_.first ?
7299 1738 : return_.first->value() :
7300 370460 : std::numeric_limits<T>::quiet_NaN();
7301 :
7302 372198 : throw break_exception<T>(result);
7303 :
7304 : #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
7305 : return std::numeric_limits<T>::quiet_NaN();
7306 : #endif
7307 : }
7308 :
7309 3418 : inline typename expression_node<T>::node_type type() const exprtk_override
7310 : {
7311 3418 : return expression_node<T>::e_break;
7312 : }
7313 :
7314 483 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7315 : {
7316 483 : expression_node<T>::ndb_t::collect(return_, node_delete_list);
7317 483 : }
7318 :
7319 1528 : std::size_t node_depth() const exprtk_override
7320 : {
7321 1528 : return expression_node<T>::ndb_t::compute_node_depth(return_);
7322 : }
7323 :
7324 : private:
7325 :
7326 : branch_t return_;
7327 : };
7328 :
7329 : template <typename T>
7330 : class continue_node exprtk_final : public expression_node<T>
7331 : {
7332 : public:
7333 :
7334 1480 : inline T value() const exprtk_override
7335 : {
7336 1480 : throw continue_exception();
7337 : #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
7338 : return std::numeric_limits<T>::quiet_NaN();
7339 : #endif
7340 : }
7341 :
7342 2560 : inline typename expression_node<T>::node_type type() const exprtk_override
7343 : {
7344 2560 : return expression_node<T>::e_break;
7345 : }
7346 : };
7347 : #endif
7348 :
7349 : struct loop_runtime_checker
7350 : {
7351 0 : loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check,
7352 : loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
7353 0 : : iteration_count_(0)
7354 0 : , loop_runtime_check_(loop_runtime_check)
7355 0 : , max_loop_iterations_(loop_runtime_check_->max_loop_iterations)
7356 0 : , loop_type_(lp_typ)
7357 : {
7358 0 : assert(loop_runtime_check_);
7359 0 : }
7360 :
7361 0 : inline void reset(const _uint64_t initial_value = 0) const
7362 : {
7363 0 : iteration_count_ = initial_value;
7364 0 : }
7365 :
7366 0 : inline bool check() const
7367 : {
7368 0 : assert(loop_runtime_check_);
7369 :
7370 0 : if (
7371 0 : (++iteration_count_ <= max_loop_iterations_) &&
7372 0 : loop_runtime_check_->check()
7373 : )
7374 : {
7375 0 : return true;
7376 : }
7377 :
7378 : loop_runtime_check::violation_context ctxt;
7379 0 : ctxt.loop = loop_type_;
7380 0 : ctxt.violation = loop_runtime_check::e_iteration_count;
7381 :
7382 0 : loop_runtime_check_->handle_runtime_violation(ctxt);
7383 :
7384 0 : return false;
7385 : }
7386 :
7387 0 : bool valid() const
7388 : {
7389 0 : return 0 != loop_runtime_check_;
7390 : }
7391 :
7392 : mutable _uint64_t iteration_count_;
7393 : mutable loop_runtime_check_ptr loop_runtime_check_;
7394 : const details::_uint64_t& max_loop_iterations_;
7395 : loop_runtime_check::loop_types loop_type_;
7396 : };
7397 :
7398 : template <typename T>
7399 : class while_loop_node : public expression_node<T>
7400 : {
7401 : public:
7402 :
7403 : typedef expression_node<T>* expression_ptr;
7404 : typedef std::pair<expression_ptr,bool> branch_t;
7405 :
7406 22 : while_loop_node(expression_ptr condition,
7407 : expression_ptr loop_body)
7408 22 : {
7409 22 : construct_branch_pair(condition_, condition);
7410 22 : construct_branch_pair(loop_body_, loop_body);
7411 22 : assert(valid());
7412 22 : }
7413 :
7414 176 : inline T value() const exprtk_override
7415 : {
7416 176 : T result = T(0);
7417 :
7418 26728 : while (is_true(condition_))
7419 : {
7420 26552 : result = loop_body_.first->value();
7421 : }
7422 :
7423 176 : return result;
7424 : }
7425 :
7426 231 : inline typename expression_node<T>::node_type type() const exprtk_override
7427 : {
7428 231 : return expression_node<T>::e_while;
7429 : }
7430 :
7431 75 : inline bool valid() const exprtk_override
7432 : {
7433 : return
7434 75 : condition_.first && condition_.first->valid() &&
7435 150 : loop_body_.first && loop_body_.first->valid() ;
7436 : }
7437 :
7438 22 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7439 : {
7440 22 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7441 22 : expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
7442 22 : }
7443 :
7444 45 : std::size_t node_depth() const exprtk_override
7445 : {
7446 45 : return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7447 : }
7448 :
7449 : protected:
7450 :
7451 : branch_t condition_;
7452 : branch_t loop_body_;
7453 : };
7454 :
7455 : template <typename T>
7456 : class while_loop_rtc_node exprtk_final
7457 : : public while_loop_node<T>
7458 : , public loop_runtime_checker
7459 : {
7460 : public:
7461 :
7462 : typedef while_loop_node<T> parent_t;
7463 : typedef expression_node<T>* expression_ptr;
7464 :
7465 0 : while_loop_rtc_node(expression_ptr condition,
7466 : expression_ptr loop_body,
7467 : loop_runtime_check_ptr loop_rt_chk)
7468 : : parent_t(condition, loop_body)
7469 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
7470 : {
7471 0 : assert(valid());
7472 0 : }
7473 :
7474 0 : inline T value() const exprtk_override
7475 : {
7476 :
7477 0 : T result = T(0);
7478 :
7479 0 : loop_runtime_checker::reset();
7480 :
7481 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
7482 : {
7483 0 : result = parent_t::loop_body_.first->value();
7484 : }
7485 :
7486 0 : return result;
7487 : }
7488 :
7489 : using parent_t::valid;
7490 :
7491 0 : bool valid() const exprtk_override exprtk_final
7492 : {
7493 0 : return parent_t::valid() &&
7494 0 : loop_runtime_checker::valid();
7495 : }
7496 : };
7497 :
7498 : template <typename T>
7499 : class repeat_until_loop_node : public expression_node<T>
7500 : {
7501 : public:
7502 :
7503 : typedef expression_node<T>* expression_ptr;
7504 : typedef std::pair<expression_ptr,bool> branch_t;
7505 :
7506 2 : repeat_until_loop_node(expression_ptr condition,
7507 : expression_ptr loop_body)
7508 2 : {
7509 2 : construct_branch_pair(condition_, condition);
7510 2 : construct_branch_pair(loop_body_, loop_body);
7511 2 : assert(valid());
7512 2 : }
7513 :
7514 30 : inline T value() const exprtk_override
7515 : {
7516 30 : T result = T(0);
7517 :
7518 : do
7519 : {
7520 465 : result = loop_body_.first->value();
7521 : }
7522 465 : while (is_false(condition_.first));
7523 :
7524 30 : return result;
7525 : }
7526 :
7527 9 : inline typename expression_node<T>::node_type type() const exprtk_override
7528 : {
7529 9 : return expression_node<T>::e_repeat;
7530 : }
7531 :
7532 7 : inline bool valid() const exprtk_override
7533 : {
7534 : return
7535 7 : condition_.first && condition_.first->valid() &&
7536 14 : loop_body_.first && loop_body_.first->valid() ;
7537 : }
7538 :
7539 2 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7540 : {
7541 2 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7542 2 : expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
7543 2 : }
7544 :
7545 4 : std::size_t node_depth() const exprtk_override
7546 : {
7547 4 : return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7548 : }
7549 :
7550 : protected:
7551 :
7552 : branch_t condition_;
7553 : branch_t loop_body_;
7554 : };
7555 :
7556 : template <typename T>
7557 : class repeat_until_loop_rtc_node exprtk_final
7558 : : public repeat_until_loop_node<T>
7559 : , public loop_runtime_checker
7560 : {
7561 : public:
7562 :
7563 : typedef repeat_until_loop_node<T> parent_t;
7564 : typedef expression_node<T>* expression_ptr;
7565 :
7566 0 : repeat_until_loop_rtc_node(expression_ptr condition,
7567 : expression_ptr loop_body,
7568 : loop_runtime_check_ptr loop_rt_chk)
7569 : : parent_t(condition, loop_body)
7570 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
7571 : {
7572 0 : assert(valid());
7573 0 : }
7574 :
7575 0 : inline T value() const exprtk_override
7576 : {
7577 0 : T result = T(0);
7578 :
7579 0 : loop_runtime_checker::reset(1);
7580 :
7581 : do
7582 : {
7583 0 : result = parent_t::loop_body_.first->value();
7584 : }
7585 0 : while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
7586 :
7587 0 : return result;
7588 : }
7589 :
7590 : using parent_t::valid;
7591 :
7592 0 : inline bool valid() const exprtk_override exprtk_final
7593 : {
7594 0 : return parent_t::valid() &&
7595 0 : loop_runtime_checker::valid();
7596 : }
7597 : };
7598 :
7599 : template <typename T>
7600 : class for_loop_node : public expression_node<T>
7601 : {
7602 : public:
7603 :
7604 : typedef expression_node<T>* expression_ptr;
7605 : typedef std::pair<expression_ptr,bool> branch_t;
7606 :
7607 2723 : for_loop_node(expression_ptr initialiser,
7608 : expression_ptr condition,
7609 : expression_ptr incrementor,
7610 : expression_ptr loop_body)
7611 2723 : {
7612 2723 : construct_branch_pair(initialiser_, initialiser);
7613 2723 : construct_branch_pair(condition_ , condition );
7614 2723 : construct_branch_pair(incrementor_, incrementor);
7615 2723 : construct_branch_pair(loop_body_ , loop_body );
7616 2723 : assert(valid());
7617 2723 : }
7618 :
7619 6776 : inline T value() const exprtk_override
7620 : {
7621 6776 : T result = T(0);
7622 :
7623 6776 : if (initialiser_.first)
7624 6776 : initialiser_.first->value();
7625 :
7626 6776 : if (incrementor_.first)
7627 : {
7628 93358890 : while (is_true(condition_))
7629 : {
7630 93352241 : result = loop_body_.first->value();
7631 93352234 : incrementor_.first->value();
7632 : }
7633 : }
7634 : else
7635 : {
7636 1020 : while (is_true(condition_))
7637 : {
7638 900 : result = loop_body_.first->value();
7639 : }
7640 : }
7641 :
7642 6769 : return result;
7643 : }
7644 :
7645 39051 : inline typename expression_node<T>::node_type type() const exprtk_override
7646 : {
7647 39051 : return expression_node<T>::e_for;
7648 : }
7649 :
7650 9045 : inline bool valid() const exprtk_override
7651 : {
7652 9045 : return condition_.first && loop_body_.first;
7653 : }
7654 :
7655 2723 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
7656 : {
7657 2723 : expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list);
7658 2723 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
7659 2723 : expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list);
7660 2723 : expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list);
7661 2723 : }
7662 :
7663 6774 : std::size_t node_depth() const exprtk_override
7664 : {
7665 : return expression_node<T>::ndb_t::compute_node_depth
7666 6774 : (initialiser_, condition_, incrementor_, loop_body_);
7667 : }
7668 :
7669 : protected:
7670 :
7671 : branch_t initialiser_;
7672 : branch_t condition_ ;
7673 : branch_t incrementor_;
7674 : branch_t loop_body_ ;
7675 : };
7676 :
7677 : template <typename T>
7678 : class for_loop_rtc_node exprtk_final
7679 : : public for_loop_node<T>
7680 : , public loop_runtime_checker
7681 : {
7682 : public:
7683 :
7684 : typedef for_loop_node<T> parent_t;
7685 : typedef expression_node<T>* expression_ptr;
7686 :
7687 0 : for_loop_rtc_node(expression_ptr initialiser,
7688 : expression_ptr condition,
7689 : expression_ptr incrementor,
7690 : expression_ptr loop_body,
7691 : loop_runtime_check_ptr loop_rt_chk)
7692 : : parent_t(initialiser, condition, incrementor, loop_body)
7693 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
7694 : {
7695 0 : assert(valid());
7696 0 : }
7697 :
7698 0 : inline T value() const exprtk_override
7699 : {
7700 0 : T result = T(0);
7701 :
7702 0 : loop_runtime_checker::reset();
7703 :
7704 0 : if (parent_t::initialiser_.first)
7705 0 : parent_t::initialiser_.first->value();
7706 :
7707 0 : if (parent_t::incrementor_.first)
7708 : {
7709 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
7710 : {
7711 0 : result = parent_t::loop_body_.first->value();
7712 0 : parent_t::incrementor_.first->value();
7713 : }
7714 : }
7715 : else
7716 : {
7717 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
7718 : {
7719 0 : result = parent_t::loop_body_.first->value();
7720 : }
7721 : }
7722 :
7723 0 : return result;
7724 : }
7725 :
7726 : using parent_t::valid;
7727 :
7728 0 : inline bool valid() const exprtk_override exprtk_final
7729 : {
7730 0 : return parent_t::valid() &&
7731 0 : loop_runtime_checker::valid();
7732 : }
7733 : };
7734 :
7735 : #ifndef exprtk_disable_break_continue
7736 : template <typename T>
7737 : class while_loop_bc_node : public while_loop_node<T>
7738 : {
7739 : public:
7740 :
7741 : typedef while_loop_node<T> parent_t;
7742 : typedef expression_node<T>* expression_ptr;
7743 :
7744 10 : while_loop_bc_node(expression_ptr condition,
7745 : expression_ptr loop_body)
7746 10 : : parent_t(condition, loop_body)
7747 : {
7748 10 : assert(parent_t::valid());
7749 10 : }
7750 :
7751 100 : inline T value() const exprtk_override
7752 : {
7753 100 : T result = T(0);
7754 :
7755 650 : while (is_true(parent_t::condition_))
7756 : {
7757 : try
7758 : {
7759 650 : result = parent_t::loop_body_.first->value();
7760 : }
7761 100 : catch(const break_exception<T>& e)
7762 : {
7763 100 : return e.value;
7764 : }
7765 0 : catch(const continue_exception&)
7766 : {}
7767 : }
7768 :
7769 0 : return result;
7770 : }
7771 : };
7772 :
7773 : template <typename T>
7774 : class while_loop_bc_rtc_node exprtk_final
7775 : : public while_loop_bc_node<T>
7776 : , public loop_runtime_checker
7777 : {
7778 : public:
7779 :
7780 : typedef while_loop_bc_node<T> parent_t;
7781 : typedef expression_node<T>* expression_ptr;
7782 :
7783 0 : while_loop_bc_rtc_node(expression_ptr condition,
7784 : expression_ptr loop_body,
7785 : loop_runtime_check_ptr loop_rt_chk)
7786 : : parent_t(condition, loop_body)
7787 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
7788 : {
7789 0 : assert(valid());
7790 0 : }
7791 :
7792 0 : inline T value() const exprtk_override
7793 : {
7794 0 : T result = T(0);
7795 :
7796 0 : loop_runtime_checker::reset();
7797 :
7798 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
7799 : {
7800 : try
7801 : {
7802 0 : result = parent_t::loop_body_.first->value();
7803 : }
7804 0 : catch(const break_exception<T>& e)
7805 : {
7806 0 : return e.value;
7807 : }
7808 0 : catch(const continue_exception&)
7809 : {}
7810 : }
7811 :
7812 0 : return result;
7813 : }
7814 :
7815 : using parent_t::valid;
7816 :
7817 0 : inline bool valid() const exprtk_override exprtk_final
7818 : {
7819 0 : return parent_t::valid() &&
7820 0 : loop_runtime_checker::valid();
7821 : }
7822 : };
7823 :
7824 : template <typename T>
7825 : class repeat_until_loop_bc_node : public repeat_until_loop_node<T>
7826 : {
7827 : public:
7828 :
7829 : typedef repeat_until_loop_node<T> parent_t;
7830 : typedef expression_node<T>* expression_ptr;
7831 :
7832 1 : repeat_until_loop_bc_node(expression_ptr condition,
7833 : expression_ptr loop_body)
7834 1 : : parent_t(condition, loop_body)
7835 : {
7836 1 : assert(parent_t::valid());
7837 1 : }
7838 :
7839 98 : inline T value() const exprtk_override
7840 : {
7841 98 : T result = T(0);
7842 :
7843 : do
7844 : {
7845 : try
7846 : {
7847 548 : result = parent_t::loop_body_.first->value();
7848 : }
7849 98 : catch(const break_exception<T>& e)
7850 : {
7851 98 : return e.value;
7852 : }
7853 0 : catch(const continue_exception&)
7854 : {}
7855 : }
7856 450 : while (is_false(parent_t::condition_.first));
7857 :
7858 0 : return result;
7859 : }
7860 : };
7861 :
7862 : template <typename T>
7863 : class repeat_until_loop_bc_rtc_node exprtk_final
7864 : : public repeat_until_loop_bc_node<T>
7865 : , public loop_runtime_checker
7866 : {
7867 : public:
7868 :
7869 : typedef repeat_until_loop_bc_node<T> parent_t;
7870 : typedef expression_node<T>* expression_ptr;
7871 :
7872 0 : repeat_until_loop_bc_rtc_node(expression_ptr condition,
7873 : expression_ptr loop_body,
7874 : loop_runtime_check_ptr loop_rt_chk)
7875 : : parent_t(condition, loop_body)
7876 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
7877 : {
7878 0 : assert(valid());
7879 0 : }
7880 :
7881 0 : inline T value() const exprtk_override
7882 : {
7883 0 : T result = T(0);
7884 :
7885 0 : loop_runtime_checker::reset();
7886 :
7887 : do
7888 : {
7889 : try
7890 : {
7891 0 : result = parent_t::loop_body_.first->value();
7892 : }
7893 0 : catch(const break_exception<T>& e)
7894 : {
7895 0 : return e.value;
7896 : }
7897 0 : catch(const continue_exception&)
7898 : {}
7899 : }
7900 0 : while (is_false(parent_t::condition_.first) && loop_runtime_checker::check());
7901 :
7902 0 : return result;
7903 : }
7904 :
7905 : using parent_t::valid;
7906 :
7907 0 : inline bool valid() const exprtk_override exprtk_final
7908 : {
7909 0 : return parent_t::valid() &&
7910 0 : loop_runtime_checker::valid();
7911 : }
7912 : };
7913 :
7914 : template <typename T>
7915 : class for_loop_bc_node : public for_loop_node<T>
7916 : {
7917 : public:
7918 :
7919 : typedef for_loop_node<T> parent_t;
7920 : typedef expression_node<T>* expression_ptr;
7921 :
7922 612 : for_loop_bc_node(expression_ptr initialiser,
7923 : expression_ptr condition,
7924 : expression_ptr incrementor,
7925 : expression_ptr loop_body)
7926 612 : : parent_t(initialiser, condition, incrementor, loop_body)
7927 : {
7928 612 : assert(parent_t::valid());
7929 612 : }
7930 :
7931 486072 : inline T value() const exprtk_override
7932 : {
7933 486072 : T result = T(0);
7934 :
7935 486072 : if (parent_t::initialiser_.first)
7936 486072 : parent_t::initialiser_.first->value();
7937 :
7938 486072 : if (parent_t::incrementor_.first)
7939 : {
7940 5131214 : while (is_true(parent_t::condition_))
7941 : {
7942 : try
7943 : {
7944 5017142 : result = parent_t::loop_body_.first->value();
7945 : }
7946 373480 : catch(const break_exception<T>& e)
7947 : {
7948 372000 : return e.value;
7949 : }
7950 1480 : catch(const continue_exception&)
7951 : {}
7952 :
7953 4645142 : parent_t::incrementor_.first->value();
7954 : }
7955 : }
7956 : else
7957 : {
7958 0 : while (is_true(parent_t::condition_))
7959 : {
7960 : try
7961 : {
7962 0 : result = parent_t::loop_body_.first->value();
7963 : }
7964 0 : catch(const break_exception<T>& e)
7965 : {
7966 0 : return e.value;
7967 : }
7968 0 : catch(const continue_exception&)
7969 : {}
7970 : }
7971 : }
7972 :
7973 114072 : return result;
7974 : }
7975 : };
7976 :
7977 : template <typename T>
7978 : class for_loop_bc_rtc_node exprtk_final
7979 : : public for_loop_bc_node<T>
7980 : , public loop_runtime_checker
7981 : {
7982 : public:
7983 :
7984 : typedef for_loop_bc_node<T> parent_t;
7985 : typedef expression_node<T>* expression_ptr;
7986 :
7987 0 : for_loop_bc_rtc_node(expression_ptr initialiser,
7988 : expression_ptr condition,
7989 : expression_ptr incrementor,
7990 : expression_ptr loop_body,
7991 : loop_runtime_check_ptr loop_rt_chk)
7992 : : parent_t(initialiser, condition, incrementor, loop_body)
7993 0 : , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
7994 : {
7995 0 : assert(valid());
7996 0 : }
7997 :
7998 0 : inline T value() const exprtk_override
7999 : {
8000 0 : T result = T(0);
8001 :
8002 0 : loop_runtime_checker::reset();
8003 :
8004 0 : if (parent_t::initialiser_.first)
8005 0 : parent_t::initialiser_.first->value();
8006 :
8007 0 : if (parent_t::incrementor_.first)
8008 : {
8009 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
8010 : {
8011 : try
8012 : {
8013 0 : result = parent_t::loop_body_.first->value();
8014 : }
8015 0 : catch(const break_exception<T>& e)
8016 : {
8017 0 : return e.value;
8018 : }
8019 0 : catch(const continue_exception&)
8020 : {}
8021 :
8022 0 : parent_t::incrementor_.first->value();
8023 : }
8024 : }
8025 : else
8026 : {
8027 0 : while (is_true(parent_t::condition_) && loop_runtime_checker::check())
8028 : {
8029 : try
8030 : {
8031 0 : result = parent_t::loop_body_.first->value();
8032 : }
8033 0 : catch(const break_exception<T>& e)
8034 : {
8035 0 : return e.value;
8036 : }
8037 0 : catch(const continue_exception&)
8038 : {}
8039 : }
8040 : }
8041 :
8042 0 : return result;
8043 : }
8044 :
8045 : using parent_t::valid;
8046 :
8047 0 : inline bool valid() const exprtk_override exprtk_final
8048 : {
8049 0 : return parent_t::valid() &&
8050 0 : loop_runtime_checker::valid();
8051 : }
8052 : };
8053 : #endif
8054 :
8055 : template <typename T>
8056 : class switch_node : public expression_node<T>
8057 : {
8058 : public:
8059 :
8060 : typedef expression_node<T>* expression_ptr;
8061 : typedef std::pair<expression_ptr,bool> branch_t;
8062 :
8063 : template <typename Allocator,
8064 : template <typename, typename> class Sequence>
8065 1005 : explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
8066 1005 : {
8067 1005 : if (1 != (arg_list.size() & 1))
8068 0 : return;
8069 :
8070 1005 : arg_list_.resize(arg_list.size());
8071 :
8072 4560 : for (std::size_t i = 0; i < arg_list.size(); ++i)
8073 : {
8074 3555 : if (arg_list[i] && arg_list[i]->valid())
8075 : {
8076 3555 : construct_branch_pair(arg_list_[i], arg_list[i]);
8077 : }
8078 : else
8079 : {
8080 0 : arg_list_.clear();
8081 0 : return;
8082 : }
8083 : }
8084 :
8085 1005 : assert(valid());
8086 0 : }
8087 :
8088 0 : inline T value() const exprtk_override
8089 : {
8090 0 : const std::size_t upper_bound = (arg_list_.size() - 1);
8091 :
8092 0 : for (std::size_t i = 0; i < upper_bound; i += 2)
8093 : {
8094 0 : expression_ptr condition = arg_list_[i ].first;
8095 0 : expression_ptr consequent = arg_list_[i + 1].first;
8096 :
8097 0 : if (is_true(condition))
8098 : {
8099 0 : return consequent->value();
8100 : }
8101 : }
8102 :
8103 0 : return arg_list_[upper_bound].first->value();
8104 : }
8105 :
8106 4802 : inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
8107 : {
8108 4802 : return expression_node<T>::e_switch;
8109 : }
8110 :
8111 1282 : inline bool valid() const exprtk_override
8112 : {
8113 1282 : return !arg_list_.empty();
8114 : }
8115 :
8116 1005 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8117 : {
8118 1005 : expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
8119 1005 : }
8120 :
8121 2020 : std::size_t node_depth() const exprtk_override exprtk_final
8122 : {
8123 2020 : return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
8124 : }
8125 :
8126 : protected:
8127 :
8128 : std::vector<branch_t> arg_list_;
8129 : };
8130 :
8131 : template <typename T, typename Switch_N>
8132 : class switch_n_node exprtk_final : public switch_node<T>
8133 : {
8134 : public:
8135 :
8136 : typedef expression_node<T>* expression_ptr;
8137 :
8138 : template <typename Allocator,
8139 : template <typename, typename> class Sequence>
8140 1005 : explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
8141 1005 : : switch_node<T>(arg_list)
8142 1005 : {}
8143 :
8144 11459417 : inline T value() const exprtk_override
8145 : {
8146 11459417 : return Switch_N::process(switch_node<T>::arg_list_);
8147 : }
8148 : };
8149 :
8150 : template <typename T>
8151 : class multi_switch_node exprtk_final : public expression_node<T>
8152 : {
8153 : public:
8154 :
8155 : typedef expression_node<T>* expression_ptr;
8156 : typedef std::pair<expression_ptr,bool> branch_t;
8157 :
8158 : template <typename Allocator,
8159 : template <typename, typename> class Sequence>
8160 180 : explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
8161 180 : {
8162 180 : if (0 != (arg_list.size() & 1))
8163 0 : return;
8164 :
8165 180 : arg_list_.resize(arg_list.size());
8166 :
8167 900 : for (std::size_t i = 0; i < arg_list.size(); ++i)
8168 : {
8169 720 : if (arg_list[i] && arg_list[i]->valid())
8170 : {
8171 720 : construct_branch_pair(arg_list_[i], arg_list[i]);
8172 : }
8173 : else
8174 : {
8175 0 : arg_list_.clear();
8176 0 : return;
8177 : }
8178 : }
8179 :
8180 180 : assert(valid());
8181 0 : }
8182 :
8183 180 : inline T value() const exprtk_override
8184 : {
8185 180 : const std::size_t upper_bound = (arg_list_.size() - 1);
8186 :
8187 180 : T result = T(0);
8188 :
8189 540 : for (std::size_t i = 0; i < upper_bound; i += 2)
8190 : {
8191 360 : expression_ptr condition = arg_list_[i ].first;
8192 360 : expression_ptr consequent = arg_list_[i + 1].first;
8193 :
8194 360 : if (is_true(condition))
8195 : {
8196 120 : result = consequent->value();
8197 : }
8198 : }
8199 :
8200 180 : return result;
8201 : }
8202 :
8203 900 : inline typename expression_node<T>::node_type type() const exprtk_override
8204 : {
8205 900 : return expression_node<T>::e_mswitch;
8206 : }
8207 :
8208 180 : inline bool valid() const exprtk_override
8209 : {
8210 180 : return !arg_list_.empty() && (0 == (arg_list_.size() % 2));
8211 : }
8212 :
8213 180 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8214 : {
8215 180 : expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
8216 180 : }
8217 :
8218 360 : std::size_t node_depth() const exprtk_override exprtk_final
8219 : {
8220 360 : return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
8221 : }
8222 :
8223 : private:
8224 :
8225 : std::vector<branch_t> arg_list_;
8226 : };
8227 :
8228 : template <typename T>
8229 : class ivariable
8230 : {
8231 : public:
8232 :
8233 506744 : virtual ~ivariable()
8234 506744 : {}
8235 :
8236 : virtual T& ref() = 0;
8237 : virtual const T& ref() const = 0;
8238 : };
8239 :
8240 : template <typename T>
8241 : class variable_node exprtk_final
8242 : : public expression_node<T>
8243 : , public ivariable <T>
8244 : {
8245 : public:
8246 :
8247 : static T null_value;
8248 :
8249 : explicit variable_node()
8250 : : value_(&null_value)
8251 : {}
8252 :
8253 499841 : explicit variable_node(T& v)
8254 499841 : : value_(&v)
8255 499841 : {}
8256 :
8257 : inline bool operator <(const variable_node<T>& v) const
8258 : {
8259 : return this < (&v);
8260 : }
8261 :
8262 127759453 : inline T value() const exprtk_override
8263 : {
8264 127759453 : return (*value_);
8265 : }
8266 :
8267 199245326 : inline T& ref() exprtk_override
8268 : {
8269 199245326 : return (*value_);
8270 : }
8271 :
8272 960 : inline const T& ref() const exprtk_override
8273 : {
8274 960 : return (*value_);
8275 : }
8276 :
8277 29015411 : inline typename expression_node<T>::node_type type() const exprtk_override
8278 : {
8279 29015411 : return expression_node<T>::e_variable;
8280 : }
8281 :
8282 : private:
8283 :
8284 : T* value_;
8285 : };
8286 :
8287 : template <typename T>
8288 : T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
8289 :
8290 : template <typename T>
8291 : struct range_pack
8292 : {
8293 : typedef expression_node<T>* expression_node_ptr;
8294 : typedef std::pair<std::size_t,std::size_t> cached_range_t;
8295 :
8296 230560 : range_pack()
8297 230560 : : n0_e (std::make_pair(false,expression_node_ptr(0)))
8298 230560 : , n1_e (std::make_pair(false,expression_node_ptr(0)))
8299 230560 : , n0_c (std::make_pair(false,0))
8300 230560 : , n1_c (std::make_pair(false,0))
8301 230560 : , cache(std::make_pair(0,0))
8302 230560 : {}
8303 :
8304 78072 : void clear()
8305 : {
8306 78072 : n0_e = std::make_pair(false,expression_node_ptr(0));
8307 78072 : n1_e = std::make_pair(false,expression_node_ptr(0));
8308 78072 : n0_c = std::make_pair(false,0);
8309 78072 : n1_c = std::make_pair(false,0);
8310 78072 : cache = std::make_pair(0,0);
8311 78072 : }
8312 :
8313 46016 : void free()
8314 : {
8315 46016 : if (n0_e.first && n0_e.second)
8316 : {
8317 5206 : n0_e.first = false;
8318 :
8319 5206 : if (
8320 6509 : !is_variable_node(n0_e.second) &&
8321 1303 : !is_string_node (n0_e.second)
8322 : )
8323 : {
8324 1303 : destroy_node(n0_e.second);
8325 : }
8326 : }
8327 :
8328 46016 : if (n1_e.first && n1_e.second)
8329 : {
8330 7056 : n1_e.first = false;
8331 :
8332 7056 : if (
8333 12109 : !is_variable_node(n1_e.second) &&
8334 5053 : !is_string_node (n1_e.second)
8335 : )
8336 : {
8337 5053 : destroy_node(n1_e.second);
8338 : }
8339 : }
8340 46016 : }
8341 :
8342 32310 : bool const_range() const
8343 : {
8344 54312 : return ( n0_c.first && n1_c.first) &&
8345 54312 : (!n0_e.first && !n1_e.first);
8346 : }
8347 :
8348 : bool var_range() const
8349 : {
8350 : return ( n0_e.first && n1_e.first) &&
8351 : (!n0_c.first && !n1_c.first);
8352 : }
8353 :
8354 99616 : bool operator() (std::size_t& r0, std::size_t& r1,
8355 : const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
8356 : {
8357 99616 : if (n0_c.first)
8358 94416 : r0 = n0_c.second;
8359 5200 : else if (n0_e.first)
8360 : {
8361 5200 : r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
8362 : }
8363 : else
8364 0 : return false;
8365 :
8366 99616 : if (n1_c.first)
8367 92566 : r1 = n1_c.second;
8368 7050 : else if (n1_e.first)
8369 : {
8370 7050 : r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
8371 : }
8372 : else
8373 0 : return false;
8374 :
8375 99616 : if (
8376 177484 : (std::numeric_limits<std::size_t>::max() != size) &&
8377 77868 : (std::numeric_limits<std::size_t>::max() == r1 )
8378 : )
8379 : {
8380 9665 : r1 = size;
8381 : }
8382 :
8383 99616 : cache.first = r0;
8384 99616 : cache.second = r1;
8385 :
8386 : #ifndef exprtk_enable_range_runtime_checks
8387 99616 : return (r0 <= r1);
8388 : #else
8389 : return range_runtime_check(r0, r1, size);
8390 : #endif
8391 : }
8392 :
8393 0 : inline std::size_t const_size() const
8394 : {
8395 0 : return (n1_c.second - n0_c.second);
8396 : }
8397 :
8398 3250 : inline std::size_t cache_size() const
8399 : {
8400 3250 : return (cache.second - cache.first);
8401 : }
8402 :
8403 : std::pair<bool,expression_node_ptr> n0_e;
8404 : std::pair<bool,expression_node_ptr> n1_e;
8405 : std::pair<bool,std::size_t > n0_c;
8406 : std::pair<bool,std::size_t > n1_c;
8407 : mutable cached_range_t cache;
8408 :
8409 : #ifdef exprtk_enable_range_runtime_checks
8410 : bool range_runtime_check(const std::size_t r0,
8411 : const std::size_t r1,
8412 : const std::size_t size) const
8413 : {
8414 : if (r0 > size)
8415 : {
8416 : throw std::runtime_error("range error: (r0 < 0) || (r0 > size)");
8417 : #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
8418 : return false;
8419 : #endif
8420 : }
8421 :
8422 : if (r1 > size)
8423 : {
8424 : throw std::runtime_error("range error: (r1 < 0) || (r1 > size)");
8425 : #if !defined(_MSC_VER) && !defined(__NVCOMPILER)
8426 : return false;
8427 : #endif
8428 : }
8429 :
8430 : return (r0 <= r1);
8431 : }
8432 : #endif
8433 : };
8434 :
8435 : template <typename T>
8436 : class string_base_node;
8437 :
8438 : template <typename T>
8439 : struct range_data_type
8440 : {
8441 : typedef range_pack<T> range_t;
8442 : typedef string_base_node<T>* strbase_ptr_t;
8443 :
8444 3724 : range_data_type()
8445 3724 : : range(0)
8446 3724 : , data (0)
8447 3724 : , size (0)
8448 3724 : , type_size(0)
8449 3724 : , str_node (0)
8450 3724 : {}
8451 :
8452 : range_t* range;
8453 : void* data;
8454 : std::size_t size;
8455 : std::size_t type_size;
8456 : strbase_ptr_t str_node;
8457 : };
8458 :
8459 : template <typename T> class vector_node;
8460 :
8461 : template <typename T>
8462 : class vector_interface
8463 : {
8464 : public:
8465 :
8466 : typedef vector_node<T>* vector_node_ptr;
8467 : typedef vec_data_store<T> vds_t;
8468 :
8469 100185 : virtual ~vector_interface()
8470 100185 : {}
8471 :
8472 : virtual std::size_t size () const = 0;
8473 :
8474 : virtual std::size_t base_size() const = 0;
8475 :
8476 : virtual vector_node_ptr vec () const = 0;
8477 :
8478 : virtual vector_node_ptr vec () = 0;
8479 :
8480 : virtual vds_t& vds () = 0;
8481 :
8482 : virtual const vds_t& vds () const = 0;
8483 :
8484 822 : virtual bool side_effect () const { return false; }
8485 : };
8486 :
8487 : template <typename T>
8488 : class vector_node exprtk_final
8489 : : public expression_node <T>
8490 : , public vector_interface<T>
8491 : {
8492 : public:
8493 :
8494 : typedef expression_node<T>* expression_ptr;
8495 : typedef vector_holder<T> vector_holder_t;
8496 : typedef vector_node<T>* vector_node_ptr;
8497 : typedef vec_data_store<T> vds_t;
8498 :
8499 49912 : explicit vector_node(vector_holder_t* vh)
8500 49912 : : vector_holder_(vh)
8501 49912 : , vds_((*vector_holder_).size(),(*vector_holder_)[0])
8502 : {
8503 49912 : vector_holder_->set_ref(&vds_.ref());
8504 49912 : }
8505 :
8506 22339 : vector_node(const vds_t& vds, vector_holder_t* vh)
8507 22339 : : vector_holder_(vh)
8508 22339 : , vds_(vds)
8509 22339 : {}
8510 :
8511 144502 : ~vector_node()
8512 : {
8513 72251 : assert(valid());
8514 72251 : vector_holder_->remove_ref(&vds_.ref());
8515 216753 : }
8516 :
8517 32899074 : inline T value() const exprtk_override
8518 : {
8519 32899074 : return vds().data()[0];
8520 : }
8521 :
8522 0 : vector_node_ptr vec() const exprtk_override
8523 : {
8524 0 : return const_cast<vector_node_ptr>(this);
8525 : }
8526 :
8527 5722 : vector_node_ptr vec() exprtk_override
8528 : {
8529 5722 : return this;
8530 : }
8531 :
8532 461205 : inline typename expression_node<T>::node_type type() const exprtk_override
8533 : {
8534 461205 : return expression_node<T>::e_vector;
8535 : }
8536 :
8537 197849 : inline bool valid() const exprtk_override
8538 : {
8539 197849 : return vector_holder_;
8540 : }
8541 :
8542 34991 : std::size_t size() const exprtk_override
8543 : {
8544 34991 : return vec_holder().size();
8545 : }
8546 :
8547 4647 : std::size_t base_size() const exprtk_override
8548 : {
8549 4647 : return vec_holder().base_size();
8550 : }
8551 :
8552 60520 : vds_t& vds() exprtk_override
8553 : {
8554 60520 : return vds_;
8555 : }
8556 :
8557 32899074 : const vds_t& vds() const exprtk_override
8558 : {
8559 32899074 : return vds_;
8560 : }
8561 :
8562 275121 : inline vector_holder_t& vec_holder()
8563 : {
8564 275121 : return (*vector_holder_);
8565 : }
8566 :
8567 39638 : inline vector_holder_t& vec_holder() const
8568 : {
8569 39638 : return (*vector_holder_);
8570 : }
8571 :
8572 : private:
8573 :
8574 : vector_holder_t* vector_holder_;
8575 : vds_t vds_;
8576 : };
8577 :
8578 : template <typename T>
8579 : class vector_size_node exprtk_final
8580 : : public expression_node <T>
8581 : {
8582 : public:
8583 :
8584 : typedef expression_node<T>* expression_ptr;
8585 : typedef vector_holder<T> vector_holder_t;
8586 :
8587 188 : explicit vector_size_node(vector_holder_t* vh)
8588 188 : : vector_holder_(vh)
8589 188 : {}
8590 :
8591 376 : ~vector_size_node()
8592 : {
8593 188 : assert(valid());
8594 564 : }
8595 :
8596 1022 : inline T value() const exprtk_override
8597 : {
8598 1022 : assert(vector_holder_);
8599 1022 : return static_cast<T>(vector_holder_->size());
8600 : }
8601 :
8602 6781 : inline typename expression_node<T>::node_type type() const exprtk_override
8603 : {
8604 6781 : return expression_node<T>::e_vecsize;
8605 : }
8606 :
8607 807 : inline bool valid() const exprtk_override
8608 : {
8609 807 : return vector_holder_ && vector_holder_->size();
8610 : }
8611 :
8612 0 : inline vector_holder_t* vec_holder()
8613 : {
8614 0 : return vector_holder_;
8615 : }
8616 :
8617 : private:
8618 :
8619 : vector_holder_t* vector_holder_;
8620 : };
8621 :
8622 : template <typename T>
8623 : class vector_elem_node exprtk_final
8624 : : public expression_node<T>
8625 : , public ivariable <T>
8626 : {
8627 : public:
8628 :
8629 : typedef expression_node<T>* expression_ptr;
8630 : typedef vector_holder<T> vector_holder_t;
8631 : typedef vector_holder_t* vector_holder_ptr;
8632 : typedef std::pair<expression_ptr,bool> branch_t;
8633 :
8634 3711 : vector_elem_node(expression_ptr vec_node,
8635 : expression_ptr index,
8636 : vector_holder_ptr vec_holder)
8637 3711 : : vector_holder_(vec_holder)
8638 3711 : , vector_base_((*vec_holder)[0])
8639 : {
8640 3711 : construct_branch_pair(vector_node_, vec_node);
8641 3711 : construct_branch_pair(index_ , index );
8642 3711 : assert(valid());
8643 3711 : }
8644 :
8645 10008123 : inline T value() const exprtk_override
8646 : {
8647 10008123 : return *access_vector();
8648 : }
8649 :
8650 22853974 : inline T& ref() exprtk_override
8651 : {
8652 22853974 : return *access_vector();
8653 : }
8654 :
8655 0 : inline const T& ref() const exprtk_override
8656 : {
8657 0 : return *access_vector();
8658 : }
8659 :
8660 77355 : inline typename expression_node<T>::node_type type() const exprtk_override
8661 : {
8662 77355 : return expression_node<T>::e_vecelem;
8663 : }
8664 :
8665 18277 : inline bool valid() const exprtk_override
8666 : {
8667 : return
8668 36554 : vector_holder_ &&
8669 18277 : index_.first &&
8670 18277 : vector_node_.first &&
8671 54831 : index_.first->valid() &&
8672 36554 : vector_node_.first->valid();
8673 : }
8674 :
8675 0 : inline vector_holder_t& vec_holder()
8676 : {
8677 0 : return (*vector_holder_);
8678 : }
8679 :
8680 3711 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8681 : {
8682 3711 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
8683 3711 : expression_node<T>::ndb_t::collect(index_ , node_delete_list);
8684 3711 : }
8685 :
8686 8226 : std::size_t node_depth() const exprtk_override
8687 : {
8688 : return expression_node<T>::ndb_t::compute_node_depth
8689 8226 : (vector_node_, index_);
8690 : }
8691 :
8692 : private:
8693 :
8694 32862097 : inline T* access_vector() const
8695 : {
8696 32862097 : vector_node_.first->value();
8697 32862097 : return (vector_base_ + details::numeric::to_uint64(index_.first->value()));
8698 : }
8699 :
8700 : vector_holder_ptr vector_holder_;
8701 : T* vector_base_;
8702 : branch_t vector_node_;
8703 : branch_t index_;
8704 : };
8705 :
8706 : template <typename T>
8707 : class vector_celem_node exprtk_final
8708 : : public expression_node<T>
8709 : , public ivariable <T>
8710 : {
8711 : public:
8712 :
8713 : typedef expression_node<T>* expression_ptr;
8714 : typedef vector_holder<T> vector_holder_t;
8715 : typedef vector_holder_t* vector_holder_ptr;
8716 : typedef std::pair<expression_ptr,bool> branch_t;
8717 :
8718 190 : vector_celem_node(expression_ptr vec_node,
8719 : const std::size_t index,
8720 : vector_holder_ptr vec_holder)
8721 190 : : index_(index)
8722 190 : , vector_holder_(vec_holder)
8723 190 : , vector_base_((*vec_holder)[0])
8724 : {
8725 190 : construct_branch_pair(vector_node_, vec_node);
8726 190 : assert(valid());
8727 190 : }
8728 :
8729 190 : inline T value() const exprtk_override
8730 : {
8731 190 : return *access_vector();
8732 : }
8733 :
8734 0 : inline T& ref() exprtk_override
8735 : {
8736 0 : return *access_vector();
8737 : }
8738 :
8739 0 : inline const T& ref() const exprtk_override
8740 : {
8741 0 : return *access_vector();
8742 : }
8743 :
8744 5890 : inline typename expression_node<T>::node_type type() const exprtk_override
8745 : {
8746 5890 : return expression_node<T>::e_veccelem;
8747 : }
8748 :
8749 760 : inline bool valid() const exprtk_override
8750 : {
8751 : return
8752 1520 : vector_holder_ &&
8753 1520 : vector_node_.first &&
8754 1520 : vector_node_.first->valid();
8755 : }
8756 :
8757 : inline vector_holder_t& vec_holder()
8758 : {
8759 : return (*vector_holder_);
8760 : }
8761 :
8762 190 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8763 : {
8764 190 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
8765 190 : }
8766 :
8767 380 : std::size_t node_depth() const exprtk_override
8768 : {
8769 380 : return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
8770 : }
8771 :
8772 : private:
8773 :
8774 190 : inline T* access_vector() const
8775 : {
8776 190 : vector_node_.first->value();
8777 190 : return (vector_base_ + index_);
8778 : }
8779 :
8780 : const std::size_t index_;
8781 : vector_holder_ptr vector_holder_;
8782 : T* vector_base_;
8783 : branch_t vector_node_;
8784 : };
8785 :
8786 : template <typename T>
8787 : class vector_elem_rtc_node exprtk_final
8788 : : public expression_node<T>
8789 : , public ivariable <T>
8790 : {
8791 : public:
8792 :
8793 : typedef expression_node<T>* expression_ptr;
8794 : typedef vector_holder<T> vector_holder_t;
8795 : typedef vector_holder_t* vector_holder_ptr;
8796 : typedef std::pair<expression_ptr,bool> branch_t;
8797 :
8798 92 : vector_elem_rtc_node(expression_ptr vec_node,
8799 : expression_ptr index,
8800 : vector_holder_ptr vec_holder,
8801 : vector_access_runtime_check_ptr vec_rt_chk)
8802 92 : : vector_holder_(vec_holder)
8803 0 : , vector_base_((*vec_holder)[0])
8804 92 : , vec_rt_chk_(vec_rt_chk)
8805 92 : , max_vector_index_(vector_holder_->size() - 1)
8806 : {
8807 92 : construct_branch_pair(vector_node_, vec_node);
8808 92 : construct_branch_pair(index_ , index );
8809 92 : assert(valid());
8810 92 : }
8811 :
8812 243 : inline T value() const exprtk_override
8813 : {
8814 243 : return *access_vector();
8815 : }
8816 :
8817 335 : inline T& ref() exprtk_override
8818 : {
8819 335 : return *access_vector();
8820 : }
8821 :
8822 0 : inline const T& ref() const exprtk_override
8823 : {
8824 0 : return *access_vector();
8825 : }
8826 :
8827 1428 : inline typename expression_node<T>::node_type type() const exprtk_override
8828 : {
8829 1428 : return expression_node<T>::e_vecelemrtc;
8830 : }
8831 :
8832 446 : inline bool valid() const exprtk_override
8833 : {
8834 : return
8835 892 : vector_holder_ &&
8836 446 : index_.first &&
8837 446 : vector_node_.first &&
8838 1338 : index_.first->valid() &&
8839 892 : vector_node_.first->valid();
8840 : }
8841 :
8842 : inline vector_holder_t& vec_holder()
8843 : {
8844 : return (*vector_holder_);
8845 : }
8846 :
8847 92 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8848 : {
8849 92 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
8850 92 : expression_node<T>::ndb_t::collect(index_, node_delete_list);
8851 92 : }
8852 :
8853 226 : std::size_t node_depth() const exprtk_override
8854 : {
8855 : return expression_node<T>::ndb_t::compute_node_depth
8856 226 : (vector_node_, index_);
8857 : }
8858 :
8859 : private:
8860 :
8861 578 : inline T* access_vector() const
8862 : {
8863 578 : const _uint64_t index = details::numeric::to_uint64(index_.first->value());
8864 578 : vector_node_.first->value();
8865 :
8866 578 : if (index <= max_vector_index_)
8867 : {
8868 156 : return (vector_holder_->data() + index);
8869 : }
8870 :
8871 422 : assert(vec_rt_chk_);
8872 :
8873 : vector_access_runtime_check::violation_context context;
8874 422 : context.base_ptr = reinterpret_cast<void*>(vector_base_);
8875 422 : context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
8876 422 : context.access_ptr = reinterpret_cast<void*>(vector_base_ + index);
8877 422 : context.type_size = sizeof(T);
8878 :
8879 422 : return vec_rt_chk_->handle_runtime_violation(context) ?
8880 : reinterpret_cast<T*>(context.access_ptr) :
8881 422 : vector_base_ ;
8882 : }
8883 :
8884 : vector_holder_ptr vector_holder_;
8885 : T* vector_base_;
8886 : branch_t vector_node_;
8887 : branch_t index_;
8888 : vector_access_runtime_check_ptr vec_rt_chk_;
8889 : const std::size_t max_vector_index_;
8890 : };
8891 :
8892 : template <typename T>
8893 : class vector_celem_rtc_node exprtk_final
8894 : : public expression_node<T>
8895 : , public ivariable <T>
8896 : {
8897 : public:
8898 :
8899 : typedef expression_node<T>* expression_ptr;
8900 : typedef vector_holder<T> vector_holder_t;
8901 : typedef vector_holder_t* vector_holder_ptr;
8902 : typedef std::pair<expression_ptr,bool> branch_t;
8903 :
8904 0 : vector_celem_rtc_node(expression_ptr vec_node,
8905 : const std::size_t index,
8906 : vector_holder_ptr vec_holder,
8907 : vector_access_runtime_check_ptr vec_rt_chk)
8908 0 : : index_(index)
8909 0 : , max_vector_index_(vec_holder->size() - 1)
8910 0 : , vector_holder_(vec_holder)
8911 0 : , vector_base_((*vec_holder)[0])
8912 0 : , vec_rt_chk_(vec_rt_chk)
8913 : {
8914 0 : construct_branch_pair(vector_node_, vec_node);
8915 0 : assert(valid());
8916 0 : }
8917 :
8918 0 : inline T value() const exprtk_override
8919 : {
8920 0 : return *access_vector();
8921 : }
8922 :
8923 0 : inline T& ref() exprtk_override
8924 : {
8925 0 : return *access_vector();
8926 : }
8927 :
8928 0 : inline const T& ref() const exprtk_override
8929 : {
8930 0 : return *access_vector();
8931 : }
8932 :
8933 0 : inline typename expression_node<T>::node_type type() const exprtk_override
8934 : {
8935 0 : return expression_node<T>::e_veccelemrtc;
8936 : }
8937 :
8938 0 : inline bool valid() const exprtk_override
8939 : {
8940 : return
8941 0 : vector_holder_ &&
8942 0 : vector_node_.first &&
8943 0 : vector_node_.first->valid();
8944 : }
8945 :
8946 : inline vector_holder_t& vec_holder()
8947 : {
8948 : return (*vector_holder_);
8949 : }
8950 :
8951 0 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
8952 : {
8953 0 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
8954 0 : }
8955 :
8956 0 : std::size_t node_depth() const exprtk_override
8957 : {
8958 0 : return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
8959 : }
8960 :
8961 : private:
8962 :
8963 0 : inline T* access_vector() const
8964 : {
8965 0 : vector_node_.first->value();
8966 :
8967 0 : if (index_ <= max_vector_index_)
8968 : {
8969 0 : return (vector_holder_->data() + index_);
8970 : }
8971 :
8972 0 : assert(vec_rt_chk_);
8973 :
8974 : vector_access_runtime_check::violation_context context;
8975 0 : context.base_ptr = reinterpret_cast<void*>(vector_base_);
8976 0 : context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
8977 0 : context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
8978 0 : context.type_size = sizeof(T);
8979 :
8980 0 : return vec_rt_chk_->handle_runtime_violation(context) ?
8981 : reinterpret_cast<T*>(context.access_ptr) :
8982 0 : vector_base_ ;
8983 : }
8984 :
8985 : const std::size_t index_;
8986 : const std::size_t max_vector_index_;
8987 : vector_holder_ptr vector_holder_;
8988 : T* vector_base_;
8989 : branch_t vector_node_;
8990 : vector_access_runtime_check_ptr vec_rt_chk_;
8991 : };
8992 :
8993 : template <typename T>
8994 : class rebasevector_elem_node exprtk_final
8995 : : public expression_node<T>
8996 : , public ivariable <T>
8997 : {
8998 : public:
8999 :
9000 : typedef expression_node<T>* expression_ptr;
9001 : typedef vector_holder<T> vector_holder_t;
9002 : typedef vector_holder_t* vector_holder_ptr;
9003 : typedef vec_data_store<T> vds_t;
9004 : typedef std::pair<expression_ptr,bool> branch_t;
9005 :
9006 1014 : rebasevector_elem_node(expression_ptr vec_node,
9007 : expression_ptr index,
9008 : vector_holder_ptr vec_holder)
9009 1014 : : vector_holder_(vec_holder)
9010 : {
9011 1014 : construct_branch_pair(vector_node_, vec_node);
9012 1014 : construct_branch_pair(index_ , index );
9013 1014 : assert(valid());
9014 1014 : }
9015 :
9016 863 : inline T value() const exprtk_override
9017 : {
9018 863 : return *access_vector();
9019 : }
9020 :
9021 600 : inline T& ref() exprtk_override
9022 : {
9023 600 : return *access_vector();
9024 : }
9025 :
9026 0 : inline const T& ref() const exprtk_override
9027 : {
9028 0 : return *access_vector();
9029 : }
9030 :
9031 25074 : inline typename expression_node<T>::node_type type() const exprtk_override
9032 : {
9033 25074 : return expression_node<T>::e_rbvecelem;
9034 : }
9035 :
9036 4631 : inline bool valid() const exprtk_override
9037 : {
9038 : return
9039 9262 : vector_holder_ &&
9040 4631 : index_.first &&
9041 4631 : vector_node_.first &&
9042 13893 : index_.first->valid() &&
9043 9262 : vector_node_.first->valid();
9044 : }
9045 :
9046 : inline vector_holder_t& vec_holder()
9047 : {
9048 : return (*vector_holder_);
9049 : }
9050 :
9051 1014 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9052 : {
9053 1014 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
9054 1014 : expression_node<T>::ndb_t::collect(index_, node_delete_list);
9055 1014 : }
9056 :
9057 2394 : std::size_t node_depth() const exprtk_override
9058 : {
9059 : return expression_node<T>::ndb_t::compute_node_depth
9060 2394 : (vector_node_, index_);
9061 : }
9062 :
9063 : private:
9064 :
9065 1463 : inline T* access_vector() const
9066 : {
9067 1463 : vector_node_.first->value();
9068 1463 : return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value()));
9069 : }
9070 :
9071 : vector_holder_ptr vector_holder_;
9072 : branch_t vector_node_;
9073 : branch_t index_;
9074 : };
9075 :
9076 : template <typename T>
9077 : class rebasevector_celem_node exprtk_final
9078 : : public expression_node<T>
9079 : , public ivariable <T>
9080 : {
9081 : public:
9082 :
9083 : typedef expression_node<T>* expression_ptr;
9084 : typedef vector_holder<T> vector_holder_t;
9085 : typedef vector_holder_t* vector_holder_ptr;
9086 : typedef std::pair<expression_ptr,bool> branch_t;
9087 :
9088 1894 : rebasevector_celem_node(expression_ptr vec_node,
9089 : const std::size_t index,
9090 : vector_holder_ptr vec_holder)
9091 1894 : : index_(index)
9092 1894 : , vector_holder_(vec_holder)
9093 : {
9094 1894 : construct_branch_pair(vector_node_, vec_node);
9095 1894 : assert(valid());
9096 1894 : }
9097 :
9098 1909 : inline T value() const exprtk_override
9099 : {
9100 1909 : vector_node_.first->value();
9101 1909 : return ref();;
9102 : }
9103 :
9104 600 : inline T& ref() exprtk_override
9105 : {
9106 600 : return *(vector_holder_->data() + index_);
9107 : }
9108 :
9109 1909 : inline const T& ref() const exprtk_override
9110 : {
9111 1909 : return *(vector_holder_->data() + index_);
9112 : }
9113 :
9114 40354 : inline typename expression_node<T>::node_type type() const exprtk_override
9115 : {
9116 40354 : return expression_node<T>::e_rbveccelem;
9117 : }
9118 :
9119 10916 : inline bool valid() const exprtk_override
9120 : {
9121 : return
9122 21832 : vector_holder_ &&
9123 21832 : vector_node_.first &&
9124 21832 : vector_node_.first->valid();
9125 : }
9126 :
9127 : inline vector_holder_t& vec_holder()
9128 : {
9129 : return (*vector_holder_);
9130 : }
9131 :
9132 1894 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9133 : {
9134 1894 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
9135 1894 : }
9136 :
9137 4990 : std::size_t node_depth() const exprtk_override
9138 : {
9139 4990 : return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
9140 : }
9141 :
9142 : private:
9143 :
9144 : const std::size_t index_;
9145 : vector_holder_ptr vector_holder_;
9146 : branch_t vector_node_;
9147 : };
9148 :
9149 : template <typename T>
9150 : class rebasevector_elem_rtc_node exprtk_final
9151 : : public expression_node<T>
9152 : , public ivariable <T>
9153 : {
9154 : public:
9155 :
9156 : typedef expression_node<T>* expression_ptr;
9157 : typedef vector_holder<T> vector_holder_t;
9158 : typedef vector_holder_t* vector_holder_ptr;
9159 : typedef std::pair<expression_ptr,bool> branch_t;
9160 :
9161 2 : rebasevector_elem_rtc_node(expression_ptr vec_node,
9162 : expression_ptr index,
9163 : vector_holder_ptr vec_holder,
9164 : vector_access_runtime_check_ptr vec_rt_chk)
9165 2 : : vector_holder_(vec_holder)
9166 2 : , vec_rt_chk_(vec_rt_chk)
9167 : {
9168 2 : construct_branch_pair(vector_node_, vec_node);
9169 2 : construct_branch_pair(index_ , index );
9170 2 : assert(valid());
9171 2 : }
9172 :
9173 30 : inline T value() const exprtk_override
9174 : {
9175 30 : return *access_vector();
9176 : }
9177 :
9178 0 : inline T& ref() exprtk_override
9179 : {
9180 0 : return *access_vector();
9181 : }
9182 :
9183 0 : inline const T& ref() const exprtk_override
9184 : {
9185 0 : return *access_vector();
9186 : }
9187 :
9188 52 : inline typename expression_node<T>::node_type type() const exprtk_override
9189 : {
9190 52 : return expression_node<T>::e_rbvecelemrtc;
9191 : }
9192 :
9193 12 : inline bool valid() const exprtk_override
9194 : {
9195 : return
9196 24 : vector_holder_ &&
9197 12 : index_.first &&
9198 12 : vector_node_.first &&
9199 36 : index_.first->valid() &&
9200 24 : vector_node_.first->valid();
9201 : }
9202 :
9203 : inline vector_holder_t& vec_holder()
9204 : {
9205 : return (*vector_holder_);
9206 : }
9207 :
9208 2 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9209 : {
9210 2 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
9211 2 : expression_node<T>::ndb_t::collect(index_ , node_delete_list);
9212 2 : }
9213 :
9214 6 : std::size_t node_depth() const exprtk_override
9215 : {
9216 : return expression_node<T>::ndb_t::compute_node_depth
9217 6 : (vector_node_, index_);
9218 : }
9219 :
9220 : private:
9221 :
9222 30 : inline T* access_vector() const
9223 : {
9224 30 : vector_node_.first->value();
9225 30 : const _uint64_t index = details::numeric::to_uint64(index_.first->value());
9226 :
9227 30 : if (index <= (vector_holder_->size() - 1))
9228 : {
9229 15 : return (vector_holder_->data() + index);
9230 : }
9231 :
9232 15 : assert(vec_rt_chk_);
9233 :
9234 : vector_access_runtime_check::violation_context context;
9235 15 : context.base_ptr = reinterpret_cast<void*>(vector_holder_->data());
9236 15 : context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size());
9237 15 : context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index);
9238 15 : context.type_size = sizeof(T);
9239 :
9240 15 : return vec_rt_chk_->handle_runtime_violation(context) ?
9241 : reinterpret_cast<T*>(context.access_ptr) :
9242 15 : vector_holder_->data() ;
9243 : }
9244 :
9245 : vector_holder_ptr vector_holder_;
9246 : branch_t vector_node_;
9247 : branch_t index_;
9248 : vector_access_runtime_check_ptr vec_rt_chk_;
9249 : };
9250 :
9251 : template <typename T>
9252 : class rebasevector_celem_rtc_node exprtk_final
9253 : : public expression_node<T>
9254 : , public ivariable <T>
9255 : {
9256 : public:
9257 :
9258 : typedef expression_node<T>* expression_ptr;
9259 : typedef vector_holder<T> vector_holder_t;
9260 : typedef vector_holder_t* vector_holder_ptr;
9261 : typedef std::pair<expression_ptr,bool> branch_t;
9262 :
9263 0 : rebasevector_celem_rtc_node(expression_ptr vec_node,
9264 : const std::size_t index,
9265 : vector_holder_ptr vec_holder,
9266 : vector_access_runtime_check_ptr vec_rt_chk)
9267 0 : : index_(index)
9268 0 : , vector_holder_(vec_holder)
9269 0 : , vector_base_((*vec_holder)[0])
9270 0 : , vec_rt_chk_(vec_rt_chk)
9271 : {
9272 0 : construct_branch_pair(vector_node_, vec_node);
9273 0 : assert(valid());
9274 0 : }
9275 :
9276 0 : inline T value() const exprtk_override
9277 : {
9278 0 : return *access_vector();
9279 : }
9280 :
9281 0 : inline T& ref() exprtk_override
9282 : {
9283 0 : return *access_vector();
9284 : }
9285 :
9286 0 : inline const T& ref() const exprtk_override
9287 : {
9288 0 : return *access_vector();
9289 : }
9290 :
9291 0 : inline typename expression_node<T>::node_type type() const exprtk_override
9292 : {
9293 0 : return expression_node<T>::e_rbveccelemrtc;
9294 : }
9295 :
9296 0 : inline bool valid() const exprtk_override
9297 : {
9298 : return
9299 0 : vector_holder_ &&
9300 0 : vector_node_.first &&
9301 0 : vector_node_.first->valid();
9302 : }
9303 :
9304 : inline vector_holder_t& vec_holder()
9305 : {
9306 : return (*vector_holder_);
9307 : }
9308 :
9309 0 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9310 : {
9311 0 : expression_node<T>::ndb_t::collect(vector_node_, node_delete_list);
9312 0 : }
9313 :
9314 0 : std::size_t node_depth() const exprtk_override
9315 : {
9316 0 : return expression_node<T>::ndb_t::compute_node_depth(vector_node_);
9317 : }
9318 :
9319 : private:
9320 :
9321 0 : inline T* access_vector() const
9322 : {
9323 0 : vector_node_.first->value();
9324 :
9325 0 : if (index_ <= vector_holder_->size() - 1)
9326 : {
9327 0 : return (vector_holder_->data() + index_);
9328 : }
9329 :
9330 0 : assert(vec_rt_chk_);
9331 :
9332 : vector_access_runtime_check::violation_context context;
9333 0 : context.base_ptr = reinterpret_cast<void*>(vector_base_);
9334 0 : context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size());
9335 0 : context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_);
9336 0 : context.type_size = sizeof(T);
9337 :
9338 0 : return vec_rt_chk_->handle_runtime_violation(context) ?
9339 : reinterpret_cast<T*>(context.access_ptr) :
9340 0 : vector_base_ ;
9341 : }
9342 :
9343 : const std::size_t index_;
9344 : vector_holder_ptr vector_holder_;
9345 : T* vector_base_;
9346 : branch_t vector_node_;
9347 : vector_access_runtime_check_ptr vec_rt_chk_;
9348 : };
9349 :
9350 : template <typename T>
9351 : class vector_initialisation_node exprtk_final : public expression_node<T>
9352 : {
9353 : public:
9354 :
9355 : typedef expression_node<T>* expression_ptr;
9356 :
9357 16614 : vector_initialisation_node(T* vector_base,
9358 : const std::size_t& size,
9359 : const std::vector<expression_ptr>& initialiser_list,
9360 : const bool single_value_initialse)
9361 16614 : : vector_base_(vector_base)
9362 16614 : , initialiser_list_(initialiser_list)
9363 16614 : , size_(size)
9364 16614 : , single_value_initialse_(single_value_initialse)
9365 16614 : , zero_value_initialse_(false)
9366 16614 : , const_nonzero_literal_value_initialse_(false)
9367 16614 : , single_initialiser_value_(T(0))
9368 : {
9369 16614 : if (single_value_initialse_)
9370 : {
9371 0 : if (initialiser_list_.empty())
9372 0 : zero_value_initialse_ = true;
9373 0 : else if (
9374 0 : (initialiser_list_.size() == 1) &&
9375 0 : details::is_constant_node(initialiser_list_[0]) &&
9376 0 : (T(0) == initialiser_list_[0]->value())
9377 : )
9378 : {
9379 0 : zero_value_initialse_ = true;
9380 : }
9381 : else
9382 : {
9383 0 : assert(initialiser_list_.size() == 1);
9384 :
9385 0 : if (details::is_constant_node(initialiser_list_[0]))
9386 : {
9387 0 : const_nonzero_literal_value_initialse_ = true;
9388 0 : single_initialiser_value_ = initialiser_list_[0]->value();
9389 0 : assert(T(0) != single_initialiser_value_);
9390 : }
9391 : }
9392 : }
9393 16614 : }
9394 :
9395 17358 : inline T value() const exprtk_override
9396 : {
9397 17358 : if (single_value_initialse_)
9398 : {
9399 0 : if (zero_value_initialse_)
9400 : {
9401 0 : details::set_zero_value(vector_base_, size_);
9402 : }
9403 0 : else if (const_nonzero_literal_value_initialse_)
9404 : {
9405 0 : for (std::size_t i = 0; i < size_; ++i)
9406 : {
9407 0 : *(vector_base_ + i) = single_initialiser_value_;
9408 : }
9409 : }
9410 : else
9411 : {
9412 0 : for (std::size_t i = 0; i < size_; ++i)
9413 : {
9414 0 : *(vector_base_ + i) = initialiser_list_[0]->value();
9415 : }
9416 : }
9417 : }
9418 : else
9419 : {
9420 17358 : const std::size_t initialiser_list_size = initialiser_list_.size();
9421 :
9422 79110 : for (std::size_t i = 0; i < initialiser_list_size; ++i)
9423 : {
9424 61752 : *(vector_base_ + i) = initialiser_list_[i]->value();
9425 : }
9426 :
9427 17358 : if (initialiser_list_size < size_)
9428 : {
9429 1178 : details::set_zero_value(
9430 1178 : vector_base_ + initialiser_list_size,
9431 1178 : (size_ - initialiser_list_size));
9432 : }
9433 : }
9434 :
9435 17358 : return *(vector_base_);
9436 : }
9437 :
9438 210588 : inline typename expression_node<T>::node_type type() const exprtk_override
9439 : {
9440 210588 : return expression_node<T>::e_vecinit;
9441 : }
9442 :
9443 33338 : inline bool valid() const exprtk_override
9444 : {
9445 33338 : return vector_base_;
9446 : }
9447 :
9448 16614 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9449 : {
9450 16614 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9451 16614 : }
9452 :
9453 41836 : std::size_t node_depth() const exprtk_override
9454 : {
9455 41836 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9456 : }
9457 :
9458 : private:
9459 :
9460 : vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete;
9461 : vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete;
9462 :
9463 : mutable T* vector_base_;
9464 : std::vector<expression_ptr> initialiser_list_;
9465 : const std::size_t size_;
9466 : const bool single_value_initialse_;
9467 : bool zero_value_initialse_;
9468 : bool const_nonzero_literal_value_initialse_;
9469 : T single_initialiser_value_;
9470 : };
9471 :
9472 : template <typename T>
9473 : class vector_init_zero_value_node exprtk_final : public expression_node<T>
9474 : {
9475 : public:
9476 :
9477 : typedef expression_node<T>* expression_ptr;
9478 :
9479 839 : vector_init_zero_value_node(T* vector_base,
9480 : const std::size_t& size,
9481 : const std::vector<expression_ptr>& initialiser_list)
9482 839 : : vector_base_(vector_base)
9483 839 : , size_(size)
9484 839 : , initialiser_list_(initialiser_list)
9485 839 : {}
9486 :
9487 833 : inline T value() const exprtk_override
9488 : {
9489 833 : details::set_zero_value(vector_base_, size_);
9490 833 : return *(vector_base_);
9491 : }
9492 :
9493 11650 : inline typename expression_node<T>::node_type type() const exprtk_override
9494 : {
9495 11650 : return expression_node<T>::e_vecinit;
9496 : }
9497 :
9498 1672 : inline bool valid() const exprtk_override
9499 : {
9500 1672 : return vector_base_;
9501 : }
9502 :
9503 839 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9504 : {
9505 839 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9506 839 : }
9507 :
9508 2499 : std::size_t node_depth() const exprtk_override
9509 : {
9510 2499 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9511 : }
9512 :
9513 : private:
9514 :
9515 : vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete;
9516 : vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete;
9517 :
9518 : mutable T* vector_base_;
9519 : const std::size_t size_;
9520 : std::vector<expression_ptr> initialiser_list_;
9521 : };
9522 :
9523 : template <typename T>
9524 : class vector_init_single_constvalue_node exprtk_final : public expression_node<T>
9525 : {
9526 : public:
9527 :
9528 : typedef expression_node<T>* expression_ptr;
9529 :
9530 6149 : vector_init_single_constvalue_node(T* vector_base,
9531 : const std::size_t& size,
9532 : const std::vector<expression_ptr>& initialiser_list)
9533 6149 : : vector_base_(vector_base)
9534 6149 : , size_(size)
9535 6149 : , initialiser_list_(initialiser_list)
9536 : {
9537 6149 : single_initialiser_value_ = initialiser_list_[0]->value();
9538 6149 : assert(valid());
9539 6149 : }
9540 :
9541 6157 : inline T value() const exprtk_override
9542 : {
9543 117022071 : for (std::size_t i = 0; i < size_; ++i)
9544 : {
9545 117015914 : *(vector_base_ + i) = single_initialiser_value_;
9546 : }
9547 :
9548 6157 : return *(vector_base_);
9549 : }
9550 :
9551 125692 : inline typename expression_node<T>::node_type type() const exprtk_override
9552 : {
9553 125692 : return expression_node<T>::e_vecinit;
9554 : }
9555 :
9556 23047 : inline bool valid() const exprtk_override
9557 : {
9558 23047 : return vector_base_ &&
9559 23047 : (initialiser_list_.size() == 1) &&
9560 69141 : (details::is_constant_node(initialiser_list_[0])) &&
9561 46094 : (single_initialiser_value_ != T(0));
9562 : }
9563 :
9564 6149 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9565 : {
9566 6149 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9567 6149 : }
9568 :
9569 19249 : std::size_t node_depth() const exprtk_override
9570 : {
9571 19249 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9572 : }
9573 :
9574 : private:
9575 :
9576 : vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete;
9577 : vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete;
9578 :
9579 : mutable T* vector_base_;
9580 : const std::size_t size_;
9581 : std::vector<expression_ptr> initialiser_list_;
9582 : T single_initialiser_value_;
9583 : };
9584 :
9585 : template <typename T>
9586 : class vector_init_single_value_node exprtk_final : public expression_node<T>
9587 : {
9588 : public:
9589 :
9590 : typedef expression_node<T>* expression_ptr;
9591 :
9592 90 : vector_init_single_value_node(T* vector_base,
9593 : const std::size_t& size,
9594 : const std::vector<expression_ptr>& initialiser_list)
9595 90 : : vector_base_(vector_base)
9596 90 : , size_(size)
9597 90 : , initialiser_list_(initialiser_list)
9598 : {
9599 90 : assert(valid());
9600 90 : }
9601 :
9602 90 : inline T value() const exprtk_override
9603 : {
9604 90 : expression_node<T>& node = *initialiser_list_[0];
9605 :
9606 520 : for (std::size_t i = 0; i < size_; ++i)
9607 : {
9608 430 : *(vector_base_ + i) = node.value();
9609 : }
9610 :
9611 90 : return *(vector_base_);
9612 : }
9613 :
9614 990 : inline typename expression_node<T>::node_type type() const exprtk_override
9615 : {
9616 990 : return expression_node<T>::e_vecinit;
9617 : }
9618 :
9619 270 : inline bool valid() const exprtk_override
9620 : {
9621 270 : return vector_base_ &&
9622 540 : (initialiser_list_.size() == 1) &&
9623 540 : !details::is_constant_node(initialiser_list_[0]);
9624 : }
9625 :
9626 90 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9627 : {
9628 90 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9629 90 : }
9630 :
9631 180 : std::size_t node_depth() const exprtk_override
9632 : {
9633 180 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9634 : }
9635 :
9636 : private:
9637 :
9638 : vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete;
9639 : vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete;
9640 :
9641 : mutable T* vector_base_;
9642 : const std::size_t size_;
9643 : std::vector<expression_ptr> initialiser_list_;
9644 : };
9645 :
9646 : template <typename T>
9647 : class vector_init_iota_constconst_node exprtk_final : public expression_node<T>
9648 : {
9649 : public:
9650 :
9651 : typedef expression_node<T>* expression_ptr;
9652 :
9653 135 : vector_init_iota_constconst_node(T* vector_base,
9654 : const std::size_t& size,
9655 : const std::vector<expression_ptr>& initialiser_list)
9656 135 : : vector_base_(vector_base)
9657 135 : , size_(size)
9658 135 : , initialiser_list_(initialiser_list)
9659 : {
9660 135 : base_value_ = initialiser_list_[0]->value();
9661 135 : increment_value_ = initialiser_list_[1]->value();
9662 :
9663 135 : assert(valid());
9664 135 : }
9665 :
9666 135 : inline T value() const exprtk_override
9667 : {
9668 135 : T value = base_value_;
9669 :
9670 615 : for (std::size_t i = 0; i < size_; ++i, value += increment_value_)
9671 : {
9672 480 : *(vector_base_ + i) = value;
9673 : }
9674 :
9675 135 : return *(vector_base_);
9676 : }
9677 :
9678 1830 : inline typename expression_node<T>::node_type type() const exprtk_override
9679 : {
9680 1830 : return expression_node<T>::e_vecinit;
9681 : }
9682 :
9683 405 : inline bool valid() const exprtk_override
9684 : {
9685 405 : return vector_base_ &&
9686 405 : (initialiser_list_.size() == 2) &&
9687 1215 : (details::is_constant_node(initialiser_list_[0])) &&
9688 810 : (details::is_constant_node(initialiser_list_[1])) ;
9689 : }
9690 :
9691 135 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9692 : {
9693 135 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9694 135 : }
9695 :
9696 385 : std::size_t node_depth() const exprtk_override
9697 : {
9698 385 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9699 : }
9700 :
9701 : private:
9702 :
9703 : vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete;
9704 : vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete;
9705 :
9706 : mutable T* vector_base_;
9707 : const std::size_t size_;
9708 : std::vector<expression_ptr> initialiser_list_;
9709 : T base_value_;
9710 : T increment_value_;
9711 : };
9712 :
9713 : template <typename T>
9714 : class vector_init_iota_constnconst_node exprtk_final : public expression_node<T>
9715 : {
9716 : public:
9717 :
9718 : typedef expression_node<T>* expression_ptr;
9719 :
9720 40 : vector_init_iota_constnconst_node(T* vector_base,
9721 : const std::size_t& size,
9722 : const std::vector<expression_ptr>& initialiser_list)
9723 40 : : vector_base_(vector_base)
9724 40 : , size_(size)
9725 40 : , initialiser_list_(initialiser_list)
9726 : {
9727 40 : assert(valid());
9728 40 : base_value_ = initialiser_list_[0]->value();
9729 40 : }
9730 :
9731 40 : inline T value() const exprtk_override
9732 : {
9733 40 : T value = base_value_;
9734 40 : expression_node<T>& increment = *initialiser_list_[1];
9735 :
9736 160 : for (std::size_t i = 0; i < size_; ++i, value += increment.value())
9737 : {
9738 120 : *(vector_base_ + i) = value;
9739 : }
9740 :
9741 40 : return *(vector_base_);
9742 : }
9743 :
9744 440 : inline typename expression_node<T>::node_type type() const exprtk_override
9745 : {
9746 440 : return expression_node<T>::e_vecinit;
9747 : }
9748 :
9749 120 : inline bool valid() const exprtk_override
9750 : {
9751 120 : return vector_base_ &&
9752 120 : (initialiser_list_.size() == 2) &&
9753 360 : ( details::is_constant_node(initialiser_list_[0])) &&
9754 240 : (!details::is_constant_node(initialiser_list_[1]));
9755 : }
9756 :
9757 40 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9758 : {
9759 40 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9760 40 : }
9761 :
9762 80 : std::size_t node_depth() const exprtk_override
9763 : {
9764 80 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9765 : }
9766 :
9767 : private:
9768 :
9769 : vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
9770 : vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete;
9771 :
9772 : mutable T* vector_base_;
9773 : const std::size_t size_;
9774 : std::vector<expression_ptr> initialiser_list_;
9775 : T base_value_;
9776 : };
9777 :
9778 : template <typename T>
9779 : class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T>
9780 : {
9781 : public:
9782 :
9783 : typedef expression_node<T>* expression_ptr;
9784 :
9785 20 : vector_init_iota_nconstconst_node(T* vector_base,
9786 : const std::size_t& size,
9787 : const std::vector<expression_ptr>& initialiser_list)
9788 20 : : vector_base_(vector_base)
9789 20 : , size_(size)
9790 20 : , initialiser_list_(initialiser_list)
9791 : {
9792 20 : assert(valid());
9793 20 : }
9794 :
9795 20 : inline T value() const exprtk_override
9796 : {
9797 20 : T value = initialiser_list_[0]->value();
9798 20 : const T increment = initialiser_list_[1]->value();
9799 :
9800 80 : for (std::size_t i = 0; i < size_; ++i, value += increment)
9801 : {
9802 60 : *(vector_base_ + i) = value;
9803 : }
9804 :
9805 20 : return *(vector_base_);
9806 : }
9807 :
9808 220 : inline typename expression_node<T>::node_type type() const exprtk_override
9809 : {
9810 220 : return expression_node<T>::e_vecinit;
9811 : }
9812 :
9813 60 : inline bool valid() const exprtk_override
9814 : {
9815 60 : return vector_base_ &&
9816 60 : (initialiser_list_.size() == 2) &&
9817 180 : (!details::is_constant_node(initialiser_list_[0])) &&
9818 120 : (details::is_constant_node(initialiser_list_[1]));
9819 : }
9820 :
9821 20 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9822 : {
9823 20 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9824 20 : }
9825 :
9826 40 : std::size_t node_depth() const exprtk_override
9827 : {
9828 40 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9829 : }
9830 :
9831 : private:
9832 :
9833 : vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
9834 : vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete;
9835 :
9836 : mutable T* vector_base_;
9837 : const std::size_t size_;
9838 : std::vector<expression_ptr> initialiser_list_;
9839 : };
9840 :
9841 : template <typename T>
9842 : class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T>
9843 : {
9844 : public:
9845 :
9846 : typedef expression_node<T>* expression_ptr;
9847 :
9848 20 : vector_init_iota_nconstnconst_node(T* vector_base,
9849 : const std::size_t& size,
9850 : const std::vector<expression_ptr>& initialiser_list)
9851 20 : : vector_base_(vector_base)
9852 20 : , size_(size)
9853 20 : , initialiser_list_(initialiser_list)
9854 : {
9855 20 : assert(valid());
9856 20 : }
9857 :
9858 20 : inline T value() const exprtk_override
9859 : {
9860 20 : T value = initialiser_list_[0]->value();
9861 20 : expression_node<T>& increment = *initialiser_list_[1];
9862 :
9863 80 : for (std::size_t i = 0; i < size_; ++i, value += increment.value())
9864 : {
9865 60 : *(vector_base_ + i) = value;
9866 : }
9867 :
9868 20 : return *(vector_base_);
9869 : }
9870 :
9871 220 : inline typename expression_node<T>::node_type type() const exprtk_override
9872 : {
9873 220 : return expression_node<T>::e_vecinit;
9874 : }
9875 :
9876 60 : inline bool valid() const exprtk_override
9877 : {
9878 60 : return vector_base_ &&
9879 60 : (initialiser_list_.size() == 2) &&
9880 180 : (!details::is_constant_node(initialiser_list_[0])) &&
9881 120 : (!details::is_constant_node(initialiser_list_[1]));
9882 : }
9883 :
9884 20 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
9885 : {
9886 20 : expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
9887 20 : }
9888 :
9889 40 : std::size_t node_depth() const exprtk_override
9890 : {
9891 40 : return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
9892 : }
9893 :
9894 : private:
9895 :
9896 : vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
9897 : vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete;
9898 :
9899 : mutable T* vector_base_;
9900 : const std::size_t size_;
9901 : std::vector<expression_ptr> initialiser_list_;
9902 : };
9903 :
9904 : template <typename T>
9905 : class swap_node exprtk_final : public expression_node<T>
9906 : {
9907 : public:
9908 :
9909 : typedef expression_node<T>* expression_ptr;
9910 : typedef variable_node<T>* variable_node_ptr;
9911 :
9912 480 : swap_node(variable_node_ptr var0, variable_node_ptr var1)
9913 480 : : var0_(var0)
9914 480 : , var1_(var1)
9915 480 : {}
9916 :
9917 480 : inline T value() const exprtk_override
9918 : {
9919 480 : std::swap(var0_->ref(),var1_->ref());
9920 480 : return var1_->ref();
9921 : }
9922 :
9923 5760 : inline typename expression_node<T>::node_type type() const exprtk_override
9924 : {
9925 5760 : return expression_node<T>::e_swap;
9926 : }
9927 :
9928 : private:
9929 :
9930 : variable_node_ptr var0_;
9931 : variable_node_ptr var1_;
9932 : };
9933 :
9934 : template <typename T>
9935 : class swap_generic_node exprtk_final : public binary_node<T>
9936 : {
9937 : public:
9938 :
9939 : typedef expression_node<T>* expression_ptr;
9940 : typedef ivariable<T>* ivariable_ptr;
9941 :
9942 646 : swap_generic_node(expression_ptr var0, expression_ptr var1)
9943 1292 : : binary_node<T>(details::e_swap, var0, var1)
9944 646 : , var0_(dynamic_cast<ivariable_ptr>(var0))
9945 1292 : , var1_(dynamic_cast<ivariable_ptr>(var1))
9946 646 : {}
9947 :
9948 685 : inline T value() const exprtk_override
9949 : {
9950 685 : std::swap(var0_->ref(),var1_->ref());
9951 685 : return var1_->ref();
9952 : }
9953 :
9954 7544 : inline typename expression_node<T>::node_type type() const exprtk_override
9955 : {
9956 7544 : return expression_node<T>::e_swap;
9957 : }
9958 :
9959 : private:
9960 :
9961 : ivariable_ptr var0_;
9962 : ivariable_ptr var1_;
9963 : };
9964 :
9965 : template <typename T>
9966 : class swap_vecvec_node exprtk_final
9967 : : public binary_node <T>
9968 : , public vector_interface<T>
9969 : {
9970 : public:
9971 :
9972 : typedef expression_node<T>* expression_ptr;
9973 : typedef vector_node <T>* vector_node_ptr;
9974 : typedef vec_data_store <T> vds_t;
9975 :
9976 : using binary_node<T>::branch;
9977 :
9978 662 : swap_vecvec_node(expression_ptr branch0,
9979 : expression_ptr branch1)
9980 0 : : binary_node<T>(details::e_swap, branch0, branch1)
9981 662 : , vec0_node_ptr_(0)
9982 662 : , vec1_node_ptr_(0)
9983 662 : , initialised_ (false)
9984 : {
9985 662 : if (is_ivector_node(branch(0)))
9986 : {
9987 662 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9988 :
9989 662 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
9990 : {
9991 662 : vec0_node_ptr_ = vi->vec();
9992 662 : vds() = vi->vds();
9993 : }
9994 : }
9995 :
9996 662 : if (is_ivector_node(branch(1)))
9997 : {
9998 662 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9999 :
10000 662 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
10001 : {
10002 662 : vec1_node_ptr_ = vi->vec();
10003 : }
10004 : }
10005 :
10006 662 : if (vec0_node_ptr_ && vec1_node_ptr_)
10007 : {
10008 662 : initialised_ = size() <= base_size();
10009 : }
10010 :
10011 662 : assert(valid());
10012 662 : }
10013 :
10014 662 : inline T value() const exprtk_override
10015 : {
10016 662 : binary_node<T>::branch(0)->value();
10017 662 : binary_node<T>::branch(1)->value();
10018 :
10019 662 : T* vec0 = vec0_node_ptr_->vds().data();
10020 662 : T* vec1 = vec1_node_ptr_->vds().data();
10021 :
10022 662 : assert(size() <= base_size());
10023 662 : const std::size_t n = size();
10024 :
10025 2186 : for (std::size_t i = 0; i < n; ++i)
10026 : {
10027 1524 : std::swap(vec0[i],vec1[i]);
10028 : }
10029 :
10030 662 : return vec1_node_ptr_->value();
10031 : }
10032 :
10033 0 : vector_node_ptr vec() const exprtk_override
10034 : {
10035 0 : return vec0_node_ptr_;
10036 : }
10037 :
10038 0 : vector_node_ptr vec() exprtk_override
10039 : {
10040 0 : return vec0_node_ptr_;
10041 : }
10042 :
10043 7282 : inline typename expression_node<T>::node_type type() const exprtk_override
10044 : {
10045 7282 : return expression_node<T>::e_vecvecswap;
10046 : }
10047 :
10048 1986 : inline bool valid() const exprtk_override
10049 : {
10050 1986 : return initialised_ && binary_node<T>::valid();
10051 : }
10052 :
10053 1986 : std::size_t size() const exprtk_override
10054 : {
10055 1986 : return std::min(
10056 1986 : vec0_node_ptr_->vec_holder().size(),
10057 3972 : vec1_node_ptr_->vec_holder().size());
10058 : }
10059 :
10060 1324 : std::size_t base_size() const exprtk_override
10061 : {
10062 1324 : return std::min(
10063 1324 : vec0_node_ptr_->vec_holder().base_size(),
10064 2648 : vec1_node_ptr_->vec_holder().base_size());
10065 : }
10066 :
10067 662 : vds_t& vds() exprtk_override
10068 : {
10069 662 : return vds_;
10070 : }
10071 :
10072 0 : const vds_t& vds() const exprtk_override
10073 : {
10074 0 : return vds_;
10075 : }
10076 :
10077 : private:
10078 :
10079 : vector_node<T>* vec0_node_ptr_;
10080 : vector_node<T>* vec1_node_ptr_;
10081 : bool initialised_;
10082 : vds_t vds_;
10083 : };
10084 :
10085 : #ifndef exprtk_disable_string_capabilities
10086 : template <typename T>
10087 : class stringvar_node exprtk_final
10088 : : public expression_node <T>
10089 : , public string_base_node<T>
10090 : , public range_interface <T>
10091 : {
10092 : public:
10093 :
10094 : typedef typename range_interface<T>::range_t range_t;
10095 :
10096 : static std::string null_value;
10097 :
10098 : explicit stringvar_node()
10099 : : value_(&null_value)
10100 : {}
10101 :
10102 132050 : explicit stringvar_node(std::string& v)
10103 132050 : : value_(&v)
10104 : {
10105 132050 : rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
10106 132050 : rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size());
10107 132050 : rp_.cache.first = rp_.n0_c.second;
10108 132050 : rp_.cache.second = rp_.n1_c.second;
10109 132050 : }
10110 :
10111 : inline bool operator <(const stringvar_node<T>& v) const
10112 : {
10113 : return this < (&v);
10114 : }
10115 :
10116 29712 : inline T value() const exprtk_override
10117 : {
10118 29712 : rp_.n1_c.second = (*value_).size();
10119 29712 : rp_.cache.second = rp_.n1_c.second;
10120 :
10121 29712 : return std::numeric_limits<T>::quiet_NaN();
10122 : }
10123 :
10124 1740 : std::string str() const exprtk_override
10125 : {
10126 1740 : return ref();
10127 : }
10128 :
10129 25505 : char_cptr base() const exprtk_override
10130 : {
10131 25505 : return &(*value_)[0];
10132 : }
10133 :
10134 10853 : std::size_t size() const exprtk_override
10135 : {
10136 10853 : return ref().size();
10137 : }
10138 :
10139 73519 : std::string& ref()
10140 : {
10141 73519 : return (*value_);
10142 : }
10143 :
10144 12593 : const std::string& ref() const
10145 : {
10146 12593 : return (*value_);
10147 : }
10148 :
10149 10629 : range_t& range_ref() exprtk_override
10150 : {
10151 10629 : return rp_;
10152 : }
10153 :
10154 0 : const range_t& range_ref() const exprtk_override
10155 : {
10156 0 : return rp_;
10157 : }
10158 :
10159 979868 : inline typename expression_node<T>::node_type type() const exprtk_override
10160 : {
10161 979868 : return expression_node<T>::e_stringvar;
10162 : }
10163 :
10164 : void rebase(std::string& s)
10165 : {
10166 : value_ = &s;
10167 : rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
10168 : rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1);
10169 : rp_.cache.first = rp_.n0_c.second;
10170 : rp_.cache.second = rp_.n1_c.second;
10171 : }
10172 :
10173 : private:
10174 :
10175 : std::string* value_;
10176 : mutable range_t rp_;
10177 : };
10178 :
10179 : template <typename T>
10180 : std::string stringvar_node<T>::null_value = std::string("");
10181 :
10182 : template <typename T>
10183 : class string_range_node exprtk_final
10184 : : public expression_node <T>
10185 : , public string_base_node<T>
10186 : , public range_interface <T>
10187 : {
10188 : public:
10189 :
10190 : typedef typename range_interface<T>::range_t range_t;
10191 :
10192 : static std::string null_value;
10193 :
10194 22401 : explicit string_range_node(std::string& v, const range_t& rp)
10195 22401 : : value_(&v)
10196 22401 : , rp_(rp)
10197 22401 : {}
10198 :
10199 44802 : virtual ~string_range_node()
10200 : {
10201 22401 : rp_.free();
10202 44802 : }
10203 :
10204 : inline bool operator <(const string_range_node<T>& v) const
10205 : {
10206 : return this < (&v);
10207 : }
10208 :
10209 13429 : inline T value() const exprtk_override
10210 : {
10211 13429 : return std::numeric_limits<T>::quiet_NaN();
10212 : }
10213 :
10214 0 : inline std::string str() const exprtk_override
10215 : {
10216 0 : return (*value_);
10217 : }
10218 :
10219 21168 : char_cptr base() const exprtk_override
10220 : {
10221 21168 : return &(*value_)[0];
10222 : }
10223 :
10224 13456 : std::size_t size() const exprtk_override
10225 : {
10226 13456 : return ref().size();
10227 : }
10228 :
10229 8960 : inline range_t range() const
10230 : {
10231 8960 : return rp_;
10232 : }
10233 :
10234 8960 : inline virtual std::string& ref()
10235 : {
10236 8960 : return (*value_);
10237 : }
10238 :
10239 13456 : inline virtual const std::string& ref() const
10240 : {
10241 13456 : return (*value_);
10242 : }
10243 :
10244 22416 : inline range_t& range_ref() exprtk_override
10245 : {
10246 22416 : return rp_;
10247 : }
10248 :
10249 0 : inline const range_t& range_ref() const exprtk_override
10250 : {
10251 0 : return rp_;
10252 : }
10253 :
10254 440261 : inline typename expression_node<T>::node_type type() const exprtk_override
10255 : {
10256 440261 : return expression_node<T>::e_stringvarrng;
10257 : }
10258 :
10259 : private:
10260 :
10261 : std::string* value_;
10262 : range_t rp_;
10263 : };
10264 :
10265 : template <typename T>
10266 : std::string string_range_node<T>::null_value = std::string("");
10267 :
10268 : template <typename T>
10269 : class const_string_range_node exprtk_final
10270 : : public expression_node <T>
10271 : , public string_base_node<T>
10272 : , public range_interface <T>
10273 : {
10274 : public:
10275 :
10276 : typedef typename range_interface<T>::range_t range_t;
10277 :
10278 5553 : explicit const_string_range_node(const std::string& v, const range_t& rp)
10279 5553 : : value_(v)
10280 5553 : , rp_(rp)
10281 5553 : {}
10282 :
10283 11106 : ~const_string_range_node()
10284 : {
10285 5553 : rp_.free();
10286 11106 : }
10287 :
10288 551 : inline T value() const exprtk_override
10289 : {
10290 551 : return std::numeric_limits<T>::quiet_NaN();
10291 : }
10292 :
10293 5000 : std::string str() const exprtk_override
10294 : {
10295 5000 : return value_;
10296 : }
10297 :
10298 551 : char_cptr base() const exprtk_override
10299 : {
10300 551 : return value_.data();
10301 : }
10302 :
10303 551 : std::size_t size() const exprtk_override
10304 : {
10305 551 : return value_.size();
10306 : }
10307 :
10308 5000 : range_t range() const
10309 : {
10310 5000 : return rp_;
10311 : }
10312 :
10313 5551 : range_t& range_ref() exprtk_override
10314 : {
10315 5551 : return rp_;
10316 : }
10317 :
10318 0 : const range_t& range_ref() const exprtk_override
10319 : {
10320 0 : return rp_;
10321 : }
10322 :
10323 110965 : inline typename expression_node<T>::node_type type() const exprtk_override
10324 : {
10325 110965 : return expression_node<T>::e_cstringvarrng;
10326 : }
10327 :
10328 : private:
10329 :
10330 : const_string_range_node(const const_string_range_node<T>&) exprtk_delete;
10331 : const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete;
10332 :
10333 : const std::string value_;
10334 : range_t rp_;
10335 : };
10336 :
10337 : template <typename T>
10338 : class generic_string_range_node exprtk_final
10339 : : public expression_node <T>
10340 : , public string_base_node<T>
10341 : , public range_interface <T>
10342 : {
10343 : public:
10344 :
10345 : typedef expression_node <T>* expression_ptr;
10346 : typedef stringvar_node <T>* strvar_node_ptr;
10347 : typedef string_base_node<T>* str_base_ptr;
10348 : typedef typename range_interface<T>::range_t range_t;
10349 : typedef range_t* range_ptr;
10350 : typedef range_interface<T> irange_t;
10351 : typedef irange_t* irange_ptr;
10352 : typedef std::pair<expression_ptr,bool> branch_t;
10353 :
10354 4102 : generic_string_range_node(expression_ptr str_branch, const range_t& brange)
10355 4102 : : initialised_(false)
10356 4102 : , str_base_ptr_ (0)
10357 4102 : , str_range_ptr_(0)
10358 4102 : , base_range_(brange)
10359 : {
10360 4102 : range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
10361 4102 : range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
10362 4102 : range_.cache.first = range_.n0_c.second;
10363 4102 : range_.cache.second = range_.n1_c.second;
10364 :
10365 4102 : construct_branch_pair(branch_, str_branch);
10366 :
10367 4102 : if (is_generally_string_node(branch_.first))
10368 : {
10369 4102 : str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
10370 :
10371 4102 : if (0 == str_base_ptr_)
10372 0 : return;
10373 :
10374 4102 : str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
10375 :
10376 4102 : if (0 == str_range_ptr_)
10377 0 : return;
10378 : }
10379 :
10380 4102 : initialised_ = (str_base_ptr_ && str_range_ptr_);
10381 4102 : assert(valid());
10382 0 : }
10383 :
10384 8204 : ~generic_string_range_node()
10385 : {
10386 4102 : base_range_.free();
10387 8204 : }
10388 :
10389 4100 : inline T value() const exprtk_override
10390 : {
10391 4100 : branch_.first->value();
10392 :
10393 4100 : std::size_t str_r0 = 0;
10394 4100 : std::size_t str_r1 = 0;
10395 :
10396 4100 : std::size_t r0 = 0;
10397 4100 : std::size_t r1 = 0;
10398 :
10399 4100 : const range_t& range = str_range_ptr_->range_ref();
10400 :
10401 4100 : const std::size_t base_str_size = str_base_ptr_->size();
10402 :
10403 4100 : if (
10404 8200 : range (str_r0, str_r1, base_str_size ) &&
10405 8200 : base_range_(r0 , r1 , base_str_size - str_r0)
10406 : )
10407 : {
10408 4100 : const std::size_t size = r1 - r0;
10409 :
10410 4100 : range_.n1_c.second = size;
10411 4100 : range_.cache.second = range_.n1_c.second;
10412 :
10413 4100 : value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
10414 : }
10415 :
10416 8200 : return std::numeric_limits<T>::quiet_NaN();
10417 : }
10418 :
10419 1300 : std::string str() const exprtk_override
10420 : {
10421 1300 : return value_;
10422 : }
10423 :
10424 2250 : char_cptr base() const exprtk_override
10425 : {
10426 2250 : return &value_[0];
10427 : }
10428 :
10429 4100 : std::size_t size() const exprtk_override
10430 : {
10431 4100 : return value_.size();
10432 : }
10433 :
10434 3550 : range_t& range_ref() exprtk_override
10435 : {
10436 3550 : return range_;
10437 : }
10438 :
10439 0 : const range_t& range_ref() const exprtk_override
10440 : {
10441 0 : return range_;
10442 : }
10443 :
10444 35556 : inline typename expression_node<T>::node_type type() const exprtk_override
10445 : {
10446 35556 : return expression_node<T>::e_strgenrange;
10447 : }
10448 :
10449 9504 : inline bool valid() const exprtk_override
10450 : {
10451 9504 : return initialised_ && branch_.first;
10452 : }
10453 :
10454 4102 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
10455 : {
10456 4102 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
10457 4102 : }
10458 :
10459 8202 : std::size_t node_depth() const exprtk_override
10460 : {
10461 8202 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
10462 : }
10463 :
10464 : private:
10465 :
10466 : bool initialised_;
10467 : branch_t branch_;
10468 : str_base_ptr str_base_ptr_;
10469 : irange_ptr str_range_ptr_;
10470 : mutable range_t base_range_;
10471 : mutable range_t range_;
10472 : mutable std::string value_;
10473 : };
10474 :
10475 : template <typename T>
10476 : class string_concat_node exprtk_final
10477 : : public binary_node <T>
10478 : , public string_base_node<T>
10479 : , public range_interface <T>
10480 : {
10481 : public:
10482 :
10483 : typedef typename range_interface<T>::range_t range_t;
10484 : typedef range_interface<T> irange_t;
10485 : typedef irange_t* irange_ptr;
10486 : typedef range_t* range_ptr;
10487 : typedef expression_node <T>* expression_ptr;
10488 : typedef string_base_node<T>* str_base_ptr;
10489 :
10490 : using binary_node<T>::branch;
10491 :
10492 5172 : string_concat_node(const operator_type& opr,
10493 : expression_ptr branch0,
10494 : expression_ptr branch1)
10495 : : binary_node<T>(opr, branch0, branch1)
10496 5172 : , initialised_(false)
10497 5172 : , str0_base_ptr_ (0)
10498 5172 : , str1_base_ptr_ (0)
10499 5172 : , str0_range_ptr_(0)
10500 5172 : , str1_range_ptr_(0)
10501 : {
10502 5172 : range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
10503 5172 : range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
10504 :
10505 5172 : range_.cache.first = range_.n0_c.second;
10506 5172 : range_.cache.second = range_.n1_c.second;
10507 :
10508 5172 : if (is_generally_string_node(branch(0)))
10509 : {
10510 5172 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
10511 :
10512 5172 : if (0 == str0_base_ptr_)
10513 0 : return;
10514 :
10515 5172 : str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
10516 :
10517 5172 : if (0 == str0_range_ptr_)
10518 0 : return;
10519 : }
10520 :
10521 5172 : if (is_generally_string_node(branch(1)))
10522 : {
10523 5172 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
10524 :
10525 5172 : if (0 == str1_base_ptr_)
10526 0 : return;
10527 :
10528 5172 : str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1));
10529 :
10530 5172 : if (0 == str1_range_ptr_)
10531 0 : return;
10532 : }
10533 :
10534 15516 : initialised_ = str0_base_ptr_ &&
10535 5172 : str1_base_ptr_ &&
10536 15516 : str0_range_ptr_ &&
10537 5172 : str1_range_ptr_ ;
10538 :
10539 5172 : assert(valid());
10540 0 : }
10541 :
10542 6115 : inline T value() const exprtk_override
10543 : {
10544 6115 : branch(0)->value();
10545 6115 : branch(1)->value();
10546 :
10547 6115 : std::size_t str0_r0 = 0;
10548 6115 : std::size_t str0_r1 = 0;
10549 :
10550 6115 : std::size_t str1_r0 = 0;
10551 6115 : std::size_t str1_r1 = 0;
10552 :
10553 6115 : const range_t& range0 = str0_range_ptr_->range_ref();
10554 6115 : const range_t& range1 = str1_range_ptr_->range_ref();
10555 :
10556 6115 : if (
10557 12230 : range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
10558 12230 : range1(str1_r0, str1_r1, str1_base_ptr_->size())
10559 : )
10560 : {
10561 6115 : const std::size_t size0 = (str0_r1 - str0_r0);
10562 6115 : const std::size_t size1 = (str1_r1 - str1_r0);
10563 :
10564 6115 : value_.assign(str0_base_ptr_->base() + str0_r0, size0);
10565 6115 : value_.append(str1_base_ptr_->base() + str1_r0, size1);
10566 :
10567 6115 : range_.n1_c.second = value_.size();
10568 6115 : range_.cache.second = range_.n1_c.second;
10569 : }
10570 :
10571 12230 : return std::numeric_limits<T>::quiet_NaN();
10572 : }
10573 :
10574 2696 : std::string str() const exprtk_override
10575 : {
10576 2696 : return value_;
10577 : }
10578 :
10579 3484 : char_cptr base() const exprtk_override
10580 : {
10581 3484 : return &value_[0];
10582 : }
10583 :
10584 6180 : std::size_t size() const exprtk_override
10585 : {
10586 6180 : return value_.size();
10587 : }
10588 :
10589 5181 : range_t& range_ref() exprtk_override
10590 : {
10591 5181 : return range_;
10592 : }
10593 :
10594 0 : const range_t& range_ref() const exprtk_override
10595 : {
10596 0 : return range_;
10597 : }
10598 :
10599 76214 : inline typename expression_node<T>::node_type type() const exprtk_override
10600 : {
10601 76214 : return expression_node<T>::e_strconcat;
10602 : }
10603 :
10604 17073 : inline bool valid() const exprtk_override
10605 : {
10606 17073 : return initialised_ && binary_node<T>::valid();
10607 : }
10608 :
10609 : private:
10610 :
10611 : bool initialised_;
10612 : str_base_ptr str0_base_ptr_;
10613 : str_base_ptr str1_base_ptr_;
10614 : irange_ptr str0_range_ptr_;
10615 : irange_ptr str1_range_ptr_;
10616 : mutable range_t range_;
10617 : mutable std::string value_;
10618 : };
10619 :
10620 : template <typename T>
10621 : class swap_string_node exprtk_final
10622 : : public binary_node <T>
10623 : , public string_base_node<T>
10624 : , public range_interface <T>
10625 : {
10626 : public:
10627 :
10628 : typedef typename range_interface<T>::range_t range_t;
10629 : typedef range_t* range_ptr;
10630 : typedef range_interface<T> irange_t;
10631 : typedef irange_t* irange_ptr;
10632 : typedef expression_node <T>* expression_ptr;
10633 : typedef stringvar_node <T>* strvar_node_ptr;
10634 : typedef string_base_node<T>* str_base_ptr;
10635 :
10636 : using binary_node<T>::branch;
10637 :
10638 0 : swap_string_node(expression_ptr branch0, expression_ptr branch1)
10639 0 : : binary_node<T>(details::e_swap, branch0, branch1)
10640 0 : , initialised_(false)
10641 0 : , str0_node_ptr_(0)
10642 0 : , str1_node_ptr_(0)
10643 : {
10644 0 : if (is_string_node(branch(0)))
10645 : {
10646 0 : str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
10647 : }
10648 :
10649 0 : if (is_string_node(branch(1)))
10650 : {
10651 0 : str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1));
10652 : }
10653 :
10654 0 : initialised_ = (str0_node_ptr_ && str1_node_ptr_);
10655 0 : assert(valid());
10656 0 : }
10657 :
10658 0 : inline T value() const exprtk_override
10659 : {
10660 0 : branch(0)->value();
10661 0 : branch(1)->value();
10662 :
10663 0 : std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
10664 :
10665 0 : return std::numeric_limits<T>::quiet_NaN();
10666 : }
10667 :
10668 0 : std::string str() const exprtk_override
10669 : {
10670 0 : return str0_node_ptr_->str();
10671 : }
10672 :
10673 0 : char_cptr base() const exprtk_override
10674 : {
10675 0 : return str0_node_ptr_->base();
10676 : }
10677 :
10678 0 : std::size_t size() const exprtk_override
10679 : {
10680 0 : return str0_node_ptr_->size();
10681 : }
10682 :
10683 0 : range_t& range_ref() exprtk_override
10684 : {
10685 0 : return str0_node_ptr_->range_ref();
10686 : }
10687 :
10688 0 : const range_t& range_ref() const exprtk_override
10689 : {
10690 0 : return str0_node_ptr_->range_ref();
10691 : }
10692 :
10693 0 : inline typename expression_node<T>::node_type type() const exprtk_override
10694 : {
10695 0 : return expression_node<T>::e_strswap;
10696 : }
10697 :
10698 0 : inline bool valid() const exprtk_override
10699 : {
10700 0 : return initialised_ && binary_node<T>::valid();
10701 : }
10702 :
10703 : private:
10704 :
10705 : bool initialised_;
10706 : strvar_node_ptr str0_node_ptr_;
10707 : strvar_node_ptr str1_node_ptr_;
10708 : };
10709 :
10710 : template <typename T>
10711 : class swap_genstrings_node exprtk_final : public binary_node<T>
10712 : {
10713 : public:
10714 :
10715 : typedef typename range_interface<T>::range_t range_t;
10716 : typedef range_t* range_ptr;
10717 : typedef range_interface<T> irange_t;
10718 : typedef irange_t* irange_ptr;
10719 : typedef expression_node <T>* expression_ptr;
10720 : typedef string_base_node<T>* str_base_ptr;
10721 :
10722 : using binary_node<T>::branch;
10723 :
10724 1500 : swap_genstrings_node(expression_ptr branch0,
10725 : expression_ptr branch1)
10726 0 : : binary_node<T>(details::e_default, branch0, branch1)
10727 1500 : , str0_base_ptr_ (0)
10728 1500 : , str1_base_ptr_ (0)
10729 1500 : , str0_range_ptr_(0)
10730 1500 : , str1_range_ptr_(0)
10731 1500 : , initialised_(false)
10732 : {
10733 1500 : if (is_generally_string_node(branch(0)))
10734 : {
10735 1500 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
10736 :
10737 1500 : if (0 == str0_base_ptr_)
10738 0 : return;
10739 :
10740 1500 : irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
10741 :
10742 1500 : if (0 == range)
10743 0 : return;
10744 :
10745 1500 : str0_range_ptr_ = &(range->range_ref());
10746 : }
10747 :
10748 1500 : if (is_generally_string_node(branch(1)))
10749 : {
10750 1500 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
10751 :
10752 1500 : if (0 == str1_base_ptr_)
10753 0 : return;
10754 :
10755 1500 : irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
10756 :
10757 1500 : if (0 == range)
10758 0 : return;
10759 :
10760 1500 : str1_range_ptr_ = &(range->range_ref());
10761 : }
10762 :
10763 4500 : initialised_ = str0_base_ptr_ &&
10764 1500 : str1_base_ptr_ &&
10765 4500 : str0_range_ptr_ &&
10766 1500 : str1_range_ptr_ ;
10767 :
10768 1500 : assert(valid());
10769 0 : }
10770 :
10771 1500 : inline T value() const exprtk_override
10772 : {
10773 1500 : branch(0)->value();
10774 1500 : branch(1)->value();
10775 :
10776 1500 : std::size_t str0_r0 = 0;
10777 1500 : std::size_t str0_r1 = 0;
10778 :
10779 1500 : std::size_t str1_r0 = 0;
10780 1500 : std::size_t str1_r1 = 0;
10781 :
10782 1500 : const range_t& range0 = (*str0_range_ptr_);
10783 1500 : const range_t& range1 = (*str1_range_ptr_);
10784 :
10785 1500 : if (
10786 3000 : range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
10787 3000 : range1(str1_r0, str1_r1, str1_base_ptr_->size())
10788 : )
10789 : {
10790 1500 : const std::size_t size0 = range0.cache_size();
10791 1500 : const std::size_t size1 = range1.cache_size();
10792 1500 : const std::size_t max_size = std::min(size0,size1);
10793 :
10794 1500 : char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
10795 1500 : char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
10796 :
10797 1500 : loop_unroll::details lud(max_size);
10798 1500 : char_cptr upper_bound = s0 + lud.upper_bound;
10799 :
10800 1500 : while (s0 < upper_bound)
10801 : {
10802 : #define exprtk_loop(N) \
10803 : std::swap(s0[N], s1[N]); \
10804 :
10805 0 : exprtk_loop( 0) exprtk_loop( 1)
10806 0 : exprtk_loop( 2) exprtk_loop( 3)
10807 : #ifndef exprtk_disable_superscalar_unroll
10808 0 : exprtk_loop( 4) exprtk_loop( 5)
10809 0 : exprtk_loop( 6) exprtk_loop( 7)
10810 0 : exprtk_loop( 8) exprtk_loop( 9)
10811 0 : exprtk_loop(10) exprtk_loop(11)
10812 0 : exprtk_loop(12) exprtk_loop(13)
10813 0 : exprtk_loop(14) exprtk_loop(15)
10814 : #endif
10815 :
10816 0 : s0 += lud.batch_size;
10817 0 : s1 += lud.batch_size;
10818 : }
10819 :
10820 1500 : int i = 0;
10821 :
10822 1500 : switch (lud.remainder)
10823 : {
10824 : #define case_stmt(N) \
10825 : case N : { std::swap(s0[i], s1[i]); ++i; } \
10826 : exprtk_fallthrough \
10827 :
10828 : #ifndef exprtk_disable_superscalar_unroll
10829 0 : case_stmt(15) case_stmt(14)
10830 0 : case_stmt(13) case_stmt(12)
10831 0 : case_stmt(11) case_stmt(10)
10832 0 : case_stmt( 9) case_stmt( 8)
10833 0 : case_stmt( 7) case_stmt( 6)
10834 600 : case_stmt( 5) case_stmt( 4)
10835 : #endif
10836 1200 : case_stmt( 3) case_stmt( 2)
10837 1500 : case_stmt( 1)
10838 1500 : default: break;
10839 : }
10840 :
10841 : #undef exprtk_loop
10842 : #undef case_stmt
10843 : }
10844 :
10845 3000 : return std::numeric_limits<T>::quiet_NaN();
10846 : }
10847 :
10848 18000 : inline typename expression_node<T>::node_type type() const exprtk_override
10849 : {
10850 18000 : return expression_node<T>::e_strswap;
10851 : }
10852 :
10853 4500 : inline bool valid() const exprtk_override
10854 : {
10855 4500 : return initialised_ && binary_node<T>::valid();
10856 : }
10857 :
10858 : private:
10859 :
10860 : swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete;
10861 : swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete;
10862 :
10863 : str_base_ptr str0_base_ptr_;
10864 : str_base_ptr str1_base_ptr_;
10865 : range_ptr str0_range_ptr_;
10866 : range_ptr str1_range_ptr_;
10867 : bool initialised_;
10868 : };
10869 :
10870 : template <typename T>
10871 : class stringvar_size_node exprtk_final : public expression_node<T>
10872 : {
10873 : public:
10874 :
10875 : static const std::string null_value;
10876 :
10877 : explicit stringvar_size_node()
10878 : : value_(&null_value)
10879 : {}
10880 :
10881 3800 : explicit stringvar_size_node(std::string& v)
10882 3800 : : value_(&v)
10883 3800 : {}
10884 :
10885 3800 : inline T value() const exprtk_override
10886 : {
10887 3800 : return T((*value_).size());
10888 : }
10889 :
10890 80140 : inline typename expression_node<T>::node_type type() const exprtk_override
10891 : {
10892 80140 : return expression_node<T>::e_stringvarsize;
10893 : }
10894 :
10895 : private:
10896 :
10897 : const std::string* value_;
10898 : };
10899 :
10900 : template <typename T>
10901 : const std::string stringvar_size_node<T>::null_value = std::string("");
10902 :
10903 : template <typename T>
10904 : class string_size_node exprtk_final : public expression_node<T>
10905 : {
10906 : public:
10907 :
10908 : typedef expression_node <T>* expression_ptr;
10909 : typedef string_base_node<T>* str_base_ptr;
10910 : typedef std::pair<expression_ptr,bool> branch_t;
10911 :
10912 750 : explicit string_size_node(expression_ptr branch)
10913 750 : : str_base_ptr_(0)
10914 : {
10915 750 : construct_branch_pair(branch_, branch);
10916 :
10917 750 : if (is_generally_string_node(branch_.first))
10918 : {
10919 750 : str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
10920 : }
10921 :
10922 750 : assert(valid());
10923 750 : }
10924 :
10925 750 : inline T value() const exprtk_override
10926 : {
10927 750 : branch_.first->value();
10928 750 : return T(str_base_ptr_->size());
10929 : }
10930 :
10931 23250 : inline typename expression_node<T>::node_type type() const exprtk_override
10932 : {
10933 23250 : return expression_node<T>::e_stringsize;
10934 : }
10935 :
10936 1500 : inline bool valid() const exprtk_override
10937 : {
10938 1500 : return str_base_ptr_;
10939 : }
10940 :
10941 750 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
10942 : {
10943 750 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
10944 750 : }
10945 :
10946 1500 : std::size_t node_depth() const exprtk_override
10947 : {
10948 1500 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
10949 : }
10950 :
10951 : private:
10952 :
10953 : branch_t branch_;
10954 : str_base_ptr str_base_ptr_;
10955 : };
10956 :
10957 : struct asn_assignment
10958 : {
10959 12990 : static inline void execute(std::string& s, char_cptr data, const std::size_t size)
10960 12990 : { s.assign(data,size); }
10961 : };
10962 :
10963 : struct asn_addassignment
10964 : {
10965 6700 : static inline void execute(std::string& s, char_cptr data, const std::size_t size)
10966 6700 : { s.append(data,size); }
10967 : };
10968 :
10969 : template <typename T, typename AssignmentProcess = asn_assignment>
10970 : class assignment_string_node exprtk_final
10971 : : public binary_node <T>
10972 : , public string_base_node<T>
10973 : , public range_interface <T>
10974 : {
10975 : public:
10976 :
10977 : typedef typename range_interface<T>::range_t range_t;
10978 : typedef range_t* range_ptr;
10979 : typedef range_interface <T> irange_t;
10980 : typedef irange_t* irange_ptr;
10981 : typedef expression_node <T>* expression_ptr;
10982 : typedef stringvar_node <T>* strvar_node_ptr;
10983 : typedef string_base_node<T>* str_base_ptr;
10984 :
10985 : using binary_node<T>::branch;
10986 :
10987 14591 : assignment_string_node(const operator_type& opr,
10988 : expression_ptr branch0,
10989 : expression_ptr branch1)
10990 : : binary_node<T>(opr, branch0, branch1)
10991 14591 : , initialised_(false)
10992 14591 : , str0_base_ptr_ (0)
10993 14591 : , str1_base_ptr_ (0)
10994 14591 : , str0_node_ptr_ (0)
10995 14591 : , str1_range_ptr_(0)
10996 : {
10997 14591 : if (is_string_node(branch(0)))
10998 : {
10999 14591 : str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0));
11000 14591 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
11001 : }
11002 :
11003 14591 : if (is_generally_string_node(branch(1)))
11004 : {
11005 14591 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
11006 :
11007 14591 : if (0 == str1_base_ptr_)
11008 0 : return;
11009 :
11010 14591 : irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
11011 :
11012 14591 : if (0 == range)
11013 0 : return;
11014 :
11015 14591 : str1_range_ptr_ = &(range->range_ref());
11016 : }
11017 :
11018 43773 : initialised_ = str0_base_ptr_ &&
11019 14591 : str1_base_ptr_ &&
11020 43773 : str0_node_ptr_ &&
11021 14591 : str1_range_ptr_ ;
11022 :
11023 14591 : assert(valid());
11024 0 : }
11025 :
11026 19690 : inline T value() const exprtk_override
11027 : {
11028 19690 : branch(1)->value();
11029 :
11030 19690 : std::size_t r0 = 0;
11031 19690 : std::size_t r1 = 0;
11032 :
11033 19690 : const range_t& range = (*str1_range_ptr_);
11034 :
11035 19690 : if (range(r0, r1, str1_base_ptr_->size()))
11036 : {
11037 19690 : AssignmentProcess::execute(
11038 19690 : str0_node_ptr_->ref(),
11039 19690 : str1_base_ptr_->base() + r0, (r1 - r0));
11040 :
11041 19690 : branch(0)->value();
11042 : }
11043 :
11044 39380 : return std::numeric_limits<T>::quiet_NaN();
11045 : }
11046 :
11047 300 : std::string str() const exprtk_override
11048 : {
11049 300 : return str0_node_ptr_->str();
11050 : }
11051 :
11052 201 : char_cptr base() const exprtk_override
11053 : {
11054 201 : return str0_node_ptr_->base();
11055 : }
11056 :
11057 701 : std::size_t size() const exprtk_override
11058 : {
11059 701 : return str0_node_ptr_->size();
11060 : }
11061 :
11062 501 : range_t& range_ref() exprtk_override
11063 : {
11064 501 : return str0_node_ptr_->range_ref();
11065 : }
11066 :
11067 0 : const range_t& range_ref() const exprtk_override
11068 : {
11069 0 : return str0_node_ptr_->range_ref();
11070 : }
11071 :
11072 174562 : inline typename expression_node<T>::node_type type() const exprtk_override
11073 : {
11074 174562 : return expression_node<T>::e_strass;
11075 : }
11076 :
11077 44640 : inline bool valid() const exprtk_override
11078 : {
11079 44640 : return initialised_ && binary_node<T>::valid();
11080 : }
11081 :
11082 : private:
11083 :
11084 : bool initialised_;
11085 : str_base_ptr str0_base_ptr_;
11086 : str_base_ptr str1_base_ptr_;
11087 : strvar_node_ptr str0_node_ptr_;
11088 : range_ptr str1_range_ptr_;
11089 : };
11090 :
11091 : template <typename T, typename AssignmentProcess = asn_assignment>
11092 : class assignment_string_range_node exprtk_final
11093 : : public binary_node <T>
11094 : , public string_base_node<T>
11095 : , public range_interface <T>
11096 : {
11097 : public:
11098 :
11099 : typedef typename range_interface<T>::range_t range_t;
11100 : typedef range_t* range_ptr;
11101 : typedef range_interface <T> irange_t;
11102 : typedef irange_t* irange_ptr;
11103 : typedef expression_node <T>* expression_ptr;
11104 : typedef stringvar_node <T>* strvar_node_ptr;
11105 : typedef string_range_node<T>* str_rng_node_ptr;
11106 : typedef string_base_node <T>* str_base_ptr;
11107 :
11108 : using binary_node<T>::branch;
11109 :
11110 4850 : assignment_string_range_node(const operator_type& opr,
11111 : expression_ptr branch0,
11112 : expression_ptr branch1)
11113 : : binary_node<T>(opr, branch0, branch1)
11114 4850 : , initialised_(false)
11115 4850 : , str0_base_ptr_ (0)
11116 4850 : , str1_base_ptr_ (0)
11117 4850 : , str0_rng_node_ptr_(0)
11118 4850 : , str0_range_ptr_ (0)
11119 4850 : , str1_range_ptr_ (0)
11120 : {
11121 4850 : if (is_string_range_node(branch(0)))
11122 : {
11123 4850 : str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0));
11124 4850 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
11125 4850 : irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
11126 :
11127 4850 : if (0 == range)
11128 0 : return;
11129 :
11130 4850 : str0_range_ptr_ = &(range->range_ref());
11131 : }
11132 :
11133 4850 : if (is_generally_string_node(branch(1)))
11134 : {
11135 4850 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
11136 :
11137 4850 : if (0 == str1_base_ptr_)
11138 0 : return;
11139 :
11140 4850 : irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
11141 :
11142 4850 : if (0 == range)
11143 0 : return;
11144 :
11145 4850 : str1_range_ptr_ = &(range->range_ref());
11146 : }
11147 :
11148 14550 : initialised_ = str0_base_ptr_ &&
11149 4850 : str1_base_ptr_ &&
11150 4850 : str0_rng_node_ptr_ &&
11151 14550 : str0_range_ptr_ &&
11152 4850 : str1_range_ptr_ ;
11153 :
11154 4850 : assert(valid());
11155 0 : }
11156 :
11157 4850 : inline T value() const exprtk_override
11158 : {
11159 4850 : branch(0)->value();
11160 4850 : branch(1)->value();
11161 :
11162 4850 : std::size_t s0_r0 = 0;
11163 4850 : std::size_t s0_r1 = 0;
11164 :
11165 4850 : std::size_t s1_r0 = 0;
11166 4850 : std::size_t s1_r1 = 0;
11167 :
11168 4850 : const range_t& range0 = (*str0_range_ptr_);
11169 4850 : const range_t& range1 = (*str1_range_ptr_);
11170 :
11171 4850 : if (
11172 9700 : range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
11173 9700 : range1(s1_r0, s1_r1, str1_base_ptr_->size())
11174 : )
11175 : {
11176 4850 : const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0));
11177 :
11178 9700 : std::copy(
11179 4850 : str1_base_ptr_->base() + s1_r0,
11180 4850 : str1_base_ptr_->base() + s1_r0 + size,
11181 4850 : const_cast<char_ptr>(base() + s0_r0));
11182 : }
11183 :
11184 9700 : return std::numeric_limits<T>::quiet_NaN();
11185 : }
11186 :
11187 0 : std::string str() const exprtk_override
11188 : {
11189 0 : return str0_base_ptr_->str();
11190 : }
11191 :
11192 4850 : char_cptr base() const exprtk_override
11193 : {
11194 4850 : return str0_base_ptr_->base();
11195 : }
11196 :
11197 0 : std::size_t size() const exprtk_override
11198 : {
11199 0 : return str0_base_ptr_->size();
11200 : }
11201 :
11202 0 : range_t& range_ref() exprtk_override
11203 : {
11204 0 : return str0_rng_node_ptr_->range_ref();
11205 : }
11206 :
11207 0 : const range_t& range_ref() const exprtk_override
11208 : {
11209 0 : return str0_rng_node_ptr_->range_ref();
11210 : }
11211 :
11212 78300 : inline typename expression_node<T>::node_type type() const exprtk_override
11213 : {
11214 78300 : return expression_node<T>::e_strass;
11215 : }
11216 :
11217 14550 : inline bool valid() const exprtk_override
11218 : {
11219 14550 : return initialised_ && binary_node<T>::valid();
11220 : }
11221 :
11222 : private:
11223 :
11224 : bool initialised_;
11225 : str_base_ptr str0_base_ptr_;
11226 : str_base_ptr str1_base_ptr_;
11227 : str_rng_node_ptr str0_rng_node_ptr_;
11228 : range_ptr str0_range_ptr_;
11229 : range_ptr str1_range_ptr_;
11230 : };
11231 :
11232 : template <typename T>
11233 : class conditional_string_node exprtk_final
11234 : : public trinary_node <T>
11235 : , public string_base_node<T>
11236 : , public range_interface <T>
11237 : {
11238 : public:
11239 :
11240 : typedef typename range_interface<T>::range_t range_t;
11241 : typedef range_t* range_ptr;
11242 : typedef range_interface <T> irange_t;
11243 : typedef irange_t* irange_ptr;
11244 : typedef expression_node <T>* expression_ptr;
11245 : typedef string_base_node<T>* str_base_ptr;
11246 :
11247 1151 : conditional_string_node(expression_ptr condition,
11248 : expression_ptr consequent,
11249 : expression_ptr alternative)
11250 0 : : trinary_node<T>(details::e_default, consequent, alternative, condition)
11251 1151 : , initialised_(false)
11252 1151 : , str0_base_ptr_ (0)
11253 1151 : , str1_base_ptr_ (0)
11254 1151 : , str0_range_ptr_(0)
11255 1151 : , str1_range_ptr_(0)
11256 1151 : , condition_ (condition )
11257 1151 : , consequent_ (consequent )
11258 1151 : , alternative_(alternative)
11259 : {
11260 1151 : range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11261 1151 : range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11262 :
11263 1151 : range_.cache.first = range_.n0_c.second;
11264 1151 : range_.cache.second = range_.n1_c.second;
11265 :
11266 1151 : if (is_generally_string_node(trinary_node<T>::branch_[0].first))
11267 : {
11268 1151 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
11269 :
11270 1151 : if (0 == str0_base_ptr_)
11271 0 : return;
11272 :
11273 1151 : str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
11274 :
11275 1151 : if (0 == str0_range_ptr_)
11276 0 : return;
11277 : }
11278 :
11279 1151 : if (is_generally_string_node(trinary_node<T>::branch_[1].first))
11280 : {
11281 1151 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
11282 :
11283 1151 : if (0 == str1_base_ptr_)
11284 0 : return;
11285 :
11286 1151 : str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
11287 :
11288 1151 : if (0 == str1_range_ptr_)
11289 0 : return;
11290 : }
11291 :
11292 3453 : initialised_ = str0_base_ptr_ &&
11293 1151 : str1_base_ptr_ &&
11294 3453 : str0_range_ptr_ &&
11295 1151 : str1_range_ptr_ ;
11296 :
11297 1151 : assert(valid());
11298 0 : }
11299 :
11300 1146 : inline T value() const exprtk_override
11301 : {
11302 1146 : std::size_t r0 = 0;
11303 1146 : std::size_t r1 = 0;
11304 :
11305 1146 : if (is_true(condition_))
11306 : {
11307 581 : consequent_->value();
11308 :
11309 581 : const range_t& range = str0_range_ptr_->range_ref();
11310 :
11311 581 : if (range(r0, r1, str0_base_ptr_->size()))
11312 : {
11313 581 : const std::size_t size = (r1 - r0);
11314 :
11315 581 : value_.assign(str0_base_ptr_->base() + r0, size);
11316 :
11317 581 : range_.n1_c.second = value_.size();
11318 581 : range_.cache.second = range_.n1_c.second;
11319 :
11320 581 : return T(1);
11321 : }
11322 : }
11323 : else
11324 : {
11325 565 : alternative_->value();
11326 :
11327 565 : const range_t& range = str1_range_ptr_->range_ref();
11328 :
11329 565 : if (range(r0, r1, str1_base_ptr_->size()))
11330 : {
11331 565 : const std::size_t size = (r1 - r0);
11332 :
11333 565 : value_.assign(str1_base_ptr_->base() + r0, size);
11334 :
11335 565 : range_.n1_c.second = value_.size();
11336 565 : range_.cache.second = range_.n1_c.second;
11337 :
11338 565 : return T(0);
11339 : }
11340 : }
11341 :
11342 0 : return std::numeric_limits<T>::quiet_NaN();
11343 : }
11344 :
11345 1100 : std::string str() const exprtk_override
11346 : {
11347 1100 : return value_;
11348 : }
11349 :
11350 46 : char_cptr base() const exprtk_override
11351 : {
11352 46 : return &value_[0];
11353 : }
11354 :
11355 1146 : std::size_t size() const exprtk_override
11356 : {
11357 1146 : return value_.size();
11358 : }
11359 :
11360 1146 : range_t& range_ref() exprtk_override
11361 : {
11362 1146 : return range_;
11363 : }
11364 :
11365 0 : const range_t& range_ref() const exprtk_override
11366 : {
11367 0 : return range_;
11368 : }
11369 :
11370 27232 : inline typename expression_node<T>::node_type type() const exprtk_override
11371 : {
11372 27232 : return expression_node<T>::e_strcondition;
11373 : }
11374 :
11375 3691 : inline bool valid() const exprtk_override
11376 : {
11377 : return
11378 7382 : initialised_ &&
11379 3691 : condition_ && condition_ ->valid() &&
11380 3691 : consequent_ && consequent_ ->valid() &&
11381 7382 : alternative_&& alternative_->valid() ;
11382 : }
11383 :
11384 : private:
11385 :
11386 : bool initialised_;
11387 : str_base_ptr str0_base_ptr_;
11388 : str_base_ptr str1_base_ptr_;
11389 : irange_ptr str0_range_ptr_;
11390 : irange_ptr str1_range_ptr_;
11391 : mutable range_t range_;
11392 : mutable std::string value_;
11393 :
11394 : expression_ptr condition_;
11395 : expression_ptr consequent_;
11396 : expression_ptr alternative_;
11397 : };
11398 :
11399 : template <typename T>
11400 : class cons_conditional_str_node exprtk_final
11401 : : public binary_node <T>
11402 : , public string_base_node<T>
11403 : , public range_interface <T>
11404 : {
11405 : public:
11406 :
11407 : typedef typename range_interface<T>::range_t range_t;
11408 : typedef range_t* range_ptr;
11409 : typedef range_interface <T> irange_t;
11410 : typedef irange_t* irange_ptr;
11411 : typedef expression_node <T>* expression_ptr;
11412 : typedef string_base_node<T>* str_base_ptr;
11413 :
11414 : using binary_node<T>::branch;
11415 :
11416 : cons_conditional_str_node(expression_ptr condition,
11417 : expression_ptr consequent)
11418 : : binary_node<T>(details::e_default, consequent, condition)
11419 : , initialised_(false)
11420 : , str0_base_ptr_ (0)
11421 : , str0_range_ptr_(0)
11422 : , condition_ (condition )
11423 : , consequent_(consequent)
11424 : {
11425 : range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11426 : range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11427 :
11428 : range_.cache.first = range_.n0_c.second;
11429 : range_.cache.second = range_.n1_c.second;
11430 :
11431 : if (is_generally_string_node(branch(0)))
11432 : {
11433 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
11434 :
11435 : if (0 == str0_base_ptr_)
11436 : return;
11437 :
11438 : str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0));
11439 :
11440 : if (0 == str0_range_ptr_)
11441 : return;
11442 : }
11443 :
11444 : initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
11445 : assert(valid());
11446 : }
11447 :
11448 : inline T value() const exprtk_override
11449 : {
11450 : if (is_true(condition_))
11451 : {
11452 : consequent_->value();
11453 :
11454 : const range_t& range = str0_range_ptr_->range_ref();
11455 :
11456 : std::size_t r0 = 0;
11457 : std::size_t r1 = 0;
11458 :
11459 : if (range(r0, r1, str0_base_ptr_->size()))
11460 : {
11461 : const std::size_t size = (r1 - r0);
11462 :
11463 : value_.assign(str0_base_ptr_->base() + r0, size);
11464 :
11465 : range_.n1_c.second = value_.size();
11466 : range_.cache.second = range_.n1_c.second;
11467 :
11468 : return T(1);
11469 : }
11470 : }
11471 :
11472 : return std::numeric_limits<T>::quiet_NaN();
11473 : }
11474 :
11475 : std::string str() const
11476 : {
11477 : return value_;
11478 : }
11479 :
11480 : char_cptr base() const
11481 : {
11482 : return &value_[0];
11483 : }
11484 :
11485 : std::size_t size() const
11486 : {
11487 : return value_.size();
11488 : }
11489 :
11490 : range_t& range_ref()
11491 : {
11492 : return range_;
11493 : }
11494 :
11495 : const range_t& range_ref() const
11496 : {
11497 : return range_;
11498 : }
11499 :
11500 : inline typename expression_node<T>::node_type type() const exprtk_override
11501 : {
11502 : return expression_node<T>::e_strccondition;
11503 : }
11504 :
11505 : inline bool valid() const exprtk_override
11506 : {
11507 : return
11508 : initialised_ &&
11509 : condition_ && condition_ ->valid() &&
11510 : consequent_ && consequent_ ->valid() ;
11511 : }
11512 :
11513 : private:
11514 :
11515 : bool initialised_;
11516 : str_base_ptr str0_base_ptr_;
11517 : irange_ptr str0_range_ptr_;
11518 : mutable range_t range_;
11519 : mutable std::string value_;
11520 :
11521 : expression_ptr condition_;
11522 : expression_ptr consequent_;
11523 : };
11524 :
11525 : template <typename T, typename VarArgFunction>
11526 : class str_vararg_node exprtk_final
11527 : : public expression_node <T>
11528 : , public string_base_node<T>
11529 : , public range_interface <T>
11530 : {
11531 : public:
11532 :
11533 : typedef typename range_interface<T>::range_t range_t;
11534 : typedef range_t* range_ptr;
11535 : typedef range_interface <T> irange_t;
11536 : typedef irange_t* irange_ptr;
11537 : typedef expression_node <T>* expression_ptr;
11538 : typedef string_base_node<T>* str_base_ptr;
11539 : typedef std::pair<expression_ptr,bool> branch_t;
11540 :
11541 : template <typename Allocator,
11542 : template <typename, typename> class Sequence>
11543 85 : explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
11544 85 : : initialised_(false)
11545 85 : , str_base_ptr_ (0)
11546 85 : , str_range_ptr_(0)
11547 : {
11548 85 : construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
11549 :
11550 85 : if (0 == final_node_.first)
11551 0 : return;
11552 85 : else if (!is_generally_string_node(final_node_.first))
11553 0 : return;
11554 :
11555 85 : str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
11556 :
11557 85 : if (0 == str_base_ptr_)
11558 0 : return;
11559 :
11560 85 : str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
11561 :
11562 85 : if (0 == str_range_ptr_)
11563 0 : return;
11564 :
11565 85 : if (arg_list.size() > 1)
11566 : {
11567 85 : const std::size_t arg_list_size = arg_list.size() - 1;
11568 :
11569 85 : arg_list_.resize(arg_list_size);
11570 :
11571 245 : for (std::size_t i = 0; i < arg_list_size; ++i)
11572 : {
11573 160 : if (arg_list[i] && arg_list[i]->valid())
11574 : {
11575 160 : construct_branch_pair(arg_list_[i], arg_list[i]);
11576 : }
11577 : else
11578 : {
11579 0 : arg_list_.clear();
11580 0 : return;
11581 : }
11582 : }
11583 :
11584 85 : initialised_ = true;
11585 : }
11586 :
11587 85 : initialised_ &= str_base_ptr_ && str_range_ptr_;
11588 85 : assert(valid());
11589 0 : }
11590 :
11591 85 : inline T value() const exprtk_override
11592 : {
11593 85 : if (!arg_list_.empty())
11594 : {
11595 85 : VarArgFunction::process(arg_list_);
11596 : }
11597 :
11598 85 : final_node_.first->value();
11599 :
11600 85 : return std::numeric_limits<T>::quiet_NaN();
11601 : }
11602 :
11603 40 : std::string str() const exprtk_override
11604 : {
11605 40 : return str_base_ptr_->str();
11606 : }
11607 :
11608 45 : char_cptr base() const exprtk_override
11609 : {
11610 45 : return str_base_ptr_->base();
11611 : }
11612 :
11613 85 : std::size_t size() const exprtk_override
11614 : {
11615 85 : return str_base_ptr_->size();
11616 : }
11617 :
11618 85 : range_t& range_ref() exprtk_override
11619 : {
11620 85 : return str_range_ptr_->range_ref();
11621 : }
11622 :
11623 0 : const range_t& range_ref() const exprtk_override
11624 : {
11625 0 : return str_range_ptr_->range_ref();
11626 : }
11627 :
11628 1285 : inline typename expression_node<T>::node_type type() const exprtk_override
11629 : {
11630 1285 : return expression_node<T>::e_stringvararg;
11631 : }
11632 :
11633 390 : inline bool valid() const exprtk_override
11634 : {
11635 : return
11636 780 : initialised_ &&
11637 390 : final_node_.first && final_node_.first->valid();
11638 : }
11639 :
11640 85 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
11641 : {
11642 85 : expression_node<T>::ndb_t::collect(final_node_ , node_delete_list);
11643 85 : expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list);
11644 85 : }
11645 :
11646 215 : std::size_t node_depth() const exprtk_override
11647 : {
11648 215 : return std::max(
11649 215 : expression_node<T>::ndb_t::compute_node_depth(final_node_),
11650 430 : expression_node<T>::ndb_t::compute_node_depth(arg_list_ ));
11651 : }
11652 :
11653 : private:
11654 :
11655 : bool initialised_;
11656 : branch_t final_node_;
11657 : str_base_ptr str_base_ptr_;
11658 : irange_ptr str_range_ptr_;
11659 : std::vector<branch_t> arg_list_;
11660 : };
11661 : #endif
11662 :
11663 : template <typename T>
11664 : class assert_node exprtk_final : public expression_node<T>
11665 : {
11666 : public:
11667 :
11668 : typedef expression_node<T>* expression_ptr;
11669 : typedef std::pair<expression_ptr,bool> branch_t;
11670 : typedef string_base_node<T>* str_base_ptr;
11671 : typedef assert_check::assert_context assert_context_t;
11672 :
11673 84 : assert_node(expression_ptr assert_condition_node,
11674 : expression_ptr assert_message_node,
11675 : assert_check_ptr assert_check,
11676 : assert_context_t context)
11677 84 : : assert_message_str_base_(0)
11678 84 : , assert_check_(assert_check)
11679 84 : , context_(context)
11680 : {
11681 84 : construct_branch_pair(assert_condition_node_, assert_condition_node);
11682 84 : construct_branch_pair(assert_message_node_ , assert_message_node );
11683 :
11684 : #ifndef exprtk_disable_string_capabilities
11685 84 : if (
11686 154 : assert_message_node_.first &&
11687 70 : details::is_generally_string_node(assert_message_node_.first)
11688 : )
11689 : {
11690 70 : assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first);
11691 : }
11692 : #endif
11693 :
11694 84 : assert(valid());
11695 84 : }
11696 :
11697 84 : inline T value() const exprtk_override
11698 : {
11699 84 : if (assert_condition_node_.first->value() != T(0))
11700 : {
11701 0 : return T(1);
11702 : }
11703 :
11704 : #ifndef exprtk_disable_string_capabilities
11705 84 : if (assert_message_node_.first)
11706 : {
11707 70 : assert_message_node_.first->value();
11708 70 : assert(assert_message_str_base_);
11709 70 : context_.message = assert_message_str_base_->str();
11710 : }
11711 : #endif
11712 :
11713 84 : assert_check_->handle_assert(context_);
11714 84 : return T(0);
11715 : }
11716 :
11717 1158 : inline typename expression_node<T>::node_type type() const exprtk_override
11718 : {
11719 1158 : return expression_node<T>::e_assert;
11720 : }
11721 :
11722 252 : inline bool valid() const exprtk_override
11723 : {
11724 : return (
11725 504 : assert_check_ &&
11726 252 : assert_condition_node_.first &&
11727 252 : assert_condition_node_.first->valid()
11728 504 : ) &&
11729 : (
11730 252 : (0 == assert_message_node_.first) ||
11731 : (
11732 210 : assert_message_node_.first &&
11733 210 : assert_message_str_base_ &&
11734 210 : assert_message_node_.first->valid() &&
11735 210 : details::is_generally_string_node(assert_message_node_.first)
11736 : )
11737 252 : );
11738 : }
11739 :
11740 84 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
11741 : {
11742 84 : expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list);
11743 84 : expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list);
11744 84 : }
11745 :
11746 222 : std::size_t node_depth() const exprtk_override
11747 : {
11748 : return expression_node<T>::ndb_t::compute_node_depth
11749 222 : (assert_condition_node_, assert_message_node_);
11750 : }
11751 :
11752 : private:
11753 :
11754 : branch_t assert_condition_node_;
11755 : branch_t assert_message_node_;
11756 : str_base_ptr assert_message_str_base_;
11757 : assert_check_ptr assert_check_;
11758 : mutable assert_context_t context_;
11759 : };
11760 :
11761 : template <typename T, std::size_t N>
11762 640 : inline T axn(const T a, const T x)
11763 : {
11764 : // a*x^n
11765 640 : return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
11766 : }
11767 :
11768 : template <typename T, std::size_t N>
11769 320 : inline T axnb(const T a, const T x, const T b)
11770 : {
11771 : // a*x^n+b
11772 320 : return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
11773 : }
11774 :
11775 : template <typename T>
11776 : struct sf_base
11777 : {
11778 : typedef typename details::functor_t<T>::Type Type;
11779 : typedef typename details::functor_t<T> functor_t;
11780 : typedef typename functor_t::qfunc_t quaternary_functor_t;
11781 : typedef typename functor_t::tfunc_t trinary_functor_t;
11782 : typedef typename functor_t::bfunc_t binary_functor_t;
11783 : typedef typename functor_t::ufunc_t unary_functor_t;
11784 : };
11785 :
11786 : #define define_sfop3(NN, OP0, OP1) \
11787 : template <typename T> \
11788 : struct sf##NN##_op : public sf_base<T> \
11789 : { \
11790 : typedef typename sf_base<T>::Type const Type; \
11791 : static inline T process(Type x, Type y, Type z) \
11792 : { \
11793 : return (OP0); \
11794 : } \
11795 : static inline std::string id() \
11796 : { \
11797 : return (OP1); \
11798 : } \
11799 : }; \
11800 :
11801 370734 : define_sfop3(00,(x + y) / z ,"(t+t)/t")
11802 370845 : define_sfop3(01,(x + y) * z ,"(t+t)*t")
11803 371235 : define_sfop3(02,(x + y) - z ,"(t+t)-t")
11804 386326 : define_sfop3(03,(x + y) + z ,"(t+t)+t")
11805 4999126 : define_sfop3(04,(x - y) + z ,"(t-t)+t")
11806 369043 : define_sfop3(05,(x - y) / z ,"(t-t)/t")
11807 371590 : define_sfop3(06,(x - y) * z ,"(t-t)*t")
11808 104384042 : define_sfop3(07,(x * y) + z ,"(t*t)+t")
11809 376882 : define_sfop3(08,(x * y) - z ,"(t*t)-t")
11810 502355 : define_sfop3(09,(x * y) / z ,"(t*t)/t")
11811 5149805 : define_sfop3(10,(x * y) * z ,"(t*t)*t")
11812 382710 : define_sfop3(11,(x / y) + z ,"(t/t)+t")
11813 376297 : define_sfop3(12,(x / y) - z ,"(t/t)-t")
11814 326020 : define_sfop3(13,(x / y) / z ,"(t/t)/t")
11815 476345 : define_sfop3(14,(x / y) * z ,"(t/t)*t")
11816 361620 : define_sfop3(15,x / (y + z) ,"t/(t+t)")
11817 361330 : define_sfop3(16,x / (y - z) ,"t/(t-t)")
11818 527115 : define_sfop3(17,x / (y * z) ,"t/(t*t)")
11819 326020 : define_sfop3(18,x / (y / z) ,"t/(t/t)")
11820 366860 : define_sfop3(19,x * (y + z) ,"t*(t+t)")
11821 361860 : define_sfop3(20,x * (y - z) ,"t*(t-t)")
11822 399748 : define_sfop3(21,x * (y * z) ,"t*(t*t)")
11823 360255 : define_sfop3(22,x * (y / z) ,"t*(t/t)")
11824 396625 : define_sfop3(23,x - (y + z) ,"t-(t+t)")
11825 354280 : define_sfop3(24,x - (y - z) ,"t-(t-t)")
11826 375495 : define_sfop3(25,x - (y / z) ,"t-(t/t)")
11827 6390073 : define_sfop3(26,x - (y * z) ,"t-(t*t)")
11828 875196 : define_sfop3(27,x + (y * z) ,"t+(t*t)")
11829 377460 : define_sfop3(28,x + (y / z) ,"t+(t/t)")
11830 354690 : define_sfop3(29,x + (y + z) ,"t+(t+t)")
11831 353620 : define_sfop3(30,x + (y - z) ,"t+(t-t)")
11832 40 : define_sfop3(31,(axnb<T,2>(x,y,z))," ")
11833 40 : define_sfop3(32,(axnb<T,3>(x,y,z))," ")
11834 40 : define_sfop3(33,(axnb<T,4>(x,y,z))," ")
11835 40 : define_sfop3(34,(axnb<T,5>(x,y,z))," ")
11836 40 : define_sfop3(35,(axnb<T,6>(x,y,z))," ")
11837 40 : define_sfop3(36,(axnb<T,7>(x,y,z))," ")
11838 40 : define_sfop3(37,(axnb<T,8>(x,y,z))," ")
11839 40 : define_sfop3(38,(axnb<T,9>(x,y,z))," ")
11840 40 : define_sfop3(39,x * numeric::log(y) + z,"")
11841 40 : define_sfop3(40,x * numeric::log(y) - z,"")
11842 40 : define_sfop3(41,x * numeric::log10(y) + z,"")
11843 40 : define_sfop3(42,x * numeric::log10(y) - z,"")
11844 40 : define_sfop3(43,x * numeric::sin(y) + z ,"")
11845 40 : define_sfop3(44,x * numeric::sin(y) - z ,"")
11846 40 : define_sfop3(45,x * numeric::cos(y) + z ,"")
11847 40 : define_sfop3(46,x * numeric::cos(y) - z ,"")
11848 40 : define_sfop3(47,details::is_true(x) ? y : z,"")
11849 :
11850 : #define define_sfop4(NN, OP0, OP1) \
11851 : template <typename T> \
11852 : struct sf##NN##_op : public sf_base<T> \
11853 : { \
11854 : typedef typename sf_base<T>::Type const Type; \
11855 : static inline T process(Type x, Type y, Type z, Type w) \
11856 : { \
11857 : return (OP0); \
11858 : } \
11859 : static inline std::string id() \
11860 : { \
11861 : return (OP1); \
11862 : } \
11863 : }; \
11864 :
11865 329110 : define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
11866 329275 : define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
11867 329110 : define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
11868 329215 : define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
11869 332965 : define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
11870 334145 : define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
11871 329260 : define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
11872 326020 : define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
11873 332595 : define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
11874 329151 : define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
11875 329110 : define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
11876 329115 : define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
11877 329110 : define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
11878 332405 : define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
11879 332585 : define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
11880 326020 : define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
11881 332715 : define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
11882 329110 : define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
11883 329110 : define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
11884 329990 : define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
11885 330745 : define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
11886 329110 : define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
11887 329110 : define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
11888 332255 : define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
11889 326020 : define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
11890 332718 : define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
11891 332110 : define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
11892 329835 : define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
11893 330955 : define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
11894 330433 : define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
11895 330515 : define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
11896 332775 : define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
11897 329110 : define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
11898 329110 : define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
11899 329135 : define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
11900 329135 : define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
11901 :
11902 40 : define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
11903 40 : define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
11904 40 : define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
11905 40 : define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
11906 40 : define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
11907 40 : define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
11908 40 : define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
11909 40 : define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
11910 75 : define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
11911 75 : define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
11912 75 : define_sfop4(94,((x < y) ? z : w),"")
11913 75 : define_sfop4(95,((x <= y) ? z : w),"")
11914 75 : define_sfop4(96,((x > y) ? z : w),"")
11915 75 : define_sfop4(97,((x >= y) ? z : w),"")
11916 75 : define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
11917 40 : define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
11918 :
11919 333970 : define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
11920 330765 : define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
11921 331695 : define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
11922 330735 : define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
11923 331845 : define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
11924 331245 : define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
11925 333510 : define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
11926 330415 : define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
11927 329070 : define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
11928 329050 : define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
11929 326705 : define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
11930 329050 : define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
11931 329270 : define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
11932 329710 : define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
11933 329370 : define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
11934 329570 : define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
11935 329230 : define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
11936 329050 : define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
11937 329050 : define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
11938 329050 : define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
11939 329050 : define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
11940 329050 : define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
11941 329050 : define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
11942 329050 : define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
11943 329050 : define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
11944 329050 : define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
11945 329485 : define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
11946 329050 : define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
11947 328625 : define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
11948 329050 : define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
11949 328620 : define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
11950 329050 : define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
11951 329480 : define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
11952 329215 : define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
11953 328900 : define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
11954 329060 : define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
11955 655035 : define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
11956 0 : define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
11957 329065 : define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
11958 329220 : define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
11959 328155 : define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
11960 325980 : define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
11961 328900 : define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
11962 326705 : define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
11963 328960 : define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
11964 328900 : define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
11965 334680 : define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
11966 334580 : define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
11967 325980 : define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
11968 325980 : define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
11969 327140 : define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
11970 327140 : define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
11971 327220 : define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
11972 327140 : define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
11973 327945 : define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
11974 327285 : define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
11975 327845 : define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
11976 327285 : define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
11977 327285 : define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
11978 327725 : define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
11979 329375 : define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
11980 342265 : define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
11981 :
11982 : #undef define_sfop3
11983 : #undef define_sfop4
11984 :
11985 : template <typename T, typename SpecialFunction>
11986 : class sf3_node exprtk_final : public trinary_node<T>
11987 : {
11988 : public:
11989 :
11990 : typedef expression_node<T>* expression_ptr;
11991 :
11992 720 : sf3_node(const operator_type& opr,
11993 : expression_ptr branch0,
11994 : expression_ptr branch1,
11995 : expression_ptr branch2)
11996 720 : : trinary_node<T>(opr, branch0, branch1, branch2)
11997 720 : {}
11998 :
11999 720 : inline T value() const exprtk_override
12000 : {
12001 720 : const T x = trinary_node<T>::branch_[0].first->value();
12002 720 : const T y = trinary_node<T>::branch_[1].first->value();
12003 720 : const T z = trinary_node<T>::branch_[2].first->value();
12004 :
12005 1440 : return SpecialFunction::process(x, y, z);
12006 : }
12007 : };
12008 :
12009 : template <typename T, typename SpecialFunction>
12010 : class sf4_node exprtk_final : public quaternary_node<T>
12011 : {
12012 : public:
12013 :
12014 : typedef expression_node<T>* expression_ptr;
12015 :
12016 815 : sf4_node(const operator_type& opr,
12017 : expression_ptr branch0,
12018 : expression_ptr branch1,
12019 : expression_ptr branch2,
12020 : expression_ptr branch3)
12021 815 : : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
12022 815 : {}
12023 :
12024 815 : inline T value() const exprtk_override
12025 : {
12026 815 : const T x = quaternary_node<T>::branch_[0].first->value();
12027 815 : const T y = quaternary_node<T>::branch_[1].first->value();
12028 815 : const T z = quaternary_node<T>::branch_[2].first->value();
12029 815 : const T w = quaternary_node<T>::branch_[3].first->value();
12030 :
12031 1630 : return SpecialFunction::process(x, y, z, w);
12032 : }
12033 : };
12034 :
12035 : template <typename T, typename SpecialFunction>
12036 : class sf3_var_node exprtk_final : public expression_node<T>
12037 : {
12038 : public:
12039 :
12040 : typedef expression_node<T>* expression_ptr;
12041 :
12042 1200 : sf3_var_node(const T& v0, const T& v1, const T& v2)
12043 1200 : : v0_(v0)
12044 1200 : , v1_(v1)
12045 1200 : , v2_(v2)
12046 1200 : {}
12047 :
12048 1200 : inline T value() const exprtk_override
12049 : {
12050 1200 : return SpecialFunction::process(v0_, v1_, v2_);
12051 : }
12052 :
12053 15600 : inline typename expression_node<T>::node_type type() const exprtk_override
12054 : {
12055 15600 : return expression_node<T>::e_trinary;
12056 : }
12057 :
12058 : private:
12059 :
12060 : sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
12061 : sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete;
12062 :
12063 : const T& v0_;
12064 : const T& v1_;
12065 : const T& v2_;
12066 : };
12067 :
12068 : template <typename T, typename SpecialFunction>
12069 : class sf4_var_node exprtk_final : public expression_node<T>
12070 : {
12071 : public:
12072 :
12073 : typedef expression_node<T>* expression_ptr;
12074 :
12075 1510 : sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
12076 1510 : : v0_(v0)
12077 1510 : , v1_(v1)
12078 1510 : , v2_(v2)
12079 1510 : , v3_(v3)
12080 1510 : {}
12081 :
12082 1510 : inline T value() const exprtk_override
12083 : {
12084 1510 : return SpecialFunction::process(v0_, v1_, v2_, v3_);
12085 : }
12086 :
12087 19630 : inline typename expression_node<T>::node_type type() const exprtk_override
12088 : {
12089 19630 : return expression_node<T>::e_trinary;
12090 : }
12091 :
12092 : private:
12093 :
12094 : sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
12095 : sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete;
12096 :
12097 : const T& v0_;
12098 : const T& v1_;
12099 : const T& v2_;
12100 : const T& v3_;
12101 : };
12102 :
12103 : template <typename T, typename VarArgFunction>
12104 : class vararg_node exprtk_final : public expression_node<T>
12105 : {
12106 : public:
12107 :
12108 : typedef expression_node<T>* expression_ptr;
12109 : typedef std::pair<expression_ptr,bool> branch_t;
12110 :
12111 : template <typename Allocator,
12112 : template <typename, typename> class Sequence>
12113 44798 : explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
12114 44798 : : initialised_(false)
12115 : {
12116 44798 : arg_list_.resize(arg_list.size());
12117 :
12118 182663 : for (std::size_t i = 0; i < arg_list.size(); ++i)
12119 : {
12120 137865 : if (arg_list[i] && arg_list[i]->valid())
12121 : {
12122 137865 : construct_branch_pair(arg_list_[i],arg_list[i]);
12123 : }
12124 : else
12125 : {
12126 0 : arg_list_.clear();
12127 0 : return;
12128 : }
12129 : }
12130 :
12131 44798 : initialised_ = (arg_list_.size() == arg_list.size());
12132 44798 : assert(valid());
12133 0 : }
12134 :
12135 10172947 : inline T value() const exprtk_override
12136 : {
12137 10172947 : return VarArgFunction::process(arg_list_);
12138 : }
12139 :
12140 251312 : inline typename expression_node<T>::node_type type() const exprtk_override
12141 : {
12142 251312 : return expression_node<T>::e_vararg;
12143 : }
12144 :
12145 108186 : inline bool valid() const exprtk_override
12146 : {
12147 108186 : return initialised_;
12148 : }
12149 :
12150 44798 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
12151 : {
12152 44798 : expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
12153 44798 : }
12154 :
12155 62159 : std::size_t node_depth() const exprtk_override
12156 : {
12157 62159 : return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
12158 : }
12159 :
12160 54 : std::size_t size() const
12161 : {
12162 54 : return arg_list_.size();
12163 : }
12164 :
12165 272 : expression_ptr operator[](const std::size_t& index) const
12166 : {
12167 272 : return arg_list_[index].first;
12168 : }
12169 :
12170 : private:
12171 :
12172 : std::vector<branch_t> arg_list_;
12173 : bool initialised_;
12174 : };
12175 :
12176 : template <typename T, typename VarArgFunction>
12177 : class vararg_varnode exprtk_final : public expression_node<T>
12178 : {
12179 : public:
12180 :
12181 : typedef expression_node<T>* expression_ptr;
12182 :
12183 : template <typename Allocator,
12184 : template <typename, typename> class Sequence>
12185 2308 : explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
12186 2308 : : initialised_(false)
12187 : {
12188 2308 : arg_list_.resize(arg_list.size());
12189 :
12190 7435 : for (std::size_t i = 0; i < arg_list.size(); ++i)
12191 : {
12192 5127 : if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i]))
12193 : {
12194 5127 : variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
12195 5127 : arg_list_[i] = (&var_node_ptr->ref());
12196 : }
12197 : else
12198 : {
12199 0 : arg_list_.clear();
12200 0 : return;
12201 : }
12202 : }
12203 :
12204 2308 : initialised_ = (arg_list.size() == arg_list_.size());
12205 2308 : assert(valid());
12206 0 : }
12207 :
12208 2308 : inline T value() const exprtk_override
12209 : {
12210 2308 : return VarArgFunction::process(arg_list_);
12211 : }
12212 :
12213 58623 : inline typename expression_node<T>::node_type type() const exprtk_override
12214 : {
12215 58623 : return expression_node<T>::e_vararg;
12216 : }
12217 :
12218 8034 : inline bool valid() const exprtk_override
12219 : {
12220 8034 : return initialised_;
12221 : }
12222 :
12223 : private:
12224 :
12225 : std::vector<const T*> arg_list_;
12226 : bool initialised_;
12227 : };
12228 :
12229 : template <typename T, typename VecFunction>
12230 : class vectorize_node exprtk_final : public expression_node<T>
12231 : {
12232 : public:
12233 :
12234 : typedef expression_node<T>* expression_ptr;
12235 : typedef std::pair<expression_ptr,bool> branch_t;
12236 :
12237 2401 : explicit vectorize_node(const expression_ptr v)
12238 2401 : : ivec_ptr_(0)
12239 : {
12240 2401 : construct_branch_pair(v_, v);
12241 :
12242 2401 : if (is_ivector_node(v_.first))
12243 : {
12244 2401 : ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
12245 : }
12246 2401 : }
12247 :
12248 2615 : inline T value() const exprtk_override
12249 : {
12250 2615 : v_.first->value();
12251 2615 : return VecFunction::process(ivec_ptr_);
12252 : }
12253 :
12254 61533 : inline typename expression_node<T>::node_type type() const exprtk_override
12255 : {
12256 61533 : return expression_node<T>::e_vecfunc;
12257 : }
12258 :
12259 5296 : inline bool valid() const exprtk_override
12260 : {
12261 5296 : return ivec_ptr_ && v_.first && v_.first->valid();
12262 : }
12263 :
12264 2401 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
12265 : {
12266 2401 : expression_node<T>::ndb_t::collect(v_, node_delete_list);
12267 2401 : }
12268 :
12269 5388 : std::size_t node_depth() const exprtk_override
12270 : {
12271 5388 : return expression_node<T>::ndb_t::compute_node_depth(v_);
12272 : }
12273 :
12274 : private:
12275 :
12276 : vector_interface<T>* ivec_ptr_;
12277 : branch_t v_;
12278 : };
12279 :
12280 : template <typename T>
12281 : class assignment_node exprtk_final : public binary_node<T>
12282 : {
12283 : public:
12284 :
12285 : typedef expression_node<T>* expression_ptr;
12286 : using binary_node<T>::branch;
12287 :
12288 46190 : assignment_node(const operator_type& opr,
12289 : expression_ptr branch0,
12290 : expression_ptr branch1)
12291 : : binary_node<T>(opr, branch0, branch1)
12292 46190 : , var_node_ptr_(0)
12293 : {
12294 46190 : if (is_variable_node(branch(0)))
12295 : {
12296 46190 : var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
12297 : }
12298 46190 : }
12299 :
12300 26769309 : inline T value() const exprtk_override
12301 : {
12302 26769309 : T& result = var_node_ptr_->ref();
12303 26769309 : result = branch(1)->value();
12304 :
12305 26769309 : return result;
12306 : }
12307 :
12308 98248 : inline bool valid() const exprtk_override
12309 : {
12310 98248 : return var_node_ptr_ && binary_node<T>::valid();
12311 : }
12312 :
12313 : private:
12314 :
12315 : variable_node<T>* var_node_ptr_;
12316 : };
12317 :
12318 : template <typename T>
12319 : class assignment_vec_elem_node exprtk_final : public binary_node<T>
12320 : {
12321 : public:
12322 :
12323 : typedef expression_node<T>* expression_ptr;
12324 : using binary_node<T>::branch;
12325 :
12326 83 : assignment_vec_elem_node(const operator_type& opr,
12327 : expression_ptr branch0,
12328 : expression_ptr branch1)
12329 : : binary_node<T>(opr, branch0, branch1)
12330 83 : , vec_node_ptr_(0)
12331 : {
12332 83 : if (is_vector_elem_node(branch(0)))
12333 : {
12334 83 : vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
12335 : }
12336 :
12337 83 : assert(valid());
12338 83 : }
12339 :
12340 22850849 : inline T value() const exprtk_override
12341 : {
12342 22850849 : T& result = vec_node_ptr_->ref();
12343 22850849 : result = branch(1)->value();
12344 :
12345 22850849 : return result;
12346 : }
12347 :
12348 246 : inline bool valid() const exprtk_override
12349 : {
12350 246 : return vec_node_ptr_ && binary_node<T>::valid();
12351 : }
12352 :
12353 : private:
12354 :
12355 : vector_elem_node<T>* vec_node_ptr_;
12356 : };
12357 :
12358 : template <typename T>
12359 : class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T>
12360 : {
12361 : public:
12362 :
12363 : typedef expression_node<T>* expression_ptr;
12364 : using binary_node<T>::branch;
12365 :
12366 20 : assignment_vec_elem_rtc_node(const operator_type& opr,
12367 : expression_ptr branch0,
12368 : expression_ptr branch1)
12369 : : binary_node<T>(opr, branch0, branch1)
12370 20 : , vec_node_ptr_(0)
12371 : {
12372 20 : if (is_vector_elem_rtc_node(branch(0)))
12373 : {
12374 20 : vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
12375 : }
12376 :
12377 20 : assert(valid());
12378 20 : }
12379 :
12380 150 : inline T value() const exprtk_override
12381 : {
12382 150 : T& result = vec_node_ptr_->ref();
12383 150 : result = branch(1)->value();
12384 :
12385 150 : return result;
12386 : }
12387 :
12388 40 : inline bool valid() const exprtk_override
12389 : {
12390 40 : return vec_node_ptr_ && binary_node<T>::valid();
12391 : }
12392 :
12393 : private:
12394 :
12395 : vector_elem_rtc_node<T>* vec_node_ptr_;
12396 : };
12397 :
12398 : template <typename T>
12399 : class assignment_rebasevec_elem_node exprtk_final : public binary_node<T>
12400 : {
12401 : public:
12402 :
12403 : typedef expression_node<T>* expression_ptr;
12404 : using expression_node<T>::branch;
12405 :
12406 0 : assignment_rebasevec_elem_node(const operator_type& opr,
12407 : expression_ptr branch0,
12408 : expression_ptr branch1)
12409 : : binary_node<T>(opr, branch0, branch1)
12410 0 : , rbvec_node_ptr_(0)
12411 : {
12412 0 : if (is_rebasevector_elem_node(branch(0)))
12413 : {
12414 0 : rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
12415 : }
12416 :
12417 0 : assert(valid());
12418 0 : }
12419 :
12420 0 : inline T value() const exprtk_override
12421 : {
12422 0 : T& result = rbvec_node_ptr_->ref();
12423 0 : result = branch(1)->value();
12424 :
12425 0 : return result;
12426 : }
12427 :
12428 0 : inline bool valid() const exprtk_override
12429 : {
12430 0 : return rbvec_node_ptr_ && binary_node<T>::valid();
12431 : }
12432 :
12433 : private:
12434 :
12435 : rebasevector_elem_node<T>* rbvec_node_ptr_;
12436 : };
12437 :
12438 : template <typename T>
12439 : class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T>
12440 : {
12441 : public:
12442 :
12443 : typedef expression_node<T>* expression_ptr;
12444 : using expression_node<T>::branch;
12445 :
12446 0 : assignment_rebasevec_elem_rtc_node(const operator_type& opr,
12447 : expression_ptr branch0,
12448 : expression_ptr branch1)
12449 : : binary_node<T>(opr, branch0, branch1)
12450 0 : , rbvec_node_ptr_(0)
12451 : {
12452 0 : if (is_rebasevector_elem_rtc_node(branch(0)))
12453 : {
12454 0 : rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
12455 : }
12456 :
12457 0 : assert(valid());
12458 0 : }
12459 :
12460 0 : inline T value() const exprtk_override
12461 : {
12462 0 : T& result = rbvec_node_ptr_->ref();
12463 0 : result = branch(1)->value();
12464 :
12465 0 : return result;
12466 : }
12467 :
12468 0 : inline bool valid() const exprtk_override
12469 : {
12470 0 : return rbvec_node_ptr_ && binary_node<T>::valid();
12471 : }
12472 :
12473 : private:
12474 :
12475 : rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
12476 : };
12477 :
12478 : template <typename T>
12479 : class assignment_rebasevec_celem_node exprtk_final : public binary_node<T>
12480 : {
12481 : public:
12482 :
12483 : typedef expression_node<T>* expression_ptr;
12484 : using binary_node<T>::branch;
12485 :
12486 0 : assignment_rebasevec_celem_node(const operator_type& opr,
12487 : expression_ptr branch0,
12488 : expression_ptr branch1)
12489 : : binary_node<T>(opr, branch0, branch1)
12490 0 : , rbvec_node_ptr_(0)
12491 : {
12492 0 : if (is_rebasevector_celem_node(branch(0)))
12493 : {
12494 0 : rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
12495 : }
12496 :
12497 0 : assert(valid());
12498 0 : }
12499 :
12500 0 : inline T value() const exprtk_override
12501 : {
12502 0 : T& result = rbvec_node_ptr_->ref();
12503 0 : result = branch(1)->value();
12504 :
12505 0 : return result;
12506 : }
12507 :
12508 0 : inline bool valid() const exprtk_override
12509 : {
12510 0 : return rbvec_node_ptr_ && binary_node<T>::valid();
12511 : }
12512 :
12513 : private:
12514 :
12515 : rebasevector_celem_node<T>* rbvec_node_ptr_;
12516 : };
12517 :
12518 : template <typename T>
12519 : class assignment_vec_node exprtk_final
12520 : : public binary_node <T>
12521 : , public vector_interface<T>
12522 : {
12523 : public:
12524 :
12525 : typedef expression_node<T>* expression_ptr;
12526 : typedef vector_node<T>* vector_node_ptr;
12527 : typedef vec_data_store<T> vds_t;
12528 :
12529 : using binary_node<T>::branch;
12530 :
12531 204 : assignment_vec_node(const operator_type& opr,
12532 : expression_ptr branch0,
12533 : expression_ptr branch1)
12534 : : binary_node<T>(opr, branch0, branch1)
12535 204 : , vec_node_ptr_(0)
12536 : {
12537 204 : if (is_vector_node(branch(0)))
12538 : {
12539 204 : vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
12540 204 : vds() = vec_node_ptr_->vds();
12541 : }
12542 :
12543 204 : assert(valid());
12544 204 : }
12545 :
12546 204 : inline T value() const exprtk_override
12547 : {
12548 204 : const T v = branch(1)->value();
12549 :
12550 204 : T* vec = vds().data();
12551 :
12552 204 : loop_unroll::details lud(size());
12553 204 : const T* upper_bound = vec + lud.upper_bound;
12554 :
12555 204 : while (vec < upper_bound)
12556 : {
12557 : #define exprtk_loop(N) \
12558 : vec[N] = v; \
12559 :
12560 0 : exprtk_loop( 0) exprtk_loop( 1)
12561 0 : exprtk_loop( 2) exprtk_loop( 3)
12562 : #ifndef exprtk_disable_superscalar_unroll
12563 0 : exprtk_loop( 4) exprtk_loop( 5)
12564 0 : exprtk_loop( 6) exprtk_loop( 7)
12565 0 : exprtk_loop( 8) exprtk_loop( 9)
12566 0 : exprtk_loop(10) exprtk_loop(11)
12567 0 : exprtk_loop(12) exprtk_loop(13)
12568 0 : exprtk_loop(14) exprtk_loop(15)
12569 : #endif
12570 :
12571 0 : vec += lud.batch_size;
12572 : }
12573 :
12574 204 : switch (lud.remainder)
12575 : {
12576 : #define case_stmt(N) \
12577 : case N : *vec++ = v; \
12578 : exprtk_fallthrough \
12579 :
12580 : #ifndef exprtk_disable_superscalar_unroll
12581 0 : case_stmt(15) case_stmt(14)
12582 0 : case_stmt(13) case_stmt(12)
12583 0 : case_stmt(11) case_stmt(10)
12584 183 : case_stmt( 9) case_stmt( 8)
12585 189 : case_stmt( 7) case_stmt( 6)
12586 195 : case_stmt( 5) case_stmt( 4)
12587 : #endif
12588 201 : case_stmt( 3) case_stmt( 2)
12589 204 : case 1 : *vec++ = v;
12590 : }
12591 :
12592 : #undef exprtk_loop
12593 : #undef case_stmt
12594 :
12595 408 : return vec_node_ptr_->value();
12596 : }
12597 :
12598 0 : vector_node_ptr vec() const exprtk_override
12599 : {
12600 0 : return vec_node_ptr_;
12601 : }
12602 :
12603 0 : vector_node_ptr vec() exprtk_override
12604 : {
12605 0 : return vec_node_ptr_;
12606 : }
12607 :
12608 2244 : inline typename expression_node<T>::node_type type() const exprtk_override
12609 : {
12610 2244 : return expression_node<T>::e_vecvalass;
12611 : }
12612 :
12613 612 : inline bool valid() const exprtk_override
12614 : {
12615 : return
12616 1224 : vec_node_ptr_ &&
12617 1224 : (vds().size() <= vec_node_ptr_->vec_holder().base_size()) &&
12618 1224 : binary_node<T>::valid();
12619 : }
12620 :
12621 204 : std::size_t size() const exprtk_override
12622 : {
12623 204 : return vec_node_ptr_->vec_holder().size();
12624 : }
12625 :
12626 0 : std::size_t base_size() const exprtk_override
12627 : {
12628 0 : return vec_node_ptr_->vec_holder().base_size();
12629 : }
12630 :
12631 204 : vds_t& vds() exprtk_override
12632 : {
12633 204 : return vds_;
12634 : }
12635 :
12636 816 : const vds_t& vds() const exprtk_override
12637 : {
12638 816 : return vds_;
12639 : }
12640 :
12641 : private:
12642 :
12643 : vector_node<T>* vec_node_ptr_;
12644 : vds_t vds_;
12645 : };
12646 :
12647 : template <typename T>
12648 : class assignment_vecvec_node exprtk_final
12649 : : public binary_node <T>
12650 : , public vector_interface<T>
12651 : {
12652 : public:
12653 :
12654 : typedef expression_node<T>* expression_ptr;
12655 : typedef vector_node<T>* vector_node_ptr;
12656 : typedef vec_data_store<T> vds_t;
12657 :
12658 : using binary_node<T>::branch;
12659 :
12660 1471 : assignment_vecvec_node(const operator_type& opr,
12661 : expression_ptr branch0,
12662 : expression_ptr branch1)
12663 : : binary_node<T>(opr, branch0, branch1)
12664 1471 : , vec0_node_ptr_(0)
12665 1471 : , vec1_node_ptr_(0)
12666 1471 : , initialised_(false)
12667 1471 : , src_is_ivec_(false)
12668 : {
12669 1471 : if (is_vector_node(branch(0)))
12670 : {
12671 1471 : vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
12672 1471 : vds() = vec0_node_ptr_->vds();
12673 : }
12674 :
12675 1471 : if (is_vector_node(branch(1)))
12676 : {
12677 489 : vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
12678 489 : vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
12679 : }
12680 982 : else if (is_ivector_node(branch(1)))
12681 : {
12682 982 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
12683 :
12684 982 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
12685 : {
12686 982 : vec1_node_ptr_ = vi->vec();
12687 :
12688 982 : if (!vi->side_effect())
12689 : {
12690 822 : vi->vds() = vds();
12691 822 : src_is_ivec_ = true;
12692 : }
12693 : else
12694 160 : vds_t::match_sizes(vds(),vi->vds());
12695 : }
12696 : }
12697 :
12698 1471 : initialised_ =
12699 2942 : vec0_node_ptr_ &&
12700 1471 : vec1_node_ptr_ &&
12701 1471 : (size() <= base_size()) &&
12702 4413 : (vds_.size() <= base_size()) &&
12703 1471 : binary_node<T>::valid();
12704 :
12705 1471 : assert(valid());
12706 1471 : }
12707 :
12708 1471 : inline T value() const exprtk_override
12709 : {
12710 1471 : branch(1)->value();
12711 :
12712 1471 : if (src_is_ivec_)
12713 822 : return vec0_node_ptr_->value();
12714 :
12715 649 : T* vec0 = vec0_node_ptr_->vds().data();
12716 649 : T* vec1 = vec1_node_ptr_->vds().data();
12717 :
12718 649 : loop_unroll::details lud(size());
12719 649 : const T* upper_bound = vec0 + lud.upper_bound;
12720 :
12721 649 : while (vec0 < upper_bound)
12722 : {
12723 : #define exprtk_loop(N) \
12724 : vec0[N] = vec1[N]; \
12725 :
12726 0 : exprtk_loop( 0) exprtk_loop( 1)
12727 0 : exprtk_loop( 2) exprtk_loop( 3)
12728 : #ifndef exprtk_disable_superscalar_unroll
12729 0 : exprtk_loop( 4) exprtk_loop( 5)
12730 0 : exprtk_loop( 6) exprtk_loop( 7)
12731 0 : exprtk_loop( 8) exprtk_loop( 9)
12732 0 : exprtk_loop(10) exprtk_loop(11)
12733 0 : exprtk_loop(12) exprtk_loop(13)
12734 0 : exprtk_loop(14) exprtk_loop(15)
12735 : #endif
12736 :
12737 0 : vec0 += lud.batch_size;
12738 0 : vec1 += lud.batch_size;
12739 : }
12740 :
12741 649 : switch (lud.remainder)
12742 : {
12743 : #define case_stmt(N,fall_through) \
12744 : case N : *vec0++ = *vec1++; \
12745 : fall_through \
12746 :
12747 : #ifndef exprtk_disable_superscalar_unroll
12748 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
12749 0 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
12750 0 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
12751 2 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
12752 8 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
12753 304 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
12754 : #endif
12755 564 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
12756 649 : case_stmt( 1, (void)0;)
12757 : }
12758 :
12759 : #undef exprtk_loop
12760 : #undef case_stmt
12761 :
12762 649 : return vec0_node_ptr_->value();
12763 : }
12764 :
12765 0 : vector_node_ptr vec() exprtk_override
12766 : {
12767 0 : return vec0_node_ptr_;
12768 : }
12769 :
12770 0 : vector_node_ptr vec() const exprtk_override
12771 : {
12772 0 : return vec0_node_ptr_;
12773 : }
12774 :
12775 16223 : inline typename expression_node<T>::node_type type() const exprtk_override
12776 : {
12777 16223 : return expression_node<T>::e_vecvecass;
12778 : }
12779 :
12780 4703 : inline bool valid() const exprtk_override
12781 : {
12782 4703 : return initialised_;
12783 : }
12784 :
12785 2120 : std::size_t size() const exprtk_override
12786 : {
12787 2120 : return std::min(
12788 2120 : vec0_node_ptr_->vec_holder().size(),
12789 4240 : vec1_node_ptr_->vec_holder().size());
12790 : }
12791 :
12792 2942 : std::size_t base_size() const exprtk_override
12793 : {
12794 2942 : return std::min(
12795 2942 : vec0_node_ptr_->vec_holder().base_size(),
12796 5884 : vec1_node_ptr_->vec_holder().base_size());
12797 : }
12798 :
12799 2942 : vds_t& vds() exprtk_override
12800 : {
12801 2942 : return vds_;
12802 : }
12803 :
12804 0 : const vds_t& vds() const exprtk_override
12805 : {
12806 0 : return vds_;
12807 : }
12808 :
12809 : private:
12810 :
12811 : vector_node<T>* vec0_node_ptr_;
12812 : vector_node<T>* vec1_node_ptr_;
12813 : bool initialised_;
12814 : bool src_is_ivec_;
12815 : vds_t vds_;
12816 : };
12817 :
12818 : template <typename T, typename Operation>
12819 : class assignment_op_node exprtk_final : public binary_node<T>
12820 : {
12821 : public:
12822 :
12823 : typedef expression_node<T>* expression_ptr;
12824 : using binary_node<T>::branch;
12825 :
12826 4875 : assignment_op_node(const operator_type& opr,
12827 : expression_ptr branch0,
12828 : expression_ptr branch1)
12829 : : binary_node<T>(opr, branch0, branch1)
12830 4875 : , var_node_ptr_(0)
12831 : {
12832 4875 : if (is_variable_node(branch(0)))
12833 : {
12834 4875 : var_node_ptr_ = static_cast<variable_node<T>*>(branch(0));
12835 : }
12836 :
12837 4875 : assert(valid());
12838 4875 : }
12839 :
12840 158668567 : inline T value() const exprtk_override
12841 : {
12842 158668567 : T& v = var_node_ptr_->ref();
12843 158668567 : v = Operation::process(v,branch(1)->value());
12844 :
12845 158668567 : return v;
12846 : }
12847 :
12848 11200 : inline bool valid() const exprtk_override
12849 : {
12850 11200 : return var_node_ptr_ && binary_node<T>::valid();
12851 : }
12852 :
12853 : private:
12854 :
12855 : variable_node<T>* var_node_ptr_;
12856 : };
12857 :
12858 : template <typename T, typename Operation>
12859 : class assignment_vec_elem_op_node exprtk_final : public binary_node<T>
12860 : {
12861 : public:
12862 :
12863 : typedef expression_node<T>* expression_ptr;
12864 : using binary_node<T>::branch;
12865 :
12866 500 : assignment_vec_elem_op_node(const operator_type& opr,
12867 : expression_ptr branch0,
12868 : expression_ptr branch1)
12869 : : binary_node<T>(opr, branch0, branch1)
12870 500 : , vec_node_ptr_(0)
12871 : {
12872 500 : if (is_vector_elem_node(branch(0)))
12873 : {
12874 500 : vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0));
12875 : }
12876 :
12877 500 : assert(valid());
12878 500 : }
12879 :
12880 1100 : inline T value() const exprtk_override
12881 : {
12882 1100 : T& v = vec_node_ptr_->ref();
12883 1100 : v = Operation::process(v,branch(1)->value());
12884 :
12885 1100 : return v;
12886 : }
12887 :
12888 1500 : inline bool valid() const exprtk_override
12889 : {
12890 1500 : return vec_node_ptr_ && binary_node<T>::valid();
12891 : }
12892 :
12893 : private:
12894 :
12895 : vector_elem_node<T>* vec_node_ptr_;
12896 : };
12897 :
12898 : template <typename T, typename Operation>
12899 : class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T>
12900 : {
12901 : public:
12902 :
12903 : typedef expression_node<T>* expression_ptr;
12904 : using binary_node<T>::branch;
12905 :
12906 12 : assignment_vec_elem_op_rtc_node(const operator_type& opr,
12907 : expression_ptr branch0,
12908 : expression_ptr branch1)
12909 : : binary_node<T>(opr, branch0, branch1)
12910 12 : , vec_node_ptr_(0)
12911 : {
12912 12 : if (is_vector_elem_rtc_node(branch(0)))
12913 : {
12914 12 : vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0));
12915 : }
12916 :
12917 12 : assert(valid());
12918 12 : }
12919 :
12920 18 : inline T value() const exprtk_override
12921 : {
12922 18 : T& v = vec_node_ptr_->ref();
12923 18 : v = Operation::process(v,branch(1)->value());
12924 :
12925 18 : return v;
12926 : }
12927 :
12928 46 : inline bool valid() const exprtk_override
12929 : {
12930 46 : return vec_node_ptr_ && binary_node<T>::valid();
12931 : }
12932 :
12933 : private:
12934 :
12935 : vector_elem_rtc_node<T>* vec_node_ptr_;
12936 : };
12937 :
12938 : template <typename T, typename Operation>
12939 : class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T>
12940 : {
12941 : public:
12942 :
12943 : typedef expression_node<T>* expression_ptr;
12944 : using binary_node<T>::branch;
12945 :
12946 0 : assignment_vec_celem_op_rtc_node(const operator_type& opr,
12947 : expression_ptr branch0,
12948 : expression_ptr branch1)
12949 : : binary_node<T>(opr, branch0, branch1)
12950 0 : , vec_node_ptr_(0)
12951 : {
12952 0 : if (is_vector_celem_rtc_node(branch(0)))
12953 : {
12954 0 : vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0));
12955 : }
12956 :
12957 0 : assert(valid());
12958 0 : }
12959 :
12960 0 : inline T value() const exprtk_override
12961 : {
12962 0 : T& v = vec_node_ptr_->ref();
12963 0 : v = Operation::process(v,branch(1)->value());
12964 :
12965 0 : return v;
12966 : }
12967 :
12968 0 : inline bool valid() const exprtk_override
12969 : {
12970 0 : return vec_node_ptr_ && binary_node<T>::valid();
12971 : }
12972 :
12973 : private:
12974 :
12975 : vector_celem_rtc_node<T>* vec_node_ptr_;
12976 : };
12977 :
12978 : template <typename T, typename Operation>
12979 : class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T>
12980 : {
12981 : public:
12982 :
12983 : typedef expression_node<T>* expression_ptr;
12984 : using binary_node<T>::branch;
12985 :
12986 300 : assignment_rebasevec_elem_op_node(const operator_type& opr,
12987 : expression_ptr branch0,
12988 : expression_ptr branch1)
12989 : : binary_node<T>(opr, branch0, branch1)
12990 300 : , rbvec_node_ptr_(0)
12991 : {
12992 300 : if (is_rebasevector_elem_node(branch(0)))
12993 : {
12994 300 : rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0));
12995 : }
12996 :
12997 300 : assert(valid());
12998 300 : }
12999 :
13000 300 : inline T value() const exprtk_override
13001 : {
13002 300 : T& v = rbvec_node_ptr_->ref();
13003 300 : v = Operation::process(v,branch(1)->value());
13004 :
13005 300 : return v;
13006 : }
13007 :
13008 900 : inline bool valid() const exprtk_override
13009 : {
13010 900 : return rbvec_node_ptr_ && binary_node<T>::valid();
13011 : }
13012 :
13013 : private:
13014 :
13015 : rebasevector_elem_node<T>* rbvec_node_ptr_;
13016 : };
13017 :
13018 : template <typename T, typename Operation>
13019 : class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T>
13020 : {
13021 : public:
13022 :
13023 : typedef expression_node<T>* expression_ptr;
13024 : using binary_node<T>::branch;
13025 :
13026 300 : assignment_rebasevec_celem_op_node(const operator_type& opr,
13027 : expression_ptr branch0,
13028 : expression_ptr branch1)
13029 : : binary_node<T>(opr, branch0, branch1)
13030 300 : , rbvec_node_ptr_(0)
13031 : {
13032 300 : if (is_rebasevector_celem_node(branch(0)))
13033 : {
13034 300 : rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0));
13035 : }
13036 :
13037 300 : assert(valid());
13038 300 : }
13039 :
13040 300 : inline T value() const exprtk_override
13041 : {
13042 300 : T& v = rbvec_node_ptr_->ref();
13043 300 : v = Operation::process(v,branch(1)->value());
13044 :
13045 300 : return v;
13046 : }
13047 :
13048 900 : inline bool valid() const exprtk_override
13049 : {
13050 900 : return rbvec_node_ptr_ && binary_node<T>::valid();
13051 : }
13052 :
13053 : private:
13054 :
13055 : rebasevector_celem_node<T>* rbvec_node_ptr_;
13056 : };
13057 :
13058 : template <typename T, typename Operation>
13059 : class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T>
13060 : {
13061 : public:
13062 :
13063 : typedef expression_node<T>* expression_ptr;
13064 : using binary_node<T>::branch;
13065 :
13066 0 : assignment_rebasevec_elem_op_rtc_node(const operator_type& opr,
13067 : expression_ptr branch0,
13068 : expression_ptr branch1)
13069 : : binary_node<T>(opr, branch0, branch1)
13070 0 : , rbvec_node_ptr_(0)
13071 : {
13072 0 : if (is_rebasevector_elem_rtc_node(branch(0)))
13073 : {
13074 0 : rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0));
13075 : }
13076 :
13077 0 : assert(valid());
13078 0 : }
13079 :
13080 0 : inline T value() const exprtk_override
13081 : {
13082 0 : T& v = rbvec_node_ptr_->ref();
13083 0 : v = Operation::process(v,branch(1)->value());
13084 :
13085 0 : return v;
13086 : }
13087 :
13088 0 : inline bool valid() const exprtk_override
13089 : {
13090 0 : return rbvec_node_ptr_ && binary_node<T>::valid();
13091 : }
13092 :
13093 : private:
13094 :
13095 : rebasevector_elem_rtc_node<T>* rbvec_node_ptr_;
13096 : };
13097 :
13098 : template <typename T, typename Operation>
13099 : class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T>
13100 : {
13101 : public:
13102 :
13103 : typedef expression_node<T>* expression_ptr;
13104 : using binary_node<T>::branch;
13105 :
13106 0 : assignment_rebasevec_celem_op_rtc_node(const operator_type& opr,
13107 : expression_ptr branch0,
13108 : expression_ptr branch1)
13109 : : binary_node<T>(opr, branch0, branch1)
13110 0 : , rbvec_node_ptr_(0)
13111 : {
13112 0 : if (is_rebasevector_celem_rtc_node(branch(0)))
13113 : {
13114 0 : rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0));
13115 : }
13116 :
13117 0 : assert(valid());
13118 0 : }
13119 :
13120 0 : inline T value() const exprtk_override
13121 : {
13122 0 : T& v = rbvec_node_ptr_->ref();
13123 0 : v = Operation::process(v,branch(1)->value());
13124 :
13125 0 : return v;
13126 : }
13127 :
13128 0 : inline bool valid() const exprtk_override
13129 : {
13130 0 : return rbvec_node_ptr_ && binary_node<T>::valid();
13131 : }
13132 :
13133 : private:
13134 :
13135 : rebasevector_celem_rtc_node<T>* rbvec_node_ptr_;
13136 : };
13137 :
13138 : template <typename T, typename Operation>
13139 : class assignment_vec_op_node exprtk_final
13140 : : public binary_node <T>
13141 : , public vector_interface<T>
13142 : {
13143 : public:
13144 :
13145 : typedef expression_node<T>* expression_ptr;
13146 : typedef vector_node<T>* vector_node_ptr;
13147 : typedef vec_data_store<T> vds_t;
13148 :
13149 : using binary_node<T>::branch;
13150 :
13151 2492 : assignment_vec_op_node(const operator_type& opr,
13152 : expression_ptr branch0,
13153 : expression_ptr branch1)
13154 : : binary_node<T>(opr, branch0, branch1)
13155 2492 : , vec_node_ptr_(0)
13156 : {
13157 2492 : if (is_vector_node(branch(0)))
13158 : {
13159 2492 : vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
13160 2492 : vds() = vec_node_ptr_->vds();
13161 : }
13162 :
13163 2492 : assert(valid());
13164 2492 : }
13165 :
13166 2519 : inline T value() const exprtk_override
13167 : {
13168 2519 : const T v = branch(1)->value();
13169 :
13170 2519 : T* vec = vds().data();
13171 :
13172 2519 : loop_unroll::details lud(size());
13173 2519 : const T* upper_bound = vec + lud.upper_bound;
13174 :
13175 2519 : while (vec < upper_bound)
13176 : {
13177 : #define exprtk_loop(N) \
13178 : Operation::assign(vec[N],v); \
13179 :
13180 0 : exprtk_loop( 0) exprtk_loop( 1)
13181 0 : exprtk_loop( 2) exprtk_loop( 3)
13182 : #ifndef exprtk_disable_superscalar_unroll
13183 0 : exprtk_loop( 4) exprtk_loop( 5)
13184 0 : exprtk_loop( 6) exprtk_loop( 7)
13185 0 : exprtk_loop( 8) exprtk_loop( 9)
13186 0 : exprtk_loop(10) exprtk_loop(11)
13187 0 : exprtk_loop(12) exprtk_loop(13)
13188 0 : exprtk_loop(14) exprtk_loop(15)
13189 : #endif
13190 :
13191 0 : vec += lud.batch_size;
13192 : }
13193 :
13194 2519 : switch (lud.remainder)
13195 : {
13196 : #define case_stmt(N,fall_through) \
13197 : case N : Operation::assign(*vec++,v); \
13198 : fall_through \
13199 :
13200 : #ifndef exprtk_disable_superscalar_unroll
13201 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
13202 0 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
13203 0 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
13204 18 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
13205 28 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
13206 338 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
13207 : #endif
13208 2194 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
13209 2519 : case_stmt( 1, (void)0;)
13210 : }
13211 :
13212 : #undef exprtk_loop
13213 : #undef case_stmt
13214 :
13215 5038 : return vec_node_ptr_->value();
13216 : }
13217 :
13218 0 : vector_node_ptr vec() const exprtk_override
13219 : {
13220 0 : return vec_node_ptr_;
13221 : }
13222 :
13223 2182 : vector_node_ptr vec() exprtk_override
13224 : {
13225 2182 : return vec_node_ptr_;
13226 : }
13227 :
13228 41763 : inline typename expression_node<T>::node_type type() const exprtk_override
13229 : {
13230 41763 : return expression_node<T>::e_vecopvalass;
13231 : }
13232 :
13233 11913 : inline bool valid() const exprtk_override
13234 : {
13235 : return
13236 23826 : vec_node_ptr_ &&
13237 23826 : (size() <= base_size()) &&
13238 23826 : binary_node<T>::valid() ;
13239 : }
13240 :
13241 14492 : std::size_t size() const exprtk_override
13242 : {
13243 14492 : return vec_node_ptr_->vec_holder().size();
13244 : }
13245 :
13246 11913 : std::size_t base_size() const exprtk_override
13247 : {
13248 11913 : return vec_node_ptr_->vec_holder().base_size();
13249 : }
13250 :
13251 3334 : vds_t& vds() exprtk_override
13252 : {
13253 3334 : return vds_;
13254 : }
13255 :
13256 2519 : const vds_t& vds() const exprtk_override
13257 : {
13258 2519 : return vds_;
13259 : }
13260 :
13261 160 : bool side_effect() const exprtk_override
13262 : {
13263 160 : return true;
13264 : }
13265 :
13266 : private:
13267 :
13268 : vector_node<T>* vec_node_ptr_;
13269 : vds_t vds_;
13270 : };
13271 :
13272 : template <typename T, typename Operation>
13273 : class assignment_vecvec_op_node exprtk_final
13274 : : public binary_node <T>
13275 : , public vector_interface<T>
13276 : {
13277 : public:
13278 :
13279 : typedef expression_node<T>* expression_ptr;
13280 : typedef vector_node<T>* vector_node_ptr;
13281 : typedef vec_data_store<T> vds_t;
13282 :
13283 : using binary_node<T>::branch;
13284 :
13285 766 : assignment_vecvec_op_node(const operator_type& opr,
13286 : expression_ptr branch0,
13287 : expression_ptr branch1)
13288 : : binary_node<T>(opr, branch0, branch1)
13289 766 : , vec0_node_ptr_(0)
13290 766 : , vec1_node_ptr_(0)
13291 766 : , initialised_(false)
13292 : {
13293 766 : if (is_vector_node(branch(0)))
13294 : {
13295 766 : vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0));
13296 766 : vds() = vec0_node_ptr_->vds();
13297 : }
13298 :
13299 766 : if (is_vector_node(branch(1)))
13300 : {
13301 320 : vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1));
13302 320 : vec1_node_ptr_->vds() = vds();
13303 : }
13304 446 : else if (is_ivector_node(branch(1)))
13305 : {
13306 446 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
13307 :
13308 446 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
13309 : {
13310 446 : vec1_node_ptr_ = vi->vec();
13311 446 : vec1_node_ptr_->vds() = vi->vds();
13312 : }
13313 : else
13314 0 : vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
13315 : }
13316 :
13317 766 : initialised_ =
13318 1532 : vec0_node_ptr_ &&
13319 766 : vec1_node_ptr_ &&
13320 2298 : (size() <= base_size()) &&
13321 766 : binary_node<T>::valid();
13322 :
13323 766 : assert(valid());
13324 766 : }
13325 :
13326 766 : inline T value() const exprtk_override
13327 : {
13328 766 : branch(0)->value();
13329 766 : branch(1)->value();
13330 :
13331 766 : T* vec0 = vec0_node_ptr_->vds().data();
13332 766 : const T* vec1 = vec1_node_ptr_->vds().data();
13333 :
13334 766 : loop_unroll::details lud(size());
13335 766 : const T* upper_bound = vec0 + lud.upper_bound;
13336 :
13337 766 : while (vec0 < upper_bound)
13338 : {
13339 : #define exprtk_loop(N) \
13340 : vec0[N] = Operation::process(vec0[N], vec1[N]); \
13341 :
13342 0 : exprtk_loop( 0) exprtk_loop( 1)
13343 0 : exprtk_loop( 2) exprtk_loop( 3)
13344 : #ifndef exprtk_disable_superscalar_unroll
13345 0 : exprtk_loop( 4) exprtk_loop( 5)
13346 0 : exprtk_loop( 6) exprtk_loop( 7)
13347 0 : exprtk_loop( 8) exprtk_loop( 9)
13348 0 : exprtk_loop(10) exprtk_loop(11)
13349 0 : exprtk_loop(12) exprtk_loop(13)
13350 0 : exprtk_loop(14) exprtk_loop(15)
13351 : #endif
13352 :
13353 0 : vec0 += lud.batch_size;
13354 0 : vec1 += lud.batch_size;
13355 : }
13356 :
13357 766 : int i = 0;
13358 :
13359 766 : switch (lud.remainder)
13360 : {
13361 : #define case_stmt(N,fall_through) \
13362 : case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
13363 : fall_through \
13364 :
13365 : #ifndef exprtk_disable_superscalar_unroll
13366 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
13367 0 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
13368 0 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
13369 18 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
13370 18 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
13371 108 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
13372 : #endif
13373 646 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
13374 766 : case_stmt( 1, (void)0;)
13375 : }
13376 :
13377 : #undef exprtk_loop
13378 : #undef case_stmt
13379 :
13380 1532 : return vec0_node_ptr_->value();
13381 : }
13382 :
13383 0 : vector_node_ptr vec() const exprtk_override
13384 : {
13385 0 : return vec0_node_ptr_;
13386 : }
13387 :
13388 0 : vector_node_ptr vec() exprtk_override
13389 : {
13390 0 : return vec0_node_ptr_;
13391 : }
13392 :
13393 8426 : inline typename expression_node<T>::node_type type() const exprtk_override
13394 : {
13395 8426 : return expression_node<T>::e_vecopvecass;
13396 : }
13397 :
13398 2298 : inline bool valid() const exprtk_override
13399 : {
13400 2298 : return initialised_;
13401 : }
13402 :
13403 1532 : std::size_t size() const exprtk_override
13404 : {
13405 1532 : return std::min(
13406 1532 : vec0_node_ptr_->vec_holder().size(),
13407 3064 : vec1_node_ptr_->vec_holder().size());
13408 : }
13409 :
13410 766 : std::size_t base_size() const exprtk_override
13411 : {
13412 766 : return std::min(
13413 766 : vec0_node_ptr_->vec_holder().base_size(),
13414 1532 : vec1_node_ptr_->vec_holder().base_size());
13415 : }
13416 :
13417 1086 : vds_t& vds() exprtk_override
13418 : {
13419 1086 : return vds_;
13420 : }
13421 :
13422 0 : const vds_t& vds() const exprtk_override
13423 : {
13424 0 : return vds_;
13425 : }
13426 :
13427 0 : bool side_effect() const exprtk_override
13428 : {
13429 0 : return true;
13430 : }
13431 :
13432 : private:
13433 :
13434 : vector_node<T>* vec0_node_ptr_;
13435 : vector_node<T>* vec1_node_ptr_;
13436 : bool initialised_;
13437 : vds_t vds_;
13438 : };
13439 :
13440 : template <typename T>
13441 : struct memory_context_t
13442 : {
13443 : typedef vector_node<T>* vector_node_ptr;
13444 : typedef vector_holder<T> vector_holder_t;
13445 : typedef vector_holder_t* vector_holder_ptr;
13446 :
13447 44678 : memory_context_t()
13448 44678 : : temp_(0)
13449 44678 : , temp_vec_node_(0)
13450 44678 : {}
13451 :
13452 22339 : void clear()
13453 : {
13454 22339 : delete temp_vec_node_;
13455 22339 : delete temp_;
13456 22339 : }
13457 :
13458 : vector_holder_ptr temp_;
13459 : vector_node_ptr temp_vec_node_;
13460 : };
13461 :
13462 : template <typename T>
13463 10891 : inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder,
13464 : vec_data_store<T>& vds)
13465 : {
13466 10891 : memory_context_t<T> result_ctxt;
13467 21782 : result_ctxt.temp_ = (vec_holder.rebaseable()) ?
13468 359 : new vector_holder<T>(vec_holder,vds) :
13469 10532 : new vector_holder<T>(vds) ;
13470 10891 : result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_);
13471 10891 : return result_ctxt;
13472 : }
13473 :
13474 : template <typename T>
13475 11448 : inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0,
13476 : vector_holder<T>& vec_holder1,
13477 : vec_data_store<T>& vds)
13478 : {
13479 11448 : memory_context_t<T> result_ctxt;
13480 :
13481 11448 : if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable())
13482 11329 : result_ctxt.temp_ = new vector_holder<T>(vds);
13483 119 : else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable())
13484 17 : result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds);
13485 102 : else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable())
13486 27 : result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds);
13487 : else
13488 : {
13489 150 : result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ?
13490 75 : new vector_holder<T>(vec_holder0, vds) :
13491 0 : new vector_holder<T>(vec_holder1, vds) ;
13492 : }
13493 :
13494 11448 : result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_);
13495 11448 : return result_ctxt;
13496 : }
13497 :
13498 : template <typename T, typename Operation>
13499 : class vec_binop_vecvec_node exprtk_final
13500 : : public binary_node <T>
13501 : , public vector_interface<T>
13502 : {
13503 : public:
13504 :
13505 : typedef expression_node<T>* expression_ptr;
13506 : typedef vector_node<T>* vector_node_ptr;
13507 : typedef vector_holder<T> vector_holder_t;
13508 : typedef vector_holder_t* vector_holder_ptr;
13509 : typedef vec_data_store<T> vds_t;
13510 : typedef memory_context_t<T> memory_context;
13511 :
13512 : using binary_node<T>::branch;
13513 :
13514 10555 : vec_binop_vecvec_node(const operator_type& opr,
13515 : expression_ptr branch0,
13516 : expression_ptr branch1)
13517 : : binary_node<T>(opr, branch0, branch1)
13518 10555 : , vec0_node_ptr_(0)
13519 10555 : , vec1_node_ptr_(0)
13520 10555 : , initialised_(false)
13521 : {
13522 10555 : bool v0_is_ivec = false;
13523 10555 : bool v1_is_ivec = false;
13524 :
13525 10555 : if (is_vector_node(branch(0)))
13526 : {
13527 7351 : vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
13528 : }
13529 3204 : else if (is_ivector_node(branch(0)))
13530 : {
13531 3204 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
13532 :
13533 3204 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
13534 : {
13535 3204 : vec0_node_ptr_ = vi->vec();
13536 3204 : v0_is_ivec = true;
13537 : }
13538 : }
13539 :
13540 10555 : if (is_vector_node(branch(1)))
13541 : {
13542 7418 : vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
13543 : }
13544 3137 : else if (is_ivector_node(branch(1)))
13545 : {
13546 3137 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
13547 :
13548 3137 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
13549 : {
13550 3137 : vec1_node_ptr_ = vi->vec();
13551 3137 : v1_is_ivec = true;
13552 : }
13553 : }
13554 :
13555 10555 : if (vec0_node_ptr_ && vec1_node_ptr_)
13556 : {
13557 10555 : vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
13558 10555 : vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
13559 :
13560 10555 : if (v0_is_ivec && (vec0.base_size() <= vec1.base_size()))
13561 : {
13562 2880 : vds_ = vds_t(vec0_node_ptr_->vds());
13563 : }
13564 7675 : else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size()))
13565 : {
13566 968 : vds_ = vds_t(vec1_node_ptr_->vds());
13567 : }
13568 : else
13569 : {
13570 6707 : vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size()));
13571 : }
13572 :
13573 10555 : memory_context_ = make_memory_context(vec0, vec1, vds());
13574 :
13575 10555 : initialised_ =
13576 21110 : (size() <= base_size()) &&
13577 10555 : binary_node<T>::valid();
13578 : }
13579 :
13580 10555 : assert(valid());
13581 10555 : }
13582 :
13583 21110 : ~vec_binop_vecvec_node()
13584 : {
13585 10555 : memory_context_.clear();
13586 21110 : }
13587 :
13588 10484 : inline T value() const exprtk_override
13589 : {
13590 10484 : branch(0)->value();
13591 10484 : branch(1)->value();
13592 :
13593 10484 : const T* vec0 = vec0_node_ptr_->vds().data();
13594 10484 : const T* vec1 = vec1_node_ptr_->vds().data();
13595 10484 : T* vec2 = vds().data();
13596 :
13597 10484 : loop_unroll::details lud(size());
13598 10484 : const T* upper_bound = vec2 + lud.upper_bound;
13599 :
13600 25947984 : while (vec2 < upper_bound)
13601 : {
13602 : #define exprtk_loop(N) \
13603 : vec2[N] = Operation::process(vec0[N], vec1[N]); \
13604 :
13605 25937500 : exprtk_loop( 0) exprtk_loop( 1)
13606 25937500 : exprtk_loop( 2) exprtk_loop( 3)
13607 : #ifndef exprtk_disable_superscalar_unroll
13608 25937500 : exprtk_loop( 4) exprtk_loop( 5)
13609 25937500 : exprtk_loop( 6) exprtk_loop( 7)
13610 25937500 : exprtk_loop( 8) exprtk_loop( 9)
13611 25937500 : exprtk_loop(10) exprtk_loop(11)
13612 25937500 : exprtk_loop(12) exprtk_loop(13)
13613 25937500 : exprtk_loop(14) exprtk_loop(15)
13614 : #endif
13615 :
13616 25937500 : vec0 += lud.batch_size;
13617 25937500 : vec1 += lud.batch_size;
13618 25937500 : vec2 += lud.batch_size;
13619 : }
13620 :
13621 10484 : int i = 0;
13622 :
13623 10484 : switch (lud.remainder)
13624 : {
13625 : #define case_stmt(N) \
13626 : case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
13627 : exprtk_fallthrough \
13628 :
13629 : #ifndef exprtk_disable_superscalar_unroll
13630 0 : case_stmt(15) case_stmt(14)
13631 0 : case_stmt(13) case_stmt(12)
13632 0 : case_stmt(11) case_stmt(10)
13633 695 : case_stmt( 9) case_stmt( 8)
13634 714 : case_stmt( 7) case_stmt( 6)
13635 3560 : case_stmt( 5) case_stmt( 4)
13636 : #endif
13637 9199 : case_stmt( 3) case_stmt( 2)
13638 9934 : case_stmt( 1)
13639 10484 : default: break;
13640 : }
13641 :
13642 : #undef exprtk_loop
13643 : #undef case_stmt
13644 :
13645 20968 : return (vds().data())[0];
13646 : }
13647 :
13648 0 : vector_node_ptr vec() const exprtk_override
13649 : {
13650 0 : return memory_context_.temp_vec_node_;
13651 : }
13652 :
13653 5901 : vector_node_ptr vec() exprtk_override
13654 : {
13655 5901 : return memory_context_.temp_vec_node_;
13656 : }
13657 :
13658 89888 : inline typename expression_node<T>::node_type type() const exprtk_override
13659 : {
13660 89888 : return expression_node<T>::e_vecvecarith;
13661 : }
13662 :
13663 37491 : inline bool valid() const exprtk_override
13664 : {
13665 37491 : return initialised_;
13666 : }
13667 :
13668 22937 : std::size_t size() const exprtk_override
13669 : {
13670 22937 : return std::min(
13671 22937 : vec0_node_ptr_->vec_holder().size(),
13672 45874 : vec1_node_ptr_->vec_holder().size());
13673 : }
13674 :
13675 10555 : std::size_t base_size() const exprtk_override
13676 : {
13677 10555 : return std::min(
13678 10555 : vec0_node_ptr_->vec_holder().base_size(),
13679 21110 : vec1_node_ptr_->vec_holder().base_size());
13680 : }
13681 :
13682 12566 : vds_t& vds() exprtk_override
13683 : {
13684 12566 : return vds_;
13685 : }
13686 :
13687 20968 : const vds_t& vds() const exprtk_override
13688 : {
13689 20968 : return vds_;
13690 : }
13691 :
13692 : private:
13693 :
13694 : vector_node_ptr vec0_node_ptr_;
13695 : vector_node_ptr vec1_node_ptr_;
13696 : bool initialised_;
13697 : vds_t vds_;
13698 : memory_context memory_context_;
13699 : };
13700 :
13701 : template <typename T, typename Operation>
13702 : class vec_binop_vecval_node exprtk_final
13703 : : public binary_node <T>
13704 : , public vector_interface<T>
13705 : {
13706 : public:
13707 :
13708 : typedef expression_node<T>* expression_ptr;
13709 : typedef vector_node<T>* vector_node_ptr;
13710 : typedef vector_holder<T> vector_holder_t;
13711 : typedef vector_holder_t* vector_holder_ptr;
13712 : typedef vec_data_store<T> vds_t;
13713 : typedef memory_context_t<T> memory_context;
13714 :
13715 : using binary_node<T>::branch;
13716 :
13717 3999 : vec_binop_vecval_node(const operator_type& opr,
13718 : expression_ptr branch0,
13719 : expression_ptr branch1)
13720 : : binary_node<T>(opr, branch0, branch1)
13721 3999 : , vec0_node_ptr_(0)
13722 : {
13723 3999 : bool v0_is_ivec = false;
13724 :
13725 3999 : if (is_vector_node(branch(0)))
13726 : {
13727 2024 : vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
13728 : }
13729 1975 : else if (is_ivector_node(branch(0)))
13730 : {
13731 1975 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
13732 :
13733 1975 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
13734 : {
13735 1975 : vec0_node_ptr_ = vi->vec();
13736 1975 : v0_is_ivec = true;
13737 : }
13738 : }
13739 :
13740 3999 : if (vec0_node_ptr_)
13741 : {
13742 3999 : if (v0_is_ivec)
13743 1975 : vds() = vec0_node_ptr_->vds();
13744 : else
13745 2024 : vds() = vds_t(vec0_node_ptr_->base_size());
13746 :
13747 3999 : memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
13748 : }
13749 :
13750 3999 : assert(valid());
13751 3999 : }
13752 :
13753 7998 : ~vec_binop_vecval_node()
13754 : {
13755 3999 : memory_context_.clear();
13756 7998 : }
13757 :
13758 5075 : inline T value() const exprtk_override
13759 : {
13760 5075 : branch(0)->value();
13761 5075 : const T v = branch(1)->value();
13762 :
13763 5075 : const T* vec0 = vec0_node_ptr_->vds().data();
13764 5075 : T* vec1 = vds().data();
13765 :
13766 5075 : loop_unroll::details lud(size());
13767 5075 : const T* upper_bound = vec0 + lud.upper_bound;
13768 :
13769 26317575 : while (vec0 < upper_bound)
13770 : {
13771 : #define exprtk_loop(N) \
13772 : vec1[N] = Operation::process(vec0[N], v); \
13773 :
13774 26312500 : exprtk_loop( 0) exprtk_loop( 1)
13775 26312500 : exprtk_loop( 2) exprtk_loop( 3)
13776 : #ifndef exprtk_disable_superscalar_unroll
13777 26312500 : exprtk_loop( 4) exprtk_loop( 5)
13778 26312500 : exprtk_loop( 6) exprtk_loop( 7)
13779 26312500 : exprtk_loop( 8) exprtk_loop( 9)
13780 26312500 : exprtk_loop(10) exprtk_loop(11)
13781 26312500 : exprtk_loop(12) exprtk_loop(13)
13782 26312500 : exprtk_loop(14) exprtk_loop(15)
13783 : #endif
13784 :
13785 26312500 : vec0 += lud.batch_size;
13786 26312500 : vec1 += lud.batch_size;
13787 : }
13788 :
13789 5075 : int i = 0;
13790 :
13791 5075 : switch (lud.remainder)
13792 : {
13793 : #define case_stmt(N,fall_through) \
13794 : case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
13795 : fall_through \
13796 :
13797 : #ifndef exprtk_disable_superscalar_unroll
13798 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
13799 0 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
13800 0 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
13801 314 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
13802 414 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
13803 3430 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
13804 : #endif
13805 4337 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
13806 4465 : case_stmt( 1, (void)0;)
13807 : }
13808 :
13809 : #undef exprtk_loop
13810 : #undef case_stmt
13811 :
13812 10150 : return (vds().data())[0];
13813 : }
13814 :
13815 0 : vector_node_ptr vec() const exprtk_override
13816 : {
13817 0 : return memory_context_.temp_vec_node_;
13818 : }
13819 :
13820 3794 : vector_node_ptr vec() exprtk_override
13821 : {
13822 3794 : return memory_context_.temp_vec_node_;
13823 : }
13824 :
13825 43790 : inline typename expression_node<T>::node_type type() const exprtk_override
13826 : {
13827 43790 : return expression_node<T>::e_vecvalarith;
13828 : }
13829 :
13830 24745 : inline bool valid() const exprtk_override
13831 : {
13832 : return
13833 49490 : vec0_node_ptr_ &&
13834 49490 : (size() <= base_size()) &&
13835 49490 : binary_node<T>::valid();
13836 : }
13837 :
13838 30279 : std::size_t size() const exprtk_override
13839 : {
13840 30279 : return vec0_node_ptr_->size();
13841 : }
13842 :
13843 24745 : std::size_t base_size() const exprtk_override
13844 : {
13845 24745 : return vec0_node_ptr_->vec_holder().base_size();
13846 : }
13847 :
13848 8509 : vds_t& vds() exprtk_override
13849 : {
13850 8509 : return vds_;
13851 : }
13852 :
13853 10150 : const vds_t& vds() const exprtk_override
13854 : {
13855 10150 : return vds_;
13856 : }
13857 :
13858 : private:
13859 :
13860 : vector_node_ptr vec0_node_ptr_;
13861 : vds_t vds_;
13862 : memory_context memory_context_;
13863 : };
13864 :
13865 : template <typename T, typename Operation>
13866 : class vec_binop_valvec_node exprtk_final
13867 : : public binary_node <T>
13868 : , public vector_interface<T>
13869 : {
13870 : public:
13871 :
13872 : typedef expression_node<T>* expression_ptr;
13873 : typedef vector_node<T>* vector_node_ptr;
13874 : typedef vector_holder<T> vector_holder_t;
13875 : typedef vector_holder_t* vector_holder_ptr;
13876 : typedef vec_data_store<T> vds_t;
13877 : typedef memory_context_t<T> memory_context;
13878 :
13879 : using binary_node<T>::branch;
13880 :
13881 4202 : vec_binop_valvec_node(const operator_type& opr,
13882 : expression_ptr branch0,
13883 : expression_ptr branch1)
13884 : : binary_node<T>(opr, branch0, branch1)
13885 4202 : , vec1_node_ptr_(0)
13886 : {
13887 4202 : bool v1_is_ivec = false;
13888 :
13889 4202 : if (is_vector_node(branch(1)))
13890 : {
13891 2512 : vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1));
13892 : }
13893 1690 : else if (is_ivector_node(branch(1)))
13894 : {
13895 1690 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
13896 :
13897 1690 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1))))
13898 : {
13899 1690 : vec1_node_ptr_ = vi->vec();
13900 1690 : v1_is_ivec = true;
13901 : }
13902 : }
13903 :
13904 4202 : if (vec1_node_ptr_)
13905 : {
13906 4202 : if (v1_is_ivec)
13907 1690 : vds() = vec1_node_ptr_->vds();
13908 : else
13909 2512 : vds() = vds_t(vec1_node_ptr_->base_size());
13910 :
13911 4202 : memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds());
13912 : }
13913 :
13914 4202 : assert(valid());
13915 4202 : }
13916 :
13917 8404 : ~vec_binop_valvec_node()
13918 : {
13919 4202 : memory_context_.clear();
13920 8404 : }
13921 :
13922 5191 : inline T value() const exprtk_override
13923 : {
13924 5191 : const T v = branch(0)->value();
13925 5191 : branch(1)->value();
13926 :
13927 5191 : T* vec0 = vds().data();
13928 5191 : const T* vec1 = vec1_node_ptr_->vds().data();
13929 :
13930 5191 : loop_unroll::details lud(size());
13931 5191 : const T* upper_bound = vec0 + lud.upper_bound;
13932 :
13933 51317691 : while (vec0 < upper_bound)
13934 : {
13935 : #define exprtk_loop(N) \
13936 : vec0[N] = Operation::process(v, vec1[N]); \
13937 :
13938 51312500 : exprtk_loop( 0) exprtk_loop( 1)
13939 51312500 : exprtk_loop( 2) exprtk_loop( 3)
13940 : #ifndef exprtk_disable_superscalar_unroll
13941 51312500 : exprtk_loop( 4) exprtk_loop( 5)
13942 51312500 : exprtk_loop( 6) exprtk_loop( 7)
13943 51312500 : exprtk_loop( 8) exprtk_loop( 9)
13944 51312500 : exprtk_loop(10) exprtk_loop(11)
13945 51312500 : exprtk_loop(12) exprtk_loop(13)
13946 51312500 : exprtk_loop(14) exprtk_loop(15)
13947 : #endif
13948 :
13949 51312500 : vec0 += lud.batch_size;
13950 51312500 : vec1 += lud.batch_size;
13951 : }
13952 :
13953 5191 : int i = 0;
13954 :
13955 5191 : switch (lud.remainder)
13956 : {
13957 : #define case_stmt(N,fall_through) \
13958 : case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
13959 : fall_through \
13960 :
13961 : #ifndef exprtk_disable_superscalar_unroll
13962 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
13963 0 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
13964 0 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
13965 167 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
13966 195 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
13967 3074 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
13968 : #endif
13969 4047 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
13970 4181 : case_stmt( 1, (void)0;)
13971 : }
13972 :
13973 : #undef exprtk_loop
13974 : #undef case_stmt
13975 :
13976 10382 : return (vds().data())[0];
13977 : }
13978 :
13979 0 : vector_node_ptr vec() const exprtk_override
13980 : {
13981 0 : return memory_context_.temp_vec_node_;
13982 : }
13983 :
13984 4094 : vector_node_ptr vec() exprtk_override
13985 : {
13986 4094 : return memory_context_.temp_vec_node_;
13987 : }
13988 :
13989 45625 : inline typename expression_node<T>::node_type type() const exprtk_override
13990 : {
13991 45625 : return expression_node<T>::e_vecvalarith;
13992 : }
13993 :
13994 25595 : inline bool valid() const exprtk_override
13995 : {
13996 : return
13997 51190 : vec1_node_ptr_ &&
13998 25595 : (size() <= base_size()) &&
13999 76785 : (vds_.size() <= base_size()) &&
14000 51190 : binary_node<T>::valid();
14001 : }
14002 :
14003 31487 : std::size_t size() const exprtk_override
14004 : {
14005 31487 : return vec1_node_ptr_->vec_holder().size();
14006 : }
14007 :
14008 51190 : std::size_t base_size() const exprtk_override
14009 : {
14010 51190 : return vec1_node_ptr_->vec_holder().base_size();
14011 : }
14012 :
14013 8825 : vds_t& vds() exprtk_override
14014 : {
14015 8825 : return vds_;
14016 : }
14017 :
14018 10382 : const vds_t& vds() const exprtk_override
14019 : {
14020 10382 : return vds_;
14021 : }
14022 :
14023 : private:
14024 :
14025 : vector_node_ptr vec1_node_ptr_;
14026 : vds_t vds_;
14027 : memory_context memory_context_;
14028 : };
14029 :
14030 : template <typename T, typename Operation>
14031 : class unary_vector_node exprtk_final
14032 : : public unary_node <T>
14033 : , public vector_interface<T>
14034 : {
14035 : public:
14036 :
14037 : typedef expression_node<T>* expression_ptr;
14038 : typedef vector_node<T>* vector_node_ptr;
14039 : typedef vector_holder<T> vector_holder_t;
14040 : typedef vector_holder_t* vector_holder_ptr;
14041 : typedef vec_data_store<T> vds_t;
14042 : typedef memory_context_t<T> memory_context;
14043 :
14044 : using expression_node<T>::branch;
14045 :
14046 2690 : unary_vector_node(const operator_type& opr, expression_ptr branch0)
14047 : : unary_node<T>(opr, branch0)
14048 2690 : , vec0_node_ptr_(0)
14049 : {
14050 2690 : bool vec0_is_ivec = false;
14051 :
14052 2690 : if (is_vector_node(branch(0)))
14053 : {
14054 111 : vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0));
14055 : }
14056 2579 : else if (is_ivector_node(branch(0)))
14057 : {
14058 2579 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
14059 :
14060 2579 : if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0))))
14061 : {
14062 2579 : vec0_node_ptr_ = vi->vec();
14063 2579 : vec0_is_ivec = true;
14064 : }
14065 : }
14066 :
14067 2690 : if (vec0_node_ptr_)
14068 : {
14069 2690 : if (vec0_is_ivec)
14070 2579 : vds_ = vec0_node_ptr_->vds();
14071 : else
14072 111 : vds_ = vds_t(vec0_node_ptr_->base_size());
14073 :
14074 2690 : memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds());
14075 : }
14076 :
14077 2690 : assert(valid());
14078 2690 : }
14079 :
14080 5380 : ~unary_vector_node()
14081 : {
14082 2690 : memory_context_.clear();
14083 5380 : }
14084 :
14085 2785 : inline T value() const exprtk_override
14086 : {
14087 2785 : branch()->value();
14088 :
14089 2785 : const T* vec0 = vec0_node_ptr_->vds().data();
14090 2785 : T* vec1 = vds().data();
14091 :
14092 2785 : loop_unroll::details lud(size());
14093 2785 : const T* upper_bound = vec0 + lud.upper_bound;
14094 :
14095 1377785 : while (vec0 < upper_bound)
14096 : {
14097 : #define exprtk_loop(N) \
14098 : vec1[N] = Operation::process(vec0[N]); \
14099 :
14100 1375000 : exprtk_loop( 0) exprtk_loop( 1)
14101 1375000 : exprtk_loop( 2) exprtk_loop( 3)
14102 : #ifndef exprtk_disable_superscalar_unroll
14103 1375000 : exprtk_loop( 4) exprtk_loop( 5)
14104 1375000 : exprtk_loop( 6) exprtk_loop( 7)
14105 1375000 : exprtk_loop( 8) exprtk_loop( 9)
14106 1375000 : exprtk_loop(10) exprtk_loop(11)
14107 1375000 : exprtk_loop(12) exprtk_loop(13)
14108 1375000 : exprtk_loop(14) exprtk_loop(15)
14109 : #endif
14110 :
14111 1375000 : vec0 += lud.batch_size;
14112 1375000 : vec1 += lud.batch_size;
14113 : }
14114 :
14115 2785 : int i = 0;
14116 :
14117 2785 : switch (lud.remainder)
14118 : {
14119 : #define case_stmt(N) \
14120 : case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
14121 : exprtk_fallthrough \
14122 :
14123 : #ifndef exprtk_disable_superscalar_unroll
14124 0 : case_stmt(15) case_stmt(14)
14125 0 : case_stmt(13) case_stmt(12)
14126 0 : case_stmt(11) case_stmt(10)
14127 125 : case_stmt( 9) case_stmt( 8)
14128 125 : case_stmt( 7) case_stmt( 6)
14129 2485 : case_stmt( 5) case_stmt( 4)
14130 : #endif
14131 2565 : case_stmt( 3) case_stmt( 2)
14132 2565 : case_stmt( 1)
14133 2785 : default: break;
14134 : }
14135 :
14136 : #undef exprtk_loop
14137 : #undef case_stmt
14138 :
14139 5570 : return (vds().data())[0];
14140 : }
14141 :
14142 0 : vector_node_ptr vec() const exprtk_override
14143 : {
14144 0 : return memory_context_.temp_vec_node_;
14145 : }
14146 :
14147 2690 : vector_node_ptr vec() exprtk_override
14148 : {
14149 2690 : return memory_context_.temp_vec_node_;
14150 : }
14151 :
14152 30387 : inline typename expression_node<T>::node_type type() const exprtk_override
14153 : {
14154 30387 : return expression_node<T>::e_vecunaryop;
14155 : }
14156 :
14157 17164 : inline bool valid() const exprtk_override
14158 : {
14159 17164 : return vec0_node_ptr_ && unary_node<T>::valid();
14160 : }
14161 :
14162 2865 : std::size_t size() const exprtk_override
14163 : {
14164 2865 : return vec0_node_ptr_->vec_holder().size();
14165 : }
14166 :
14167 0 : std::size_t base_size() const exprtk_override
14168 : {
14169 0 : return vec0_node_ptr_->vec_holder().base_size();
14170 : }
14171 :
14172 2770 : vds_t& vds() exprtk_override
14173 : {
14174 2770 : return vds_;
14175 : }
14176 :
14177 5570 : const vds_t& vds() const exprtk_override
14178 : {
14179 5570 : return vds_;
14180 : }
14181 :
14182 : private:
14183 :
14184 : vector_node_ptr vec0_node_ptr_;
14185 : vds_t vds_;
14186 : memory_context memory_context_;
14187 : };
14188 :
14189 : template <typename T>
14190 : class conditional_vector_node exprtk_final
14191 : : public expression_node <T>
14192 : , public vector_interface<T>
14193 : {
14194 : public:
14195 :
14196 : typedef expression_node <T>* expression_ptr;
14197 : typedef vector_interface<T>* vec_interface_ptr;
14198 : typedef vector_node <T>* vector_node_ptr;
14199 : typedef vector_holder <T> vector_holder_t;
14200 : typedef vector_holder_t* vector_holder_ptr;
14201 : typedef vec_data_store <T> vds_t;
14202 : typedef memory_context_t<T> memory_context;
14203 : typedef std::pair<expression_ptr,bool> branch_t;
14204 :
14205 893 : conditional_vector_node(expression_ptr condition,
14206 : expression_ptr consequent,
14207 : expression_ptr alternative)
14208 893 : : consequent_node_ptr_ (0)
14209 893 : , alternative_node_ptr_(0)
14210 893 : , temp_vec_node_ (0)
14211 893 : , temp_ (0)
14212 893 : , result_vec_size_ (0)
14213 893 : , initialised_ (false)
14214 : {
14215 893 : construct_branch_pair(condition_ , condition );
14216 893 : construct_branch_pair(consequent_ , consequent );
14217 893 : construct_branch_pair(alternative_, alternative);
14218 :
14219 893 : if (details::is_ivector_node(consequent_.first))
14220 : {
14221 893 : vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first);
14222 :
14223 893 : if (0 != ivec_ptr)
14224 : {
14225 893 : consequent_node_ptr_ = ivec_ptr->vec();
14226 : }
14227 : }
14228 :
14229 893 : if (details::is_ivector_node(alternative_.first))
14230 : {
14231 893 : vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first);
14232 :
14233 893 : if (0 != ivec_ptr)
14234 : {
14235 893 : alternative_node_ptr_ = ivec_ptr->vec();
14236 : }
14237 : }
14238 :
14239 893 : if (consequent_node_ptr_ && alternative_node_ptr_)
14240 : {
14241 893 : const std::size_t vec_size =
14242 893 : std::max(consequent_node_ptr_ ->vec_holder().base_size(),
14243 893 : alternative_node_ptr_->vec_holder().base_size());
14244 :
14245 893 : vds_ = vds_t(vec_size);
14246 893 : memory_context_ = make_memory_context(
14247 893 : consequent_node_ptr_ ->vec_holder(),
14248 893 : alternative_node_ptr_->vec_holder(),
14249 893 : vds());
14250 :
14251 893 : initialised_ = (vec_size > 0);
14252 : }
14253 :
14254 893 : assert(initialised_);
14255 893 : }
14256 :
14257 1786 : ~conditional_vector_node()
14258 : {
14259 893 : memory_context_.clear();
14260 1786 : }
14261 :
14262 902 : inline T value() const exprtk_override
14263 : {
14264 902 : T result = T(0);
14265 902 : T* source_vector = 0;
14266 902 : T* result_vector = vds().data();
14267 :
14268 902 : if (is_true(condition_))
14269 : {
14270 462 : result = consequent_.first->value();
14271 462 : source_vector = consequent_node_ptr_->vds().data();
14272 462 : result_vec_size_ = consequent_node_ptr_->size();
14273 : }
14274 : else
14275 : {
14276 440 : result = alternative_.first->value();
14277 440 : source_vector = alternative_node_ptr_->vds().data();
14278 440 : result_vec_size_ = alternative_node_ptr_->size();
14279 : }
14280 :
14281 3760 : for (std::size_t i = 0; i < result_vec_size_; ++i)
14282 : {
14283 2858 : result_vector[i] = source_vector[i];
14284 : }
14285 :
14286 902 : return result;
14287 : }
14288 :
14289 0 : vector_node_ptr vec() const exprtk_override
14290 : {
14291 0 : return memory_context_.temp_vec_node_;
14292 : }
14293 :
14294 902 : vector_node_ptr vec() exprtk_override
14295 : {
14296 902 : return memory_context_.temp_vec_node_;
14297 : }
14298 :
14299 11704 : inline typename expression_node<T>::node_type type() const exprtk_override
14300 : {
14301 11704 : return expression_node<T>::e_vecondition;
14302 : }
14303 :
14304 1786 : inline bool valid() const exprtk_override
14305 : {
14306 : return
14307 3572 : initialised_ &&
14308 1786 : condition_ .first && condition_ .first->valid() &&
14309 1786 : consequent_ .first && consequent_ .first->valid() &&
14310 5358 : alternative_.first && alternative_.first->valid() &&
14311 3572 : size() <= base_size();
14312 : }
14313 :
14314 1808 : std::size_t size() const exprtk_override
14315 : {
14316 1808 : return result_vec_size_;
14317 : }
14318 :
14319 1786 : std::size_t base_size() const exprtk_override
14320 : {
14321 1786 : return std::min(
14322 1786 : consequent_node_ptr_ ->vec_holder().base_size(),
14323 3572 : alternative_node_ptr_->vec_holder().base_size());
14324 : }
14325 :
14326 893 : vds_t& vds() exprtk_override
14327 : {
14328 893 : return vds_;
14329 : }
14330 :
14331 902 : const vds_t& vds() const exprtk_override
14332 : {
14333 902 : return vds_;
14334 : }
14335 :
14336 893 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
14337 : {
14338 893 : expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
14339 893 : expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
14340 893 : expression_node<T>::ndb_t::collect(alternative_ , node_delete_list);
14341 893 : }
14342 :
14343 2279 : std::size_t node_depth() const exprtk_override
14344 : {
14345 : return expression_node<T>::ndb_t::compute_node_depth
14346 2279 : (condition_, consequent_, alternative_);
14347 : }
14348 :
14349 : private:
14350 :
14351 : branch_t condition_;
14352 : branch_t consequent_;
14353 : branch_t alternative_;
14354 : vector_node_ptr consequent_node_ptr_;
14355 : vector_node_ptr alternative_node_ptr_;
14356 : vector_node_ptr temp_vec_node_;
14357 : vector_holder_ptr temp_;
14358 : vds_t vds_;
14359 : mutable std::size_t result_vec_size_;
14360 : bool initialised_;
14361 : memory_context memory_context_;
14362 : };
14363 :
14364 : template <typename T>
14365 : class scand_node exprtk_final : public binary_node<T>
14366 : {
14367 : public:
14368 :
14369 : typedef expression_node<T>* expression_ptr;
14370 : using binary_node<T>::branch;
14371 :
14372 120 : scand_node(const operator_type& opr,
14373 : expression_ptr branch0,
14374 : expression_ptr branch1)
14375 120 : : binary_node<T>(opr, branch0, branch1)
14376 : {
14377 120 : assert(binary_node<T>::valid());
14378 120 : }
14379 :
14380 105 : inline T value() const exprtk_override
14381 : {
14382 : return (
14383 105 : std::not_equal_to<T>()
14384 210 : (T(0),branch(0)->value()) &&
14385 0 : std::not_equal_to<T>()
14386 210 : (T(0),branch(1)->value())
14387 315 : ) ? T(1) : T(0);
14388 : }
14389 : };
14390 :
14391 : template <typename T>
14392 : class scor_node exprtk_final : public binary_node<T>
14393 : {
14394 : public:
14395 :
14396 : typedef expression_node<T>* expression_ptr;
14397 : using binary_node<T>::branch;
14398 :
14399 105 : scor_node(const operator_type& opr,
14400 : expression_ptr branch0,
14401 : expression_ptr branch1)
14402 105 : : binary_node<T>(opr, branch0, branch1)
14403 : {
14404 105 : assert(binary_node<T>::valid());
14405 105 : }
14406 :
14407 105 : inline T value() const exprtk_override
14408 : {
14409 : return (
14410 105 : std::not_equal_to<T>()
14411 210 : (T(0),branch(0)->value()) ||
14412 0 : std::not_equal_to<T>()
14413 210 : (T(0),branch(1)->value())
14414 315 : ) ? T(1) : T(0);
14415 : }
14416 : };
14417 :
14418 : template <typename T, typename IFunction, std::size_t N>
14419 : class function_N_node exprtk_final : public expression_node<T>
14420 : {
14421 : public:
14422 :
14423 : // Function of N parameters.
14424 : typedef expression_node<T>* expression_ptr;
14425 : typedef std::pair<expression_ptr,bool> branch_t;
14426 : typedef IFunction ifunction;
14427 :
14428 60380 : explicit function_N_node(ifunction* func)
14429 60380 : : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
14430 60380 : , parameter_count_(func->param_count)
14431 60380 : , initialised_(false)
14432 60380 : {}
14433 :
14434 : template <std::size_t NumBranches>
14435 120640 : bool init_branches(expression_ptr (&b)[NumBranches])
14436 : {
14437 : // Needed for incompetent and broken msvc compiler versions
14438 : #ifdef _MSC_VER
14439 : #pragma warning(push)
14440 : #pragma warning(disable: 4127)
14441 : #endif
14442 :
14443 : if (N != NumBranches)
14444 : {
14445 : return false;
14446 : }
14447 :
14448 519718 : for (std::size_t i = 0; i < NumBranches; ++i)
14449 : {
14450 399078 : if (b[i] && b[i]->valid())
14451 399078 : branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
14452 : else
14453 0 : return false;
14454 : }
14455 :
14456 120640 : initialised_ = function_;
14457 120640 : assert(valid());
14458 120640 : return initialised_;
14459 :
14460 : #ifdef _MSC_VER
14461 : #pragma warning(pop)
14462 : #endif
14463 : }
14464 :
14465 : inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
14466 : {
14467 : return this < (&fn);
14468 : }
14469 :
14470 45898398 : inline T value() const exprtk_override
14471 : {
14472 : // Needed for incompetent and broken msvc compiler versions
14473 : #ifdef _MSC_VER
14474 : #pragma warning(push)
14475 : #pragma warning(disable: 4127)
14476 : #endif
14477 :
14478 : T v[N];
14479 45898398 : evaluate_branches<T,N>::execute(v,branch_);
14480 91796796 : return invoke<T,N>::execute(*function_,v);
14481 :
14482 : #ifdef _MSC_VER
14483 : #pragma warning(pop)
14484 : #endif
14485 : }
14486 :
14487 1635343 : inline typename expression_node<T>::node_type type() const exprtk_override
14488 : {
14489 1635343 : return expression_node<T>::e_function;
14490 : }
14491 :
14492 1042604 : inline bool valid() const exprtk_override
14493 : {
14494 1042604 : return initialised_;
14495 : }
14496 :
14497 60380 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
14498 : {
14499 60380 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
14500 60380 : }
14501 :
14502 176077 : std::size_t node_depth() const exprtk_override
14503 : {
14504 176077 : return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
14505 : }
14506 :
14507 : template <typename T_, std::size_t BranchCount>
14508 : struct evaluate_branches
14509 : {
14510 8120 : static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
14511 : {
14512 93380 : for (std::size_t i = 0; i < BranchCount; ++i)
14513 : {
14514 85260 : v[i] = b[i].first->value();
14515 : }
14516 8120 : }
14517 : };
14518 :
14519 : template <typename T_>
14520 : struct evaluate_branches <T_,6>
14521 : {
14522 1215 : static inline void execute(T_ (&v)[6], const branch_t (&b)[6])
14523 : {
14524 1215 : v[0] = b[0].first->value();
14525 1215 : v[1] = b[1].first->value();
14526 1215 : v[2] = b[2].first->value();
14527 1215 : v[3] = b[3].first->value();
14528 1215 : v[4] = b[4].first->value();
14529 1215 : v[5] = b[5].first->value();
14530 1215 : }
14531 : };
14532 :
14533 : template <typename T_>
14534 : struct evaluate_branches <T_,5>
14535 : {
14536 2024 : static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
14537 : {
14538 2024 : v[0] = b[0].first->value();
14539 2024 : v[1] = b[1].first->value();
14540 2024 : v[2] = b[2].first->value();
14541 2024 : v[3] = b[3].first->value();
14542 2024 : v[4] = b[4].first->value();
14543 2024 : }
14544 : };
14545 :
14546 : template <typename T_>
14547 : struct evaluate_branches <T_,4>
14548 : {
14549 5288 : static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
14550 : {
14551 5288 : v[0] = b[0].first->value();
14552 5288 : v[1] = b[1].first->value();
14553 5288 : v[2] = b[2].first->value();
14554 5288 : v[3] = b[3].first->value();
14555 5288 : }
14556 : };
14557 :
14558 : template <typename T_>
14559 : struct evaluate_branches <T_,3>
14560 : {
14561 13924 : static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
14562 : {
14563 13924 : v[0] = b[0].first->value();
14564 13924 : v[1] = b[1].first->value();
14565 13924 : v[2] = b[2].first->value();
14566 13924 : }
14567 : };
14568 :
14569 : template <typename T_>
14570 : struct evaluate_branches <T_,2>
14571 : {
14572 156842 : static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
14573 : {
14574 156842 : v[0] = b[0].first->value();
14575 156842 : v[1] = b[1].first->value();
14576 156842 : }
14577 : };
14578 :
14579 : template <typename T_>
14580 : struct evaluate_branches <T_,1>
14581 : {
14582 45710985 : static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
14583 : {
14584 45710985 : v[0] = b[0].first->value();
14585 45710985 : }
14586 : };
14587 :
14588 : template <typename T_, std::size_t ParamCount>
14589 : struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
14590 :
14591 : template <typename T_>
14592 : struct invoke<T_,20>
14593 : {
14594 0 : static inline T_ execute(ifunction& f, T_ (&v)[20])
14595 0 : { 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]); }
14596 : };
14597 :
14598 : template <typename T_>
14599 : struct invoke<T_,19>
14600 : {
14601 0 : static inline T_ execute(ifunction& f, T_ (&v)[19])
14602 0 : { 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]); }
14603 : };
14604 :
14605 : template <typename T_>
14606 : struct invoke<T_,18>
14607 : {
14608 0 : static inline T_ execute(ifunction& f, T_ (&v)[18])
14609 0 : { 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]); }
14610 : };
14611 :
14612 : template <typename T_>
14613 : struct invoke<T_,17>
14614 : {
14615 0 : static inline T_ execute(ifunction& f, T_ (&v)[17])
14616 0 : { 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]); }
14617 : };
14618 :
14619 : template <typename T_>
14620 : struct invoke<T_,16>
14621 : {
14622 0 : static inline T_ execute(ifunction& f, T_ (&v)[16])
14623 0 : { 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]); }
14624 : };
14625 :
14626 : template <typename T_>
14627 : struct invoke<T_,15>
14628 : {
14629 0 : static inline T_ execute(ifunction& f, T_ (&v)[15])
14630 0 : { 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]); }
14631 : };
14632 :
14633 : template <typename T_>
14634 : struct invoke<T_,14>
14635 : {
14636 1015 : static inline T_ execute(ifunction& f, T_ (&v)[14])
14637 1015 : { 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]); }
14638 : };
14639 :
14640 : template <typename T_>
14641 : struct invoke<T_,13>
14642 : {
14643 1015 : static inline T_ execute(ifunction& f, T_ (&v)[13])
14644 1015 : { 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]); }
14645 : };
14646 :
14647 : template <typename T_>
14648 : struct invoke<T_,12>
14649 : {
14650 1015 : static inline T_ execute(ifunction& f, T_ (&v)[12])
14651 1015 : { 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]); }
14652 : };
14653 :
14654 : template <typename T_>
14655 : struct invoke<T_,11>
14656 : {
14657 1015 : static inline T_ execute(ifunction& f, T_ (&v)[11])
14658 1015 : { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); }
14659 : };
14660 :
14661 : template <typename T_>
14662 : struct invoke<T_,10>
14663 : {
14664 1015 : static inline T_ execute(ifunction& f, T_ (&v)[10])
14665 1015 : { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); }
14666 : };
14667 :
14668 : template <typename T_>
14669 : struct invoke<T_,9>
14670 : {
14671 1015 : static inline T_ execute(ifunction& f, T_ (&v)[9])
14672 1015 : { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); }
14673 : };
14674 :
14675 : template <typename T_>
14676 : struct invoke<T_,8>
14677 : {
14678 1015 : static inline T_ execute(ifunction& f, T_ (&v)[8])
14679 1015 : { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); }
14680 : };
14681 :
14682 : template <typename T_>
14683 : struct invoke<T_,7>
14684 : {
14685 1015 : static inline T_ execute(ifunction& f, T_ (&v)[7])
14686 1015 : { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); }
14687 : };
14688 :
14689 : template <typename T_>
14690 : struct invoke<T_,6>
14691 : {
14692 1215 : static inline T_ execute(ifunction& f, T_ (&v)[6])
14693 1215 : { return f(v[0], v[1], v[2], v[3], v[4], v[5]); }
14694 : };
14695 :
14696 : template <typename T_>
14697 : struct invoke<T_,5>
14698 : {
14699 2024 : static inline T_ execute(ifunction& f, T_ (&v)[5])
14700 2024 : { return f(v[0], v[1], v[2], v[3], v[4]); }
14701 : };
14702 :
14703 : template <typename T_>
14704 : struct invoke<T_,4>
14705 : {
14706 5288 : static inline T_ execute(ifunction& f, T_ (&v)[4])
14707 5288 : { return f(v[0], v[1], v[2], v[3]); }
14708 : };
14709 :
14710 : template <typename T_>
14711 : struct invoke<T_,3>
14712 : {
14713 13924 : static inline T_ execute(ifunction& f, T_ (&v)[3])
14714 13924 : { return f(v[0], v[1], v[2]); }
14715 : };
14716 :
14717 : template <typename T_>
14718 : struct invoke<T_,2>
14719 : {
14720 156842 : static inline T_ execute(ifunction& f, T_ (&v)[2])
14721 156842 : { return f(v[0], v[1]); }
14722 : };
14723 :
14724 : template <typename T_>
14725 : struct invoke<T_,1>
14726 : {
14727 45710985 : static inline T_ execute(ifunction& f, T_ (&v)[1])
14728 45710985 : { return f(v[0]); }
14729 : };
14730 :
14731 : private:
14732 :
14733 : ifunction* function_;
14734 : std::size_t parameter_count_;
14735 : branch_t branch_[N];
14736 : bool initialised_;
14737 : };
14738 :
14739 : template <typename T, typename IFunction>
14740 : class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T>
14741 : {
14742 : public:
14743 :
14744 : typedef expression_node<T>* expression_ptr;
14745 : typedef IFunction ifunction;
14746 :
14747 231 : explicit function_N_node(ifunction* func)
14748 231 : : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
14749 : {
14750 231 : assert(valid());
14751 231 : }
14752 :
14753 : inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
14754 : {
14755 : return this < (&fn);
14756 : }
14757 :
14758 77530 : inline T value() const exprtk_override
14759 : {
14760 77530 : return (*function_)();
14761 : }
14762 :
14763 3981 : inline typename expression_node<T>::node_type type() const exprtk_override
14764 : {
14765 3981 : return expression_node<T>::e_function;
14766 : }
14767 :
14768 501 : inline bool valid() const exprtk_override
14769 : {
14770 501 : return function_;
14771 : }
14772 :
14773 : private:
14774 :
14775 : ifunction* function_;
14776 : };
14777 :
14778 : template <typename T, typename VarArgFunction>
14779 : class vararg_function_node exprtk_final : public expression_node<T>
14780 : {
14781 : public:
14782 :
14783 : typedef expression_node<T>* expression_ptr;
14784 :
14785 49 : vararg_function_node(VarArgFunction* func,
14786 : const std::vector<expression_ptr>& arg_list)
14787 49 : : function_(func)
14788 49 : , arg_list_(arg_list)
14789 : {
14790 49 : value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
14791 49 : assert(valid());
14792 49 : }
14793 :
14794 : inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
14795 : {
14796 : return this < (&fn);
14797 : }
14798 :
14799 49 : inline T value() const exprtk_override
14800 : {
14801 49 : populate_value_list();
14802 49 : return (*function_)(value_list_);
14803 : }
14804 :
14805 344 : inline typename expression_node<T>::node_type type() const exprtk_override
14806 : {
14807 344 : return expression_node<T>::e_vafunction;
14808 : }
14809 :
14810 131 : inline bool valid() const exprtk_override
14811 : {
14812 131 : return function_;
14813 : }
14814 :
14815 49 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
14816 : {
14817 166 : for (std::size_t i = 0; i < arg_list_.size(); ++i)
14818 : {
14819 117 : if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
14820 : {
14821 69 : node_delete_list.push_back(&arg_list_[i]);
14822 : }
14823 : }
14824 49 : }
14825 :
14826 144 : std::size_t node_depth() const exprtk_override
14827 : {
14828 144 : return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
14829 : }
14830 :
14831 : private:
14832 :
14833 49 : inline void populate_value_list() const
14834 : {
14835 166 : for (std::size_t i = 0; i < arg_list_.size(); ++i)
14836 : {
14837 117 : value_list_[i] = arg_list_[i]->value();
14838 : }
14839 49 : }
14840 :
14841 : VarArgFunction* function_;
14842 : std::vector<expression_ptr> arg_list_;
14843 : mutable std::vector<T> value_list_;
14844 : };
14845 :
14846 : template <typename T, typename GenericFunction>
14847 : class generic_function_node : public expression_node<T>
14848 : {
14849 : public:
14850 :
14851 : typedef type_store<T> type_store_t;
14852 : typedef expression_node<T>* expression_ptr;
14853 : typedef variable_node<T> variable_node_t;
14854 : typedef vector_node<T> vector_node_t;
14855 : typedef variable_node_t* variable_node_ptr_t;
14856 : typedef vector_node_t* vector_node_ptr_t;
14857 : typedef range_interface<T> range_interface_t;
14858 : typedef range_data_type<T> range_data_type_t;
14859 : typedef typename range_interface<T>::range_t range_t;
14860 :
14861 : typedef std::pair<expression_ptr,bool> branch_t;
14862 : typedef vector_holder<T>* vh_t;
14863 : typedef vector_view<T>* vecview_t;
14864 :
14865 : typedef std::vector<T> tmp_vs_t;
14866 : typedef std::vector<type_store_t> typestore_list_t;
14867 : typedef std::vector<range_data_type_t> range_list_t;
14868 :
14869 3724 : explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
14870 : GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
14871 3724 : : function_(func)
14872 3724 : , arg_list_(arg_list)
14873 3724 : {}
14874 :
14875 3781 : virtual ~generic_function_node()
14876 : {
14877 11989 : for (std::size_t i = 0; i < vv_list_.size(); ++i)
14878 : {
14879 8265 : vecview_t& vv = vv_list_[i];
14880 8265 : if (vv && typestore_list_[i].vec_data)
14881 : {
14882 111 : vv->remove_ref(&typestore_list_[i].vec_data);
14883 111 : typestore_list_[i].vec_data = 0;
14884 : }
14885 : }
14886 7505 : }
14887 :
14888 3724 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
14889 : {
14890 3724 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
14891 3724 : }
14892 :
14893 7609 : std::size_t node_depth() const exprtk_override exprtk_final
14894 : {
14895 7609 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
14896 : }
14897 :
14898 3724 : virtual bool init_branches()
14899 : {
14900 3724 : expr_as_vec1_store_.resize(arg_list_.size(), T(0) );
14901 3724 : typestore_list_ .resize(arg_list_.size(), type_store_t() );
14902 3724 : range_list_ .resize(arg_list_.size(), range_data_type_t());
14903 3724 : branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false));
14904 3724 : vv_list_ .resize(arg_list_.size(), vecview_t(0));
14905 :
14906 11989 : for (std::size_t i = 0; i < arg_list_.size(); ++i)
14907 : {
14908 8265 : type_store_t& ts = typestore_list_[i];
14909 :
14910 8265 : if (0 == arg_list_[i])
14911 0 : return false;
14912 8265 : else if (is_ivector_node(arg_list_[i]))
14913 : {
14914 4325 : vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
14915 :
14916 4325 : if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
14917 0 : return false;
14918 :
14919 4325 : ts.size = vi->size();
14920 4325 : ts.data = vi->vds().data();
14921 4325 : ts.type = type_store_t::e_vector;
14922 :
14923 4325 : if (
14924 4436 : vi->vec()->vec_holder().rebaseable() &&
14925 111 : vi->vec()->vec_holder().rebaseable_instance()
14926 : )
14927 : {
14928 111 : vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance();
14929 111 : vv_list_[i]->set_ref(&ts.vec_data);
14930 : }
14931 : }
14932 : #ifndef exprtk_disable_string_capabilities
14933 3940 : else if (is_generally_string_node(arg_list_[i]))
14934 : {
14935 254 : string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
14936 :
14937 254 : if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
14938 0 : return false;
14939 :
14940 254 : ts.size = sbn->size();
14941 254 : ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
14942 254 : ts.type = type_store_t::e_string;
14943 :
14944 254 : range_list_[i].data = ts.data;
14945 254 : range_list_[i].size = ts.size;
14946 254 : range_list_[i].type_size = sizeof(char);
14947 254 : range_list_[i].str_node = sbn;
14948 :
14949 254 : range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
14950 :
14951 254 : if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
14952 0 : return false;
14953 :
14954 254 : const range_t& rp = ri->range_ref();
14955 :
14956 254 : if (
14957 508 : rp.const_range() &&
14958 254 : is_const_string_range_node(arg_list_[i])
14959 : )
14960 : {
14961 0 : ts.size = rp.const_size();
14962 0 : ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
14963 0 : range_list_[i].range = reinterpret_cast<range_t*>(0);
14964 : }
14965 : else
14966 : {
14967 254 : range_list_[i].range = &(ri->range_ref());
14968 254 : range_param_list_.push_back(i);
14969 : }
14970 : }
14971 : #endif
14972 3686 : else if (is_variable_node(arg_list_[i]))
14973 : {
14974 517 : variable_node_ptr_t var = variable_node_ptr_t(0);
14975 :
14976 517 : if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
14977 0 : return false;
14978 :
14979 517 : ts.size = 1;
14980 517 : ts.data = &var->ref();
14981 517 : ts.type = type_store_t::e_scalar;
14982 : }
14983 : else
14984 : {
14985 3169 : ts.size = 1;
14986 3169 : ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
14987 3169 : ts.type = type_store_t::e_scalar;
14988 : }
14989 :
14990 8265 : branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
14991 : }
14992 :
14993 3724 : return true;
14994 : }
14995 :
14996 : inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
14997 : {
14998 : return this < (&fn);
14999 : }
15000 :
15001 120 : inline T value() const exprtk_override
15002 : {
15003 120 : if (populate_value_list())
15004 : {
15005 : typedef typename GenericFunction::parameter_list_t parameter_list_t;
15006 :
15007 120 : return (*function_)(parameter_list_t(typestore_list_));
15008 : }
15009 :
15010 0 : return std::numeric_limits<T>::quiet_NaN();
15011 : }
15012 :
15013 337 : inline typename expression_node<T>::node_type type() const exprtk_override
15014 : {
15015 337 : return expression_node<T>::e_genfunction;
15016 : }
15017 :
15018 12169 : inline bool valid() const exprtk_override
15019 : {
15020 12169 : return function_;
15021 : }
15022 :
15023 : protected:
15024 :
15025 5088 : inline virtual bool populate_value_list() const
15026 : {
15027 16159 : for (std::size_t i = 0; i < branch_.size(); ++i)
15028 : {
15029 11071 : expr_as_vec1_store_[i] = branch_[i].first->value();
15030 : }
15031 :
15032 5088 : if (!range_param_list_.empty())
15033 : {
15034 158 : assert(range_param_list_.size() <= branch_.size());
15035 :
15036 408 : for (std::size_t i = 0; i < range_param_list_.size(); ++i)
15037 : {
15038 250 : const std::size_t index = range_param_list_[i];
15039 250 : range_data_type_t& rdt = range_list_[index];
15040 :
15041 250 : const range_t& rp = (*rdt.range);
15042 250 : std::size_t r0 = 0;
15043 250 : std::size_t r1 = 0;
15044 :
15045 250 : const std::size_t data_size =
15046 : #ifndef exprtk_disable_string_capabilities
15047 250 : rdt.str_node ? rdt.str_node->size() : rdt.size;
15048 : #else
15049 : rdt.size;
15050 : #endif
15051 :
15052 250 : if (!rp(r0, r1, data_size))
15053 : {
15054 0 : return false;
15055 : }
15056 :
15057 250 : type_store_t& ts = typestore_list_[index];
15058 :
15059 250 : ts.size = rp.cache_size();
15060 : #ifndef exprtk_disable_string_capabilities
15061 250 : if (ts.type == type_store_t::e_string)
15062 250 : ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
15063 : else
15064 : #endif
15065 0 : ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
15066 : }
15067 : }
15068 :
15069 5088 : return true;
15070 : }
15071 :
15072 : GenericFunction* function_;
15073 : mutable typestore_list_t typestore_list_;
15074 :
15075 : private:
15076 :
15077 : std::vector<expression_ptr> arg_list_;
15078 : std::vector<branch_t> branch_;
15079 : std::vector<vecview_t> vv_list_;
15080 : mutable tmp_vs_t expr_as_vec1_store_;
15081 : mutable range_list_t range_list_;
15082 : std::vector<std::size_t> range_param_list_;
15083 : };
15084 :
15085 : #ifndef exprtk_disable_string_capabilities
15086 : template <typename T, typename StringFunction>
15087 : class string_function_node : public generic_function_node<T,StringFunction>
15088 : , public string_base_node<T>
15089 : , public range_interface <T>
15090 : {
15091 : public:
15092 :
15093 : typedef generic_function_node<T,StringFunction> gen_function_t;
15094 : typedef typename range_interface<T>::range_t range_t;
15095 :
15096 72 : string_function_node(StringFunction* func,
15097 : const std::vector<typename gen_function_t::expression_ptr>& arg_list)
15098 72 : : gen_function_t(arg_list,func)
15099 : {
15100 72 : range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
15101 72 : range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
15102 72 : range_.cache.first = range_.n0_c.second;
15103 72 : range_.cache.second = range_.n1_c.second;
15104 72 : assert(valid());
15105 72 : }
15106 :
15107 : inline bool operator <(const string_function_node<T,StringFunction>& fn) const
15108 : {
15109 : return this < (&fn);
15110 : }
15111 :
15112 0 : inline T value() const exprtk_override
15113 : {
15114 0 : if (gen_function_t::populate_value_list())
15115 : {
15116 : typedef typename StringFunction::parameter_list_t parameter_list_t;
15117 :
15118 : const T result =
15119 0 : (*gen_function_t::function_)
15120 0 : (
15121 0 : ret_string_,
15122 0 : parameter_list_t(gen_function_t::typestore_list_)
15123 : );
15124 :
15125 0 : range_.n1_c.second = ret_string_.size();
15126 0 : range_.cache.second = range_.n1_c.second;
15127 :
15128 0 : return result;
15129 : }
15130 :
15131 0 : return std::numeric_limits<T>::quiet_NaN();
15132 : }
15133 :
15134 0 : inline typename expression_node<T>::node_type type() const exprtk_override
15135 : {
15136 0 : return expression_node<T>::e_strfunction;
15137 : }
15138 :
15139 414 : inline bool valid() const exprtk_override
15140 : {
15141 414 : return gen_function_t::function_;
15142 : }
15143 :
15144 6 : std::string str() const exprtk_override
15145 : {
15146 6 : return ret_string_;
15147 : }
15148 :
15149 66 : char_cptr base() const exprtk_override
15150 : {
15151 66 : return &ret_string_[0];
15152 : }
15153 :
15154 72 : std::size_t size() const exprtk_override
15155 : {
15156 72 : return ret_string_.size();
15157 : }
15158 :
15159 72 : range_t& range_ref() exprtk_override
15160 : {
15161 72 : return range_;
15162 : }
15163 :
15164 0 : const range_t& range_ref() const exprtk_override
15165 : {
15166 0 : return range_;
15167 : }
15168 :
15169 : protected:
15170 :
15171 : mutable range_t range_;
15172 : mutable std::string ret_string_;
15173 : };
15174 : #endif
15175 :
15176 : template <typename T, typename GenericFunction>
15177 : class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
15178 : {
15179 : public:
15180 :
15181 : typedef generic_function_node<T,GenericFunction> gen_function_t;
15182 : typedef typename gen_function_t::range_t range_t;
15183 :
15184 3479 : multimode_genfunction_node(GenericFunction* func,
15185 : const std::size_t& param_seq_index,
15186 : const std::vector<typename gen_function_t::expression_ptr>& arg_list)
15187 : : gen_function_t(arg_list,func)
15188 3479 : , param_seq_index_(param_seq_index)
15189 3479 : {}
15190 :
15191 4865 : inline T value() const exprtk_override
15192 : {
15193 4865 : assert(gen_function_t::valid());
15194 :
15195 4865 : if (gen_function_t::populate_value_list())
15196 : {
15197 : typedef typename GenericFunction::parameter_list_t parameter_list_t;
15198 :
15199 : return
15200 4865 : (*gen_function_t::function_)
15201 4865 : (
15202 4865 : param_seq_index_,
15203 4865 : parameter_list_t(gen_function_t::typestore_list_)
15204 4865 : );
15205 : }
15206 :
15207 0 : return std::numeric_limits<T>::quiet_NaN();
15208 : }
15209 :
15210 50666 : inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final
15211 : {
15212 50666 : return expression_node<T>::e_genfunction;
15213 : }
15214 :
15215 : private:
15216 :
15217 : std::size_t param_seq_index_;
15218 : };
15219 :
15220 : #ifndef exprtk_disable_string_capabilities
15221 : template <typename T, typename StringFunction>
15222 : class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction>
15223 : {
15224 : public:
15225 :
15226 : typedef string_function_node<T,StringFunction> str_function_t;
15227 : typedef typename str_function_t::range_t range_t;
15228 :
15229 72 : multimode_strfunction_node(StringFunction* func,
15230 : const std::size_t& param_seq_index,
15231 : const std::vector<typename str_function_t::expression_ptr>& arg_list)
15232 : : str_function_t(func,arg_list)
15233 72 : , param_seq_index_(param_seq_index)
15234 72 : {}
15235 :
15236 72 : inline T value() const exprtk_override
15237 : {
15238 72 : if (str_function_t::populate_value_list())
15239 : {
15240 : typedef typename StringFunction::parameter_list_t parameter_list_t;
15241 :
15242 : const T result =
15243 72 : (*str_function_t::function_)
15244 216 : (
15245 72 : param_seq_index_,
15246 72 : str_function_t::ret_string_,
15247 72 : parameter_list_t(str_function_t::typestore_list_)
15248 : );
15249 :
15250 72 : str_function_t::range_.n1_c.second = str_function_t::ret_string_.size();
15251 72 : str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
15252 :
15253 72 : return result;
15254 : }
15255 :
15256 0 : return std::numeric_limits<T>::quiet_NaN();
15257 : }
15258 :
15259 984 : inline typename expression_node<T>::node_type type() const exprtk_override
15260 : {
15261 984 : return expression_node<T>::e_strfunction;
15262 : }
15263 :
15264 : private:
15265 :
15266 : const std::size_t param_seq_index_;
15267 : };
15268 : #endif
15269 :
15270 : class return_exception {};
15271 :
15272 : template <typename T>
15273 : class null_igenfunc
15274 : {
15275 : public:
15276 :
15277 : virtual ~null_igenfunc()
15278 : {}
15279 :
15280 : typedef type_store<T> generic_type;
15281 : typedef typename generic_type::parameter_list parameter_list_t;
15282 :
15283 : inline virtual T operator() (parameter_list_t)
15284 : {
15285 : return std::numeric_limits<T>::quiet_NaN();
15286 : }
15287 : };
15288 :
15289 : #ifndef exprtk_disable_return_statement
15290 : template <typename T>
15291 : class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> >
15292 : {
15293 : public:
15294 :
15295 : typedef results_context<T> results_context_t;
15296 : typedef null_igenfunc<T> igeneric_function_t;
15297 : typedef igeneric_function_t* igeneric_function_ptr;
15298 : typedef generic_function_node<T,igeneric_function_t> gen_function_t;
15299 :
15300 116 : return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
15301 : results_context_t& rc)
15302 : : gen_function_t (arg_list)
15303 116 : , results_context_(&rc)
15304 116 : {}
15305 :
15306 31 : inline T value() const exprtk_override
15307 : {
15308 31 : if (
15309 62 : (0 != results_context_) &&
15310 31 : gen_function_t::populate_value_list()
15311 : )
15312 : {
15313 : typedef typename type_store<T>::parameter_list parameter_list_t;
15314 :
15315 31 : results_context_->
15316 31 : assign(parameter_list_t(gen_function_t::typestore_list_));
15317 :
15318 31 : throw return_exception();
15319 : }
15320 :
15321 0 : return std::numeric_limits<T>::quiet_NaN();
15322 : }
15323 :
15324 542 : inline typename expression_node<T>::node_type type() const exprtk_override
15325 : {
15326 542 : return expression_node<T>::e_return;
15327 : }
15328 :
15329 162 : inline bool valid() const exprtk_override
15330 : {
15331 162 : return results_context_;
15332 : }
15333 :
15334 : private:
15335 :
15336 : results_context_t* results_context_;
15337 : };
15338 :
15339 : template <typename T>
15340 : class return_envelope_node exprtk_final : public expression_node<T>
15341 : {
15342 : public:
15343 :
15344 : typedef expression_node<T>* expression_ptr;
15345 : typedef results_context<T> results_context_t;
15346 : typedef std::pair<expression_ptr,bool> branch_t;
15347 :
15348 111 : return_envelope_node(expression_ptr body, results_context_t& rc)
15349 111 : : results_context_(&rc )
15350 111 : , return_invoked_ (false)
15351 : {
15352 111 : construct_branch_pair(body_, body);
15353 111 : assert(valid());
15354 111 : }
15355 :
15356 111 : inline T value() const exprtk_override
15357 : {
15358 : try
15359 : {
15360 111 : return_invoked_ = false;
15361 111 : results_context_->clear();
15362 :
15363 111 : return body_.first->value();
15364 : }
15365 31 : catch(const return_exception&)
15366 : {
15367 31 : return_invoked_ = true;
15368 :
15369 31 : return std::numeric_limits<T>::quiet_NaN();
15370 : }
15371 : }
15372 :
15373 222 : inline typename expression_node<T>::node_type type() const exprtk_override
15374 : {
15375 222 : return expression_node<T>::e_retenv;
15376 : }
15377 :
15378 111 : inline bool valid() const exprtk_override
15379 : {
15380 111 : return results_context_ && body_.first;
15381 : }
15382 :
15383 111 : inline bool* retinvk_ptr()
15384 : {
15385 111 : return &return_invoked_;
15386 : }
15387 :
15388 111 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
15389 : {
15390 111 : expression_node<T>::ndb_t::collect(body_, node_delete_list);
15391 111 : }
15392 :
15393 111 : std::size_t node_depth() const exprtk_override
15394 : {
15395 111 : return expression_node<T>::ndb_t::compute_node_depth(body_);
15396 : }
15397 :
15398 : private:
15399 :
15400 : results_context_t* results_context_;
15401 : mutable bool return_invoked_;
15402 : branch_t body_;
15403 : };
15404 : #endif
15405 :
15406 : #define exprtk_define_unary_op(OpName) \
15407 : template <typename T> \
15408 : struct OpName##_op \
15409 : { \
15410 : typedef typename functor_t<T>::Type Type; \
15411 : typedef typename expression_node<T>::node_type node_t; \
15412 : \
15413 : static inline T process(Type v) \
15414 : { \
15415 : return numeric:: OpName (v); \
15416 : } \
15417 : \
15418 : static inline node_t type() \
15419 : { \
15420 : return expression_node<T>::e_##OpName; \
15421 : } \
15422 : \
15423 : static inline details::operator_type operation() \
15424 : { \
15425 : return details::e_##OpName; \
15426 : } \
15427 : }; \
15428 :
15429 22116398 : exprtk_define_unary_op(abs )
15430 1560 : exprtk_define_unary_op(acos )
15431 1740 : exprtk_define_unary_op(acosh)
15432 1740 : exprtk_define_unary_op(asin )
15433 1800 : exprtk_define_unary_op(asinh)
15434 1870 : exprtk_define_unary_op(atan )
15435 0 : exprtk_define_unary_op(atanh)
15436 1440 : exprtk_define_unary_op(ceil )
15437 40031237 : exprtk_define_unary_op(cos )
15438 1740 : exprtk_define_unary_op(cosh )
15439 1876 : exprtk_define_unary_op(cot )
15440 1630 : exprtk_define_unary_op(csc )
15441 1440 : exprtk_define_unary_op(d2g )
15442 1800 : exprtk_define_unary_op(d2r )
15443 30001450 : exprtk_define_unary_op(erf )
15444 30001570 : exprtk_define_unary_op(erfc )
15445 1800 : exprtk_define_unary_op(exp )
15446 1560 : exprtk_define_unary_op(expm1)
15447 1440 : exprtk_define_unary_op(floor)
15448 2604 : exprtk_define_unary_op(frac )
15449 1560 : exprtk_define_unary_op(g2d )
15450 3070 : exprtk_define_unary_op(log )
15451 3190 : exprtk_define_unary_op(log10)
15452 0 : exprtk_define_unary_op(log2 )
15453 1440 : exprtk_define_unary_op(log1p)
15454 0 : exprtk_define_unary_op(ncdf )
15455 146526 : exprtk_define_unary_op(neg )
15456 112 : exprtk_define_unary_op(notl )
15457 0 : exprtk_define_unary_op(pos )
15458 1740 : exprtk_define_unary_op(r2d )
15459 1800 : exprtk_define_unary_op(round)
15460 1510 : exprtk_define_unary_op(sec )
15461 4098 : exprtk_define_unary_op(sgn )
15462 144368184 : exprtk_define_unary_op(sin )
15463 70 : exprtk_define_unary_op(sinc )
15464 1560 : exprtk_define_unary_op(sinh )
15465 6003291 : exprtk_define_unary_op(sqrt )
15466 290899 : exprtk_define_unary_op(tan )
15467 1740 : exprtk_define_unary_op(tanh )
15468 940 : exprtk_define_unary_op(trunc)
15469 : #undef exprtk_define_unary_op
15470 :
15471 : template <typename T>
15472 : struct opr_base
15473 : {
15474 : typedef typename details::functor_t<T>::Type Type;
15475 : typedef typename details::functor_t<T>::RefType RefType;
15476 : typedef typename details::functor_t<T> functor_t;
15477 : typedef typename functor_t::qfunc_t quaternary_functor_t;
15478 : typedef typename functor_t::tfunc_t trinary_functor_t;
15479 : typedef typename functor_t::bfunc_t binary_functor_t;
15480 : typedef typename functor_t::ufunc_t unary_functor_t;
15481 : };
15482 :
15483 : template <typename T>
15484 : struct add_op : public opr_base<T>
15485 : {
15486 : typedef typename opr_base<T>::Type Type;
15487 : typedef typename opr_base<T>::RefType RefType;
15488 :
15489 278746690 : static inline T process(Type t1, Type t2) { return t1 + t2; }
15490 : static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
15491 5568 : static inline void assign(RefType t1, Type t2) { t1 += t2; }
15492 1770063 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
15493 119142 : static inline details::operator_type operation() { return details::e_add; }
15494 : };
15495 :
15496 : template <typename T>
15497 : struct mul_op : public opr_base<T>
15498 : {
15499 : typedef typename opr_base<T>::Type Type;
15500 : typedef typename opr_base<T>::RefType RefType;
15501 :
15502 900469021 : static inline T process(Type t1, Type t2) { return t1 * t2; }
15503 : static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
15504 240 : static inline void assign(RefType t1, Type t2) { t1 *= t2; }
15505 3975181 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
15506 214083 : static inline details::operator_type operation() { return details::e_mul; }
15507 : };
15508 :
15509 : template <typename T>
15510 : struct sub_op : public opr_base<T>
15511 : {
15512 : typedef typename opr_base<T>::Type Type;
15513 : typedef typename opr_base<T>::RefType RefType;
15514 :
15515 445983141 : static inline T process(Type t1, Type t2) { return t1 - t2; }
15516 : static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
15517 1004 : static inline void assign(RefType t1, Type t2) { t1 -= t2; }
15518 1593439 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
15519 116791 : static inline details::operator_type operation() { return details::e_sub; }
15520 : };
15521 :
15522 : template <typename T>
15523 : struct div_op : public opr_base<T>
15524 : {
15525 : typedef typename opr_base<T>::Type Type;
15526 : typedef typename opr_base<T>::RefType RefType;
15527 :
15528 400187315 : static inline T process(Type t1, Type t2) { return t1 / t2; }
15529 : static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
15530 240 : static inline void assign(RefType t1, Type t2) { t1 /= t2; }
15531 3041094 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
15532 185468 : static inline details::operator_type operation() { return details::e_div; }
15533 : };
15534 :
15535 : template <typename T>
15536 : struct mod_op : public opr_base<T>
15537 : {
15538 : typedef typename opr_base<T>::Type Type;
15539 : typedef typename opr_base<T>::RefType RefType;
15540 :
15541 118403 : static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
15542 0 : static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
15543 118 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
15544 21 : static inline details::operator_type operation() { return details::e_mod; }
15545 : };
15546 :
15547 : template <typename T>
15548 : struct pow_op : public opr_base<T>
15549 : {
15550 : typedef typename opr_base<T>::Type Type;
15551 : typedef typename opr_base<T>::RefType RefType;
15552 :
15553 1380 : static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
15554 : static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
15555 3714 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
15556 446 : static inline details::operator_type operation() { return details::e_pow; }
15557 : };
15558 :
15559 : template <typename T>
15560 : struct lt_op : public opr_base<T>
15561 : {
15562 : typedef typename opr_base<T>::Type Type;
15563 :
15564 43491690 : static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
15565 656 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
15566 16518 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
15567 121 : static inline details::operator_type operation() { return details::e_lt; }
15568 : };
15569 :
15570 : template <typename T>
15571 : struct lte_op : public opr_base<T>
15572 : {
15573 : typedef typename opr_base<T>::Type Type;
15574 :
15575 60009490 : static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
15576 155 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
15577 13274 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
15578 0 : static inline details::operator_type operation() { return details::e_lte; }
15579 : };
15580 :
15581 : template <typename T>
15582 : struct gt_op : public opr_base<T>
15583 : {
15584 : typedef typename opr_base<T>::Type Type;
15585 :
15586 39115 : static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
15587 655 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
15588 18478 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
15589 151 : static inline details::operator_type operation() { return details::e_gt; }
15590 : };
15591 :
15592 : template <typename T>
15593 : struct gte_op : public opr_base<T>
15594 : {
15595 : typedef typename opr_base<T>::Type Type;
15596 :
15597 675 : static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
15598 155 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
15599 1480 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
15600 0 : static inline details::operator_type operation() { return details::e_gte; }
15601 : };
15602 :
15603 : template <typename T>
15604 : struct eq_op : public opr_base<T>
15605 : {
15606 : typedef typename opr_base<T>::Type Type;
15607 94985622 : static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
15608 25921 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
15609 267750 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
15610 6007 : static inline details::operator_type operation() { return details::e_eq; }
15611 : };
15612 :
15613 : template <typename T>
15614 : struct equal_op : public opr_base<T>
15615 : {
15616 : typedef typename opr_base<T>::Type Type;
15617 :
15618 360 : static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
15619 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
15620 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
15621 : static inline details::operator_type operation() { return details::e_equal; }
15622 : };
15623 :
15624 : template <typename T>
15625 : struct ne_op : public opr_base<T>
15626 : {
15627 : typedef typename opr_base<T>::Type Type;
15628 :
15629 1817 : static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
15630 2450 : static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
15631 14060 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
15632 120 : static inline details::operator_type operation() { return details::e_ne; }
15633 : };
15634 :
15635 : template <typename T>
15636 : struct and_op : public opr_base<T>
15637 : {
15638 : typedef typename opr_base<T>::Type Type;
15639 :
15640 9894 : static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
15641 570 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
15642 0 : static inline details::operator_type operation() { return details::e_and; }
15643 : };
15644 :
15645 : template <typename T>
15646 : struct nand_op : public opr_base<T>
15647 : {
15648 : typedef typename opr_base<T>::Type Type;
15649 :
15650 4 : static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
15651 68 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
15652 0 : static inline details::operator_type operation() { return details::e_nand; }
15653 : };
15654 :
15655 : template <typename T>
15656 : struct or_op : public opr_base<T>
15657 : {
15658 : typedef typename opr_base<T>::Type Type;
15659 :
15660 11406052 : static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
15661 570 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
15662 0 : static inline details::operator_type operation() { return details::e_or; }
15663 : };
15664 :
15665 : template <typename T>
15666 : struct nor_op : public opr_base<T>
15667 : {
15668 : typedef typename opr_base<T>::Type Type;
15669 :
15670 4 : static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
15671 68 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
15672 0 : static inline details::operator_type operation() { return details::e_nor; }
15673 : };
15674 :
15675 : template <typename T>
15676 : struct xor_op : public opr_base<T>
15677 : {
15678 : typedef typename opr_base<T>::Type Type;
15679 :
15680 25 : static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
15681 0 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
15682 0 : static inline details::operator_type operation() { return details::e_xor; }
15683 : };
15684 :
15685 : template <typename T>
15686 : struct xnor_op : public opr_base<T>
15687 : {
15688 : typedef typename opr_base<T>::Type Type;
15689 :
15690 0 : static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
15691 0 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
15692 0 : static inline details::operator_type operation() { return details::e_xnor; }
15693 : };
15694 :
15695 : template <typename T>
15696 : struct in_op : public opr_base<T>
15697 : {
15698 : typedef typename opr_base<T>::Type Type;
15699 :
15700 : static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
15701 760 : static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
15702 9300 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
15703 0 : static inline details::operator_type operation() { return details::e_in; }
15704 : };
15705 :
15706 : template <typename T>
15707 : struct like_op : public opr_base<T>
15708 : {
15709 : typedef typename opr_base<T>::Type Type;
15710 :
15711 : static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
15712 3070 : static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
15713 18550 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
15714 0 : static inline details::operator_type operation() { return details::e_like; }
15715 : };
15716 :
15717 : template <typename T>
15718 : struct ilike_op : public opr_base<T>
15719 : {
15720 : typedef typename opr_base<T>::Type Type;
15721 :
15722 : static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
15723 3245 : static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
15724 18550 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
15725 0 : static inline details::operator_type operation() { return details::e_ilike; }
15726 : };
15727 :
15728 : template <typename T>
15729 : struct inrange_op : public opr_base<T>
15730 : {
15731 : typedef typename opr_base<T>::Type Type;
15732 :
15733 : static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
15734 300 : static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
15735 : {
15736 300 : return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
15737 : }
15738 1500 : static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
15739 0 : static inline details::operator_type operation() { return details::e_inrange; }
15740 : };
15741 :
15742 : template <typename T>
15743 : inline T value(details::expression_node<T>* n)
15744 : {
15745 : return n->value();
15746 : }
15747 :
15748 : template <typename T>
15749 31848709 : inline T value(std::pair<details::expression_node<T>*,bool> n)
15750 : {
15751 31848709 : return n.first->value();
15752 : }
15753 :
15754 : template <typename T>
15755 5111 : inline T value(const T* t)
15756 : {
15757 5111 : return (*t);
15758 : }
15759 :
15760 : template <typename T>
15761 : inline T value(const T& t)
15762 : {
15763 : return t;
15764 : }
15765 :
15766 : template <typename T>
15767 : struct vararg_add_op exprtk_final : public opr_base<T>
15768 : {
15769 : typedef typename opr_base<T>::Type Type;
15770 :
15771 : template <typename Type,
15772 : typename Allocator,
15773 : template <typename, typename> class Sequence>
15774 191 : static inline T process(const Sequence<Type,Allocator>& arg_list)
15775 : {
15776 191 : switch (arg_list.size())
15777 : {
15778 0 : case 0 : return T(0);
15779 0 : case 1 : return process_1(arg_list);
15780 30 : case 2 : return process_2(arg_list);
15781 30 : case 3 : return process_3(arg_list);
15782 30 : case 4 : return process_4(arg_list);
15783 30 : case 5 : return process_5(arg_list);
15784 71 : default :
15785 : {
15786 71 : T result = T(0);
15787 :
15788 569 : for (std::size_t i = 0; i < arg_list.size(); ++i)
15789 : {
15790 498 : result += value(arg_list[i]);
15791 : }
15792 :
15793 71 : return result;
15794 : }
15795 : }
15796 : }
15797 :
15798 : template <typename Sequence>
15799 0 : static inline T process_1(const Sequence& arg_list)
15800 : {
15801 0 : return value(arg_list[0]);
15802 : }
15803 :
15804 : template <typename Sequence>
15805 30 : static inline T process_2(const Sequence& arg_list)
15806 : {
15807 30 : return value(arg_list[0]) + value(arg_list[1]);
15808 : }
15809 :
15810 : template <typename Sequence>
15811 30 : static inline T process_3(const Sequence& arg_list)
15812 : {
15813 30 : return value(arg_list[0]) + value(arg_list[1]) +
15814 30 : value(arg_list[2]) ;
15815 : }
15816 :
15817 : template <typename Sequence>
15818 30 : static inline T process_4(const Sequence& arg_list)
15819 : {
15820 30 : return value(arg_list[0]) + value(arg_list[1]) +
15821 30 : value(arg_list[2]) + value(arg_list[3]) ;
15822 : }
15823 :
15824 : template <typename Sequence>
15825 30 : static inline T process_5(const Sequence& arg_list)
15826 : {
15827 30 : return value(arg_list[0]) + value(arg_list[1]) +
15828 30 : value(arg_list[2]) + value(arg_list[3]) +
15829 30 : value(arg_list[4]) ;
15830 : }
15831 : };
15832 :
15833 : template <typename T>
15834 : struct vararg_mul_op exprtk_final : public opr_base<T>
15835 : {
15836 : typedef typename opr_base<T>::Type Type;
15837 :
15838 : template <typename Type,
15839 : typename Allocator,
15840 : template <typename, typename> class Sequence>
15841 164 : static inline T process(const Sequence<Type,Allocator>& arg_list)
15842 : {
15843 164 : switch (arg_list.size())
15844 : {
15845 0 : case 0 : return T(0);
15846 0 : case 1 : return process_1(arg_list);
15847 30 : case 2 : return process_2(arg_list);
15848 30 : case 3 : return process_3(arg_list);
15849 30 : case 4 : return process_4(arg_list);
15850 30 : case 5 : return process_5(arg_list);
15851 44 : default :
15852 : {
15853 44 : T result = T(value(arg_list[0]));
15854 :
15855 304 : for (std::size_t i = 1; i < arg_list.size(); ++i)
15856 : {
15857 260 : result *= value(arg_list[i]);
15858 : }
15859 :
15860 44 : return result;
15861 : }
15862 : }
15863 : }
15864 :
15865 : template <typename Sequence>
15866 0 : static inline T process_1(const Sequence& arg_list)
15867 : {
15868 0 : return value(arg_list[0]);
15869 : }
15870 :
15871 : template <typename Sequence>
15872 30 : static inline T process_2(const Sequence& arg_list)
15873 : {
15874 30 : return value(arg_list[0]) * value(arg_list[1]);
15875 : }
15876 :
15877 : template <typename Sequence>
15878 30 : static inline T process_3(const Sequence& arg_list)
15879 : {
15880 30 : return value(arg_list[0]) * value(arg_list[1]) *
15881 30 : value(arg_list[2]) ;
15882 : }
15883 :
15884 : template <typename Sequence>
15885 30 : static inline T process_4(const Sequence& arg_list)
15886 : {
15887 30 : return value(arg_list[0]) * value(arg_list[1]) *
15888 30 : value(arg_list[2]) * value(arg_list[3]) ;
15889 : }
15890 :
15891 : template <typename Sequence>
15892 30 : static inline T process_5(const Sequence& arg_list)
15893 : {
15894 30 : return value(arg_list[0]) * value(arg_list[1]) *
15895 30 : value(arg_list[2]) * value(arg_list[3]) *
15896 30 : value(arg_list[4]) ;
15897 : }
15898 : };
15899 :
15900 : template <typename T>
15901 : struct vararg_avg_op exprtk_final : public opr_base<T>
15902 : {
15903 : typedef typename opr_base<T>::Type Type;
15904 :
15905 : template <typename Type,
15906 : typename Allocator,
15907 : template <typename, typename> class Sequence>
15908 247 : static inline T process(const Sequence<Type,Allocator>& arg_list)
15909 : {
15910 247 : switch (arg_list.size())
15911 : {
15912 0 : case 0 : return T(0);
15913 0 : case 1 : return process_1(arg_list);
15914 55 : case 2 : return process_2(arg_list);
15915 55 : case 3 : return process_3(arg_list);
15916 55 : case 4 : return process_4(arg_list);
15917 55 : case 5 : return process_5(arg_list);
15918 27 : default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size());
15919 : }
15920 : }
15921 :
15922 : template <typename Sequence>
15923 0 : static inline T process_1(const Sequence& arg_list)
15924 : {
15925 0 : return value(arg_list[0]);
15926 : }
15927 :
15928 : template <typename Sequence>
15929 55 : static inline T process_2(const Sequence& arg_list)
15930 : {
15931 55 : return (value(arg_list[0]) + value(arg_list[1])) / T(2);
15932 : }
15933 :
15934 : template <typename Sequence>
15935 55 : static inline T process_3(const Sequence& arg_list)
15936 : {
15937 55 : return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
15938 : }
15939 :
15940 : template <typename Sequence>
15941 55 : static inline T process_4(const Sequence& arg_list)
15942 : {
15943 55 : return (value(arg_list[0]) + value(arg_list[1]) +
15944 55 : value(arg_list[2]) + value(arg_list[3])) / T(4);
15945 : }
15946 :
15947 : template <typename Sequence>
15948 55 : static inline T process_5(const Sequence& arg_list)
15949 : {
15950 55 : return (value(arg_list[0]) + value(arg_list[1]) +
15951 55 : value(arg_list[2]) + value(arg_list[3]) +
15952 55 : value(arg_list[4])) / T(5);
15953 : }
15954 : };
15955 :
15956 : template <typename T>
15957 : struct vararg_min_op exprtk_final : public opr_base<T>
15958 : {
15959 : typedef typename opr_base<T>::Type Type;
15960 :
15961 : template <typename Type,
15962 : typename Allocator,
15963 : template <typename, typename> class Sequence>
15964 4924 : static inline T process(const Sequence<Type,Allocator>& arg_list)
15965 : {
15966 4924 : switch (arg_list.size())
15967 : {
15968 0 : case 0 : return T(0);
15969 0 : case 1 : return process_1(arg_list);
15970 4690 : case 2 : return process_2(arg_list);
15971 82 : case 3 : return process_3(arg_list);
15972 55 : case 4 : return process_4(arg_list);
15973 56 : case 5 : return process_5(arg_list);
15974 41 : default :
15975 : {
15976 41 : T result = T(value(arg_list[0]));
15977 :
15978 278 : for (std::size_t i = 1; i < arg_list.size(); ++i)
15979 : {
15980 237 : const T v = value(arg_list[i]);
15981 :
15982 237 : if (v < result)
15983 1 : result = v;
15984 : }
15985 :
15986 41 : return result;
15987 : }
15988 : }
15989 : }
15990 :
15991 : template <typename Sequence>
15992 0 : static inline T process_1(const Sequence& arg_list)
15993 : {
15994 0 : return value(arg_list[0]);
15995 : }
15996 :
15997 : template <typename Sequence>
15998 4690 : static inline T process_2(const Sequence& arg_list)
15999 : {
16000 4690 : return std::min<T>(value(arg_list[0]),value(arg_list[1]));
16001 : }
16002 :
16003 : template <typename Sequence>
16004 82 : static inline T process_3(const Sequence& arg_list)
16005 : {
16006 82 : return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
16007 : }
16008 :
16009 : template <typename Sequence>
16010 55 : static inline T process_4(const Sequence& arg_list)
16011 : {
16012 55 : return std::min<T>(
16013 55 : std::min<T>(value(arg_list[0]), value(arg_list[1])),
16014 110 : std::min<T>(value(arg_list[2]), value(arg_list[3])));
16015 : }
16016 :
16017 : template <typename Sequence>
16018 56 : static inline T process_5(const Sequence& arg_list)
16019 : {
16020 56 : return std::min<T>(
16021 56 : std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
16022 56 : std::min<T>(value(arg_list[2]), value(arg_list[3]))),
16023 112 : value(arg_list[4]));
16024 : }
16025 : };
16026 :
16027 : template <typename T>
16028 : struct vararg_max_op exprtk_final : public opr_base<T>
16029 : {
16030 : typedef typename opr_base<T>::Type Type;
16031 :
16032 : template <typename Type,
16033 : typename Allocator,
16034 : template <typename, typename> class Sequence>
16035 307 : static inline T process(const Sequence<Type,Allocator>& arg_list)
16036 : {
16037 307 : switch (arg_list.size())
16038 : {
16039 0 : case 0 : return T(0);
16040 0 : case 1 : return process_1(arg_list);
16041 100 : case 2 : return process_2(arg_list);
16042 55 : case 3 : return process_3(arg_list);
16043 55 : case 4 : return process_4(arg_list);
16044 56 : case 5 : return process_5(arg_list);
16045 41 : default :
16046 : {
16047 41 : T result = T(value(arg_list[0]));
16048 :
16049 278 : for (std::size_t i = 1; i < arg_list.size(); ++i)
16050 : {
16051 237 : const T v = value(arg_list[i]);
16052 :
16053 237 : if (v > result)
16054 237 : result = v;
16055 : }
16056 :
16057 41 : return result;
16058 : }
16059 : }
16060 : }
16061 :
16062 : template <typename Sequence>
16063 0 : static inline T process_1(const Sequence& arg_list)
16064 : {
16065 0 : return value(arg_list[0]);
16066 : }
16067 :
16068 : template <typename Sequence>
16069 100 : static inline T process_2(const Sequence& arg_list)
16070 : {
16071 100 : return std::max<T>(value(arg_list[0]),value(arg_list[1]));
16072 : }
16073 :
16074 : template <typename Sequence>
16075 55 : static inline T process_3(const Sequence& arg_list)
16076 : {
16077 55 : return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
16078 : }
16079 :
16080 : template <typename Sequence>
16081 55 : static inline T process_4(const Sequence& arg_list)
16082 : {
16083 55 : return std::max<T>(
16084 55 : std::max<T>(value(arg_list[0]), value(arg_list[1])),
16085 110 : std::max<T>(value(arg_list[2]), value(arg_list[3])));
16086 : }
16087 :
16088 : template <typename Sequence>
16089 56 : static inline T process_5(const Sequence& arg_list)
16090 : {
16091 56 : return std::max<T>(
16092 56 : std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
16093 56 : std::max<T>(value(arg_list[2]), value(arg_list[3]))),
16094 112 : value(arg_list[4]));
16095 : }
16096 : };
16097 :
16098 : template <typename T>
16099 : struct vararg_mand_op exprtk_final : public opr_base<T>
16100 : {
16101 : typedef typename opr_base<T>::Type Type;
16102 :
16103 : template <typename Type,
16104 : typename Allocator,
16105 : template <typename, typename> class Sequence>
16106 256 : static inline T process(const Sequence<Type,Allocator>& arg_list)
16107 : {
16108 256 : switch (arg_list.size())
16109 : {
16110 0 : case 1 : return process_1(arg_list);
16111 249 : case 2 : return process_2(arg_list);
16112 2 : case 3 : return process_3(arg_list);
16113 2 : case 4 : return process_4(arg_list);
16114 2 : case 5 : return process_5(arg_list);
16115 1 : default :
16116 : {
16117 6 : for (std::size_t i = 0; i < arg_list.size(); ++i)
16118 : {
16119 6 : if (std::equal_to<T>()(T(0), value(arg_list[i])))
16120 1 : return T(0);
16121 : }
16122 :
16123 0 : return T(1);
16124 : }
16125 : }
16126 : }
16127 :
16128 : template <typename Sequence>
16129 0 : static inline T process_1(const Sequence& arg_list)
16130 : {
16131 0 : return std::not_equal_to<T>()
16132 0 : (T(0), value(arg_list[0])) ? T(1) : T(0);
16133 : }
16134 :
16135 : template <typename Sequence>
16136 249 : static inline T process_2(const Sequence& arg_list)
16137 : {
16138 : return (
16139 374 : std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
16140 374 : std::not_equal_to<T>()(T(0), value(arg_list[1]))
16141 614 : ) ? T(1) : T(0);
16142 : }
16143 :
16144 : template <typename Sequence>
16145 2 : static inline T process_3(const Sequence& arg_list)
16146 : {
16147 : return (
16148 4 : std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
16149 4 : std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
16150 4 : std::not_equal_to<T>()(T(0), value(arg_list[2]))
16151 4 : ) ? T(1) : T(0);
16152 : }
16153 :
16154 : template <typename Sequence>
16155 2 : static inline T process_4(const Sequence& arg_list)
16156 : {
16157 : return (
16158 4 : std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
16159 4 : std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
16160 4 : std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
16161 4 : std::not_equal_to<T>()(T(0), value(arg_list[3]))
16162 4 : ) ? T(1) : T(0);
16163 : }
16164 :
16165 : template <typename Sequence>
16166 2 : static inline T process_5(const Sequence& arg_list)
16167 : {
16168 : return (
16169 4 : std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
16170 4 : std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
16171 4 : std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
16172 4 : std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
16173 4 : std::not_equal_to<T>()(T(0), value(arg_list[4]))
16174 4 : ) ? T(1) : T(0);
16175 : }
16176 : };
16177 :
16178 : template <typename T>
16179 : struct vararg_mor_op exprtk_final : public opr_base<T>
16180 : {
16181 : typedef typename opr_base<T>::Type Type;
16182 :
16183 : template <typename Type,
16184 : typename Allocator,
16185 : template <typename, typename> class Sequence>
16186 257 : static inline T process(const Sequence<Type,Allocator>& arg_list)
16187 : {
16188 257 : switch (arg_list.size())
16189 : {
16190 0 : case 1 : return process_1(arg_list);
16191 250 : case 2 : return process_2(arg_list);
16192 3 : case 3 : return process_3(arg_list);
16193 1 : case 4 : return process_4(arg_list);
16194 1 : case 5 : return process_5(arg_list);
16195 2 : default :
16196 : {
16197 15 : for (std::size_t i = 0; i < arg_list.size(); ++i)
16198 : {
16199 14 : if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
16200 1 : return T(1);
16201 : }
16202 :
16203 1 : return T(0);
16204 : }
16205 : }
16206 : }
16207 :
16208 : template <typename Sequence>
16209 0 : static inline T process_1(const Sequence& arg_list)
16210 : {
16211 0 : return std::not_equal_to<T>()
16212 0 : (T(0), value(arg_list[0])) ? T(1) : T(0);
16213 : }
16214 :
16215 : template <typename Sequence>
16216 250 : static inline T process_2(const Sequence& arg_list)
16217 : {
16218 : return (
16219 375 : std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
16220 375 : std::not_equal_to<T>()(T(0), value(arg_list[1]))
16221 615 : ) ? T(1) : T(0);
16222 : }
16223 :
16224 : template <typename Sequence>
16225 3 : static inline T process_3(const Sequence& arg_list)
16226 : {
16227 : return (
16228 4 : std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
16229 2 : std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
16230 4 : std::not_equal_to<T>()(T(0), value(arg_list[2]))
16231 4 : ) ? T(1) : T(0);
16232 : }
16233 :
16234 : template <typename Sequence>
16235 1 : static inline T process_4(const Sequence& arg_list)
16236 : {
16237 : return (
16238 1 : std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
16239 0 : std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
16240 0 : std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
16241 1 : std::not_equal_to<T>()(T(0), value(arg_list[3]))
16242 1 : ) ? T(1) : T(0);
16243 : }
16244 :
16245 : template <typename Sequence>
16246 1 : static inline T process_5(const Sequence& arg_list)
16247 : {
16248 : return (
16249 2 : std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
16250 2 : std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
16251 2 : std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
16252 2 : std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
16253 2 : std::not_equal_to<T>()(T(0), value(arg_list[4]))
16254 2 : ) ? T(1) : T(0);
16255 : }
16256 : };
16257 :
16258 : template <typename T>
16259 : struct vararg_multi_op exprtk_final : public opr_base<T>
16260 : {
16261 : typedef typename opr_base<T>::Type Type;
16262 :
16263 : template <typename Type,
16264 : typename Allocator,
16265 : template <typename, typename> class Sequence>
16266 10169021 : static inline T process(const Sequence<Type,Allocator>& arg_list)
16267 : {
16268 10169021 : switch (arg_list.size())
16269 : {
16270 0 : case 0 : return std::numeric_limits<T>::quiet_NaN();
16271 40 : case 1 : return process_1(arg_list);
16272 4656458 : case 2 : return process_2(arg_list);
16273 16177 : case 3 : return process_3(arg_list);
16274 5005264 : case 4 : return process_4(arg_list);
16275 490504 : case 5 : return process_5(arg_list);
16276 258 : case 6 : return process_6(arg_list);
16277 15 : case 7 : return process_7(arg_list);
16278 204 : case 8 : return process_8(arg_list);
16279 101 : default :
16280 : {
16281 909 : for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
16282 : {
16283 808 : value(arg_list[i]);
16284 : }
16285 101 : return value(arg_list.back());
16286 : }
16287 : }
16288 : }
16289 :
16290 : template <typename Sequence>
16291 40 : static inline T process_1(const Sequence& arg_list)
16292 : {
16293 40 : return value(arg_list[0]);
16294 : }
16295 :
16296 : template <typename Sequence>
16297 4656458 : static inline T process_2(const Sequence& arg_list)
16298 : {
16299 4656458 : value(arg_list[0]);
16300 4656408 : return value(arg_list[1]);
16301 : }
16302 :
16303 : template <typename Sequence>
16304 16177 : static inline T process_3(const Sequence& arg_list)
16305 : {
16306 16177 : value(arg_list[0]);
16307 16127 : value(arg_list[1]);
16308 16077 : return value(arg_list[2]);
16309 : }
16310 :
16311 : template <typename Sequence>
16312 5005264 : static inline T process_4(const Sequence& arg_list)
16313 : {
16314 5005264 : value(arg_list[0]);
16315 5005264 : value(arg_list[1]);
16316 5005264 : value(arg_list[2]);
16317 5005264 : return value(arg_list[3]);
16318 : }
16319 :
16320 : template <typename Sequence>
16321 490504 : static inline T process_5(const Sequence& arg_list)
16322 : {
16323 490504 : value(arg_list[0]);
16324 490504 : value(arg_list[1]);
16325 490504 : value(arg_list[2]);
16326 490504 : value(arg_list[3]);
16327 490504 : return value(arg_list[4]);
16328 : }
16329 :
16330 : template <typename Sequence>
16331 258 : static inline T process_6(const Sequence& arg_list)
16332 : {
16333 258 : value(arg_list[0]);
16334 258 : value(arg_list[1]);
16335 258 : value(arg_list[2]);
16336 258 : value(arg_list[3]);
16337 258 : value(arg_list[4]);
16338 258 : return value(arg_list[5]);
16339 : }
16340 :
16341 : template <typename Sequence>
16342 15 : static inline T process_7(const Sequence& arg_list)
16343 : {
16344 15 : value(arg_list[0]);
16345 15 : value(arg_list[1]);
16346 15 : value(arg_list[2]);
16347 15 : value(arg_list[3]);
16348 15 : value(arg_list[4]);
16349 15 : value(arg_list[5]);
16350 15 : return value(arg_list[6]);
16351 : }
16352 :
16353 : template <typename Sequence>
16354 204 : static inline T process_8(const Sequence& arg_list)
16355 : {
16356 204 : value(arg_list[0]);
16357 204 : value(arg_list[1]);
16358 204 : value(arg_list[2]);
16359 204 : value(arg_list[3]);
16360 204 : value(arg_list[4]);
16361 204 : value(arg_list[5]);
16362 204 : value(arg_list[6]);
16363 204 : return value(arg_list[7]);
16364 : }
16365 : };
16366 :
16367 : template <typename T>
16368 : struct vec_add_op
16369 : {
16370 : typedef vector_interface<T>* ivector_ptr;
16371 :
16372 2365 : static inline T process(const ivector_ptr v)
16373 : {
16374 2365 : const T* vec = v->vec()->vds().data();
16375 2365 : const std::size_t vec_size = v->size();
16376 :
16377 2365 : loop_unroll::details lud(vec_size);
16378 :
16379 2365 : if (vec_size <= static_cast<std::size_t>(lud.batch_size))
16380 : {
16381 1705 : T result = T(0);
16382 1705 : int i = 0;
16383 :
16384 1705 : switch (vec_size)
16385 : {
16386 : #define case_stmt(N,fall_through) \
16387 : case N : result += vec[i++]; \
16388 : fall_through \
16389 :
16390 : #ifndef exprtk_disable_superscalar_unroll
16391 20 : case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
16392 20 : case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
16393 20 : case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
16394 23 : case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
16395 313 : case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
16396 772 : case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
16397 :
16398 : #endif
16399 1617 : case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
16400 1705 : case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
16401 : }
16402 :
16403 : #undef case_stmt
16404 :
16405 1705 : return result;
16406 : }
16407 :
16408 660 : T r[] = {
16409 : T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
16410 : T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
16411 : };
16412 :
16413 660 : const T* upper_bound = vec + lud.upper_bound;
16414 :
16415 26375720 : while (vec < upper_bound)
16416 : {
16417 : #define exprtk_loop(N) \
16418 : r[N] += vec[N]; \
16419 :
16420 26375060 : exprtk_loop( 0) exprtk_loop( 1)
16421 26375060 : exprtk_loop( 2) exprtk_loop( 3)
16422 : #ifndef exprtk_disable_superscalar_unroll
16423 26375060 : exprtk_loop( 4) exprtk_loop( 5)
16424 26375060 : exprtk_loop( 6) exprtk_loop( 7)
16425 26375060 : exprtk_loop( 8) exprtk_loop( 9)
16426 26375060 : exprtk_loop(10) exprtk_loop(11)
16427 26375060 : exprtk_loop(12) exprtk_loop(13)
16428 26375060 : exprtk_loop(14) exprtk_loop(15)
16429 : #endif
16430 :
16431 26375060 : vec += lud.batch_size;
16432 : }
16433 :
16434 660 : int i = 0;
16435 :
16436 660 : switch (lud.remainder)
16437 : {
16438 : #define case_stmt(N,fall_through) \
16439 : case N : r[0] += vec[i++]; \
16440 : fall_through \
16441 :
16442 : #ifndef exprtk_disable_superscalar_unroll
16443 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
16444 10 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
16445 10 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
16446 10 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
16447 10 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
16448 10 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
16449 : #endif
16450 10 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
16451 30 : case_stmt( 1, (void)0;)
16452 : }
16453 :
16454 : #undef exprtk_loop
16455 : #undef case_stmt
16456 :
16457 660 : return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
16458 : #ifndef exprtk_disable_superscalar_unroll
16459 660 : + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
16460 660 : + (r[ 8] + r[ 9] + r[10] + r[11])
16461 660 : + (r[12] + r[13] + r[14] + r[15])
16462 : #endif
16463 : ;
16464 : }
16465 : };
16466 :
16467 : template <typename T>
16468 : struct vec_mul_op
16469 : {
16470 : typedef vector_interface<T>* ivector_ptr;
16471 :
16472 60 : static inline T process(const ivector_ptr v)
16473 : {
16474 60 : const T* vec = v->vec()->vds().data();
16475 60 : const std::size_t vec_size = v->vec()->size();
16476 :
16477 60 : loop_unroll::details lud(vec_size);
16478 :
16479 60 : if (vec_size <= static_cast<std::size_t>(lud.batch_size))
16480 : {
16481 20 : T result = T(1);
16482 20 : int i = 0;
16483 :
16484 20 : switch (vec_size)
16485 : {
16486 : #define case_stmt(N,fall_through) \
16487 : case N : result *= vec[i++]; \
16488 : fall_through \
16489 :
16490 : #ifndef exprtk_disable_superscalar_unroll
16491 20 : case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough)
16492 20 : case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough)
16493 20 : case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough)
16494 20 : case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough)
16495 20 : case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough)
16496 20 : case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough)
16497 : #endif
16498 20 : case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough)
16499 20 : case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;)
16500 : }
16501 :
16502 : #undef case_stmt
16503 :
16504 20 : return result;
16505 : }
16506 :
16507 40 : T r[] = {
16508 : T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
16509 : T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
16510 : };
16511 :
16512 40 : const T* upper_bound = vec + lud.upper_bound;
16513 :
16514 100 : while (vec < upper_bound)
16515 : {
16516 : #define exprtk_loop(N) \
16517 : r[N] *= vec[N]; \
16518 :
16519 60 : exprtk_loop( 0) exprtk_loop( 1)
16520 60 : exprtk_loop( 2) exprtk_loop( 3)
16521 : #ifndef exprtk_disable_superscalar_unroll
16522 60 : exprtk_loop( 4) exprtk_loop( 5)
16523 60 : exprtk_loop( 6) exprtk_loop( 7)
16524 60 : exprtk_loop( 8) exprtk_loop( 9)
16525 60 : exprtk_loop(10) exprtk_loop(11)
16526 60 : exprtk_loop(12) exprtk_loop(13)
16527 60 : exprtk_loop(14) exprtk_loop(15)
16528 : #endif
16529 :
16530 60 : vec += lud.batch_size;
16531 : }
16532 :
16533 40 : int i = 0;
16534 :
16535 40 : switch (lud.remainder)
16536 : {
16537 : #define case_stmt(N,fall_through) \
16538 : case N : r[0] *= vec[i++]; \
16539 : fall_through \
16540 :
16541 : #ifndef exprtk_disable_superscalar_unroll
16542 0 : case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough)
16543 10 : case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough)
16544 10 : case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough)
16545 10 : case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough)
16546 10 : case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough)
16547 10 : case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough)
16548 : #endif
16549 10 : case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough)
16550 30 : case_stmt( 1, (void)0;)
16551 : }
16552 :
16553 : #undef exprtk_loop
16554 : #undef case_stmt
16555 :
16556 40 : return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
16557 : #ifndef exprtk_disable_superscalar_unroll
16558 40 : * (r[ 4] * r[ 5] * r[ 6] * r[ 7])
16559 40 : * (r[ 8] * r[ 9] * r[10] * r[11])
16560 40 : * (r[12] * r[13] * r[14] * r[15])
16561 : #endif
16562 : ;
16563 : }
16564 : };
16565 :
16566 : template <typename T>
16567 : struct vec_avg_op
16568 : {
16569 : typedef vector_interface<T>* ivector_ptr;
16570 :
16571 90 : static inline T process(const ivector_ptr v)
16572 : {
16573 90 : const T vec_size = T(v->vec()->size());
16574 90 : return vec_add_op<T>::process(v) / vec_size;
16575 : }
16576 : };
16577 :
16578 : template <typename T>
16579 : struct vec_min_op
16580 : {
16581 : typedef vector_interface<T>* ivector_ptr;
16582 :
16583 100 : static inline T process(const ivector_ptr v)
16584 : {
16585 100 : const T* vec = v->vec()->vds().data();
16586 100 : const std::size_t vec_size = v->vec()->size();
16587 :
16588 100 : T result = vec[0];
16589 :
16590 449 : for (std::size_t i = 1; i < vec_size; ++i)
16591 : {
16592 349 : const T v_i = vec[i];
16593 :
16594 349 : if (v_i < result)
16595 20 : result = v_i;
16596 : }
16597 :
16598 100 : return result;
16599 : }
16600 : };
16601 :
16602 : template <typename T>
16603 : struct vec_max_op
16604 : {
16605 : typedef vector_interface<T>* ivector_ptr;
16606 :
16607 90 : static inline T process(const ivector_ptr v)
16608 : {
16609 90 : const T* vec = v->vec()->vds().data();
16610 90 : const std::size_t vec_size = v->vec()->size();
16611 :
16612 90 : T result = vec[0];
16613 :
16614 434 : for (std::size_t i = 1; i < vec_size; ++i)
16615 : {
16616 344 : const T v_i = vec[i];
16617 :
16618 344 : if (v_i > result)
16619 304 : result = v_i;
16620 : }
16621 :
16622 90 : return result;
16623 : }
16624 : };
16625 :
16626 : template <typename T>
16627 : class vov_base_node : public expression_node<T>
16628 : {
16629 : public:
16630 :
16631 265747 : virtual ~vov_base_node()
16632 265747 : {}
16633 :
16634 0 : inline virtual operator_type operation() const
16635 : {
16636 0 : return details::e_default;
16637 : }
16638 :
16639 : virtual const T& v0() const = 0;
16640 :
16641 : virtual const T& v1() const = 0;
16642 : };
16643 :
16644 : template <typename T>
16645 : class cov_base_node : public expression_node<T>
16646 : {
16647 : public:
16648 :
16649 243926 : virtual ~cov_base_node()
16650 243926 : {}
16651 :
16652 0 : inline virtual operator_type operation() const
16653 : {
16654 0 : return details::e_default;
16655 : }
16656 :
16657 : virtual const T c() const = 0;
16658 :
16659 : virtual const T& v() const = 0;
16660 : };
16661 :
16662 : template <typename T>
16663 : class voc_base_node : public expression_node<T>
16664 : {
16665 : public:
16666 :
16667 288796 : virtual ~voc_base_node()
16668 288796 : {}
16669 :
16670 0 : inline virtual operator_type operation() const
16671 : {
16672 0 : return details::e_default;
16673 : }
16674 :
16675 : virtual const T c() const = 0;
16676 :
16677 : virtual const T& v() const = 0;
16678 : };
16679 :
16680 : template <typename T>
16681 : class vob_base_node : public expression_node<T>
16682 : {
16683 : public:
16684 :
16685 33759 : virtual ~vob_base_node()
16686 33759 : {}
16687 :
16688 : virtual const T& v() const = 0;
16689 : };
16690 :
16691 : template <typename T>
16692 : class bov_base_node : public expression_node<T>
16693 : {
16694 : public:
16695 :
16696 352771 : virtual ~bov_base_node()
16697 352771 : {}
16698 :
16699 : virtual const T& v() const = 0;
16700 : };
16701 :
16702 : template <typename T>
16703 : class cob_base_node : public expression_node<T>
16704 : {
16705 : public:
16706 :
16707 89268 : virtual ~cob_base_node()
16708 89268 : {}
16709 :
16710 0 : inline virtual operator_type operation() const
16711 : {
16712 0 : return details::e_default;
16713 : }
16714 :
16715 : virtual const T c() const = 0;
16716 :
16717 : virtual void set_c(const T) = 0;
16718 :
16719 : virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
16720 : };
16721 :
16722 : template <typename T>
16723 : class boc_base_node : public expression_node<T>
16724 : {
16725 : public:
16726 :
16727 144576 : virtual ~boc_base_node()
16728 144576 : {}
16729 :
16730 0 : inline virtual operator_type operation() const
16731 : {
16732 0 : return details::e_default;
16733 : }
16734 :
16735 : virtual const T c() const = 0;
16736 :
16737 : virtual void set_c(const T) = 0;
16738 :
16739 : virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
16740 : };
16741 :
16742 : template <typename T>
16743 : class uv_base_node : public expression_node<T>
16744 : {
16745 : public:
16746 :
16747 8332 : virtual ~uv_base_node()
16748 8332 : {}
16749 :
16750 0 : inline virtual operator_type operation() const
16751 : {
16752 0 : return details::e_default;
16753 : }
16754 :
16755 : virtual const T& v() const = 0;
16756 : };
16757 :
16758 : template <typename T>
16759 : class sos_base_node : public expression_node<T>
16760 : {
16761 : public:
16762 :
16763 30647 : virtual ~sos_base_node()
16764 30647 : {}
16765 :
16766 0 : inline virtual operator_type operation() const
16767 : {
16768 0 : return details::e_default;
16769 : }
16770 : };
16771 :
16772 : template <typename T>
16773 : class sosos_base_node : public expression_node<T>
16774 : {
16775 : public:
16776 :
16777 300 : virtual ~sosos_base_node()
16778 300 : {}
16779 :
16780 0 : inline virtual operator_type operation() const
16781 : {
16782 0 : return details::e_default;
16783 : }
16784 : };
16785 :
16786 : template <typename T>
16787 : class T0oT1oT2_base_node : public expression_node<T>
16788 : {
16789 : public:
16790 :
16791 377040 : virtual ~T0oT1oT2_base_node()
16792 377040 : {}
16793 :
16794 : virtual std::string type_id() const = 0;
16795 : };
16796 :
16797 : template <typename T>
16798 : class T0oT1oT2oT3_base_node : public expression_node<T>
16799 : {
16800 : public:
16801 :
16802 104801 : virtual ~T0oT1oT2oT3_base_node()
16803 104801 : {}
16804 :
16805 : virtual std::string type_id() const = 0;
16806 : };
16807 :
16808 : template <typename T, typename Operation>
16809 : class unary_variable_node exprtk_final : public uv_base_node<T>
16810 : {
16811 : public:
16812 :
16813 : typedef expression_node<T>* expression_ptr;
16814 : typedef Operation operation_t;
16815 :
16816 8332 : explicit unary_variable_node(const T& var)
16817 8332 : : v_(var)
16818 8332 : {}
16819 :
16820 60006359 : inline T value() const exprtk_override
16821 : {
16822 60006359 : return Operation::process(v_);
16823 : }
16824 :
16825 205316 : inline typename expression_node<T>::node_type type() const exprtk_override
16826 : {
16827 205316 : return Operation::type();
16828 : }
16829 :
16830 2346 : inline operator_type operation() const exprtk_override
16831 : {
16832 2346 : return Operation::operation();
16833 : }
16834 :
16835 2360 : inline const T& v() const exprtk_override
16836 : {
16837 2360 : return v_;
16838 : }
16839 :
16840 : private:
16841 :
16842 : unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete;
16843 : unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete;
16844 :
16845 : const T& v_;
16846 : };
16847 :
16848 : template <typename T>
16849 : class uvouv_node exprtk_final : public expression_node<T>
16850 : {
16851 : public:
16852 :
16853 : // UOpr1(v0) Op UOpr2(v1)
16854 : typedef typename details::functor_t<T> functor_t;
16855 : typedef typename functor_t::bfunc_t bfunc_t;
16856 : typedef typename functor_t::ufunc_t ufunc_t;
16857 : typedef expression_node<T>* expression_ptr;
16858 :
16859 620 : explicit uvouv_node(const T& var0,const T& var1,
16860 : ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
16861 620 : : v0_(var0)
16862 620 : , v1_(var1)
16863 620 : , u0_(uf0 )
16864 620 : , u1_(uf1 )
16865 620 : , f_ (bf )
16866 620 : {}
16867 :
16868 140 : inline T value() const exprtk_override
16869 : {
16870 140 : return f_(u0_(v0_),u1_(v1_));
16871 : }
16872 :
16873 20990 : inline typename expression_node<T>::node_type type() const exprtk_override
16874 : {
16875 20990 : return expression_node<T>::e_uvouv;
16876 : }
16877 :
16878 : inline const T& v0()
16879 : {
16880 : return v0_;
16881 : }
16882 :
16883 : inline const T& v1()
16884 : {
16885 : return v1_;
16886 : }
16887 :
16888 : inline ufunc_t u0()
16889 : {
16890 : return u0_;
16891 : }
16892 :
16893 : inline ufunc_t u1()
16894 : {
16895 : return u1_;
16896 : }
16897 :
16898 : inline ufunc_t f()
16899 : {
16900 : return f_;
16901 : }
16902 :
16903 : private:
16904 :
16905 : uvouv_node(const uvouv_node<T>&) exprtk_delete;
16906 : uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete;
16907 :
16908 : const T& v0_;
16909 : const T& v1_;
16910 : const ufunc_t u0_;
16911 : const ufunc_t u1_;
16912 : const bfunc_t f_;
16913 : };
16914 :
16915 : template <typename T, typename Operation>
16916 : class unary_branch_node exprtk_final : public expression_node<T>
16917 : {
16918 : public:
16919 :
16920 : typedef Operation operation_t;
16921 : typedef expression_node<T>* expression_ptr;
16922 : typedef std::pair<expression_ptr,bool> branch_t;
16923 :
16924 59953 : explicit unary_branch_node(expression_ptr branch)
16925 59953 : {
16926 59953 : construct_branch_pair(branch_, branch);
16927 59953 : }
16928 :
16929 190043663 : inline T value() const exprtk_override
16930 : {
16931 190043663 : return Operation::process(branch_.first->value());
16932 : }
16933 :
16934 737421 : inline typename expression_node<T>::node_type type() const exprtk_override
16935 : {
16936 737421 : return Operation::type();
16937 : }
16938 :
16939 133488 : inline bool valid() const exprtk_override
16940 : {
16941 133488 : return branch_.first && branch_.first->valid();
16942 : }
16943 :
16944 : inline operator_type operation()
16945 : {
16946 : return Operation::operation();
16947 : }
16948 :
16949 1460 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
16950 : {
16951 1460 : return branch_.first;
16952 : }
16953 :
16954 1460 : inline void release()
16955 : {
16956 1460 : branch_.second = false;
16957 1460 : }
16958 :
16959 59953 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
16960 : {
16961 59953 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
16962 59953 : }
16963 :
16964 113909 : std::size_t node_depth() const exprtk_override
16965 : {
16966 113909 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
16967 : }
16968 :
16969 : private:
16970 :
16971 : unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete;
16972 : unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete;
16973 :
16974 : branch_t branch_;
16975 : };
16976 :
16977 : template <typename T> struct is_const { enum {result = 0}; };
16978 : template <typename T> struct is_const <const T> { enum {result = 1}; };
16979 : template <typename T> struct is_const_ref { enum {result = 0}; };
16980 : template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
16981 : template <typename T> struct is_ref { enum {result = 0}; };
16982 : template <typename T> struct is_ref<T&> { enum {result = 1}; };
16983 : template <typename T> struct is_ref<const T&> { enum {result = 0}; };
16984 :
16985 : template <std::size_t State>
16986 140 : struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
16987 :
16988 : template <>
16989 72 : struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
16990 :
16991 : #define exprtk_crtype(Type) \
16992 : param_to_str<is_const_ref< Type >::result>::result() \
16993 :
16994 : template <typename T>
16995 : struct T0oT1oT2process
16996 : {
16997 : typedef typename details::functor_t<T> functor_t;
16998 : typedef typename functor_t::bfunc_t bfunc_t;
16999 :
17000 : struct mode0
17001 : {
17002 5069329 : static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
17003 : {
17004 : // (T0 o0 T1) o1 T2
17005 5069329 : return bf1(bf0(t0,t1),t2);
17006 : }
17007 :
17008 : template <typename T0, typename T1, typename T2>
17009 652080 : static inline std::string id()
17010 : {
17011 652080 : static const std::string result = "(" + exprtk_crtype(T0) + "o" +
17012 : exprtk_crtype(T1) + ")o(" +
17013 : exprtk_crtype(T2) + ")" ;
17014 652080 : return result;
17015 : }
17016 : };
17017 :
17018 : struct mode1
17019 : {
17020 53400 : static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
17021 : {
17022 : // T0 o0 (T1 o1 T2)
17023 53400 : return bf0(t0,bf1(t1,t2));
17024 : }
17025 :
17026 : template <typename T0, typename T1, typename T2>
17027 651993 : static inline std::string id()
17028 : {
17029 651993 : static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
17030 : exprtk_crtype(T1) + "o" +
17031 : exprtk_crtype(T2) + ")" ;
17032 651993 : return result;
17033 : }
17034 : };
17035 : };
17036 :
17037 : template <typename T>
17038 : struct T0oT1oT20T3process
17039 : {
17040 : typedef typename details::functor_t<T> functor_t;
17041 : typedef typename functor_t::bfunc_t bfunc_t;
17042 :
17043 : struct mode0
17044 : {
17045 11413258 : static inline T process(const T& t0, const T& t1,
17046 : const T& t2, const T& t3,
17047 : const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
17048 : {
17049 : // (T0 o0 T1) o1 (T2 o2 T3)
17050 11413258 : return bf1(bf0(t0,t1),bf2(t2,t3));
17051 : }
17052 :
17053 : template <typename T0, typename T1, typename T2, typename T3>
17054 982190 : static inline std::string id()
17055 : {
17056 982190 : static const std::string result = "(" + exprtk_crtype(T0) + "o" +
17057 : exprtk_crtype(T1) + ")o" +
17058 : "(" + exprtk_crtype(T2) + "o" +
17059 : exprtk_crtype(T3) + ")" ;
17060 982190 : return result;
17061 : }
17062 : };
17063 :
17064 : struct mode1
17065 : {
17066 0 : static inline T process(const T& t0, const T& t1,
17067 : const T& t2, const T& t3,
17068 : const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
17069 : {
17070 : // (T0 o0 (T1 o1 (T2 o2 T3))
17071 0 : return bf0(t0,bf1(t1,bf2(t2,t3)));
17072 : }
17073 : template <typename T0, typename T1, typename T2, typename T3>
17074 977940 : static inline std::string id()
17075 : {
17076 977940 : static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
17077 : exprtk_crtype(T1) + ")o(" +
17078 : exprtk_crtype(T2) + "o" +
17079 : exprtk_crtype(T3) + "))" ;
17080 977940 : return result;
17081 : }
17082 : };
17083 :
17084 : struct mode2
17085 : {
17086 0 : static inline T process(const T& t0, const T& t1,
17087 : const T& t2, const T& t3,
17088 : const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
17089 : {
17090 : // (T0 o0 ((T1 o1 T2) o2 T3)
17091 0 : return bf0(t0,bf2(bf1(t1,t2),t3));
17092 : }
17093 :
17094 : template <typename T0, typename T1, typename T2, typename T3>
17095 869280 : static inline std::string id()
17096 : {
17097 869280 : static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
17098 : exprtk_crtype(T1) + "o" +
17099 : exprtk_crtype(T2) + ")o(" +
17100 : exprtk_crtype(T3) + "))" ;
17101 869280 : return result;
17102 : }
17103 : };
17104 :
17105 : struct mode3
17106 : {
17107 0 : static inline T process(const T& t0, const T& t1,
17108 : const T& t2, const T& t3,
17109 : const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
17110 : {
17111 : // (((T0 o0 T1) o1 T2) o2 T3)
17112 0 : return bf2(bf1(bf0(t0,t1),t2),t3);
17113 : }
17114 :
17115 : template <typename T0, typename T1, typename T2, typename T3>
17116 977940 : static inline std::string id()
17117 : {
17118 977940 : static const std::string result = "((" + exprtk_crtype(T0) + "o" +
17119 : exprtk_crtype(T1) + ")o(" +
17120 : exprtk_crtype(T2) + "))o(" +
17121 : exprtk_crtype(T3) + ")";
17122 977940 : return result;
17123 : }
17124 : };
17125 :
17126 : struct mode4
17127 : {
17128 0 : static inline T process(const T& t0, const T& t1,
17129 : const T& t2, const T& t3,
17130 : const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
17131 : {
17132 : // ((T0 o0 (T1 o1 T2)) o2 T3
17133 0 : return bf2(bf0(t0,bf1(t1,t2)),t3);
17134 : }
17135 :
17136 : template <typename T0, typename T1, typename T2, typename T3>
17137 869280 : static inline std::string id()
17138 : {
17139 869280 : static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
17140 : exprtk_crtype(T1) + "o" +
17141 : exprtk_crtype(T2) + "))o(" +
17142 : exprtk_crtype(T3) + ")" ;
17143 869280 : return result;
17144 : }
17145 : };
17146 : };
17147 :
17148 : #undef exprtk_crtype
17149 :
17150 : template <typename T, typename T0, typename T1>
17151 : struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
17152 : template <typename T, typename T0, typename T1>
17153 : const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
17154 :
17155 : #define synthesis_node_type_define(T0_, T1_, v_) \
17156 : template <typename T, typename T0, typename T1> \
17157 : struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
17158 : template <typename T, typename T0, typename T1> \
17159 : const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
17160 :
17161 : synthesis_node_type_define(const T0&, const T1&, e_vov)
17162 : synthesis_node_type_define(const T0&, const T1 , e_voc)
17163 : synthesis_node_type_define(const T0 , const T1&, e_cov)
17164 : synthesis_node_type_define( T0&, T1&, e_none)
17165 : synthesis_node_type_define(const T0 , const T1 , e_none)
17166 : synthesis_node_type_define( T0&, const T1 , e_none)
17167 : synthesis_node_type_define(const T0 , T1&, e_none)
17168 : synthesis_node_type_define(const T0&, T1&, e_none)
17169 : synthesis_node_type_define( T0&, const T1&, e_none)
17170 : #undef synthesis_node_type_define
17171 :
17172 : template <typename T, typename T0, typename T1, typename T2>
17173 : struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
17174 : template <typename T, typename T0, typename T1, typename T2>
17175 : const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
17176 :
17177 : #define synthesis_node_type_define(T0_, T1_, T2_, v_) \
17178 : template <typename T, typename T0, typename T1, typename T2> \
17179 : struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
17180 : template <typename T, typename T0, typename T1, typename T2> \
17181 : const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
17182 :
17183 : synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
17184 : synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
17185 : synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
17186 : synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
17187 : synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
17188 : synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
17189 : synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
17190 : synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
17191 : synthesis_node_type_define( T0&, T1&, T2&, e_none )
17192 : #undef synthesis_node_type_define
17193 :
17194 : template <typename T, typename T0, typename T1, typename T2, typename T3>
17195 : struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
17196 : template <typename T, typename T0, typename T1, typename T2, typename T3>
17197 : const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
17198 :
17199 : #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \
17200 : template <typename T, typename T0, typename T1, typename T2, typename T3> \
17201 : struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
17202 : template <typename T, typename T0, typename T1, typename T2, typename T3> \
17203 : const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
17204 :
17205 : synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
17206 : synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
17207 : synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
17208 : synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
17209 : synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
17210 : synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
17211 : synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
17212 : synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
17213 : synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
17214 : synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
17215 : synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
17216 : synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
17217 : synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
17218 : synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
17219 : synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
17220 : synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
17221 : #undef synthesis_node_type_define
17222 :
17223 : template <typename T, typename T0, typename T1>
17224 : class T0oT1 exprtk_final : public expression_node<T>
17225 : {
17226 : public:
17227 :
17228 : typedef typename details::functor_t<T> functor_t;
17229 : typedef typename functor_t::bfunc_t bfunc_t;
17230 : typedef T value_type;
17231 : typedef T0oT1<T,T0,T1> node_type;
17232 :
17233 : T0oT1(T0 p0, T1 p1, const bfunc_t p2)
17234 : : t0_(p0)
17235 : , t1_(p1)
17236 : , f_ (p2)
17237 : {}
17238 :
17239 : inline typename expression_node<T>::node_type type() const exprtk_override
17240 : {
17241 : static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
17242 : return result;
17243 : }
17244 :
17245 : inline operator_type operation() const exprtk_override
17246 : {
17247 : return e_default;
17248 : }
17249 :
17250 : inline T value() const exprtk_override
17251 : {
17252 : return f_(t0_,t1_);
17253 : }
17254 :
17255 : inline T0 t0() const
17256 : {
17257 : return t0_;
17258 : }
17259 :
17260 : inline T1 t1() const
17261 : {
17262 : return t1_;
17263 : }
17264 :
17265 : inline bfunc_t f() const
17266 : {
17267 : return f_;
17268 : }
17269 :
17270 : template <typename Allocator>
17271 : static inline expression_node<T>* allocate(Allocator& allocator,
17272 : T0 p0, T1 p1,
17273 : bfunc_t p2)
17274 : {
17275 : return allocator
17276 : .template allocate_type<node_type, T0, T1, bfunc_t&>
17277 : (p0, p1, p2);
17278 : }
17279 :
17280 : private:
17281 :
17282 : T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete;
17283 : T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); }
17284 :
17285 : T0 t0_;
17286 : T1 t1_;
17287 : const bfunc_t f_;
17288 : };
17289 :
17290 : template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
17291 : class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T>
17292 : {
17293 : public:
17294 :
17295 : typedef typename details::functor_t<T> functor_t;
17296 : typedef typename functor_t::bfunc_t bfunc_t;
17297 : typedef T value_type;
17298 : typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
17299 : typedef ProcessMode process_mode_t;
17300 :
17301 5960 : T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
17302 5960 : : t0_(p0)
17303 5960 : , t1_(p1)
17304 5960 : , t2_(p2)
17305 5960 : , f0_(p3)
17306 5960 : , f1_(p4)
17307 5960 : {}
17308 :
17309 38380 : inline typename expression_node<T>::node_type type() const exprtk_override
17310 : {
17311 : static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
17312 38380 : return result;
17313 : }
17314 :
17315 : inline operator_type operation()
17316 : {
17317 : return e_default;
17318 : }
17319 :
17320 5122729 : inline T value() const exprtk_override
17321 : {
17322 5122729 : return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
17323 : }
17324 :
17325 0 : inline T0 t0() const
17326 : {
17327 0 : return t0_;
17328 : }
17329 :
17330 0 : inline T1 t1() const
17331 : {
17332 0 : return t1_;
17333 : }
17334 :
17335 0 : inline T2 t2() const
17336 : {
17337 0 : return t2_;
17338 : }
17339 :
17340 0 : bfunc_t f0() const
17341 : {
17342 0 : return f0_;
17343 : }
17344 :
17345 0 : bfunc_t f1() const
17346 : {
17347 0 : return f1_;
17348 : }
17349 :
17350 153 : std::string type_id() const exprtk_override
17351 : {
17352 153 : return id();
17353 : }
17354 :
17355 1304073 : static inline std::string id()
17356 : {
17357 1304073 : return process_mode_t::template id<T0,T1,T2>();
17358 : }
17359 :
17360 : template <typename Allocator>
17361 5960 : static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
17362 : {
17363 : return allocator
17364 : .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
17365 5960 : (p0, p1, p2, p3, p4);
17366 : }
17367 :
17368 : private:
17369 :
17370 : T0oT1oT2(const node_type&) exprtk_delete;
17371 : node_type& operator=(const node_type&) exprtk_delete;
17372 :
17373 : T0 t0_;
17374 : T1 t1_;
17375 : T2 t2_;
17376 : const bfunc_t f0_;
17377 : const bfunc_t f1_;
17378 : };
17379 :
17380 : template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
17381 : class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T>
17382 : {
17383 : public:
17384 :
17385 : typedef typename details::functor_t<T> functor_t;
17386 : typedef typename functor_t::bfunc_t bfunc_t;
17387 : typedef T value_type;
17388 : typedef T0_ T0;
17389 : typedef T1_ T1;
17390 : typedef T2_ T2;
17391 : typedef T3_ T3;
17392 : typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
17393 : typedef ProcessMode process_mode_t;
17394 :
17395 6917 : T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
17396 6917 : : t0_(p0)
17397 6917 : , t1_(p1)
17398 6917 : , t2_(p2)
17399 6917 : , t3_(p3)
17400 6917 : , f0_(p4)
17401 6917 : , f1_(p5)
17402 6917 : , f2_(p6)
17403 6917 : {}
17404 :
17405 11413258 : inline T value() const exprtk_override
17406 : {
17407 11413258 : return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
17408 : }
17409 :
17410 : inline T0 t0() const
17411 : {
17412 : return t0_;
17413 : }
17414 :
17415 : inline T1 t1() const
17416 : {
17417 : return t1_;
17418 : }
17419 :
17420 : inline T2 t2() const
17421 : {
17422 : return t2_;
17423 : }
17424 :
17425 : inline T3 t3() const
17426 : {
17427 : return t3_;
17428 : }
17429 :
17430 : inline bfunc_t f0() const
17431 : {
17432 : return f0_;
17433 : }
17434 :
17435 : inline bfunc_t f1() const
17436 : {
17437 : return f1_;
17438 : }
17439 :
17440 : inline bfunc_t f2() const
17441 : {
17442 : return f2_;
17443 : }
17444 :
17445 4250 : inline std::string type_id() const exprtk_override
17446 : {
17447 4250 : return id();
17448 : }
17449 :
17450 4676630 : static inline std::string id()
17451 : {
17452 4676630 : return process_mode_t::template id<T0, T1, T2, T3>();
17453 : }
17454 :
17455 : template <typename Allocator>
17456 6917 : static inline expression_node<T>* allocate(Allocator& allocator,
17457 : T0 p0, T1 p1, T2 p2, T3 p3,
17458 : bfunc_t p4, bfunc_t p5, bfunc_t p6)
17459 : {
17460 : return allocator
17461 : .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
17462 6917 : (p0, p1, p2, p3, p4, p5, p6);
17463 : }
17464 :
17465 : private:
17466 :
17467 : T0oT1oT2oT3(const node_type&) exprtk_delete;
17468 : node_type& operator=(const node_type&) exprtk_delete;
17469 :
17470 : T0 t0_;
17471 : T1 t1_;
17472 : T2 t2_;
17473 : T3 t3_;
17474 : const bfunc_t f0_;
17475 : const bfunc_t f1_;
17476 : const bfunc_t f2_;
17477 : };
17478 :
17479 : template <typename T, typename T0, typename T1, typename T2>
17480 : class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T>
17481 : {
17482 : public:
17483 :
17484 : typedef typename details::functor_t<T> functor_t;
17485 : typedef typename functor_t::tfunc_t tfunc_t;
17486 : typedef T value_type;
17487 : typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
17488 :
17489 : T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
17490 : : t0_(p0)
17491 : , t1_(p1)
17492 : , t2_(p2)
17493 : , f_ (p3)
17494 : {}
17495 :
17496 : inline typename expression_node<T>::node_type type() const exprtk_override
17497 : {
17498 : static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
17499 : return result;
17500 : }
17501 :
17502 : inline operator_type operation() const exprtk_override
17503 : {
17504 : return e_default;
17505 : }
17506 :
17507 : inline T value() const exprtk_override
17508 : {
17509 : return f_(t0_, t1_, t2_);
17510 : }
17511 :
17512 : inline T0 t0() const
17513 : {
17514 : return t0_;
17515 : }
17516 :
17517 : inline T1 t1() const
17518 : {
17519 : return t1_;
17520 : }
17521 :
17522 : inline T2 t2() const
17523 : {
17524 : return t2_;
17525 : }
17526 :
17527 : tfunc_t f() const
17528 : {
17529 : return f_;
17530 : }
17531 :
17532 : std::string type_id() const
17533 : {
17534 : return id();
17535 : }
17536 :
17537 : static inline std::string id()
17538 : {
17539 : return "sf3";
17540 : }
17541 :
17542 : template <typename Allocator>
17543 : static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
17544 : {
17545 : return allocator
17546 : .template allocate_type<node_type, T0, T1, T2, tfunc_t>
17547 : (p0, p1, p2, p3);
17548 : }
17549 :
17550 : private:
17551 :
17552 : T0oT1oT2_sf3(const node_type&) exprtk_delete;
17553 : node_type& operator=(const node_type&) exprtk_delete;
17554 :
17555 : T0 t0_;
17556 : T1 t1_;
17557 : T2 t2_;
17558 : const tfunc_t f_;
17559 : };
17560 :
17561 : template <typename T, typename T0, typename T1, typename T2>
17562 : class sf3ext_type_node : public T0oT1oT2_base_node<T>
17563 : {
17564 : public:
17565 :
17566 371080 : virtual ~sf3ext_type_node()
17567 371080 : {}
17568 :
17569 : virtual T0 t0() const = 0;
17570 :
17571 : virtual T1 t1() const = 0;
17572 :
17573 : virtual T2 t2() const = 0;
17574 : };
17575 :
17576 : template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
17577 : class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2>
17578 : {
17579 : public:
17580 :
17581 : typedef T value_type;
17582 : typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type;
17583 :
17584 371080 : T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
17585 371080 : : t0_(p0)
17586 371080 : , t1_(p1)
17587 371080 : , t2_(p2)
17588 371080 : {}
17589 :
17590 12070008 : inline typename expression_node<T>::node_type type() const exprtk_override
17591 : {
17592 : static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
17593 12070008 : return result;
17594 : }
17595 :
17596 : inline operator_type operation()
17597 : {
17598 : return e_default;
17599 : }
17600 :
17601 120067133 : inline T value() const exprtk_override
17602 : {
17603 120067133 : return SF3Operation::process(t0_, t1_, t2_);
17604 : }
17605 :
17606 181199 : T0 t0() const exprtk_override
17607 : {
17608 181199 : return t0_;
17609 : }
17610 :
17611 181199 : T1 t1() const exprtk_override
17612 : {
17613 181199 : return t1_;
17614 : }
17615 :
17616 181199 : T2 t2() const exprtk_override
17617 : {
17618 181199 : return t2_;
17619 : }
17620 :
17621 527283 : std::string type_id() const exprtk_override
17622 : {
17623 527283 : return id();
17624 : }
17625 :
17626 527283 : static inline std::string id()
17627 : {
17628 527283 : return SF3Operation::id();
17629 : }
17630 :
17631 : template <typename Allocator>
17632 371080 : static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
17633 : {
17634 : return allocator
17635 : .template allocate_type<node_type, T0, T1, T2>
17636 371080 : (p0, p1, p2);
17637 : }
17638 :
17639 : private:
17640 :
17641 : T0oT1oT2_sf3ext(const node_type&) exprtk_delete;
17642 : node_type& operator=(const node_type&) exprtk_delete;
17643 :
17644 : T0 t0_;
17645 : T1 t1_;
17646 : T2 t2_;
17647 : };
17648 :
17649 : template <typename T>
17650 839039 : inline bool is_sf3ext_node(const expression_node<T>* n)
17651 : {
17652 839039 : switch (n->type())
17653 : {
17654 99912 : case expression_node<T>::e_vovov : return true;
17655 82671 : case expression_node<T>::e_vovoc : return true;
17656 80666 : case expression_node<T>::e_vocov : return true;
17657 84620 : case expression_node<T>::e_covov : return true;
17658 14530 : case expression_node<T>::e_covoc : return true;
17659 476640 : default : return false;
17660 : }
17661 : }
17662 :
17663 : template <typename T, typename T0, typename T1, typename T2, typename T3>
17664 : class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T>
17665 : {
17666 : public:
17667 :
17668 : typedef typename details::functor_t<T> functor_t;
17669 : typedef typename functor_t::qfunc_t qfunc_t;
17670 : typedef T value_type;
17671 : typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type;
17672 :
17673 : T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
17674 : : t0_(p0)
17675 : , t1_(p1)
17676 : , t2_(p2)
17677 : , t3_(p3)
17678 : , f_ (p4)
17679 : {}
17680 :
17681 : inline typename expression_node<T>::node_type type() const exprtk_override
17682 : {
17683 : static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
17684 : return result;
17685 : }
17686 :
17687 : inline operator_type operation() const exprtk_override
17688 : {
17689 : return e_default;
17690 : }
17691 :
17692 : inline T value() const exprtk_override
17693 : {
17694 : return f_(t0_, t1_, t2_, t3_);
17695 : }
17696 :
17697 : inline T0 t0() const
17698 : {
17699 : return t0_;
17700 : }
17701 :
17702 : inline T1 t1() const
17703 : {
17704 : return t1_;
17705 : }
17706 :
17707 : inline T2 t2() const
17708 : {
17709 : return t2_;
17710 : }
17711 :
17712 : inline T3 t3() const
17713 : {
17714 : return t3_;
17715 : }
17716 :
17717 : qfunc_t f() const
17718 : {
17719 : return f_;
17720 : }
17721 :
17722 : std::string type_id() const
17723 : {
17724 : return id();
17725 : }
17726 :
17727 : static inline std::string id()
17728 : {
17729 : return "sf4";
17730 : }
17731 :
17732 : template <typename Allocator>
17733 : static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
17734 : {
17735 : return allocator
17736 : .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
17737 : (p0, p1, p2, p3, p4);
17738 : }
17739 :
17740 : private:
17741 :
17742 : T0oT1oT2oT3_sf4(const node_type&) exprtk_delete;
17743 : node_type& operator=(const node_type&) exprtk_delete;
17744 :
17745 : T0 t0_;
17746 : T1 t1_;
17747 : T2 t2_;
17748 : T3 t3_;
17749 : const qfunc_t f_;
17750 : };
17751 :
17752 : template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
17753 : class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T>
17754 : {
17755 : public:
17756 :
17757 : typedef T value_type;
17758 : typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type;
17759 :
17760 97884 : T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
17761 97884 : : t0_(p0)
17762 97884 : , t1_(p1)
17763 97884 : , t2_(p2)
17764 97884 : , t3_(p3)
17765 97884 : {}
17766 :
17767 3280533 : inline typename expression_node<T>::node_type type() const exprtk_override
17768 : {
17769 : static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
17770 3280533 : return result;
17771 : }
17772 :
17773 97271 : inline T value() const exprtk_override
17774 : {
17775 97271 : return SF4Operation::process(t0_, t1_, t2_, t3_);
17776 : }
17777 :
17778 : inline T0 t0() const
17779 : {
17780 : return t0_;
17781 : }
17782 :
17783 : inline T1 t1() const
17784 : {
17785 : return t1_;
17786 : }
17787 :
17788 : inline T2 t2() const
17789 : {
17790 : return t2_;
17791 : }
17792 :
17793 : inline T3 t3() const
17794 : {
17795 : return t3_;
17796 : }
17797 :
17798 84472 : std::string type_id() const exprtk_override
17799 : {
17800 84472 : return id();
17801 : }
17802 :
17803 84472 : static inline std::string id()
17804 : {
17805 84472 : return SF4Operation::id();
17806 : }
17807 :
17808 : template <typename Allocator>
17809 97884 : static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
17810 : {
17811 : return allocator
17812 : .template allocate_type<node_type, T0, T1, T2, T3>
17813 97884 : (p0, p1, p2, p3);
17814 : }
17815 :
17816 : private:
17817 :
17818 : T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete;
17819 : node_type& operator=(const node_type&) exprtk_delete;
17820 :
17821 : T0 t0_;
17822 : T1 t1_;
17823 : T2 t2_;
17824 : T3 t3_;
17825 : };
17826 :
17827 : template <typename T>
17828 0 : inline bool is_sf4ext_node(const expression_node<T>* n)
17829 : {
17830 0 : switch (n->type())
17831 : {
17832 0 : case expression_node<T>::e_vovovov : return true;
17833 0 : case expression_node<T>::e_vovovoc : return true;
17834 0 : case expression_node<T>::e_vovocov : return true;
17835 0 : case expression_node<T>::e_vocovov : return true;
17836 0 : case expression_node<T>::e_covovov : return true;
17837 0 : case expression_node<T>::e_covocov : return true;
17838 0 : case expression_node<T>::e_vocovoc : return true;
17839 0 : case expression_node<T>::e_covovoc : return true;
17840 0 : case expression_node<T>::e_vococov : return true;
17841 0 : default : return false;
17842 : }
17843 : }
17844 :
17845 : template <typename T, typename T0, typename T1>
17846 : struct T0oT1_define
17847 : {
17848 : typedef details::T0oT1<T, T0, T1> type0;
17849 : };
17850 :
17851 : template <typename T, typename T0, typename T1, typename T2>
17852 : struct T0oT1oT2_define
17853 : {
17854 : typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
17855 : typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
17856 : typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
17857 : typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
17858 : };
17859 :
17860 : template <typename T, typename T0, typename T1, typename T2, typename T3>
17861 : struct T0oT1oT2oT3_define
17862 : {
17863 : typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
17864 : typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
17865 : typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
17866 : typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
17867 : typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
17868 : typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
17869 : };
17870 :
17871 : template <typename T, typename Operation>
17872 : class vov_node exprtk_final : public vov_base_node<T>
17873 : {
17874 : public:
17875 :
17876 : typedef expression_node<T>* expression_ptr;
17877 : typedef Operation operation_t;
17878 :
17879 : // variable op variable node
17880 265747 : explicit vov_node(const T& var0, const T& var1)
17881 265747 : : v0_(var0)
17882 265747 : , v1_(var1)
17883 265747 : {}
17884 :
17885 10561674 : inline T value() const exprtk_override
17886 : {
17887 10561674 : return Operation::process(v0_,v1_);
17888 : }
17889 :
17890 5332602 : inline typename expression_node<T>::node_type type() const exprtk_override
17891 : {
17892 5332602 : return Operation::type();
17893 : }
17894 :
17895 217869 : inline operator_type operation() const exprtk_override
17896 : {
17897 217869 : return Operation::operation();
17898 : }
17899 :
17900 217869 : inline const T& v0() const exprtk_override
17901 : {
17902 217869 : return v0_;
17903 : }
17904 :
17905 217869 : inline const T& v1() const exprtk_override
17906 : {
17907 217869 : return v1_;
17908 : }
17909 :
17910 : protected:
17911 :
17912 : const T& v0_;
17913 : const T& v1_;
17914 :
17915 : private:
17916 :
17917 : vov_node(const vov_node<T,Operation>&) exprtk_delete;
17918 : vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete;
17919 : };
17920 :
17921 : template <typename T, typename Operation>
17922 : class cov_node exprtk_final : public cov_base_node<T>
17923 : {
17924 : public:
17925 :
17926 : typedef expression_node<T>* expression_ptr;
17927 : typedef Operation operation_t;
17928 :
17929 : // constant op variable node
17930 243926 : explicit cov_node(const T& const_var, const T& var)
17931 243926 : : c_(const_var)
17932 243926 : , v_(var)
17933 243926 : {}
17934 :
17935 40059009 : inline T value() const exprtk_override
17936 : {
17937 40059009 : return Operation::process(c_,v_);
17938 : }
17939 :
17940 5131284 : inline typename expression_node<T>::node_type type() const exprtk_override
17941 : {
17942 5131284 : return Operation::type();
17943 : }
17944 :
17945 184595 : inline operator_type operation() const exprtk_override
17946 : {
17947 184595 : return Operation::operation();
17948 : }
17949 :
17950 184595 : inline const T c() const exprtk_override
17951 : {
17952 184595 : return c_;
17953 : }
17954 :
17955 184595 : inline const T& v() const exprtk_override
17956 : {
17957 184595 : return v_;
17958 : }
17959 :
17960 : protected:
17961 :
17962 : const T c_;
17963 : const T& v_;
17964 :
17965 : private:
17966 :
17967 : cov_node(const cov_node<T,Operation>&) exprtk_delete;
17968 : cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete;
17969 : };
17970 :
17971 : template <typename T, typename Operation>
17972 : class voc_node exprtk_final : public voc_base_node<T>
17973 : {
17974 : public:
17975 :
17976 : typedef expression_node<T>* expression_ptr;
17977 : typedef Operation operation_t;
17978 :
17979 : // variable op constant node
17980 288796 : explicit voc_node(const T& var, const T& const_var)
17981 288796 : : v_(var)
17982 288796 : , c_(const_var)
17983 288796 : {}
17984 :
17985 245875857 : inline T value() const exprtk_override
17986 : {
17987 245875857 : return Operation::process(v_,c_);
17988 : }
17989 :
17990 161215 : inline operator_type operation() const exprtk_override
17991 : {
17992 161215 : return Operation::operation();
17993 : }
17994 :
17995 161215 : inline const T c() const exprtk_override
17996 : {
17997 161215 : return c_;
17998 : }
17999 :
18000 161215 : inline const T& v() const exprtk_override
18001 : {
18002 161215 : return v_;
18003 : }
18004 :
18005 : protected:
18006 :
18007 : const T& v_;
18008 : const T c_;
18009 :
18010 : private:
18011 :
18012 : voc_node(const voc_node<T,Operation>&) exprtk_delete;
18013 : voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete;
18014 : };
18015 :
18016 : template <typename T, typename Operation>
18017 : class vob_node exprtk_final : public vob_base_node<T>
18018 : {
18019 : public:
18020 :
18021 : typedef expression_node<T>* expression_ptr;
18022 : typedef std::pair<expression_ptr,bool> branch_t;
18023 : typedef Operation operation_t;
18024 :
18025 : // variable op binary node
18026 33759 : explicit vob_node(const T& var, const expression_ptr branch)
18027 33759 : : v_(var)
18028 : {
18029 33759 : construct_branch_pair(branch_, branch);
18030 33759 : assert(valid());
18031 33759 : }
18032 :
18033 26104 : inline T value() const exprtk_override
18034 : {
18035 26104 : return Operation::process(v_,branch_.first->value());
18036 : }
18037 :
18038 0 : inline const T& v() const exprtk_override
18039 : {
18040 0 : return v_;
18041 : }
18042 :
18043 150568 : inline bool valid() const exprtk_override
18044 : {
18045 150568 : return branch_.first && branch_.first->valid();
18046 : }
18047 :
18048 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
18049 : {
18050 0 : return branch_.first;
18051 : }
18052 :
18053 33759 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18054 : {
18055 33759 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18056 33759 : }
18057 :
18058 135806 : std::size_t node_depth() const exprtk_override
18059 : {
18060 135806 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18061 : }
18062 :
18063 : private:
18064 :
18065 : vob_node(const vob_node<T,Operation>&) exprtk_delete;
18066 : vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete;
18067 :
18068 : const T& v_;
18069 : branch_t branch_;
18070 : };
18071 :
18072 : template <typename T, typename Operation>
18073 : class bov_node exprtk_final : public bov_base_node<T>
18074 : {
18075 : public:
18076 :
18077 : typedef expression_node<T>* expression_ptr;
18078 : typedef std::pair<expression_ptr,bool> branch_t;
18079 : typedef Operation operation_t;
18080 :
18081 : // binary node op variable node
18082 352771 : explicit bov_node(const expression_ptr branch, const T& var)
18083 352771 : : v_(var)
18084 : {
18085 352771 : construct_branch_pair(branch_, branch);
18086 352771 : assert(valid());
18087 352771 : }
18088 :
18089 5042963 : inline T value() const exprtk_override
18090 : {
18091 5042963 : return Operation::process(branch_.first->value(),v_);
18092 : }
18093 :
18094 0 : inline const T& v() const exprtk_override
18095 : {
18096 0 : return v_;
18097 : }
18098 :
18099 16169031 : inline bool valid() const exprtk_override
18100 : {
18101 16169031 : return branch_.first && branch_.first->valid();
18102 : }
18103 :
18104 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
18105 : {
18106 0 : return branch_.first;
18107 : }
18108 :
18109 352771 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18110 : {
18111 352771 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18112 352771 : }
18113 :
18114 894013 : std::size_t node_depth() const exprtk_override
18115 : {
18116 894013 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18117 : }
18118 :
18119 : private:
18120 :
18121 : bov_node(const bov_node<T,Operation>&) exprtk_delete;
18122 : bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete;
18123 :
18124 : const T& v_;
18125 : branch_t branch_;
18126 : };
18127 :
18128 : template <typename T, typename Operation>
18129 : class cob_node exprtk_final : public cob_base_node<T>
18130 : {
18131 : public:
18132 :
18133 : typedef expression_node<T>* expression_ptr;
18134 : typedef std::pair<expression_ptr,bool> branch_t;
18135 : typedef Operation operation_t;
18136 :
18137 : // constant op variable node
18138 89268 : explicit cob_node(const T const_var, const expression_ptr branch)
18139 89268 : : c_(const_var)
18140 : {
18141 89268 : construct_branch_pair(branch_, branch);
18142 89268 : assert(valid());
18143 89268 : }
18144 :
18145 10225863 : inline T value() const exprtk_override
18146 : {
18147 10225863 : return Operation::process(c_,branch_.first->value());
18148 : }
18149 :
18150 21065 : inline operator_type operation() const exprtk_override
18151 : {
18152 21065 : return Operation::operation();
18153 : }
18154 :
18155 5920 : inline const T c() const exprtk_override
18156 : {
18157 5920 : return c_;
18158 : }
18159 :
18160 4985 : inline void set_c(const T new_c) exprtk_override
18161 : {
18162 4985 : (*const_cast<T*>(&c_)) = new_c;
18163 4985 : }
18164 :
18165 656096 : inline bool valid() const exprtk_override
18166 : {
18167 656096 : return branch_.first && branch_.first->valid();
18168 : }
18169 :
18170 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
18171 : {
18172 0 : return branch_.first;
18173 : }
18174 :
18175 935 : inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
18176 : {
18177 935 : branch_.second = false;
18178 935 : return branch_.first;
18179 : }
18180 :
18181 89268 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18182 : {
18183 89268 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18184 89268 : }
18185 :
18186 296884 : std::size_t node_depth() const exprtk_override
18187 : {
18188 296884 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18189 : }
18190 :
18191 : private:
18192 :
18193 : cob_node(const cob_node<T,Operation>&) exprtk_delete;
18194 : cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete;
18195 :
18196 : const T c_;
18197 : branch_t branch_;
18198 : };
18199 :
18200 : template <typename T, typename Operation>
18201 : class boc_node exprtk_final : public boc_base_node<T>
18202 : {
18203 : public:
18204 :
18205 : typedef expression_node<T>* expression_ptr;
18206 : typedef std::pair<expression_ptr,bool> branch_t;
18207 : typedef Operation operation_t;
18208 :
18209 : // binary node op constant node
18210 144576 : explicit boc_node(const expression_ptr branch, const T const_var)
18211 144576 : : c_(const_var)
18212 : {
18213 144576 : construct_branch_pair(branch_, branch);
18214 144576 : assert(valid());
18215 144576 : }
18216 :
18217 130440 : inline T value() const exprtk_override
18218 : {
18219 130440 : return Operation::process(branch_.first->value(),c_);
18220 : }
18221 :
18222 57606 : inline operator_type operation() const exprtk_override
18223 : {
18224 57606 : return Operation::operation();
18225 : }
18226 :
18227 21382 : inline const T c() const exprtk_override
18228 : {
18229 21382 : return c_;
18230 : }
18231 :
18232 18723 : inline void set_c(const T new_c) exprtk_override
18233 : {
18234 18723 : (*const_cast<T*>(&c_)) = new_c;
18235 18723 : }
18236 :
18237 634348 : inline bool valid() const exprtk_override
18238 : {
18239 634348 : return branch_.first && branch_.first->valid();
18240 : }
18241 :
18242 0 : inline expression_node<T>* branch(const std::size_t&) const exprtk_override
18243 : {
18244 0 : return branch_.first;
18245 : }
18246 :
18247 2659 : inline expression_node<T>* move_branch(const std::size_t&) exprtk_override
18248 : {
18249 2659 : branch_.second = false;
18250 2659 : return branch_.first;
18251 : }
18252 :
18253 144576 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18254 : {
18255 144576 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18256 144576 : }
18257 :
18258 456534 : std::size_t node_depth() const exprtk_override
18259 : {
18260 456534 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18261 : }
18262 :
18263 : private:
18264 :
18265 : boc_node(const boc_node<T,Operation>&) exprtk_delete;
18266 : boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete;
18267 :
18268 : const T c_;
18269 : branch_t branch_;
18270 : };
18271 :
18272 : #ifndef exprtk_disable_string_capabilities
18273 : template <typename T, typename SType0, typename SType1, typename Operation>
18274 : class sos_node exprtk_final : public sos_base_node<T>
18275 : {
18276 : public:
18277 :
18278 : typedef expression_node<T>* expression_ptr;
18279 : typedef Operation operation_t;
18280 :
18281 : // string op string node
18282 20042 : explicit sos_node(SType0 p0, SType1 p1)
18283 20042 : : s0_(p0)
18284 20042 : , s1_(p1)
18285 20042 : {}
18286 :
18287 20041 : inline T value() const exprtk_override
18288 : {
18289 20041 : return Operation::process(s0_,s1_);
18290 : }
18291 :
18292 221104 : inline typename expression_node<T>::node_type type() const exprtk_override
18293 : {
18294 221104 : return Operation::type();
18295 : }
18296 :
18297 0 : inline operator_type operation() const exprtk_override
18298 : {
18299 0 : return Operation::operation();
18300 : }
18301 :
18302 : inline std::string& s0()
18303 : {
18304 : return s0_;
18305 : }
18306 :
18307 : inline std::string& s1()
18308 : {
18309 : return s1_;
18310 : }
18311 :
18312 : protected:
18313 :
18314 : SType0 s0_;
18315 : SType1 s1_;
18316 :
18317 : private:
18318 :
18319 : sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
18320 : sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete;
18321 : };
18322 :
18323 : template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
18324 : class str_xrox_node exprtk_final : public sos_base_node<T>
18325 : {
18326 : public:
18327 :
18328 : typedef expression_node<T>* expression_ptr;
18329 : typedef Operation operation_t;
18330 : typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type;
18331 :
18332 : // string-range op string node
18333 3690 : explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
18334 3690 : : s0_ (p0 )
18335 3690 : , s1_ (p1 )
18336 3690 : , rp0_(rp0)
18337 3690 : {}
18338 :
18339 7380 : ~str_xrox_node()
18340 : {
18341 3690 : rp0_.free();
18342 7380 : }
18343 :
18344 3690 : inline T value() const exprtk_override
18345 : {
18346 3690 : std::size_t r0 = 0;
18347 3690 : std::size_t r1 = 0;
18348 :
18349 3690 : if (rp0_(r0, r1, s0_.size()))
18350 3690 : return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
18351 : else
18352 0 : return T(0);
18353 : }
18354 :
18355 18450 : inline typename expression_node<T>::node_type type() const exprtk_override
18356 : {
18357 18450 : return Operation::type();
18358 : }
18359 :
18360 0 : inline operator_type operation() const exprtk_override
18361 : {
18362 0 : return Operation::operation();
18363 : }
18364 :
18365 : inline std::string& s0()
18366 : {
18367 : return s0_;
18368 : }
18369 :
18370 : inline std::string& s1()
18371 : {
18372 : return s1_;
18373 : }
18374 :
18375 : protected:
18376 :
18377 : SType0 s0_;
18378 : SType1 s1_;
18379 : RangePack rp0_;
18380 :
18381 : private:
18382 :
18383 : str_xrox_node(const node_type&) exprtk_delete;
18384 : node_type& operator=(const node_type&) exprtk_delete;
18385 : };
18386 :
18387 : template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
18388 : class str_xoxr_node exprtk_final : public sos_base_node<T>
18389 : {
18390 : public:
18391 :
18392 : typedef expression_node<T>* expression_ptr;
18393 : typedef Operation operation_t;
18394 : typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type;
18395 :
18396 : // string op string range node
18397 3560 : explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
18398 3560 : : s0_ (p0 )
18399 3560 : , s1_ (p1 )
18400 3560 : , rp1_(rp1)
18401 3560 : {}
18402 :
18403 7120 : ~str_xoxr_node()
18404 : {
18405 3560 : rp1_.free();
18406 7120 : }
18407 :
18408 3560 : inline T value() const exprtk_override
18409 : {
18410 3560 : std::size_t r0 = 0;
18411 3560 : std::size_t r1 = 0;
18412 :
18413 3560 : if (rp1_(r0, r1, s1_.size()))
18414 : {
18415 : return Operation::process
18416 3560 : (
18417 3560 : s0_,
18418 3560 : s1_.substr(r0, (r1 - r0) + 1)
18419 3560 : );
18420 : }
18421 : else
18422 0 : return T(0);
18423 : }
18424 :
18425 17800 : inline typename expression_node<T>::node_type type() const exprtk_override
18426 : {
18427 17800 : return Operation::type();
18428 : }
18429 :
18430 0 : inline operator_type operation() const exprtk_override
18431 : {
18432 0 : return Operation::operation();
18433 : }
18434 :
18435 : inline std::string& s0()
18436 : {
18437 : return s0_;
18438 : }
18439 :
18440 : inline std::string& s1()
18441 : {
18442 : return s1_;
18443 : }
18444 :
18445 : protected:
18446 :
18447 : SType0 s0_;
18448 : SType1 s1_;
18449 : RangePack rp1_;
18450 :
18451 : private:
18452 :
18453 : str_xoxr_node(const node_type&) exprtk_delete;
18454 : node_type& operator=(const node_type&) exprtk_delete;
18455 : };
18456 :
18457 : template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
18458 : class str_xroxr_node exprtk_final : public sos_base_node<T>
18459 : {
18460 : public:
18461 :
18462 : typedef expression_node<T>* expression_ptr;
18463 : typedef Operation operation_t;
18464 : typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type;
18465 :
18466 : // string-range op string-range node
18467 3355 : explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
18468 3355 : : s0_ (p0 )
18469 3355 : , s1_ (p1 )
18470 3355 : , rp0_(rp0)
18471 3355 : , rp1_(rp1)
18472 3355 : {}
18473 :
18474 6710 : ~str_xroxr_node()
18475 : {
18476 3355 : rp0_.free();
18477 3355 : rp1_.free();
18478 10065 : }
18479 :
18480 3355 : inline T value() const exprtk_override
18481 : {
18482 3355 : std::size_t r0_0 = 0;
18483 3355 : std::size_t r0_1 = 0;
18484 3355 : std::size_t r1_0 = 0;
18485 3355 : std::size_t r1_1 = 0;
18486 :
18487 3355 : if (
18488 6710 : rp0_(r0_0, r1_0, s0_.size()) &&
18489 6710 : rp1_(r0_1, r1_1, s1_.size())
18490 : )
18491 : {
18492 : return Operation::process
18493 6710 : (
18494 3355 : s0_.substr(r0_0, (r1_0 - r0_0) + 1),
18495 3355 : s1_.substr(r0_1, (r1_1 - r0_1) + 1)
18496 3355 : );
18497 : }
18498 : else
18499 0 : return T(0);
18500 : }
18501 :
18502 16775 : inline typename expression_node<T>::node_type type() const exprtk_override
18503 : {
18504 16775 : return Operation::type();
18505 : }
18506 :
18507 0 : inline operator_type operation() const exprtk_override
18508 : {
18509 0 : return Operation::operation();
18510 : }
18511 :
18512 : inline std::string& s0()
18513 : {
18514 : return s0_;
18515 : }
18516 :
18517 : inline std::string& s1()
18518 : {
18519 : return s1_;
18520 : }
18521 :
18522 : protected:
18523 :
18524 : SType0 s0_;
18525 : SType1 s1_;
18526 : RangePack rp0_;
18527 : RangePack rp1_;
18528 :
18529 : private:
18530 :
18531 : str_xroxr_node(const node_type&) exprtk_delete;
18532 : node_type& operator=(const node_type&) exprtk_delete;
18533 : };
18534 :
18535 : template <typename T, typename Operation>
18536 : class str_sogens_node exprtk_final : public binary_node<T>
18537 : {
18538 : public:
18539 :
18540 : typedef expression_node <T>* expression_ptr;
18541 : typedef string_base_node<T>* str_base_ptr;
18542 : typedef range_pack <T> range_t;
18543 : typedef range_t* range_ptr;
18544 : typedef range_interface <T> irange_t;
18545 : typedef irange_t* irange_ptr;
18546 :
18547 : using binary_node<T>::branch;
18548 :
18549 4846 : str_sogens_node(const operator_type& opr,
18550 : expression_ptr branch0,
18551 : expression_ptr branch1)
18552 : : binary_node<T>(opr, branch0, branch1)
18553 4846 : , str0_base_ptr_ (0)
18554 4846 : , str1_base_ptr_ (0)
18555 4846 : , str0_range_ptr_(0)
18556 4846 : , str1_range_ptr_(0)
18557 4846 : , initialised_ (false)
18558 : {
18559 4846 : if (is_generally_string_node(branch(0)))
18560 : {
18561 4846 : str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0));
18562 :
18563 4846 : if (0 == str0_base_ptr_)
18564 0 : return;
18565 :
18566 4846 : irange_ptr range = dynamic_cast<irange_ptr>(branch(0));
18567 :
18568 4846 : if (0 == range)
18569 0 : return;
18570 :
18571 4846 : str0_range_ptr_ = &(range->range_ref());
18572 : }
18573 :
18574 4846 : if (is_generally_string_node(branch(1)))
18575 : {
18576 4846 : str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1));
18577 :
18578 4846 : if (0 == str1_base_ptr_)
18579 0 : return;
18580 :
18581 4846 : irange_ptr range = dynamic_cast<irange_ptr>(branch(1));
18582 :
18583 4846 : if (0 == range)
18584 0 : return;
18585 :
18586 4846 : str1_range_ptr_ = &(range->range_ref());
18587 : }
18588 :
18589 4846 : initialised_ =
18590 9692 : str0_base_ptr_ &&
18591 4846 : str1_base_ptr_ &&
18592 14538 : str0_range_ptr_ &&
18593 4846 : str1_range_ptr_;
18594 :
18595 4846 : assert(valid());
18596 0 : }
18597 :
18598 4846 : inline T value() const exprtk_override
18599 : {
18600 4846 : branch(0)->value();
18601 4846 : branch(1)->value();
18602 :
18603 4846 : std::size_t str0_r0 = 0;
18604 4846 : std::size_t str0_r1 = 0;
18605 :
18606 4846 : std::size_t str1_r0 = 0;
18607 4846 : std::size_t str1_r1 = 0;
18608 :
18609 4846 : const range_t& range0 = (*str0_range_ptr_);
18610 4846 : const range_t& range1 = (*str1_range_ptr_);
18611 :
18612 4846 : if (
18613 9692 : range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
18614 9692 : range1(str1_r0, str1_r1, str1_base_ptr_->size())
18615 : )
18616 : {
18617 : return Operation::process
18618 14538 : (
18619 4846 : str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)),
18620 4846 : str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0))
18621 4846 : );
18622 : }
18623 :
18624 0 : return std::numeric_limits<T>::quiet_NaN();
18625 : }
18626 :
18627 24830 : inline typename expression_node<T>::node_type type() const exprtk_override
18628 : {
18629 24830 : return Operation::type();
18630 : }
18631 :
18632 7392 : inline bool valid() const exprtk_override
18633 : {
18634 7392 : return initialised_;
18635 : }
18636 :
18637 : private:
18638 :
18639 : str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete;
18640 : str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete;
18641 :
18642 : str_base_ptr str0_base_ptr_;
18643 : str_base_ptr str1_base_ptr_;
18644 : range_ptr str0_range_ptr_;
18645 : range_ptr str1_range_ptr_;
18646 : bool initialised_;
18647 : };
18648 :
18649 : template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
18650 : class sosos_node exprtk_final : public sosos_base_node<T>
18651 : {
18652 : public:
18653 :
18654 : typedef expression_node<T>* expression_ptr;
18655 : typedef Operation operation_t;
18656 : typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type;
18657 :
18658 : // string op string op string node
18659 300 : explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
18660 300 : : s0_(p0)
18661 300 : , s1_(p1)
18662 300 : , s2_(p2)
18663 300 : {}
18664 :
18665 300 : inline T value() const exprtk_override
18666 : {
18667 300 : return Operation::process(s0_, s1_, s2_);
18668 : }
18669 :
18670 1500 : inline typename expression_node<T>::node_type type() const exprtk_override
18671 : {
18672 1500 : return Operation::type();
18673 : }
18674 :
18675 0 : inline operator_type operation() const exprtk_override
18676 : {
18677 0 : return Operation::operation();
18678 : }
18679 :
18680 : inline std::string& s0()
18681 : {
18682 : return s0_;
18683 : }
18684 :
18685 : inline std::string& s1()
18686 : {
18687 : return s1_;
18688 : }
18689 :
18690 : inline std::string& s2()
18691 : {
18692 : return s2_;
18693 : }
18694 :
18695 : protected:
18696 :
18697 : SType0 s0_;
18698 : SType1 s1_;
18699 : SType2 s2_;
18700 :
18701 : private:
18702 :
18703 : sosos_node(const node_type&) exprtk_delete;
18704 : node_type& operator=(const node_type&) exprtk_delete;
18705 : };
18706 : #endif
18707 :
18708 : template <typename T, typename PowOp>
18709 : class ipow_node exprtk_final: public expression_node<T>
18710 : {
18711 : public:
18712 :
18713 : typedef expression_node<T>* expression_ptr;
18714 : typedef PowOp operation_t;
18715 :
18716 59062 : explicit ipow_node(const T& v)
18717 59062 : : v_(v)
18718 59062 : {}
18719 :
18720 59062 : inline T value() const exprtk_override
18721 : {
18722 59062 : return PowOp::result(v_);
18723 : }
18724 :
18725 1665218 : inline typename expression_node<T>::node_type type() const exprtk_override
18726 : {
18727 1665218 : return expression_node<T>::e_ipow;
18728 : }
18729 :
18730 : private:
18731 :
18732 : ipow_node(const ipow_node<T,PowOp>&) exprtk_delete;
18733 : ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete;
18734 :
18735 : const T& v_;
18736 : };
18737 :
18738 : template <typename T, typename PowOp>
18739 : class bipow_node exprtk_final : public expression_node<T>
18740 : {
18741 : public:
18742 :
18743 : typedef expression_node<T>* expression_ptr;
18744 : typedef std::pair<expression_ptr, bool> branch_t;
18745 : typedef PowOp operation_t;
18746 :
18747 1 : explicit bipow_node(expression_ptr branch)
18748 1 : {
18749 1 : construct_branch_pair(branch_, branch);
18750 1 : assert(valid());
18751 1 : }
18752 :
18753 1 : inline T value() const exprtk_override
18754 : {
18755 1 : return PowOp::result(branch_.first->value());
18756 : }
18757 :
18758 13 : inline typename expression_node<T>::node_type type() const exprtk_override
18759 : {
18760 13 : return expression_node<T>::e_ipow;
18761 : }
18762 :
18763 3 : inline bool valid() const exprtk_override
18764 : {
18765 3 : return branch_.first && branch_.first->valid();
18766 : }
18767 :
18768 1 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18769 : {
18770 1 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18771 1 : }
18772 :
18773 3 : std::size_t node_depth() const exprtk_override
18774 : {
18775 3 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18776 : }
18777 :
18778 : private:
18779 :
18780 : bipow_node(const bipow_node<T,PowOp>&) exprtk_delete;
18781 : bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete;
18782 :
18783 : branch_t branch_;
18784 : };
18785 :
18786 : template <typename T, typename PowOp>
18787 : class ipowinv_node exprtk_final : public expression_node<T>
18788 : {
18789 : public:
18790 :
18791 : typedef expression_node<T>* expression_ptr;
18792 : typedef PowOp operation_t;
18793 :
18794 3050 : explicit ipowinv_node(const T& v)
18795 3050 : : v_(v)
18796 3050 : {}
18797 :
18798 3050 : inline T value() const exprtk_override
18799 : {
18800 3050 : return (T(1) / PowOp::result(v_));
18801 : }
18802 :
18803 39700 : inline typename expression_node<T>::node_type type() const exprtk_override
18804 : {
18805 39700 : return expression_node<T>::e_ipowinv;
18806 : }
18807 :
18808 : private:
18809 :
18810 : ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete;
18811 : ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete;
18812 :
18813 : const T& v_;
18814 : };
18815 :
18816 : template <typename T, typename PowOp>
18817 : class bipowinv_node exprtk_final : public expression_node<T>
18818 : {
18819 : public:
18820 :
18821 : typedef expression_node<T>* expression_ptr;
18822 : typedef std::pair<expression_ptr, bool> branch_t;
18823 : typedef PowOp operation_t;
18824 :
18825 0 : explicit bipowinv_node(expression_ptr branch)
18826 0 : {
18827 0 : construct_branch_pair(branch_, branch);
18828 0 : assert(valid());
18829 0 : }
18830 :
18831 0 : inline T value() const exprtk_override
18832 : {
18833 0 : return (T(1) / PowOp::result(branch_.first->value()));
18834 : }
18835 :
18836 0 : inline typename expression_node<T>::node_type type() const exprtk_override
18837 : {
18838 0 : return expression_node<T>::e_ipowinv;
18839 : }
18840 :
18841 0 : inline bool valid() const exprtk_override
18842 : {
18843 0 : return branch_.first && branch_.first->valid();
18844 : }
18845 :
18846 0 : void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override
18847 : {
18848 0 : expression_node<T>::ndb_t::collect(branch_, node_delete_list);
18849 0 : }
18850 :
18851 0 : std::size_t node_depth() const exprtk_override
18852 : {
18853 0 : return expression_node<T>::ndb_t::compute_node_depth(branch_);
18854 : }
18855 :
18856 : private:
18857 :
18858 : bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete;
18859 : bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete;
18860 :
18861 : branch_t branch_;
18862 : };
18863 :
18864 : template <typename T>
18865 2067140 : inline bool is_vov_node(const expression_node<T>* node)
18866 : {
18867 2067140 : return (0 != dynamic_cast<const vov_base_node<T>*>(node));
18868 : }
18869 :
18870 : template <typename T>
18871 1811130 : inline bool is_cov_node(const expression_node<T>* node)
18872 : {
18873 1811130 : return (0 != dynamic_cast<const cov_base_node<T>*>(node));
18874 : }
18875 :
18876 : template <typename T>
18877 1575481 : inline bool is_voc_node(const expression_node<T>* node)
18878 : {
18879 1575481 : return (0 != dynamic_cast<const voc_base_node<T>*>(node));
18880 : }
18881 :
18882 : template <typename T>
18883 708392 : inline bool is_cob_node(const expression_node<T>* node)
18884 : {
18885 708392 : return (0 != dynamic_cast<const cob_base_node<T>*>(node));
18886 : }
18887 :
18888 : template <typename T>
18889 764293 : inline bool is_boc_node(const expression_node<T>* node)
18890 : {
18891 764293 : return (0 != dynamic_cast<const boc_base_node<T>*>(node));
18892 : }
18893 :
18894 : template <typename T>
18895 1380548 : inline bool is_t0ot1ot2_node(const expression_node<T>* node)
18896 : {
18897 1380548 : return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
18898 : }
18899 :
18900 : template <typename T>
18901 1034311 : inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
18902 : {
18903 1034311 : return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
18904 : }
18905 :
18906 : template <typename T>
18907 1625928 : inline bool is_uv_node(const expression_node<T>* node)
18908 : {
18909 1625928 : return (0 != dynamic_cast<const uv_base_node<T>*>(node));
18910 : }
18911 :
18912 : template <typename T>
18913 7675757 : inline bool is_string_node(const expression_node<T>* node)
18914 : {
18915 7675757 : return node && (expression_node<T>::e_stringvar == node->type());
18916 : }
18917 :
18918 : template <typename T>
18919 1482567 : inline bool is_string_range_node(const expression_node<T>* node)
18920 : {
18921 1482567 : return node && (expression_node<T>::e_stringvarrng == node->type());
18922 : }
18923 :
18924 : template <typename T>
18925 1472591 : inline bool is_const_string_node(const expression_node<T>* node)
18926 : {
18927 1472591 : return node && (expression_node<T>::e_stringconst == node->type());
18928 : }
18929 :
18930 : template <typename T>
18931 1471446 : inline bool is_const_string_range_node(const expression_node<T>* node)
18932 : {
18933 1471446 : return node && (expression_node<T>::e_cstringvarrng == node->type());
18934 : }
18935 :
18936 : template <typename T>
18937 90644 : inline bool is_string_assignment_node(const expression_node<T>* node)
18938 : {
18939 90644 : return node && (expression_node<T>::e_strass == node->type());
18940 : }
18941 :
18942 : template <typename T>
18943 89044 : inline bool is_string_concat_node(const expression_node<T>* node)
18944 : {
18945 89044 : return node && (expression_node<T>::e_strconcat == node->type());
18946 : }
18947 :
18948 : template <typename T>
18949 86388 : inline bool is_string_function_node(const expression_node<T>* node)
18950 : {
18951 86388 : return node && (expression_node<T>::e_strfunction == node->type());
18952 : }
18953 :
18954 : template <typename T>
18955 86358 : inline bool is_string_condition_node(const expression_node<T>* node)
18956 : {
18957 86358 : return node && (expression_node<T>::e_strcondition == node->type());
18958 : }
18959 :
18960 : template <typename T>
18961 85252 : inline bool is_string_ccondition_node(const expression_node<T>* node)
18962 : {
18963 85252 : return node && (expression_node<T>::e_strccondition == node->type());
18964 : }
18965 :
18966 : template <typename T>
18967 85252 : inline bool is_string_vararg_node(const expression_node<T>* node)
18968 : {
18969 85252 : return node && (expression_node<T>::e_stringvararg == node->type());
18970 : }
18971 :
18972 : template <typename T>
18973 90344 : inline bool is_genricstring_range_node(const expression_node<T>* node)
18974 : {
18975 90344 : return node && (expression_node<T>::e_strgenrange == node->type());
18976 : }
18977 :
18978 : template <typename T>
18979 27749271 : inline bool is_generally_string_node(const expression_node<T>* node)
18980 : {
18981 27749271 : if (node)
18982 : {
18983 27747819 : switch (node->type())
18984 : {
18985 566229 : case expression_node<T>::e_stringvar :
18986 : case expression_node<T>::e_stringconst :
18987 : case expression_node<T>::e_stringvarrng :
18988 : case expression_node<T>::e_cstringvarrng :
18989 : case expression_node<T>::e_strgenrange :
18990 : case expression_node<T>::e_strass :
18991 : case expression_node<T>::e_strconcat :
18992 : case expression_node<T>::e_strfunction :
18993 : case expression_node<T>::e_strcondition :
18994 : case expression_node<T>::e_strccondition :
18995 566229 : case expression_node<T>::e_stringvararg : return true;
18996 27181590 : default : return false;
18997 : }
18998 : }
18999 :
19000 1452 : return false;
19001 : }
19002 :
19003 : class node_allocator
19004 : {
19005 : public:
19006 :
19007 : template <typename ResultNode, typename OpType, typename ExprNode>
19008 100770 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
19009 : {
19010 : expression_node<typename ResultNode::value_type>* result =
19011 100770 : allocate<ResultNode>(operation, branch[0]);
19012 100770 : result->node_depth();
19013 100770 : return result;
19014 : }
19015 :
19016 : template <typename ResultNode, typename OpType, typename ExprNode>
19017 521344 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
19018 : {
19019 : expression_node<typename ResultNode::value_type>* result =
19020 521344 : allocate<ResultNode>(operation, branch[0], branch[1]);
19021 521344 : result->node_depth();
19022 521344 : return result;
19023 : }
19024 :
19025 : template <typename ResultNode, typename OpType, typename ExprNode>
19026 836 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
19027 : {
19028 : expression_node<typename ResultNode::value_type>* result =
19029 836 : allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
19030 836 : result->node_depth();
19031 836 : return result;
19032 : }
19033 :
19034 : template <typename ResultNode, typename OpType, typename ExprNode>
19035 815 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
19036 : {
19037 : expression_node<typename ResultNode::value_type>* result =
19038 815 : allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
19039 815 : result->node_depth();
19040 815 : return result;
19041 : }
19042 :
19043 : template <typename ResultNode, typename OpType, typename ExprNode>
19044 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
19045 : {
19046 : expression_node<typename ResultNode::value_type>* result =
19047 : allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
19048 : result->node_depth();
19049 : return result;
19050 : }
19051 :
19052 : template <typename ResultNode, typename OpType, typename ExprNode>
19053 : inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
19054 : {
19055 : expression_node<typename ResultNode::value_type>* result =
19056 : allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
19057 : result->node_depth();
19058 : return result;
19059 : }
19060 :
19061 : template <typename node_type>
19062 795 : inline expression_node<typename node_type::value_type>* allocate() const
19063 : {
19064 795 : return (new node_type());
19065 : }
19066 :
19067 : template <typename node_type,
19068 : typename Type,
19069 : typename Allocator,
19070 : template <typename, typename> class Sequence>
19071 52875 : inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
19072 : {
19073 : expression_node<typename node_type::value_type>*
19074 52875 : result = (new node_type(seq));
19075 52875 : result->node_depth();
19076 52875 : return result;
19077 : }
19078 :
19079 : template <typename node_type, typename T1>
19080 2524608 : inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
19081 : {
19082 : expression_node<typename node_type::value_type>*
19083 2524608 : result = (new node_type(t1));
19084 2524608 : result->node_depth();
19085 2524608 : return result;
19086 : }
19087 :
19088 : template <typename node_type, typename T1>
19089 5643 : inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
19090 : {
19091 : expression_node<typename node_type::value_type>*
19092 5643 : result = (new node_type(t1));
19093 5643 : result->node_depth();
19094 5643 : return result;
19095 : }
19096 :
19097 : template <typename node_type,
19098 : typename T1, typename T2>
19099 514916 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
19100 : {
19101 : expression_node<typename node_type::value_type>*
19102 514916 : result = (new node_type(t1, t2));
19103 514916 : result->node_depth();
19104 514916 : return result;
19105 : }
19106 :
19107 : template <typename node_type,
19108 : typename T1, typename T2>
19109 739000 : inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
19110 : {
19111 : expression_node<typename node_type::value_type>*
19112 739000 : result = (new node_type(t1, t2));
19113 739000 : result->node_depth();
19114 739000 : return result;
19115 : }
19116 :
19117 : template <typename node_type,
19118 : typename T1, typename T2>
19119 322750 : inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
19120 : {
19121 : expression_node<typename node_type::value_type>*
19122 322750 : result = (new node_type(t1, t2));
19123 322750 : result->node_depth();
19124 322750 : return result;
19125 : }
19126 :
19127 : template <typename node_type,
19128 : typename T1, typename T2>
19129 288264 : inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
19130 : {
19131 : expression_node<typename node_type::value_type>*
19132 288264 : result = (new node_type(t1, t2));
19133 288264 : result->node_depth();
19134 288264 : return result;
19135 : }
19136 :
19137 : template <typename node_type,
19138 : typename T1, typename T2>
19139 121349 : inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
19140 : {
19141 : expression_node<typename node_type::value_type>*
19142 121349 : result = (new node_type(t1, t2));
19143 121349 : result->node_depth();
19144 121349 : return result;
19145 : }
19146 :
19147 : template <typename node_type,
19148 : typename T1, typename T2, typename T3>
19149 12096 : inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
19150 : {
19151 : expression_node<typename node_type::value_type>*
19152 12096 : result = (new node_type(t1, t2, t3));
19153 12096 : result->node_depth();
19154 12096 : return result;
19155 : }
19156 :
19157 : template <typename node_type,
19158 : typename T1, typename T2, typename T3, typename T4>
19159 3355 : inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
19160 : {
19161 : expression_node<typename node_type::value_type>*
19162 3355 : result = (new node_type(t1, t2, t3, t4));
19163 3355 : result->node_depth();
19164 3355 : return result;
19165 : }
19166 :
19167 : template <typename node_type,
19168 : typename T1, typename T2, typename T3>
19169 29201 : inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
19170 : {
19171 : expression_node<typename node_type::value_type>*
19172 29201 : result = (new node_type(t1, t2, t3));
19173 29201 : result->node_depth();
19174 29201 : return result;
19175 : }
19176 :
19177 : template <typename node_type,
19178 : typename T1, typename T2, typename T3, typename T4>
19179 1594 : inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
19180 : {
19181 : expression_node<typename node_type::value_type>*
19182 1594 : result = (new node_type(t1, t2, t3, t4));
19183 1594 : result->node_depth();
19184 1594 : return result;
19185 : }
19186 :
19187 : template <typename node_type,
19188 : typename T1, typename T2, typename T3, typename T4, typename T5>
19189 620 : inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
19190 : {
19191 : expression_node<typename node_type::value_type>*
19192 620 : result = (new node_type(t1, t2, t3, t4, t5));
19193 620 : result->node_depth();
19194 620 : return result;
19195 : }
19196 :
19197 : template <typename node_type,
19198 : typename T1, typename T2, typename T3>
19199 543888 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19200 : const T3& t3) const
19201 : {
19202 : expression_node<typename node_type::value_type>*
19203 543888 : result = (new node_type(t1, t2, t3));
19204 543888 : result->node_depth();
19205 543888 : return result;
19206 : }
19207 :
19208 : template <typename node_type,
19209 : typename T1, typename T2,
19210 : typename T3, typename T4>
19211 20267 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19212 : const T3& t3, const T4& t4) const
19213 : {
19214 : expression_node<typename node_type::value_type>*
19215 20267 : result = (new node_type(t1, t2, t3, t4));
19216 20267 : result->node_depth();
19217 20267 : return result;
19218 : }
19219 :
19220 : template <typename node_type,
19221 : typename T1, typename T2,
19222 : typename T3, typename T4, typename T5>
19223 815 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19224 : const T3& t3, const T4& t4,
19225 : const T5& t5) const
19226 : {
19227 : expression_node<typename node_type::value_type>*
19228 815 : result = (new node_type(t1, t2, t3, t4, t5));
19229 815 : result->node_depth();
19230 815 : return result;
19231 : }
19232 :
19233 : template <typename node_type,
19234 : typename T1, typename T2,
19235 : typename T3, typename T4, typename T5, typename T6>
19236 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19237 : const T3& t3, const T4& t4,
19238 : const T5& t5, const T6& t6) const
19239 : {
19240 : expression_node<typename node_type::value_type>*
19241 : result = (new node_type(t1, t2, t3, t4, t5, t6));
19242 : result->node_depth();
19243 : return result;
19244 : }
19245 :
19246 : template <typename node_type,
19247 : typename T1, typename T2,
19248 : typename T3, typename T4,
19249 : typename T5, typename T6, typename T7>
19250 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19251 : const T3& t3, const T4& t4,
19252 : const T5& t5, const T6& t6,
19253 : const T7& t7) const
19254 : {
19255 : expression_node<typename node_type::value_type>*
19256 : result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
19257 : result->node_depth();
19258 : return result;
19259 : }
19260 :
19261 : template <typename node_type,
19262 : typename T1, typename T2,
19263 : typename T3, typename T4,
19264 : typename T5, typename T6,
19265 : typename T7, typename T8>
19266 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19267 : const T3& t3, const T4& t4,
19268 : const T5& t5, const T6& t6,
19269 : const T7& t7, const T8& t8) const
19270 : {
19271 : expression_node<typename node_type::value_type>*
19272 : result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
19273 : result->node_depth();
19274 : return result;
19275 : }
19276 :
19277 : template <typename node_type,
19278 : typename T1, typename T2,
19279 : typename T3, typename T4,
19280 : typename T5, typename T6,
19281 : typename T7, typename T8, typename T9>
19282 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19283 : const T3& t3, const T4& t4,
19284 : const T5& t5, const T6& t6,
19285 : const T7& t7, const T8& t8,
19286 : const T9& t9) const
19287 : {
19288 : expression_node<typename node_type::value_type>*
19289 : result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
19290 : result->node_depth();
19291 : return result;
19292 : }
19293 :
19294 : template <typename node_type,
19295 : typename T1, typename T2,
19296 : typename T3, typename T4,
19297 : typename T5, typename T6,
19298 : typename T7, typename T8,
19299 : typename T9, typename T10>
19300 : inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
19301 : const T3& t3, const T4& t4,
19302 : const T5& t5, const T6& t6,
19303 : const T7& t7, const T8& t8,
19304 : const T9& t9, const T10& t10) const
19305 : {
19306 : expression_node<typename node_type::value_type>*
19307 : result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
19308 : result->node_depth();
19309 : return result;
19310 : }
19311 :
19312 : template <typename node_type,
19313 : typename T1, typename T2, typename T3>
19314 371380 : inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
19315 : {
19316 : expression_node<typename node_type::value_type>*
19317 371380 : result = (new node_type(t1, t2, t3));
19318 371380 : result->node_depth();
19319 371380 : return result;
19320 : }
19321 :
19322 : template <typename node_type,
19323 : typename T1, typename T2,
19324 : typename T3, typename T4>
19325 97884 : inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
19326 : T3 t3, T4 t4) const
19327 : {
19328 : expression_node<typename node_type::value_type>*
19329 97884 : result = (new node_type(t1, t2, t3, t4));
19330 97884 : result->node_depth();
19331 97884 : return result;
19332 : }
19333 :
19334 : template <typename node_type,
19335 : typename T1, typename T2,
19336 : typename T3, typename T4,
19337 : typename T5>
19338 5960 : inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
19339 : T3 t3, T4 t4,
19340 : T5 t5) const
19341 : {
19342 : expression_node<typename node_type::value_type>*
19343 5960 : result = (new node_type(t1, t2, t3, t4, t5));
19344 5960 : result->node_depth();
19345 5960 : return result;
19346 : }
19347 :
19348 : template <typename node_type,
19349 : typename T1, typename T2,
19350 : typename T3, typename T4,
19351 : typename T5, typename T6>
19352 : inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
19353 : T3 t3, T4 t4,
19354 : T5 t5, T6 t6) const
19355 : {
19356 : expression_node<typename node_type::value_type>*
19357 : result = (new node_type(t1, t2, t3, t4, t5, t6));
19358 : result->node_depth();
19359 : return result;
19360 : }
19361 :
19362 : template <typename node_type,
19363 : typename T1, typename T2,
19364 : typename T3, typename T4,
19365 : typename T5, typename T6, typename T7>
19366 6917 : inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
19367 : T3 t3, T4 t4,
19368 : T5 t5, T6 t6,
19369 : T7 t7) const
19370 : {
19371 : expression_node<typename node_type::value_type>*
19372 6917 : result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
19373 6917 : result->node_depth();
19374 6917 : return result;
19375 : }
19376 :
19377 : template <typename T>
19378 1 : void inline free(expression_node<T>*& e) const
19379 : {
19380 : exprtk_debug(("node_allocator::free() - deleting expression_node "
19381 : "type: %03d addr: %p\n",
19382 : static_cast<int>(e->type()),
19383 : reinterpret_cast<void*>(e)));
19384 1 : delete e;
19385 1 : e = 0;
19386 1 : }
19387 : };
19388 :
19389 108660 : inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
19390 : {
19391 : #define register_op(Symbol, Type, Args) \
19392 : m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
19393 :
19394 217320 : register_op("abs" , e_abs , 1)
19395 217320 : register_op("acos" , e_acos , 1)
19396 217320 : register_op("acosh" , e_acosh , 1)
19397 217320 : register_op("asin" , e_asin , 1)
19398 217320 : register_op("asinh" , e_asinh , 1)
19399 217320 : register_op("atan" , e_atan , 1)
19400 217320 : register_op("atanh" , e_atanh , 1)
19401 217320 : register_op("ceil" , e_ceil , 1)
19402 217320 : register_op("cos" , e_cos , 1)
19403 217320 : register_op("cosh" , e_cosh , 1)
19404 217320 : register_op("exp" , e_exp , 1)
19405 217320 : register_op("expm1" , e_expm1 , 1)
19406 217320 : register_op("floor" , e_floor , 1)
19407 217320 : register_op("log" , e_log , 1)
19408 217320 : register_op("log10" , e_log10 , 1)
19409 217320 : register_op("log2" , e_log2 , 1)
19410 217320 : register_op("log1p" , e_log1p , 1)
19411 217320 : register_op("round" , e_round , 1)
19412 217320 : register_op("sin" , e_sin , 1)
19413 217320 : register_op("sinc" , e_sinc , 1)
19414 217320 : register_op("sinh" , e_sinh , 1)
19415 217320 : register_op("sec" , e_sec , 1)
19416 217320 : register_op("csc" , e_csc , 1)
19417 217320 : register_op("sqrt" , e_sqrt , 1)
19418 217320 : register_op("tan" , e_tan , 1)
19419 217320 : register_op("tanh" , e_tanh , 1)
19420 217320 : register_op("cot" , e_cot , 1)
19421 217320 : register_op("rad2deg" , e_r2d , 1)
19422 217320 : register_op("deg2rad" , e_d2r , 1)
19423 217320 : register_op("deg2grad" , e_d2g , 1)
19424 217320 : register_op("grad2deg" , e_g2d , 1)
19425 217320 : register_op("sgn" , e_sgn , 1)
19426 217320 : register_op("not" , e_notl , 1)
19427 217320 : register_op("erf" , e_erf , 1)
19428 217320 : register_op("erfc" , e_erfc , 1)
19429 217320 : register_op("ncdf" , e_ncdf , 1)
19430 217320 : register_op("frac" , e_frac , 1)
19431 217320 : register_op("trunc" , e_trunc , 1)
19432 217320 : register_op("atan2" , e_atan2 , 2)
19433 217320 : register_op("mod" , e_mod , 2)
19434 217320 : register_op("logn" , e_logn , 2)
19435 217320 : register_op("pow" , e_pow , 2)
19436 217320 : register_op("root" , e_root , 2)
19437 217320 : register_op("roundn" , e_roundn , 2)
19438 217320 : register_op("equal" , e_equal , 2)
19439 217320 : register_op("not_equal" , e_nequal , 2)
19440 217320 : register_op("hypot" , e_hypot , 2)
19441 217320 : register_op("shr" , e_shr , 2)
19442 217320 : register_op("shl" , e_shl , 2)
19443 217320 : register_op("clamp" , e_clamp , 3)
19444 217320 : register_op("iclamp" , e_iclamp , 3)
19445 217320 : register_op("inrange" , e_inrange , 3)
19446 : #undef register_op
19447 108660 : }
19448 :
19449 : } // namespace details
19450 :
19451 : class function_traits
19452 : {
19453 : public:
19454 :
19455 132070 : function_traits()
19456 132070 : : allow_zero_parameters_(false)
19457 132070 : , has_side_effects_(true)
19458 132070 : , min_num_args_(0)
19459 132070 : , max_num_args_(std::numeric_limits<std::size_t>::max())
19460 132070 : {}
19461 :
19462 79 : inline bool& allow_zero_parameters()
19463 : {
19464 79 : return allow_zero_parameters_;
19465 : }
19466 :
19467 135153 : inline bool& has_side_effects()
19468 : {
19469 135153 : return has_side_effects_;
19470 : }
19471 :
19472 115 : std::size_t& min_num_args()
19473 : {
19474 115 : return min_num_args_;
19475 : }
19476 :
19477 51 : std::size_t& max_num_args()
19478 : {
19479 51 : return max_num_args_;
19480 : }
19481 :
19482 : private:
19483 :
19484 : bool allow_zero_parameters_;
19485 : bool has_side_effects_;
19486 : std::size_t min_num_args_;
19487 : std::size_t max_num_args_;
19488 : };
19489 :
19490 : template <typename FunctionType>
19491 62 : void enable_zero_parameters(FunctionType& func)
19492 : {
19493 62 : func.allow_zero_parameters() = true;
19494 :
19495 62 : if (0 != func.min_num_args())
19496 : {
19497 0 : func.min_num_args() = 0;
19498 : }
19499 62 : }
19500 :
19501 : template <typename FunctionType>
19502 : void disable_zero_parameters(FunctionType& func)
19503 : {
19504 : func.allow_zero_parameters() = false;
19505 : }
19506 :
19507 : template <typename FunctionType>
19508 : void enable_has_side_effects(FunctionType& func)
19509 : {
19510 : func.has_side_effects() = true;
19511 : }
19512 :
19513 : template <typename FunctionType>
19514 128736 : void disable_has_side_effects(FunctionType& func)
19515 : {
19516 128736 : func.has_side_effects() = false;
19517 128736 : }
19518 :
19519 : template <typename FunctionType>
19520 2 : void set_min_num_args(FunctionType& func, const std::size_t& num_args)
19521 : {
19522 2 : func.min_num_args() = num_args;
19523 :
19524 2 : if ((0 != func.min_num_args()) && func.allow_zero_parameters())
19525 0 : func.allow_zero_parameters() = false;
19526 2 : }
19527 :
19528 : template <typename FunctionType>
19529 2 : void set_max_num_args(FunctionType& func, const std::size_t& num_args)
19530 : {
19531 2 : func.max_num_args() = num_args;
19532 2 : }
19533 :
19534 : template <typename T>
19535 : class ifunction : public function_traits
19536 : {
19537 : public:
19538 :
19539 131097 : explicit ifunction(const std::size_t& pc)
19540 131097 : : param_count(pc)
19541 131097 : {}
19542 :
19543 131097 : virtual ~ifunction()
19544 131097 : {}
19545 :
19546 : #define empty_method_body(N) \
19547 : { \
19548 : exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
19549 : return std::numeric_limits<T>::quiet_NaN(); \
19550 : } \
19551 :
19552 0 : inline virtual T operator() ()
19553 0 : empty_method_body(0)
19554 :
19555 0 : inline virtual T operator() (const T&)
19556 0 : empty_method_body(1)
19557 :
19558 0 : inline virtual T operator() (const T&,const T&)
19559 0 : empty_method_body(2)
19560 :
19561 0 : inline virtual T operator() (const T&, const T&, const T&)
19562 0 : empty_method_body(3)
19563 :
19564 0 : inline virtual T operator() (const T&, const T&, const T&, const T&)
19565 0 : empty_method_body(4)
19566 :
19567 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
19568 0 : empty_method_body(5)
19569 :
19570 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
19571 0 : empty_method_body(6)
19572 :
19573 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19574 0 : empty_method_body(7)
19575 :
19576 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19577 0 : empty_method_body(8)
19578 :
19579 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19580 0 : empty_method_body(9)
19581 :
19582 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19583 0 : empty_method_body(10)
19584 :
19585 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19586 : const T&)
19587 0 : empty_method_body(11)
19588 :
19589 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19590 : const T&, const T&)
19591 0 : empty_method_body(12)
19592 :
19593 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19594 : const T&, const T&, const T&)
19595 0 : empty_method_body(13)
19596 :
19597 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19598 : const T&, const T&, const T&, const T&)
19599 0 : empty_method_body(14)
19600 :
19601 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19602 : const T&, const T&, const T&, const T&, const T&)
19603 0 : empty_method_body(15)
19604 :
19605 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19606 : const T&, const T&, const T&, const T&, const T&, const T&)
19607 0 : empty_method_body(16)
19608 :
19609 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19610 : const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19611 0 : empty_method_body(17)
19612 :
19613 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19614 : const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19615 0 : empty_method_body(18)
19616 :
19617 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19618 : const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19619 0 : empty_method_body(19)
19620 :
19621 0 : inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
19622 : const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
19623 0 : empty_method_body(20)
19624 :
19625 : #undef empty_method_body
19626 :
19627 : std::size_t param_count;
19628 : };
19629 :
19630 : template <typename T>
19631 : class ivararg_function : public function_traits
19632 : {
19633 : public:
19634 :
19635 2 : virtual ~ivararg_function()
19636 2 : {}
19637 :
19638 0 : inline virtual T operator() (const std::vector<T>&)
19639 : {
19640 : exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
19641 0 : return std::numeric_limits<T>::quiet_NaN();
19642 : }
19643 : };
19644 :
19645 : template <typename T>
19646 : class igeneric_function : public function_traits
19647 : {
19648 : public:
19649 :
19650 : enum return_type
19651 : {
19652 : e_rtrn_scalar = 0,
19653 : e_rtrn_string = 1,
19654 : e_rtrn_overload = 2
19655 : };
19656 :
19657 : typedef T type;
19658 : typedef type_store<T> generic_type;
19659 : typedef typename generic_type::parameter_list parameter_list_t;
19660 :
19661 971 : explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
19662 971 : : parameter_sequence(param_seq)
19663 971 : , rtrn_type(rtr_type)
19664 971 : {}
19665 :
19666 971 : virtual ~igeneric_function()
19667 971 : {}
19668 :
19669 : #define igeneric_function_empty_body(N) \
19670 : { \
19671 : exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
19672 : return std::numeric_limits<T>::quiet_NaN(); \
19673 : } \
19674 :
19675 : // f(i_0,i_1,....,i_N) --> Scalar
19676 0 : inline virtual T operator() (parameter_list_t)
19677 0 : igeneric_function_empty_body(1)
19678 :
19679 : // f(i_0,i_1,....,i_N) --> String
19680 0 : inline virtual T operator() (std::string&, parameter_list_t)
19681 0 : igeneric_function_empty_body(2)
19682 :
19683 : // f(psi,i_0,i_1,....,i_N) --> Scalar
19684 0 : inline virtual T operator() (const std::size_t&, parameter_list_t)
19685 0 : igeneric_function_empty_body(3)
19686 :
19687 : // f(psi,i_0,i_1,....,i_N) --> String
19688 0 : inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
19689 0 : igeneric_function_empty_body(4)
19690 :
19691 : #undef igeneric_function_empty_body
19692 :
19693 : std::string parameter_sequence;
19694 : return_type rtrn_type;
19695 : };
19696 :
19697 : #ifndef exprtk_disable_string_capabilities
19698 : template <typename T>
19699 : class stringvar_base
19700 : {
19701 : public:
19702 :
19703 : typedef typename details::stringvar_node<T> stringvar_node_t;
19704 :
19705 : stringvar_base(const std::string& name, stringvar_node_t* svn)
19706 : : name_(name)
19707 : , string_varnode_(svn)
19708 : {}
19709 :
19710 : bool valid() const
19711 : {
19712 : return !name_.empty() && (0 != string_varnode_);
19713 : }
19714 :
19715 : std::string name() const
19716 : {
19717 : assert(string_varnode_);
19718 : return name_;
19719 : }
19720 :
19721 : void rebase(std::string& s)
19722 : {
19723 : assert(string_varnode_);
19724 : string_varnode_->rebase(s);
19725 : }
19726 :
19727 : private:
19728 :
19729 : std::string name_;
19730 : stringvar_node_t* string_varnode_;
19731 : };
19732 : #endif
19733 :
19734 : template <typename T> class parser;
19735 : template <typename T> class expression_helper;
19736 :
19737 : template <typename T>
19738 : class symbol_table
19739 : {
19740 : public:
19741 :
19742 : enum symtab_mutability_type
19743 : {
19744 : e_unknown = 0,
19745 : e_mutable = 1,
19746 : e_immutable = 2
19747 : };
19748 :
19749 : typedef T (*ff00_functor)();
19750 : typedef T (*ff01_functor)(T);
19751 : typedef T (*ff02_functor)(T, T);
19752 : typedef T (*ff03_functor)(T, T, T);
19753 : typedef T (*ff04_functor)(T, T, T, T);
19754 : typedef T (*ff05_functor)(T, T, T, T, T);
19755 : typedef T (*ff06_functor)(T, T, T, T, T, T);
19756 : typedef T (*ff07_functor)(T, T, T, T, T, T, T);
19757 : typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
19758 : typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
19759 : typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
19760 : typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
19761 : typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
19762 : typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
19763 : typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
19764 : typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
19765 :
19766 : protected:
19767 :
19768 : struct freefunc00 exprtk_final : public exprtk::ifunction<T>
19769 : {
19770 : using exprtk::ifunction<T>::operator();
19771 :
19772 : explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
19773 : inline T operator() () exprtk_override
19774 : { return f(); }
19775 : ff00_functor f;
19776 : };
19777 :
19778 : struct freefunc01 exprtk_final : public exprtk::ifunction<T>
19779 : {
19780 : using exprtk::ifunction<T>::operator();
19781 :
19782 102 : explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
19783 0 : inline T operator() (const T& v0) exprtk_override
19784 0 : { return f(v0); }
19785 : ff01_functor f;
19786 : };
19787 :
19788 : struct freefunc02 exprtk_final : public exprtk::ifunction<T>
19789 : {
19790 : using exprtk::ifunction<T>::operator();
19791 :
19792 102 : explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
19793 0 : inline T operator() (const T& v0, const T& v1) exprtk_override
19794 0 : { return f(v0, v1); }
19795 : ff02_functor f;
19796 : };
19797 :
19798 : struct freefunc03 exprtk_final : public exprtk::ifunction<T>
19799 : {
19800 : using exprtk::ifunction<T>::operator();
19801 :
19802 102 : explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
19803 0 : inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override
19804 0 : { return f(v0, v1, v2); }
19805 : ff03_functor f;
19806 : };
19807 :
19808 : struct freefunc04 exprtk_final : public exprtk::ifunction<T>
19809 : {
19810 : using exprtk::ifunction<T>::operator();
19811 :
19812 102 : explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
19813 0 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override
19814 0 : { return f(v0, v1, v2, v3); }
19815 : ff04_functor f;
19816 : };
19817 :
19818 : struct freefunc05 : public exprtk::ifunction<T>
19819 : {
19820 : using exprtk::ifunction<T>::operator();
19821 :
19822 102 : explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
19823 0 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override
19824 0 : { return f(v0, v1, v2, v3, v4); }
19825 : ff05_functor f;
19826 : };
19827 :
19828 : struct freefunc06 exprtk_final : public exprtk::ifunction<T>
19829 : {
19830 : using exprtk::ifunction<T>::operator();
19831 :
19832 102 : explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
19833 0 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override
19834 0 : { return f(v0, v1, v2, v3, v4, v5); }
19835 : ff06_functor f;
19836 : };
19837 :
19838 : struct freefunc07 exprtk_final : public exprtk::ifunction<T>
19839 : {
19840 : using exprtk::ifunction<T>::operator();
19841 :
19842 : explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
19843 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
19844 : const T& v5, const T& v6) exprtk_override
19845 : { return f(v0, v1, v2, v3, v4, v5, v6); }
19846 : ff07_functor f;
19847 : };
19848 :
19849 : struct freefunc08 exprtk_final : public exprtk::ifunction<T>
19850 : {
19851 : using exprtk::ifunction<T>::operator();
19852 :
19853 : explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
19854 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
19855 : const T& v5, const T& v6, const T& v7) exprtk_override
19856 : { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
19857 : ff08_functor f;
19858 : };
19859 :
19860 : struct freefunc09 exprtk_final : public exprtk::ifunction<T>
19861 : {
19862 : using exprtk::ifunction<T>::operator();
19863 :
19864 : explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
19865 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
19866 : const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override
19867 : { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
19868 : ff09_functor f;
19869 : };
19870 :
19871 : struct freefunc10 exprtk_final : public exprtk::ifunction<T>
19872 : {
19873 : using exprtk::ifunction<T>::operator();
19874 :
19875 : explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
19876 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
19877 : const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override
19878 : { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
19879 : ff10_functor f;
19880 : };
19881 :
19882 : struct freefunc11 exprtk_final : public exprtk::ifunction<T>
19883 : {
19884 : using exprtk::ifunction<T>::operator();
19885 :
19886 : explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
19887 : inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
19888 : const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override
19889 : { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
19890 : ff11_functor f;
19891 : };
19892 :
19893 : struct freefunc12 exprtk_final : public exprtk::ifunction<T>
19894 : {
19895 : using exprtk::ifunction<T>::operator();
19896 :
19897 : explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
19898 : inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
19899 : const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
19900 : const T& v10, const T& v11) exprtk_override
19901 : { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
19902 : ff12_functor f;
19903 : };
19904 :
19905 : struct freefunc13 exprtk_final : public exprtk::ifunction<T>
19906 : {
19907 : using exprtk::ifunction<T>::operator();
19908 :
19909 : explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
19910 : inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
19911 : const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
19912 : const T& v10, const T& v11, const T& v12) exprtk_override
19913 : { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
19914 : ff13_functor f;
19915 : };
19916 :
19917 : struct freefunc14 exprtk_final : public exprtk::ifunction<T>
19918 : {
19919 : using exprtk::ifunction<T>::operator();
19920 :
19921 : explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
19922 : inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
19923 : const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
19924 : const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override
19925 : { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
19926 : ff14_functor f;
19927 : };
19928 :
19929 : struct freefunc15 exprtk_final : public exprtk::ifunction<T>
19930 : {
19931 : using exprtk::ifunction<T>::operator();
19932 :
19933 : explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
19934 : inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
19935 : const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
19936 : const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override
19937 : { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
19938 : ff15_functor f;
19939 : };
19940 :
19941 : template <typename Type, typename RawType>
19942 : struct type_store
19943 : {
19944 : typedef details::expression_node<T>* expression_ptr;
19945 : typedef typename details::variable_node<T> variable_node_t;
19946 : typedef ifunction<T> ifunction_t;
19947 : typedef ivararg_function<T> ivararg_function_t;
19948 : typedef igeneric_function<T> igeneric_function_t;
19949 : typedef details::vector_holder<T> vector_t;
19950 : #ifndef exprtk_disable_string_capabilities
19951 : typedef typename details::stringvar_node<T> stringvar_node_t;
19952 : #endif
19953 :
19954 : typedef Type type_t;
19955 : typedef type_t* type_ptr;
19956 : typedef std::pair<bool,type_ptr> type_pair_t;
19957 : typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
19958 : typedef typename type_map_t::iterator tm_itr_t;
19959 : typedef typename type_map_t::const_iterator tm_const_itr_t;
19960 :
19961 : enum { lut_size = 256 };
19962 :
19963 : type_map_t map;
19964 : std::size_t size;
19965 :
19966 669048 : type_store()
19967 669048 : : size(0)
19968 669048 : {}
19969 :
19970 : struct deleter
19971 : {
19972 : #define exprtk_define_process(Type) \
19973 : static inline void process(std::pair<bool,Type*>& n) \
19974 : { \
19975 : delete n.second; \
19976 : } \
19977 :
19978 443835 : exprtk_define_process(variable_node_t )
19979 6422 : exprtk_define_process(vector_t )
19980 : #ifndef exprtk_disable_string_capabilities
19981 122310 : exprtk_define_process(stringvar_node_t)
19982 : #endif
19983 :
19984 : #undef exprtk_define_process
19985 :
19986 : template <typename DeleteType>
19987 143012 : static inline void process(std::pair<bool,DeleteType*>&)
19988 143012 : {}
19989 : };
19990 :
19991 3963156 : inline bool symbol_exists(const std::string& symbol_name) const
19992 : {
19993 3963156 : if (symbol_name.empty())
19994 0 : return false;
19995 3963156 : else if (map.end() != map.find(symbol_name))
19996 205027 : return true;
19997 : else
19998 3758129 : return false;
19999 : }
20000 :
20001 : template <typename PtrType>
20002 4 : inline std::string entity_name(const PtrType& ptr) const
20003 : {
20004 4 : if (map.empty())
20005 0 : return std::string();
20006 :
20007 4 : tm_const_itr_t itr = map.begin();
20008 :
20009 7 : while (map.end() != itr)
20010 : {
20011 7 : if (itr->second.second == ptr)
20012 : {
20013 4 : return itr->first;
20014 : }
20015 : else
20016 3 : ++itr;
20017 : }
20018 :
20019 0 : return std::string();
20020 : }
20021 :
20022 1956071 : inline bool is_constant(const std::string& symbol_name) const
20023 : {
20024 1956071 : if (symbol_name.empty())
20025 0 : return false;
20026 : else
20027 : {
20028 1956071 : const tm_const_itr_t itr = map.find(symbol_name);
20029 :
20030 1956071 : if (map.end() == itr)
20031 102929 : return false;
20032 : else
20033 1853142 : return (*itr).second.first;
20034 : }
20035 : }
20036 :
20037 : template <typename Tie, typename RType>
20038 6422 : inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
20039 : {
20040 6422 : if (symbol_name.size() > 1)
20041 : {
20042 208800 : for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
20043 : {
20044 206480 : if (details::imatch(symbol_name, details::reserved_symbols[i]))
20045 : {
20046 0 : return false;
20047 : }
20048 : }
20049 : }
20050 :
20051 6422 : const tm_itr_t itr = map.find(symbol_name);
20052 :
20053 6422 : if (map.end() == itr)
20054 : {
20055 6422 : map[symbol_name] = Tie::make(t,is_const);
20056 6422 : ++size;
20057 : }
20058 :
20059 6422 : return true;
20060 : }
20061 :
20062 : struct tie_array
20063 : {
20064 2143 : static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
20065 : {
20066 2143 : return std::make_pair(is_const, new vector_t(v.first, v.second));
20067 : }
20068 : };
20069 :
20070 : struct tie_stdvec
20071 : {
20072 : template <typename Allocator>
20073 84 : static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
20074 : {
20075 84 : return std::make_pair(is_const, new vector_t(v));
20076 : }
20077 : };
20078 :
20079 : struct tie_vecview
20080 : {
20081 4195 : static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
20082 : {
20083 4195 : return std::make_pair(is_const, new vector_t(v));
20084 : }
20085 : };
20086 :
20087 : struct tie_stddeq
20088 : {
20089 : template <typename Allocator>
20090 : static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
20091 : {
20092 : return std::make_pair(is_const, new vector_t(v));
20093 : }
20094 : };
20095 :
20096 : template <std::size_t v_size>
20097 2143 : inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
20098 : {
20099 : return add_impl<tie_array,std::pair<T*,std::size_t> >
20100 2143 : (symbol_name, std::make_pair(v,v_size), is_const);
20101 : }
20102 :
20103 0 : inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
20104 : {
20105 : return add_impl<tie_array,std::pair<T*,std::size_t> >
20106 0 : (symbol_name, std::make_pair(v,v_size), is_const);
20107 : }
20108 :
20109 : template <typename Allocator>
20110 84 : inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
20111 : {
20112 : return add_impl<tie_stdvec,std::vector<T,Allocator>&>
20113 84 : (symbol_name, v, is_const);
20114 : }
20115 :
20116 4195 : inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
20117 : {
20118 : return add_impl<tie_vecview,exprtk::vector_view<T>&>
20119 4195 : (symbol_name, v, is_const);
20120 : }
20121 :
20122 : template <typename Allocator>
20123 : inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
20124 : {
20125 : return add_impl<tie_stddeq,std::deque<T,Allocator>&>
20126 : (symbol_name, v, is_const);
20127 : }
20128 :
20129 710193 : inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false)
20130 : {
20131 : struct tie
20132 : {
20133 443835 : static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false)
20134 : {
20135 443835 : return std::make_pair(is_constant, new variable_node_t(t));
20136 : }
20137 :
20138 : #ifndef exprtk_disable_string_capabilities
20139 122310 : static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false)
20140 : {
20141 122310 : return std::make_pair(is_constant, new stringvar_node_t(t));
20142 : }
20143 : #endif
20144 :
20145 143011 : static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
20146 : {
20147 143011 : return std::make_pair(is_constant,&t);
20148 : }
20149 :
20150 2 : static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
20151 : {
20152 2 : return std::make_pair(is_constant,&t);
20153 : }
20154 :
20155 1035 : static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
20156 : {
20157 1035 : return std::make_pair(is_constant,&t);
20158 : }
20159 : };
20160 :
20161 710193 : const tm_itr_t itr = map.find(symbol_name);
20162 :
20163 710193 : if (map.end() == itr)
20164 : {
20165 710193 : map[symbol_name] = tie::make(t_,is_const);
20166 710193 : ++size;
20167 : }
20168 :
20169 710193 : return true;
20170 : }
20171 :
20172 14450580 : inline type_ptr get(const std::string& symbol_name) const
20173 : {
20174 14450580 : const tm_const_itr_t itr = map.find(symbol_name);
20175 :
20176 14450580 : if (map.end() == itr)
20177 524036 : return reinterpret_cast<type_ptr>(0);
20178 : else
20179 13926544 : return itr->second.second;
20180 : }
20181 :
20182 : template <typename TType, typename TRawType, typename PtrType>
20183 : struct ptr_match
20184 : {
20185 : static inline bool test(const PtrType, const void*)
20186 : {
20187 : return false;
20188 : }
20189 : };
20190 :
20191 : template <typename TType, typename TRawType>
20192 : struct ptr_match<TType,TRawType,variable_node_t*>
20193 : {
20194 960 : static inline bool test(const variable_node_t* p, const void* ptr)
20195 : {
20196 : exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr));
20197 960 : return (&(p->ref()) == ptr);
20198 : }
20199 : };
20200 :
20201 320 : inline type_ptr get_from_varptr(const void* ptr) const
20202 : {
20203 320 : tm_const_itr_t itr = map.begin();
20204 :
20205 1280 : while (map.end() != itr)
20206 : {
20207 960 : type_ptr ret_ptr = itr->second.second;
20208 :
20209 960 : if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
20210 : {
20211 0 : return ret_ptr;
20212 : }
20213 :
20214 960 : ++itr;
20215 : }
20216 :
20217 320 : return type_ptr(0);
20218 : }
20219 :
20220 422 : inline bool remove(const std::string& symbol_name, const bool delete_node = true)
20221 : {
20222 422 : const tm_itr_t itr = map.find(symbol_name);
20223 :
20224 422 : if (map.end() != itr)
20225 : {
20226 411 : if (delete_node)
20227 : {
20228 411 : deleter::process((*itr).second);
20229 : }
20230 :
20231 411 : map.erase(itr);
20232 411 : --size;
20233 :
20234 411 : return true;
20235 : }
20236 : else
20237 11 : return false;
20238 : }
20239 :
20240 : inline RawType& type_ref(const std::string& symbol_name)
20241 : {
20242 : struct init_type
20243 : {
20244 : static inline double set(double) { return (0.0); }
20245 : static inline double set(long double) { return (0.0); }
20246 : static inline float set(float) { return (0.0f); }
20247 : static inline std::string set(std::string) { return std::string(""); }
20248 : };
20249 :
20250 : static RawType null_type = init_type::set(RawType());
20251 :
20252 : const tm_const_itr_t itr = map.find(symbol_name);
20253 :
20254 : if (map.end() == itr)
20255 : return null_type;
20256 : else
20257 : return itr->second.second->ref();
20258 : }
20259 :
20260 749468 : inline void clear(const bool delete_node = true)
20261 : {
20262 749468 : if (!map.empty())
20263 : {
20264 171891 : if (delete_node)
20265 : {
20266 171891 : tm_itr_t itr = map.begin();
20267 171891 : tm_itr_t end = map.end ();
20268 :
20269 887059 : while (end != itr)
20270 : {
20271 715168 : deleter::process((*itr).second);
20272 715168 : ++itr;
20273 : }
20274 : }
20275 :
20276 171891 : map.clear();
20277 : }
20278 :
20279 749468 : size = 0;
20280 749468 : }
20281 :
20282 : template <typename Allocator,
20283 : template <typename, typename> class Sequence>
20284 20 : inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
20285 : {
20286 20 : std::size_t count = 0;
20287 :
20288 20 : if (!map.empty())
20289 : {
20290 20 : tm_const_itr_t itr = map.begin();
20291 20 : tm_const_itr_t end = map.end ();
20292 :
20293 100 : while (end != itr)
20294 : {
20295 80 : list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
20296 80 : ++itr;
20297 80 : ++count;
20298 : }
20299 : }
20300 :
20301 20 : return count;
20302 : }
20303 :
20304 : template <typename Allocator,
20305 : template <typename, typename> class Sequence>
20306 3655 : inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
20307 : {
20308 3655 : std::size_t count = 0;
20309 :
20310 3655 : if (!map.empty())
20311 : {
20312 641 : tm_const_itr_t itr = map.begin();
20313 641 : tm_const_itr_t end = map.end ();
20314 :
20315 2899 : while (end != itr)
20316 : {
20317 2258 : vlist.push_back((*itr).first);
20318 2258 : ++itr;
20319 2258 : ++count;
20320 : }
20321 : }
20322 :
20323 3655 : return count;
20324 : }
20325 : };
20326 :
20327 : typedef details::expression_node<T>* expression_ptr;
20328 : typedef typename details::variable_node<T> variable_t;
20329 : typedef typename details::vector_holder<T> vector_holder_t;
20330 : typedef variable_t* variable_ptr;
20331 : #ifndef exprtk_disable_string_capabilities
20332 : typedef typename details::stringvar_node<T> stringvar_t;
20333 : typedef stringvar_t* stringvar_ptr;
20334 : #endif
20335 : typedef ifunction <T> function_t;
20336 : typedef ivararg_function <T> vararg_function_t;
20337 : typedef igeneric_function<T> generic_function_t;
20338 : typedef function_t* function_ptr;
20339 : typedef vararg_function_t* vararg_function_ptr;
20340 : typedef generic_function_t* generic_function_ptr;
20341 :
20342 : static const std::size_t lut_size = 256;
20343 :
20344 : // Symbol Table Holder
20345 : struct control_block
20346 : {
20347 : struct st_data
20348 : {
20349 : type_store<variable_t , T > variable_store;
20350 : type_store<function_t , function_t > function_store;
20351 : type_store<vararg_function_t , vararg_function_t > vararg_function_store;
20352 : type_store<generic_function_t, generic_function_t> generic_function_store;
20353 : type_store<generic_function_t, generic_function_t> string_function_store;
20354 : type_store<generic_function_t, generic_function_t> overload_function_store;
20355 : type_store<vector_holder_t , vector_holder_t > vector_store;
20356 : #ifndef exprtk_disable_string_capabilities
20357 : type_store<stringvar_t , std::string > stringvar_store;
20358 : #endif
20359 :
20360 83631 : st_data()
20361 83631 : {
20362 2843454 : for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20363 : {
20364 2759823 : reserved_symbol_table_.insert(details::reserved_words[i]);
20365 : }
20366 :
20367 7526790 : for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
20368 : {
20369 7443159 : reserved_symbol_table_.insert(details::reserved_symbols[i]);
20370 : }
20371 83631 : }
20372 :
20373 83631 : ~st_data()
20374 : {
20375 84243 : for (std::size_t i = 0; i < free_function_list_.size(); ++i)
20376 : {
20377 612 : delete free_function_list_[i];
20378 : }
20379 83631 : }
20380 :
20381 17696825 : inline bool is_reserved_symbol(const std::string& symbol) const
20382 : {
20383 17696825 : return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
20384 : }
20385 :
20386 83631 : static inline st_data* create()
20387 : {
20388 83631 : return (new st_data);
20389 : }
20390 :
20391 83631 : static inline void destroy(st_data*& sd)
20392 : {
20393 83631 : delete sd;
20394 83631 : sd = reinterpret_cast<st_data*>(0);
20395 83631 : }
20396 :
20397 : std::list<T> local_symbol_list_;
20398 : std::list<std::string> local_stringvar_list_;
20399 : std::set<std::string> reserved_symbol_table_;
20400 : std::vector<ifunction<T>*> free_function_list_;
20401 : };
20402 :
20403 83631 : control_block()
20404 83631 : : ref_count(1)
20405 83631 : , data_(st_data::create())
20406 83631 : , mutability_(e_mutable)
20407 83631 : {}
20408 :
20409 : explicit control_block(st_data* data)
20410 : : ref_count(1)
20411 : , data_(data)
20412 : , mutability_(e_mutable)
20413 : {}
20414 :
20415 83631 : ~control_block()
20416 : {
20417 83631 : if (data_ && (0 == ref_count))
20418 : {
20419 83631 : st_data::destroy(data_);
20420 : }
20421 83631 : }
20422 :
20423 83631 : static inline control_block* create()
20424 : {
20425 83631 : return (new control_block);
20426 : }
20427 :
20428 : template <typename SymTab>
20429 1043126 : static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
20430 : {
20431 1043126 : if (cntrl_blck)
20432 : {
20433 1043126 : if (
20434 2086252 : (0 != cntrl_blck->ref_count) &&
20435 1043126 : (0 == --cntrl_blck->ref_count)
20436 : )
20437 : {
20438 83631 : if (sym_tab)
20439 83630 : sym_tab->clear();
20440 :
20441 83631 : delete cntrl_blck;
20442 : }
20443 :
20444 1043126 : cntrl_blck = 0;
20445 : }
20446 1043126 : }
20447 :
20448 83631 : void set_mutability(const symtab_mutability_type mutability)
20449 : {
20450 83631 : mutability_ = mutability;
20451 83631 : }
20452 :
20453 : std::size_t ref_count;
20454 : st_data* data_;
20455 : symtab_mutability_type mutability_;
20456 : };
20457 :
20458 : public:
20459 :
20460 83631 : explicit symbol_table(const symtab_mutability_type mutability = e_mutable)
20461 83631 : : control_block_(control_block::create())
20462 : {
20463 83631 : control_block_->set_mutability(mutability);
20464 83631 : clear();
20465 83631 : }
20466 :
20467 1043122 : ~symbol_table()
20468 : {
20469 1043122 : exprtk::details::dump_ptr("~symbol_table", this);
20470 1043122 : control_block::destroy(control_block_, this);
20471 1043122 : }
20472 :
20473 959491 : symbol_table(const symbol_table<T>& st)
20474 : {
20475 959491 : control_block_ = st.control_block_;
20476 959491 : control_block_->ref_count++;
20477 959491 : }
20478 :
20479 4 : inline symbol_table<T>& operator=(const symbol_table<T>& st)
20480 : {
20481 4 : if (this != &st)
20482 : {
20483 4 : control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
20484 :
20485 4 : control_block_ = st.control_block_;
20486 4 : control_block_->ref_count++;
20487 : }
20488 :
20489 4 : return (*this);
20490 : }
20491 :
20492 31545 : inline bool operator==(const symbol_table<T>& st) const
20493 : {
20494 31545 : return (this == &st) || (control_block_ == st.control_block_);
20495 : }
20496 :
20497 1813759 : inline symtab_mutability_type mutability() const
20498 : {
20499 1813759 : return valid() ? control_block_->mutability_ : e_unknown;
20500 : }
20501 :
20502 187367 : inline void clear_variables(const bool delete_node = true)
20503 : {
20504 187367 : local_data().variable_store.clear(delete_node);
20505 187367 : }
20506 :
20507 187367 : inline void clear_functions()
20508 : {
20509 187367 : local_data().function_store.clear();
20510 187367 : }
20511 :
20512 187367 : inline void clear_strings()
20513 : {
20514 : #ifndef exprtk_disable_string_capabilities
20515 187367 : local_data().stringvar_store.clear();
20516 : #endif
20517 187367 : }
20518 :
20519 187367 : inline void clear_vectors()
20520 : {
20521 187367 : local_data().vector_store.clear();
20522 187367 : }
20523 :
20524 187367 : inline void clear_local_constants()
20525 : {
20526 187367 : local_data().local_symbol_list_.clear();
20527 187367 : }
20528 :
20529 187367 : inline void clear()
20530 : {
20531 187367 : if (!valid()) return;
20532 187367 : clear_variables ();
20533 187367 : clear_functions ();
20534 187367 : clear_strings ();
20535 187367 : clear_vectors ();
20536 187367 : clear_local_constants();
20537 : }
20538 :
20539 600 : inline std::size_t variable_count() const
20540 : {
20541 600 : if (valid())
20542 600 : return local_data().variable_store.size;
20543 : else
20544 0 : return 0;
20545 : }
20546 :
20547 : #ifndef exprtk_disable_string_capabilities
20548 10 : inline std::size_t stringvar_count() const
20549 : {
20550 10 : if (valid())
20551 10 : return local_data().stringvar_store.size;
20552 : else
20553 0 : return 0;
20554 : }
20555 : #endif
20556 :
20557 : inline std::size_t function_count() const
20558 : {
20559 : if (valid())
20560 : return local_data().function_store.size;
20561 : else
20562 : return 0;
20563 : }
20564 :
20565 : inline std::size_t vector_count() const
20566 : {
20567 : if (valid())
20568 : return local_data().vector_store.size;
20569 : else
20570 : return 0;
20571 : }
20572 :
20573 12000045 : inline variable_ptr get_variable(const std::string& variable_name) const
20574 : {
20575 12000045 : if (!valid())
20576 0 : return reinterpret_cast<variable_ptr>(0);
20577 12000045 : else if (!valid_symbol(variable_name))
20578 0 : return reinterpret_cast<variable_ptr>(0);
20579 : else
20580 12000045 : return local_data().variable_store.get(variable_name);
20581 : }
20582 :
20583 : inline variable_ptr get_variable(const T& var_ref) const
20584 : {
20585 : if (!valid())
20586 : return reinterpret_cast<variable_ptr>(0);
20587 : else
20588 : return local_data().variable_store.get_from_varptr(
20589 : reinterpret_cast<const void*>(&var_ref));
20590 : }
20591 :
20592 : #ifndef exprtk_disable_string_capabilities
20593 44 : inline stringvar_ptr get_stringvar(const std::string& string_name) const
20594 : {
20595 44 : if (!valid())
20596 0 : return reinterpret_cast<stringvar_ptr>(0);
20597 44 : else if (!valid_symbol(string_name))
20598 0 : return reinterpret_cast<stringvar_ptr>(0);
20599 : else
20600 44 : return local_data().stringvar_store.get(string_name);
20601 : }
20602 :
20603 : inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const
20604 : {
20605 : static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0));
20606 : if (!valid())
20607 : return null_stringvar_base;
20608 : else if (!valid_symbol(string_name))
20609 : return null_stringvar_base;
20610 :
20611 : stringvar_ptr stringvar = local_data().stringvar_store.get(string_name);
20612 :
20613 : if (0 == stringvar)
20614 : {
20615 : return null_stringvar_base;
20616 : }
20617 :
20618 : return stringvar_base<T>(string_name,stringvar);
20619 : }
20620 : #endif
20621 :
20622 2178 : inline function_ptr get_function(const std::string& function_name) const
20623 : {
20624 2178 : if (!valid())
20625 0 : return reinterpret_cast<function_ptr>(0);
20626 2178 : else if (!valid_symbol(function_name))
20627 0 : return reinterpret_cast<function_ptr>(0);
20628 : else
20629 2178 : return local_data().function_store.get(function_name);
20630 : }
20631 :
20632 0 : inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
20633 : {
20634 0 : if (!valid())
20635 0 : return reinterpret_cast<vararg_function_ptr>(0);
20636 0 : else if (!valid_symbol(vararg_function_name))
20637 0 : return reinterpret_cast<vararg_function_ptr>(0);
20638 : else
20639 0 : return local_data().vararg_function_store.get(vararg_function_name);
20640 : }
20641 :
20642 0 : inline generic_function_ptr get_generic_function(const std::string& function_name) const
20643 : {
20644 0 : if (!valid())
20645 0 : return reinterpret_cast<generic_function_ptr>(0);
20646 0 : else if (!valid_symbol(function_name))
20647 0 : return reinterpret_cast<generic_function_ptr>(0);
20648 : else
20649 0 : return local_data().generic_function_store.get(function_name);
20650 : }
20651 :
20652 0 : inline generic_function_ptr get_string_function(const std::string& function_name) const
20653 : {
20654 0 : if (!valid())
20655 0 : return reinterpret_cast<generic_function_ptr>(0);
20656 0 : else if (!valid_symbol(function_name))
20657 0 : return reinterpret_cast<generic_function_ptr>(0);
20658 : else
20659 0 : return local_data().string_function_store.get(function_name);
20660 : }
20661 :
20662 0 : inline generic_function_ptr get_overload_function(const std::string& function_name) const
20663 : {
20664 0 : if (!valid())
20665 0 : return reinterpret_cast<generic_function_ptr>(0);
20666 0 : else if (!valid_symbol(function_name))
20667 0 : return reinterpret_cast<generic_function_ptr>(0);
20668 : else
20669 0 : return local_data().overload_function_store.get(function_name);
20670 : }
20671 :
20672 : typedef vector_holder_t* vector_holder_ptr;
20673 :
20674 4 : inline vector_holder_ptr get_vector(const std::string& vector_name) const
20675 : {
20676 4 : if (!valid())
20677 0 : return reinterpret_cast<vector_holder_ptr>(0);
20678 4 : else if (!valid_symbol(vector_name))
20679 0 : return reinterpret_cast<vector_holder_ptr>(0);
20680 : else
20681 4 : return local_data().vector_store.get(vector_name);
20682 : }
20683 :
20684 : inline T& variable_ref(const std::string& symbol_name)
20685 : {
20686 : static T null_var = T(0);
20687 : if (!valid())
20688 : return null_var;
20689 : else if (!valid_symbol(symbol_name))
20690 : return null_var;
20691 : else
20692 : return local_data().variable_store.type_ref(symbol_name);
20693 : }
20694 :
20695 : #ifndef exprtk_disable_string_capabilities
20696 : inline std::string& stringvar_ref(const std::string& symbol_name)
20697 : {
20698 : static std::string null_stringvar;
20699 : if (!valid())
20700 : return null_stringvar;
20701 : else if (!valid_symbol(symbol_name))
20702 : return null_stringvar;
20703 : else
20704 : return local_data().stringvar_store.type_ref(symbol_name);
20705 : }
20706 : #endif
20707 :
20708 : inline bool is_constant_node(const std::string& symbol_name) const
20709 : {
20710 : if (!valid())
20711 : return false;
20712 : else if (!valid_symbol(symbol_name))
20713 : return false;
20714 : else
20715 : return local_data().variable_store.is_constant(symbol_name);
20716 : }
20717 :
20718 : #ifndef exprtk_disable_string_capabilities
20719 : inline bool is_constant_string(const std::string& symbol_name) const
20720 : {
20721 : if (!valid())
20722 : return false;
20723 : else if (!valid_symbol(symbol_name))
20724 : return false;
20725 : else if (!local_data().stringvar_store.symbol_exists(symbol_name))
20726 : return false;
20727 : else
20728 : return local_data().stringvar_store.is_constant(symbol_name);
20729 : }
20730 : #endif
20731 :
20732 2302 : inline bool create_variable(const std::string& variable_name, const T& value = T(0))
20733 : {
20734 2302 : if (!valid())
20735 0 : return false;
20736 2302 : else if (!valid_symbol(variable_name))
20737 0 : return false;
20738 2302 : else if (symbol_exists(variable_name))
20739 0 : return false;
20740 :
20741 2302 : local_data().local_symbol_list_.push_back(value);
20742 2302 : T& t = local_data().local_symbol_list_.back();
20743 :
20744 2302 : return add_variable(variable_name,t);
20745 : }
20746 :
20747 : #ifndef exprtk_disable_string_capabilities
20748 : inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
20749 : {
20750 : if (!valid())
20751 : return false;
20752 : else if (!valid_symbol(stringvar_name))
20753 : return false;
20754 : else if (symbol_exists(stringvar_name))
20755 : return false;
20756 :
20757 : local_data().local_stringvar_list_.push_back(value);
20758 : std::string& s = local_data().local_stringvar_list_.back();
20759 :
20760 : return add_stringvar(stringvar_name,s);
20761 : }
20762 : #endif
20763 :
20764 443911 : inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
20765 : {
20766 443911 : if (!valid())
20767 0 : return false;
20768 443911 : else if (!valid_symbol(variable_name))
20769 0 : return false;
20770 443911 : else if (symbol_exists(variable_name))
20771 76 : return false;
20772 : else
20773 443835 : return local_data().variable_store.add(variable_name, t, is_constant);
20774 : }
20775 :
20776 101541 : inline bool add_constant(const std::string& constant_name, const T& value)
20777 : {
20778 101541 : if (!valid())
20779 0 : return false;
20780 101541 : else if (!valid_symbol(constant_name))
20781 0 : return false;
20782 101541 : else if (symbol_exists(constant_name))
20783 0 : return false;
20784 :
20785 101541 : local_data().local_symbol_list_.push_back(value);
20786 101541 : T& t = local_data().local_symbol_list_.back();
20787 :
20788 101541 : return add_variable(constant_name, t, true);
20789 : }
20790 :
20791 : #ifndef exprtk_disable_string_capabilities
20792 122386 : inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
20793 : {
20794 122386 : if (!valid())
20795 0 : return false;
20796 122386 : else if (!valid_symbol(stringvar_name))
20797 0 : return false;
20798 122386 : else if (symbol_exists(stringvar_name))
20799 76 : return false;
20800 : else
20801 122310 : return local_data().stringvar_store.add(stringvar_name, s, is_constant);
20802 : }
20803 : #endif
20804 :
20805 143009 : inline bool add_function(const std::string& function_name, function_t& function)
20806 : {
20807 143009 : if (!valid())
20808 0 : return false;
20809 143009 : else if (!valid_symbol(function_name))
20810 0 : return false;
20811 143009 : else if (symbol_exists(function_name))
20812 0 : return false;
20813 : else
20814 143009 : return local_data().function_store.add(function_name,function);
20815 : }
20816 :
20817 2 : inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
20818 : {
20819 2 : if (!valid())
20820 0 : return false;
20821 2 : else if (!valid_symbol(vararg_function_name))
20822 0 : return false;
20823 2 : else if (symbol_exists(vararg_function_name))
20824 0 : return false;
20825 : else
20826 2 : return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
20827 : }
20828 :
20829 1035 : inline bool add_function(const std::string& function_name, generic_function_t& function)
20830 : {
20831 1035 : if (!valid())
20832 0 : return false;
20833 1035 : else if (!valid_symbol(function_name))
20834 0 : return false;
20835 1035 : else if (symbol_exists(function_name))
20836 0 : return false;
20837 : else
20838 : {
20839 1035 : switch (function.rtrn_type)
20840 : {
20841 1032 : case generic_function_t::e_rtrn_scalar :
20842 2064 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
20843 2064 : local_data().generic_function_store.add(function_name,function) : false;
20844 :
20845 1 : case generic_function_t::e_rtrn_string :
20846 2 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
20847 2 : local_data().string_function_store.add(function_name,function) : false;
20848 :
20849 2 : case generic_function_t::e_rtrn_overload :
20850 4 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
20851 4 : local_data().overload_function_store.add(function_name,function) : false;
20852 : }
20853 : }
20854 :
20855 0 : return false;
20856 : }
20857 :
20858 : #define exprtk_define_freefunction(NN) \
20859 : inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
20860 : { \
20861 : if (!valid()) \
20862 : { return false; } \
20863 : if (!valid_symbol(function_name)) \
20864 : { return false; } \
20865 : if (symbol_exists(function_name)) \
20866 : { return false; } \
20867 : \
20868 : exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
20869 : \
20870 : local_data().free_function_list_.push_back(ifunc); \
20871 : \
20872 : return add_function(function_name,(*local_data().free_function_list_.back())); \
20873 : } \
20874 :
20875 102 : exprtk_define_freefunction(00) exprtk_define_freefunction(01)
20876 204 : exprtk_define_freefunction(02) exprtk_define_freefunction(03)
20877 204 : exprtk_define_freefunction(04) exprtk_define_freefunction(05)
20878 102 : exprtk_define_freefunction(06) exprtk_define_freefunction(07)
20879 : exprtk_define_freefunction(08) exprtk_define_freefunction(09)
20880 : exprtk_define_freefunction(10) exprtk_define_freefunction(11)
20881 : exprtk_define_freefunction(12) exprtk_define_freefunction(13)
20882 : exprtk_define_freefunction(14) exprtk_define_freefunction(15)
20883 :
20884 : #undef exprtk_define_freefunction
20885 :
20886 2 : inline bool add_reserved_function(const std::string& function_name, function_t& function)
20887 : {
20888 2 : if (!valid())
20889 0 : return false;
20890 2 : else if (!valid_symbol(function_name,false))
20891 0 : return false;
20892 2 : else if (symbol_exists(function_name,false))
20893 0 : return false;
20894 : else
20895 2 : return local_data().function_store.add(function_name,function);
20896 : }
20897 :
20898 : inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
20899 : {
20900 : if (!valid())
20901 : return false;
20902 : else if (!valid_symbol(vararg_function_name,false))
20903 : return false;
20904 : else if (symbol_exists(vararg_function_name,false))
20905 : return false;
20906 : else
20907 : return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
20908 : }
20909 :
20910 : inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
20911 : {
20912 : if (!valid())
20913 : return false;
20914 : else if (!valid_symbol(function_name,false))
20915 : return false;
20916 : else if (symbol_exists(function_name,false))
20917 : return false;
20918 : else
20919 : {
20920 : switch (function.rtrn_type)
20921 : {
20922 : case generic_function_t::e_rtrn_scalar :
20923 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
20924 : local_data().generic_function_store.add(function_name,function) : false;
20925 :
20926 : case generic_function_t::e_rtrn_string :
20927 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
20928 : local_data().string_function_store.add(function_name,function) : false;
20929 :
20930 : case generic_function_t::e_rtrn_overload :
20931 : return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
20932 : local_data().overload_function_store.add(function_name,function) : false;
20933 : }
20934 : }
20935 :
20936 : return false;
20937 : }
20938 :
20939 : #define exprtk_define_reserved_function(NN) \
20940 : inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \
20941 : { \
20942 : if (!valid()) \
20943 : { return false; } \
20944 : if (!valid_symbol(function_name,false)) \
20945 : { return false; } \
20946 : if (symbol_exists(function_name,false)) \
20947 : { return false; } \
20948 : \
20949 : exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
20950 : \
20951 : local_data().free_function_list_.push_back(ifunc); \
20952 : \
20953 : return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \
20954 : } \
20955 :
20956 : exprtk_define_reserved_function(00) exprtk_define_reserved_function(01)
20957 : exprtk_define_reserved_function(02) exprtk_define_reserved_function(03)
20958 : exprtk_define_reserved_function(04) exprtk_define_reserved_function(05)
20959 : exprtk_define_reserved_function(06) exprtk_define_reserved_function(07)
20960 : exprtk_define_reserved_function(08) exprtk_define_reserved_function(09)
20961 : exprtk_define_reserved_function(10) exprtk_define_reserved_function(11)
20962 : exprtk_define_reserved_function(12) exprtk_define_reserved_function(13)
20963 : exprtk_define_reserved_function(14) exprtk_define_reserved_function(15)
20964 :
20965 : #undef exprtk_define_reserved_function
20966 :
20967 : template <std::size_t N>
20968 2143 : inline bool add_vector(const std::string& vector_name, T (&v)[N])
20969 : {
20970 2143 : if (!valid())
20971 0 : return false;
20972 2143 : else if (!valid_symbol(vector_name))
20973 0 : return false;
20974 2143 : else if (symbol_exists(vector_name))
20975 0 : return false;
20976 : else
20977 2143 : return local_data().vector_store.add(vector_name,v);
20978 : }
20979 :
20980 0 : inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
20981 : {
20982 0 : if (!valid())
20983 0 : return false;
20984 0 : else if (!valid_symbol(vector_name))
20985 0 : return false;
20986 0 : else if (symbol_exists(vector_name))
20987 0 : return false;
20988 0 : else if (0 == v_size)
20989 0 : return false;
20990 : else
20991 0 : return local_data().vector_store.add(vector_name, v, v_size);
20992 : }
20993 :
20994 : template <typename Allocator>
20995 84 : inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
20996 : {
20997 84 : if (!valid())
20998 0 : return false;
20999 84 : else if (!valid_symbol(vector_name))
21000 0 : return false;
21001 84 : else if (symbol_exists(vector_name))
21002 0 : return false;
21003 84 : else if (0 == v.size())
21004 0 : return false;
21005 : else
21006 84 : return local_data().vector_store.add(vector_name,v);
21007 : }
21008 :
21009 4195 : inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
21010 : {
21011 4195 : if (!valid())
21012 0 : return false;
21013 4195 : else if (!valid_symbol(vector_name))
21014 0 : return false;
21015 4195 : else if (symbol_exists(vector_name))
21016 0 : return false;
21017 4195 : else if (0 == v.size())
21018 0 : return false;
21019 : else
21020 4195 : return local_data().vector_store.add(vector_name,v);
21021 : }
21022 :
21023 344 : inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
21024 : {
21025 344 : if (!valid())
21026 0 : return false;
21027 : else
21028 344 : return local_data().variable_store.remove(variable_name, delete_node);
21029 : }
21030 :
21031 : #ifndef exprtk_disable_string_capabilities
21032 43 : inline bool remove_stringvar(const std::string& string_name)
21033 : {
21034 43 : if (!valid())
21035 0 : return false;
21036 : else
21037 43 : return local_data().stringvar_store.remove(string_name);
21038 : }
21039 : #endif
21040 :
21041 29 : inline bool remove_function(const std::string& function_name)
21042 : {
21043 29 : if (!valid())
21044 0 : return false;
21045 : else
21046 29 : return local_data().function_store.remove(function_name);
21047 : }
21048 :
21049 3 : inline bool remove_vararg_function(const std::string& vararg_function_name)
21050 : {
21051 3 : if (!valid())
21052 0 : return false;
21053 : else
21054 3 : return local_data().vararg_function_store.remove(vararg_function_name);
21055 : }
21056 :
21057 3 : inline bool remove_vector(const std::string& vector_name)
21058 : {
21059 3 : if (!valid())
21060 0 : return false;
21061 : else
21062 3 : return local_data().vector_store.remove(vector_name);
21063 : }
21064 :
21065 33080 : inline bool add_constants()
21066 : {
21067 33080 : return add_pi () &&
21068 66160 : add_epsilon () &&
21069 66160 : add_infinity() ;
21070 : }
21071 :
21072 33081 : inline bool add_pi()
21073 : {
21074 33081 : const typename details::numeric::details::number_type<T>::type num_type;
21075 33081 : static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
21076 66162 : return add_constant("pi",local_pi);
21077 : }
21078 :
21079 33080 : inline bool add_epsilon()
21080 : {
21081 33080 : static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
21082 66160 : return add_constant("epsilon",local_epsilon);
21083 : }
21084 :
21085 33080 : inline bool add_infinity()
21086 : {
21087 : static const T local_infinity = std::numeric_limits<T>::infinity();
21088 66160 : return add_constant("inf",local_infinity);
21089 : }
21090 :
21091 : template <typename Package>
21092 62 : inline bool add_package(Package& package)
21093 : {
21094 62 : return package.register_package(*this);
21095 : }
21096 :
21097 : template <typename Allocator,
21098 : template <typename, typename> class Sequence>
21099 10 : inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
21100 : {
21101 10 : if (!valid())
21102 0 : return 0;
21103 : else
21104 10 : return local_data().variable_store.get_list(vlist);
21105 : }
21106 :
21107 : template <typename Allocator,
21108 : template <typename, typename> class Sequence>
21109 10 : inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
21110 : {
21111 10 : if (!valid())
21112 0 : return 0;
21113 : else
21114 10 : return local_data().variable_store.get_list(vlist);
21115 : }
21116 :
21117 : #ifndef exprtk_disable_string_capabilities
21118 : template <typename Allocator,
21119 : template <typename, typename> class Sequence>
21120 10 : inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
21121 : {
21122 10 : if (!valid())
21123 0 : return 0;
21124 : else
21125 10 : return local_data().stringvar_store.get_list(svlist);
21126 : }
21127 :
21128 : template <typename Allocator,
21129 : template <typename, typename> class Sequence>
21130 10 : inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
21131 : {
21132 10 : if (!valid())
21133 0 : return 0;
21134 : else
21135 10 : return local_data().stringvar_store.get_list(svlist);
21136 : }
21137 : #endif
21138 :
21139 : template <typename Allocator,
21140 : template <typename, typename> class Sequence>
21141 : inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const
21142 : {
21143 : if (!valid())
21144 : return 0;
21145 : else
21146 : return local_data().vector_store.get_list(vec_list);
21147 : }
21148 :
21149 : template <typename Allocator,
21150 : template <typename, typename> class Sequence>
21151 : inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const
21152 : {
21153 : if (!valid())
21154 : return 0;
21155 :
21156 : std::vector<std::string> function_names;
21157 : std::size_t count = 0;
21158 :
21159 : count += local_data().function_store .get_list(function_names);
21160 : count += local_data().vararg_function_store .get_list(function_names);
21161 : count += local_data().generic_function_store .get_list(function_names);
21162 : count += local_data().string_function_store .get_list(function_names);
21163 : count += local_data().overload_function_store.get_list(function_names);
21164 :
21165 : std::set<std::string> function_set;
21166 :
21167 : for (std::size_t i = 0; i < function_names.size(); ++i)
21168 : {
21169 : function_set.insert(function_names[i]);
21170 : }
21171 :
21172 : std::copy(function_set.begin(), function_set.end(),
21173 : std::back_inserter(function_list));
21174 :
21175 : return count;
21176 : }
21177 :
21178 : inline std::vector<std::string> get_function_list() const
21179 : {
21180 : std::vector<std::string> result;
21181 : get_function_list(result);
21182 : return result;
21183 : }
21184 :
21185 903527 : inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
21186 : {
21187 : /*
21188 : Function will return true if symbol_name exists as either a
21189 : reserved symbol, variable, stringvar, vector or function name
21190 : in any of the type stores.
21191 : */
21192 903527 : if (!valid())
21193 0 : return false;
21194 903527 : else if (local_data().variable_store.symbol_exists(symbol_name))
21195 118 : return true;
21196 : #ifndef exprtk_disable_string_capabilities
21197 903409 : else if (local_data().stringvar_store.symbol_exists(symbol_name))
21198 118 : return true;
21199 : #endif
21200 903291 : else if (local_data().vector_store.symbol_exists(symbol_name))
21201 2 : return true;
21202 903289 : else if (local_data().function_store.symbol_exists(symbol_name))
21203 20 : return true;
21204 903269 : else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
21205 0 : return true;
21206 : else
21207 903269 : return false;
21208 : }
21209 :
21210 727 : inline bool is_variable(const std::string& variable_name) const
21211 : {
21212 727 : if (!valid())
21213 0 : return false;
21214 : else
21215 727 : return local_data().variable_store.symbol_exists(variable_name);
21216 : }
21217 :
21218 : #ifndef exprtk_disable_string_capabilities
21219 727 : inline bool is_stringvar(const std::string& stringvar_name) const
21220 : {
21221 727 : if (!valid())
21222 0 : return false;
21223 : else
21224 727 : return local_data().stringvar_store.symbol_exists(stringvar_name);
21225 : }
21226 :
21227 : inline bool is_conststr_stringvar(const std::string& symbol_name) const
21228 : {
21229 : if (!valid())
21230 : return false;
21231 : else if (!valid_symbol(symbol_name))
21232 : return false;
21233 : else if (!local_data().stringvar_store.symbol_exists(symbol_name))
21234 : return false;
21235 :
21236 : return (
21237 : local_data().stringvar_store.symbol_exists(symbol_name) ||
21238 : local_data().stringvar_store.is_constant (symbol_name)
21239 : );
21240 : }
21241 : #endif
21242 :
21243 727 : inline bool is_function(const std::string& function_name) const
21244 : {
21245 727 : if (!valid())
21246 0 : return false;
21247 : else
21248 727 : return local_data().function_store.symbol_exists(function_name);
21249 : }
21250 :
21251 727 : inline bool is_vararg_function(const std::string& vararg_function_name) const
21252 : {
21253 727 : if (!valid())
21254 0 : return false;
21255 : else
21256 727 : return local_data().vararg_function_store.symbol_exists(vararg_function_name);
21257 : }
21258 :
21259 727 : inline bool is_vector(const std::string& vector_name) const
21260 : {
21261 727 : if (!valid())
21262 0 : return false;
21263 : else
21264 727 : return local_data().vector_store.symbol_exists(vector_name);
21265 : }
21266 :
21267 : inline std::string get_variable_name(const expression_ptr& ptr) const
21268 : {
21269 : return local_data().variable_store.entity_name(ptr);
21270 : }
21271 :
21272 : inline std::string get_vector_name(const vector_holder_ptr& ptr) const
21273 : {
21274 : return local_data().vector_store.entity_name(ptr);
21275 : }
21276 :
21277 : #ifndef exprtk_disable_string_capabilities
21278 : inline std::string get_stringvar_name(const expression_ptr& ptr) const
21279 : {
21280 : return local_data().stringvar_store.entity_name(ptr);
21281 : }
21282 :
21283 : inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
21284 : {
21285 : return local_data().stringvar_store.entity_name(ptr);
21286 : }
21287 : #endif
21288 :
21289 34522198 : inline bool valid() const
21290 : {
21291 : // Symbol table sanity check.
21292 34522198 : return control_block_ && control_block_->data_;
21293 : }
21294 :
21295 727 : inline void load_from(const symbol_table<T>& st)
21296 : {
21297 : {
21298 727 : std::vector<std::string> name_list;
21299 :
21300 727 : st.local_data().function_store.get_list(name_list);
21301 :
21302 727 : if (!name_list.empty())
21303 : {
21304 2799 : for (std::size_t i = 0; i < name_list.size(); ++i)
21305 : {
21306 2178 : exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
21307 2178 : add_function(name_list[i],ifunc);
21308 : }
21309 : }
21310 727 : }
21311 :
21312 : {
21313 727 : std::vector<std::string> name_list;
21314 :
21315 727 : st.local_data().vararg_function_store.get_list(name_list);
21316 :
21317 727 : if (!name_list.empty())
21318 : {
21319 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21320 : {
21321 0 : exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
21322 0 : add_function(name_list[i],ivafunc);
21323 : }
21324 : }
21325 727 : }
21326 :
21327 : {
21328 727 : std::vector<std::string> name_list;
21329 :
21330 727 : st.local_data().generic_function_store.get_list(name_list);
21331 :
21332 727 : if (!name_list.empty())
21333 : {
21334 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21335 : {
21336 0 : exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
21337 0 : add_function(name_list[i],ifunc);
21338 : }
21339 : }
21340 727 : }
21341 :
21342 : {
21343 727 : std::vector<std::string> name_list;
21344 :
21345 727 : st.local_data().string_function_store.get_list(name_list);
21346 :
21347 727 : if (!name_list.empty())
21348 : {
21349 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21350 : {
21351 0 : exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
21352 0 : add_function(name_list[i],ifunc);
21353 : }
21354 : }
21355 727 : }
21356 :
21357 : {
21358 727 : std::vector<std::string> name_list;
21359 :
21360 727 : st.local_data().overload_function_store.get_list(name_list);
21361 :
21362 727 : if (!name_list.empty())
21363 : {
21364 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21365 : {
21366 0 : exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
21367 0 : add_function(name_list[i],ifunc);
21368 : }
21369 : }
21370 727 : }
21371 727 : }
21372 :
21373 0 : inline void load_variables_from(const symbol_table<T>& st)
21374 : {
21375 0 : std::vector<std::string> name_list;
21376 :
21377 0 : st.local_data().variable_store.get_list(name_list);
21378 :
21379 0 : if (!name_list.empty())
21380 : {
21381 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21382 : {
21383 0 : T& variable = st.get_variable(name_list[i])->ref();
21384 0 : add_variable(name_list[i], variable);
21385 : }
21386 : }
21387 0 : }
21388 :
21389 0 : inline void load_vectors_from(const symbol_table<T>& st)
21390 : {
21391 0 : std::vector<std::string> name_list;
21392 :
21393 0 : st.local_data().vector_store.get_list(name_list);
21394 :
21395 0 : if (!name_list.empty())
21396 : {
21397 0 : for (std::size_t i = 0; i < name_list.size(); ++i)
21398 : {
21399 0 : vector_holder_t& vecholder = *st.get_vector(name_list[i]);
21400 0 : add_vector(name_list[i], vecholder.data(), vecholder.size());
21401 : }
21402 : }
21403 0 : }
21404 :
21405 : private:
21406 :
21407 16793583 : inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
21408 : {
21409 16793583 : if (symbol.empty())
21410 0 : return false;
21411 16793583 : else if (!details::is_letter(symbol[0]))
21412 23 : return false;
21413 16793560 : else if (symbol.size() > 1)
21414 : {
21415 3143937 : for (std::size_t i = 1; i < symbol.size(); ++i)
21416 : {
21417 2257117 : if (
21418 2268303 : !details::is_letter_or_digit(symbol[i]) &&
21419 11186 : ('_' != symbol[i])
21420 : )
21421 : {
21422 604 : if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
21423 604 : continue;
21424 : else
21425 0 : return false;
21426 : }
21427 : }
21428 : }
21429 :
21430 16793560 : return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
21431 : }
21432 :
21433 185443 : inline bool valid_function(const std::string& symbol) const
21434 : {
21435 185443 : if (symbol.empty())
21436 0 : return false;
21437 185443 : else if (!details::is_letter(symbol[0]))
21438 115 : return false;
21439 185328 : else if (symbol.size() > 1)
21440 : {
21441 662596 : for (std::size_t i = 1; i < symbol.size(); ++i)
21442 : {
21443 510054 : if (
21444 520099 : !details::is_letter_or_digit(symbol[i]) &&
21445 10045 : ('_' != symbol[i])
21446 : )
21447 : {
21448 1820 : if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
21449 1820 : continue;
21450 : else
21451 0 : return false;
21452 : }
21453 : }
21454 : }
21455 :
21456 185328 : return true;
21457 : }
21458 :
21459 : typedef typename control_block::st_data local_data_t;
21460 :
21461 1862782 : inline local_data_t& local_data()
21462 : {
21463 1862782 : return *(control_block_->data_);
21464 : }
21465 :
21466 38071241 : inline const local_data_t& local_data() const
21467 : {
21468 38071241 : return *(control_block_->data_);
21469 : }
21470 :
21471 : control_block* control_block_;
21472 :
21473 : friend class parser<T>;
21474 : }; // class symbol_table
21475 :
21476 : template <typename T>
21477 : class function_compositor;
21478 :
21479 : template <typename T>
21480 : class expression
21481 : {
21482 : private:
21483 :
21484 : typedef details::expression_node<T>* expression_ptr;
21485 : typedef details::vector_holder<T>* vector_holder_ptr;
21486 : typedef std::vector<symbol_table<T> > symtab_list_t;
21487 :
21488 : struct control_block
21489 : {
21490 : enum data_type
21491 : {
21492 : e_unknown ,
21493 : e_expr ,
21494 : e_vecholder,
21495 : e_data ,
21496 : e_vecdata ,
21497 : e_string
21498 : };
21499 :
21500 : struct data_pack
21501 : {
21502 : data_pack()
21503 : : pointer(0)
21504 : , type(e_unknown)
21505 : , size(0)
21506 : {}
21507 :
21508 169435 : data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
21509 169435 : : pointer(ptr)
21510 169435 : , type(dt)
21511 169435 : , size(sz)
21512 169435 : {}
21513 :
21514 : void* pointer;
21515 : data_type type;
21516 : std::size_t size;
21517 : };
21518 :
21519 : typedef std::vector<data_pack> local_data_list_t;
21520 : typedef results_context<T> results_context_t;
21521 : typedef control_block* cntrl_blck_ptr_t;
21522 :
21523 : control_block()
21524 : : ref_count(0)
21525 : , expr (0)
21526 : , results (0)
21527 : , retinv_null(false)
21528 : , return_invoked(&retinv_null)
21529 : {}
21530 :
21531 703723 : explicit control_block(expression_ptr e)
21532 703723 : : ref_count(1)
21533 703723 : , expr (e)
21534 703723 : , results (0)
21535 703723 : , retinv_null(false)
21536 703723 : , return_invoked(&retinv_null)
21537 703723 : {}
21538 :
21539 703723 : ~control_block()
21540 : {
21541 703723 : if (expr && details::branch_deletable(expr))
21542 : {
21543 703478 : destroy_node(expr);
21544 : }
21545 :
21546 703723 : if (!local_data_list.empty())
21547 : {
21548 208222 : for (std::size_t i = 0; i < local_data_list.size(); ++i)
21549 : {
21550 169435 : switch (local_data_list[i].type)
21551 : {
21552 68301 : case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
21553 68301 : break;
21554 :
21555 23261 : case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
21556 23261 : break;
21557 :
21558 44872 : case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer);
21559 44872 : break;
21560 :
21561 23261 : case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer);
21562 23261 : break;
21563 :
21564 9740 : case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer);
21565 9740 : break;
21566 :
21567 0 : default : break;
21568 : }
21569 : }
21570 : }
21571 :
21572 703723 : if (results)
21573 : {
21574 111 : delete results;
21575 : }
21576 703723 : }
21577 :
21578 703723 : static inline cntrl_blck_ptr_t create(expression_ptr e)
21579 : {
21580 703723 : return new control_block(e);
21581 : }
21582 :
21583 594097 : static inline void destroy(cntrl_blck_ptr_t& cntrl_blck)
21584 : {
21585 594097 : if (cntrl_blck)
21586 : {
21587 584137 : if (
21588 1168274 : (0 != cntrl_blck->ref_count) &&
21589 584137 : (0 == --cntrl_blck->ref_count)
21590 : )
21591 : {
21592 343641 : delete cntrl_blck;
21593 : }
21594 :
21595 584137 : cntrl_blck = 0;
21596 : }
21597 594097 : }
21598 :
21599 : std::size_t ref_count;
21600 : expression_ptr expr;
21601 : local_data_list_t local_data_list;
21602 : results_context_t* results;
21603 : bool retinv_null;
21604 : bool* return_invoked;
21605 :
21606 : friend class function_compositor<T>;
21607 : };
21608 :
21609 : public:
21610 :
21611 344564 : expression()
21612 344564 : : control_block_(0)
21613 : {
21614 344564 : set_expression(new details::null_node<T>());
21615 344564 : }
21616 :
21617 239042 : expression(const expression<T>& e)
21618 239042 : : control_block_ (e.control_block_ )
21619 239042 : , symbol_table_list_(e.symbol_table_list_)
21620 : {
21621 239042 : control_block_->ref_count++;
21622 239042 : }
21623 :
21624 : explicit expression(const symbol_table<T>& symbol_table)
21625 : : control_block_(0)
21626 : {
21627 : set_expression(new details::null_node<T>());
21628 : symbol_table_list_.push_back(symbol_table);
21629 : }
21630 :
21631 1454 : inline expression<T>& operator=(const expression<T>& e)
21632 : {
21633 1454 : if (this != &e)
21634 : {
21635 1454 : if (control_block_)
21636 : {
21637 1454 : if (
21638 2908 : (0 != control_block_->ref_count) &&
21639 1454 : (0 == --control_block_->ref_count)
21640 : )
21641 : {
21642 1454 : delete control_block_;
21643 : }
21644 :
21645 1454 : control_block_ = 0;
21646 : }
21647 :
21648 1454 : control_block_ = e.control_block_;
21649 1454 : control_block_->ref_count++;
21650 1454 : symbol_table_list_ = e.symbol_table_list_;
21651 : }
21652 :
21653 1454 : return *this;
21654 : }
21655 :
21656 : inline bool operator==(const expression<T>& e) const
21657 : {
21658 : return (this == &e);
21659 : }
21660 :
21661 359659 : inline bool operator!() const
21662 : {
21663 : return (
21664 718818 : (0 == control_block_ ) ||
21665 359159 : (0 == control_block_->expr)
21666 359659 : );
21667 : }
21668 :
21669 10491 : inline expression<T>& release()
21670 : {
21671 10491 : exprtk::details::dump_ptr("expression::release", this);
21672 10491 : control_block::destroy(control_block_);
21673 :
21674 10491 : return (*this);
21675 : }
21676 :
21677 583606 : ~expression()
21678 : {
21679 583606 : control_block::destroy(control_block_);
21680 583606 : }
21681 :
21682 196282243 : inline T value() const
21683 : {
21684 196282243 : assert(control_block_ );
21685 196282243 : assert(control_block_->expr);
21686 :
21687 196282243 : return control_block_->expr->value();
21688 : }
21689 :
21690 : inline T operator() () const
21691 : {
21692 : return value();
21693 : }
21694 :
21695 : inline operator T() const
21696 : {
21697 : return value();
21698 : }
21699 :
21700 : inline operator bool() const
21701 : {
21702 : return details::is_true(value());
21703 : }
21704 :
21705 363842 : inline bool register_symbol_table(symbol_table<T>& st)
21706 : {
21707 375383 : for (std::size_t i = 0; i < symbol_table_list_.size(); ++i)
21708 : {
21709 31543 : if (st == symbol_table_list_[i])
21710 : {
21711 20002 : return false;
21712 : }
21713 : }
21714 :
21715 343840 : symbol_table_list_.push_back(st);
21716 343840 : return true;
21717 : }
21718 :
21719 36000003 : inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
21720 : {
21721 12000001 : return symbol_table_list_[index];
21722 : }
21723 :
21724 : inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
21725 : {
21726 : return symbol_table_list_[index];
21727 : }
21728 :
21729 4 : std::size_t num_symbol_tables() const
21730 : {
21731 4 : return symbol_table_list_.size();
21732 : }
21733 :
21734 : typedef results_context<T> results_context_t;
21735 :
21736 45 : inline const results_context_t& results() const
21737 : {
21738 45 : if (control_block_->results)
21739 45 : return (*control_block_->results);
21740 : else
21741 : {
21742 0 : static const results_context_t null_results;
21743 0 : return null_results;
21744 : }
21745 : }
21746 :
21747 30 : inline bool return_invoked() const
21748 : {
21749 30 : return (*control_block_->return_invoked);
21750 : }
21751 :
21752 : private:
21753 :
21754 370158 : inline symtab_list_t get_symbol_table_list() const
21755 : {
21756 370158 : return symbol_table_list_;
21757 : }
21758 :
21759 703723 : inline void set_expression(const expression_ptr expr)
21760 : {
21761 703723 : if (expr)
21762 : {
21763 703723 : if (control_block_)
21764 : {
21765 358628 : if (0 == --control_block_->ref_count)
21766 : {
21767 358628 : delete control_block_;
21768 : }
21769 : }
21770 :
21771 703723 : control_block_ = control_block::create(expr);
21772 : }
21773 703723 : }
21774 :
21775 68301 : inline void register_local_var(expression_ptr expr)
21776 : {
21777 68301 : if (expr)
21778 : {
21779 68301 : if (control_block_)
21780 : {
21781 68301 : control_block_->
21782 68301 : local_data_list.push_back(
21783 : typename expression<T>::control_block::
21784 136602 : data_pack(reinterpret_cast<void*>(expr),
21785 : control_block::e_expr));
21786 : }
21787 : }
21788 68301 : }
21789 :
21790 23261 : inline void register_local_var(vector_holder_ptr vec_holder)
21791 : {
21792 23261 : if (vec_holder)
21793 : {
21794 23261 : if (control_block_)
21795 : {
21796 23261 : control_block_->
21797 23261 : local_data_list.push_back(
21798 : typename expression<T>::control_block::
21799 46522 : data_pack(reinterpret_cast<void*>(vec_holder),
21800 : control_block::e_vecholder));
21801 : }
21802 : }
21803 23261 : }
21804 :
21805 77873 : inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
21806 : {
21807 77873 : if (data)
21808 : {
21809 77873 : if (control_block_)
21810 : {
21811 77873 : typename control_block::data_type dt = control_block::e_data;
21812 :
21813 77873 : switch (data_mode)
21814 : {
21815 44872 : case 0 : dt = control_block::e_data; break;
21816 23261 : case 1 : dt = control_block::e_vecdata; break;
21817 9740 : case 2 : dt = control_block::e_string; break;
21818 : }
21819 :
21820 77873 : control_block_->
21821 77873 : local_data_list.push_back(
21822 : typename expression<T>::control_block::
21823 155746 : data_pack(reinterpret_cast<void*>(data), dt, size));
21824 : }
21825 : }
21826 77873 : }
21827 :
21828 727 : inline const typename control_block::local_data_list_t& local_data_list()
21829 : {
21830 727 : if (control_block_)
21831 : {
21832 727 : return control_block_->local_data_list;
21833 : }
21834 : else
21835 : {
21836 0 : static typename control_block::local_data_list_t null_local_data_list;
21837 0 : return null_local_data_list;
21838 : }
21839 : }
21840 :
21841 359159 : inline void register_return_results(results_context_t* rc)
21842 : {
21843 359159 : if (control_block_ && rc)
21844 : {
21845 111 : control_block_->results = rc;
21846 : }
21847 359159 : }
21848 :
21849 359159 : inline void set_retinvk(bool* retinvk_ptr)
21850 : {
21851 359159 : if (control_block_)
21852 : {
21853 359159 : control_block_->return_invoked = retinvk_ptr;
21854 : }
21855 359159 : }
21856 :
21857 : control_block* control_block_;
21858 : symtab_list_t symbol_table_list_;
21859 :
21860 : friend class parser<T>;
21861 : friend class expression_helper<T>;
21862 : friend class function_compositor<T>;
21863 : template <typename TT>
21864 : friend bool is_valid(const expression<TT>& expr);
21865 : }; // class expression
21866 :
21867 : template <typename T>
21868 : class expression_helper
21869 : {
21870 : public:
21871 :
21872 : enum node_types
21873 : {
21874 : e_literal,
21875 : e_variable,
21876 : e_string,
21877 : e_unary,
21878 : e_binary,
21879 : e_function,
21880 : e_vararg,
21881 : e_null,
21882 : e_assert,
21883 : e_sf3ext,
21884 : e_sf4ext
21885 : };
21886 :
21887 10759 : static inline bool is_literal(const expression<T>& expr)
21888 : {
21889 10759 : return expr.control_block_ && details::is_literal_node(expr.control_block_->expr);
21890 : }
21891 :
21892 : static inline bool is_variable(const expression<T>& expr)
21893 : {
21894 : return expr.control_block_ && details::is_variable_node(expr.control_block_->expr);
21895 : }
21896 :
21897 : static inline bool is_string(const expression<T>& expr)
21898 : {
21899 : return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr);
21900 : }
21901 :
21902 : static inline bool is_unary(const expression<T>& expr)
21903 : {
21904 : return expr.control_block_ && details::is_unary_node(expr.control_block_->expr);
21905 : }
21906 :
21907 : static inline bool is_binary(const expression<T>& expr)
21908 : {
21909 : return expr.control_block_ && details::is_binary_node(expr.control_block_->expr);
21910 : }
21911 :
21912 : static inline bool is_function(const expression<T>& expr)
21913 : {
21914 : return expr.control_block_ && details::is_function(expr.control_block_->expr);
21915 : }
21916 :
21917 54 : static inline bool is_vararg(const expression<T>& expr)
21918 : {
21919 54 : return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr);
21920 : }
21921 :
21922 12 : static inline bool is_null(const expression<T>& expr)
21923 : {
21924 12 : return expr.control_block_ && details::is_null_node(expr.control_block_->expr);
21925 : }
21926 :
21927 : static inline bool is_assert(const expression<T>& expr)
21928 : {
21929 : return expr.control_block_ && details::is_assert_node(expr.control_block_->expr);
21930 : }
21931 :
21932 : static inline bool is_sf3ext(const expression<T>& expr)
21933 : {
21934 : return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr);
21935 : }
21936 :
21937 : static inline bool is_sf4ext(const expression<T>& expr)
21938 : {
21939 : return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr);
21940 : }
21941 :
21942 : static inline bool is_type(const expression<T>& expr, const node_types node_type)
21943 : {
21944 : if (0 == expr.control_block_)
21945 : {
21946 : return false;
21947 : }
21948 :
21949 : switch (node_type)
21950 : {
21951 : case e_literal : return is_literal_node(expr);
21952 : case e_variable : return is_variable (expr);
21953 : case e_string : return is_string (expr);
21954 : case e_unary : return is_unary (expr);
21955 : case e_binary : return is_binary (expr);
21956 : case e_function : return is_function (expr);
21957 : case e_null : return is_null (expr);
21958 : case e_assert : return is_assert (expr);
21959 : case e_sf3ext : return is_sf3ext (expr);
21960 : case e_sf4ext : return is_sf4ext (expr);
21961 : };
21962 :
21963 : return false;
21964 : }
21965 :
21966 54 : static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq)
21967 : {
21968 54 : if ((0 == expr.control_block_) || !is_vararg(expr))
21969 : {
21970 0 : return false;
21971 : }
21972 :
21973 : typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t;
21974 :
21975 54 : mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr);
21976 :
21977 54 : if (
21978 54 : (0 == vnode) ||
21979 108 : type_seq.empty() ||
21980 54 : (vnode->size() < type_seq.size())
21981 : )
21982 : {
21983 0 : return false;
21984 : }
21985 :
21986 190 : for (std::size_t i = 0; i < type_seq.size(); ++i)
21987 : {
21988 136 : assert((*vnode)[i]);
21989 :
21990 136 : switch(type_seq[i])
21991 : {
21992 25 : case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break;
21993 0 : case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break;
21994 26 : case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break;
21995 0 : case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break;
21996 0 : case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break;
21997 0 : case e_function : { if (details::is_function ((*vnode)[i])) continue; } break;
21998 0 : case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break;
21999 84 : case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break;
22000 1 : case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break;
22001 0 : case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break;
22002 0 : case e_vararg : break;
22003 : }
22004 :
22005 0 : return false;
22006 : }
22007 :
22008 54 : return true;
22009 : }
22010 : };
22011 :
22012 : template <typename T>
22013 : inline bool is_valid(const expression<T>& expr)
22014 : {
22015 : return expr.control_block_ && !expression_helper<T>::is_null(expr);
22016 : }
22017 :
22018 : namespace parser_error
22019 : {
22020 : enum error_mode
22021 : {
22022 : e_unknown = 0,
22023 : e_syntax = 1,
22024 : e_token = 2,
22025 : e_numeric = 4,
22026 : e_symtab = 5,
22027 : e_lexer = 6,
22028 : e_synthesis = 7,
22029 : e_helper = 8,
22030 : e_parser = 9
22031 : };
22032 :
22033 : struct type
22034 : {
22035 43680 : type()
22036 87360 : : mode(parser_error::e_unknown)
22037 43680 : , line_no (0)
22038 43680 : , column_no(0)
22039 43680 : {}
22040 :
22041 : lexer::token token;
22042 : error_mode mode;
22043 : std::string diagnostic;
22044 : std::string src_location;
22045 : std::string error_line;
22046 : std::size_t line_no;
22047 : std::size_t column_no;
22048 : };
22049 :
22050 1 : inline type make_error(const error_mode mode,
22051 : const std::string& diagnostic = "",
22052 : const std::string& src_location = "")
22053 : {
22054 1 : type t;
22055 1 : t.mode = mode;
22056 1 : t.token.type = lexer::token::e_error;
22057 1 : t.diagnostic = diagnostic;
22058 1 : t.src_location = src_location;
22059 : exprtk_debug(("%s\n", diagnostic .c_str()));
22060 1 : return t;
22061 0 : }
22062 :
22063 43679 : inline type make_error(const error_mode mode,
22064 : const lexer::token& tk,
22065 : const std::string& diagnostic = "",
22066 : const std::string& src_location = "")
22067 : {
22068 43679 : type t;
22069 43679 : t.mode = mode;
22070 43679 : t.token = tk;
22071 43679 : t.diagnostic = diagnostic;
22072 43679 : t.src_location = src_location;
22073 : exprtk_debug(("%s\n", diagnostic .c_str()));
22074 43679 : return t;
22075 0 : }
22076 :
22077 0 : inline std::string to_str(error_mode mode)
22078 : {
22079 0 : switch (mode)
22080 : {
22081 0 : case e_unknown : return std::string("Unknown Error");
22082 0 : case e_syntax : return std::string("Syntax Error" );
22083 0 : case e_token : return std::string("Token Error" );
22084 0 : case e_numeric : return std::string("Numeric Error");
22085 0 : case e_symtab : return std::string("Symbol Error" );
22086 0 : case e_lexer : return std::string("Lexer Error" );
22087 0 : case e_helper : return std::string("Helper Error" );
22088 0 : case e_parser : return std::string("Parser Error" );
22089 0 : default : return std::string("Unknown Error");
22090 : }
22091 : }
22092 :
22093 0 : inline bool update_error(type& error, const std::string& expression)
22094 : {
22095 0 : if (
22096 0 : expression.empty() ||
22097 0 : (error.token.position > expression.size()) ||
22098 0 : (std::numeric_limits<std::size_t>::max() == error.token.position)
22099 : )
22100 : {
22101 0 : return false;
22102 : }
22103 :
22104 0 : std::size_t error_line_start = 0;
22105 :
22106 0 : for (std::size_t i = error.token.position; i > 0; --i)
22107 : {
22108 0 : const details::char_t c = expression[i];
22109 :
22110 0 : if (('\n' == c) || ('\r' == c))
22111 : {
22112 0 : error_line_start = i + 1;
22113 0 : break;
22114 : }
22115 : }
22116 :
22117 0 : std::size_t next_nl_position = std::min(expression.size(),
22118 0 : expression.find_first_of('\n',error.token.position + 1));
22119 :
22120 0 : error.column_no = error.token.position - error_line_start;
22121 0 : error.error_line = expression.substr(error_line_start,
22122 0 : next_nl_position - error_line_start);
22123 :
22124 0 : error.line_no = 0;
22125 :
22126 0 : for (std::size_t i = 0; i < next_nl_position; ++i)
22127 : {
22128 0 : if ('\n' == expression[i])
22129 0 : ++error.line_no;
22130 : }
22131 :
22132 0 : return true;
22133 : }
22134 :
22135 : inline void dump_error(const type& error)
22136 : {
22137 : printf("Position: %02d Type: [%s] Msg: %s\n",
22138 : static_cast<int>(error.token.position),
22139 : exprtk::parser_error::to_str(error.mode).c_str(),
22140 : error.diagnostic.c_str());
22141 : }
22142 : }
22143 :
22144 : namespace details
22145 : {
22146 : template <typename Parser>
22147 4 : inline void disable_type_checking(Parser& p)
22148 : {
22149 4 : p.state_.type_check_enabled = false;
22150 4 : }
22151 : }
22152 :
22153 : template <typename T>
22154 : class parser : public lexer::parser_helper
22155 : {
22156 : private:
22157 :
22158 : enum precedence_level
22159 : {
22160 : e_level00, e_level01, e_level02, e_level03, e_level04,
22161 : e_level05, e_level06, e_level07, e_level08, e_level09,
22162 : e_level10, e_level11, e_level12, e_level13, e_level14
22163 : };
22164 :
22165 : typedef const T& cref_t;
22166 : typedef const T const_t;
22167 : typedef ifunction<T> F;
22168 : typedef ivararg_function<T> VAF;
22169 : typedef igeneric_function<T> GF;
22170 : typedef ifunction<T> ifunction_t;
22171 : typedef ivararg_function<T> ivararg_function_t;
22172 : typedef igeneric_function<T> igeneric_function_t;
22173 : typedef details::expression_node<T> expression_node_t;
22174 : typedef details::literal_node<T> literal_node_t;
22175 : typedef details::unary_node<T> unary_node_t;
22176 : typedef details::binary_node<T> binary_node_t;
22177 : typedef details::trinary_node<T> trinary_node_t;
22178 : typedef details::quaternary_node<T> quaternary_node_t;
22179 : typedef details::conditional_node<T> conditional_node_t;
22180 : typedef details::cons_conditional_node<T> cons_conditional_node_t;
22181 : typedef details::while_loop_node<T> while_loop_node_t;
22182 : typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
22183 : typedef details::for_loop_node<T> for_loop_node_t;
22184 : typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t;
22185 : typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t;
22186 : typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t;
22187 : #ifndef exprtk_disable_break_continue
22188 : typedef details::while_loop_bc_node<T> while_loop_bc_node_t;
22189 : typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
22190 : typedef details::for_loop_bc_node<T> for_loop_bc_node_t;
22191 : typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t;
22192 : typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t;
22193 : typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t;
22194 : #endif
22195 : typedef details::switch_node<T> switch_node_t;
22196 : typedef details::variable_node<T> variable_node_t;
22197 : typedef details::vector_elem_node<T> vector_elem_node_t;
22198 : typedef details::vector_celem_node<T> vector_celem_node_t;
22199 : typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t;
22200 : typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t;
22201 : typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t;
22202 : typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
22203 : typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t;
22204 : typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t;
22205 : typedef details::vector_node<T> vector_node_t;
22206 : typedef details::vector_size_node<T> vector_size_node_t;
22207 : typedef details::range_pack<T> range_t;
22208 : #ifndef exprtk_disable_string_capabilities
22209 : typedef details::stringvar_node<T> stringvar_node_t;
22210 : typedef details::string_literal_node<T> string_literal_node_t;
22211 : typedef details::string_range_node<T> string_range_node_t;
22212 : typedef details::const_string_range_node<T> const_string_range_node_t;
22213 : typedef details::generic_string_range_node<T> generic_string_range_node_t;
22214 : typedef details::string_concat_node<T> string_concat_node_t;
22215 : typedef details::assignment_string_node<T> assignment_string_node_t;
22216 : typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
22217 : typedef details::conditional_string_node<T> conditional_string_node_t;
22218 : typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
22219 : #endif
22220 : typedef details::assignment_node<T> assignment_node_t;
22221 : typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t;
22222 : typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t;
22223 : typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t;
22224 : typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t;
22225 : typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
22226 : typedef details::assignment_vec_node<T> assignment_vec_node_t;
22227 : typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t;
22228 : typedef details::conditional_vector_node<T> conditional_vector_node_t;
22229 : typedef details::scand_node<T> scand_node_t;
22230 : typedef details::scor_node<T> scor_node_t;
22231 : typedef lexer::token token_t;
22232 : typedef expression_node_t* expression_node_ptr;
22233 : typedef expression<T> expression_t;
22234 : typedef symbol_table<T> symbol_table_t;
22235 : typedef typename expression<T>::symtab_list_t symbol_table_list_t;
22236 : typedef details::vector_holder<T> vector_holder_t;
22237 : typedef vector_holder_t* vector_holder_ptr;
22238 :
22239 : typedef typename details::functor_t<T> functor_t;
22240 : typedef typename functor_t::qfunc_t quaternary_functor_t;
22241 : typedef typename functor_t::tfunc_t trinary_functor_t;
22242 : typedef typename functor_t::bfunc_t binary_functor_t;
22243 : typedef typename functor_t::ufunc_t unary_functor_t;
22244 :
22245 : typedef details::operator_type operator_t;
22246 :
22247 : typedef std::map<operator_t, unary_functor_t > unary_op_map_t;
22248 : typedef std::map<operator_t, binary_functor_t > binary_op_map_t;
22249 : typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t;
22250 :
22251 : typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
22252 : typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
22253 :
22254 : typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
22255 : typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
22256 : typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
22257 :
22258 : typedef details::T0oT1_define<T, cref_t , cref_t > vov_t;
22259 : typedef details::T0oT1_define<T, const_t, cref_t > cov_t;
22260 : typedef details::T0oT1_define<T, cref_t , const_t> voc_t;
22261 :
22262 : typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t;
22263 : typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t;
22264 : typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t;
22265 : typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t;
22266 : typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t;
22267 : typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t;
22268 : typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t;
22269 :
22270 : typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t;
22271 : typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t;
22272 : typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t;
22273 : typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t;
22274 : typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t;
22275 :
22276 : typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t;
22277 : typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t;
22278 : typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t;
22279 : typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t;
22280 :
22281 : typedef results_context<T> results_context_t;
22282 :
22283 : typedef parser_helper prsrhlpr_t;
22284 :
22285 : struct scope_element
22286 : {
22287 : enum element_type
22288 : {
22289 : e_none ,
22290 : e_literal ,
22291 : e_variable,
22292 : e_vector ,
22293 : e_vecelem ,
22294 : e_string
22295 : };
22296 :
22297 : typedef details::vector_holder<T> vector_holder_t;
22298 : typedef literal_node_t* literal_node_ptr;
22299 : typedef variable_node_t* variable_node_ptr;
22300 : typedef vector_holder_t* vector_holder_ptr;
22301 : typedef expression_node_t* expression_node_ptr;
22302 : #ifndef exprtk_disable_string_capabilities
22303 : typedef stringvar_node_t* stringvar_node_ptr;
22304 : #endif
22305 :
22306 200318 : scope_element()
22307 400636 : : name("???")
22308 200318 : , size (std::numeric_limits<std::size_t>::max())
22309 200318 : , index(std::numeric_limits<std::size_t>::max())
22310 200318 : , depth(std::numeric_limits<std::size_t>::max())
22311 200318 : , ref_count(0)
22312 200318 : , ip_index (0)
22313 200318 : , type (e_none)
22314 200318 : , active (false)
22315 200318 : , data (0)
22316 200318 : , var_node (0)
22317 200318 : , vec_node (0)
22318 : #ifndef exprtk_disable_string_capabilities
22319 200318 : , str_node(0)
22320 : #endif
22321 200318 : {}
22322 :
22323 209277 : bool operator < (const scope_element& se) const
22324 : {
22325 209277 : if (ip_index < se.ip_index)
22326 2 : return true;
22327 209275 : else if (ip_index > se.ip_index)
22328 7040 : return false;
22329 202235 : else if (depth < se.depth)
22330 919 : return true;
22331 201316 : else if (depth > se.depth)
22332 6768 : return false;
22333 194548 : else if (index < se.index)
22334 15660 : return true;
22335 178888 : else if (index > se.index)
22336 41916 : return false;
22337 : else
22338 136972 : return (name < se.name);
22339 : }
22340 :
22341 47184 : void clear()
22342 : {
22343 47184 : name = "???";
22344 47184 : size = std::numeric_limits<std::size_t>::max();
22345 47184 : index = std::numeric_limits<std::size_t>::max();
22346 47184 : depth = std::numeric_limits<std::size_t>::max();
22347 47184 : type = e_none;
22348 47184 : active = false;
22349 47184 : ref_count = 0;
22350 47184 : ip_index = 0;
22351 47184 : data = 0;
22352 47184 : var_node = 0;
22353 47184 : vec_node = 0;
22354 : #ifndef exprtk_disable_string_capabilities
22355 47184 : str_node = 0;
22356 : #endif
22357 47184 : }
22358 :
22359 : std::string name;
22360 : std::size_t size;
22361 : std::size_t index;
22362 : std::size_t depth;
22363 : std::size_t ref_count;
22364 : std::size_t ip_index;
22365 : element_type type;
22366 : bool active;
22367 : void* data;
22368 : expression_node_ptr var_node;
22369 : vector_holder_ptr vec_node;
22370 : #ifndef exprtk_disable_string_capabilities
22371 : stringvar_node_ptr str_node;
22372 : #endif
22373 : };
22374 :
22375 : class scope_element_manager
22376 : {
22377 : public:
22378 :
22379 : typedef expression_node_t* expression_node_ptr;
22380 : typedef variable_node_t* variable_node_ptr;
22381 : typedef parser<T> parser_t;
22382 :
22383 108660 : explicit scope_element_manager(parser<T>& p)
22384 108660 : : parser_(p)
22385 108660 : , input_param_cnt_(0)
22386 108660 : {}
22387 :
22388 450721 : inline std::size_t size() const
22389 : {
22390 450721 : return element_.size();
22391 : }
22392 :
22393 257179 : inline bool empty() const
22394 : {
22395 257179 : return element_.empty();
22396 : }
22397 :
22398 91562 : inline scope_element& get_element(const std::size_t& index)
22399 : {
22400 91562 : if (index < element_.size())
22401 91562 : return element_[index];
22402 : else
22403 0 : return null_element_;
22404 : }
22405 :
22406 177539 : inline scope_element& get_element(const std::string& var_name,
22407 : const std::size_t index = std::numeric_limits<std::size_t>::max())
22408 : {
22409 177539 : const std::size_t current_depth = parser_.state_.scope_depth;
22410 :
22411 350384 : for (std::size_t i = 0; i < element_.size(); ++i)
22412 : {
22413 180047 : scope_element& se = element_[i];
22414 :
22415 180047 : if (se.depth > current_depth)
22416 1524 : continue;
22417 178523 : else if (
22418 206306 : details::imatch(se.name, var_name) &&
22419 27783 : (se.index == index)
22420 : )
22421 7202 : return se;
22422 : }
22423 :
22424 170337 : return null_element_;
22425 : }
22426 :
22427 252592 : inline scope_element& get_active_element(const std::string& var_name,
22428 : const std::size_t index = std::numeric_limits<std::size_t>::max())
22429 : {
22430 252592 : const std::size_t current_depth = parser_.state_.scope_depth;
22431 :
22432 439396 : for (std::size_t i = 0; i < element_.size(); ++i)
22433 : {
22434 372947 : scope_element& se = element_[i];
22435 :
22436 372947 : if (se.depth > current_depth)
22437 38 : continue;
22438 372909 : else if (
22439 372909 : details::imatch(se.name, var_name) &&
22440 559292 : (se.index == index) &&
22441 186383 : (se.active)
22442 : )
22443 186143 : return se;
22444 : }
22445 :
22446 66449 : return null_element_;
22447 : }
22448 :
22449 91658 : inline bool add_element(const scope_element& se)
22450 : {
22451 194164 : for (std::size_t i = 0; i < element_.size(); ++i)
22452 : {
22453 102506 : scope_element& cse = element_[i];
22454 :
22455 102506 : if (
22456 102506 : details::imatch(cse.name, se.name) &&
22457 22239 : (cse.depth <= se.depth) &&
22458 21319 : (cse.index == se.index) &&
22459 1120 : (cse.size == se.size ) &&
22460 124905 : (cse.type == se.type ) &&
22461 160 : (cse.active)
22462 : )
22463 0 : return false;
22464 : }
22465 :
22466 91658 : element_.push_back(se);
22467 91658 : std::sort(element_.begin(),element_.end());
22468 :
22469 91658 : return true;
22470 : }
22471 :
22472 23679 : inline void deactivate(const std::size_t& scope_depth)
22473 : {
22474 : exprtk_debug(("deactivate() - Scope depth: %d\n",
22475 : static_cast<int>(parser_.state_.scope_depth)));
22476 :
22477 74454 : for (std::size_t i = 0; i < element_.size(); ++i)
22478 : {
22479 50775 : scope_element& se = element_[i];
22480 :
22481 50775 : if (se.active && (se.depth >= scope_depth))
22482 : {
22483 : exprtk_debug(("deactivate() - element[%02d] '%s'\n",
22484 : static_cast<int>(i),
22485 : se.name.c_str()));
22486 :
22487 27407 : se.active = false;
22488 : }
22489 : }
22490 23679 : }
22491 :
22492 47184 : inline void free_element(scope_element& se)
22493 : {
22494 : exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
22495 :
22496 47184 : switch (se.type)
22497 : {
22498 2635 : case scope_element::e_literal : delete reinterpret_cast<T*>(se.data);
22499 2635 : delete se.var_node;
22500 2635 : break;
22501 :
22502 22133 : case scope_element::e_variable : delete reinterpret_cast<T*>(se.data);
22503 22133 : delete se.var_node;
22504 22133 : break;
22505 :
22506 15785 : case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data);
22507 15785 : delete se.vec_node;
22508 15785 : break;
22509 :
22510 5821 : case scope_element::e_vecelem : delete se.var_node;
22511 5821 : break;
22512 :
22513 : #ifndef exprtk_disable_string_capabilities
22514 810 : case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data);
22515 810 : delete se.str_node;
22516 810 : break;
22517 : #endif
22518 :
22519 0 : default : return;
22520 : }
22521 :
22522 47184 : se.clear();
22523 : }
22524 :
22525 391685 : inline void cleanup()
22526 : {
22527 438869 : for (std::size_t i = 0; i < element_.size(); ++i)
22528 : {
22529 47184 : free_element(element_[i]);
22530 : }
22531 :
22532 391685 : element_.clear();
22533 :
22534 391685 : input_param_cnt_ = 0;
22535 391685 : }
22536 :
22537 2140 : inline std::size_t next_ip_index()
22538 : {
22539 2140 : return ++input_param_cnt_;
22540 : }
22541 :
22542 320 : inline expression_node_ptr get_variable(const T& v)
22543 : {
22544 480 : for (std::size_t i = 0; i < element_.size(); ++i)
22545 : {
22546 480 : scope_element& se = element_[i];
22547 :
22548 480 : if (
22549 960 : se.active &&
22550 960 : se.var_node &&
22551 480 : details::is_variable_node(se.var_node)
22552 : )
22553 : {
22554 480 : variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
22555 :
22556 480 : if (&(vn->ref()) == (&v))
22557 : {
22558 320 : return se.var_node;
22559 : }
22560 : }
22561 : }
22562 :
22563 0 : return expression_node_ptr(0);
22564 : }
22565 :
22566 660 : inline std::string get_vector_name(const T* data)
22567 : {
22568 2603 : for (std::size_t i = 0; i < element_.size(); ++i)
22569 : {
22570 1943 : scope_element& se = element_[i];
22571 :
22572 1943 : if (
22573 3886 : se.active &&
22574 2521 : se.vec_node &&
22575 578 : (se.vec_node->data() == data)
22576 : )
22577 : {
22578 0 : return se.name;
22579 : }
22580 : }
22581 :
22582 1320 : return "neo-vector";
22583 : }
22584 :
22585 : private:
22586 :
22587 : scope_element_manager(const scope_element_manager&) exprtk_delete;
22588 : scope_element_manager& operator=(const scope_element_manager&) exprtk_delete;
22589 :
22590 : parser_t& parser_;
22591 : std::vector<scope_element> element_;
22592 : scope_element null_element_;
22593 : std::size_t input_param_cnt_;
22594 : };
22595 :
22596 : class scope_handler
22597 : {
22598 : public:
22599 :
22600 : typedef parser<T> parser_t;
22601 :
22602 23679 : explicit scope_handler(parser<T>& p)
22603 23679 : : parser_(p)
22604 : {
22605 23679 : parser_.state_.scope_depth++;
22606 : #ifdef exprtk_enable_debugging
22607 : const std::string depth(2 * parser_.state_.scope_depth,'-');
22608 : exprtk_debug(("%s> Scope Depth: %02d\n",
22609 : depth.c_str(),
22610 : static_cast<int>(parser_.state_.scope_depth)));
22611 : #endif
22612 23679 : }
22613 :
22614 23679 : ~scope_handler()
22615 : {
22616 23679 : parser_.sem_.deactivate(parser_.state_.scope_depth);
22617 23679 : parser_.state_.scope_depth--;
22618 : #ifdef exprtk_enable_debugging
22619 : const std::string depth(2 * parser_.state_.scope_depth,'-');
22620 : exprtk_debug(("<%s Scope Depth: %02d\n",
22621 : depth.c_str(),
22622 : static_cast<int>(parser_.state_.scope_depth)));
22623 : #endif
22624 23679 : }
22625 :
22626 : private:
22627 :
22628 : scope_handler(const scope_handler&) exprtk_delete;
22629 : scope_handler& operator=(const scope_handler&) exprtk_delete;
22630 :
22631 : parser_t& parser_;
22632 : };
22633 :
22634 : template <typename T_>
22635 : struct halfopen_range_policy
22636 : {
22637 51 : static inline bool is_within(const T_& v, const T_& begin, const T_& end)
22638 : {
22639 51 : assert(begin <= end);
22640 51 : return (begin <= v) && (v < end);
22641 : }
22642 :
22643 : static inline bool is_less(const T_& v, const T_& begin)
22644 : {
22645 : return (v < begin);
22646 : }
22647 :
22648 20 : static inline bool is_greater(const T_& v, const T_& end)
22649 : {
22650 20 : return (end <= v);
22651 : }
22652 :
22653 76789 : static inline bool end_inclusive()
22654 : {
22655 76789 : return false;
22656 : }
22657 : };
22658 :
22659 : template <typename T_>
22660 : struct closed_range_policy
22661 : {
22662 : static inline bool is_within(const T_& v, const T_& begin, const T_& end)
22663 : {
22664 : assert(begin <= end);
22665 : return (begin <= v) && (v <= end);
22666 : }
22667 :
22668 : static inline bool is_less(const T_& v, const T_& begin)
22669 : {
22670 : return (v < begin);
22671 : }
22672 :
22673 : static inline bool is_greater(const T_& v, const T_& end)
22674 : {
22675 : return (end < v);
22676 : }
22677 :
22678 : static inline bool end_inclusive()
22679 : {
22680 : return true;
22681 : }
22682 : };
22683 :
22684 : template <typename IntervalPointType,
22685 : typename RangePolicy = halfopen_range_policy<IntervalPointType> >
22686 : class interval_container_t
22687 : {
22688 : public:
22689 :
22690 : typedef IntervalPointType interval_point_t;
22691 : typedef std::pair<interval_point_t, interval_point_t> interval_t;
22692 : typedef std::map<interval_point_t, interval_t> interval_map_t;
22693 : typedef typename interval_map_t::const_iterator interval_map_citr_t;
22694 :
22695 : std::size_t size() const
22696 : {
22697 : return interval_map_.size();
22698 : }
22699 :
22700 380686 : void reset()
22701 : {
22702 380686 : interval_map_.clear();
22703 380686 : }
22704 :
22705 76789 : bool in_interval(const interval_point_t point, interval_t& interval) const
22706 : {
22707 76789 : interval_map_citr_t itr = RangePolicy::end_inclusive() ?
22708 0 : interval_map_.lower_bound(point):
22709 76789 : interval_map_.upper_bound(point);
22710 :
22711 76809 : for (; itr != interval_map_.end(); ++itr)
22712 : {
22713 51 : const interval_point_t& begin = itr->second.first;
22714 51 : const interval_point_t& end = itr->second.second;
22715 :
22716 51 : if (RangePolicy::is_within(point, begin, end))
22717 : {
22718 31 : interval = interval_t(begin,end);
22719 31 : return true;
22720 : }
22721 20 : else if (RangePolicy::is_greater(point, end))
22722 : {
22723 0 : break;
22724 : }
22725 : }
22726 :
22727 76758 : return false;
22728 : }
22729 :
22730 107 : bool in_interval(const interval_point_t point) const
22731 : {
22732 107 : interval_t interval;
22733 214 : return in_interval(point,interval);
22734 : }
22735 :
22736 55 : bool add_interval(const interval_point_t begin, const interval_point_t end)
22737 : {
22738 55 : if ((end <= begin) || in_interval(begin) || in_interval(end))
22739 : {
22740 3 : return false;
22741 : }
22742 :
22743 52 : interval_map_[end] = std::make_pair(begin, end);
22744 :
22745 52 : return true;
22746 : }
22747 :
22748 55 : bool add_interval(const interval_t interval)
22749 : {
22750 55 : return add_interval(interval.first, interval.second);
22751 : }
22752 :
22753 : private:
22754 :
22755 : interval_map_t interval_map_;
22756 : };
22757 :
22758 : class stack_limit_handler
22759 : {
22760 : public:
22761 :
22762 : typedef parser<T> parser_t;
22763 :
22764 12693582 : explicit stack_limit_handler(parser<T>& p)
22765 12693582 : : parser_(p)
22766 12693582 : , limit_exceeded_(false)
22767 : {
22768 12693582 : if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
22769 : {
22770 0 : limit_exceeded_ = true;
22771 0 : parser_.set_error(make_error(
22772 : parser_error::e_parser,
22773 0 : "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
22774 0 : " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
22775 : exprtk_error_location));
22776 : }
22777 12693582 : }
22778 :
22779 12693582 : ~stack_limit_handler()
22780 : {
22781 12693582 : assert(parser_.state_.stack_depth > 0);
22782 12693582 : parser_.state_.stack_depth--;
22783 12693582 : }
22784 :
22785 12693582 : bool operator!()
22786 : {
22787 12693582 : return limit_exceeded_;
22788 : }
22789 :
22790 : private:
22791 :
22792 : stack_limit_handler(const stack_limit_handler&) exprtk_delete;
22793 : stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete;
22794 :
22795 : parser_t& parser_;
22796 : bool limit_exceeded_;
22797 : };
22798 :
22799 : struct symtab_store
22800 : {
22801 : symbol_table_list_t symtab_list_;
22802 :
22803 : typedef typename symbol_table_t::local_data_t local_data_t;
22804 : typedef typename symbol_table_t::variable_ptr variable_ptr;
22805 : typedef typename symbol_table_t::function_ptr function_ptr;
22806 : #ifndef exprtk_disable_string_capabilities
22807 : typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
22808 : #endif
22809 : typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr;
22810 : typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr;
22811 : typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
22812 :
22813 : struct variable_context
22814 : {
22815 2057676 : variable_context()
22816 2057676 : : symbol_table(0)
22817 2057676 : , variable(0)
22818 2057676 : {}
22819 :
22820 : const symbol_table_t* symbol_table;
22821 : variable_ptr variable;
22822 : };
22823 :
22824 : struct vector_context
22825 : {
22826 6869 : vector_context()
22827 6869 : : symbol_table(0)
22828 6869 : , vector_holder(0)
22829 6869 : {}
22830 :
22831 : const symbol_table_t* symbol_table;
22832 : vector_holder_ptr vector_holder;
22833 : };
22834 :
22835 : #ifndef exprtk_disable_string_capabilities
22836 : struct string_context
22837 : {
22838 49475 : string_context()
22839 49475 : : symbol_table(0)
22840 49475 : , str_var(0)
22841 49475 : {}
22842 :
22843 : const symbol_table_t* symbol_table;
22844 : stringvar_ptr str_var;
22845 : };
22846 : #endif
22847 :
22848 2055564 : inline bool empty() const
22849 : {
22850 2055564 : return symtab_list_.empty();
22851 : }
22852 :
22853 : inline void clear()
22854 : {
22855 : symtab_list_.clear();
22856 : }
22857 :
22858 2055564 : inline bool valid() const
22859 : {
22860 2055564 : if (!empty())
22861 : {
22862 2055396 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22863 : {
22864 2055396 : if (symtab_list_[i].valid())
22865 2055396 : return true;
22866 : }
22867 : }
22868 :
22869 168 : return false;
22870 : }
22871 :
22872 3970164 : inline bool valid_symbol(const std::string& symbol) const
22873 : {
22874 3970164 : if (!symtab_list_.empty())
22875 3970090 : return symtab_list_[0].valid_symbol(symbol);
22876 : else
22877 74 : return false;
22878 : }
22879 :
22880 185503 : inline bool valid_function_name(const std::string& symbol) const
22881 : {
22882 185503 : if (!symtab_list_.empty())
22883 185443 : return symtab_list_[0].valid_function(symbol);
22884 : else
22885 60 : return false;
22886 : }
22887 :
22888 2057676 : inline variable_context get_variable_context(const std::string& variable_name) const
22889 : {
22890 2057676 : variable_context result;
22891 :
22892 2057676 : if (valid_symbol(variable_name))
22893 : {
22894 2377584 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22895 : {
22896 2123070 : if (!symtab_list_[i].valid())
22897 : {
22898 0 : continue;
22899 : }
22900 :
22901 2123070 : result.variable = local_data(i)
22902 2123070 : .variable_store.get(variable_name);
22903 2123070 : if (result.variable)
22904 : {
22905 1800665 : result.symbol_table = &symtab_list_[i];
22906 1800665 : break;
22907 : }
22908 : }
22909 : }
22910 :
22911 2057676 : return result;
22912 : }
22913 :
22914 3002 : inline variable_ptr get_variable(const std::string& variable_name) const
22915 : {
22916 3002 : if (!valid_symbol(variable_name))
22917 0 : return reinterpret_cast<variable_ptr>(0);
22918 :
22919 3002 : variable_ptr result = reinterpret_cast<variable_ptr>(0);
22920 :
22921 3002 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22922 : {
22923 3002 : if (!symtab_list_[i].valid())
22924 0 : continue;
22925 : else
22926 3002 : result = local_data(i)
22927 3002 : .variable_store.get(variable_name);
22928 :
22929 3002 : if (result) break;
22930 : }
22931 :
22932 3002 : return result;
22933 : }
22934 :
22935 320 : inline variable_ptr get_variable(const T& var_ref) const
22936 : {
22937 320 : variable_ptr result = reinterpret_cast<variable_ptr>(0);
22938 :
22939 640 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22940 : {
22941 320 : if (!symtab_list_[i].valid())
22942 0 : continue;
22943 : else
22944 320 : result = local_data(i).variable_store
22945 320 : .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
22946 :
22947 320 : if (result) break;
22948 : }
22949 :
22950 320 : return result;
22951 : }
22952 :
22953 : #ifndef exprtk_disable_string_capabilities
22954 49475 : inline string_context get_string_context(const std::string& string_name) const
22955 : {
22956 49475 : string_context result;
22957 :
22958 49475 : if (!valid_symbol(string_name))
22959 0 : return result;
22960 :
22961 49475 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22962 : {
22963 49475 : if (!symtab_list_[i].valid())
22964 : {
22965 0 : continue;
22966 : }
22967 :
22968 49475 : result.str_var = local_data(i).stringvar_store.get(string_name);
22969 :
22970 49475 : if (result.str_var)
22971 : {
22972 49475 : result.symbol_table = &symtab_list_[i];
22973 49475 : break;
22974 : }
22975 : }
22976 :
22977 49475 : return result;
22978 : }
22979 :
22980 : inline stringvar_ptr get_stringvar(const std::string& string_name) const
22981 : {
22982 : if (!valid_symbol(string_name))
22983 : return reinterpret_cast<stringvar_ptr>(0);
22984 :
22985 : stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
22986 :
22987 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
22988 : {
22989 : if (!symtab_list_[i].valid())
22990 : continue;
22991 : else
22992 : result = local_data(i)
22993 : .stringvar_store.get(string_name);
22994 :
22995 : if (result) break;
22996 : }
22997 :
22998 : return result;
22999 : }
23000 : #endif
23001 :
23002 87026 : inline function_ptr get_function(const std::string& function_name) const
23003 : {
23004 87026 : if (!valid_function_name(function_name))
23005 35 : return reinterpret_cast<function_ptr>(0);
23006 :
23007 86991 : function_ptr result = reinterpret_cast<function_ptr>(0);
23008 :
23009 131404 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23010 : {
23011 105024 : if (!symtab_list_[i].valid())
23012 0 : continue;
23013 : else
23014 105024 : result = local_data(i)
23015 105024 : .function_store.get(function_name);
23016 :
23017 105024 : if (result) break;
23018 : }
23019 :
23020 86991 : return result;
23021 : }
23022 :
23023 26415 : inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
23024 : {
23025 26415 : if (!valid_function_name(vararg_function_name))
23026 35 : return reinterpret_cast<vararg_function_ptr>(0);
23027 :
23028 26380 : vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
23029 :
23030 68344 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23031 : {
23032 42013 : if (!symtab_list_[i].valid())
23033 0 : continue;
23034 : else
23035 42013 : result = local_data(i)
23036 42013 : .vararg_function_store.get(vararg_function_name);
23037 :
23038 42013 : if (result) break;
23039 : }
23040 :
23041 26380 : return result;
23042 : }
23043 :
23044 26366 : inline generic_function_ptr get_generic_function(const std::string& function_name) const
23045 : {
23046 26366 : if (!valid_function_name(function_name))
23047 35 : return reinterpret_cast<generic_function_ptr>(0);
23048 :
23049 26331 : generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
23050 :
23051 64795 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23052 : {
23053 41964 : if (!symtab_list_[i].valid())
23054 0 : continue;
23055 : else
23056 41964 : result = local_data(i)
23057 41964 : .generic_function_store.get(function_name);
23058 :
23059 41964 : if (result) break;
23060 : }
23061 :
23062 26331 : return result;
23063 : }
23064 :
23065 22866 : inline generic_function_ptr get_string_function(const std::string& function_name) const
23066 : {
23067 22866 : if (!valid_function_name(function_name))
23068 35 : return reinterpret_cast<generic_function_ptr>(0);
23069 :
23070 22831 : generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
23071 :
23072 61259 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23073 : {
23074 38464 : if (!symtab_list_[i].valid())
23075 0 : continue;
23076 : else
23077 : result =
23078 38464 : local_data(i).string_function_store.get(function_name);
23079 :
23080 38464 : if (result) break;
23081 : }
23082 :
23083 22831 : return result;
23084 : }
23085 :
23086 22830 : inline generic_function_ptr get_overload_function(const std::string& function_name) const
23087 : {
23088 22830 : if (!valid_function_name(function_name))
23089 35 : return reinterpret_cast<generic_function_ptr>(0);
23090 :
23091 22795 : generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
23092 :
23093 61151 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23094 : {
23095 38428 : if (!symtab_list_[i].valid())
23096 0 : continue;
23097 : else
23098 : result =
23099 38428 : local_data(i).overload_function_store.get(function_name);
23100 :
23101 38428 : if (result) break;
23102 : }
23103 :
23104 22795 : return result;
23105 : }
23106 :
23107 6869 : inline vector_context get_vector_context(const std::string& vector_name) const
23108 : {
23109 6869 : vector_context result;
23110 6869 : if (!valid_symbol(vector_name))
23111 0 : return result;
23112 :
23113 6869 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23114 : {
23115 6869 : if (!symtab_list_[i].valid())
23116 : {
23117 0 : continue;
23118 : }
23119 :
23120 6869 : result.vector_holder = local_data(i).vector_store.get(vector_name);
23121 :
23122 6869 : if (result.vector_holder)
23123 : {
23124 6869 : result.symbol_table = &symtab_list_[i];
23125 6869 : break;
23126 : }
23127 : }
23128 :
23129 6869 : return result;
23130 : }
23131 :
23132 : inline vector_holder_ptr get_vector(const std::string& vector_name) const
23133 : {
23134 : if (!valid_symbol(vector_name))
23135 : return reinterpret_cast<vector_holder_ptr>(0);
23136 :
23137 : vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
23138 :
23139 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23140 : {
23141 : if (!symtab_list_[i].valid())
23142 : {
23143 : continue;
23144 : }
23145 :
23146 : result = local_data(i).vector_store.get(vector_name);
23147 :
23148 : if (result)
23149 : {
23150 : break;
23151 : }
23152 : }
23153 :
23154 : return result;
23155 : }
23156 :
23157 1803667 : inline bool is_constant_node(const std::string& symbol_name) const
23158 : {
23159 1803667 : if (!valid_symbol(symbol_name))
23160 0 : return false;
23161 :
23162 3665513 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23163 : {
23164 1906596 : if (!symtab_list_[i].valid())
23165 : {
23166 0 : continue;
23167 : }
23168 :
23169 1906596 : if (local_data(i).variable_store.is_constant(symbol_name))
23170 : {
23171 44750 : return true;
23172 : }
23173 : }
23174 :
23175 1758917 : return false;
23176 : }
23177 :
23178 : #ifndef exprtk_disable_string_capabilities
23179 49475 : inline bool is_constant_string(const std::string& symbol_name) const
23180 : {
23181 49475 : if (!valid_symbol(symbol_name))
23182 0 : return false;
23183 :
23184 98974 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23185 : {
23186 49499 : if (!symtab_list_[i].valid())
23187 0 : continue;
23188 49499 : else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
23189 24 : continue;
23190 49475 : else if (local_data(i).stringvar_store.is_constant(symbol_name))
23191 0 : return true;
23192 : }
23193 :
23194 49475 : return false;
23195 : }
23196 : #endif
23197 :
23198 82250 : inline bool symbol_exists(const std::string& symbol) const
23199 : {
23200 164443 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23201 : {
23202 82193 : if (!symtab_list_[i].valid())
23203 : {
23204 0 : continue;
23205 : }
23206 :
23207 82193 : if (symtab_list_[i].symbol_exists(symbol))
23208 : {
23209 0 : return true;
23210 : }
23211 : }
23212 :
23213 82250 : return false;
23214 : }
23215 :
23216 400 : inline bool is_variable(const std::string& variable_name) const
23217 : {
23218 800 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23219 : {
23220 400 : if (!symtab_list_[i].valid())
23221 0 : continue;
23222 400 : else if (
23223 400 : symtab_list_[i].local_data().variable_store
23224 400 : .symbol_exists(variable_name)
23225 : )
23226 0 : return true;
23227 : }
23228 :
23229 400 : return false;
23230 : }
23231 :
23232 : #ifndef exprtk_disable_string_capabilities
23233 136501 : inline bool is_stringvar(const std::string& stringvar_name) const
23234 : {
23235 245748 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23236 : {
23237 158722 : if (!symtab_list_[i].valid())
23238 0 : continue;
23239 158722 : else if (
23240 158722 : symtab_list_[i].local_data().stringvar_store
23241 158722 : .symbol_exists(stringvar_name)
23242 : )
23243 49475 : return true;
23244 : }
23245 :
23246 87026 : return false;
23247 : }
23248 :
23249 49475 : inline bool is_conststr_stringvar(const std::string& symbol_name) const
23250 : {
23251 49475 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23252 : {
23253 49475 : if (!symtab_list_[i].valid())
23254 0 : continue;
23255 49475 : else if (
23256 49475 : symtab_list_[i].local_data().stringvar_store
23257 49475 : .symbol_exists(symbol_name)
23258 : )
23259 : {
23260 : return (
23261 49475 : local_data(i).stringvar_store.symbol_exists(symbol_name) ||
23262 0 : local_data(i).stringvar_store.is_constant (symbol_name)
23263 49475 : );
23264 :
23265 : }
23266 : }
23267 :
23268 0 : return false;
23269 : }
23270 : #endif
23271 :
23272 : inline bool is_function(const std::string& function_name) const
23273 : {
23274 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23275 : {
23276 : if (!symtab_list_[i].valid())
23277 : continue;
23278 : else if (
23279 : local_data(i).vararg_function_store
23280 : .symbol_exists(function_name)
23281 : )
23282 : return true;
23283 : }
23284 :
23285 : return false;
23286 : }
23287 :
23288 : inline bool is_vararg_function(const std::string& vararg_function_name) const
23289 : {
23290 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23291 : {
23292 : if (!symtab_list_[i].valid())
23293 : continue;
23294 : else if (
23295 : local_data(i).vararg_function_store
23296 : .symbol_exists(vararg_function_name)
23297 : )
23298 : return true;
23299 : }
23300 :
23301 : return false;
23302 : }
23303 :
23304 22838 : inline bool is_vector(const std::string& vector_name) const
23305 : {
23306 54403 : for (std::size_t i = 0; i < symtab_list_.size(); ++i)
23307 : {
23308 38434 : if (!symtab_list_[i].valid())
23309 0 : continue;
23310 38434 : else if (
23311 38434 : local_data(i).vector_store
23312 38434 : .symbol_exists(vector_name)
23313 : )
23314 6869 : return true;
23315 : }
23316 :
23317 15969 : return false;
23318 : }
23319 :
23320 3 : inline std::string get_variable_name(const expression_node_ptr& ptr) const
23321 : {
23322 6 : return local_data().variable_store.entity_name(ptr);
23323 : }
23324 :
23325 0 : inline std::string get_vector_name(const vector_holder_ptr& ptr) const
23326 : {
23327 0 : return local_data().vector_store.entity_name(ptr);
23328 : }
23329 :
23330 : #ifndef exprtk_disable_string_capabilities
23331 1 : inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
23332 : {
23333 2 : return local_data().stringvar_store.entity_name(ptr);
23334 : }
23335 :
23336 : inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
23337 : {
23338 : return local_data().stringvar_store.entity_name(ptr);
23339 : }
23340 : #endif
23341 :
23342 : inline local_data_t& local_data(const std::size_t& index = 0)
23343 : {
23344 : return symtab_list_[index].local_data();
23345 : }
23346 :
23347 8 : inline const local_data_t& local_data(const std::size_t& index = 0) const
23348 : {
23349 4542112 : return symtab_list_[index].local_data();
23350 : }
23351 :
23352 15624 : inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
23353 : {
23354 5208 : return symtab_list_[index];
23355 : }
23356 : };
23357 :
23358 : struct parser_state
23359 : {
23360 108660 : parser_state()
23361 108660 : : type_check_enabled(true)
23362 : {
23363 108660 : reset();
23364 108660 : }
23365 :
23366 489346 : void reset()
23367 : {
23368 489346 : parsing_return_stmt = false;
23369 489346 : parsing_break_stmt = false;
23370 489346 : parsing_assert_stmt = false;
23371 489346 : return_stmt_present = false;
23372 489346 : side_effect_present = false;
23373 489346 : scope_depth = 0;
23374 489346 : stack_depth = 0;
23375 489346 : parsing_loop_stmt_count = 0;
23376 489346 : }
23377 :
23378 : #ifndef exprtk_enable_debugging
23379 280926 : void activate_side_effect(const std::string&)
23380 : #else
23381 : void activate_side_effect(const std::string& source)
23382 : #endif
23383 : {
23384 280926 : if (!side_effect_present)
23385 : {
23386 163728 : side_effect_present = true;
23387 :
23388 : exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str()));
23389 : }
23390 280926 : }
23391 :
23392 : bool parsing_return_stmt;
23393 : bool parsing_break_stmt;
23394 : bool parsing_assert_stmt;
23395 : bool return_stmt_present;
23396 : bool side_effect_present;
23397 : bool type_check_enabled;
23398 : std::size_t scope_depth;
23399 : std::size_t stack_depth;
23400 : std::size_t parsing_loop_stmt_count;
23401 : };
23402 :
23403 : public:
23404 :
23405 : struct unknown_symbol_resolver
23406 : {
23407 :
23408 : enum usr_symbol_type
23409 : {
23410 : e_usr_unknown_type = 0,
23411 : e_usr_variable_type = 1,
23412 : e_usr_constant_type = 2
23413 : };
23414 :
23415 : enum usr_mode
23416 : {
23417 : e_usrmode_default = 0,
23418 : e_usrmode_extended = 1
23419 : };
23420 :
23421 : usr_mode mode;
23422 :
23423 108864 : unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
23424 108864 : : mode(m)
23425 108864 : {}
23426 :
23427 108864 : virtual ~unknown_symbol_resolver()
23428 108864 : {}
23429 :
23430 2 : virtual bool process(const std::string& /*unknown_symbol*/,
23431 : usr_symbol_type& st,
23432 : T& default_value,
23433 : std::string& error_message)
23434 : {
23435 2 : if (e_usrmode_default != mode)
23436 0 : return false;
23437 :
23438 2 : st = e_usr_variable_type;
23439 2 : default_value = T(0);
23440 2 : error_message.clear();
23441 :
23442 2 : return true;
23443 : }
23444 :
23445 0 : virtual bool process(const std::string& /* unknown_symbol */,
23446 : symbol_table_t& /* symbol_table */,
23447 : std::string& /* error_message */)
23448 : {
23449 0 : return false;
23450 : }
23451 : };
23452 :
23453 : enum collect_type
23454 : {
23455 : e_ct_none = 0,
23456 : e_ct_variables = 1,
23457 : e_ct_functions = 2,
23458 : e_ct_assignments = 4
23459 : };
23460 :
23461 : enum symbol_type
23462 : {
23463 : e_st_unknown = 0,
23464 : e_st_variable = 1,
23465 : e_st_vector = 2,
23466 : e_st_vecelem = 3,
23467 : e_st_string = 4,
23468 : e_st_function = 5,
23469 : e_st_local_variable = 6,
23470 : e_st_local_vector = 7,
23471 : e_st_local_string = 8
23472 : };
23473 :
23474 : class dependent_entity_collector
23475 : {
23476 : public:
23477 :
23478 : typedef std::pair<std::string,symbol_type> symbol_t;
23479 : typedef std::vector<symbol_t> symbol_list_t;
23480 :
23481 108660 : dependent_entity_collector(const std::size_t options = e_ct_none)
23482 108660 : : options_(options)
23483 108660 : , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables )
23484 108660 : , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions )
23485 108660 : , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments)
23486 108660 : , return_present_ (false)
23487 108660 : , final_stmt_return_(false)
23488 108660 : {}
23489 :
23490 : template <typename Allocator,
23491 : template <typename, typename> class Sequence>
23492 3 : inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
23493 : {
23494 3 : if (!collect_variables_ && !collect_functions_)
23495 0 : return 0;
23496 3 : else if (symbol_name_list_.empty())
23497 0 : return 0;
23498 :
23499 23 : for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
23500 : {
23501 20 : details::case_normalise(symbol_name_list_[i].first);
23502 : }
23503 :
23504 3 : std::sort(symbol_name_list_.begin(), symbol_name_list_.end());
23505 :
23506 : std::unique_copy
23507 3 : (
23508 : symbol_name_list_.begin(),
23509 : symbol_name_list_.end (),
23510 : std::back_inserter(symbols_list)
23511 : );
23512 :
23513 3 : return symbols_list.size();
23514 : }
23515 :
23516 : template <typename Allocator,
23517 : template <typename, typename> class Sequence>
23518 1 : inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
23519 : {
23520 1 : if (!collect_assignments_)
23521 0 : return 0;
23522 1 : else if (assignment_name_list_.empty())
23523 0 : return 0;
23524 :
23525 5 : for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
23526 : {
23527 4 : details::case_normalise(assignment_name_list_[i].first);
23528 : }
23529 :
23530 1 : std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
23531 :
23532 : std::unique_copy
23533 1 : (
23534 : assignment_name_list_.begin(),
23535 : assignment_name_list_.end (),
23536 : std::back_inserter(assignment_list)
23537 : );
23538 :
23539 1 : return assignment_list.size();
23540 : }
23541 :
23542 381157 : void clear()
23543 : {
23544 381157 : symbol_name_list_ .clear();
23545 381157 : assignment_name_list_.clear();
23546 381157 : retparam_list_ .clear();
23547 381157 : return_present_ = false;
23548 381157 : final_stmt_return_ = false;
23549 381157 : }
23550 :
23551 108663 : bool& collect_variables()
23552 : {
23553 108663 : return collect_variables_;
23554 : }
23555 :
23556 108663 : bool& collect_functions()
23557 : {
23558 108663 : return collect_functions_;
23559 : }
23560 :
23561 185315 : bool& collect_assignments()
23562 : {
23563 185315 : return collect_assignments_;
23564 : }
23565 :
23566 1484 : bool return_present() const
23567 : {
23568 1484 : return return_present_;
23569 : }
23570 :
23571 : bool final_stmt_return() const
23572 : {
23573 : return final_stmt_return_;
23574 : }
23575 :
23576 : typedef std::vector<std::string> retparam_list_t;
23577 :
23578 0 : retparam_list_t return_param_type_list() const
23579 : {
23580 0 : return retparam_list_;
23581 : }
23582 :
23583 : private:
23584 :
23585 2427545 : inline void add_symbol(const std::string& symbol, const symbol_type st)
23586 : {
23587 2427545 : switch (st)
23588 : {
23589 2017783 : case e_st_variable :
23590 : case e_st_vector :
23591 : case e_st_string :
23592 : case e_st_local_variable :
23593 : case e_st_local_vector :
23594 2017783 : case e_st_local_string : if (collect_variables_)
23595 : symbol_name_list_
23596 19 : .push_back(std::make_pair(symbol, st));
23597 2017783 : break;
23598 :
23599 409762 : case e_st_function : if (collect_functions_)
23600 : symbol_name_list_
23601 5 : .push_back(std::make_pair(symbol, st));
23602 409762 : break;
23603 :
23604 0 : default : return;
23605 : }
23606 : }
23607 :
23608 4 : inline void add_assignment(const std::string& symbol, const symbol_type st)
23609 : {
23610 4 : switch (st)
23611 : {
23612 4 : case e_st_variable :
23613 : case e_st_vector :
23614 4 : case e_st_string : if (collect_assignments_)
23615 : assignment_name_list_
23616 4 : .push_back(std::make_pair(symbol, st));
23617 4 : break;
23618 :
23619 0 : default : return;
23620 : }
23621 : }
23622 :
23623 : std::size_t options_;
23624 : bool collect_variables_;
23625 : bool collect_functions_;
23626 : bool collect_assignments_;
23627 : bool return_present_;
23628 : bool final_stmt_return_;
23629 : symbol_list_t symbol_name_list_;
23630 : symbol_list_t assignment_name_list_;
23631 : retparam_list_t retparam_list_;
23632 :
23633 : friend class parser<T>;
23634 : };
23635 :
23636 : class settings_store
23637 : {
23638 : private:
23639 :
23640 : typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
23641 : typedef disabled_entity_set_t::iterator des_itr_t;
23642 :
23643 : public:
23644 :
23645 : enum settings_compilation_options
23646 : {
23647 : e_unknown = 0,
23648 : e_replacer = 1,
23649 : e_joiner = 2,
23650 : e_numeric_check = 4,
23651 : e_bracket_check = 8,
23652 : e_sequence_check = 16,
23653 : e_commutative_check = 32,
23654 : e_strength_reduction = 64,
23655 : e_disable_vardef = 128,
23656 : e_collect_vars = 256,
23657 : e_collect_funcs = 512,
23658 : e_collect_assings = 1024,
23659 : e_disable_usr_on_rsrvd = 2048,
23660 : e_disable_zero_return = 4096
23661 : };
23662 :
23663 : enum settings_base_funcs
23664 : {
23665 : e_bf_unknown = 0,
23666 : e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
23667 : e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
23668 : e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
23669 : e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
23670 : e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
23671 : e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
23672 : e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
23673 : e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
23674 : e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
23675 : e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
23676 : e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
23677 : e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
23678 : e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
23679 : e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad ,
23680 : e_bf_rad2deg , e_bf_grad2deg
23681 : };
23682 :
23683 : enum settings_control_structs
23684 : {
23685 : e_ctrl_unknown = 0,
23686 : e_ctrl_ifelse,
23687 : e_ctrl_switch,
23688 : e_ctrl_for_loop,
23689 : e_ctrl_while_loop,
23690 : e_ctrl_repeat_loop,
23691 : e_ctrl_return
23692 : };
23693 :
23694 : enum settings_logic_opr
23695 : {
23696 : e_logic_unknown = 0,
23697 : e_logic_and, e_logic_nand , e_logic_nor ,
23698 : e_logic_not, e_logic_or , e_logic_xnor,
23699 : e_logic_xor, e_logic_scand, e_logic_scor
23700 : };
23701 :
23702 : enum settings_arithmetic_opr
23703 : {
23704 : e_arith_unknown = 0,
23705 : e_arith_add, e_arith_sub, e_arith_mul,
23706 : e_arith_div, e_arith_mod, e_arith_pow
23707 : };
23708 :
23709 : enum settings_assignment_opr
23710 : {
23711 : e_assign_unknown = 0,
23712 : e_assign_assign, e_assign_addass, e_assign_subass,
23713 : e_assign_mulass, e_assign_divass, e_assign_modass
23714 : };
23715 :
23716 : enum settings_inequality_opr
23717 : {
23718 : e_ineq_unknown = 0,
23719 : e_ineq_lt , e_ineq_lte, e_ineq_eq ,
23720 : e_ineq_equal, e_ineq_ne , e_ineq_nequal,
23721 : e_ineq_gte , e_ineq_gt
23722 : };
23723 :
23724 : static const std::size_t default_compile_all_opts =
23725 : e_replacer +
23726 : e_joiner +
23727 : e_numeric_check +
23728 : e_bracket_check +
23729 : e_sequence_check +
23730 : e_commutative_check +
23731 : e_strength_reduction;
23732 :
23733 108660 : settings_store(const std::size_t compile_options = default_compile_all_opts)
23734 108660 : : max_stack_depth_(400)
23735 108660 : , max_node_depth_(10000)
23736 108660 : , max_local_vector_size_(2000000000)
23737 : {
23738 108660 : load_compile_options(compile_options);
23739 108660 : }
23740 :
23741 : settings_store& enable_all_base_functions()
23742 : {
23743 : disabled_func_set_.clear();
23744 : return (*this);
23745 : }
23746 :
23747 : settings_store& enable_all_control_structures()
23748 : {
23749 : disabled_ctrl_set_.clear();
23750 : return (*this);
23751 : }
23752 :
23753 : settings_store& enable_all_logic_ops()
23754 : {
23755 : disabled_logic_set_.clear();
23756 : return (*this);
23757 : }
23758 :
23759 : settings_store& enable_all_arithmetic_ops()
23760 : {
23761 : disabled_arithmetic_set_.clear();
23762 : return (*this);
23763 : }
23764 :
23765 : settings_store& enable_all_assignment_ops()
23766 : {
23767 : disabled_assignment_set_.clear();
23768 : return (*this);
23769 : }
23770 :
23771 : settings_store& enable_all_inequality_ops()
23772 : {
23773 : disabled_inequality_set_.clear();
23774 : return (*this);
23775 : }
23776 :
23777 : settings_store& enable_local_vardef()
23778 : {
23779 : disable_vardef_ = false;
23780 : return (*this);
23781 : }
23782 :
23783 : settings_store& enable_commutative_check()
23784 : {
23785 : enable_commutative_check_ = true;
23786 : return (*this);
23787 : }
23788 :
23789 : settings_store& enable_strength_reduction()
23790 : {
23791 : enable_strength_reduction_ = true;
23792 : return (*this);
23793 : }
23794 :
23795 : settings_store& disable_all_base_functions()
23796 : {
23797 : std::copy(details::base_function_list,
23798 : details::base_function_list + details::base_function_list_size,
23799 : std::insert_iterator<disabled_entity_set_t>
23800 : (disabled_func_set_, disabled_func_set_.begin()));
23801 : return (*this);
23802 : }
23803 :
23804 : settings_store& disable_all_control_structures()
23805 : {
23806 : std::copy(details::cntrl_struct_list,
23807 : details::cntrl_struct_list + details::cntrl_struct_list_size,
23808 : std::insert_iterator<disabled_entity_set_t>
23809 : (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
23810 : return (*this);
23811 : }
23812 :
23813 : settings_store& disable_all_logic_ops()
23814 : {
23815 : std::copy(details::logic_ops_list,
23816 : details::logic_ops_list + details::logic_ops_list_size,
23817 : std::insert_iterator<disabled_entity_set_t>
23818 : (disabled_logic_set_, disabled_logic_set_.begin()));
23819 : return (*this);
23820 : }
23821 :
23822 : settings_store& disable_all_arithmetic_ops()
23823 : {
23824 : std::copy(details::arithmetic_ops_list,
23825 : details::arithmetic_ops_list + details::arithmetic_ops_list_size,
23826 : std::insert_iterator<disabled_entity_set_t>
23827 : (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
23828 : return (*this);
23829 : }
23830 :
23831 : settings_store& disable_all_assignment_ops()
23832 : {
23833 : std::copy(details::assignment_ops_list,
23834 : details::assignment_ops_list + details::assignment_ops_list_size,
23835 : std::insert_iterator<disabled_entity_set_t>
23836 : (disabled_assignment_set_, disabled_assignment_set_.begin()));
23837 : return (*this);
23838 : }
23839 :
23840 : settings_store& disable_all_inequality_ops()
23841 : {
23842 : std::copy(details::inequality_ops_list,
23843 : details::inequality_ops_list + details::inequality_ops_list_size,
23844 : std::insert_iterator<disabled_entity_set_t>
23845 : (disabled_inequality_set_, disabled_inequality_set_.begin()));
23846 : return (*this);
23847 : }
23848 :
23849 : settings_store& disable_local_vardef()
23850 : {
23851 : disable_vardef_ = true;
23852 : return (*this);
23853 : }
23854 :
23855 : settings_store& disable_commutative_check()
23856 : {
23857 : enable_commutative_check_ = false;
23858 : return (*this);
23859 : }
23860 :
23861 : settings_store& disable_strength_reduction()
23862 : {
23863 : enable_strength_reduction_ = false;
23864 : return (*this);
23865 : }
23866 :
23867 491757 : bool replacer_enabled () const { return enable_replacer_; }
23868 502098 : bool commutative_check_enabled () const { return enable_commutative_check_; }
23869 488557 : bool joiner_enabled () const { return enable_joiner_; }
23870 597217 : bool numeric_check_enabled () const { return enable_numeric_check_; }
23871 108660 : bool bracket_check_enabled () const { return enable_bracket_check_; }
23872 108660 : bool sequence_check_enabled () const { return enable_sequence_check_; }
23873 604013 : bool strength_reduction_enabled () const { return enable_strength_reduction_; }
23874 108660 : bool collect_variables_enabled () const { return enable_collect_vars_; }
23875 108660 : bool collect_functions_enabled () const { return enable_collect_funcs_; }
23876 108660 : bool collect_assignments_enabled() const { return enable_collect_assings_; }
23877 82250 : bool vardef_disabled () const { return disable_vardef_; }
23878 5208 : bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
23879 1 : bool zero_return_disabled () const { return disable_zero_return_; }
23880 :
23881 570903 : bool function_enabled(const std::string& function_name) const
23882 : {
23883 570903 : if (disabled_func_set_.empty())
23884 564903 : return true;
23885 : else
23886 6000 : return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
23887 : }
23888 :
23889 9387 : bool control_struct_enabled(const std::string& control_struct) const
23890 : {
23891 9387 : if (disabled_ctrl_set_.empty())
23892 9387 : return true;
23893 : else
23894 0 : return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
23895 : }
23896 :
23897 : bool logic_enabled(const std::string& logic_operation) const
23898 : {
23899 : if (disabled_logic_set_.empty())
23900 : return true;
23901 : else
23902 : return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
23903 : }
23904 :
23905 : bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
23906 : {
23907 : if (disabled_logic_set_.empty())
23908 : return true;
23909 : else
23910 : return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
23911 : .find(arith_opr_to_string(arithmetic_operation));
23912 : }
23913 :
23914 23715 : bool assignment_enabled(const details::operator_type& assignment) const
23915 : {
23916 23715 : if (disabled_assignment_set_.empty())
23917 23715 : return true;
23918 : else
23919 0 : return disabled_assignment_set_.end() == disabled_assignment_set_
23920 0 : .find(assign_opr_to_string(assignment));
23921 : }
23922 :
23923 : bool inequality_enabled(const details::operator_type& inequality) const
23924 : {
23925 : if (disabled_inequality_set_.empty())
23926 : return true;
23927 : else
23928 : return disabled_inequality_set_.end() == disabled_inequality_set_
23929 : .find(inequality_opr_to_string(inequality));
23930 : }
23931 :
23932 : bool function_disabled(const std::string& function_name) const
23933 : {
23934 : if (disabled_func_set_.empty())
23935 : return false;
23936 : else
23937 : return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
23938 : }
23939 :
23940 : bool control_struct_disabled(const std::string& control_struct) const
23941 : {
23942 : if (disabled_ctrl_set_.empty())
23943 : return false;
23944 : else
23945 : return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
23946 : }
23947 :
23948 728 : bool logic_disabled(const std::string& logic_operation) const
23949 : {
23950 728 : if (disabled_logic_set_.empty())
23951 728 : return false;
23952 : else
23953 0 : return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
23954 : }
23955 :
23956 2796166 : bool assignment_disabled(const details::operator_type assignment_operation) const
23957 : {
23958 2796166 : if (disabled_assignment_set_.empty())
23959 2796166 : return false;
23960 : else
23961 0 : return disabled_assignment_set_.end() != disabled_assignment_set_
23962 0 : .find(assign_opr_to_string(assignment_operation));
23963 : }
23964 :
23965 2796166 : bool logic_disabled(const details::operator_type logic_operation) const
23966 : {
23967 2796166 : if (disabled_logic_set_.empty())
23968 2796166 : return false;
23969 : else
23970 0 : return disabled_logic_set_.end() != disabled_logic_set_
23971 0 : .find(logic_opr_to_string(logic_operation));
23972 : }
23973 :
23974 2796166 : bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
23975 : {
23976 2796166 : if (disabled_arithmetic_set_.empty())
23977 2796166 : return false;
23978 : else
23979 0 : return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
23980 0 : .find(arith_opr_to_string(arithmetic_operation));
23981 : }
23982 :
23983 2796166 : bool inequality_disabled(const details::operator_type& inequality) const
23984 : {
23985 2796166 : if (disabled_inequality_set_.empty())
23986 2796166 : return false;
23987 : else
23988 0 : return disabled_inequality_set_.end() != disabled_inequality_set_
23989 0 : .find(inequality_opr_to_string(inequality));
23990 : }
23991 :
23992 3200 : settings_store& disable_base_function(const settings_base_funcs bf)
23993 : {
23994 3200 : if (
23995 3200 : (e_bf_unknown != bf) &&
23996 : (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
23997 : )
23998 : {
23999 3200 : disabled_func_set_.insert(details::base_function_list[bf - 1]);
24000 : }
24001 :
24002 3200 : return (*this);
24003 : }
24004 :
24005 : settings_store& disable_control_structure(const settings_control_structs ctrl_struct)
24006 : {
24007 : if (
24008 : (e_ctrl_unknown != ctrl_struct) &&
24009 : (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
24010 : )
24011 : {
24012 : disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
24013 : }
24014 :
24015 : return (*this);
24016 : }
24017 :
24018 : settings_store& disable_logic_operation(const settings_logic_opr logic)
24019 : {
24020 : if (
24021 : (e_logic_unknown != logic) &&
24022 : (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
24023 : )
24024 : {
24025 : disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
24026 : }
24027 :
24028 : return (*this);
24029 : }
24030 :
24031 : settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
24032 : {
24033 : if (
24034 : (e_arith_unknown != arithmetic) &&
24035 : (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
24036 : )
24037 : {
24038 : disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
24039 : }
24040 :
24041 : return (*this);
24042 : }
24043 :
24044 : settings_store& disable_assignment_operation(const settings_assignment_opr assignment)
24045 : {
24046 : if (
24047 : (e_assign_unknown != assignment) &&
24048 : (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
24049 : )
24050 : {
24051 : disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
24052 : }
24053 :
24054 : return (*this);
24055 : }
24056 :
24057 : settings_store& disable_inequality_operation(const settings_inequality_opr inequality)
24058 : {
24059 : if (
24060 : (e_ineq_unknown != inequality) &&
24061 : (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
24062 : )
24063 : {
24064 : disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
24065 : }
24066 :
24067 : return (*this);
24068 : }
24069 :
24070 : settings_store& enable_base_function(const settings_base_funcs bf)
24071 : {
24072 : if (
24073 : (e_bf_unknown != bf) &&
24074 : (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
24075 : )
24076 : {
24077 : const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
24078 :
24079 : if (disabled_func_set_.end() != itr)
24080 : {
24081 : disabled_func_set_.erase(itr);
24082 : }
24083 : }
24084 :
24085 : return (*this);
24086 : }
24087 :
24088 : settings_store& enable_control_structure(const settings_control_structs ctrl_struct)
24089 : {
24090 : if (
24091 : (e_ctrl_unknown != ctrl_struct) &&
24092 : (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
24093 : )
24094 : {
24095 : const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
24096 :
24097 : if (disabled_ctrl_set_.end() != itr)
24098 : {
24099 : disabled_ctrl_set_.erase(itr);
24100 : }
24101 : }
24102 :
24103 : return (*this);
24104 : }
24105 :
24106 : settings_store& enable_logic_operation(const settings_logic_opr logic)
24107 : {
24108 : if (
24109 : (e_logic_unknown != logic) &&
24110 : (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
24111 : )
24112 : {
24113 : const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
24114 :
24115 : if (disabled_logic_set_.end() != itr)
24116 : {
24117 : disabled_logic_set_.erase(itr);
24118 : }
24119 : }
24120 :
24121 : return (*this);
24122 : }
24123 :
24124 : settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic)
24125 : {
24126 : if (
24127 : (e_arith_unknown != arithmetic) &&
24128 : (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
24129 : )
24130 : {
24131 : const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
24132 :
24133 : if (disabled_arithmetic_set_.end() != itr)
24134 : {
24135 : disabled_arithmetic_set_.erase(itr);
24136 : }
24137 : }
24138 :
24139 : return (*this);
24140 : }
24141 :
24142 : settings_store& enable_assignment_operation(const settings_assignment_opr assignment)
24143 : {
24144 : if (
24145 : (e_assign_unknown != assignment) &&
24146 : (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
24147 : )
24148 : {
24149 : const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
24150 :
24151 : if (disabled_assignment_set_.end() != itr)
24152 : {
24153 : disabled_assignment_set_.erase(itr);
24154 : }
24155 : }
24156 :
24157 : return (*this);
24158 : }
24159 :
24160 : settings_store& enable_inequality_operation(const settings_inequality_opr inequality)
24161 : {
24162 : if (
24163 : (e_ineq_unknown != inequality) &&
24164 : (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
24165 : )
24166 : {
24167 : const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
24168 :
24169 : if (disabled_inequality_set_.end() != itr)
24170 : {
24171 : disabled_inequality_set_.erase(itr);
24172 : }
24173 : }
24174 :
24175 : return (*this);
24176 : }
24177 :
24178 : void set_max_stack_depth(const std::size_t max_stack_depth)
24179 : {
24180 : max_stack_depth_ = max_stack_depth;
24181 : }
24182 :
24183 : void set_max_node_depth(const std::size_t max_node_depth)
24184 : {
24185 : max_node_depth_ = max_node_depth;
24186 : }
24187 :
24188 : void set_max_local_vector_size(const std::size_t max_local_vector_size)
24189 : {
24190 : max_local_vector_size_ = max_local_vector_size;
24191 : }
24192 :
24193 : std::size_t max_stack_depth() const
24194 : {
24195 : return max_stack_depth_;
24196 : }
24197 :
24198 : std::size_t max_node_depth() const
24199 : {
24200 : return max_node_depth_;
24201 : }
24202 :
24203 24277 : std::size_t max_local_vector_size() const
24204 : {
24205 24277 : return max_local_vector_size_;
24206 : }
24207 :
24208 : private:
24209 :
24210 108660 : void load_compile_options(const std::size_t compile_options)
24211 : {
24212 108660 : enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
24213 108660 : enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
24214 108660 : enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
24215 108660 : enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
24216 108660 : enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
24217 108660 : enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
24218 108660 : enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
24219 108660 : enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
24220 108660 : enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
24221 108660 : enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
24222 108660 : disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
24223 108660 : disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
24224 108660 : disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
24225 108660 : }
24226 :
24227 0 : std::string assign_opr_to_string(details::operator_type opr) const
24228 : {
24229 0 : switch (opr)
24230 : {
24231 0 : case details::e_assign : return ":=";
24232 0 : case details::e_addass : return "+=";
24233 0 : case details::e_subass : return "-=";
24234 0 : case details::e_mulass : return "*=";
24235 0 : case details::e_divass : return "/=";
24236 0 : case details::e_modass : return "%=";
24237 0 : default : return "" ;
24238 : }
24239 : }
24240 :
24241 0 : std::string arith_opr_to_string(details::operator_type opr) const
24242 : {
24243 0 : switch (opr)
24244 : {
24245 0 : case details::e_add : return "+";
24246 0 : case details::e_sub : return "-";
24247 0 : case details::e_mul : return "*";
24248 0 : case details::e_div : return "/";
24249 0 : case details::e_mod : return "%";
24250 0 : case details::e_pow : return "^";
24251 0 : default : return "" ;
24252 : }
24253 : }
24254 :
24255 0 : std::string inequality_opr_to_string(details::operator_type opr) const
24256 : {
24257 0 : switch (opr)
24258 : {
24259 0 : case details::e_lt : return "<" ;
24260 0 : case details::e_lte : return "<=";
24261 0 : case details::e_eq : return "==";
24262 0 : case details::e_equal : return "=" ;
24263 0 : case details::e_ne : return "!=";
24264 0 : case details::e_nequal: return "<>";
24265 0 : case details::e_gte : return ">=";
24266 0 : case details::e_gt : return ">" ;
24267 0 : default : return "" ;
24268 : }
24269 : }
24270 :
24271 0 : std::string logic_opr_to_string(details::operator_type opr) const
24272 : {
24273 0 : switch (opr)
24274 : {
24275 0 : case details::e_and : return "and" ;
24276 0 : case details::e_or : return "or" ;
24277 0 : case details::e_xor : return "xor" ;
24278 0 : case details::e_nand : return "nand";
24279 0 : case details::e_nor : return "nor" ;
24280 0 : case details::e_xnor : return "xnor";
24281 0 : case details::e_notl : return "not" ;
24282 0 : default : return "" ;
24283 : }
24284 : }
24285 :
24286 : bool enable_replacer_;
24287 : bool enable_joiner_;
24288 : bool enable_numeric_check_;
24289 : bool enable_bracket_check_;
24290 : bool enable_sequence_check_;
24291 : bool enable_commutative_check_;
24292 : bool enable_strength_reduction_;
24293 : bool enable_collect_vars_;
24294 : bool enable_collect_funcs_;
24295 : bool enable_collect_assings_;
24296 : bool disable_vardef_;
24297 : bool disable_rsrvd_sym_usr_;
24298 : bool disable_zero_return_;
24299 :
24300 : disabled_entity_set_t disabled_func_set_ ;
24301 : disabled_entity_set_t disabled_ctrl_set_ ;
24302 : disabled_entity_set_t disabled_logic_set_;
24303 : disabled_entity_set_t disabled_arithmetic_set_;
24304 : disabled_entity_set_t disabled_assignment_set_;
24305 : disabled_entity_set_t disabled_inequality_set_;
24306 :
24307 : std::size_t max_stack_depth_;
24308 : std::size_t max_node_depth_;
24309 : std::size_t max_local_vector_size_;
24310 :
24311 : friend class parser<T>;
24312 : };
24313 :
24314 : typedef settings_store settings_t;
24315 :
24316 108660 : explicit parser(const settings_t& settings = settings_t())
24317 108660 : : settings_(settings)
24318 108660 : , resolve_unknown_symbol_(false)
24319 108660 : , results_context_(0)
24320 108660 : , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0))
24321 : #ifdef _MSC_VER
24322 : #pragma warning(push)
24323 : #pragma warning (disable:4355)
24324 : #endif
24325 108660 : , sem_(*this)
24326 : #ifdef _MSC_VER
24327 : #pragma warning(pop)
24328 : #endif
24329 108660 : , operator_joiner_2_(2)
24330 108660 : , operator_joiner_3_(3)
24331 108660 : , loop_runtime_check_(0)
24332 108660 : , vector_access_runtime_check_(0)
24333 108660 : , compilation_check_ptr_(0)
24334 434640 : , assert_check_(0)
24335 : {
24336 108660 : init_precompilation();
24337 :
24338 108660 : load_operations_map (base_ops_map_ );
24339 108660 : load_unary_operations_map (unary_op_map_ );
24340 108660 : load_binary_operations_map (binary_op_map_ );
24341 108660 : load_inv_binary_operations_map(inv_binary_op_map_);
24342 108660 : load_sf3_map (sf3_map_ );
24343 108660 : load_sf4_map (sf4_map_ );
24344 :
24345 108660 : expression_generator_.init_synthesize_map();
24346 108660 : expression_generator_.set_parser(*this);
24347 108660 : expression_generator_.set_uom (unary_op_map_ );
24348 108660 : expression_generator_.set_bom (binary_op_map_ );
24349 108660 : expression_generator_.set_ibom(inv_binary_op_map_);
24350 108660 : expression_generator_.set_sf3m(sf3_map_ );
24351 108660 : expression_generator_.set_sf4m(sf4_map_ );
24352 108660 : expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
24353 108660 : }
24354 :
24355 108660 : ~parser()
24356 108660 : {}
24357 :
24358 108660 : inline void init_precompilation()
24359 : {
24360 108660 : dec_.collect_variables() =
24361 108660 : settings_.collect_variables_enabled();
24362 :
24363 108660 : dec_.collect_functions() =
24364 108660 : settings_.collect_functions_enabled();
24365 :
24366 108660 : dec_.collect_assignments() =
24367 108660 : settings_.collect_assignments_enabled();
24368 :
24369 108660 : if (settings_.replacer_enabled())
24370 : {
24371 108660 : symbol_replacer_.clear();
24372 434640 : symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
24373 434640 : symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
24374 108660 : helper_assembly_.token_modifier_list.clear();
24375 108660 : helper_assembly_.register_modifier(&symbol_replacer_);
24376 : }
24377 :
24378 108660 : if (settings_.commutative_check_enabled())
24379 : {
24380 3694406 : for (std::size_t i = 0; i < details::reserved_words_size; ++i)
24381 : {
24382 3585747 : commutative_inserter_.ignore_symbol(details::reserved_words[i]);
24383 : }
24384 :
24385 108659 : helper_assembly_.token_inserter_list.clear();
24386 108659 : helper_assembly_.register_inserter(&commutative_inserter_);
24387 : }
24388 :
24389 108660 : if (settings_.joiner_enabled())
24390 : {
24391 108660 : helper_assembly_.token_joiner_list.clear();
24392 108660 : helper_assembly_.register_joiner(&operator_joiner_2_);
24393 108660 : helper_assembly_.register_joiner(&operator_joiner_3_);
24394 : }
24395 :
24396 108660 : if (
24397 108660 : settings_.numeric_check_enabled () ||
24398 108660 : settings_.bracket_check_enabled () ||
24399 0 : settings_.sequence_check_enabled()
24400 : )
24401 : {
24402 108660 : helper_assembly_.token_scanner_list.clear();
24403 :
24404 108660 : if (settings_.numeric_check_enabled())
24405 : {
24406 108660 : helper_assembly_.register_scanner(&numeric_checker_);
24407 : }
24408 :
24409 108660 : if (settings_.bracket_check_enabled())
24410 : {
24411 108660 : helper_assembly_.register_scanner(&bracket_checker_);
24412 : }
24413 :
24414 108660 : if (settings_.sequence_check_enabled())
24415 : {
24416 108660 : helper_assembly_.register_scanner(&sequence_validator_ );
24417 108660 : helper_assembly_.register_scanner(&sequence_validator_3tkns_);
24418 : }
24419 : }
24420 108660 : }
24421 :
24422 380686 : inline bool compile(const std::string& expression_string, expression<T>& expr)
24423 : {
24424 380686 : state_ .reset();
24425 380686 : error_list_ .clear();
24426 380686 : brkcnt_list_ .clear();
24427 380686 : synthesis_error_ .clear();
24428 380686 : immutable_memory_map_.reset();
24429 380686 : immutable_symtok_map_.clear();
24430 380686 : current_state_stack_ .clear();
24431 380686 : assert_ids_ .clear();
24432 380686 : sem_ .cleanup();
24433 :
24434 380686 : return_cleanup();
24435 :
24436 380686 : expression_generator_.set_allocator(node_allocator_);
24437 :
24438 380686 : if (expression_string.empty())
24439 : {
24440 0 : set_error(make_error(
24441 : parser_error::e_syntax,
24442 : "ERR001 - Empty expression!",
24443 : exprtk_error_location));
24444 :
24445 0 : return false;
24446 : }
24447 :
24448 380686 : if (!init(expression_string))
24449 : {
24450 788 : process_lexer_errors();
24451 788 : return false;
24452 : }
24453 :
24454 379898 : if (lexer().empty())
24455 : {
24456 3 : set_error(make_error(
24457 : parser_error::e_syntax,
24458 : "ERR002 - Empty expression!",
24459 : exprtk_error_location));
24460 :
24461 1 : return false;
24462 : }
24463 :
24464 379897 : if (halt_compilation_check())
24465 : {
24466 : exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n"));
24467 0 : return false;
24468 : }
24469 :
24470 379897 : if (!run_assemblies())
24471 : {
24472 9739 : return false;
24473 : }
24474 :
24475 370158 : if (halt_compilation_check())
24476 : {
24477 : exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n"));
24478 0 : return false;
24479 : }
24480 :
24481 370158 : symtab_store_.symtab_list_ = expr.get_symbol_table_list();
24482 370158 : dec_.clear();
24483 :
24484 370158 : lexer().begin();
24485 :
24486 370158 : next_token();
24487 :
24488 370158 : expression_node_ptr e = parse_corpus();
24489 :
24490 370158 : if ((0 != e) && (token_t::e_eof == current_token().type))
24491 : {
24492 359159 : bool* retinvk_ptr = 0;
24493 :
24494 359159 : if (state_.return_stmt_present)
24495 : {
24496 111 : dec_.return_present_ = true;
24497 :
24498 111 : e = expression_generator_
24499 111 : .return_envelope(e, results_context_, retinvk_ptr);
24500 : }
24501 :
24502 359159 : expr.set_expression(e);
24503 359159 : expr.set_retinvk(retinvk_ptr);
24504 :
24505 359159 : register_local_vars(expr);
24506 359159 : register_return_results(expr);
24507 :
24508 359159 : return !(!expr);
24509 : }
24510 : else
24511 : {
24512 10999 : if (error_list_.empty())
24513 : {
24514 0 : set_error(make_error(
24515 : parser_error::e_syntax,
24516 0 : current_token(),
24517 : "ERR003 - Invalid expression encountered",
24518 : exprtk_error_location));
24519 : }
24520 :
24521 10999 : if ((0 != e) && branch_deletable(e))
24522 : {
24523 0 : destroy_node(e);
24524 : }
24525 :
24526 10999 : dec_.clear ();
24527 10999 : sem_.cleanup ();
24528 10999 : return_cleanup();
24529 :
24530 10999 : return false;
24531 : }
24532 : }
24533 :
24534 : inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
24535 : {
24536 : expression_t expression;
24537 : expression.register_symbol_table(symtab);
24538 : compile(expression_string,expression);
24539 : return expression;
24540 : }
24541 :
24542 788 : void process_lexer_errors()
24543 : {
24544 78215 : for (std::size_t i = 0; i < lexer().size(); ++i)
24545 : {
24546 77427 : if (lexer()[i].is_error())
24547 : {
24548 788 : std::string diagnostic = "ERR004 - ";
24549 :
24550 788 : switch (lexer()[i].type)
24551 : {
24552 491 : case lexer::token::e_error : diagnostic += "General token error";
24553 491 : break;
24554 :
24555 0 : case lexer::token::e_err_symbol : diagnostic += "Symbol error";
24556 0 : break;
24557 :
24558 60 : case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
24559 60 : break;
24560 :
24561 237 : case lexer::token::e_err_string : diagnostic += "Invalid string token";
24562 237 : break;
24563 :
24564 0 : case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
24565 0 : break;
24566 :
24567 0 : default : diagnostic += "Unknown compiler error";
24568 : }
24569 :
24570 2364 : set_error(make_error(
24571 : parser_error::e_lexer,
24572 788 : lexer()[i],
24573 788 : diagnostic + ": " + lexer()[i].value,
24574 : exprtk_error_location));
24575 788 : }
24576 : }
24577 788 : }
24578 :
24579 379897 : inline bool run_assemblies()
24580 : {
24581 379897 : if (settings_.commutative_check_enabled())
24582 : {
24583 379887 : helper_assembly_.run_inserters(lexer());
24584 : }
24585 :
24586 379897 : if (settings_.joiner_enabled())
24587 : {
24588 379897 : helper_assembly_.run_joiners(lexer());
24589 : }
24590 :
24591 379897 : if (settings_.replacer_enabled())
24592 : {
24593 379897 : helper_assembly_.run_modifiers(lexer());
24594 : }
24595 :
24596 379897 : if (
24597 379897 : settings_.numeric_check_enabled () ||
24598 379897 : settings_.bracket_check_enabled () ||
24599 0 : settings_.sequence_check_enabled()
24600 : )
24601 : {
24602 379897 : if (!helper_assembly_.run_scanners(lexer()))
24603 : {
24604 9739 : if (helper_assembly_.error_token_scanner)
24605 : {
24606 9739 : lexer::helper::bracket_checker* bracket_checker_ptr = 0;
24607 9739 : lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0;
24608 9739 : lexer::helper::sequence_validator* sequence_validator_ptr = 0;
24609 9739 : lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
24610 :
24611 9739 : if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
24612 : {
24613 26682 : set_error(make_error(
24614 : parser_error::e_token,
24615 : bracket_checker_ptr->error_token(),
24616 17788 : "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
24617 : exprtk_error_location));
24618 : }
24619 845 : else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner)))
24620 : {
24621 28 : for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
24622 : {
24623 14 : lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
24624 :
24625 14 : set_error(make_error(
24626 : parser_error::e_token,
24627 : error_token,
24628 : "ERR006 - Invalid numeric token: '" + error_token.value + "'",
24629 : exprtk_error_location));
24630 : }
24631 :
24632 14 : if (numeric_checker_ptr->error_count())
24633 : {
24634 14 : numeric_checker_ptr->clear_errors();
24635 : }
24636 : }
24637 831 : else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
24638 : {
24639 1831 : for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
24640 : {
24641 1002 : std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
24642 :
24643 1002 : set_error(make_error(
24644 : parser_error::e_token,
24645 : error_token.first,
24646 : "ERR007 - Invalid token sequence: '" +
24647 : error_token.first.value + "' and '" +
24648 : error_token.second.value + "'",
24649 : exprtk_error_location));
24650 : }
24651 :
24652 829 : if (sequence_validator_ptr->error_count())
24653 : {
24654 829 : sequence_validator_ptr->clear_errors();
24655 : }
24656 : }
24657 2 : else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
24658 : {
24659 6 : for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
24660 : {
24661 4 : std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
24662 :
24663 4 : set_error(make_error(
24664 : parser_error::e_token,
24665 : error_token.first,
24666 : "ERR008 - Invalid token sequence: '" +
24667 : error_token.first.value + "' and '" +
24668 : error_token.second.value + "'",
24669 : exprtk_error_location));
24670 : }
24671 :
24672 2 : if (sequence_validator3_ptr->error_count())
24673 : {
24674 2 : sequence_validator3_ptr->clear_errors();
24675 : }
24676 : }
24677 : }
24678 :
24679 9739 : return false;
24680 : }
24681 : }
24682 :
24683 370158 : return true;
24684 : }
24685 :
24686 1600 : inline settings_store& settings()
24687 : {
24688 1600 : return settings_;
24689 : }
24690 :
24691 0 : inline parser_error::type get_error(const std::size_t& index) const
24692 : {
24693 0 : if (index < error_list_.size())
24694 : {
24695 0 : return error_list_[index];
24696 : }
24697 :
24698 0 : throw std::invalid_argument("parser::get_error() - Invalid error index specified");
24699 : }
24700 :
24701 0 : inline std::string error() const
24702 : {
24703 0 : if (!error_list_.empty())
24704 : {
24705 0 : return error_list_[0].diagnostic;
24706 : }
24707 : else
24708 0 : return std::string("No Error");
24709 : }
24710 :
24711 0 : inline std::size_t error_count() const
24712 : {
24713 0 : return error_list_.size();
24714 : }
24715 :
24716 1495 : inline dependent_entity_collector& dec()
24717 : {
24718 1495 : return dec_;
24719 : }
24720 :
24721 3200 : inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
24722 : {
24723 3200 : if (!settings_.replacer_enabled())
24724 0 : return false;
24725 3200 : else if (details::is_reserved_word(old_symbol))
24726 0 : return false;
24727 : else
24728 3200 : return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
24729 : }
24730 :
24731 : inline bool remove_replace_symbol(const std::string& symbol)
24732 : {
24733 : if (!settings_.replacer_enabled())
24734 : return false;
24735 : else if (details::is_reserved_word(symbol))
24736 : return false;
24737 : else
24738 : return symbol_replacer_.remove(symbol);
24739 : }
24740 :
24741 204 : inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
24742 : {
24743 204 : resolve_unknown_symbol_ = true;
24744 :
24745 204 : if (usr)
24746 202 : unknown_symbol_resolver_ = usr;
24747 : else
24748 2 : unknown_symbol_resolver_ = &default_usr_;
24749 204 : }
24750 :
24751 : inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
24752 : {
24753 : enable_unknown_symbol_resolver(&usr);
24754 : }
24755 :
24756 : inline void disable_unknown_symbol_resolver()
24757 : {
24758 : resolve_unknown_symbol_ = false;
24759 : unknown_symbol_resolver_ = &default_usr_;
24760 : }
24761 :
24762 : inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
24763 : {
24764 : loop_runtime_check_ = &lrtchk;
24765 : }
24766 :
24767 70 : inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk)
24768 : {
24769 70 : vector_access_runtime_check_ = &vartchk;
24770 70 : }
24771 :
24772 : inline void register_compilation_timeout_check(compilation_check& compchk)
24773 : {
24774 : compilation_check_ptr_ = &compchk;
24775 : }
24776 :
24777 54 : inline void register_assert_check(assert_check& assrt_chck)
24778 : {
24779 54 : assert_check_ = &assrt_chck;
24780 54 : }
24781 :
24782 : inline void clear_loop_runtime_check()
24783 : {
24784 : loop_runtime_check_ = loop_runtime_check_ptr(0);
24785 : }
24786 :
24787 : inline void clear_vector_access_runtime_check()
24788 : {
24789 : vector_access_runtime_check_ = vector_access_runtime_check_ptr(0);
24790 : }
24791 :
24792 : inline void clear_compilation_timeout_check()
24793 : {
24794 : compilation_check_ptr_ = compilation_check_ptr(0);
24795 : }
24796 :
24797 : inline void clear_assert_check()
24798 : {
24799 : assert_check_ = assert_check_ptr(0);
24800 : }
24801 :
24802 : private:
24803 :
24804 2511953 : inline bool valid_base_operation(const std::string& symbol) const
24805 : {
24806 2511953 : const std::size_t length = symbol.size();
24807 :
24808 2511953 : if (
24809 549903 : (length < 3) || // Shortest base op symbol length
24810 : (length > 9) // Longest base op symbol length
24811 : )
24812 1963400 : return false;
24813 : else
24814 1094706 : return settings_.function_enabled(symbol) &&
24815 1094706 : (base_ops_map_.end() != base_ops_map_.find(symbol));
24816 : }
24817 :
24818 2535008 : inline bool valid_vararg_operation(const std::string& symbol) const
24819 : {
24820 2535010 : static const std::string s_sum = "sum" ;
24821 2535010 : static const std::string s_mul = "mul" ;
24822 2535010 : static const std::string s_avg = "avg" ;
24823 2535010 : static const std::string s_min = "min" ;
24824 2535010 : static const std::string s_max = "max" ;
24825 2535010 : static const std::string s_mand = "mand";
24826 2535010 : static const std::string s_mor = "mor" ;
24827 2535010 : static const std::string s_multi = "~" ;
24828 2535010 : static const std::string s_mswitch = "[*]" ;
24829 :
24830 : return
24831 : (
24832 5067812 : details::imatch(symbol,s_sum ) ||
24833 5065384 : details::imatch(symbol,s_mul ) ||
24834 5064822 : details::imatch(symbol,s_avg ) ||
24835 5060072 : details::imatch(symbol,s_min ) ||
24836 5055281 : details::imatch(symbol,s_max ) ||
24837 5054646 : details::imatch(symbol,s_mand ) ||
24838 5054133 : details::imatch(symbol,s_mor ) ||
24839 5039809 : details::imatch(symbol,s_multi ) ||
24840 2512871 : details::imatch(symbol,s_mswitch)
24841 5070016 : ) &&
24842 2557335 : settings_.function_enabled(symbol);
24843 : }
24844 :
24845 2796166 : bool is_invalid_logic_operation(const details::operator_type operation) const
24846 : {
24847 2796166 : return settings_.logic_disabled(operation);
24848 : }
24849 :
24850 2796166 : bool is_invalid_arithmetic_operation(const details::operator_type operation) const
24851 : {
24852 2796166 : return settings_.arithmetic_disabled(operation);
24853 : }
24854 :
24855 2796166 : bool is_invalid_assignment_operation(const details::operator_type operation) const
24856 : {
24857 2796166 : return settings_.assignment_disabled(operation);
24858 : }
24859 :
24860 2796166 : bool is_invalid_inequality_operation(const details::operator_type operation) const
24861 : {
24862 2796166 : return settings_.inequality_disabled(operation);
24863 : }
24864 :
24865 : #ifdef exprtk_enable_debugging
24866 : inline void next_token()
24867 : {
24868 : const std::string ct_str = current_token().value;
24869 : const std::size_t ct_pos = current_token().position;
24870 : parser_helper::next_token();
24871 : const std::string depth(2 * state_.scope_depth,' ');
24872 : exprtk_debug(("%s"
24873 : "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n",
24874 : depth.c_str(),
24875 : ct_str.c_str(),
24876 : static_cast<unsigned int>(ct_pos),
24877 : current_token().value.c_str(),
24878 : static_cast<unsigned int>(current_token().position),
24879 : static_cast<unsigned int>(state_.stack_depth)));
24880 : }
24881 : #endif
24882 :
24883 370158 : inline expression_node_ptr parse_corpus()
24884 : {
24885 370158 : std::vector<expression_node_ptr> arg_list;
24886 370158 : std::vector<bool> side_effect_list;
24887 :
24888 370158 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24889 :
24890 370158 : lexer::token begin_token;
24891 370158 : lexer::token end_token;
24892 :
24893 75652 : for ( ; ; )
24894 : {
24895 445810 : state_.side_effect_present = false;
24896 :
24897 445810 : begin_token = current_token();
24898 :
24899 445810 : expression_node_ptr arg = parse_expression();
24900 :
24901 445810 : if (0 == arg)
24902 : {
24903 10999 : if (error_list_.empty())
24904 : {
24905 0 : set_error(make_error(
24906 : parser_error::e_syntax,
24907 0 : current_token(),
24908 : "ERR009 - Invalid expression encountered",
24909 : exprtk_error_location));
24910 : }
24911 :
24912 10999 : return error_node();
24913 : }
24914 : else
24915 : {
24916 434811 : arg_list.push_back(arg);
24917 :
24918 434811 : side_effect_list.push_back(state_.side_effect_present);
24919 :
24920 434811 : end_token = current_token();
24921 :
24922 434811 : const std::string sub_expr = construct_subexpr(begin_token, end_token);
24923 :
24924 : exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
24925 : static_cast<int>(arg_list.size() - 1),
24926 : sub_expr.c_str()));
24927 :
24928 : exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
24929 : static_cast<int>(arg_list.size() - 1),
24930 : state_.side_effect_present ? "true" : "false"));
24931 :
24932 : exprtk_debug(("-------------------------------------------------\n"));
24933 434811 : }
24934 :
24935 434811 : if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24936 : {
24937 421620 : if (lexer().finished())
24938 359159 : break;
24939 : else
24940 62461 : next_token();
24941 : }
24942 : }
24943 :
24944 359159 : if (
24945 718318 : !arg_list.empty() &&
24946 359159 : is_return_node(arg_list.back())
24947 : )
24948 : {
24949 2 : dec_.final_stmt_return_ = true;
24950 : }
24951 :
24952 359159 : const expression_node_ptr result = simplify(arg_list,side_effect_list);
24953 :
24954 359159 : sdd.delete_ptr = (0 == result);
24955 :
24956 359159 : return result;
24957 370158 : }
24958 :
24959 434811 : std::string construct_subexpr(lexer::token& begin_token,
24960 : lexer::token& end_token,
24961 : const bool cleanup_whitespace = true)
24962 : {
24963 434811 : std::string result = lexer().substr(begin_token.position,end_token.position);
24964 434811 : if (cleanup_whitespace)
24965 : {
24966 30648260 : for (std::size_t i = 0; i < result.size(); ++i)
24967 : {
24968 30213449 : if (details::is_whitespace(result[i])) result[i] = ' ';
24969 : }
24970 : }
24971 :
24972 434811 : return result;
24973 0 : }
24974 :
24975 : static const precedence_level default_precedence = e_level00;
24976 :
24977 : struct state_t
24978 : {
24979 3998707 : inline void set(const precedence_level& l,
24980 : const precedence_level& r,
24981 : const details::operator_type& o,
24982 : const token_t tkn = token_t())
24983 : {
24984 3998707 : left = l;
24985 3998707 : right = r;
24986 3998707 : operation = o;
24987 3998707 : token = tkn;
24988 3998707 : }
24989 :
24990 8875389 : inline void reset()
24991 : {
24992 8875389 : left = e_level00;
24993 8875389 : right = e_level00;
24994 8875389 : operation = details::e_default;
24995 8875389 : }
24996 :
24997 : precedence_level left;
24998 : precedence_level right;
24999 : details::operator_type operation;
25000 : token_t token;
25001 : };
25002 :
25003 2682168 : inline void push_current_state(const state_t current_state)
25004 : {
25005 2682168 : current_state_stack_.push_back(current_state);
25006 2682168 : }
25007 :
25008 2682168 : inline void pop_current_state()
25009 : {
25010 2682168 : if (!current_state_stack_.empty())
25011 : {
25012 2682168 : current_state_stack_.pop_back();
25013 : }
25014 2682168 : }
25015 :
25016 3 : inline state_t current_state() const
25017 : {
25018 3 : return (!current_state_stack_.empty()) ?
25019 3 : current_state_stack_.back() :
25020 3 : state_t();
25021 : }
25022 :
25023 7096846 : inline bool halt_compilation_check()
25024 : {
25025 7096846 : compilation_check::compilation_context context;
25026 :
25027 7096846 : if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context))
25028 : {
25029 0 : const std::string error_message =
25030 0 : !context.error_message.empty() ? " Details: " + context.error_message : "";
25031 :
25032 0 : set_error(make_error(
25033 : parser_error::e_parser,
25034 0 : token_t(),
25035 : "ERR010 - Internal compilation check failed." + error_message,
25036 : exprtk_error_location));
25037 :
25038 0 : return true;
25039 0 : }
25040 :
25041 7096846 : return false;
25042 7096846 : }
25043 :
25044 6346791 : inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
25045 : {
25046 6346791 : if (halt_compilation_check())
25047 : {
25048 : exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n"));
25049 0 : return error_node();
25050 : }
25051 :
25052 6346791 : stack_limit_handler slh(*this);
25053 :
25054 6346791 : if (!slh)
25055 : {
25056 0 : return error_node();
25057 : }
25058 :
25059 6346791 : expression_node_ptr expression = parse_branch(precedence);
25060 :
25061 6346791 : if (0 == expression)
25062 : {
25063 153527 : return error_node();
25064 : }
25065 :
25066 6193264 : bool break_loop = false;
25067 :
25068 6193264 : state_t current_state;
25069 :
25070 5478291 : for ( ; ; )
25071 : {
25072 8875389 : current_state.reset();
25073 :
25074 8875389 : switch (current_token().type)
25075 : {
25076 11348 : case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break;
25077 10080 : case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break;
25078 1048 : case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break;
25079 330 : case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break;
25080 331 : case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break;
25081 75 : case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break;
25082 2728 : case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break;
25083 7491 : case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break;
25084 2256 : case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break;
25085 71765 : case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break;
25086 3045 : case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break;
25087 690 : case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break;
25088 7424 : case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break;
25089 1416909 : case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break;
25090 815459 : case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break;
25091 643982 : case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break;
25092 884906 : case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break;
25093 498 : case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break;
25094 94523 : case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break;
25095 4900501 : default :
25096 4900501 : if (token_t::e_symbol == current_token().type)
25097 : {
25098 43631 : static const std::string s_and = "and" ;
25099 43631 : static const std::string s_nand = "nand" ;
25100 43631 : static const std::string s_or = "or" ;
25101 43631 : static const std::string s_nor = "nor" ;
25102 43631 : static const std::string s_xor = "xor" ;
25103 43631 : static const std::string s_xnor = "xnor" ;
25104 43631 : static const std::string s_in = "in" ;
25105 43631 : static const std::string s_like = "like" ;
25106 43631 : static const std::string s_ilike = "ilike";
25107 43631 : static const std::string s_and1 = "&" ;
25108 43631 : static const std::string s_or1 = "|" ;
25109 43631 : static const std::string s_not = "not" ;
25110 :
25111 43629 : if (details::imatch(current_token().value,s_and))
25112 : {
25113 13565 : current_state.set(e_level03, e_level04, details::e_and, current_token());
25114 13565 : break;
25115 : }
25116 30064 : else if (details::imatch(current_token().value,s_and1))
25117 : {
25118 : #ifndef exprtk_disable_sc_andor
25119 463 : current_state.set(e_level03, e_level04, details::e_scand, current_token());
25120 : #else
25121 : current_state.set(e_level03, e_level04, details::e_and, current_token());
25122 : #endif
25123 463 : break;
25124 : }
25125 29601 : else if (details::imatch(current_token().value,s_nand))
25126 : {
25127 604 : current_state.set(e_level03, e_level04, details::e_nand, current_token());
25128 604 : break;
25129 : }
25130 28997 : else if (details::imatch(current_token().value,s_or))
25131 : {
25132 723 : current_state.set(e_level01, e_level02, details::e_or, current_token());
25133 723 : break;
25134 : }
25135 28274 : else if (details::imatch(current_token().value,s_or1))
25136 : {
25137 : #ifndef exprtk_disable_sc_andor
25138 420 : current_state.set(e_level01, e_level02, details::e_scor, current_token());
25139 : #else
25140 : current_state.set(e_level01, e_level02, details::e_or, current_token());
25141 : #endif
25142 420 : break;
25143 : }
25144 27854 : else if (details::imatch(current_token().value,s_nor))
25145 : {
25146 604 : current_state.set(e_level01, e_level02, details::e_nor, current_token());
25147 604 : break;
25148 : }
25149 27250 : else if (details::imatch(current_token().value,s_xor))
25150 : {
25151 265 : current_state.set(e_level01, e_level02, details::e_xor, current_token());
25152 265 : break;
25153 : }
25154 26985 : else if (details::imatch(current_token().value,s_xnor))
25155 : {
25156 80 : current_state.set(e_level01, e_level02, details::e_xnor, current_token());
25157 80 : break;
25158 : }
25159 26905 : else if (details::imatch(current_token().value,s_in))
25160 : {
25161 780 : current_state.set(e_level04, e_level04, details::e_in, current_token());
25162 780 : break;
25163 : }
25164 26125 : else if (details::imatch(current_token().value,s_like))
25165 : {
25166 3070 : current_state.set(e_level04, e_level04, details::e_like, current_token());
25167 3070 : break;
25168 : }
25169 23055 : else if (details::imatch(current_token().value,s_ilike))
25170 : {
25171 3245 : current_state.set(e_level04, e_level04, details::e_ilike, current_token());
25172 3245 : break;
25173 : }
25174 19810 : else if (details::imatch(current_token().value,s_not))
25175 : {
25176 0 : break;
25177 : }
25178 : }
25179 :
25180 4876682 : break_loop = true;
25181 : }
25182 :
25183 8875389 : if (break_loop)
25184 : {
25185 4876682 : parse_pending_string_rangesize(expression);
25186 4876682 : break;
25187 : }
25188 3998707 : else if (current_state.left < precedence)
25189 1202541 : break;
25190 :
25191 2796166 : const lexer::token prev_token = current_token();
25192 :
25193 2796166 : next_token();
25194 :
25195 2796166 : expression_node_ptr right_branch = error_node();
25196 2796166 : expression_node_ptr new_expression = error_node();
25197 :
25198 2796166 : if (is_invalid_logic_operation(current_state.operation))
25199 : {
25200 0 : free_node(node_allocator_,expression);
25201 :
25202 0 : set_error(make_error(
25203 : parser_error::e_syntax,
25204 : prev_token,
25205 : "ERR011 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
25206 : exprtk_error_location));
25207 :
25208 0 : return error_node();
25209 : }
25210 2796166 : else if (is_invalid_arithmetic_operation(current_state.operation))
25211 : {
25212 0 : free_node(node_allocator_,expression);
25213 :
25214 0 : set_error(make_error(
25215 : parser_error::e_syntax,
25216 : prev_token,
25217 : "ERR012 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
25218 : exprtk_error_location));
25219 :
25220 0 : return error_node();
25221 : }
25222 2796166 : else if (is_invalid_inequality_operation(current_state.operation))
25223 : {
25224 0 : free_node(node_allocator_,expression);
25225 :
25226 0 : set_error(make_error(
25227 : parser_error::e_syntax,
25228 : prev_token,
25229 : "ERR013 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
25230 : exprtk_error_location));
25231 :
25232 0 : return error_node();
25233 : }
25234 2796166 : else if (is_invalid_assignment_operation(current_state.operation))
25235 : {
25236 0 : free_node(node_allocator_,expression);
25237 :
25238 0 : set_error(make_error(
25239 : parser_error::e_syntax,
25240 : prev_token,
25241 : "ERR014 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
25242 : exprtk_error_location));
25243 :
25244 0 : return error_node();
25245 : }
25246 :
25247 2796166 : if (0 != (right_branch = parse_expression(current_state.right)))
25248 : {
25249 2682168 : if (
25250 5364336 : details::is_return_node(expression ) ||
25251 2682168 : details::is_return_node(right_branch)
25252 : )
25253 : {
25254 0 : free_node(node_allocator_, expression );
25255 0 : free_node(node_allocator_, right_branch);
25256 :
25257 0 : set_error(make_error(
25258 : parser_error::e_syntax,
25259 : prev_token,
25260 : "ERR015 - Return statements cannot be part of sub-expressions",
25261 : exprtk_error_location));
25262 :
25263 0 : return error_node();
25264 : }
25265 :
25266 2682168 : push_current_state(current_state);
25267 :
25268 : new_expression = expression_generator_
25269 2682168 : (
25270 : current_state.operation,
25271 : expression,
25272 : right_branch
25273 : );
25274 :
25275 2682168 : pop_current_state();
25276 : }
25277 :
25278 2796166 : if (0 == new_expression)
25279 : {
25280 114041 : if (error_list_.empty())
25281 : {
25282 36 : set_error(make_error(
25283 : parser_error::e_syntax,
25284 : prev_token,
25285 24 : !synthesis_error_.empty() ?
25286 0 : synthesis_error_ :
25287 : "ERR016 - General parsing error at token: '" + prev_token.value + "'",
25288 : exprtk_error_location));
25289 : }
25290 :
25291 114041 : free_node(node_allocator_, expression );
25292 114041 : free_node(node_allocator_, right_branch);
25293 :
25294 114041 : return error_node();
25295 : }
25296 : else
25297 : {
25298 2682125 : if (
25299 2682125 : token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
25300 : (e_level00 == precedence)
25301 : )
25302 : {
25303 2111 : expression = parse_ternary_conditional_statement(new_expression);
25304 : }
25305 : else
25306 2680014 : expression = new_expression;
25307 :
25308 2682125 : parse_pending_string_rangesize(expression);
25309 : }
25310 : }
25311 :
25312 6079223 : if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
25313 : {
25314 0 : set_error(make_error(
25315 : parser_error::e_syntax,
25316 0 : current_token(),
25317 0 : "ERR017 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
25318 0 : " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
25319 : exprtk_error_location));
25320 :
25321 0 : free_node(node_allocator_,expression);
25322 :
25323 0 : return error_node();
25324 : }
25325 :
25326 6079223 : return expression;
25327 6346791 : }
25328 :
25329 1780 : bool simplify_unary_negation_branch(expression_node_ptr& node)
25330 : {
25331 : {
25332 : typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
25333 1780 : ubn_t* n = dynamic_cast<ubn_t*>(node);
25334 :
25335 1780 : if (n)
25336 : {
25337 1460 : expression_node_ptr un_r = n->branch(0);
25338 1460 : n->release();
25339 1460 : free_node(node_allocator_,node);
25340 1460 : node = un_r;
25341 :
25342 1460 : return true;
25343 : }
25344 : }
25345 :
25346 : {
25347 : typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
25348 :
25349 320 : uvn_t* n = dynamic_cast<uvn_t*>(node);
25350 :
25351 320 : if (n)
25352 : {
25353 320 : const T& v = n->v();
25354 320 : expression_node_ptr return_node = error_node();
25355 :
25356 320 : if (
25357 640 : (0 != (return_node = symtab_store_.get_variable(v))) ||
25358 320 : (0 != (return_node = sem_ .get_variable(v)))
25359 : )
25360 : {
25361 320 : free_node(node_allocator_,node);
25362 320 : node = return_node;
25363 :
25364 320 : return true;
25365 : }
25366 : else
25367 : {
25368 0 : set_error(make_error(
25369 : parser_error::e_syntax,
25370 0 : current_token(),
25371 : "ERR018 - Failed to find variable node in symbol table",
25372 : exprtk_error_location));
25373 :
25374 0 : free_node(node_allocator_,node);
25375 :
25376 0 : return false;
25377 : }
25378 : }
25379 : }
25380 :
25381 0 : return false;
25382 : }
25383 :
25384 23486486 : static inline expression_node_ptr error_node()
25385 : {
25386 23486486 : return reinterpret_cast<expression_node_ptr>(0);
25387 : }
25388 :
25389 : struct scoped_expression_delete
25390 : {
25391 1195 : scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
25392 1195 : : delete_ptr(true)
25393 1195 : , parser_(pr)
25394 1195 : , expression_(expression)
25395 1195 : {}
25396 :
25397 1195 : ~scoped_expression_delete()
25398 : {
25399 1195 : if (delete_ptr)
25400 : {
25401 0 : free_node(parser_.node_allocator_, expression_);
25402 : }
25403 1195 : }
25404 :
25405 : bool delete_ptr;
25406 : parser<T>& parser_;
25407 : expression_node_ptr& expression_;
25408 :
25409 : private:
25410 :
25411 : scoped_expression_delete(const scoped_expression_delete&) exprtk_delete;
25412 : scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete;
25413 : };
25414 :
25415 : template <typename Type, std::size_t N>
25416 : struct scoped_delete
25417 : {
25418 : typedef Type* ptr_t;
25419 :
25420 : scoped_delete(parser<T>& pr, ptr_t& p)
25421 : : delete_ptr(true)
25422 : , parser_(pr)
25423 : , p_(&p)
25424 : {}
25425 :
25426 423974 : scoped_delete(parser<T>& pr, ptr_t (&p)[N])
25427 423974 : : delete_ptr(true)
25428 423974 : , parser_(pr)
25429 423974 : , p_(&p[0])
25430 423974 : {}
25431 :
25432 423974 : ~scoped_delete()
25433 : {
25434 423974 : if (delete_ptr)
25435 : {
25436 109625 : for (std::size_t i = 0; i < N; ++i)
25437 : {
25438 87700 : free_node(parser_.node_allocator_, p_[i]);
25439 : }
25440 : }
25441 423974 : }
25442 :
25443 : bool delete_ptr;
25444 : parser<T>& parser_;
25445 : ptr_t* p_;
25446 :
25447 : private:
25448 :
25449 : scoped_delete(const scoped_delete<Type,N>&) exprtk_delete;
25450 : scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete;
25451 : };
25452 :
25453 : template <typename Type>
25454 : struct scoped_deq_delete
25455 : {
25456 : typedef Type* ptr_t;
25457 :
25458 : scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
25459 : : delete_ptr(true)
25460 : , parser_(pr)
25461 : , deq_(deq)
25462 : {}
25463 :
25464 : ~scoped_deq_delete()
25465 : {
25466 : if (delete_ptr && !deq_.empty())
25467 : {
25468 : for (std::size_t i = 0; i < deq_.size(); ++i)
25469 : {
25470 : free_node(parser_.node_allocator_,deq_[i]);
25471 : }
25472 :
25473 : deq_.clear();
25474 : }
25475 : }
25476 :
25477 : bool delete_ptr;
25478 : parser<T>& parser_;
25479 : std::deque<ptr_t>& deq_;
25480 :
25481 : private:
25482 :
25483 : scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete;
25484 : scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete;
25485 : };
25486 :
25487 : template <typename Type>
25488 : struct scoped_vec_delete
25489 : {
25490 : typedef Type* ptr_t;
25491 :
25492 428715 : scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
25493 428715 : : delete_ptr(true)
25494 428715 : , parser_(pr)
25495 428715 : , vec_(vec)
25496 428715 : {}
25497 :
25498 428715 : ~scoped_vec_delete()
25499 : {
25500 428715 : if (delete_ptr && !vec_.empty())
25501 : {
25502 273 : for (std::size_t i = 0; i < vec_.size(); ++i)
25503 : {
25504 : exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i])));
25505 183 : free_node(parser_.node_allocator_,vec_[i]);
25506 : }
25507 :
25508 90 : vec_.clear();
25509 : }
25510 428715 : }
25511 :
25512 : ptr_t operator[](const std::size_t index)
25513 : {
25514 : return vec_[index];
25515 : }
25516 :
25517 : bool delete_ptr;
25518 : parser<T>& parser_;
25519 : std::vector<ptr_t>& vec_;
25520 :
25521 : private:
25522 :
25523 : scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete;
25524 : scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete;
25525 : };
25526 :
25527 : struct scoped_bool_negator
25528 : {
25529 707 : explicit scoped_bool_negator(bool& bb)
25530 707 : : b(bb)
25531 707 : { b = !b; }
25532 :
25533 707 : ~scoped_bool_negator()
25534 707 : { b = !b; }
25535 :
25536 : bool& b;
25537 : };
25538 :
25539 : struct scoped_bool_or_restorer
25540 : {
25541 20944 : explicit scoped_bool_or_restorer(bool& bb)
25542 20944 : : b(bb)
25543 20944 : , original_value_(bb)
25544 20944 : {}
25545 :
25546 20944 : ~scoped_bool_or_restorer()
25547 : {
25548 20944 : b = b || original_value_;
25549 20944 : }
25550 :
25551 : bool& b;
25552 : bool original_value_;
25553 : };
25554 :
25555 : struct scoped_inc_dec
25556 : {
25557 2837 : explicit scoped_inc_dec(std::size_t& v)
25558 2837 : : v_(v)
25559 2837 : { ++v_; }
25560 :
25561 2837 : ~scoped_inc_dec()
25562 : {
25563 2837 : assert(v_ > 0);
25564 2837 : --v_;
25565 2837 : }
25566 :
25567 : std::size_t& v_;
25568 : };
25569 :
25570 60611 : inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
25571 : {
25572 60611 : expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
25573 :
25574 60611 : switch (function->param_count)
25575 : {
25576 231 : case 0 : func_node = parse_function_call_0 (function,function_name); break;
25577 5250 : case 1 : func_node = parse_function_call< 1>(function,function_name); break;
25578 40616 : case 2 : func_node = parse_function_call< 2>(function,function_name); break;
25579 1626 : case 3 : func_node = parse_function_call< 3>(function,function_name); break;
25580 1727 : case 4 : func_node = parse_function_call< 4>(function,function_name); break;
25581 1725 : case 5 : func_node = parse_function_call< 5>(function,function_name); break;
25582 1316 : case 6 : func_node = parse_function_call< 6>(function,function_name); break;
25583 1015 : case 7 : func_node = parse_function_call< 7>(function,function_name); break;
25584 1015 : case 8 : func_node = parse_function_call< 8>(function,function_name); break;
25585 1015 : case 9 : func_node = parse_function_call< 9>(function,function_name); break;
25586 1015 : case 10 : func_node = parse_function_call<10>(function,function_name); break;
25587 1015 : case 11 : func_node = parse_function_call<11>(function,function_name); break;
25588 1015 : case 12 : func_node = parse_function_call<12>(function,function_name); break;
25589 1015 : case 13 : func_node = parse_function_call<13>(function,function_name); break;
25590 1015 : case 14 : func_node = parse_function_call<14>(function,function_name); break;
25591 0 : case 15 : func_node = parse_function_call<15>(function,function_name); break;
25592 0 : case 16 : func_node = parse_function_call<16>(function,function_name); break;
25593 0 : case 17 : func_node = parse_function_call<17>(function,function_name); break;
25594 0 : case 18 : func_node = parse_function_call<18>(function,function_name); break;
25595 0 : case 19 : func_node = parse_function_call<19>(function,function_name); break;
25596 0 : case 20 : func_node = parse_function_call<20>(function,function_name); break;
25597 0 : default : {
25598 0 : set_error(make_error(
25599 : parser_error::e_syntax,
25600 0 : current_token(),
25601 : "ERR019 - Invalid number of parameters for function: '" + function_name + "'",
25602 : exprtk_error_location));
25603 :
25604 0 : return error_node();
25605 : }
25606 : }
25607 :
25608 60611 : if (func_node)
25609 60611 : return func_node;
25610 : else
25611 : {
25612 0 : set_error(make_error(
25613 : parser_error::e_syntax,
25614 0 : current_token(),
25615 : "ERR020 - Failed to generate call to function: '" + function_name + "'",
25616 : exprtk_error_location));
25617 :
25618 0 : return error_node();
25619 : }
25620 : }
25621 :
25622 : template <std::size_t NumberofParameters>
25623 60380 : inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
25624 : {
25625 : #ifdef _MSC_VER
25626 : #pragma warning(push)
25627 : #pragma warning(disable: 4127)
25628 : #endif
25629 : if (0 == NumberofParameters)
25630 : {
25631 : set_error(make_error(
25632 : parser_error::e_syntax,
25633 : current_token(),
25634 : "ERR021 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
25635 : exprtk_error_location));
25636 :
25637 : return error_node();
25638 : }
25639 : #ifdef _MSC_VER
25640 : #pragma warning(pop)
25641 : #endif
25642 :
25643 : expression_node_ptr branch[NumberofParameters];
25644 60380 : expression_node_ptr result = error_node();
25645 :
25646 60380 : std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
25647 :
25648 60380 : scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
25649 :
25650 60380 : next_token();
25651 :
25652 60380 : if (!token_is(token_t::e_lbracket))
25653 : {
25654 0 : set_error(make_error(
25655 : parser_error::e_syntax,
25656 0 : current_token(),
25657 : "ERR022 - Expecting argument list for function: '" + function_name + "'",
25658 : exprtk_error_location));
25659 :
25660 0 : return error_node();
25661 : }
25662 :
25663 260429 : for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
25664 : {
25665 200049 : branch[i] = parse_expression();
25666 :
25667 200049 : if (0 == branch[i])
25668 : {
25669 0 : set_error(make_error(
25670 : parser_error::e_syntax,
25671 0 : current_token(),
25672 : "ERR023 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
25673 : exprtk_error_location));
25674 :
25675 0 : return error_node();
25676 : }
25677 200049 : else if (i < static_cast<int>(NumberofParameters - 1))
25678 : {
25679 139669 : if (!token_is(token_t::e_comma))
25680 : {
25681 0 : set_error(make_error(
25682 : parser_error::e_syntax,
25683 0 : current_token(),
25684 : "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
25685 : exprtk_error_location));
25686 :
25687 0 : return error_node();
25688 : }
25689 : }
25690 : }
25691 :
25692 60380 : if (!token_is(token_t::e_rbracket))
25693 : {
25694 0 : set_error(make_error(
25695 : parser_error::e_syntax,
25696 0 : current_token(),
25697 : "ERR025 - Invalid number of arguments for function: '" + function_name + "'",
25698 : exprtk_error_location));
25699 :
25700 0 : return error_node();
25701 : }
25702 : else
25703 60380 : result = expression_generator_.function(function,branch);
25704 :
25705 60380 : sd.delete_ptr = (0 == result);
25706 :
25707 60380 : return result;
25708 60380 : }
25709 :
25710 231 : inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
25711 : {
25712 231 : expression_node_ptr result = expression_generator_.function(function);
25713 :
25714 231 : state_.side_effect_present = function->has_side_effects();
25715 :
25716 231 : next_token();
25717 :
25718 231 : if (
25719 347 : token_is(token_t::e_lbracket) &&
25720 347 : !token_is(token_t::e_rbracket)
25721 : )
25722 : {
25723 0 : set_error(make_error(
25724 : parser_error::e_syntax,
25725 0 : current_token(),
25726 : "ERR026 - Expecting '()' to proceed call to function: '" + function_name + "'",
25727 : exprtk_error_location));
25728 :
25729 0 : free_node(node_allocator_,result);
25730 :
25731 0 : return error_node();
25732 : }
25733 : else
25734 231 : return result;
25735 : }
25736 :
25737 : template <std::size_t MaxNumberofParameters>
25738 359349 : inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "")
25739 : {
25740 359349 : std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
25741 :
25742 359349 : scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
25743 :
25744 359349 : next_token();
25745 :
25746 359349 : if (!token_is(token_t::e_lbracket))
25747 : {
25748 0 : set_error(make_error(
25749 : parser_error::e_syntax,
25750 0 : current_token(),
25751 : "ERR027 - Expected a '(' at start of function call to '" + function_name +
25752 0 : "', instead got: '" + current_token().value + "'",
25753 : exprtk_error_location));
25754 :
25755 0 : return 0;
25756 : }
25757 :
25758 359349 : if (token_is(token_t::e_rbracket, e_hold))
25759 : {
25760 0 : set_error(make_error(
25761 : parser_error::e_syntax,
25762 0 : current_token(),
25763 : "ERR028 - Expected at least one input parameter for function call '" + function_name + "'",
25764 : exprtk_error_location));
25765 :
25766 0 : return 0;
25767 : }
25768 :
25769 359349 : std::size_t param_index = 0;
25770 :
25771 626882 : for (; param_index < MaxNumberofParameters; ++param_index)
25772 : {
25773 626882 : param_list[param_index] = parse_expression();
25774 :
25775 626882 : if (0 == param_list[param_index])
25776 21919 : return 0;
25777 604963 : else if (token_is(token_t::e_rbracket))
25778 : {
25779 337424 : sd.delete_ptr = false;
25780 337424 : break;
25781 : }
25782 267539 : else if (token_is(token_t::e_comma))
25783 267533 : continue;
25784 : else
25785 : {
25786 18 : set_error(make_error(
25787 : parser_error::e_syntax,
25788 6 : current_token(),
25789 6 : "ERR029 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
25790 : exprtk_error_location));
25791 :
25792 6 : return 0;
25793 : }
25794 : }
25795 :
25796 337424 : if (sd.delete_ptr)
25797 : {
25798 0 : set_error(make_error(
25799 : parser_error::e_syntax,
25800 0 : current_token(),
25801 : "ERR030 - Invalid number of input parameters passed to function '" + function_name + "'",
25802 : exprtk_error_location));
25803 :
25804 0 : return 0;
25805 : }
25806 :
25807 337424 : return (param_index + 1);
25808 359349 : }
25809 :
25810 359349 : inline expression_node_ptr parse_base_operation()
25811 : {
25812 : typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
25813 :
25814 359349 : const std::string operation_name = current_token().value;
25815 359349 : const token_t diagnostic_token = current_token();
25816 :
25817 359349 : map_range_t itr_range = base_ops_map_.equal_range(operation_name);
25818 :
25819 359349 : if (0 == std::distance(itr_range.first,itr_range.second))
25820 : {
25821 0 : set_error(make_error(
25822 : parser_error::e_syntax,
25823 : diagnostic_token,
25824 : "ERR031 - No entry found for base operation: " + operation_name,
25825 : exprtk_error_location));
25826 :
25827 0 : return error_node();
25828 : }
25829 :
25830 : static const std::size_t MaxNumberofParameters = 4;
25831 359349 : expression_node_ptr param_list[MaxNumberofParameters] = {0};
25832 :
25833 359349 : const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
25834 :
25835 359349 : if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
25836 : {
25837 337424 : for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
25838 : {
25839 337424 : const details::base_operation_t& operation = itr->second;
25840 :
25841 337424 : if (operation.num_params == parameter_count)
25842 : {
25843 337424 : switch (parameter_count)
25844 : {
25845 : #define base_opr_case(N) \
25846 : case N : { \
25847 : expression_node_ptr pl##N[N] = {0}; \
25848 : std::copy(param_list, param_list + N, pl##N); \
25849 : lodge_symbol(operation_name, e_st_function); \
25850 : return expression_generator_(operation.type, pl##N); \
25851 : } \
25852 :
25853 70362 : base_opr_case(1)
25854 266591 : base_opr_case(2)
25855 471 : base_opr_case(3)
25856 0 : base_opr_case(4)
25857 : #undef base_opr_case
25858 : }
25859 : }
25860 : }
25861 : }
25862 :
25863 109625 : for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
25864 : {
25865 87700 : free_node(node_allocator_, param_list[i]);
25866 : }
25867 :
25868 21925 : set_error(make_error(
25869 : parser_error::e_syntax,
25870 : diagnostic_token,
25871 : "ERR032 - Invalid number of input parameters for call to function: '" + operation_name + "'",
25872 : exprtk_error_location));
25873 :
25874 21925 : return error_node();
25875 359349 : }
25876 :
25877 1356 : inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
25878 : {
25879 : // Parse: [if][(][condition][,][consequent][,][alternative][)]
25880 :
25881 1356 : expression_node_ptr consequent = error_node();
25882 1356 : expression_node_ptr alternative = error_node();
25883 :
25884 1356 : bool result = true;
25885 :
25886 1356 : if (!token_is(token_t::e_comma))
25887 : {
25888 0 : set_error(make_error(
25889 : parser_error::e_syntax,
25890 0 : current_token(),
25891 : "ERR033 - Expected ',' between if-statement condition and consequent",
25892 : exprtk_error_location));
25893 :
25894 0 : result = false;
25895 : }
25896 1356 : else if (0 == (consequent = parse_expression()))
25897 : {
25898 0 : set_error(make_error(
25899 : parser_error::e_syntax,
25900 0 : current_token(),
25901 : "ERR034 - Failed to parse consequent for if-statement",
25902 : exprtk_error_location));
25903 :
25904 0 : result = false;
25905 : }
25906 1356 : else if (!token_is(token_t::e_comma))
25907 : {
25908 0 : set_error(make_error(
25909 : parser_error::e_syntax,
25910 0 : current_token(),
25911 : "ERR035 - Expected ',' between if-statement consequent and alternative",
25912 : exprtk_error_location));
25913 :
25914 0 : result = false;
25915 : }
25916 1356 : else if (0 == (alternative = parse_expression()))
25917 : {
25918 0 : set_error(make_error(
25919 : parser_error::e_syntax,
25920 0 : current_token(),
25921 : "ERR036 - Failed to parse alternative for if-statement",
25922 : exprtk_error_location));
25923 :
25924 0 : result = false;
25925 : }
25926 1356 : else if (!token_is(token_t::e_rbracket))
25927 : {
25928 0 : set_error(make_error(
25929 : parser_error::e_syntax,
25930 0 : current_token(),
25931 : "ERR037 - Expected ')' at the end of if-statement",
25932 : exprtk_error_location));
25933 :
25934 0 : result = false;
25935 : }
25936 :
25937 : #ifndef exprtk_disable_string_capabilities
25938 1356 : if (result)
25939 : {
25940 1356 : const bool consq_is_str = is_generally_string_node(consequent );
25941 1356 : const bool alter_is_str = is_generally_string_node(alternative);
25942 :
25943 1356 : if (consq_is_str || alter_is_str)
25944 : {
25945 0 : if (consq_is_str && alter_is_str)
25946 : {
25947 0 : expression_node_ptr result_node =
25948 : expression_generator_
25949 0 : .conditional_string(condition, consequent, alternative);
25950 :
25951 0 : if (result_node && result_node->valid())
25952 : {
25953 0 : return result_node;
25954 : }
25955 :
25956 0 : set_error(make_error(
25957 : parser_error::e_synthesis,
25958 0 : current_token(),
25959 : "ERR038 - Failed to synthesize node: conditional_string",
25960 : exprtk_error_location));
25961 :
25962 0 : free_node(node_allocator_, result_node);
25963 0 : return error_node();
25964 : }
25965 :
25966 0 : set_error(make_error(
25967 : parser_error::e_syntax,
25968 0 : current_token(),
25969 : "ERR039 - Return types of if-statement differ: string/non-string",
25970 : exprtk_error_location));
25971 :
25972 0 : result = false;
25973 : }
25974 : }
25975 : #endif
25976 :
25977 1356 : if (result)
25978 : {
25979 1356 : const bool consq_is_vec = is_ivector_node(consequent );
25980 1356 : const bool alter_is_vec = is_ivector_node(alternative);
25981 :
25982 1356 : if (consq_is_vec || alter_is_vec)
25983 : {
25984 800 : if (consq_is_vec && alter_is_vec)
25985 : {
25986 : return expression_generator_
25987 800 : .conditional_vector(condition, consequent, alternative);
25988 : }
25989 :
25990 0 : set_error(make_error(
25991 : parser_error::e_syntax,
25992 0 : current_token(),
25993 : "ERR040 - Return types of if-statement differ: vector/non-vector",
25994 : exprtk_error_location));
25995 :
25996 0 : result = false;
25997 : }
25998 : }
25999 :
26000 556 : if (!result)
26001 : {
26002 0 : free_node(node_allocator_, condition );
26003 0 : free_node(node_allocator_, consequent );
26004 0 : free_node(node_allocator_, alternative);
26005 :
26006 0 : return error_node();
26007 : }
26008 : else
26009 : return expression_generator_
26010 556 : .conditional(condition, consequent, alternative);
26011 : }
26012 :
26013 4434 : inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
26014 : {
26015 4434 : expression_node_ptr consequent = error_node();
26016 4434 : expression_node_ptr alternative = error_node();
26017 :
26018 4434 : bool result = true;
26019 :
26020 4434 : if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
26021 : {
26022 5888 : if (0 == (consequent = parse_multi_sequence("if-statement-01")))
26023 : {
26024 0 : set_error(make_error(
26025 : parser_error::e_syntax,
26026 0 : current_token(),
26027 : "ERR041 - Failed to parse body of consequent for if-statement",
26028 : exprtk_error_location));
26029 :
26030 0 : result = false;
26031 : }
26032 2944 : else if
26033 : (
26034 5914 : !settings_.commutative_check_enabled() &&
26035 2983 : !token_is("else",prsrhlpr_t::e_hold) &&
26036 10 : !token_is_loop(prsrhlpr_t::e_hold) &&
26037 10 : !token_is_arithmetic_opr(prsrhlpr_t::e_hold) &&
26038 10 : !token_is_right_bracket (prsrhlpr_t::e_hold) &&
26039 10 : !token_is_ineq_opr (prsrhlpr_t::e_hold) &&
26040 2967 : !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
26041 2954 : !token_is(token_t::e_eof)
26042 : )
26043 : {
26044 32 : set_error(make_error(
26045 : parser_error::e_syntax,
26046 8 : current_token(),
26047 : "ERR042 - Expected ';' at the end of the consequent for if-statement (1)",
26048 : exprtk_error_location));
26049 :
26050 8 : result = false;
26051 : }
26052 : }
26053 : else
26054 : {
26055 1490 : if (
26056 2978 : settings_.commutative_check_enabled() &&
26057 2978 : token_is(token_t::e_mul,prsrhlpr_t::e_hold)
26058 : )
26059 : {
26060 1362 : next_token();
26061 : }
26062 :
26063 1490 : if (0 != (consequent = parse_expression()))
26064 : {
26065 1490 : if (!token_is(token_t::e_eof))
26066 : {
26067 8 : set_error(make_error(
26068 : parser_error::e_syntax,
26069 2 : current_token(),
26070 : "ERR043 - Expected ';' at the end of the consequent for if-statement (2)",
26071 : exprtk_error_location));
26072 :
26073 2 : result = false;
26074 : }
26075 : }
26076 : else
26077 : {
26078 0 : set_error(make_error(
26079 : parser_error::e_syntax,
26080 0 : current_token(),
26081 : "ERR044 - Failed to parse body of consequent for if-statement",
26082 : exprtk_error_location));
26083 :
26084 0 : result = false;
26085 : }
26086 : }
26087 :
26088 4434 : if (result)
26089 : {
26090 8848 : if (details::imatch(current_token().value,"else"))
26091 : {
26092 2972 : next_token();
26093 :
26094 2972 : if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
26095 : {
26096 1810 : if (0 == (alternative = parse_multi_sequence("else-statement-01")))
26097 : {
26098 0 : set_error(make_error(
26099 : parser_error::e_syntax,
26100 0 : current_token(),
26101 : "ERR045 - Failed to parse body of the 'else' for if-statement",
26102 : exprtk_error_location));
26103 :
26104 0 : result = false;
26105 : }
26106 : }
26107 4134 : else if (details::imatch(current_token().value,"if"))
26108 : {
26109 563 : if (0 == (alternative = parse_conditional_statement()))
26110 : {
26111 12 : set_error(make_error(
26112 : parser_error::e_syntax,
26113 3 : current_token(),
26114 : "ERR046 - Failed to parse body of if-else statement",
26115 : exprtk_error_location));
26116 :
26117 3 : result = false;
26118 : }
26119 : }
26120 1504 : else if (0 != (alternative = parse_expression()))
26121 : {
26122 1504 : if (
26123 3008 : !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
26124 3008 : !token_is(token_t::e_eof)
26125 : )
26126 : {
26127 0 : set_error(make_error(
26128 : parser_error::e_syntax,
26129 0 : current_token(),
26130 : "ERR047 - Expected ';' at the end of the 'else-if' for the if-statement",
26131 : exprtk_error_location));
26132 :
26133 0 : result = false;
26134 : }
26135 : }
26136 : else
26137 : {
26138 0 : set_error(make_error(
26139 : parser_error::e_syntax,
26140 0 : current_token(),
26141 : "ERR048 - Failed to parse body of the 'else' for if-statement",
26142 : exprtk_error_location));
26143 :
26144 0 : result = false;
26145 : }
26146 : }
26147 : }
26148 :
26149 : #ifndef exprtk_disable_string_capabilities
26150 4434 : if (result)
26151 : {
26152 4421 : const bool consq_is_str = is_generally_string_node(consequent );
26153 4421 : const bool alter_is_str = is_generally_string_node(alternative);
26154 :
26155 4421 : if (consq_is_str || alter_is_str)
26156 : {
26157 45 : if (consq_is_str && alter_is_str)
26158 : {
26159 : return expression_generator_
26160 45 : .conditional_string(condition, consequent, alternative);
26161 : }
26162 :
26163 0 : set_error(make_error(
26164 : parser_error::e_syntax,
26165 0 : current_token(),
26166 : "ERR049 - Return types of if-statement differ: string/non-string",
26167 : exprtk_error_location));
26168 :
26169 0 : result = false;
26170 : }
26171 : }
26172 : #endif
26173 :
26174 4389 : if (result)
26175 : {
26176 4376 : const bool consq_is_vec = is_ivector_node(consequent );
26177 4376 : const bool alter_is_vec = is_ivector_node(alternative);
26178 :
26179 4376 : if (consq_is_vec || alter_is_vec)
26180 : {
26181 813 : if (consq_is_vec && alter_is_vec)
26182 : {
26183 : return expression_generator_
26184 813 : .conditional_vector(condition, consequent, alternative);
26185 : }
26186 :
26187 0 : set_error(make_error(
26188 : parser_error::e_syntax,
26189 0 : current_token(),
26190 : "ERR050 - Return types of if-statement differ: vector/non-vector",
26191 : exprtk_error_location));
26192 :
26193 0 : result = false;
26194 : }
26195 : }
26196 :
26197 3576 : if (!result)
26198 : {
26199 13 : free_node(node_allocator_, condition );
26200 13 : free_node(node_allocator_, consequent );
26201 13 : free_node(node_allocator_, alternative);
26202 :
26203 13 : return error_node();
26204 : }
26205 : else
26206 : return expression_generator_
26207 3563 : .conditional(condition, consequent, alternative);
26208 : }
26209 :
26210 5790 : inline expression_node_ptr parse_conditional_statement()
26211 : {
26212 5790 : expression_node_ptr condition = error_node();
26213 :
26214 5790 : next_token();
26215 :
26216 5790 : if (!token_is(token_t::e_lbracket))
26217 : {
26218 0 : set_error(make_error(
26219 : parser_error::e_syntax,
26220 0 : current_token(),
26221 0 : "ERR051 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
26222 : exprtk_error_location));
26223 :
26224 0 : return error_node();
26225 : }
26226 5790 : else if (0 == (condition = parse_expression()))
26227 : {
26228 0 : set_error(make_error(
26229 : parser_error::e_syntax,
26230 0 : current_token(),
26231 : "ERR052 - Failed to parse condition for if-statement",
26232 : exprtk_error_location));
26233 :
26234 0 : return error_node();
26235 : }
26236 5790 : else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
26237 : {
26238 : // if (x,y,z)
26239 1356 : return parse_conditional_statement_01(condition);
26240 : }
26241 4434 : else if (token_is(token_t::e_rbracket))
26242 : {
26243 : /*
26244 : 00. if (x) y;
26245 : 01. if (x) y; else z;
26246 : 02. if (x) y; else {z0; ... zn;}
26247 : 03. if (x) y; else if (z) w;
26248 : 04. if (x) y; else if (z) w; else u;
26249 : 05. if (x) y; else if (z) w; else {u0; ... un;}
26250 : 06. if (x) y; else if (z) {w0; ... wn;}
26251 : 07. if (x) {y0; ... yn;}
26252 : 08. if (x) {y0; ... yn;} else z;
26253 : 09. if (x) {y0; ... yn;} else {z0; ... zn;};
26254 : 10. if (x) {y0; ... yn;} else if (z) w;
26255 : 11. if (x) {y0; ... yn;} else if (z) w; else u;
26256 : 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
26257 : 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
26258 : */
26259 4434 : return parse_conditional_statement_02(condition);
26260 : }
26261 :
26262 0 : set_error(make_error(
26263 : parser_error::e_syntax,
26264 0 : current_token(),
26265 : "ERR053 - Invalid if-statement",
26266 : exprtk_error_location));
26267 :
26268 0 : free_node(node_allocator_,condition);
26269 :
26270 0 : return error_node();
26271 : }
26272 :
26273 2811 : inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
26274 : {
26275 : // Parse: [condition][?][consequent][:][alternative]
26276 2811 : expression_node_ptr consequent = error_node();
26277 2811 : expression_node_ptr alternative = error_node();
26278 :
26279 2811 : bool result = true;
26280 :
26281 2811 : if (0 == condition)
26282 : {
26283 0 : set_error(make_error(
26284 : parser_error::e_syntax,
26285 0 : current_token(),
26286 : "ERR054 - Encountered invalid condition branch for ternary if-statement",
26287 : exprtk_error_location));
26288 :
26289 0 : return error_node();
26290 : }
26291 2811 : else if (!token_is(token_t::e_ternary))
26292 : {
26293 0 : set_error(make_error(
26294 : parser_error::e_syntax,
26295 0 : current_token(),
26296 : "ERR055 - Expected '?' after condition of ternary if-statement",
26297 : exprtk_error_location));
26298 :
26299 0 : result = false;
26300 : }
26301 2811 : else if (0 == (consequent = parse_expression()))
26302 : {
26303 56 : set_error(make_error(
26304 : parser_error::e_syntax,
26305 14 : current_token(),
26306 : "ERR056 - Failed to parse consequent for ternary if-statement",
26307 : exprtk_error_location));
26308 :
26309 14 : result = false;
26310 : }
26311 2797 : else if (!token_is(token_t::e_colon))
26312 : {
26313 64 : set_error(make_error(
26314 : parser_error::e_syntax,
26315 16 : current_token(),
26316 : "ERR057 - Expected ':' between ternary if-statement consequent and alternative",
26317 : exprtk_error_location));
26318 :
26319 16 : result = false;
26320 : }
26321 2781 : else if (0 == (alternative = parse_expression()))
26322 : {
26323 0 : set_error(make_error(
26324 : parser_error::e_syntax,
26325 0 : current_token(),
26326 : "ERR058 - Failed to parse alternative for ternary if-statement",
26327 : exprtk_error_location));
26328 :
26329 0 : result = false;
26330 : }
26331 :
26332 : #ifndef exprtk_disable_string_capabilities
26333 2811 : if (result)
26334 : {
26335 2781 : const bool consq_is_str = is_generally_string_node(consequent );
26336 2781 : const bool alter_is_str = is_generally_string_node(alternative);
26337 :
26338 2781 : if (consq_is_str || alter_is_str)
26339 : {
26340 1106 : if (consq_is_str && alter_is_str)
26341 : {
26342 : return expression_generator_
26343 1106 : .conditional_string(condition, consequent, alternative);
26344 : }
26345 :
26346 0 : set_error(make_error(
26347 : parser_error::e_syntax,
26348 0 : current_token(),
26349 : "ERR059 - Return types of ternary differ: string/non-string",
26350 : exprtk_error_location));
26351 :
26352 0 : result = false;
26353 : }
26354 : }
26355 : #endif
26356 :
26357 1705 : if (result)
26358 : {
26359 1675 : const bool consq_is_vec = is_ivector_node(consequent );
26360 1675 : const bool alter_is_vec = is_ivector_node(alternative);
26361 :
26362 1675 : if (consq_is_vec || alter_is_vec)
26363 : {
26364 160 : if (consq_is_vec && alter_is_vec)
26365 : {
26366 : return expression_generator_
26367 160 : .conditional_vector(condition, consequent, alternative);
26368 : }
26369 :
26370 0 : set_error(make_error(
26371 : parser_error::e_syntax,
26372 0 : current_token(),
26373 : "ERR060 - Return types of ternary differ: vector/non-vector",
26374 : exprtk_error_location));
26375 :
26376 0 : result = false;
26377 : }
26378 : }
26379 :
26380 1545 : if (!result)
26381 : {
26382 30 : free_node(node_allocator_, condition );
26383 30 : free_node(node_allocator_, consequent );
26384 30 : free_node(node_allocator_, alternative);
26385 :
26386 30 : return error_node();
26387 : }
26388 : else
26389 : return expression_generator_
26390 1515 : .conditional(condition, consequent, alternative);
26391 : }
26392 :
26393 728 : inline expression_node_ptr parse_not_statement()
26394 : {
26395 2184 : if (settings_.logic_disabled("not"))
26396 : {
26397 0 : set_error(make_error(
26398 : parser_error::e_syntax,
26399 0 : current_token(),
26400 : "ERR061 - Invalid or disabled logic operation 'not'",
26401 : exprtk_error_location));
26402 :
26403 0 : return error_node();
26404 : }
26405 :
26406 728 : return parse_base_operation();
26407 : }
26408 :
26409 2827 : void handle_brkcnt_scope_exit()
26410 : {
26411 2827 : assert(!brkcnt_list_.empty());
26412 2827 : brkcnt_list_.pop_front();
26413 2827 : }
26414 :
26415 22 : inline expression_node_ptr parse_while_loop()
26416 : {
26417 : // Parse: [while][(][test expr][)][{][expression][}]
26418 22 : expression_node_ptr condition = error_node();
26419 22 : expression_node_ptr branch = error_node();
26420 22 : expression_node_ptr result_node = error_node();
26421 :
26422 22 : bool result = true;
26423 :
26424 22 : next_token();
26425 :
26426 22 : if (!token_is(token_t::e_lbracket))
26427 : {
26428 0 : set_error(make_error(
26429 : parser_error::e_syntax,
26430 0 : current_token(),
26431 : "ERR062 - Expected '(' at start of while-loop condition statement",
26432 : exprtk_error_location));
26433 :
26434 0 : return error_node();
26435 : }
26436 22 : else if (0 == (condition = parse_expression()))
26437 : {
26438 0 : set_error(make_error(
26439 : parser_error::e_syntax,
26440 0 : current_token(),
26441 : "ERR063 - Failed to parse condition for while-loop",
26442 : exprtk_error_location));
26443 :
26444 0 : return error_node();
26445 : }
26446 22 : else if (!token_is(token_t::e_rbracket))
26447 : {
26448 0 : set_error(make_error(
26449 : parser_error::e_syntax,
26450 0 : current_token(),
26451 : "ERR064 - Expected ')' at end of while-loop condition statement",
26452 : exprtk_error_location));
26453 :
26454 0 : result = false;
26455 : }
26456 :
26457 22 : brkcnt_list_.push_front(false);
26458 :
26459 22 : if (result)
26460 : {
26461 22 : scoped_inc_dec sid(state_.parsing_loop_stmt_count);
26462 :
26463 44 : if (0 == (branch = parse_multi_sequence("while-loop", true)))
26464 : {
26465 0 : set_error(make_error(
26466 : parser_error::e_syntax,
26467 0 : current_token(),
26468 : "ERR065 - Failed to parse body of while-loop"));
26469 0 : result = false;
26470 : }
26471 22 : else if (0 == (result_node = expression_generator_.while_loop(condition,
26472 : branch,
26473 22 : brkcnt_list_.front())))
26474 : {
26475 0 : set_error(make_error(
26476 : parser_error::e_syntax,
26477 0 : current_token(),
26478 : "ERR066 - Failed to synthesize while-loop",
26479 : exprtk_error_location));
26480 :
26481 0 : result = false;
26482 : }
26483 22 : }
26484 :
26485 22 : handle_brkcnt_scope_exit();
26486 :
26487 22 : if (!result)
26488 : {
26489 0 : free_node(node_allocator_, branch );
26490 0 : free_node(node_allocator_, condition );
26491 0 : free_node(node_allocator_, result_node);
26492 :
26493 0 : return error_node();
26494 : }
26495 :
26496 22 : if (result_node && result_node->valid())
26497 : {
26498 22 : return result_node;
26499 : }
26500 :
26501 0 : set_error(make_error(
26502 : parser_error::e_synthesis,
26503 0 : current_token(),
26504 : "ERR067 - Failed to synthesize 'valid' while-loop",
26505 : exprtk_error_location));
26506 :
26507 0 : free_node(node_allocator_, result_node);
26508 :
26509 0 : return error_node();
26510 : }
26511 :
26512 92 : inline expression_node_ptr parse_repeat_until_loop()
26513 : {
26514 : // Parse: [repeat][{][expression][}][until][(][test expr][)]
26515 92 : expression_node_ptr condition = error_node();
26516 92 : expression_node_ptr branch = error_node();
26517 92 : next_token();
26518 :
26519 92 : std::vector<expression_node_ptr> arg_list;
26520 92 : std::vector<bool> side_effect_list;
26521 :
26522 92 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
26523 :
26524 92 : brkcnt_list_.push_front(false);
26525 :
26526 184 : if (details::imatch(current_token().value,"until"))
26527 : {
26528 0 : next_token();
26529 0 : branch = node_allocator_.allocate<details::null_node<T> >();
26530 : }
26531 : else
26532 : {
26533 92 : const token_t::token_type separator = token_t::e_eof;
26534 :
26535 92 : scope_handler sh(*this);
26536 :
26537 92 : scoped_bool_or_restorer sbr(state_.side_effect_present);
26538 :
26539 92 : scoped_inc_dec sid(state_.parsing_loop_stmt_count);
26540 :
26541 101 : for ( ; ; )
26542 : {
26543 193 : state_.side_effect_present = false;
26544 :
26545 193 : expression_node_ptr arg = parse_expression();
26546 :
26547 193 : if (0 == arg)
26548 10 : return error_node();
26549 : else
26550 : {
26551 183 : arg_list.push_back(arg);
26552 183 : side_effect_list.push_back(state_.side_effect_present);
26553 : }
26554 :
26555 366 : if (details::imatch(current_token().value,"until"))
26556 : {
26557 42 : next_token();
26558 42 : break;
26559 : }
26560 :
26561 196 : const bool is_next_until = peek_token_is(token_t::e_symbol) &&
26562 251 : peek_token_is("until");
26563 :
26564 141 : if (!token_is(separator) && is_next_until)
26565 : {
26566 0 : set_error(make_error(
26567 : parser_error::e_syntax,
26568 0 : current_token(),
26569 : "ERR068 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop",
26570 : exprtk_error_location));
26571 :
26572 0 : return error_node();
26573 : }
26574 :
26575 282 : if (details::imatch(current_token().value,"until"))
26576 : {
26577 40 : next_token();
26578 40 : break;
26579 : }
26580 : }
26581 :
26582 82 : branch = simplify(arg_list,side_effect_list);
26583 :
26584 82 : sdd.delete_ptr = (0 == branch);
26585 :
26586 82 : if (sdd.delete_ptr)
26587 : {
26588 0 : set_error(make_error(
26589 : parser_error::e_syntax,
26590 0 : current_token(),
26591 : "ERR069 - Failed to parse body of repeat until loop",
26592 : exprtk_error_location));
26593 :
26594 0 : return error_node();
26595 : }
26596 112 : }
26597 :
26598 82 : if (!token_is(token_t::e_lbracket))
26599 : {
26600 0 : set_error(make_error(
26601 : parser_error::e_syntax,
26602 0 : current_token(),
26603 : "ERR070 - Expected '(' before condition statement of repeat until loop",
26604 : exprtk_error_location));
26605 :
26606 0 : free_node(node_allocator_,branch);
26607 0 : return error_node();
26608 : }
26609 82 : else if (0 == (condition = parse_expression()))
26610 : {
26611 0 : set_error(make_error(
26612 : parser_error::e_syntax,
26613 0 : current_token(),
26614 : "ERR071 - Failed to parse condition for repeat until loop",
26615 : exprtk_error_location));
26616 :
26617 0 : free_node(node_allocator_,branch);
26618 0 : return error_node();
26619 : }
26620 82 : else if (!token_is(token_t::e_rbracket))
26621 : {
26622 0 : set_error(make_error(
26623 : parser_error::e_syntax,
26624 0 : current_token(),
26625 : "ERR072 - Expected ')' after condition of repeat until loop",
26626 : exprtk_error_location));
26627 :
26628 0 : free_node(node_allocator_, branch );
26629 0 : free_node(node_allocator_, condition);
26630 :
26631 0 : return error_node();
26632 : }
26633 :
26634 82 : expression_node_ptr result_node =
26635 : expression_generator_
26636 82 : .repeat_until_loop(
26637 : condition,
26638 : branch,
26639 82 : brkcnt_list_.front());
26640 :
26641 82 : if (0 == result_node)
26642 : {
26643 0 : set_error(make_error(
26644 : parser_error::e_syntax,
26645 0 : current_token(),
26646 : "ERR073 - Failed to synthesize repeat until loop",
26647 : exprtk_error_location));
26648 :
26649 0 : free_node(node_allocator_,condition);
26650 :
26651 0 : return error_node();
26652 : }
26653 :
26654 82 : handle_brkcnt_scope_exit();
26655 :
26656 82 : if (result_node && result_node->valid())
26657 : {
26658 82 : return result_node;
26659 : }
26660 :
26661 0 : set_error(make_error(
26662 : parser_error::e_synthesis,
26663 0 : current_token(),
26664 : "ERR074 - Failed to synthesize 'valid' repeat until loop",
26665 : exprtk_error_location));
26666 :
26667 0 : free_node(node_allocator_, result_node);
26668 :
26669 0 : return error_node();
26670 92 : }
26671 :
26672 2735 : inline expression_node_ptr parse_for_loop()
26673 : {
26674 2735 : expression_node_ptr initialiser = error_node();
26675 2735 : expression_node_ptr condition = error_node();
26676 2735 : expression_node_ptr incrementor = error_node();
26677 2735 : expression_node_ptr loop_body = error_node();
26678 :
26679 2735 : scope_element* se = 0;
26680 2735 : bool result = true;
26681 :
26682 2735 : next_token();
26683 :
26684 2735 : scope_handler sh(*this);
26685 :
26686 2735 : if (!token_is(token_t::e_lbracket))
26687 : {
26688 0 : set_error(make_error(
26689 : parser_error::e_syntax,
26690 0 : current_token(),
26691 : "ERR075 - Expected '(' at start of for-loop",
26692 : exprtk_error_location));
26693 :
26694 0 : return error_node();
26695 : }
26696 :
26697 2735 : if (!token_is(token_t::e_eof))
26698 : {
26699 2735 : if (
26700 2745 : !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
26701 2755 : details::imatch(current_token().value,"var")
26702 : )
26703 : {
26704 0 : next_token();
26705 :
26706 0 : if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
26707 : {
26708 0 : set_error(make_error(
26709 : parser_error::e_syntax,
26710 0 : current_token(),
26711 : "ERR076 - Expected a variable at the start of initialiser section of for-loop",
26712 : exprtk_error_location));
26713 :
26714 0 : return error_node();
26715 : }
26716 0 : else if (!peek_token_is(token_t::e_assign))
26717 : {
26718 0 : set_error(make_error(
26719 : parser_error::e_syntax,
26720 0 : current_token(),
26721 : "ERR077 - Expected variable assignment of initialiser section of for-loop",
26722 : exprtk_error_location));
26723 :
26724 0 : return error_node();
26725 : }
26726 :
26727 0 : const std::string loop_counter_symbol = current_token().value;
26728 :
26729 0 : se = &sem_.get_element(loop_counter_symbol);
26730 :
26731 0 : if ((se->name == loop_counter_symbol) && se->active)
26732 : {
26733 0 : set_error(make_error(
26734 : parser_error::e_syntax,
26735 0 : current_token(),
26736 : "ERR078 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
26737 : exprtk_error_location));
26738 :
26739 0 : return error_node();
26740 : }
26741 0 : else if (!symtab_store_.is_variable(loop_counter_symbol))
26742 : {
26743 0 : if (
26744 0 : !se->active &&
26745 0 : (se->name == loop_counter_symbol) &&
26746 0 : (se->type == scope_element::e_variable)
26747 : )
26748 : {
26749 0 : se->active = true;
26750 0 : se->ref_count++;
26751 : }
26752 : else
26753 : {
26754 0 : scope_element nse;
26755 0 : nse.name = loop_counter_symbol;
26756 0 : nse.active = true;
26757 0 : nse.ref_count = 1;
26758 0 : nse.type = scope_element::e_variable;
26759 0 : nse.depth = state_.scope_depth;
26760 0 : nse.data = new T(T(0));
26761 0 : nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
26762 :
26763 0 : if (!sem_.add_element(nse))
26764 : {
26765 0 : set_error(make_error(
26766 : parser_error::e_syntax,
26767 0 : current_token(),
26768 : "ERR079 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
26769 : exprtk_error_location));
26770 :
26771 0 : sem_.free_element(nse);
26772 :
26773 0 : result = false;
26774 : }
26775 : else
26776 : {
26777 : exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str()));
26778 :
26779 0 : state_.activate_side_effect("parse_for_loop()");
26780 : }
26781 0 : }
26782 : }
26783 0 : }
26784 :
26785 2735 : if (0 == (initialiser = parse_expression()))
26786 : {
26787 40 : set_error(make_error(
26788 : parser_error::e_syntax,
26789 10 : current_token(),
26790 : "ERR080 - Failed to parse initialiser of for-loop",
26791 : exprtk_error_location));
26792 :
26793 10 : result = false;
26794 : }
26795 2725 : else if (!token_is(token_t::e_eof))
26796 : {
26797 0 : set_error(make_error(
26798 : parser_error::e_syntax,
26799 0 : current_token(),
26800 : "ERR081 - Expected ';' after initialiser of for-loop",
26801 : exprtk_error_location));
26802 :
26803 0 : result = false;
26804 : }
26805 : }
26806 :
26807 2735 : if (!token_is(token_t::e_eof))
26808 : {
26809 2735 : if (0 == (condition = parse_expression()))
26810 : {
26811 48 : set_error(make_error(
26812 : parser_error::e_syntax,
26813 12 : current_token(),
26814 : "ERR082 - Failed to parse condition of for-loop",
26815 : exprtk_error_location));
26816 :
26817 12 : result = false;
26818 : }
26819 2723 : else if (!token_is(token_t::e_eof))
26820 : {
26821 0 : set_error(make_error(
26822 : parser_error::e_syntax,
26823 0 : current_token(),
26824 : "ERR083 - Expected ';' after condition section of for-loop",
26825 : exprtk_error_location));
26826 :
26827 0 : result = false;
26828 : }
26829 : }
26830 :
26831 2735 : if (!token_is(token_t::e_rbracket))
26832 : {
26833 2605 : if (0 == (incrementor = parse_expression()))
26834 : {
26835 8 : set_error(make_error(
26836 : parser_error::e_syntax,
26837 2 : current_token(),
26838 : "ERR084 - Failed to parse incrementor of for-loop",
26839 : exprtk_error_location));
26840 :
26841 2 : result = false;
26842 : }
26843 2603 : else if (!token_is(token_t::e_rbracket))
26844 : {
26845 0 : set_error(make_error(
26846 : parser_error::e_syntax,
26847 0 : current_token(),
26848 : "ERR085 - Expected ')' after incrementor section of for-loop",
26849 : exprtk_error_location));
26850 :
26851 0 : result = false;
26852 : }
26853 : }
26854 :
26855 2735 : if (result)
26856 : {
26857 2723 : brkcnt_list_.push_front(false);
26858 :
26859 2723 : scoped_inc_dec sid(state_.parsing_loop_stmt_count);
26860 :
26861 5446 : if (0 == (loop_body = parse_multi_sequence("for-loop", true)))
26862 : {
26863 0 : set_error(make_error(
26864 : parser_error::e_syntax,
26865 0 : current_token(),
26866 : "ERR086 - Failed to parse body of for-loop",
26867 : exprtk_error_location));
26868 :
26869 0 : result = false;
26870 : }
26871 2723 : }
26872 :
26873 2735 : if (!result)
26874 : {
26875 12 : if (se)
26876 : {
26877 0 : se->ref_count--;
26878 : }
26879 :
26880 12 : free_node(node_allocator_, initialiser);
26881 12 : free_node(node_allocator_, condition );
26882 12 : free_node(node_allocator_, incrementor);
26883 12 : free_node(node_allocator_, loop_body );
26884 12 : return error_node();
26885 : }
26886 :
26887 2723 : expression_node_ptr result_node =
26888 2723 : expression_generator_.for_loop(initialiser,
26889 : condition,
26890 : incrementor,
26891 : loop_body,
26892 2723 : brkcnt_list_.front());
26893 2723 : handle_brkcnt_scope_exit();
26894 :
26895 2723 : if (result_node && result_node->valid())
26896 : {
26897 2723 : return result_node;
26898 : }
26899 :
26900 0 : set_error(make_error(
26901 : parser_error::e_synthesis,
26902 0 : current_token(),
26903 : "ERR087 - Failed to synthesize 'valid' for-loop",
26904 : exprtk_error_location));
26905 :
26906 0 : free_node(node_allocator_, result_node);
26907 :
26908 0 : return error_node();
26909 2735 : }
26910 :
26911 1195 : inline expression_node_ptr parse_switch_statement()
26912 : {
26913 1195 : std::vector<expression_node_ptr> arg_list;
26914 1195 : expression_node_ptr result = error_node();
26915 :
26916 2390 : if (!details::imatch(current_token().value,"switch"))
26917 : {
26918 0 : set_error(make_error(
26919 : parser_error::e_syntax,
26920 0 : current_token(),
26921 : "ERR088 - Expected keyword 'switch'",
26922 : exprtk_error_location));
26923 :
26924 0 : return error_node();
26925 : }
26926 :
26927 1195 : scoped_vec_delete<expression_node_t> svd((*this),arg_list);
26928 :
26929 1195 : next_token();
26930 :
26931 1195 : if (!token_is(token_t::e_lcrlbracket))
26932 : {
26933 0 : set_error(make_error(
26934 : parser_error::e_syntax,
26935 0 : current_token(),
26936 : "ERR089 - Expected '{' for call to switch statement",
26937 : exprtk_error_location));
26938 :
26939 0 : return error_node();
26940 : }
26941 :
26942 1195 : expression_node_ptr default_statement = error_node();
26943 :
26944 1195 : scoped_expression_delete defstmt_delete((*this), default_statement);
26945 :
26946 2730 : for ( ; ; )
26947 : {
26948 11775 : if (details::imatch("case",current_token().value))
26949 : {
26950 1535 : next_token();
26951 :
26952 1535 : expression_node_ptr condition = parse_expression();
26953 :
26954 1535 : if (0 == condition)
26955 0 : return error_node();
26956 1535 : else if (!token_is(token_t::e_colon))
26957 : {
26958 0 : set_error(make_error(
26959 : parser_error::e_syntax,
26960 0 : current_token(),
26961 : "ERR090 - Expected ':' for case of switch statement",
26962 : exprtk_error_location));
26963 :
26964 0 : free_node(node_allocator_, condition);
26965 :
26966 0 : return error_node();
26967 : }
26968 :
26969 1535 : expression_node_ptr consequent =
26970 1535 : (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
26971 1535 : parse_multi_sequence("switch-consequent") :
26972 1345 : parse_expression();
26973 :
26974 1535 : if (0 == consequent)
26975 : {
26976 0 : free_node(node_allocator_, condition);
26977 :
26978 0 : return error_node();
26979 : }
26980 1535 : else if (!token_is(token_t::e_eof))
26981 : {
26982 0 : set_error(make_error(
26983 : parser_error::e_syntax,
26984 0 : current_token(),
26985 : "ERR091 - Expected ';' at end of case for switch statement",
26986 : exprtk_error_location));
26987 :
26988 0 : free_node(node_allocator_, condition );
26989 0 : free_node(node_allocator_, consequent);
26990 :
26991 0 : return error_node();
26992 : }
26993 :
26994 : // Can we optimise away the case statement?
26995 1535 : if (is_constant_node(condition) && is_false(condition))
26996 : {
26997 80 : free_node(node_allocator_, condition );
26998 80 : free_node(node_allocator_, consequent);
26999 : }
27000 : else
27001 : {
27002 1455 : arg_list.push_back(condition );
27003 1455 : arg_list.push_back(consequent);
27004 : }
27005 :
27006 : }
27007 7170 : else if (details::imatch("default",current_token().value))
27008 : {
27009 1195 : if (0 != default_statement)
27010 : {
27011 0 : set_error(make_error(
27012 : parser_error::e_syntax,
27013 0 : current_token(),
27014 : "ERR092 - Multiple default cases for switch statement",
27015 : exprtk_error_location));
27016 :
27017 0 : return error_node();
27018 : }
27019 :
27020 1195 : next_token();
27021 :
27022 1195 : if (!token_is(token_t::e_colon))
27023 : {
27024 0 : set_error(make_error(
27025 : parser_error::e_syntax,
27026 0 : current_token(),
27027 : "ERR093 - Expected ':' for default of switch statement",
27028 : exprtk_error_location));
27029 :
27030 0 : return error_node();
27031 : }
27032 :
27033 1195 : default_statement =
27034 1195 : (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
27035 1195 : parse_multi_sequence("switch-default"):
27036 1194 : parse_expression();
27037 :
27038 1195 : if (0 == default_statement)
27039 0 : return error_node();
27040 1195 : else if (!token_is(token_t::e_eof))
27041 : {
27042 0 : set_error(make_error(
27043 : parser_error::e_syntax,
27044 0 : current_token(),
27045 : "ERR094 - Expected ';' at end of default for switch statement",
27046 : exprtk_error_location));
27047 :
27048 0 : return error_node();
27049 : }
27050 : }
27051 1195 : else if (token_is(token_t::e_rcrlbracket))
27052 1195 : break;
27053 : else
27054 : {
27055 0 : set_error(make_error(
27056 : parser_error::e_syntax,
27057 0 : current_token(),
27058 : "ERR095 - Expected '}' at end of switch statement",
27059 : exprtk_error_location));
27060 :
27061 0 : return error_node();
27062 : }
27063 : }
27064 :
27065 1195 : const bool default_statement_present = (0 != default_statement);
27066 :
27067 1195 : if (default_statement_present)
27068 : {
27069 1195 : arg_list.push_back(default_statement);
27070 : }
27071 : else
27072 : {
27073 0 : arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN()));
27074 : }
27075 :
27076 1195 : result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
27077 :
27078 1195 : svd.delete_ptr = (0 == result);
27079 1195 : defstmt_delete.delete_ptr = (0 == result);
27080 :
27081 1195 : return result;
27082 1195 : }
27083 :
27084 190 : inline expression_node_ptr parse_multi_switch_statement()
27085 : {
27086 190 : std::vector<expression_node_ptr> arg_list;
27087 :
27088 380 : if (!details::imatch(current_token().value,"[*]"))
27089 : {
27090 0 : set_error(make_error(
27091 : parser_error::e_syntax,
27092 0 : current_token(),
27093 : "ERR096 - Expected token '[*]'",
27094 : exprtk_error_location));
27095 :
27096 0 : return error_node();
27097 : }
27098 :
27099 190 : scoped_vec_delete<expression_node_t> svd((*this),arg_list);
27100 :
27101 190 : next_token();
27102 :
27103 190 : if (!token_is(token_t::e_lcrlbracket))
27104 : {
27105 0 : set_error(make_error(
27106 : parser_error::e_syntax,
27107 0 : current_token(),
27108 : "ERR097 - Expected '{' for call to [*] statement",
27109 : exprtk_error_location));
27110 :
27111 0 : return error_node();
27112 : }
27113 :
27114 210 : for ( ; ; )
27115 : {
27116 1200 : if (!details::imatch("case",current_token().value))
27117 : {
27118 0 : set_error(make_error(
27119 : parser_error::e_syntax,
27120 0 : current_token(),
27121 : "ERR098 - Expected a 'case' statement for multi-switch",
27122 : exprtk_error_location));
27123 :
27124 0 : return error_node();
27125 : }
27126 :
27127 400 : next_token();
27128 :
27129 400 : expression_node_ptr condition = parse_expression();
27130 :
27131 400 : if (0 == condition)
27132 0 : return error_node();
27133 :
27134 400 : if (!token_is(token_t::e_colon))
27135 : {
27136 0 : set_error(make_error(
27137 : parser_error::e_syntax,
27138 0 : current_token(),
27139 : "ERR099 - Expected ':' for case of [*] statement",
27140 : exprtk_error_location));
27141 :
27142 0 : return error_node();
27143 : }
27144 :
27145 400 : expression_node_ptr consequent =
27146 400 : (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ?
27147 400 : parse_multi_sequence("multi-switch-consequent") :
27148 400 : parse_expression();
27149 :
27150 400 : if (0 == consequent)
27151 0 : return error_node();
27152 :
27153 400 : if (!token_is(token_t::e_eof))
27154 : {
27155 0 : set_error(make_error(
27156 : parser_error::e_syntax,
27157 0 : current_token(),
27158 : "ERR100 - Expected ';' at end of case for [*] statement",
27159 : exprtk_error_location));
27160 :
27161 0 : return error_node();
27162 : }
27163 :
27164 : // Can we optimise away the case statement?
27165 400 : if (is_constant_node(condition) && is_false(condition))
27166 : {
27167 0 : free_node(node_allocator_, condition );
27168 0 : free_node(node_allocator_, consequent);
27169 : }
27170 : else
27171 : {
27172 400 : arg_list.push_back(condition );
27173 400 : arg_list.push_back(consequent);
27174 : }
27175 :
27176 400 : if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
27177 : {
27178 190 : break;
27179 : }
27180 : }
27181 :
27182 190 : if (!token_is(token_t::e_rcrlbracket))
27183 : {
27184 0 : set_error(make_error(
27185 : parser_error::e_syntax,
27186 0 : current_token(),
27187 : "ERR101 - Expected '}' at end of [*] statement",
27188 : exprtk_error_location));
27189 :
27190 0 : return error_node();
27191 : }
27192 :
27193 190 : const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
27194 :
27195 190 : svd.delete_ptr = (0 == result);
27196 :
27197 190 : return result;
27198 190 : }
27199 :
27200 22327 : inline expression_node_ptr parse_vararg_function()
27201 : {
27202 22327 : std::vector<expression_node_ptr> arg_list;
27203 :
27204 22327 : details::operator_type opt_type = details::e_default;
27205 22327 : const std::string symbol = current_token().value;
27206 :
27207 44654 : if (details::imatch(symbol,"~"))
27208 : {
27209 14067 : next_token();
27210 28134 : return parse_multi_sequence();
27211 : }
27212 16520 : else if (details::imatch(symbol,"[*]"))
27213 : {
27214 190 : return parse_multi_switch_statement();
27215 : }
27216 16140 : else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
27217 15464 : else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
27218 14952 : else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
27219 14194 : else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
27220 5370 : else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
27221 4856 : else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
27222 4408 : else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
27223 : else
27224 : {
27225 0 : set_error(make_error(
27226 : parser_error::e_syntax,
27227 0 : current_token(),
27228 : "ERR102 - Unsupported built-in vararg function: " + symbol,
27229 : exprtk_error_location));
27230 :
27231 0 : return error_node();
27232 : }
27233 :
27234 8070 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
27235 :
27236 8070 : lodge_symbol(symbol, e_st_function);
27237 :
27238 8070 : next_token();
27239 :
27240 8070 : if (!token_is(token_t::e_lbracket))
27241 : {
27242 0 : set_error(make_error(
27243 : parser_error::e_syntax,
27244 0 : current_token(),
27245 : "ERR103 - Expected '(' for call to vararg function: " + symbol,
27246 : exprtk_error_location));
27247 :
27248 0 : return error_node();
27249 : }
27250 :
27251 8070 : if (token_is(token_t::e_rbracket))
27252 : {
27253 0 : set_error(make_error(
27254 : parser_error::e_syntax,
27255 0 : current_token(),
27256 : "ERR104 - vararg function: " + symbol +
27257 : " requires at least one input parameter",
27258 : exprtk_error_location));
27259 :
27260 0 : return error_node();
27261 : }
27262 :
27263 8024 : for ( ; ; )
27264 : {
27265 16094 : expression_node_ptr arg = parse_expression();
27266 :
27267 16094 : if (0 == arg)
27268 2 : return error_node();
27269 : else
27270 16092 : arg_list.push_back(arg);
27271 :
27272 16092 : if (token_is(token_t::e_rbracket))
27273 8068 : break;
27274 8024 : else if (!token_is(token_t::e_comma))
27275 : {
27276 0 : set_error(make_error(
27277 : parser_error::e_syntax,
27278 0 : current_token(),
27279 : "ERR105 - Expected ',' for call to vararg function: " + symbol,
27280 : exprtk_error_location));
27281 :
27282 0 : return error_node();
27283 : }
27284 : }
27285 :
27286 8068 : const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
27287 :
27288 8068 : sdd.delete_ptr = (0 == result);
27289 8068 : return result;
27290 22327 : }
27291 :
27292 : #ifndef exprtk_disable_string_capabilities
27293 4852 : inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
27294 : {
27295 4852 : if (!token_is(token_t::e_lsqrbracket))
27296 : {
27297 0 : set_error(make_error(
27298 : parser_error::e_syntax,
27299 0 : current_token(),
27300 : "ERR106 - Expected '[' as start of string range definition",
27301 : exprtk_error_location));
27302 :
27303 0 : free_node(node_allocator_,expression);
27304 :
27305 0 : return error_node();
27306 : }
27307 4852 : else if (token_is(token_t::e_rsqrbracket))
27308 : {
27309 750 : return node_allocator_.allocate<details::string_size_node<T> >(expression);
27310 : }
27311 :
27312 4102 : range_t rp;
27313 :
27314 4102 : if (!parse_range(rp,true))
27315 : {
27316 0 : free_node(node_allocator_,expression);
27317 :
27318 0 : return error_node();
27319 : }
27320 :
27321 4102 : expression_node_ptr result = expression_generator_(expression,rp);
27322 :
27323 4102 : if (0 == result)
27324 : {
27325 0 : set_error(make_error(
27326 : parser_error::e_syntax,
27327 0 : current_token(),
27328 : "ERR107 - Failed to generate string range node",
27329 : exprtk_error_location));
27330 :
27331 0 : free_node(node_allocator_,expression);
27332 0 : rp.free();
27333 : }
27334 :
27335 4102 : rp.clear();
27336 :
27337 4102 : if (result && result->valid())
27338 : {
27339 4102 : return result;
27340 : }
27341 :
27342 0 : set_error(make_error(
27343 : parser_error::e_synthesis,
27344 0 : current_token(),
27345 : "ERR108 - Failed to synthesize node: string_range_node",
27346 : exprtk_error_location));
27347 :
27348 0 : free_node(node_allocator_, result);
27349 0 : rp.free();
27350 0 : return error_node();
27351 : }
27352 : #else
27353 : inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
27354 : {
27355 : return error_node();
27356 : }
27357 : #endif
27358 :
27359 13784857 : inline bool parse_pending_string_rangesize(expression_node_ptr& expression)
27360 : {
27361 : // Allow no more than 100 range calls, eg: s[][][]...[][]
27362 13784857 : const std::size_t max_rangesize_parses = 100;
27363 :
27364 13784857 : std::size_t i = 0;
27365 :
27366 13784857 : while
27367 : (
27368 27546610 : (0 != expression) &&
27369 27513802 : (i++ < max_rangesize_parses) &&
27370 13756901 : error_list_.empty() &&
27371 27805115 : is_generally_string_node(expression) &&
27372 14048214 : token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
27373 : )
27374 : {
27375 4852 : expression = parse_string_range_statement(expression);
27376 : }
27377 :
27378 13784857 : return (i > 1);
27379 : }
27380 :
27381 1715579 : inline void parse_pending_vector_index_operator(expression_node_ptr& expression)
27382 : {
27383 1715579 : if
27384 : (
27385 1715579 : (0 != expression) &&
27386 3431158 : error_list_.empty() &&
27387 1715579 : is_ivector_node(expression)
27388 : )
27389 : {
27390 6581 : if (
27391 6581 : settings_.commutative_check_enabled() &&
27392 7481 : token_is(token_t::e_mul,prsrhlpr_t::e_hold) &&
27393 7481 : peek_token_is(token_t::e_lsqrbracket)
27394 : )
27395 : {
27396 660 : token_is(token_t::e_mul);
27397 660 : token_is(token_t::e_lsqrbracket);
27398 : }
27399 5921 : else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
27400 : {
27401 0 : token_is(token_t::e_lsqrbracket);
27402 : }
27403 5921 : else if (
27404 6210 : token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) &&
27405 6210 : peek_token_is(token_t::e_lsqrbracket)
27406 : )
27407 : {
27408 0 : token_is(token_t::e_rbracket );
27409 0 : token_is(token_t::e_lsqrbracket);
27410 : }
27411 : else
27412 5921 : return;
27413 :
27414 660 : details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression);
27415 :
27416 660 : if (vi)
27417 : {
27418 660 : details::vector_holder<T>& vec = vi->vec()->vec_holder();
27419 660 : const std::string vector_name = sem_.get_vector_name(vec.data());
27420 660 : expression_node_ptr index = parse_vector_index(vector_name);
27421 :
27422 660 : if (index)
27423 : {
27424 660 : expression = synthesize_vector_element(vector_name, &vec, expression, index);
27425 660 : return;
27426 : }
27427 660 : }
27428 :
27429 0 : free_node(node_allocator_,expression);
27430 0 : expression = error_node();
27431 : }
27432 : }
27433 :
27434 : template <typename Allocator1,
27435 : typename Allocator2,
27436 : template <typename, typename> class Sequence>
27437 380093 : inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
27438 : Sequence<bool,Allocator2>& side_effect_list,
27439 : const bool specialise_on_final_type = false)
27440 : {
27441 380093 : if (expression_list.empty())
27442 0 : return error_node();
27443 380093 : else if (1 == expression_list.size())
27444 336105 : return expression_list[0];
27445 :
27446 43988 : Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
27447 :
27448 43988 : bool return_node_present = false;
27449 :
27450 142960 : for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
27451 : {
27452 99309 : if (is_variable_node(expression_list[i]))
27453 0 : continue;
27454 99309 : else if (
27455 99309 : is_return_node (expression_list[i]) ||
27456 198281 : is_break_node (expression_list[i]) ||
27457 98972 : is_continue_node(expression_list[i])
27458 : )
27459 : {
27460 337 : tmp_expression_list.push_back(expression_list[i]);
27461 :
27462 : // Remove all subexpressions after first short-circuit
27463 : // node has been encountered.
27464 :
27465 1264 : for (std::size_t j = i + 1; j < expression_list.size(); ++j)
27466 : {
27467 927 : free_node(node_allocator_,expression_list[j]);
27468 : }
27469 :
27470 337 : return_node_present = true;
27471 :
27472 337 : break;
27473 : }
27474 109922 : else if (
27475 98972 : is_constant_node(expression_list[i]) ||
27476 192549 : is_null_node (expression_list[i]) ||
27477 192549 : !side_effect_list[i]
27478 : )
27479 : {
27480 10950 : free_node(node_allocator_,expression_list[i]);
27481 10950 : continue;
27482 : }
27483 : else
27484 88022 : tmp_expression_list.push_back(expression_list[i]);
27485 : }
27486 :
27487 43988 : if (!return_node_present)
27488 : {
27489 43651 : tmp_expression_list.push_back(expression_list.back());
27490 : }
27491 :
27492 43988 : expression_list.swap(tmp_expression_list);
27493 :
27494 43988 : if (tmp_expression_list.size() > expression_list.size())
27495 : {
27496 : exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
27497 : static_cast<int>(tmp_expression_list.size()),
27498 : static_cast<int>(expression_list .size())));
27499 : }
27500 :
27501 43988 : if (
27502 43651 : return_node_present ||
27503 87639 : side_effect_list.back() ||
27504 36435 : (expression_list.size() > 1)
27505 : )
27506 127497 : state_.activate_side_effect("simplify()");
27507 :
27508 43988 : if (1 == expression_list.size())
27509 2440 : return expression_list[0];
27510 41548 : else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
27511 85 : return expression_generator_.vararg_function(details::e_smulti,expression_list);
27512 : else
27513 41463 : return expression_generator_.vararg_function(details::e_multi,expression_list);
27514 43988 : }
27515 :
27516 20852 : inline expression_node_ptr parse_multi_sequence(const std::string& source = "",
27517 : const bool enforce_crlbrackets = false)
27518 : {
27519 20852 : token_t::token_type open_bracket = token_t::e_lcrlbracket;
27520 20852 : token_t::token_type close_bracket = token_t::e_rcrlbracket;
27521 20852 : token_t::token_type separator = token_t::e_eof;
27522 :
27523 20852 : if (!token_is(open_bracket))
27524 : {
27525 322 : if (!enforce_crlbrackets && token_is(token_t::e_lbracket))
27526 : {
27527 322 : open_bracket = token_t::e_lbracket;
27528 322 : close_bracket = token_t::e_rbracket;
27529 322 : separator = token_t::e_comma;
27530 : }
27531 : else
27532 : {
27533 0 : set_error(make_error(
27534 : parser_error::e_syntax,
27535 0 : current_token(),
27536 : "ERR109 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" +
27537 0 : ((!source.empty()) ? std::string(" section of " + source): ""),
27538 : exprtk_error_location));
27539 :
27540 0 : return error_node();
27541 : }
27542 : }
27543 20530 : else if (token_is(close_bracket))
27544 : {
27545 0 : return node_allocator_.allocate<details::null_node<T> >();
27546 : }
27547 :
27548 20852 : std::vector<expression_node_ptr> arg_list;
27549 20852 : std::vector<bool> side_effect_list;
27550 :
27551 20852 : expression_node_ptr result = error_node();
27552 :
27553 20852 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
27554 :
27555 20852 : scope_handler sh(*this);
27556 :
27557 20852 : scoped_bool_or_restorer sbr(state_.side_effect_present);
27558 :
27559 24257 : for ( ; ; )
27560 : {
27561 45109 : state_.side_effect_present = false;
27562 :
27563 45109 : expression_node_ptr arg = parse_expression();
27564 :
27565 45109 : if (0 == arg)
27566 0 : return error_node();
27567 : else
27568 : {
27569 45109 : arg_list.push_back(arg);
27570 45109 : side_effect_list.push_back(state_.side_effect_present);
27571 : }
27572 :
27573 45109 : if (token_is(close_bracket))
27574 17054 : break;
27575 :
27576 28055 : const bool is_next_close = peek_token_is(close_bracket);
27577 :
27578 28055 : if (!token_is(separator) && is_next_close)
27579 : {
27580 0 : set_error(make_error(
27581 : parser_error::e_syntax,
27582 0 : current_token(),
27583 : "ERR110 - Expected '" + details::to_str(separator) + "' for call to multi-sequence section of " + source,
27584 : exprtk_error_location));
27585 :
27586 0 : return error_node();
27587 : }
27588 :
27589 28055 : if (token_is(close_bracket))
27590 3798 : break;
27591 : }
27592 :
27593 20852 : result = simplify(arg_list, side_effect_list, source.empty());
27594 :
27595 20852 : sdd.delete_ptr = (0 == result);
27596 20852 : return result;
27597 20852 : }
27598 :
27599 32056 : inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
27600 : {
27601 : // Examples of valid ranges:
27602 : // 1. [1:5] -> [1,5)
27603 : // 2. [ :5] -> [0,5)
27604 : // 3. [1: ] -> [1,end)
27605 : // 4. [x:y] -> [x,y) where x <= y
27606 : // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2
27607 : // 6. [ :y] -> [0,y) where 0 <= y
27608 : // 7. [x: ] -> [x,end) where x <= end
27609 :
27610 32056 : rp.clear();
27611 :
27612 32056 : if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
27613 : {
27614 0 : set_error(make_error(
27615 : parser_error::e_syntax,
27616 0 : current_token(),
27617 : "ERR111 - Expected '[' for start of range",
27618 : exprtk_error_location));
27619 :
27620 0 : return false;
27621 : }
27622 :
27623 32056 : if (token_is(token_t::e_colon))
27624 : {
27625 10180 : rp.n0_c.first = true;
27626 10180 : rp.n0_c.second = 0;
27627 10180 : rp.cache.first = 0;
27628 : }
27629 : else
27630 : {
27631 21876 : expression_node_ptr r0 = parse_expression();
27632 :
27633 21876 : if (0 == r0)
27634 : {
27635 0 : set_error(make_error(
27636 : parser_error::e_syntax,
27637 0 : current_token(),
27638 : "ERR112 - Failed parse begin section of range",
27639 : exprtk_error_location));
27640 :
27641 0 : return false;
27642 : }
27643 21876 : else if (is_constant_node(r0))
27644 : {
27645 16670 : const T r0_value = r0->value();
27646 :
27647 16670 : if (r0_value >= T(0))
27648 : {
27649 16670 : rp.n0_c.first = true;
27650 16670 : rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
27651 16670 : rp.cache.first = rp.n0_c.second;
27652 : }
27653 :
27654 16670 : free_node(node_allocator_,r0);
27655 :
27656 16670 : if (r0_value < T(0))
27657 : {
27658 0 : set_error(make_error(
27659 : parser_error::e_syntax,
27660 0 : current_token(),
27661 : "ERR113 - Range lower bound less than zero! Constraint: r0 >= 0",
27662 : exprtk_error_location));
27663 :
27664 0 : return false;
27665 : }
27666 : }
27667 : else
27668 : {
27669 5206 : rp.n0_e.first = true;
27670 5206 : rp.n0_e.second = r0;
27671 : }
27672 :
27673 21876 : if (!token_is(token_t::e_colon))
27674 : {
27675 0 : set_error(make_error(
27676 : parser_error::e_syntax,
27677 0 : current_token(),
27678 : "ERR114 - Expected ':' for break in range",
27679 : exprtk_error_location));
27680 :
27681 0 : rp.free();
27682 :
27683 0 : return false;
27684 : }
27685 : }
27686 :
27687 32056 : if (token_is(token_t::e_rsqrbracket))
27688 : {
27689 11415 : rp.n1_c.first = true;
27690 11415 : rp.n1_c.second = std::numeric_limits<std::size_t>::max();
27691 : }
27692 : else
27693 : {
27694 20641 : expression_node_ptr r1 = parse_expression();
27695 :
27696 20641 : if (0 == r1)
27697 : {
27698 0 : set_error(make_error(
27699 : parser_error::e_syntax,
27700 0 : current_token(),
27701 : "ERR115 - Failed parse end section of range",
27702 : exprtk_error_location));
27703 :
27704 0 : rp.free();
27705 :
27706 0 : return false;
27707 : }
27708 20641 : else if (is_constant_node(r1))
27709 : {
27710 13585 : const T r1_value = r1->value();
27711 :
27712 13585 : if (r1_value >= T(0))
27713 : {
27714 13585 : rp.n1_c.first = true;
27715 13585 : rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
27716 13585 : rp.cache.second = rp.n1_c.second;
27717 : }
27718 :
27719 13585 : free_node(node_allocator_,r1);
27720 :
27721 13585 : if (r1_value < T(0))
27722 : {
27723 0 : set_error(make_error(
27724 : parser_error::e_syntax,
27725 0 : current_token(),
27726 : "ERR116 - Range upper bound less than zero! Constraint: r1 >= 0",
27727 : exprtk_error_location));
27728 :
27729 0 : rp.free();
27730 :
27731 0 : return false;
27732 : }
27733 : }
27734 : else
27735 : {
27736 7056 : rp.n1_e.first = true;
27737 7056 : rp.n1_e.second = r1;
27738 : }
27739 :
27740 20641 : if (!token_is(token_t::e_rsqrbracket))
27741 : {
27742 0 : set_error(make_error(
27743 : parser_error::e_syntax,
27744 0 : current_token(),
27745 : "ERR117 - Expected ']' for start of range",
27746 : exprtk_error_location));
27747 :
27748 0 : rp.free();
27749 :
27750 0 : return false;
27751 : }
27752 : }
27753 :
27754 32056 : if (rp.const_range())
27755 : {
27756 21748 : std::size_t r0 = 0;
27757 21748 : std::size_t r1 = 0;
27758 :
27759 21748 : bool rp_result = false;
27760 :
27761 : try
27762 : {
27763 21748 : rp_result = rp(r0, r1);
27764 : }
27765 0 : catch (std::runtime_error&)
27766 : {}
27767 :
27768 21748 : if (!rp_result || (r0 > r1))
27769 : {
27770 0 : set_error(make_error(
27771 : parser_error::e_syntax,
27772 0 : current_token(),
27773 : "ERR118 - Invalid range, Constraint: r0 <= r1",
27774 : exprtk_error_location));
27775 :
27776 0 : return false;
27777 : }
27778 : }
27779 :
27780 32056 : return true;
27781 : }
27782 :
27783 2427545 : inline void lodge_symbol(const std::string& symbol,
27784 : const symbol_type st)
27785 : {
27786 2427545 : dec_.add_symbol(symbol,st);
27787 2427545 : }
27788 :
27789 : #ifndef exprtk_disable_string_capabilities
27790 68710 : inline expression_node_ptr parse_string()
27791 : {
27792 68710 : const std::string symbol = current_token().value;
27793 :
27794 : typedef details::stringvar_node<T>* strvar_node_t;
27795 :
27796 68710 : expression_node_ptr result = error_node();
27797 68710 : strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
27798 :
27799 68710 : scope_element& se = sem_.get_active_element(symbol);
27800 :
27801 68710 : if (scope_element::e_string == se.type)
27802 : {
27803 19235 : se.active = true;
27804 19235 : result = se.str_node;
27805 19235 : lodge_symbol(symbol, e_st_local_string);
27806 : }
27807 : else
27808 : {
27809 : typedef typename symtab_store::string_context str_ctxt_t;
27810 49475 : str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol);
27811 :
27812 49475 : if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol))
27813 : {
27814 0 : set_error(make_error(
27815 : parser_error::e_syntax,
27816 0 : current_token(),
27817 : "ERR119 - Unknown string symbol",
27818 : exprtk_error_location));
27819 :
27820 0 : return error_node();
27821 : }
27822 :
27823 49475 : assert(str_ctx.str_var != 0);
27824 49475 : assert(str_ctx.symbol_table != 0);
27825 :
27826 49475 : result = str_ctx.str_var;
27827 :
27828 49475 : if (symtab_store_.is_constant_string(symbol))
27829 : {
27830 0 : const_str_node = static_cast<strvar_node_t>(result);
27831 0 : result = expression_generator_(const_str_node->str());
27832 : }
27833 49475 : else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability())
27834 : {
27835 48 : lodge_immutable_symbol(
27836 24 : current_token(),
27837 24 : make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size()));
27838 : }
27839 :
27840 49475 : lodge_symbol(symbol, e_st_string);
27841 : }
27842 :
27843 68710 : if (peek_token_is(token_t::e_lsqrbracket))
27844 : {
27845 26201 : next_token();
27846 :
27847 26201 : if (peek_token_is(token_t::e_rsqrbracket))
27848 : {
27849 3800 : next_token();
27850 3800 : next_token();
27851 :
27852 3800 : if (const_str_node)
27853 : {
27854 0 : free_node(node_allocator_,result);
27855 :
27856 0 : return expression_generator_(T(const_str_node->size()));
27857 : }
27858 : else
27859 : return node_allocator_.allocate<details::stringvar_size_node<T> >
27860 3800 : (static_cast<details::stringvar_node<T>*>(result)->ref());
27861 : }
27862 :
27863 22401 : range_t rp;
27864 :
27865 22401 : if (!parse_range(rp))
27866 : {
27867 0 : free_node(node_allocator_,result);
27868 :
27869 0 : return error_node();
27870 : }
27871 22401 : else if (const_str_node)
27872 : {
27873 0 : free_node(node_allocator_,result);
27874 0 : result = expression_generator_(const_str_node->ref(),rp);
27875 : }
27876 : else
27877 22401 : result = expression_generator_(static_cast<details::stringvar_node<T>*>
27878 : (result)->ref(), rp);
27879 :
27880 22401 : if (result)
27881 22401 : rp.clear();
27882 : }
27883 : else
27884 42509 : next_token();
27885 :
27886 64910 : return result;
27887 68710 : }
27888 : #else
27889 : inline expression_node_ptr parse_string()
27890 : {
27891 : return error_node();
27892 : }
27893 : #endif
27894 :
27895 : #ifndef exprtk_disable_string_capabilities
27896 52875 : inline expression_node_ptr parse_const_string()
27897 : {
27898 52875 : const std::string const_str = current_token().value;
27899 52875 : expression_node_ptr result = expression_generator_(const_str);
27900 :
27901 52875 : if (peek_token_is(token_t::e_lsqrbracket))
27902 : {
27903 6203 : next_token();
27904 :
27905 6203 : if (peek_token_is(token_t::e_rsqrbracket))
27906 : {
27907 650 : next_token();
27908 650 : next_token();
27909 :
27910 650 : free_node(node_allocator_,result);
27911 :
27912 650 : return expression_generator_(T(const_str.size()));
27913 : }
27914 :
27915 5553 : range_t rp;
27916 :
27917 5553 : if (!parse_range(rp))
27918 : {
27919 0 : free_node(node_allocator_,result);
27920 0 : rp.free();
27921 :
27922 0 : return error_node();
27923 : }
27924 :
27925 5553 : free_node(node_allocator_,result);
27926 :
27927 5553 : if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
27928 : {
27929 1750 : rp.n1_c.second = const_str.size() - 1;
27930 1750 : rp.cache.second = rp.n1_c.second;
27931 : }
27932 :
27933 5553 : if (
27934 11106 : (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
27935 5553 : (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
27936 : )
27937 : {
27938 0 : set_error(make_error(
27939 : parser_error::e_syntax,
27940 0 : current_token(),
27941 : "ERR120 - Overflow in range for string: '" + const_str + "'[" +
27942 0 : (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
27943 0 : (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
27944 : exprtk_error_location));
27945 :
27946 0 : rp.free();
27947 :
27948 0 : return error_node();
27949 : }
27950 :
27951 5553 : result = expression_generator_(const_str,rp);
27952 :
27953 5553 : if (result)
27954 5553 : rp.clear();
27955 : }
27956 : else
27957 46672 : next_token();
27958 :
27959 52225 : return result;
27960 52875 : }
27961 : #else
27962 : inline expression_node_ptr parse_const_string()
27963 : {
27964 : return error_node();
27965 : }
27966 : #endif
27967 :
27968 19542 : inline expression_node_ptr parse_vector_index(const std::string& vector_name = "")
27969 : {
27970 19542 : expression_node_ptr index_expr = error_node();
27971 :
27972 19542 : if (0 == (index_expr = parse_expression()))
27973 : {
27974 0 : set_error(make_error(
27975 : parser_error::e_syntax,
27976 0 : current_token(),
27977 : "ERR121 - Failed to parse index for vector: '" + vector_name + "'",
27978 : exprtk_error_location));
27979 :
27980 0 : return error_node();
27981 : }
27982 19542 : else if (!token_is(token_t::e_rsqrbracket))
27983 : {
27984 0 : set_error(make_error(
27985 : parser_error::e_syntax,
27986 0 : current_token(),
27987 : "ERR122 - Expected ']' for index of vector: '" + vector_name + "'",
27988 : exprtk_error_location));
27989 :
27990 0 : free_node(node_allocator_,index_expr);
27991 :
27992 0 : return error_node();
27993 : }
27994 :
27995 19542 : return index_expr;
27996 : }
27997 :
27998 52977 : inline expression_node_ptr parse_vector()
27999 : {
28000 52977 : const std::string vector_name = current_token().value;
28001 :
28002 52977 : vector_holder_ptr vec = vector_holder_ptr(0);
28003 :
28004 52977 : const scope_element& se = sem_.get_active_element(vector_name);
28005 :
28006 52977 : if (
28007 52977 : !details::imatch(se.name, vector_name) ||
28008 99085 : (se.depth > state_.scope_depth) ||
28009 46108 : (scope_element::e_vector != se.type)
28010 : )
28011 : {
28012 : typedef typename symtab_store::vector_context vec_ctxt_t;
28013 6869 : vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name);
28014 :
28015 6869 : if (0 == vec_ctx.vector_holder)
28016 : {
28017 0 : set_error(make_error(
28018 : parser_error::e_syntax,
28019 0 : current_token(),
28020 : "ERR123 - Symbol '" + vector_name + " not a vector",
28021 : exprtk_error_location));
28022 :
28023 0 : return error_node();
28024 : }
28025 :
28026 6869 : assert(0 != vec_ctx.vector_holder);
28027 6869 : assert(0 != vec_ctx.symbol_table );
28028 :
28029 6869 : vec = vec_ctx.vector_holder;
28030 :
28031 6869 : if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability())
28032 : {
28033 26 : lodge_immutable_symbol(
28034 13 : current_token(),
28035 13 : make_memory_range(vec->data(), vec->size()));
28036 : }
28037 : }
28038 : else
28039 : {
28040 46108 : vec = se.vec_node;
28041 : }
28042 :
28043 52977 : assert(0 != vec);
28044 :
28045 52977 : next_token();
28046 :
28047 52977 : if (!token_is(token_t::e_lsqrbracket))
28048 : {
28049 30740 : return node_allocator_.allocate<vector_node_t>(vec);
28050 : }
28051 22237 : else if (token_is(token_t::e_rsqrbracket))
28052 : {
28053 3355 : return (vec->rebaseable()) ?
28054 188 : node_allocator_.allocate<vector_size_node_t>(vec) :
28055 3355 : expression_generator_(T(vec->size()));
28056 : }
28057 :
28058 18882 : expression_node_ptr index_expr = parse_vector_index(vector_name);
28059 :
28060 18882 : if (index_expr)
28061 : {
28062 18882 : expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec);
28063 :
28064 18882 : return synthesize_vector_element(vector_name, vec, vec_node, index_expr);
28065 : }
28066 :
28067 0 : return error_node();
28068 52977 : }
28069 :
28070 19542 : inline expression_node_ptr synthesize_vector_element(const std::string& vector_name,
28071 : vector_holder_ptr vec,
28072 : expression_node_ptr vec_node,
28073 : expression_node_ptr index_expr)
28074 : {
28075 : // Perform compile-time range check
28076 19542 : if (details::is_constant_node(index_expr))
28077 : {
28078 14723 : const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
28079 14723 : const std::size_t vec_size = vec->size();
28080 :
28081 14723 : if (index >= vec_size)
28082 : {
28083 0 : set_error(make_error(
28084 : parser_error::e_syntax,
28085 0 : current_token(),
28086 : "ERR124 - Index of " + details::to_str(index) + " out of range for "
28087 : "vector '" + vector_name + "' of size " + details::to_str(vec_size),
28088 : exprtk_error_location));
28089 :
28090 0 : free_node(node_allocator_, vec_node );
28091 0 : free_node(node_allocator_, index_expr);
28092 :
28093 0 : return error_node();
28094 : }
28095 : }
28096 :
28097 19542 : return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr);
28098 : }
28099 :
28100 49 : inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
28101 : {
28102 49 : std::vector<expression_node_ptr> arg_list;
28103 :
28104 49 : expression_node_ptr result = error_node();
28105 :
28106 49 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
28107 :
28108 49 : next_token();
28109 :
28110 49 : if (token_is(token_t::e_lbracket))
28111 : {
28112 48 : if (token_is(token_t::e_rbracket))
28113 : {
28114 1 : if (!vararg_function->allow_zero_parameters())
28115 : {
28116 0 : set_error(make_error(
28117 : parser_error::e_syntax,
28118 0 : current_token(),
28119 : "ERR125 - Zero parameter call to vararg function: "
28120 : + vararg_function_name + " not allowed",
28121 : exprtk_error_location));
28122 :
28123 0 : return error_node();
28124 : }
28125 : }
28126 : else
28127 : {
28128 70 : for ( ; ; )
28129 : {
28130 117 : expression_node_ptr arg = parse_expression();
28131 :
28132 117 : if (0 == arg)
28133 0 : return error_node();
28134 : else
28135 117 : arg_list.push_back(arg);
28136 :
28137 117 : if (token_is(token_t::e_rbracket))
28138 47 : break;
28139 70 : else if (!token_is(token_t::e_comma))
28140 : {
28141 0 : set_error(make_error(
28142 : parser_error::e_syntax,
28143 0 : current_token(),
28144 : "ERR126 - Expected ',' for call to vararg function: "
28145 : + vararg_function_name,
28146 : exprtk_error_location));
28147 :
28148 0 : return error_node();
28149 : }
28150 : }
28151 : }
28152 : }
28153 1 : else if (!vararg_function->allow_zero_parameters())
28154 : {
28155 0 : set_error(make_error(
28156 : parser_error::e_syntax,
28157 0 : current_token(),
28158 : "ERR127 - Zero parameter call to vararg function: "
28159 : + vararg_function_name + " not allowed",
28160 : exprtk_error_location));
28161 :
28162 0 : return error_node();
28163 : }
28164 :
28165 49 : if (arg_list.size() < vararg_function->min_num_args())
28166 : {
28167 0 : set_error(make_error(
28168 : parser_error::e_syntax,
28169 0 : current_token(),
28170 : "ERR128 - Invalid number of parameters to call to vararg function: "
28171 : + vararg_function_name + ", require at least "
28172 0 : + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
28173 : exprtk_error_location));
28174 :
28175 0 : return error_node();
28176 : }
28177 49 : else if (arg_list.size() > vararg_function->max_num_args())
28178 : {
28179 0 : set_error(make_error(
28180 : parser_error::e_syntax,
28181 0 : current_token(),
28182 : "ERR129 - Invalid number of parameters to call to vararg function: "
28183 : + vararg_function_name + ", require no more than "
28184 0 : + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
28185 : exprtk_error_location));
28186 :
28187 0 : return error_node();
28188 : }
28189 :
28190 49 : result = expression_generator_.vararg_function_call(vararg_function,arg_list);
28191 :
28192 49 : sdd.delete_ptr = (0 == result);
28193 :
28194 49 : return result;
28195 49 : }
28196 :
28197 : class type_checker
28198 : {
28199 : public:
28200 :
28201 : enum return_type_t
28202 : {
28203 : e_overload = ' ',
28204 : e_numeric = 'T',
28205 : e_string = 'S'
28206 : };
28207 :
28208 : struct function_prototype_t
28209 : {
28210 : return_type_t return_type;
28211 : std::string param_seq;
28212 : };
28213 :
28214 : typedef parser<T> parser_t;
28215 : typedef std::vector<function_prototype_t> function_definition_list_t;
28216 :
28217 3608 : type_checker(parser_t& p,
28218 : const std::string& func_name,
28219 : const std::string& func_prototypes,
28220 : const return_type_t default_return_type)
28221 3608 : : invalid_state_(true)
28222 3608 : , parser_(p)
28223 3608 : , function_name_(func_name)
28224 3608 : , default_return_type_(default_return_type)
28225 : {
28226 3608 : parse_function_prototypes(func_prototypes);
28227 3608 : }
28228 :
28229 3608 : bool verify(const std::string& param_seq, std::size_t& pseq_index)
28230 : {
28231 3608 : if (function_definition_list_.empty())
28232 10 : return true;
28233 :
28234 3598 : std::vector<std::pair<std::size_t,char> > error_list;
28235 :
28236 5662 : for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
28237 : {
28238 5662 : details::char_t diff_value = 0;
28239 5662 : std::size_t diff_index = 0;
28240 :
28241 5662 : const bool result = details::sequence_match(function_definition_list_[i].param_seq,
28242 : param_seq,
28243 : diff_index, diff_value);
28244 :
28245 5662 : if (result)
28246 : {
28247 3598 : pseq_index = i;
28248 3598 : return true;
28249 : }
28250 : else
28251 2064 : error_list.push_back(std::make_pair(diff_index, diff_value));
28252 : }
28253 :
28254 0 : if (1 == error_list.size())
28255 : {
28256 0 : parser_.set_error(make_error(
28257 : parser_error::e_syntax,
28258 0 : parser_.current_token(),
28259 0 : "ERR130 - Failed parameter type check for function '" + function_name_ + "', "
28260 0 : "Expected '" + function_definition_list_[0].param_seq +
28261 : "' call set: '" + param_seq + "'",
28262 : exprtk_error_location));
28263 : }
28264 : else
28265 : {
28266 : // find first with largest diff_index;
28267 0 : std::size_t max_diff_index = 0;
28268 :
28269 0 : for (std::size_t i = 1; i < error_list.size(); ++i)
28270 : {
28271 0 : if (error_list[i].first > error_list[max_diff_index].first)
28272 : {
28273 0 : max_diff_index = i;
28274 : }
28275 : }
28276 :
28277 0 : parser_.set_error(make_error(
28278 : parser_error::e_syntax,
28279 0 : parser_.current_token(),
28280 0 : "ERR131 - Failed parameter type check for function '" + function_name_ + "', "
28281 0 : "Best match: '" + function_definition_list_[max_diff_index].param_seq +
28282 : "' call set: '" + param_seq + "'",
28283 : exprtk_error_location));
28284 : }
28285 :
28286 0 : return false;
28287 3598 : }
28288 :
28289 3716 : std::size_t paramseq_count() const
28290 : {
28291 3716 : return function_definition_list_.size();
28292 : }
28293 :
28294 : std::string paramseq(const std::size_t& index) const
28295 : {
28296 : return function_definition_list_[index].param_seq;
28297 : }
28298 :
28299 108 : return_type_t return_type(const std::size_t& index) const
28300 : {
28301 108 : return function_definition_list_[index].return_type;
28302 : }
28303 :
28304 3500 : bool invalid() const
28305 : {
28306 3500 : return !invalid_state_;
28307 : }
28308 :
28309 8 : bool allow_zero_parameters() const
28310 : {
28311 :
28312 8 : for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
28313 : {
28314 8 : if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
28315 : {
28316 8 : return true;
28317 : }
28318 : }
28319 :
28320 0 : return false;
28321 : }
28322 :
28323 : private:
28324 :
28325 3598 : std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
28326 : {
28327 3598 : std::string::const_iterator current_begin = param_seq.begin();
28328 3598 : std::string::const_iterator iter = param_seq.begin();
28329 :
28330 3598 : std::vector<std::string> result;
28331 :
28332 38882 : while (iter != param_seq.end())
28333 : {
28334 35284 : if (*iter == delimiter)
28335 : {
28336 5872 : result.push_back(std::string(current_begin, iter));
28337 5872 : current_begin = ++iter;
28338 : }
28339 : else
28340 29412 : ++iter;
28341 : }
28342 :
28343 3598 : if (current_begin != iter)
28344 : {
28345 7196 : result.push_back(std::string(current_begin, iter));
28346 : }
28347 :
28348 7196 : return result;
28349 0 : }
28350 :
28351 9470 : inline bool is_valid_token(std::string param_seq,
28352 : function_prototype_t& funcproto) const
28353 : {
28354 : // Determine return type
28355 9470 : funcproto.return_type = default_return_type_;
28356 :
28357 9470 : if (param_seq.size() > 2)
28358 : {
28359 6129 : if (':' == param_seq[1])
28360 : {
28361 : // Note: Only overloaded igeneric functions can have return
28362 : // type definitions.
28363 1296 : if (type_checker::e_overload != default_return_type_)
28364 0 : return false;
28365 :
28366 1296 : switch (param_seq[0])
28367 : {
28368 648 : case 'T' : funcproto.return_type = type_checker::e_numeric;
28369 648 : break;
28370 :
28371 648 : case 'S' : funcproto.return_type = type_checker::e_string;
28372 648 : break;
28373 :
28374 0 : default : return false;
28375 : }
28376 :
28377 1296 : param_seq.erase(0,2);
28378 : }
28379 : }
28380 :
28381 9470 : if (
28382 18940 : (std::string::npos != param_seq.find("?*")) ||
28383 9470 : (std::string::npos != param_seq.find("**"))
28384 : )
28385 : {
28386 0 : return false;
28387 : }
28388 9470 : else if (
28389 9499 : (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
28390 29 : ("Z" == param_seq)
28391 : )
28392 : {
28393 9470 : funcproto.param_seq = param_seq;
28394 9470 : return true;
28395 : }
28396 :
28397 0 : return false;
28398 : }
28399 :
28400 3608 : void parse_function_prototypes(const std::string& func_prototypes)
28401 : {
28402 3608 : if (func_prototypes.empty())
28403 10 : return;
28404 :
28405 3598 : std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
28406 :
28407 : typedef std::map<std::string,std::size_t> param_seq_map_t;
28408 3598 : param_seq_map_t param_seq_map;
28409 :
28410 22538 : for (std::size_t i = 0; i < param_seq_list.size(); ++i)
28411 : {
28412 9470 : function_prototype_t func_proto;
28413 :
28414 9470 : if (!is_valid_token(param_seq_list[i], func_proto))
28415 : {
28416 0 : invalid_state_ = false;
28417 :
28418 0 : parser_.set_error(make_error(
28419 : parser_error::e_syntax,
28420 0 : parser_.current_token(),
28421 0 : "ERR132 - Invalid parameter sequence of '" + param_seq_list[i] +
28422 0 : "' for function: " + function_name_,
28423 : exprtk_error_location));
28424 0 : return;
28425 : }
28426 :
28427 9470 : param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
28428 :
28429 9470 : if (param_seq_map.end() != seq_itr)
28430 : {
28431 0 : invalid_state_ = false;
28432 :
28433 0 : parser_.set_error(make_error(
28434 : parser_error::e_syntax,
28435 0 : parser_.current_token(),
28436 0 : "ERR133 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
28437 0 : "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
28438 : "pseq_idx[" + details::to_str(i) + "] " +
28439 0 : "param seq: " + param_seq_list[i],
28440 : exprtk_error_location));
28441 0 : return;
28442 : }
28443 :
28444 9470 : function_definition_list_.push_back(func_proto);
28445 : }
28446 3598 : }
28447 :
28448 : type_checker(const type_checker&) exprtk_delete;
28449 : type_checker& operator=(const type_checker&) exprtk_delete;
28450 :
28451 : bool invalid_state_;
28452 : parser_t& parser_;
28453 : std::string function_name_;
28454 : const return_type_t default_return_type_;
28455 : function_definition_list_t function_definition_list_;
28456 : };
28457 :
28458 3500 : inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
28459 : {
28460 3500 : std::vector<expression_node_ptr> arg_list;
28461 :
28462 3500 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
28463 :
28464 3500 : next_token();
28465 :
28466 3500 : std::string param_type_list;
28467 :
28468 3500 : type_checker tc(
28469 : (*this),
28470 : function_name,
28471 3500 : function->parameter_sequence,
28472 : type_checker::e_string);
28473 :
28474 3500 : if (tc.invalid())
28475 : {
28476 0 : set_error(make_error(
28477 : parser_error::e_syntax,
28478 0 : current_token(),
28479 : "ERR134 - Type checker instantiation failure for generic function: " + function_name,
28480 : exprtk_error_location));
28481 :
28482 0 : return error_node();
28483 : }
28484 :
28485 3500 : if (token_is(token_t::e_lbracket))
28486 : {
28487 3493 : if (token_is(token_t::e_rbracket))
28488 : {
28489 8 : if (
28490 16 : !function->allow_zero_parameters() &&
28491 8 : !tc .allow_zero_parameters()
28492 : )
28493 : {
28494 0 : set_error(make_error(
28495 : parser_error::e_syntax,
28496 0 : current_token(),
28497 : "ERR135 - Zero parameter call to generic function: "
28498 : + function_name + " not allowed",
28499 : exprtk_error_location));
28500 :
28501 0 : return error_node();
28502 : }
28503 : }
28504 : else
28505 : {
28506 4381 : for ( ; ; )
28507 : {
28508 7866 : expression_node_ptr arg = parse_expression();
28509 :
28510 7866 : if (0 == arg)
28511 0 : return error_node();
28512 :
28513 7866 : if (is_ivector_node(arg))
28514 4324 : param_type_list += 'V';
28515 3542 : else if (is_generally_string_node(arg))
28516 94 : param_type_list += 'S';
28517 : else // Everything else is assumed to be a scalar returning expression
28518 3448 : param_type_list += 'T';
28519 :
28520 7866 : arg_list.push_back(arg);
28521 :
28522 7866 : if (token_is(token_t::e_rbracket))
28523 3485 : break;
28524 4381 : else if (!token_is(token_t::e_comma))
28525 : {
28526 0 : set_error(make_error(
28527 : parser_error::e_syntax,
28528 0 : current_token(),
28529 : "ERR136 - Expected ',' for call to generic function: " + function_name,
28530 : exprtk_error_location));
28531 :
28532 0 : return error_node();
28533 : }
28534 : }
28535 : }
28536 : }
28537 7 : else if (
28538 14 : !function->parameter_sequence.empty() &&
28539 14 : function->allow_zero_parameters () &&
28540 0 : !tc .allow_zero_parameters ()
28541 : )
28542 : {
28543 0 : set_error(make_error(
28544 : parser_error::e_syntax,
28545 0 : current_token(),
28546 : "ERR137 - Zero parameter call to generic function: "
28547 : + function_name + " not allowed",
28548 : exprtk_error_location));
28549 :
28550 0 : return error_node();
28551 : }
28552 :
28553 3500 : std::size_t param_seq_index = 0;
28554 :
28555 3500 : if (
28556 7000 : state_.type_check_enabled &&
28557 3500 : !tc.verify(param_type_list, param_seq_index)
28558 : )
28559 : {
28560 0 : set_error(make_error(
28561 : parser_error::e_syntax,
28562 0 : current_token(),
28563 : "ERR138 - Invalid input parameter sequence for call to generic function: " + function_name,
28564 : exprtk_error_location));
28565 :
28566 0 : return error_node();
28567 : }
28568 :
28569 3500 : expression_node_ptr result = error_node();
28570 :
28571 3500 : result = (tc.paramseq_count() <= 1) ?
28572 : expression_generator_
28573 57 : .generic_function_call(function, arg_list) :
28574 : expression_generator_
28575 3443 : .generic_function_call(function, arg_list, param_seq_index);
28576 :
28577 3500 : sdd.delete_ptr = (0 == result);
28578 :
28579 3500 : return result;
28580 3500 : }
28581 :
28582 108 : inline bool parse_igeneric_function_params(std::string& param_type_list,
28583 : std::vector<expression_node_ptr>& arg_list,
28584 : const std::string& function_name,
28585 : igeneric_function<T>* function,
28586 : const type_checker& tc)
28587 : {
28588 108 : if (token_is(token_t::e_lbracket))
28589 : {
28590 108 : if (token_is(token_t::e_rbracket))
28591 : {
28592 0 : if (
28593 0 : !function->allow_zero_parameters() &&
28594 0 : !tc .allow_zero_parameters()
28595 : )
28596 : {
28597 0 : set_error(make_error(
28598 : parser_error::e_syntax,
28599 0 : current_token(),
28600 : "ERR139 - Zero parameter call to generic function: "
28601 : + function_name + " not allowed",
28602 : exprtk_error_location));
28603 :
28604 0 : return false;
28605 : }
28606 : }
28607 : else
28608 : {
28609 144 : for ( ; ; )
28610 : {
28611 252 : expression_node_ptr arg = parse_expression();
28612 :
28613 252 : if (0 == arg)
28614 0 : return false;
28615 :
28616 252 : if (is_ivector_node(arg))
28617 0 : param_type_list += 'V';
28618 252 : else if (is_generally_string_node(arg))
28619 144 : param_type_list += 'S';
28620 : else // Everything else is a scalar returning expression
28621 108 : param_type_list += 'T';
28622 :
28623 252 : arg_list.push_back(arg);
28624 :
28625 252 : if (token_is(token_t::e_rbracket))
28626 108 : break;
28627 144 : else if (!token_is(token_t::e_comma))
28628 : {
28629 0 : set_error(make_error(
28630 : parser_error::e_syntax,
28631 0 : current_token(),
28632 : "ERR140 - Expected ',' for call to string function: " + function_name,
28633 : exprtk_error_location));
28634 :
28635 0 : return false;
28636 : }
28637 : }
28638 : }
28639 :
28640 108 : return true;
28641 : }
28642 : else
28643 0 : return false;
28644 : }
28645 :
28646 : #ifndef exprtk_disable_string_capabilities
28647 36 : inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
28648 : {
28649 : // Move pass the function name
28650 36 : next_token();
28651 :
28652 36 : std::string param_type_list;
28653 :
28654 36 : type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
28655 :
28656 36 : if (
28657 72 : (!function->parameter_sequence.empty()) &&
28658 36 : (0 == tc.paramseq_count())
28659 : )
28660 : {
28661 0 : return error_node();
28662 : }
28663 :
28664 36 : std::vector<expression_node_ptr> arg_list;
28665 36 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
28666 :
28667 36 : if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
28668 : {
28669 0 : return error_node();
28670 : }
28671 :
28672 36 : std::size_t param_seq_index = 0;
28673 :
28674 36 : if (!tc.verify(param_type_list, param_seq_index))
28675 : {
28676 0 : set_error(make_error(
28677 : parser_error::e_syntax,
28678 0 : current_token(),
28679 : "ERR141 - Invalid input parameter sequence for call to string function: " + function_name,
28680 : exprtk_error_location));
28681 :
28682 0 : return error_node();
28683 : }
28684 :
28685 36 : expression_node_ptr result = error_node();
28686 :
28687 36 : result = (tc.paramseq_count() <= 1) ?
28688 : expression_generator_
28689 0 : .string_function_call(function, arg_list) :
28690 : expression_generator_
28691 36 : .string_function_call(function, arg_list, param_seq_index);
28692 :
28693 36 : sdd.delete_ptr = (0 == result);
28694 :
28695 36 : return result;
28696 36 : }
28697 :
28698 72 : inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
28699 : {
28700 : // Move pass the function name
28701 72 : next_token();
28702 :
28703 72 : std::string param_type_list;
28704 :
28705 72 : type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
28706 :
28707 72 : if (
28708 144 : (!function->parameter_sequence.empty()) &&
28709 72 : (0 == tc.paramseq_count())
28710 : )
28711 : {
28712 0 : return error_node();
28713 : }
28714 :
28715 72 : std::vector<expression_node_ptr> arg_list;
28716 72 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
28717 :
28718 72 : if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
28719 : {
28720 0 : return error_node();
28721 : }
28722 :
28723 72 : std::size_t param_seq_index = 0;
28724 :
28725 72 : if (!tc.verify(param_type_list, param_seq_index))
28726 : {
28727 0 : set_error(make_error(
28728 : parser_error::e_syntax,
28729 0 : current_token(),
28730 : "ERR142 - Invalid input parameter sequence for call to overloaded function: " + function_name,
28731 : exprtk_error_location));
28732 :
28733 0 : return error_node();
28734 : }
28735 :
28736 72 : expression_node_ptr result = error_node();
28737 :
28738 72 : if (type_checker::e_numeric == tc.return_type(param_seq_index))
28739 : {
28740 36 : if (tc.paramseq_count() <= 1)
28741 : result = expression_generator_
28742 0 : .generic_function_call(function, arg_list);
28743 : else
28744 : result = expression_generator_
28745 36 : .generic_function_call(function, arg_list, param_seq_index);
28746 : }
28747 36 : else if (type_checker::e_string == tc.return_type(param_seq_index))
28748 : {
28749 36 : if (tc.paramseq_count() <= 1)
28750 : result = expression_generator_
28751 0 : .string_function_call(function, arg_list);
28752 : else
28753 : result = expression_generator_
28754 36 : .string_function_call(function, arg_list, param_seq_index);
28755 : }
28756 : else
28757 : {
28758 0 : set_error(make_error(
28759 : parser_error::e_syntax,
28760 0 : current_token(),
28761 : "ERR143 - Invalid return type for call to overloaded function: " + function_name,
28762 : exprtk_error_location));
28763 : }
28764 :
28765 72 : sdd.delete_ptr = (0 == result);
28766 72 : return result;
28767 72 : }
28768 : #endif
28769 :
28770 : template <typename Type, std::size_t NumberOfParameters>
28771 : struct parse_special_function_impl
28772 : {
28773 4245 : static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
28774 : {
28775 : expression_node_ptr branch[NumberOfParameters];
28776 4245 : expression_node_ptr result = error_node();
28777 :
28778 4245 : std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
28779 :
28780 4245 : scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
28781 :
28782 4245 : p.next_token();
28783 :
28784 4245 : if (!p.token_is(token_t::e_lbracket))
28785 : {
28786 0 : p.set_error(make_error(
28787 : parser_error::e_syntax,
28788 0 : p.current_token(),
28789 : "ERR144 - Expected '(' for special function '" + sf_name + "'",
28790 : exprtk_error_location));
28791 :
28792 0 : return error_node();
28793 : }
28794 :
28795 19305 : for (std::size_t i = 0; i < NumberOfParameters; ++i)
28796 : {
28797 15060 : branch[i] = p.parse_expression();
28798 :
28799 15060 : if (0 == branch[i])
28800 : {
28801 0 : return p.error_node();
28802 : }
28803 15060 : else if (i < (NumberOfParameters - 1))
28804 : {
28805 10815 : if (!p.token_is(token_t::e_comma))
28806 : {
28807 0 : p.set_error(make_error(
28808 : parser_error::e_syntax,
28809 0 : p.current_token(),
28810 : "ERR145 - Expected ',' before next parameter of special function '" + sf_name + "'",
28811 : exprtk_error_location));
28812 :
28813 0 : return p.error_node();
28814 : }
28815 : }
28816 : }
28817 :
28818 4245 : if (!p.token_is(token_t::e_rbracket))
28819 : {
28820 0 : p.set_error(make_error(
28821 : parser_error::e_syntax,
28822 0 : p.current_token(),
28823 : "ERR146 - Invalid number of parameters for special function '" + sf_name + "'",
28824 : exprtk_error_location));
28825 :
28826 0 : return p.error_node();
28827 : }
28828 : else
28829 4245 : result = p.expression_generator_.special_function(opt_type,branch);
28830 :
28831 4245 : sd.delete_ptr = (0 == result);
28832 :
28833 4245 : return result;
28834 4245 : }
28835 : };
28836 :
28837 4245 : inline expression_node_ptr parse_special_function()
28838 : {
28839 4245 : const std::string sf_name = current_token().value;
28840 :
28841 : // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
28842 4245 : if (
28843 8490 : !details::is_digit(sf_name[2]) ||
28844 4245 : !details::is_digit(sf_name[3])
28845 : )
28846 : {
28847 0 : set_error(make_error(
28848 : parser_error::e_token,
28849 0 : current_token(),
28850 : "ERR147 - Invalid special function[1]: " + sf_name,
28851 : exprtk_error_location));
28852 :
28853 0 : return error_node();
28854 : }
28855 :
28856 4245 : const int id = (sf_name[2] - '0') * 10 +
28857 4245 : (sf_name[3] - '0');
28858 :
28859 4245 : if (id >= details::e_sffinal)
28860 : {
28861 0 : set_error(make_error(
28862 : parser_error::e_token,
28863 0 : current_token(),
28864 : "ERR148 - Invalid special function[2]: " + sf_name,
28865 : exprtk_error_location));
28866 :
28867 0 : return error_node();
28868 : }
28869 :
28870 4245 : const int sf_3_to_4 = details::e_sf48;
28871 4245 : const details::operator_type opt_type = details::operator_type(id + 1000);
28872 4245 : const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
28873 :
28874 4245 : switch (NumberOfParameters)
28875 : {
28876 1920 : case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
28877 2325 : case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
28878 0 : default : return error_node();
28879 : }
28880 4245 : }
28881 :
28882 275 : inline expression_node_ptr parse_null_statement()
28883 : {
28884 275 : next_token();
28885 275 : return node_allocator_.allocate<details::null_node<T> >();
28886 : }
28887 :
28888 : #ifndef exprtk_disable_break_continue
28889 483 : inline expression_node_ptr parse_break_statement()
28890 : {
28891 483 : if (state_.parsing_break_stmt)
28892 : {
28893 0 : set_error(make_error(
28894 : parser_error::e_syntax,
28895 0 : current_token(),
28896 : "ERR149 - Invoking 'break' within a break call is not allowed",
28897 : exprtk_error_location));
28898 :
28899 0 : return error_node();
28900 : }
28901 483 : else if (0 == state_.parsing_loop_stmt_count)
28902 : {
28903 0 : set_error(make_error(
28904 : parser_error::e_syntax,
28905 0 : current_token(),
28906 : "ERR150 - Invalid use of 'break', allowed only in the scope of a loop",
28907 : exprtk_error_location));
28908 :
28909 0 : return error_node();
28910 : }
28911 :
28912 483 : scoped_bool_negator sbn(state_.parsing_break_stmt);
28913 :
28914 483 : if (!brkcnt_list_.empty())
28915 : {
28916 483 : next_token();
28917 :
28918 483 : brkcnt_list_.front() = true;
28919 :
28920 483 : expression_node_ptr return_expr = error_node();
28921 :
28922 483 : if (token_is(token_t::e_lsqrbracket))
28923 : {
28924 402 : if (0 == (return_expr = parse_expression()))
28925 : {
28926 0 : set_error(make_error(
28927 : parser_error::e_syntax,
28928 0 : current_token(),
28929 : "ERR151 - Failed to parse return expression for 'break' statement",
28930 : exprtk_error_location));
28931 :
28932 0 : return error_node();
28933 : }
28934 402 : else if (!token_is(token_t::e_rsqrbracket))
28935 : {
28936 0 : set_error(make_error(
28937 : parser_error::e_syntax,
28938 0 : current_token(),
28939 : "ERR152 - Expected ']' at the completion of break's return expression",
28940 : exprtk_error_location));
28941 :
28942 0 : free_node(node_allocator_,return_expr);
28943 :
28944 0 : return error_node();
28945 : }
28946 : }
28947 :
28948 966 : state_.activate_side_effect("parse_break_statement()");
28949 :
28950 483 : return node_allocator_.allocate<details::break_node<T> >(return_expr);
28951 : }
28952 : else
28953 : {
28954 0 : set_error(make_error(
28955 : parser_error::e_syntax,
28956 0 : current_token(),
28957 : "ERR153 - Invalid use of 'break', allowed only in the scope of a loop",
28958 : exprtk_error_location));
28959 : }
28960 :
28961 0 : return error_node();
28962 483 : }
28963 :
28964 460 : inline expression_node_ptr parse_continue_statement()
28965 : {
28966 460 : if (0 == state_.parsing_loop_stmt_count)
28967 : {
28968 0 : set_error(make_error(
28969 : parser_error::e_syntax,
28970 0 : current_token(),
28971 : "ERR154 - Invalid use of 'continue', allowed only in the scope of a loop",
28972 : exprtk_error_location));
28973 :
28974 0 : return error_node();
28975 : }
28976 : else
28977 : {
28978 460 : next_token();
28979 :
28980 460 : brkcnt_list_.front() = true;
28981 920 : state_.activate_side_effect("parse_continue_statement()");
28982 :
28983 460 : return node_allocator_.allocate<details::continue_node<T> >();
28984 : }
28985 : }
28986 : #endif
28987 :
28988 24277 : inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
28989 : {
28990 24277 : expression_node_ptr size_expression_node = error_node();
28991 :
28992 24277 : if (!token_is(token_t::e_lsqrbracket))
28993 : {
28994 0 : set_error(make_error(
28995 : parser_error::e_syntax,
28996 0 : current_token(),
28997 : "ERR155 - Expected '[' as part of vector size definition",
28998 : exprtk_error_location));
28999 :
29000 0 : return error_node();
29001 : }
29002 24277 : else if (0 == (size_expression_node = parse_expression()))
29003 : {
29004 0 : set_error(make_error(
29005 : parser_error::e_syntax,
29006 0 : current_token(),
29007 : "ERR156 - Failed to determine size of vector '" + vec_name + "'",
29008 : exprtk_error_location));
29009 :
29010 0 : return error_node();
29011 : }
29012 24277 : else if (!is_constant_node(size_expression_node))
29013 : {
29014 0 : const bool is_rebaseble_vector =
29015 0 : (size_expression_node->type() == details::expression_node<T>::e_vecsize) &&
29016 0 : static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable();
29017 :
29018 0 : free_node(node_allocator_,size_expression_node);
29019 :
29020 0 : const std::string error_msg = (is_rebaseble_vector) ?
29021 : std::string("Rebasable/Resizable vector cannot be used to define the size of vector") :
29022 : std::string("Expected a constant literal number as size of vector");
29023 0 : set_error(make_error(
29024 : parser_error::e_syntax,
29025 0 : current_token(),
29026 : "ERR157 - " + error_msg + " '" + vec_name + "'",
29027 : exprtk_error_location));
29028 :
29029 0 : return error_node();
29030 0 : }
29031 :
29032 24277 : const T vector_size = size_expression_node->value();
29033 :
29034 24277 : free_node(node_allocator_,size_expression_node);
29035 :
29036 24277 : const std::size_t max_vector_size = settings_.max_local_vector_size();
29037 :
29038 24277 : if (
29039 24277 : (vector_size <= T(0)) ||
29040 0 : std::not_equal_to<T>()
29041 48554 : (T(0),vector_size - details::numeric::trunc(vector_size)) ||
29042 24277 : (static_cast<std::size_t>(vector_size) > max_vector_size)
29043 : )
29044 : {
29045 0 : set_error(make_error(
29046 : parser_error::e_syntax,
29047 0 : current_token(),
29048 : "ERR158 - Invalid vector size. Must be an integer in the "
29049 : "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " +
29050 : details::to_str(details::numeric::to_int32(vector_size)),
29051 : exprtk_error_location));
29052 :
29053 0 : return error_node();
29054 : }
29055 :
29056 24277 : typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
29057 :
29058 24277 : const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
29059 :
29060 24277 : scope_element& se = sem_.get_element(vec_name);
29061 :
29062 24277 : if (se.name == vec_name)
29063 : {
29064 1440 : if (se.active)
29065 : {
29066 0 : set_error(make_error(
29067 : parser_error::e_syntax,
29068 0 : current_token(),
29069 : "ERR159 - Illegal redefinition of local vector: '" + vec_name + "'",
29070 : exprtk_error_location));
29071 :
29072 0 : return error_node();
29073 : }
29074 1440 : else if (
29075 1440 : (se.size == vec_size) &&
29076 1000 : (scope_element::e_vector == se.type)
29077 : )
29078 : {
29079 1000 : vec_holder = se.vec_node;
29080 1000 : se.active = true;
29081 1000 : se.depth = state_.scope_depth;
29082 1000 : se.ref_count++;
29083 : }
29084 : }
29085 :
29086 24277 : if (0 == vec_holder)
29087 : {
29088 23277 : scope_element nse;
29089 23277 : nse.name = vec_name;
29090 23277 : nse.active = true;
29091 23277 : nse.ref_count = 1;
29092 23277 : nse.type = scope_element::e_vector;
29093 23277 : nse.depth = state_.scope_depth;
29094 23277 : nse.size = vec_size;
29095 23277 : nse.data = new T[vec_size];
29096 23277 : nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
29097 :
29098 23277 : std::memset(nse.data, 0x00, vec_size * sizeof(T));
29099 :
29100 23277 : if (!sem_.add_element(nse))
29101 : {
29102 0 : set_error(make_error(
29103 : parser_error::e_syntax,
29104 0 : current_token(),
29105 : "ERR160 - Failed to add new local vector '" + vec_name + "' to SEM",
29106 : exprtk_error_location));
29107 :
29108 0 : sem_.free_element(nse);
29109 :
29110 0 : return error_node();
29111 : }
29112 :
29113 23277 : vec_holder = nse.vec_node;
29114 :
29115 : exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
29116 : nse.name.c_str(),
29117 : static_cast<int>(nse.size)));
29118 23277 : }
29119 :
29120 48554 : state_.activate_side_effect("parse_define_vector_statement()");
29121 :
29122 24277 : lodge_symbol(vec_name, e_st_local_vector);
29123 :
29124 24277 : std::vector<expression_node_ptr> vec_initilizer_list;
29125 :
29126 24277 : scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
29127 :
29128 24277 : bool single_value_initialiser = false;
29129 24277 : bool range_value_initialiser = false;
29130 24277 : bool vec_to_vec_initialiser = false;
29131 24277 : bool null_initialisation = false;
29132 :
29133 24277 : if (!token_is(token_t::e_rsqrbracket))
29134 : {
29135 0 : set_error(make_error(
29136 : parser_error::e_syntax,
29137 0 : current_token(),
29138 : "ERR161 - Expected ']' as part of vector size definition",
29139 : exprtk_error_location));
29140 :
29141 0 : return error_node();
29142 : }
29143 24277 : else if (!token_is(token_t::e_eof))
29144 : {
29145 24189 : if (!token_is(token_t::e_assign))
29146 : {
29147 0 : set_error(make_error(
29148 : parser_error::e_syntax,
29149 0 : current_token(),
29150 : "ERR162 - Expected ':=' as part of vector definition",
29151 : exprtk_error_location));
29152 :
29153 0 : return error_node();
29154 : }
29155 24189 : else if (token_is(token_t::e_lsqrbracket))
29156 : {
29157 7293 : expression_node_ptr initialiser_component = parse_expression();
29158 :
29159 7293 : if (0 == initialiser_component)
29160 : {
29161 0 : set_error(make_error(
29162 : parser_error::e_syntax,
29163 0 : current_token(),
29164 : "ERR163 - Failed to parse first component of vector initialiser for vector: " + vec_name,
29165 : exprtk_error_location));
29166 :
29167 0 : return error_node();
29168 : }
29169 :
29170 7293 : vec_initilizer_list.push_back(initialiser_component);
29171 :
29172 7293 : if (token_is(token_t::e_colon))
29173 : {
29174 215 : initialiser_component = parse_expression();
29175 :
29176 215 : if (0 == initialiser_component)
29177 : {
29178 0 : set_error(make_error(
29179 : parser_error::e_syntax,
29180 0 : current_token(),
29181 : "ERR164 - Failed to parse second component of vector initialiser for vector: " + vec_name,
29182 : exprtk_error_location));
29183 :
29184 0 : return error_node();
29185 : }
29186 :
29187 215 : vec_initilizer_list.push_back(initialiser_component);
29188 : }
29189 :
29190 7293 : if (!token_is(token_t::e_rsqrbracket))
29191 : {
29192 0 : set_error(make_error(
29193 : parser_error::e_syntax,
29194 0 : current_token(),
29195 : "ERR165 - Expected ']' to close single value vector initialiser",
29196 : exprtk_error_location));
29197 :
29198 0 : return error_node();
29199 : }
29200 :
29201 7293 : switch (vec_initilizer_list.size())
29202 : {
29203 7078 : case 1 : single_value_initialiser = true; break;
29204 215 : case 2 : range_value_initialiser = true; break;
29205 : }
29206 : }
29207 16896 : else if (!token_is(token_t::e_lcrlbracket))
29208 : {
29209 370 : expression_node_ptr initialiser = error_node();
29210 :
29211 : // Is this a vector to vector assignment and initialisation?
29212 370 : if (token_t::e_symbol == current_token().type)
29213 : {
29214 : // Is it a locally defined vector?
29215 370 : const scope_element& lcl_se = sem_.get_active_element(current_token().value);
29216 :
29217 370 : if (scope_element::e_vector == lcl_se.type)
29218 : {
29219 290 : if (0 != (initialiser = parse_expression()))
29220 290 : vec_initilizer_list.push_back(initialiser);
29221 : else
29222 0 : return error_node();
29223 : }
29224 : // Are we dealing with a user defined vector?
29225 80 : else if (symtab_store_.is_vector(current_token().value))
29226 : {
29227 0 : lodge_symbol(current_token().value, e_st_vector);
29228 :
29229 0 : if (0 != (initialiser = parse_expression()))
29230 0 : vec_initilizer_list.push_back(initialiser);
29231 : else
29232 0 : return error_node();
29233 : }
29234 : // Are we dealing with a null initialisation vector definition?
29235 240 : else if (token_is(token_t::e_symbol,"null"))
29236 80 : null_initialisation = true;
29237 : }
29238 :
29239 370 : if (!null_initialisation)
29240 : {
29241 290 : if (0 == initialiser)
29242 : {
29243 0 : set_error(make_error(
29244 : parser_error::e_syntax,
29245 0 : current_token(),
29246 : "ERR166 - Expected '{' as part of vector initialiser list",
29247 : exprtk_error_location));
29248 :
29249 0 : return error_node();
29250 : }
29251 : else
29252 290 : vec_to_vec_initialiser = true;
29253 : }
29254 : }
29255 16526 : else if (!token_is(token_t::e_rcrlbracket))
29256 : {
29257 43716 : for ( ; ; )
29258 : {
29259 59422 : expression_node_ptr initialiser = parse_expression();
29260 :
29261 59422 : if (0 == initialiser)
29262 : {
29263 0 : set_error(make_error(
29264 : parser_error::e_syntax,
29265 0 : current_token(),
29266 : "ERR167 - Expected '{' as part of vector initialiser list",
29267 : exprtk_error_location));
29268 :
29269 0 : return error_node();
29270 : }
29271 : else
29272 59422 : vec_initilizer_list.push_back(initialiser);
29273 :
29274 59422 : if (token_is(token_t::e_rcrlbracket))
29275 15706 : break;
29276 :
29277 43716 : const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
29278 :
29279 43716 : if (!token_is(token_t::e_comma) && is_next_close)
29280 : {
29281 0 : set_error(make_error(
29282 : parser_error::e_syntax,
29283 0 : current_token(),
29284 : "ERR168 - Expected ',' between vector initialisers",
29285 : exprtk_error_location));
29286 :
29287 0 : return error_node();
29288 : }
29289 :
29290 43716 : if (token_is(token_t::e_rcrlbracket))
29291 0 : break;
29292 : }
29293 : }
29294 :
29295 24189 : if (
29296 24189 : !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
29297 46058 : !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
29298 46058 : !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
29299 : )
29300 : {
29301 21869 : if (!token_is(token_t::e_eof))
29302 : {
29303 0 : set_error(make_error(
29304 : parser_error::e_syntax,
29305 0 : current_token(),
29306 : "ERR169 - Expected ';' at end of vector definition",
29307 : exprtk_error_location));
29308 :
29309 0 : return error_node();
29310 : }
29311 : }
29312 :
29313 24189 : if (
29314 41300 : !single_value_initialiser &&
29315 41085 : !range_value_initialiser &&
29316 16896 : (T(vec_initilizer_list.size()) > vector_size)
29317 : )
29318 : {
29319 0 : set_error(make_error(
29320 : parser_error::e_syntax,
29321 0 : current_token(),
29322 : "ERR170 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
29323 : exprtk_error_location));
29324 :
29325 0 : return error_node();
29326 : }
29327 : }
29328 :
29329 24277 : expression_node_ptr result = error_node();
29330 :
29331 24277 : if (
29332 24277 : (vec_initilizer_list.size() == 1) &&
29333 : single_value_initialiser
29334 : )
29335 : {
29336 7078 : if (details::is_constant_node(vec_initilizer_list[0]))
29337 : {
29338 : // vector_init_zero_value_node var v[10] := [0]
29339 6988 : if (T(0) == vec_initilizer_list[0]->value())
29340 : {
29341 839 : result = node_allocator_
29342 2517 : .allocate<details::vector_init_zero_value_node<T> >(
29343 839 : (*vec_holder)[0],
29344 : vec_size,
29345 : vec_initilizer_list);
29346 : }
29347 : else
29348 : {
29349 : // vector_init_single_constvalue_node var v[10] := [123]
29350 6149 : result = node_allocator_
29351 18447 : .allocate<details::vector_init_single_constvalue_node<T> >(
29352 6149 : (*vec_holder)[0],
29353 : vec_size,
29354 : vec_initilizer_list);
29355 : }
29356 : }
29357 : else
29358 : {
29359 : // vector_init_single_value_node var v[10] := [123 + (x / y)]
29360 90 : result = node_allocator_
29361 270 : .allocate<details::vector_init_single_value_node<T> >(
29362 90 : (*vec_holder)[0],
29363 : vec_size,
29364 : vec_initilizer_list);
29365 : }
29366 : }
29367 17199 : else if (
29368 17199 : (vec_initilizer_list.size() == 2) &&
29369 : range_value_initialiser
29370 : )
29371 : {
29372 215 : bool base_const = details::is_constant_node(vec_initilizer_list[0]);
29373 215 : bool inc_const = details::is_constant_node(vec_initilizer_list[1]);
29374 :
29375 215 : if (base_const && inc_const)
29376 : {
29377 : // vector_init_single_value_node var v[10] := [1 : 3.5]
29378 135 : result = node_allocator_
29379 405 : .allocate<details::vector_init_iota_constconst_node<T> >(
29380 135 : (*vec_holder)[0],
29381 : vec_size,
29382 : vec_initilizer_list);
29383 : }
29384 80 : else if (base_const && !inc_const)
29385 : {
29386 : // vector_init_single_value_node var v[10] := [1 : x + y]
29387 40 : result = node_allocator_
29388 120 : .allocate<details::vector_init_iota_constnconst_node<T> >(
29389 40 : (*vec_holder)[0],
29390 : vec_size,
29391 : vec_initilizer_list);
29392 : }
29393 40 : else if (!base_const && inc_const)
29394 : {
29395 : // vector_init_single_value_node var v[10] := [x + y : 3]
29396 20 : result = node_allocator_
29397 60 : .allocate<details::vector_init_iota_nconstconst_node<T> >(
29398 20 : (*vec_holder)[0],
29399 : vec_size,
29400 : vec_initilizer_list);
29401 : }
29402 20 : else if (!base_const && !inc_const)
29403 : {
29404 : // vector_init_single_value_node var v[10] := [x + y : z / w]
29405 20 : result = node_allocator_
29406 60 : .allocate<details::vector_init_iota_nconstnconst_node<T> >(
29407 20 : (*vec_holder)[0],
29408 : vec_size,
29409 : vec_initilizer_list);
29410 : }
29411 : }
29412 16984 : else if (null_initialisation)
29413 80 : result = expression_generator_(T(0.0));
29414 16904 : else if (vec_to_vec_initialiser)
29415 : {
29416 290 : expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
29417 :
29418 870 : result = expression_generator_(
29419 290 : details::e_assign,
29420 : vec_node,
29421 290 : vec_initilizer_list[0]);
29422 : }
29423 : else
29424 : {
29425 16614 : result = node_allocator_
29426 49842 : .allocate<details::vector_initialisation_node<T> >(
29427 16614 : (*vec_holder)[0],
29428 : vec_size,
29429 : vec_initilizer_list,
29430 : single_value_initialiser);
29431 : }
29432 :
29433 24277 : svd.delete_ptr = false;
29434 :
29435 24277 : if (result && result->valid())
29436 : {
29437 24277 : return result;
29438 : }
29439 :
29440 0 : details::free_node(node_allocator_,result);
29441 :
29442 0 : set_error(make_error(
29443 : parser_error::e_synthesis,
29444 0 : current_token(),
29445 : "ERR171 - Failed to generate initialisation node for vector: " + vec_name,
29446 : exprtk_error_location));
29447 :
29448 0 : return error_node();
29449 24277 : }
29450 :
29451 : #ifndef exprtk_disable_string_capabilities
29452 9820 : inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
29453 : {
29454 9820 : stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
29455 :
29456 9820 : scope_element& se = sem_.get_element(str_name);
29457 :
29458 9820 : if (se.name == str_name)
29459 : {
29460 120 : if (se.active)
29461 : {
29462 0 : set_error(make_error(
29463 : parser_error::e_syntax,
29464 0 : current_token(),
29465 : "ERR172 - Illegal redefinition of local variable: '" + str_name + "'",
29466 : exprtk_error_location));
29467 :
29468 0 : free_node(node_allocator_,initialisation_expression);
29469 :
29470 0 : return error_node();
29471 : }
29472 120 : else if (scope_element::e_string == se.type)
29473 : {
29474 80 : str_node = se.str_node;
29475 80 : se.active = true;
29476 80 : se.depth = state_.scope_depth;
29477 80 : se.ref_count++;
29478 : }
29479 : }
29480 :
29481 9820 : if (0 == str_node)
29482 : {
29483 9740 : scope_element nse;
29484 9740 : nse.name = str_name;
29485 9740 : nse.active = true;
29486 9740 : nse.ref_count = 1;
29487 9740 : nse.type = scope_element::e_string;
29488 9740 : nse.depth = state_.scope_depth;
29489 9740 : nse.data = new std::string;
29490 9740 : nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data));
29491 :
29492 9740 : if (!sem_.add_element(nse))
29493 : {
29494 0 : set_error(make_error(
29495 : parser_error::e_syntax,
29496 0 : current_token(),
29497 : "ERR173 - Failed to add new local string variable '" + str_name + "' to SEM",
29498 : exprtk_error_location));
29499 :
29500 0 : free_node(node_allocator_,initialisation_expression);
29501 :
29502 0 : sem_.free_element(nse);
29503 :
29504 0 : return error_node();
29505 : }
29506 :
29507 9740 : str_node = nse.str_node;
29508 :
29509 : exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str()));
29510 9740 : }
29511 :
29512 9820 : lodge_symbol(str_name, e_st_local_string);
29513 :
29514 19640 : state_.activate_side_effect("parse_define_string_statement()");
29515 :
29516 9820 : expression_node_ptr branch[2] = {0};
29517 :
29518 9820 : branch[0] = str_node;
29519 9820 : branch[1] = initialisation_expression;
29520 :
29521 9820 : return expression_generator_(details::e_assign,branch);
29522 : }
29523 : #else
29524 : inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
29525 : {
29526 : return error_node();
29527 : }
29528 : #endif
29529 :
29530 82250 : inline bool local_variable_is_shadowed(const std::string& symbol)
29531 : {
29532 82250 : const scope_element& se = sem_.get_element(symbol);
29533 82250 : return (se.name == symbol) && se.active;
29534 : }
29535 :
29536 79605 : inline expression_node_ptr parse_define_var_statement()
29537 : {
29538 79605 : if (settings_.vardef_disabled())
29539 : {
29540 0 : set_error(make_error(
29541 : parser_error::e_syntax,
29542 0 : current_token(),
29543 : "ERR174 - Illegal variable definition",
29544 : exprtk_error_location));
29545 :
29546 0 : return error_node();
29547 : }
29548 159210 : else if (!details::imatch(current_token().value,"var"))
29549 : {
29550 0 : return error_node();
29551 : }
29552 : else
29553 79605 : next_token();
29554 :
29555 79605 : const std::string var_name = current_token().value;
29556 :
29557 79605 : expression_node_ptr initialisation_expression = error_node();
29558 :
29559 79605 : if (!token_is(token_t::e_symbol))
29560 : {
29561 0 : set_error(make_error(
29562 : parser_error::e_syntax,
29563 0 : current_token(),
29564 : "ERR175 - Expected a symbol for variable definition",
29565 : exprtk_error_location));
29566 :
29567 0 : return error_node();
29568 : }
29569 79605 : else if (details::is_reserved_symbol(var_name))
29570 : {
29571 0 : set_error(make_error(
29572 : parser_error::e_syntax,
29573 0 : current_token(),
29574 : "ERR176 - Illegal redefinition of reserved keyword: '" + var_name + "'",
29575 : exprtk_error_location));
29576 :
29577 0 : return error_node();
29578 : }
29579 79605 : else if (symtab_store_.symbol_exists(var_name))
29580 : {
29581 0 : set_error(make_error(
29582 : parser_error::e_syntax,
29583 0 : current_token(),
29584 : "ERR177 - Illegal redefinition of variable '" + var_name + "'",
29585 : exprtk_error_location));
29586 :
29587 0 : return error_node();
29588 : }
29589 79605 : else if (local_variable_is_shadowed(var_name))
29590 : {
29591 0 : set_error(make_error(
29592 : parser_error::e_syntax,
29593 0 : current_token(),
29594 : "ERR178 - Illegal redefinition of local variable: '" + var_name + "'",
29595 : exprtk_error_location));
29596 :
29597 0 : return error_node();
29598 : }
29599 79605 : else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
29600 : {
29601 24277 : return parse_define_vector_statement(var_name);
29602 : }
29603 55328 : else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
29604 : {
29605 2140 : return parse_uninitialised_var_statement(var_name);
29606 : }
29607 53188 : else if (token_is(token_t::e_assign))
29608 : {
29609 53115 : if (0 == (initialisation_expression = parse_expression()))
29610 : {
29611 0 : set_error(make_error(
29612 : parser_error::e_syntax,
29613 0 : current_token(),
29614 : "ERR179 - Failed to parse initialisation expression",
29615 : exprtk_error_location));
29616 :
29617 0 : return error_node();
29618 : }
29619 : }
29620 :
29621 53188 : if (
29622 53188 : !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
29623 105246 : !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
29624 105246 : !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
29625 : )
29626 : {
29627 52058 : if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
29628 : {
29629 0 : set_error(make_error(
29630 : parser_error::e_syntax,
29631 0 : current_token(),
29632 : "ERR180 - Expected ';' after variable definition",
29633 : exprtk_error_location));
29634 :
29635 0 : free_node(node_allocator_,initialisation_expression);
29636 :
29637 0 : return error_node();
29638 : }
29639 : }
29640 :
29641 53188 : if (
29642 106303 : (0 != initialisation_expression) &&
29643 53115 : details::is_generally_string_node(initialisation_expression)
29644 : )
29645 : {
29646 9820 : return parse_define_string_statement(var_name,initialisation_expression);
29647 : }
29648 :
29649 43368 : expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
29650 :
29651 43368 : scope_element& se = sem_.get_element(var_name);
29652 :
29653 43368 : if (se.name == var_name)
29654 : {
29655 1041 : if (se.active)
29656 : {
29657 0 : set_error(make_error(
29658 : parser_error::e_syntax,
29659 0 : current_token(),
29660 : "ERR181 - Illegal redefinition of local variable: '" + var_name + "'",
29661 : exprtk_error_location));
29662 :
29663 0 : free_node(node_allocator_, initialisation_expression);
29664 :
29665 0 : return error_node();
29666 : }
29667 1041 : else if (scope_element::e_variable == se.type)
29668 : {
29669 561 : var_node = se.var_node;
29670 561 : se.active = true;
29671 561 : se.depth = state_.scope_depth;
29672 561 : se.ref_count++;
29673 : }
29674 : }
29675 :
29676 43368 : if (0 == var_node)
29677 : {
29678 42807 : scope_element nse;
29679 42807 : nse.name = var_name;
29680 42807 : nse.active = true;
29681 42807 : nse.ref_count = 1;
29682 42807 : nse.type = scope_element::e_variable;
29683 42807 : nse.depth = state_.scope_depth;
29684 42807 : nse.data = new T(T(0));
29685 42807 : nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
29686 :
29687 42807 : if (!sem_.add_element(nse))
29688 : {
29689 0 : set_error(make_error(
29690 : parser_error::e_syntax,
29691 0 : current_token(),
29692 : "ERR182 - Failed to add new local variable '" + var_name + "' to SEM",
29693 : exprtk_error_location));
29694 :
29695 0 : free_node(node_allocator_, initialisation_expression);
29696 :
29697 0 : sem_.free_element(nse);
29698 :
29699 0 : return error_node();
29700 : }
29701 :
29702 42807 : var_node = nse.var_node;
29703 :
29704 : exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str()));
29705 42807 : }
29706 :
29707 86736 : state_.activate_side_effect("parse_define_var_statement()");
29708 :
29709 43368 : lodge_symbol(var_name, e_st_local_variable);
29710 :
29711 43368 : expression_node_ptr branch[2] = {0};
29712 :
29713 43368 : branch[0] = var_node;
29714 43368 : branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
29715 :
29716 43368 : return expression_generator_(details::e_assign,branch);
29717 79605 : }
29718 :
29719 2645 : inline expression_node_ptr parse_define_constvar_statement()
29720 : {
29721 2645 : if (settings_.vardef_disabled())
29722 : {
29723 0 : set_error(make_error(
29724 : parser_error::e_syntax,
29725 0 : current_token(),
29726 : "ERR183 - Illegal const variable definition",
29727 : exprtk_error_location));
29728 :
29729 0 : return error_node();
29730 : }
29731 7935 : else if (!token_is("const"))
29732 : {
29733 0 : set_error(make_error(
29734 : parser_error::e_syntax,
29735 0 : current_token(),
29736 : "ERR184 - Expected 'const' keyword for const-variable definition",
29737 : exprtk_error_location));
29738 :
29739 0 : return error_node();
29740 : }
29741 7935 : else if (!token_is("var"))
29742 : {
29743 0 : set_error(make_error(
29744 : parser_error::e_syntax,
29745 0 : current_token(),
29746 : "ERR185 - Expected 'var' keyword for const-variable definition",
29747 : exprtk_error_location));
29748 :
29749 0 : return error_node();
29750 : }
29751 :
29752 2645 : const std::string var_name = current_token().value;
29753 :
29754 2645 : expression_node_ptr initialisation_expression = error_node();
29755 :
29756 2645 : if (!token_is(token_t::e_symbol))
29757 : {
29758 0 : set_error(make_error(
29759 : parser_error::e_syntax,
29760 0 : current_token(),
29761 : "ERR186 - Expected a symbol for const-variable definition",
29762 : exprtk_error_location));
29763 :
29764 0 : return error_node();
29765 : }
29766 2645 : else if (details::is_reserved_symbol(var_name))
29767 : {
29768 0 : set_error(make_error(
29769 : parser_error::e_syntax,
29770 0 : current_token(),
29771 : "ERR187 - Illegal redefinition of reserved keyword: '" + var_name + "'",
29772 : exprtk_error_location));
29773 :
29774 0 : return error_node();
29775 : }
29776 2645 : else if (symtab_store_.symbol_exists(var_name))
29777 : {
29778 0 : set_error(make_error(
29779 : parser_error::e_syntax,
29780 0 : current_token(),
29781 : "ERR188 - Illegal redefinition of variable '" + var_name + "'",
29782 : exprtk_error_location));
29783 :
29784 0 : return error_node();
29785 : }
29786 2645 : else if (local_variable_is_shadowed(var_name))
29787 : {
29788 0 : set_error(make_error(
29789 : parser_error::e_syntax,
29790 0 : current_token(),
29791 : "ERR189 - Illegal redefinition of local variable: '" + var_name + "'",
29792 : exprtk_error_location));
29793 :
29794 0 : return error_node();
29795 : }
29796 2645 : else if (token_is(token_t::e_assign))
29797 : {
29798 2645 : if (0 == (initialisation_expression = parse_expression()))
29799 : {
29800 0 : set_error(make_error(
29801 : parser_error::e_syntax,
29802 0 : current_token(),
29803 : "ERR190 - Failed to parse initialisation expression for const-variable: '" + var_name + "'",
29804 : exprtk_error_location));
29805 :
29806 0 : return error_node();
29807 : }
29808 2645 : else if (!details::is_literal_node(initialisation_expression))
29809 : {
29810 0 : set_error(make_error(
29811 : parser_error::e_syntax,
29812 0 : current_token(),
29813 : "ERR191 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal",
29814 : exprtk_error_location));
29815 :
29816 0 : free_node(node_allocator_, initialisation_expression);
29817 :
29818 0 : return error_node();
29819 : }
29820 : }
29821 :
29822 2645 : const T init_value = initialisation_expression->value();
29823 :
29824 2645 : free_node(node_allocator_, initialisation_expression);
29825 :
29826 2645 : expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
29827 :
29828 2645 : scope_element& se = sem_.get_element(var_name);
29829 :
29830 2645 : if (se.name == var_name)
29831 : {
29832 10 : if (se.active)
29833 : {
29834 0 : set_error(make_error(
29835 : parser_error::e_syntax,
29836 0 : current_token(),
29837 : "ERR192 - Illegal redefinition of local variable: '" + var_name + "'",
29838 : exprtk_error_location));
29839 :
29840 0 : return error_node();
29841 : }
29842 10 : else if (scope_element::e_literal == se.type)
29843 : {
29844 10 : var_node = se.var_node;
29845 10 : se.active = true;
29846 10 : se.depth = state_.scope_depth;
29847 10 : se.ref_count++;
29848 : }
29849 : }
29850 :
29851 2645 : if (0 == var_node)
29852 : {
29853 2635 : scope_element nse;
29854 2635 : nse.name = var_name;
29855 2635 : nse.active = true;
29856 2635 : nse.ref_count = 1;
29857 2635 : nse.type = scope_element::e_literal;
29858 2635 : nse.depth = state_.scope_depth;
29859 2635 : nse.data = 0;
29860 2635 : nse.var_node = node_allocator_.allocate<literal_node_t>(init_value);
29861 :
29862 2635 : if (!sem_.add_element(nse))
29863 : {
29864 0 : set_error(make_error(
29865 : parser_error::e_syntax,
29866 0 : current_token(),
29867 : "ERR193 - Failed to add new local const-variable '" + var_name + "' to SEM",
29868 : exprtk_error_location));
29869 :
29870 0 : sem_.free_element(nse);
29871 :
29872 0 : return error_node();
29873 : }
29874 :
29875 2635 : var_node = nse.var_node;
29876 :
29877 : exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str()));
29878 2635 : }
29879 :
29880 5290 : state_.activate_side_effect("parse_define_constvar_statement()");
29881 :
29882 2645 : lodge_symbol(var_name, e_st_local_variable);
29883 :
29884 2645 : return expression_generator_(var_node->value());
29885 2645 : }
29886 :
29887 2140 : inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
29888 : {
29889 2140 : if (
29890 4280 : !token_is(token_t::e_lcrlbracket) ||
29891 4280 : !token_is(token_t::e_rcrlbracket)
29892 : )
29893 : {
29894 0 : set_error(make_error(
29895 : parser_error::e_syntax,
29896 0 : current_token(),
29897 : "ERR194 - Expected a '{}' for uninitialised var definition",
29898 : exprtk_error_location));
29899 :
29900 0 : return error_node();
29901 : }
29902 2140 : else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
29903 : {
29904 0 : set_error(make_error(
29905 : parser_error::e_syntax,
29906 0 : current_token(),
29907 : "ERR195 - Expected ';' after uninitialised variable definition",
29908 : exprtk_error_location));
29909 :
29910 0 : return error_node();
29911 : }
29912 :
29913 2140 : expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
29914 :
29915 2140 : scope_element& se = sem_.get_element(var_name);
29916 :
29917 2140 : if (se.name == var_name)
29918 : {
29919 0 : if (se.active)
29920 : {
29921 0 : set_error(make_error(
29922 : parser_error::e_syntax,
29923 0 : current_token(),
29924 : "ERR196 - Illegal redefinition of local variable: '" + var_name + "'",
29925 : exprtk_error_location));
29926 :
29927 0 : return error_node();
29928 : }
29929 0 : else if (scope_element::e_variable == se.type)
29930 : {
29931 0 : var_node = se.var_node;
29932 0 : se.active = true;
29933 0 : se.ref_count++;
29934 : }
29935 : }
29936 :
29937 2140 : if (0 == var_node)
29938 : {
29939 2140 : scope_element nse;
29940 2140 : nse.name = var_name;
29941 2140 : nse.active = true;
29942 2140 : nse.ref_count = 1;
29943 2140 : nse.type = scope_element::e_variable;
29944 2140 : nse.depth = state_.scope_depth;
29945 2140 : nse.ip_index = sem_.next_ip_index();
29946 2140 : nse.data = new T(T(0));
29947 2140 : nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
29948 :
29949 2140 : if (!sem_.add_element(nse))
29950 : {
29951 0 : set_error(make_error(
29952 : parser_error::e_syntax,
29953 0 : current_token(),
29954 : "ERR197 - Failed to add new local variable '" + var_name + "' to SEM",
29955 : exprtk_error_location));
29956 :
29957 0 : sem_.free_element(nse);
29958 :
29959 0 : return error_node();
29960 : }
29961 :
29962 : exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
29963 : nse.name.c_str()));
29964 2140 : }
29965 :
29966 2140 : lodge_symbol(var_name, e_st_local_variable);
29967 :
29968 4280 : state_.activate_side_effect("parse_uninitialised_var_statement()");
29969 :
29970 2140 : return expression_generator_(T(0));
29971 : }
29972 :
29973 560 : inline expression_node_ptr parse_swap_statement()
29974 : {
29975 1120 : if (!details::imatch(current_token().value,"swap"))
29976 : {
29977 0 : return error_node();
29978 : }
29979 : else
29980 560 : next_token();
29981 :
29982 560 : if (!token_is(token_t::e_lbracket))
29983 : {
29984 0 : set_error(make_error(
29985 : parser_error::e_syntax,
29986 0 : current_token(),
29987 : "ERR198 - Expected '(' at start of swap statement",
29988 : exprtk_error_location));
29989 :
29990 0 : return error_node();
29991 : }
29992 :
29993 560 : expression_node_ptr variable0 = error_node();
29994 560 : expression_node_ptr variable1 = error_node();
29995 :
29996 560 : bool variable0_generated = false;
29997 560 : bool variable1_generated = false;
29998 :
29999 560 : const std::string var0_name = current_token().value;
30000 :
30001 560 : if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
30002 : {
30003 0 : set_error(make_error(
30004 : parser_error::e_syntax,
30005 0 : current_token(),
30006 : "ERR199 - Expected a symbol for variable or vector element definition",
30007 : exprtk_error_location));
30008 :
30009 0 : return error_node();
30010 : }
30011 560 : else if (peek_token_is(token_t::e_lsqrbracket))
30012 : {
30013 360 : if (0 == (variable0 = parse_vector()))
30014 : {
30015 0 : set_error(make_error(
30016 : parser_error::e_syntax,
30017 0 : current_token(),
30018 : "ERR200 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
30019 : exprtk_error_location));
30020 :
30021 0 : return error_node();
30022 : }
30023 :
30024 360 : variable0_generated = true;
30025 : }
30026 : else
30027 : {
30028 200 : if (symtab_store_.is_variable(var0_name))
30029 : {
30030 0 : variable0 = symtab_store_.get_variable(var0_name);
30031 : }
30032 :
30033 200 : const scope_element& se = sem_.get_element(var0_name);
30034 :
30035 200 : if (
30036 200 : (se.active) &&
30037 400 : (se.name == var0_name) &&
30038 200 : (scope_element::e_variable == se.type)
30039 : )
30040 : {
30041 200 : variable0 = se.var_node;
30042 : }
30043 :
30044 200 : lodge_symbol(var0_name, e_st_variable);
30045 :
30046 200 : if (0 == variable0)
30047 : {
30048 0 : set_error(make_error(
30049 : parser_error::e_syntax,
30050 0 : current_token(),
30051 : "ERR201 - First parameter to swap is an invalid variable: '" + var0_name + "'",
30052 : exprtk_error_location));
30053 :
30054 0 : return error_node();
30055 : }
30056 : else
30057 200 : next_token();
30058 : }
30059 :
30060 560 : if (!token_is(token_t::e_comma))
30061 : {
30062 0 : set_error(make_error(
30063 : parser_error::e_syntax,
30064 0 : current_token(),
30065 : "ERR202 - Expected ',' between parameters to swap",
30066 : exprtk_error_location));
30067 :
30068 0 : if (variable0_generated)
30069 : {
30070 0 : free_node(node_allocator_,variable0);
30071 : }
30072 :
30073 0 : return error_node();
30074 : }
30075 :
30076 560 : const std::string var1_name = current_token().value;
30077 :
30078 560 : if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
30079 : {
30080 0 : set_error(make_error(
30081 : parser_error::e_syntax,
30082 0 : current_token(),
30083 : "ERR203 - Expected a symbol for variable or vector element definition",
30084 : exprtk_error_location));
30085 :
30086 0 : if (variable0_generated)
30087 : {
30088 0 : free_node(node_allocator_,variable0);
30089 : }
30090 :
30091 0 : return error_node();
30092 : }
30093 560 : else if (peek_token_is(token_t::e_lsqrbracket))
30094 : {
30095 360 : if (0 == (variable1 = parse_vector()))
30096 : {
30097 0 : set_error(make_error(
30098 : parser_error::e_syntax,
30099 0 : current_token(),
30100 : "ERR204 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
30101 : exprtk_error_location));
30102 :
30103 0 : if (variable0_generated)
30104 : {
30105 0 : free_node(node_allocator_,variable0);
30106 : }
30107 :
30108 0 : return error_node();
30109 : }
30110 :
30111 360 : variable1_generated = true;
30112 : }
30113 : else
30114 : {
30115 200 : if (symtab_store_.is_variable(var1_name))
30116 : {
30117 0 : variable1 = symtab_store_.get_variable(var1_name);
30118 : }
30119 :
30120 200 : const scope_element& se = sem_.get_element(var1_name);
30121 :
30122 200 : if (
30123 200 : (se.active) &&
30124 400 : (se.name == var1_name) &&
30125 200 : (scope_element::e_variable == se.type)
30126 : )
30127 : {
30128 200 : variable1 = se.var_node;
30129 : }
30130 :
30131 200 : lodge_symbol(var1_name, e_st_variable);
30132 :
30133 200 : if (0 == variable1)
30134 : {
30135 0 : set_error(make_error(
30136 : parser_error::e_syntax,
30137 0 : current_token(),
30138 : "ERR205 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
30139 : exprtk_error_location));
30140 :
30141 0 : if (variable0_generated)
30142 : {
30143 0 : free_node(node_allocator_,variable0);
30144 : }
30145 :
30146 0 : return error_node();
30147 : }
30148 : else
30149 200 : next_token();
30150 : }
30151 :
30152 560 : if (!token_is(token_t::e_rbracket))
30153 : {
30154 0 : set_error(make_error(
30155 : parser_error::e_syntax,
30156 0 : current_token(),
30157 : "ERR206 - Expected ')' at end of swap statement",
30158 : exprtk_error_location));
30159 :
30160 0 : if (variable0_generated)
30161 : {
30162 0 : free_node(node_allocator_,variable0);
30163 : }
30164 :
30165 0 : if (variable1_generated)
30166 : {
30167 0 : free_node(node_allocator_,variable1);
30168 : }
30169 :
30170 0 : return error_node();
30171 : }
30172 :
30173 : typedef details::variable_node<T>* variable_node_ptr;
30174 :
30175 560 : variable_node_ptr v0 = variable_node_ptr(0);
30176 560 : variable_node_ptr v1 = variable_node_ptr(0);
30177 :
30178 560 : expression_node_ptr result = error_node();
30179 :
30180 560 : if (
30181 880 : (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
30182 320 : (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
30183 : )
30184 : {
30185 240 : result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
30186 :
30187 240 : if (variable0_generated)
30188 : {
30189 120 : free_node(node_allocator_,variable0);
30190 : }
30191 :
30192 240 : if (variable1_generated)
30193 : {
30194 120 : free_node(node_allocator_,variable1);
30195 : }
30196 : }
30197 : else
30198 : result = node_allocator_.allocate<details::swap_generic_node<T> >
30199 320 : (variable0, variable1);
30200 :
30201 1120 : state_.activate_side_effect("parse_swap_statement()");
30202 :
30203 560 : return result;
30204 560 : }
30205 :
30206 : #ifndef exprtk_disable_return_statement
30207 116 : inline expression_node_ptr parse_return_statement()
30208 : {
30209 116 : if (state_.parsing_return_stmt)
30210 : {
30211 0 : set_error(make_error(
30212 : parser_error::e_syntax,
30213 0 : current_token(),
30214 : "ERR207 - Return call within a return call is not allowed",
30215 : exprtk_error_location));
30216 :
30217 0 : return error_node();
30218 : }
30219 :
30220 116 : scoped_bool_negator sbn(state_.parsing_return_stmt);
30221 :
30222 116 : std::vector<expression_node_ptr> arg_list;
30223 :
30224 116 : scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
30225 :
30226 232 : if (!details::imatch(current_token().value,"return"))
30227 : {
30228 0 : return error_node();
30229 : }
30230 : else
30231 116 : next_token();
30232 :
30233 116 : if (!token_is(token_t::e_lsqrbracket))
30234 : {
30235 0 : set_error(make_error(
30236 : parser_error::e_syntax,
30237 0 : current_token(),
30238 : "ERR208 - Expected '[' at start of return statement",
30239 : exprtk_error_location));
30240 :
30241 0 : return error_node();
30242 : }
30243 116 : else if (!token_is(token_t::e_rsqrbracket))
30244 : {
30245 32 : for ( ; ; )
30246 : {
30247 147 : expression_node_ptr arg = parse_expression();
30248 :
30249 147 : if (0 == arg)
30250 0 : return error_node();
30251 :
30252 147 : arg_list.push_back(arg);
30253 :
30254 147 : if (token_is(token_t::e_rsqrbracket))
30255 115 : break;
30256 32 : else if (!token_is(token_t::e_comma))
30257 : {
30258 0 : set_error(make_error(
30259 : parser_error::e_syntax,
30260 0 : current_token(),
30261 : "ERR209 - Expected ',' between values during call to return",
30262 : exprtk_error_location));
30263 :
30264 0 : return error_node();
30265 : }
30266 : }
30267 : }
30268 1 : else if (settings_.zero_return_disabled())
30269 : {
30270 0 : set_error(make_error(
30271 : parser_error::e_syntax,
30272 0 : current_token(),
30273 : "ERR210 - Zero parameter return statement not allowed",
30274 : exprtk_error_location));
30275 :
30276 0 : return error_node();
30277 : }
30278 :
30279 116 : const lexer::token prev_token = current_token();
30280 :
30281 116 : if (token_is(token_t::e_rsqrbracket))
30282 : {
30283 0 : if (!arg_list.empty())
30284 : {
30285 0 : set_error(make_error(
30286 : parser_error::e_syntax,
30287 : prev_token,
30288 : "ERR211 - Invalid ']' found during return call",
30289 : exprtk_error_location));
30290 :
30291 0 : return error_node();
30292 : }
30293 : }
30294 :
30295 116 : std::string ret_param_type_list;
30296 :
30297 263 : for (std::size_t i = 0; i < arg_list.size(); ++i)
30298 : {
30299 147 : if (0 == arg_list[i])
30300 0 : return error_node();
30301 147 : else if (is_ivector_node(arg_list[i]))
30302 1 : ret_param_type_list += 'V';
30303 146 : else if (is_generally_string_node(arg_list[i]))
30304 16 : ret_param_type_list += 'S';
30305 : else
30306 130 : ret_param_type_list += 'T';
30307 : }
30308 :
30309 116 : dec_.retparam_list_.push_back(ret_param_type_list);
30310 :
30311 116 : expression_node_ptr result = expression_generator_.return_call(arg_list);
30312 :
30313 116 : sdd.delete_ptr = (0 == result);
30314 :
30315 116 : state_.return_stmt_present = true;
30316 :
30317 232 : state_.activate_side_effect("parse_return_statement()");
30318 :
30319 116 : return result;
30320 116 : }
30321 : #else
30322 : inline expression_node_ptr parse_return_statement()
30323 : {
30324 : return error_node();
30325 : }
30326 : #endif
30327 :
30328 108 : inline expression_node_ptr parse_assert_statement()
30329 : {
30330 108 : assert(details::imatch(current_token().value, "assert"));
30331 :
30332 108 : if (state_.parsing_assert_stmt)
30333 : {
30334 0 : set_error(make_error(
30335 : parser_error::e_syntax,
30336 0 : current_token(),
30337 : "ERR212 - Assert statement within an assert statement is not allowed",
30338 : exprtk_error_location));
30339 :
30340 0 : return error_node();
30341 : }
30342 :
30343 108 : scoped_bool_negator sbn(state_.parsing_assert_stmt);
30344 :
30345 108 : next_token();
30346 :
30347 108 : std::vector<expression_node_ptr> assert_arg_list(3, error_node());
30348 108 : scoped_vec_delete<expression_node_t> sdd((*this), assert_arg_list);
30349 :
30350 108 : expression_node_ptr& assert_condition = assert_arg_list[0];
30351 108 : expression_node_ptr& assert_message = assert_arg_list[1];
30352 108 : expression_node_ptr& assert_id = assert_arg_list[2];
30353 :
30354 108 : if (!token_is(token_t::e_lbracket))
30355 : {
30356 0 : set_error(make_error(
30357 : parser_error::e_syntax,
30358 0 : current_token(),
30359 : "ERR213 - Expected '(' at start of assert statement",
30360 : exprtk_error_location));
30361 :
30362 0 : return error_node();
30363 : }
30364 :
30365 108 : const token_t start_token = current_token();
30366 :
30367 : // Parse the assert condition
30368 108 : if (0 == (assert_condition = parse_expression()))
30369 : {
30370 0 : set_error(make_error(
30371 : parser_error::e_syntax,
30372 0 : current_token(),
30373 : "ERR214 - Failed to parse condition for assert statement",
30374 : exprtk_error_location));
30375 :
30376 0 : return error_node();
30377 : }
30378 :
30379 108 : const token_t end_token = current_token();
30380 :
30381 108 : if (!token_is(token_t::e_rbracket))
30382 : {
30383 90 : if (!token_is(token_t::e_comma))
30384 : {
30385 0 : set_error(make_error(
30386 : parser_error::e_syntax,
30387 0 : current_token(),
30388 : "ERR215 - Expected ',' between condition and message for assert statement",
30389 : exprtk_error_location));
30390 :
30391 0 : return error_node();
30392 : }
30393 : // Parse the assert message
30394 90 : else if (
30395 180 : (0 == (assert_message = parse_expression())) ||
30396 90 : !details::is_generally_string_node(assert_message)
30397 : )
30398 : {
30399 0 : set_error(make_error(
30400 : parser_error::e_syntax,
30401 0 : current_token(),
30402 : "ERR216 - " +
30403 0 : (assert_message ?
30404 : std::string("Expected string for assert message") :
30405 : std::string("Failed to parse message for assert statement")),
30406 : exprtk_error_location));
30407 :
30408 0 : return error_node();
30409 : }
30410 90 : else if (!token_is(token_t::e_rbracket))
30411 : {
30412 36 : if (!token_is(token_t::e_comma))
30413 : {
30414 0 : set_error(make_error(
30415 : parser_error::e_syntax,
30416 0 : current_token(),
30417 : "ERR217 - Expected ',' between message and ID for assert statement",
30418 : exprtk_error_location));
30419 :
30420 0 : return error_node();
30421 : }
30422 : // Parse assert ID
30423 36 : else if (
30424 72 : (0 == (assert_id = parse_expression())) ||
30425 36 : !details::is_const_string_node(assert_id)
30426 : )
30427 : {
30428 0 : set_error(make_error(
30429 : parser_error::e_syntax,
30430 0 : current_token(),
30431 : "ERR218 - " +
30432 0 : (assert_id ?
30433 : std::string("Expected literal string for assert ID") :
30434 : std::string("Failed to parse string for assert ID")),
30435 : exprtk_error_location));
30436 :
30437 0 : return error_node();
30438 : }
30439 36 : else if (!token_is(token_t::e_rbracket))
30440 : {
30441 0 : set_error(make_error(
30442 : parser_error::e_syntax,
30443 0 : current_token(),
30444 : "ERR219 - Expected ')' at start of assert statement",
30445 : exprtk_error_location));
30446 :
30447 0 : return error_node();
30448 : }
30449 : }
30450 : }
30451 :
30452 108 : exprtk::assert_check::assert_context context;
30453 108 : context.condition = lexer().substr(start_token.position, end_token.position);
30454 108 : context.offet = start_token.position;
30455 :
30456 108 : if (0 == assert_check_)
30457 : {
30458 : exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n",
30459 : context.condition.c_str()));
30460 :
30461 24 : return new details::null_node<T>();
30462 : }
30463 :
30464 : #ifndef exprtk_disable_string_capabilities
30465 84 : if (assert_message && details::is_const_string_node(assert_message))
30466 : {
30467 70 : context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str();
30468 : }
30469 :
30470 84 : if (assert_id && details::is_const_string_node(assert_id))
30471 : {
30472 28 : context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str();
30473 :
30474 28 : if (assert_ids_.end() != assert_ids_.find(context.id))
30475 : {
30476 0 : set_error(make_error(
30477 : parser_error::e_syntax,
30478 0 : current_token(),
30479 : "ERR220 - Duplicate assert ID: " + context.id,
30480 : exprtk_error_location));
30481 :
30482 0 : return error_node();
30483 : }
30484 :
30485 28 : assert_ids_.insert(context.id);
30486 28 : free_node(node_allocator_, assert_id);
30487 : }
30488 : #endif
30489 :
30490 : expression_node_ptr result_node =
30491 84 : expression_generator_.assert_call(
30492 : assert_condition,
30493 : assert_message,
30494 : context);
30495 :
30496 : exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() ));
30497 : exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() ));
30498 : exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() ));
30499 : exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet)));
30500 :
30501 84 : if (0 == result_node)
30502 : {
30503 0 : set_error(make_error(
30504 : parser_error::e_syntax,
30505 0 : current_token(),
30506 : "ERR221 - Failed to synthesize assert",
30507 : exprtk_error_location));
30508 :
30509 0 : return error_node();
30510 : }
30511 :
30512 84 : sdd.delete_ptr = false;
30513 84 : return result_node;
30514 108 : }
30515 :
30516 1859554 : inline bool post_variable_process(const std::string& symbol)
30517 : {
30518 1859554 : if (
30519 3718684 : peek_token_is(token_t::e_lbracket ) ||
30520 3718684 : peek_token_is(token_t::e_lcrlbracket) ||
30521 3718684 : peek_token_is(token_t::e_lsqrbracket)
30522 : )
30523 : {
30524 426 : if (!settings_.commutative_check_enabled())
30525 : {
30526 0 : set_error(make_error(
30527 : parser_error::e_syntax,
30528 0 : current_token(),
30529 : "ERR222 - Invalid sequence of variable '" + symbol + "' and bracket",
30530 : exprtk_error_location));
30531 :
30532 0 : return false;
30533 : }
30534 :
30535 426 : lexer().insert_front(token_t::e_mul);
30536 : }
30537 :
30538 1859554 : return true;
30539 : }
30540 :
30541 1724379 : inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
30542 : {
30543 1724379 : bool implied_mul = false;
30544 :
30545 1724379 : if (details::is_generally_string_node(branch))
30546 9869 : return true;
30547 :
30548 1714510 : const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
30549 :
30550 1714510 : switch (token)
30551 : {
30552 2145 : case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) ||
30553 3810 : token_is(token_t::e_lcrlbracket, hold) ||
30554 1665 : token_is(token_t::e_lsqrbracket, hold) ;
30555 2145 : break;
30556 :
30557 1706280 : case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) ||
30558 3412080 : token_is(token_t::e_lcrlbracket, hold) ||
30559 1705800 : token_is(token_t::e_lsqrbracket, hold) ;
30560 1706280 : break;
30561 :
30562 6085 : case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) ||
30563 12170 : token_is(token_t::e_lcrlbracket, hold) ||
30564 6085 : token_is(token_t::e_lsqrbracket, hold) ;
30565 6085 : break;
30566 :
30567 0 : default : return true;
30568 : }
30569 :
30570 1714510 : if (implied_mul)
30571 : {
30572 2100 : if (!settings_.commutative_check_enabled())
30573 : {
30574 0 : set_error(make_error(
30575 : parser_error::e_syntax,
30576 0 : current_token(),
30577 : "ERR223 - Invalid sequence of brackets",
30578 : exprtk_error_location));
30579 :
30580 0 : return false;
30581 : }
30582 2100 : else if (token_t::e_eof != current_token().type)
30583 : {
30584 2100 : lexer().insert_front(current_token().type);
30585 2100 : lexer().insert_front(token_t::e_mul);
30586 2100 : next_token();
30587 : }
30588 : }
30589 :
30590 1714510 : return true;
30591 : }
30592 :
30593 : typedef typename interval_container_t<const void*>::interval_t interval_t;
30594 : typedef interval_container_t<const void*> immutable_memory_map_t;
30595 : typedef std::map<interval_t,token_t> immutable_symtok_map_t;
30596 :
30597 18 : inline interval_t make_memory_range(const T& t)
30598 : {
30599 18 : const T* begin = reinterpret_cast<const T*>(&t);
30600 18 : const T* end = begin + 1;
30601 18 : return interval_t(begin, end);
30602 : }
30603 :
30604 13 : inline interval_t make_memory_range(const T* begin, const std::size_t size)
30605 : {
30606 13 : return interval_t(begin, begin + size);
30607 : }
30608 :
30609 24 : inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size)
30610 : {
30611 24 : return interval_t(begin, begin + size);
30612 : }
30613 :
30614 55 : void lodge_immutable_symbol(const lexer::token& token, const interval_t interval)
30615 : {
30616 55 : immutable_memory_map_.add_interval(interval);
30617 55 : immutable_symtok_map_[interval] = token;
30618 55 : }
30619 :
30620 2057676 : inline expression_node_ptr parse_symtab_symbol()
30621 : {
30622 2057676 : const std::string symbol = current_token().value;
30623 :
30624 : // Are we dealing with a variable or a special constant?
30625 : typedef typename symtab_store::variable_context var_ctxt_t;
30626 2057676 : var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol);
30627 :
30628 2057676 : if (var_ctx.variable)
30629 : {
30630 1800665 : assert(var_ctx.symbol_table);
30631 :
30632 1800665 : expression_node_ptr result_variable = var_ctx.variable;
30633 :
30634 1800665 : if (symtab_store_.is_constant_node(symbol))
30635 : {
30636 43250 : result_variable = expression_generator_(var_ctx.variable->value());
30637 : }
30638 1757415 : else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability())
30639 : {
30640 18 : lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref()));
30641 18 : result_variable = var_ctx.variable;
30642 : }
30643 :
30644 1800665 : if (!post_variable_process(symbol))
30645 0 : return error_node();
30646 :
30647 1800665 : lodge_symbol(symbol, e_st_variable);
30648 :
30649 1800665 : next_token();
30650 :
30651 1800665 : return result_variable;
30652 : }
30653 :
30654 : // Are we dealing with a locally defined variable, vector or string?
30655 257011 : if (!sem_.empty())
30656 : {
30657 130535 : scope_element& se = sem_.get_active_element(symbol);
30658 :
30659 130535 : if (se.active && details::imatch(se.name, symbol))
30660 : {
30661 120510 : if (
30662 120510 : (scope_element::e_variable == se.type) ||
30663 68838 : (scope_element::e_literal == se.type)
30664 : )
30665 : {
30666 55887 : se.active = true;
30667 55887 : lodge_symbol(symbol, e_st_local_variable);
30668 :
30669 55887 : if (!post_variable_process(symbol))
30670 0 : return error_node();
30671 :
30672 55887 : next_token();
30673 :
30674 55887 : return (scope_element::e_variable == se.type) ?
30675 : se.var_node :
30676 55887 : expression_generator_(se.var_node->value());
30677 : }
30678 64623 : else if (scope_element::e_vector == se.type)
30679 : {
30680 45388 : return parse_vector();
30681 : }
30682 : #ifndef exprtk_disable_string_capabilities
30683 19235 : else if (scope_element::e_string == se.type)
30684 : {
30685 19235 : return parse_string();
30686 : }
30687 : #endif
30688 : }
30689 : }
30690 :
30691 : #ifndef exprtk_disable_string_capabilities
30692 : // Are we dealing with a string variable?
30693 136501 : if (symtab_store_.is_stringvar(symbol))
30694 : {
30695 49475 : return parse_string();
30696 : }
30697 : #endif
30698 :
30699 : {
30700 : // Are we dealing with a function?
30701 87026 : ifunction<T>* function = symtab_store_.get_function(symbol);
30702 :
30703 87026 : if (function)
30704 : {
30705 60611 : lodge_symbol(symbol, e_st_function);
30706 :
30707 : expression_node_ptr func_node =
30708 60611 : parse_function_invocation(function,symbol);
30709 :
30710 60611 : if (func_node)
30711 60611 : return func_node;
30712 : else
30713 : {
30714 0 : set_error(make_error(
30715 : parser_error::e_syntax,
30716 0 : current_token(),
30717 : "ERR224 - Failed to generate node for function: '" + symbol + "'",
30718 : exprtk_error_location));
30719 :
30720 0 : return error_node();
30721 : }
30722 : }
30723 : }
30724 :
30725 : {
30726 : // Are we dealing with a vararg function?
30727 26415 : ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
30728 :
30729 26415 : if (vararg_function)
30730 : {
30731 49 : lodge_symbol(symbol, e_st_function);
30732 :
30733 : expression_node_ptr vararg_func_node =
30734 49 : parse_vararg_function_call(vararg_function, symbol);
30735 :
30736 49 : if (vararg_func_node)
30737 49 : return vararg_func_node;
30738 : else
30739 : {
30740 0 : set_error(make_error(
30741 : parser_error::e_syntax,
30742 0 : current_token(),
30743 : "ERR225 - Failed to generate node for vararg function: '" + symbol + "'",
30744 : exprtk_error_location));
30745 :
30746 0 : return error_node();
30747 : }
30748 : }
30749 : }
30750 :
30751 : {
30752 : // Are we dealing with a vararg generic function?
30753 26366 : igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
30754 :
30755 26366 : if (generic_function)
30756 : {
30757 3500 : lodge_symbol(symbol, e_st_function);
30758 :
30759 : expression_node_ptr genericfunc_node =
30760 3500 : parse_generic_function_call(generic_function, symbol);
30761 :
30762 3500 : if (genericfunc_node)
30763 3500 : return genericfunc_node;
30764 : else
30765 : {
30766 0 : set_error(make_error(
30767 : parser_error::e_syntax,
30768 0 : current_token(),
30769 : "ERR226 - Failed to generate node for generic function: '" + symbol + "'",
30770 : exprtk_error_location));
30771 :
30772 0 : return error_node();
30773 : }
30774 : }
30775 : }
30776 :
30777 : #ifndef exprtk_disable_string_capabilities
30778 : {
30779 : // Are we dealing with a vararg string returning function?
30780 22866 : igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
30781 :
30782 22866 : if (string_function)
30783 : {
30784 36 : lodge_symbol(symbol, e_st_function);
30785 :
30786 : expression_node_ptr stringfunc_node =
30787 36 : parse_string_function_call(string_function, symbol);
30788 :
30789 36 : if (stringfunc_node)
30790 36 : return stringfunc_node;
30791 : else
30792 : {
30793 0 : set_error(make_error(
30794 : parser_error::e_syntax,
30795 0 : current_token(),
30796 : "ERR227 - Failed to generate node for string function: '" + symbol + "'",
30797 : exprtk_error_location));
30798 :
30799 0 : return error_node();
30800 : }
30801 : }
30802 : }
30803 :
30804 : {
30805 : // Are we dealing with a vararg overloaded scalar/string returning function?
30806 22830 : igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
30807 :
30808 22830 : if (overload_function)
30809 : {
30810 72 : lodge_symbol(symbol, e_st_function);
30811 :
30812 : expression_node_ptr overloadfunc_node =
30813 72 : parse_overload_function_call(overload_function, symbol);
30814 :
30815 72 : if (overloadfunc_node)
30816 72 : return overloadfunc_node;
30817 : else
30818 : {
30819 0 : set_error(make_error(
30820 : parser_error::e_syntax,
30821 0 : current_token(),
30822 : "ERR228 - Failed to generate node for overload function: '" + symbol + "'",
30823 : exprtk_error_location));
30824 :
30825 0 : return error_node();
30826 : }
30827 : }
30828 : }
30829 : #endif
30830 :
30831 : // Are we dealing with a vector?
30832 22758 : if (symtab_store_.is_vector(symbol))
30833 : {
30834 6869 : lodge_symbol(symbol, e_st_vector);
30835 6869 : return parse_vector();
30836 : }
30837 :
30838 15889 : if (details::is_reserved_symbol(symbol))
30839 : {
30840 23 : if (
30841 23 : settings_.function_enabled(symbol) ||
30842 0 : !details::is_base_function(symbol)
30843 : )
30844 : {
30845 46 : set_error(make_error(
30846 : parser_error::e_syntax,
30847 23 : current_token(),
30848 : "ERR229 - Invalid use of reserved symbol '" + symbol + "'",
30849 : exprtk_error_location));
30850 :
30851 23 : return error_node();
30852 : }
30853 : }
30854 :
30855 : // Should we handle unknown symbols?
30856 15866 : if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
30857 : {
30858 5208 : if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
30859 : {
30860 5208 : symbol_table_t& symtab = symtab_store_.get_symbol_table();
30861 :
30862 5208 : std::string error_message;
30863 :
30864 5208 : if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
30865 : {
30866 3002 : T default_value = T(0);
30867 :
30868 3002 : typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
30869 :
30870 3002 : if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
30871 : {
30872 3002 : bool create_result = false;
30873 :
30874 3002 : switch (usr_symbol_type)
30875 : {
30876 1502 : case unknown_symbol_resolver::e_usr_variable_type :
30877 1502 : create_result = symtab.create_variable(symbol, default_value);
30878 1502 : break;
30879 :
30880 1500 : case unknown_symbol_resolver::e_usr_constant_type :
30881 1500 : create_result = symtab.add_constant(symbol, default_value);
30882 1500 : break;
30883 :
30884 0 : default : create_result = false;
30885 : }
30886 :
30887 3002 : if (create_result)
30888 : {
30889 3002 : expression_node_ptr var = symtab_store_.get_variable(symbol);
30890 :
30891 3002 : if (var)
30892 : {
30893 3002 : if (symtab_store_.is_constant_node(symbol))
30894 : {
30895 1500 : var = expression_generator_(var->value());
30896 : }
30897 :
30898 3002 : lodge_symbol(symbol, e_st_variable);
30899 :
30900 3002 : if (!post_variable_process(symbol))
30901 3002 : return error_node();
30902 :
30903 3002 : next_token();
30904 :
30905 3002 : return var;
30906 : }
30907 : }
30908 : }
30909 :
30910 0 : set_error(make_error(
30911 : parser_error::e_symtab,
30912 0 : current_token(),
30913 : "ERR230 - Failed to create variable: '" + symbol + "'" +
30914 0 : (error_message.empty() ? "" : " - " + error_message),
30915 : exprtk_error_location));
30916 :
30917 : }
30918 2206 : else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
30919 : {
30920 2206 : if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
30921 : {
30922 2206 : expression_node_ptr result = parse_symtab_symbol();
30923 :
30924 2206 : if (result)
30925 : {
30926 2206 : return result;
30927 : }
30928 : }
30929 :
30930 0 : set_error(make_error(
30931 : parser_error::e_symtab,
30932 0 : current_token(),
30933 : "ERR231 - Failed to resolve symbol: '" + symbol + "'" +
30934 0 : (error_message.empty() ? "" : " - " + error_message),
30935 : exprtk_error_location));
30936 : }
30937 :
30938 0 : return error_node();
30939 5208 : }
30940 : }
30941 :
30942 21316 : set_error(make_error(
30943 : parser_error::e_syntax,
30944 10658 : current_token(),
30945 : "ERR232 - Undefined symbol: '" + symbol + "'",
30946 : exprtk_error_location));
30947 :
30948 10658 : return error_node();
30949 2057676 : }
30950 :
30951 2535008 : inline expression_node_ptr parse_symbol()
30952 : {
30953 2535010 : static const std::string symbol_if = "if" ;
30954 2535010 : static const std::string symbol_while = "while" ;
30955 2535010 : static const std::string symbol_repeat = "repeat" ;
30956 2535010 : static const std::string symbol_for = "for" ;
30957 2535010 : static const std::string symbol_switch = "switch" ;
30958 2535010 : static const std::string symbol_null = "null" ;
30959 2535010 : static const std::string symbol_break = "break" ;
30960 2535010 : static const std::string symbol_continue = "continue";
30961 2535010 : static const std::string symbol_var = "var" ;
30962 2535010 : static const std::string symbol_const = "const" ;
30963 2535010 : static const std::string symbol_swap = "swap" ;
30964 2535010 : static const std::string symbol_return = "return" ;
30965 2535010 : static const std::string symbol_not = "not" ;
30966 2535010 : static const std::string symbol_assert = "assert" ;
30967 :
30968 2535008 : const std::string symbol = current_token().value;
30969 :
30970 2535008 : if (valid_vararg_operation(symbol))
30971 : {
30972 22327 : return parse_vararg_function();
30973 : }
30974 2512681 : else if (details::imatch(symbol, symbol_not))
30975 : {
30976 728 : return parse_not_statement();
30977 : }
30978 2511953 : else if (valid_base_operation(symbol))
30979 : {
30980 358621 : return parse_base_operation();
30981 : }
30982 2153332 : else if (
30983 2158559 : details::imatch(symbol, symbol_if) &&
30984 5227 : settings_.control_struct_enabled(symbol)
30985 : )
30986 : {
30987 5227 : return parse_conditional_statement();
30988 : }
30989 2148105 : else if (
30990 2148127 : details::imatch(symbol, symbol_while) &&
30991 22 : settings_.control_struct_enabled(symbol)
30992 : )
30993 : {
30994 22 : return parse_while_loop();
30995 : }
30996 2148083 : else if (
30997 2148175 : details::imatch(symbol, symbol_repeat) &&
30998 92 : settings_.control_struct_enabled(symbol)
30999 : )
31000 : {
31001 92 : return parse_repeat_until_loop();
31002 : }
31003 2147991 : else if (
31004 2150726 : details::imatch(symbol, symbol_for) &&
31005 2735 : settings_.control_struct_enabled(symbol)
31006 : )
31007 : {
31008 2735 : return parse_for_loop();
31009 : }
31010 2145256 : else if (
31011 2146451 : details::imatch(symbol, symbol_switch) &&
31012 1195 : settings_.control_struct_enabled(symbol)
31013 : )
31014 : {
31015 1195 : return parse_switch_statement();
31016 : }
31017 2144061 : else if (details::is_valid_sf_symbol(symbol))
31018 : {
31019 4245 : return parse_special_function();
31020 : }
31021 2139816 : else if (details::imatch(symbol, symbol_null))
31022 : {
31023 275 : return parse_null_statement();
31024 : }
31025 : #ifndef exprtk_disable_break_continue
31026 2139541 : else if (details::imatch(symbol, symbol_break))
31027 : {
31028 483 : return parse_break_statement();
31029 : }
31030 2139058 : else if (details::imatch(symbol, symbol_continue))
31031 : {
31032 460 : return parse_continue_statement();
31033 : }
31034 : #endif
31035 2138598 : else if (details::imatch(symbol, symbol_var))
31036 : {
31037 79605 : return parse_define_var_statement();
31038 : }
31039 2058993 : else if (details::imatch(symbol, symbol_const))
31040 : {
31041 2645 : return parse_define_constvar_statement();
31042 : }
31043 2056348 : else if (details::imatch(symbol, symbol_swap))
31044 : {
31045 560 : return parse_swap_statement();
31046 : }
31047 : #ifndef exprtk_disable_return_statement
31048 2055788 : else if (
31049 2055904 : details::imatch(symbol, symbol_return) &&
31050 116 : settings_.control_struct_enabled(symbol)
31051 : )
31052 : {
31053 116 : return parse_return_statement();
31054 : }
31055 : #endif
31056 2055672 : else if (details::imatch(symbol, symbol_assert))
31057 : {
31058 108 : return parse_assert_statement();
31059 : }
31060 2055564 : else if (symtab_store_.valid() || !sem_.empty())
31061 : {
31062 2055470 : return parse_symtab_symbol();
31063 : }
31064 : else
31065 : {
31066 188 : set_error(make_error(
31067 : parser_error::e_symtab,
31068 94 : current_token(),
31069 : "ERR233 - Unknown variable or function encountered. Symbol table(s) "
31070 : "is either invalid or does not contain symbol: '" + symbol + "'",
31071 : exprtk_error_location));
31072 :
31073 94 : return error_node();
31074 : }
31075 2535008 : }
31076 :
31077 6346791 : inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
31078 : {
31079 6346791 : stack_limit_handler slh(*this);
31080 :
31081 6346791 : if (!slh)
31082 : {
31083 0 : return error_node();
31084 : }
31085 :
31086 6346791 : expression_node_ptr branch = error_node();
31087 :
31088 6346791 : if (token_t::e_number == current_token().type)
31089 : {
31090 1805868 : T numeric_value = T(0);
31091 :
31092 1805868 : if (details::string_to_real(current_token().value, numeric_value))
31093 : {
31094 1805868 : expression_node_ptr literal_exp = expression_generator_(numeric_value);
31095 :
31096 1805868 : if (0 == literal_exp)
31097 : {
31098 0 : set_error(make_error(
31099 : parser_error::e_numeric,
31100 0 : current_token(),
31101 0 : "ERR234 - Failed generate node for scalar: '" + current_token().value + "'",
31102 : exprtk_error_location));
31103 :
31104 0 : return error_node();
31105 : }
31106 :
31107 1805868 : next_token();
31108 1805868 : branch = literal_exp;
31109 : }
31110 : else
31111 : {
31112 0 : set_error(make_error(
31113 : parser_error::e_numeric,
31114 0 : current_token(),
31115 0 : "ERR235 - Failed to convert '" + current_token().value + "' to a number",
31116 : exprtk_error_location));
31117 :
31118 0 : return error_node();
31119 : }
31120 : }
31121 4540923 : else if (token_t::e_symbol == current_token().type)
31122 : {
31123 2535008 : branch = parse_symbol();
31124 : }
31125 : #ifndef exprtk_disable_string_capabilities
31126 2005915 : else if (token_t::e_string == current_token().type)
31127 : {
31128 52875 : branch = parse_const_string();
31129 : }
31130 : #endif
31131 1953040 : else if (token_t::e_lbracket == current_token().type)
31132 : {
31133 1836231 : next_token();
31134 :
31135 1836231 : if (0 == (branch = parse_expression()))
31136 120578 : return error_node();
31137 1715653 : else if (token_is(token_t::e_eof))
31138 : {}
31139 1715623 : else if (!token_is(token_t::e_rbracket))
31140 : {
31141 222 : set_error(make_error(
31142 : parser_error::e_syntax,
31143 74 : current_token(),
31144 74 : "ERR236 - Expected ')' instead of: '" + current_token().value + "'",
31145 : exprtk_error_location));
31146 :
31147 74 : details::free_node(node_allocator_,branch);
31148 :
31149 74 : return error_node();
31150 : }
31151 1715549 : else if (!post_bracket_process(token_t::e_lbracket,branch))
31152 : {
31153 0 : details::free_node(node_allocator_,branch);
31154 :
31155 0 : return error_node();
31156 : }
31157 :
31158 1715579 : parse_pending_vector_index_operator(branch);
31159 : }
31160 116809 : else if (token_t::e_lsqrbracket == current_token().type)
31161 : {
31162 6387 : next_token();
31163 :
31164 6387 : if (0 == (branch = parse_expression()))
31165 2 : return error_node();
31166 6385 : else if (!token_is(token_t::e_rsqrbracket))
31167 : {
31168 0 : set_error(make_error(
31169 : parser_error::e_syntax,
31170 0 : current_token(),
31171 0 : "ERR237 - Expected ']' instead of: '" + current_token().value + "'",
31172 : exprtk_error_location));
31173 :
31174 0 : details::free_node(node_allocator_,branch);
31175 :
31176 0 : return error_node();
31177 : }
31178 6385 : else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
31179 : {
31180 0 : details::free_node(node_allocator_,branch);
31181 :
31182 0 : return error_node();
31183 : }
31184 : }
31185 110422 : else if (token_t::e_lcrlbracket == current_token().type)
31186 : {
31187 2445 : next_token();
31188 :
31189 2445 : if (0 == (branch = parse_expression()))
31190 0 : return error_node();
31191 2445 : else if (!token_is(token_t::e_rcrlbracket))
31192 : {
31193 0 : set_error(make_error(
31194 : parser_error::e_syntax,
31195 0 : current_token(),
31196 0 : "ERR238 - Expected '}' instead of: '" + current_token().value + "'",
31197 : exprtk_error_location));
31198 :
31199 0 : details::free_node(node_allocator_,branch);
31200 :
31201 0 : return error_node();
31202 : }
31203 2445 : else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
31204 : {
31205 0 : details::free_node(node_allocator_,branch);
31206 :
31207 0 : return error_node();
31208 : }
31209 : }
31210 107977 : else if (token_t::e_sub == current_token().type)
31211 : {
31212 101315 : next_token();
31213 101315 : branch = parse_expression(e_level11);
31214 :
31215 101315 : if (
31216 202618 : branch &&
31217 : !(
31218 101303 : details::is_neg_unary_node (branch) &&
31219 640 : simplify_unary_negation_branch(branch)
31220 : )
31221 : )
31222 : {
31223 100663 : expression_node_ptr result = expression_generator_(details::e_neg,branch);
31224 :
31225 100663 : if (0 == result)
31226 : {
31227 0 : details::free_node(node_allocator_,branch);
31228 :
31229 0 : return error_node();
31230 : }
31231 : else
31232 100663 : branch = result;
31233 : }
31234 : }
31235 6662 : else if (token_t::e_add == current_token().type)
31236 : {
31237 6575 : next_token();
31238 6575 : branch = parse_expression(e_level13);
31239 : }
31240 87 : else if (token_t::e_eof == current_token().type)
31241 : {
31242 64 : set_error(make_error(
31243 : parser_error::e_syntax,
31244 16 : current_token(),
31245 : "ERR239 - Premature end of expression[1]",
31246 : exprtk_error_location));
31247 :
31248 16 : return error_node();
31249 : }
31250 : else
31251 : {
31252 284 : set_error(make_error(
31253 : parser_error::e_syntax,
31254 71 : current_token(),
31255 : "ERR240 - Premature end of expression[2]",
31256 : exprtk_error_location));
31257 :
31258 71 : return error_node();
31259 : }
31260 :
31261 6226050 : if (
31262 6193283 : branch &&
31263 12419333 : (e_level00 == precedence) &&
31264 9623484 : token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
31265 : )
31266 : {
31267 700 : branch = parse_ternary_conditional_statement(branch);
31268 : }
31269 :
31270 6226050 : parse_pending_string_rangesize(branch);
31271 :
31272 6226050 : return branch;
31273 6346791 : }
31274 :
31275 : template <typename Type>
31276 : class expression_generator
31277 : {
31278 : public:
31279 :
31280 : typedef details::expression_node<Type>* expression_node_ptr;
31281 : typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
31282 : typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
31283 : typedef typename exprtk::parser<Type> parser_t;
31284 : typedef const Type& vtype;
31285 : typedef const Type ctype;
31286 :
31287 108660 : inline void init_synthesize_map()
31288 : {
31289 : #ifndef exprtk_disable_enhanced_features
31290 217320 : synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
31291 217320 : synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
31292 217320 : synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
31293 :
31294 : #define register_synthezier(S) \
31295 : synthesize_map_[S ::node_type::id()] = S ::process; \
31296 :
31297 108660 : register_synthezier(synthesize_vovov_expression0)
31298 108660 : register_synthezier(synthesize_vovov_expression1)
31299 108660 : register_synthezier(synthesize_vovoc_expression0)
31300 108660 : register_synthezier(synthesize_vovoc_expression1)
31301 108660 : register_synthezier(synthesize_vocov_expression0)
31302 108660 : register_synthezier(synthesize_vocov_expression1)
31303 108660 : register_synthezier(synthesize_covov_expression0)
31304 108660 : register_synthezier(synthesize_covov_expression1)
31305 108660 : register_synthezier(synthesize_covoc_expression0)
31306 108660 : register_synthezier(synthesize_covoc_expression1)
31307 108660 : register_synthezier(synthesize_cocov_expression1)
31308 108660 : register_synthezier(synthesize_vococ_expression0)
31309 :
31310 108660 : register_synthezier(synthesize_vovovov_expression0)
31311 108660 : register_synthezier(synthesize_vovovoc_expression0)
31312 108660 : register_synthezier(synthesize_vovocov_expression0)
31313 108660 : register_synthezier(synthesize_vocovov_expression0)
31314 108660 : register_synthezier(synthesize_covovov_expression0)
31315 108660 : register_synthezier(synthesize_covocov_expression0)
31316 108660 : register_synthezier(synthesize_vocovoc_expression0)
31317 108660 : register_synthezier(synthesize_covovoc_expression0)
31318 108660 : register_synthezier(synthesize_vococov_expression0)
31319 :
31320 108660 : register_synthezier(synthesize_vovovov_expression1)
31321 108660 : register_synthezier(synthesize_vovovoc_expression1)
31322 108660 : register_synthezier(synthesize_vovocov_expression1)
31323 108660 : register_synthezier(synthesize_vocovov_expression1)
31324 108660 : register_synthezier(synthesize_covovov_expression1)
31325 108660 : register_synthezier(synthesize_covocov_expression1)
31326 108660 : register_synthezier(synthesize_vocovoc_expression1)
31327 108660 : register_synthezier(synthesize_covovoc_expression1)
31328 108660 : register_synthezier(synthesize_vococov_expression1)
31329 :
31330 108660 : register_synthezier(synthesize_vovovov_expression2)
31331 108660 : register_synthezier(synthesize_vovovoc_expression2)
31332 108660 : register_synthezier(synthesize_vovocov_expression2)
31333 108660 : register_synthezier(synthesize_vocovov_expression2)
31334 108660 : register_synthezier(synthesize_covovov_expression2)
31335 108660 : register_synthezier(synthesize_covocov_expression2)
31336 108660 : register_synthezier(synthesize_vocovoc_expression2)
31337 108660 : register_synthezier(synthesize_covovoc_expression2)
31338 :
31339 108660 : register_synthezier(synthesize_vovovov_expression3)
31340 108660 : register_synthezier(synthesize_vovovoc_expression3)
31341 108660 : register_synthezier(synthesize_vovocov_expression3)
31342 108660 : register_synthezier(synthesize_vocovov_expression3)
31343 108660 : register_synthezier(synthesize_covovov_expression3)
31344 108660 : register_synthezier(synthesize_covocov_expression3)
31345 108660 : register_synthezier(synthesize_vocovoc_expression3)
31346 108660 : register_synthezier(synthesize_covovoc_expression3)
31347 108660 : register_synthezier(synthesize_vococov_expression3)
31348 :
31349 108660 : register_synthezier(synthesize_vovovov_expression4)
31350 108660 : register_synthezier(synthesize_vovovoc_expression4)
31351 108660 : register_synthezier(synthesize_vovocov_expression4)
31352 108660 : register_synthezier(synthesize_vocovov_expression4)
31353 108660 : register_synthezier(synthesize_covovov_expression4)
31354 108660 : register_synthezier(synthesize_covocov_expression4)
31355 108660 : register_synthezier(synthesize_vocovoc_expression4)
31356 108660 : register_synthezier(synthesize_covovoc_expression4)
31357 :
31358 : #undef register_synthezier
31359 : #endif
31360 108660 : }
31361 :
31362 108660 : inline void set_parser(parser_t& p)
31363 : {
31364 108660 : parser_ = &p;
31365 108660 : }
31366 :
31367 108660 : inline void set_uom(unary_op_map_t& unary_op_map)
31368 : {
31369 108660 : unary_op_map_ = &unary_op_map;
31370 108660 : }
31371 :
31372 108660 : inline void set_bom(binary_op_map_t& binary_op_map)
31373 : {
31374 108660 : binary_op_map_ = &binary_op_map;
31375 108660 : }
31376 :
31377 108660 : inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
31378 : {
31379 108660 : inv_binary_op_map_ = &inv_binary_op_map;
31380 108660 : }
31381 :
31382 108660 : inline void set_sf3m(sf3_map_t& sf3_map)
31383 : {
31384 108660 : sf3_map_ = &sf3_map;
31385 108660 : }
31386 :
31387 108660 : inline void set_sf4m(sf4_map_t& sf4_map)
31388 : {
31389 108660 : sf4_map_ = &sf4_map;
31390 108660 : }
31391 :
31392 380686 : inline void set_allocator(details::node_allocator& na)
31393 : {
31394 380686 : node_allocator_ = &na;
31395 380686 : }
31396 :
31397 108660 : inline void set_strength_reduction_state(const bool enabled)
31398 : {
31399 108660 : strength_reduction_enabled_ = enabled;
31400 108660 : }
31401 :
31402 : inline bool strength_reduction_enabled() const
31403 : {
31404 : return strength_reduction_enabled_;
31405 : }
31406 :
31407 33571 : inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
31408 : {
31409 33571 : typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
31410 :
31411 33571 : if (binary_op_map_->end() == bop_itr)
31412 0 : return false;
31413 :
31414 33571 : bop = bop_itr->second;
31415 :
31416 33571 : return true;
31417 : }
31418 :
31419 1800 : inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
31420 : {
31421 1800 : typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
31422 :
31423 1800 : if ((*unary_op_map_).end() == uop_itr)
31424 0 : return false;
31425 :
31426 1800 : uop = uop_itr->second;
31427 :
31428 1800 : return true;
31429 : }
31430 :
31431 0 : inline details::operator_type get_operator(const binary_functor_t& bop) const
31432 : {
31433 0 : return (*inv_binary_op_map_).find(bop)->second;
31434 : }
31435 :
31436 1864959 : inline expression_node_ptr operator() (const Type& v) const
31437 : {
31438 1864959 : return node_allocator_->allocate<literal_node_t>(v);
31439 : }
31440 :
31441 : #ifndef exprtk_disable_string_capabilities
31442 52875 : inline expression_node_ptr operator() (const std::string& s) const
31443 : {
31444 52875 : return node_allocator_->allocate<string_literal_node_t>(s);
31445 : }
31446 :
31447 22401 : inline expression_node_ptr operator() (std::string& s, range_t& rp) const
31448 : {
31449 22401 : return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
31450 : }
31451 :
31452 5553 : inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
31453 : {
31454 5553 : return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
31455 : }
31456 :
31457 4102 : inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
31458 : {
31459 4102 : if (is_generally_string_node(branch))
31460 4102 : return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
31461 : else
31462 0 : return error_node();
31463 : }
31464 : #endif
31465 :
31466 133618 : inline bool unary_optimisable(const details::operator_type& operation) const
31467 : {
31468 123812 : return (details::e_abs == operation) || (details::e_acos == operation) ||
31469 123752 : (details::e_acosh == operation) || (details::e_asin == operation) ||
31470 123632 : (details::e_asinh == operation) || (details::e_atan == operation) ||
31471 123502 : (details::e_atanh == operation) || (details::e_ceil == operation) ||
31472 123442 : (details::e_cos == operation) || (details::e_cosh == operation) ||
31473 107657 : (details::e_exp == operation) || (details::e_expm1 == operation) ||
31474 107537 : (details::e_floor == operation) || (details::e_log == operation) ||
31475 107363 : (details::e_log10 == operation) || (details::e_log2 == operation) ||
31476 107253 : (details::e_log1p == operation) || (details::e_neg == operation) ||
31477 98649 : (details::e_pos == operation) || (details::e_round == operation) ||
31478 98589 : (details::e_sin == operation) || (details::e_sinc == operation) ||
31479 18237 : (details::e_sinh == operation) || (details::e_sqrt == operation) ||
31480 18029 : (details::e_tan == operation) || (details::e_tanh == operation) ||
31481 941 : (details::e_cot == operation) || (details::e_sec == operation) ||
31482 807 : (details::e_csc == operation) || (details::e_r2d == operation) ||
31483 682 : (details::e_d2r == operation) || (details::e_d2g == operation) ||
31484 562 : (details::e_g2d == operation) || (details::e_notl == operation) ||
31485 486 : (details::e_sgn == operation) || (details::e_erf == operation) ||
31486 213 : (details::e_erfc == operation) || (details::e_ncdf == operation) ||
31487 257430 : (details::e_frac == operation) || (details::e_trunc == operation) ;
31488 : }
31489 :
31490 : inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
31491 : {
31492 : typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
31493 :
31494 : if (sf3_map_->end() == itr)
31495 : return false;
31496 : else
31497 : tfunc = itr->second.first;
31498 :
31499 : return true;
31500 : }
31501 :
31502 : inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
31503 : {
31504 : typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
31505 :
31506 : if (sf4_map_->end() == itr)
31507 : return false;
31508 : else
31509 : qfunc = itr->second.first;
31510 :
31511 : return true;
31512 : }
31513 :
31514 377040 : inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
31515 : {
31516 377040 : typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
31517 :
31518 377040 : if (sf3_map_->end() == itr)
31519 5960 : return false;
31520 : else
31521 371080 : operation = itr->second.second;
31522 :
31523 371080 : return true;
31524 : }
31525 :
31526 243720 : inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
31527 : {
31528 243720 : typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
31529 :
31530 243720 : if (sf4_map_->end() == itr)
31531 145836 : return false;
31532 : else
31533 97884 : operation = itr->second.second;
31534 :
31535 97884 : return true;
31536 : }
31537 :
31538 171745 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
31539 : {
31540 171745 : if (0 == branch[0])
31541 : {
31542 0 : return error_node();
31543 : }
31544 171745 : else if (details::is_null_node(branch[0]))
31545 : {
31546 0 : return branch[0];
31547 : }
31548 171745 : else if (details::is_break_node(branch[0]))
31549 : {
31550 0 : return error_node();
31551 : }
31552 171745 : else if (details::is_continue_node(branch[0]))
31553 : {
31554 0 : return error_node();
31555 : }
31556 171745 : else if (details::is_constant_node(branch[0]))
31557 : {
31558 100770 : return synthesize_expression<unary_node_t,1>(operation,branch);
31559 : }
31560 70975 : else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
31561 : {
31562 8332 : return synthesize_uv_expression(operation,branch);
31563 : }
31564 62643 : else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
31565 : {
31566 2690 : return synthesize_uvec_expression(operation,branch);
31567 : }
31568 : else
31569 59953 : return synthesize_unary_expression(operation,branch);
31570 : }
31571 :
31572 5936917 : inline bool is_assignment_operation(const details::operator_type& operation) const
31573 : {
31574 : return (
31575 11853680 : (details::e_addass == operation) ||
31576 5916763 : (details::e_subass == operation) ||
31577 5914672 : (details::e_mulass == operation) ||
31578 5914012 : (details::e_divass == operation) ||
31579 5913352 : (details::e_modass == operation)
31580 11873834 : ) &&
31581 5960632 : parser_->settings_.assignment_enabled(operation);
31582 : }
31583 :
31584 : #ifndef exprtk_disable_string_capabilities
31585 3047559 : inline bool valid_string_operation(const details::operator_type& operation) const
31586 : {
31587 5346060 : return (details::e_add == operation) ||
31588 2298501 : (details::e_lt == operation) ||
31589 2290601 : (details::e_lte == operation) ||
31590 2288230 : (details::e_gt == operation) ||
31591 2280836 : (details::e_gte == operation) ||
31592 2280001 : (details::e_eq == operation) ||
31593 2191326 : (details::e_ne == operation) ||
31594 2185831 : (details::e_in == operation) ||
31595 2184299 : (details::e_like == operation) ||
31596 2178159 : (details::e_ilike == operation) ||
31597 2171669 : (details::e_assign == operation) ||
31598 7442826 : (details::e_addass == operation) ||
31599 5144325 : (details::e_swap == operation) ;
31600 : }
31601 : #else
31602 : inline bool valid_string_operation(const details::operator_type&) const
31603 : {
31604 : return false;
31605 : }
31606 : #endif
31607 :
31608 1034692 : inline std::string to_str(const details::operator_type& operation) const
31609 : {
31610 1034692 : switch (operation)
31611 : {
31612 692346 : case details::e_add : return "+" ;
31613 671628 : case details::e_sub : return "-" ;
31614 1042827 : case details::e_mul : return "*" ;
31615 642708 : case details::e_div : return "/" ;
31616 66 : case details::e_mod : return "%" ;
31617 2121 : case details::e_pow : return "^" ;
31618 1533 : case details::e_lt : return "<" ;
31619 363 : case details::e_lte : return "<=" ;
31620 3030 : case details::e_gt : return ">" ;
31621 0 : case details::e_gte : return ">=" ;
31622 37275 : case details::e_eq : return "==" ;
31623 360 : case details::e_ne : return "!=" ;
31624 9816 : case details::e_and : return "and" ;
31625 0 : case details::e_nand : return "nand" ;
31626 3 : case details::e_or : return "or" ;
31627 0 : case details::e_nor : return "nor" ;
31628 0 : case details::e_xor : return "xor" ;
31629 0 : case details::e_xnor : return "xnor" ;
31630 0 : default : return "UNKNOWN";
31631 : }
31632 : }
31633 :
31634 11168957 : inline bool operation_optimisable(const details::operator_type& operation) const
31635 : {
31636 18996421 : return (details::e_add == operation) ||
31637 7827464 : (details::e_sub == operation) ||
31638 5749346 : (details::e_mul == operation) ||
31639 3858880 : (details::e_div == operation) ||
31640 2500605 : (details::e_mod == operation) ||
31641 2499108 : (details::e_pow == operation) ||
31642 2361325 : (details::e_lt == operation) ||
31643 2346170 : (details::e_lte == operation) ||
31644 2341654 : (details::e_gt == operation) ||
31645 2326949 : (details::e_gte == operation) ||
31646 2325329 : (details::e_eq == operation) ||
31647 2204983 : (details::e_ne == operation) ||
31648 2202530 : (details::e_and == operation) ||
31649 2149266 : (details::e_nand == operation) ||
31650 2144462 : (details::e_or == operation) ||
31651 2139253 : (details::e_nor == operation) ||
31652 21128925 : (details::e_xor == operation) ||
31653 13301461 : (details::e_xnor == operation) ;
31654 : }
31655 :
31656 5182302 : inline std::string branch_to_id(expression_node_ptr branch) const
31657 : {
31658 5182304 : static const std::string null_str ("(null)" );
31659 5182304 : static const std::string const_str ("(c)" );
31660 5182304 : static const std::string var_str ("(v)" );
31661 5182304 : static const std::string vov_str ("(vov)" );
31662 5182304 : static const std::string cov_str ("(cov)" );
31663 5182304 : static const std::string voc_str ("(voc)" );
31664 5182304 : static const std::string str_str ("(s)" );
31665 5182304 : static const std::string strrng_str ("(rngs)" );
31666 5182304 : static const std::string cs_str ("(cs)" );
31667 5182304 : static const std::string cstrrng_str("(crngs)");
31668 :
31669 5182302 : if (details::is_null_node(branch))
31670 0 : return null_str;
31671 5182302 : else if (details::is_constant_node(branch))
31672 1384901 : return const_str;
31673 3797401 : else if (details::is_variable_node(branch))
31674 1730261 : return var_str;
31675 2067140 : else if (details::is_vov_node(branch))
31676 256010 : return vov_str;
31677 1811130 : else if (details::is_cov_node(branch))
31678 235649 : return cov_str;
31679 1575481 : else if (details::is_voc_node(branch))
31680 194933 : return voc_str;
31681 1380548 : else if (details::is_string_node(branch))
31682 0 : return str_str;
31683 1380548 : else if (details::is_const_string_node(branch))
31684 0 : return cs_str;
31685 1380548 : else if (details::is_string_range_node(branch))
31686 0 : return strrng_str;
31687 1380548 : else if (details::is_const_string_range_node(branch))
31688 0 : return cstrrng_str;
31689 1380548 : else if (details::is_t0ot1ot2_node(branch))
31690 346237 : return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
31691 1034311 : else if (details::is_t0ot1ot2ot3_node(branch))
31692 88722 : return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
31693 : else
31694 1891178 : return "ERROR";
31695 : }
31696 :
31697 2591151 : inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
31698 : {
31699 7773453 : return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
31700 : }
31701 :
31702 855557 : inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31703 : {
31704 855557 : if (!operation_optimisable(operation))
31705 266483 : return false;
31706 : else
31707 771141 : return details::is_constant_node(branch[0]) &&
31708 771141 : details::is_variable_node(branch[1]) ;
31709 : }
31710 :
31711 : inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31712 : {
31713 : if (!operation_optimisable(operation))
31714 : return false;
31715 : else
31716 : return details::is_variable_node(branch[0]) &&
31717 : details::is_constant_node(branch[1]) ;
31718 : }
31719 :
31720 : inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31721 : {
31722 : if (!operation_optimisable(operation))
31723 : return false;
31724 : else
31725 : return details::is_variable_node(branch[0]) &&
31726 : details::is_variable_node(branch[1]) ;
31727 : }
31728 :
31729 1101697 : inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31730 : {
31731 1101697 : if (!operation_optimisable(operation))
31732 266483 : return false;
31733 : else
31734 1116413 : return details::is_constant_node(branch[0]) &&
31735 1116413 : !details::is_constant_node(branch[1]) ;
31736 : }
31737 :
31738 1002565 : inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31739 : {
31740 1002565 : if (!operation_optimisable(operation))
31741 266483 : return false;
31742 : else
31743 1290097 : return !details::is_constant_node(branch[0]) &&
31744 1290097 : details::is_constant_node(branch[1]) ;
31745 : }
31746 :
31747 1544104 : inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31748 : {
31749 1544104 : if (
31750 1544104 : (details::e_add == operation) ||
31751 1030141 : (details::e_sub == operation) ||
31752 725772 : (details::e_mul == operation) ||
31753 461042 : (details::e_div == operation)
31754 : )
31755 : {
31756 2482909 : return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
31757 2482909 : (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
31758 : }
31759 : else
31760 301049 : return false;
31761 : }
31762 :
31763 1536146 : inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31764 : {
31765 1536146 : if (
31766 1536146 : (details::e_add == operation) ||
31767 1023996 : (details::e_sub == operation) ||
31768 722217 : (details::e_mul == operation) ||
31769 458847 : (details::e_div == operation)
31770 : )
31771 : {
31772 2467939 : return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
31773 2467939 : (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
31774 : }
31775 : else
31776 301049 : return false;
31777 : }
31778 :
31779 1516802 : inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31780 : {
31781 1516802 : if (!operation_optimisable(operation))
31782 266483 : return false;
31783 : else
31784 1252603 : return details::is_uv_node(branch[0]) &&
31785 1252603 : details::is_uv_node(branch[1]) ;
31786 : }
31787 :
31788 1515902 : inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31789 : {
31790 1515902 : if (!operation_optimisable(operation))
31791 266483 : return false;
31792 : else
31793 1302078 : return details::is_variable_node(branch[0]) &&
31794 1302078 : !details::is_variable_node(branch[1]) ;
31795 : }
31796 :
31797 1463243 : inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31798 : {
31799 1463243 : if (!operation_optimisable(operation))
31800 266483 : return false;
31801 : else
31802 2393520 : return !details::is_variable_node(branch[0]) &&
31803 2393520 : details::is_variable_node(branch[1]) ;
31804 : }
31805 :
31806 855557 : inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31807 : {
31808 855557 : if (!operation_optimisable(operation))
31809 266483 : return false;
31810 : else
31811 771141 : return !details::is_constant_node(branch[0]) ||
31812 771141 : !details::is_constant_node(branch[1]) ;
31813 : }
31814 :
31815 3002237 : inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31816 : {
31817 3002237 : if (is_assignment_operation(operation))
31818 : {
31819 11859 : const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
31820 :
31821 11859 : if (details::is_string_node(branch[0]))
31822 2600 : return !b1_is_genstring;
31823 9259 : else if (details::is_literal_node(branch[0]))
31824 0 : return true;
31825 : else
31826 : return (
31827 9259 : !details::is_variable_node (branch[0]) &&
31828 4377 : !details::is_vector_elem_node (branch[0]) &&
31829 3876 : !details::is_vector_celem_node (branch[0]) &&
31830 3876 : !details::is_vector_elem_rtc_node (branch[0]) &&
31831 3864 : !details::is_vector_celem_rtc_node (branch[0]) &&
31832 3864 : !details::is_rebasevector_elem_node (branch[0]) &&
31833 3564 : !details::is_rebasevector_celem_node (branch[0]) &&
31834 3264 : !details::is_rebasevector_elem_rtc_node (branch[0]) &&
31835 3264 : !details::is_rebasevector_celem_rtc_node(branch[0]) &&
31836 3264 : !details::is_vector_node (branch[0])
31837 : )
31838 13636 : || b1_is_genstring;
31839 : }
31840 : else
31841 2990378 : return false;
31842 : }
31843 :
31844 2857635 : inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
31845 : {
31846 2857635 : if (
31847 2857635 : !details::is_constant_node(branch[1]) ||
31848 851589 : details::is_constant_node(branch[0]) ||
31849 653422 : details::is_variable_node(branch[0]) ||
31850 4006100 : details::is_vector_node (branch[0]) ||
31851 296876 : details::is_generally_string_node(branch[0])
31852 : )
31853 2560759 : return false;
31854 :
31855 296876 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
31856 :
31857 296876 : return cardinal_pow_optimisable(operation, c);
31858 : }
31859 :
31860 3002234 : inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
31861 : {
31862 : return (
31863 3002234 : details::is_break_node (branch[0]) ||
31864 3002234 : details::is_break_node (branch[1]) ||
31865 9006702 : details::is_continue_node(branch[0]) ||
31866 3002234 : details::is_continue_node(branch[1])
31867 3002234 : );
31868 : }
31869 :
31870 3002237 : inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31871 : {
31872 3002237 : const bool b0_string = is_generally_string_node(branch[0]);
31873 3002237 : const bool b1_string = is_generally_string_node(branch[1]);
31874 :
31875 3002237 : bool result = false;
31876 :
31877 3002237 : if (b0_string != b1_string)
31878 0 : result = true;
31879 3002237 : else if (!valid_string_operation(operation) && b0_string && b1_string)
31880 0 : result = true;
31881 :
31882 3002237 : if (result)
31883 : {
31884 0 : parser_->set_synthesis_error("Invalid string operation");
31885 : }
31886 :
31887 3002237 : return result;
31888 : }
31889 :
31890 471 : inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
31891 : {
31892 471 : const bool b0_string = is_generally_string_node(branch[0]);
31893 471 : const bool b1_string = is_generally_string_node(branch[1]);
31894 471 : const bool b2_string = is_generally_string_node(branch[2]);
31895 :
31896 471 : bool result = false;
31897 :
31898 471 : if ((b0_string != b1_string) || (b1_string != b2_string))
31899 0 : result = true;
31900 471 : else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
31901 0 : result = true;
31902 :
31903 471 : if (result)
31904 : {
31905 0 : parser_->set_synthesis_error("Invalid string operation");
31906 : }
31907 :
31908 471 : return result;
31909 : }
31910 :
31911 2903212 : inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31912 : {
31913 2903212 : const bool b0_string = is_generally_string_node(branch[0]);
31914 2903212 : const bool b1_string = is_generally_string_node(branch[1]);
31915 :
31916 2903212 : return (b0_string && b1_string && valid_string_operation(operation));
31917 : }
31918 :
31919 471 : inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
31920 : {
31921 471 : const bool b0_string = is_generally_string_node(branch[0]);
31922 471 : const bool b1_string = is_generally_string_node(branch[1]);
31923 471 : const bool b2_string = is_generally_string_node(branch[2]);
31924 :
31925 471 : return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
31926 : }
31927 :
31928 : #ifndef exprtk_disable_sc_andor
31929 2904068 : inline bool is_shortcircuit_expression(const details::operator_type& operation) const
31930 : {
31931 : return (
31932 5807700 : (details::e_scand == operation) ||
31933 2903632 : (details::e_scor == operation)
31934 2904068 : );
31935 : }
31936 : #else
31937 : inline bool is_shortcircuit_expression(const details::operator_type&) const
31938 : {
31939 : return false;
31940 : }
31941 : #endif
31942 :
31943 2857890 : inline bool is_null_present(expression_node_ptr (&branch)[2]) const
31944 : {
31945 : return (
31946 5715720 : details::is_null_node(branch[0]) ||
31947 2857830 : details::is_null_node(branch[1])
31948 2857890 : );
31949 : }
31950 :
31951 2922824 : inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31952 : {
31953 2922824 : if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
31954 2904068 : return false;
31955 : else
31956 : return (
31957 36707 : (details::e_lt == operation) ||
31958 17951 : (details::e_lte == operation) ||
31959 17671 : (details::e_gt == operation) ||
31960 17351 : (details::e_gte == operation) ||
31961 17151 : (details::e_eq == operation) ||
31962 12579 : (details::e_ne == operation) ||
31963 12419 : (details::e_equal == operation) ||
31964 12299 : (details::e_and == operation) ||
31965 12299 : (details::e_nand == operation) ||
31966 12299 : (details::e_or == operation) ||
31967 12299 : (details::e_nor == operation) ||
31968 49006 : (details::e_xor == operation) ||
31969 12299 : (details::e_xnor == operation)
31970 18756 : );
31971 : }
31972 :
31973 2916367 : inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
31974 : {
31975 2916367 : if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
31976 2904068 : return false;
31977 : else
31978 : return (
31979 21984 : (details::e_add == operation) ||
31980 9685 : (details::e_sub == operation) ||
31981 5484 : (details::e_mul == operation) ||
31982 22024 : (details::e_div == operation) ||
31983 40 : (details::e_pow == operation)
31984 12299 : );
31985 : }
31986 :
31987 3002237 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
31988 : {
31989 3002237 : if ((0 == branch[0]) || (0 == branch[1]))
31990 : {
31991 0 : parser_->set_error(parser_error::make_error(
31992 : parser_error::e_syntax,
31993 0 : parser_->current_state().token,
31994 : "ERR241 - Invalid branches received for operator '" + details::to_str(operation) + "'",
31995 : exprtk_error_location));
31996 :
31997 0 : return error_node();
31998 : }
31999 3002237 : else if (is_invalid_string_op(operation,branch))
32000 : {
32001 0 : parser_->set_error(parser_error::make_error(
32002 : parser_error::e_syntax,
32003 0 : parser_->current_state().token,
32004 : "ERR242 - Invalid branch pair for string operator '" + details::to_str(operation) + "'",
32005 : exprtk_error_location));
32006 :
32007 0 : return error_node();
32008 : }
32009 3002237 : else if (is_invalid_assignment_op(operation,branch))
32010 : {
32011 9 : parser_->set_error(parser_error::make_error(
32012 : parser_error::e_syntax,
32013 6 : parser_->current_state().token,
32014 : "ERR243 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'",
32015 : exprtk_error_location));
32016 :
32017 3 : return error_node();
32018 : }
32019 3002234 : else if (is_invalid_break_continue_op(branch))
32020 : {
32021 0 : parser_->set_error(parser_error::make_error(
32022 : parser_error::e_syntax,
32023 0 : parser_->current_state().token,
32024 : "ERR244 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'",
32025 : exprtk_error_location));
32026 :
32027 0 : return error_node();
32028 : }
32029 3002234 : else if (details::e_assign == operation)
32030 : {
32031 64826 : return synthesize_assignment_expression(operation, branch);
32032 : }
32033 2937408 : else if (details::e_swap == operation)
32034 : {
32035 2728 : return synthesize_swap_expression(branch);
32036 : }
32037 2934680 : else if (is_assignment_operation(operation))
32038 : {
32039 11856 : return synthesize_assignment_operation_expression(operation, branch);
32040 : }
32041 2922824 : else if (is_vector_eqineq_logic_operation(operation, branch))
32042 : {
32043 6457 : return synthesize_veceqineqlogic_operation_expression(operation, branch);
32044 : }
32045 2916367 : else if (is_vector_arithmetic_operation(operation, branch))
32046 : {
32047 12299 : return synthesize_vecarithmetic_operation_expression(operation, branch);
32048 : }
32049 2904068 : else if (is_shortcircuit_expression(operation))
32050 : {
32051 856 : return synthesize_shortcircuit_expression(operation, branch);
32052 : }
32053 2903212 : else if (is_string_operation(operation, branch))
32054 : {
32055 45322 : return synthesize_string_expression(operation, branch);
32056 : }
32057 2857890 : else if (is_null_present(branch))
32058 : {
32059 255 : return synthesize_null_expression(operation, branch);
32060 : }
32061 : #ifndef exprtk_disable_cardinal_pow_optimisation
32062 2857635 : else if (is_constpow_operation(operation, branch))
32063 : {
32064 1 : return cardinal_pow_optimisation(branch);
32065 : }
32066 : #endif
32067 :
32068 2857634 : expression_node_ptr result = error_node();
32069 :
32070 : #ifndef exprtk_disable_enhanced_features
32071 2857634 : if (synthesize_expression(operation, branch, result))
32072 : {
32073 1313530 : return result;
32074 : }
32075 : else
32076 : #endif
32077 :
32078 : {
32079 : /*
32080 : Possible reductions:
32081 : 1. c o cob -> cob
32082 : 2. cob o c -> cob
32083 : 3. c o boc -> boc
32084 : 4. boc o c -> boc
32085 : */
32086 1544104 : result = error_node();
32087 :
32088 1544104 : if (cocob_optimisable(operation, branch))
32089 : {
32090 7958 : result = synthesize_cocob_expression::process((*this), operation, branch);
32091 : }
32092 1536146 : else if (coboc_optimisable(operation, branch) && (0 == result))
32093 : {
32094 24432 : result = synthesize_coboc_expression::process((*this), operation, branch);
32095 : }
32096 :
32097 1544104 : if (result)
32098 27302 : return result;
32099 : }
32100 :
32101 1516802 : if (uvouv_optimisable(operation, branch))
32102 : {
32103 900 : return synthesize_uvouv_expression(operation, branch);
32104 : }
32105 1515902 : else if (vob_optimisable(operation, branch))
32106 : {
32107 52659 : return synthesize_vob_expression::process((*this), operation, branch);
32108 : }
32109 1463243 : else if (bov_optimisable(operation, branch))
32110 : {
32111 361546 : return synthesize_bov_expression::process((*this), operation, branch);
32112 : }
32113 1101697 : else if (cob_optimisable(operation, branch))
32114 : {
32115 99132 : return synthesize_cob_expression::process((*this), operation, branch);
32116 : }
32117 1002565 : else if (boc_optimisable(operation, branch))
32118 : {
32119 147008 : return synthesize_boc_expression::process((*this), operation, branch);
32120 : }
32121 : #ifndef exprtk_disable_enhanced_features
32122 855557 : else if (cov_optimisable(operation, branch))
32123 : {
32124 0 : return synthesize_cov_expression::process((*this), operation, branch);
32125 : }
32126 : #endif
32127 855557 : else if (binext_optimisable(operation, branch))
32128 : {
32129 407007 : return synthesize_binary_ext_expression::process((*this), operation, branch);
32130 : }
32131 : else
32132 448550 : return synthesize_expression<binary_node_t,2>(operation, branch);
32133 : }
32134 :
32135 471 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
32136 : {
32137 471 : if (
32138 471 : (0 == branch[0]) ||
32139 471 : (0 == branch[1]) ||
32140 471 : (0 == branch[2])
32141 : )
32142 : {
32143 0 : details::free_all_nodes(*node_allocator_,branch);
32144 :
32145 0 : parser_->set_error(parser_error::make_error(
32146 : parser_error::e_syntax,
32147 0 : parser_->current_state().token,
32148 : "ERR245 - Invalid branches operator '" + details::to_str(operation) + "'",
32149 : exprtk_error_location));
32150 :
32151 0 : return error_node();
32152 : }
32153 471 : else if (is_invalid_string_op(operation, branch))
32154 : {
32155 0 : parser_->set_error(parser_error::make_error(
32156 : parser_error::e_syntax,
32157 0 : parser_->current_state().token,
32158 : "ERR246 - Invalid branches for string operator '" + details::to_str(operation) + "'",
32159 : exprtk_error_location));
32160 :
32161 0 : return error_node();
32162 : }
32163 471 : else if (is_string_operation(operation, branch))
32164 : {
32165 355 : return synthesize_string_expression(operation, branch);
32166 : }
32167 : else
32168 116 : return synthesize_expression<trinary_node_t,3>(operation, branch);
32169 : }
32170 :
32171 0 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
32172 : {
32173 0 : return synthesize_expression<quaternary_node_t,4>(operation,branch);
32174 : }
32175 :
32176 101383 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
32177 : {
32178 101383 : expression_node_ptr branch[1] = { b0 };
32179 202766 : return (*this)(operation,branch);
32180 : }
32181 :
32182 2682458 : inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
32183 : {
32184 2682458 : expression_node_ptr result = error_node();
32185 :
32186 2682458 : if ((0 != b0) && (0 != b1))
32187 : {
32188 2682458 : expression_node_ptr branch[2] = { b0, b1 };
32189 2682458 : result = expression_generator<Type>::operator()(operation, branch);
32190 2682458 : b0 = branch[0];
32191 2682458 : b1 = branch[1];
32192 : }
32193 :
32194 2682458 : return result;
32195 : }
32196 :
32197 5634 : inline expression_node_ptr conditional(expression_node_ptr condition,
32198 : expression_node_ptr consequent,
32199 : expression_node_ptr alternative) const
32200 : {
32201 5634 : if ((0 == condition) || (0 == consequent))
32202 : {
32203 0 : details::free_node(*node_allocator_, condition );
32204 0 : details::free_node(*node_allocator_, consequent );
32205 0 : details::free_node(*node_allocator_, alternative);
32206 :
32207 0 : const std::string invalid_branches =
32208 0 : ((0 == condition ) ? std::string("condition ") : "") +
32209 0 : ((0 == consequent) ? std::string("consequent") : "") ;
32210 :
32211 0 : parser_->set_error(parser_error::make_error(
32212 : parser_error::e_parser,
32213 0 : parser_->current_state().token,
32214 : "ERR247 - Invalid " + invalid_branches + " for conditional statement",
32215 : exprtk_error_location));
32216 :
32217 0 : return error_node();
32218 0 : }
32219 : // Can the condition be immediately evaluated? if so optimise.
32220 5634 : else if (details::is_constant_node(condition))
32221 : {
32222 : // True branch
32223 1756 : if (details::is_true(condition))
32224 : {
32225 1126 : details::free_node(*node_allocator_, condition );
32226 1126 : details::free_node(*node_allocator_, alternative);
32227 :
32228 1126 : return consequent;
32229 : }
32230 : // False branch
32231 : else
32232 : {
32233 630 : details::free_node(*node_allocator_, condition );
32234 630 : details::free_node(*node_allocator_, consequent);
32235 :
32236 630 : if (alternative)
32237 570 : return alternative;
32238 : else
32239 60 : return node_allocator_->allocate<details::null_node<T> >();
32240 : }
32241 : }
32242 :
32243 3878 : expression_node_ptr result = error_node();
32244 3878 : std::string node_name = "Unknown!";
32245 :
32246 3878 : if ((0 != consequent) && (0 != alternative))
32247 : {
32248 2847 : result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative);
32249 2847 : node_name = "conditional_node_t";
32250 : }
32251 : else
32252 : {
32253 1031 : result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent);
32254 1031 : node_name = "cons_conditional_node_t";
32255 : }
32256 :
32257 3878 : if (result && result->valid())
32258 : {
32259 3878 : return result;
32260 : }
32261 :
32262 0 : parser_->set_error(parser_error::make_error(
32263 : parser_error::e_parser,
32264 0 : token_t(),
32265 : "ERR248 - Failed to synthesize node: " + node_name,
32266 : exprtk_error_location));
32267 :
32268 0 : details::free_node(*node_allocator_, result);
32269 0 : return error_node();
32270 3878 : }
32271 :
32272 : #ifndef exprtk_disable_string_capabilities
32273 1151 : inline expression_node_ptr conditional_string(expression_node_ptr condition,
32274 : expression_node_ptr consequent,
32275 : expression_node_ptr alternative) const
32276 : {
32277 1151 : if ((0 == condition) || (0 == consequent))
32278 : {
32279 0 : details::free_node(*node_allocator_, condition );
32280 0 : details::free_node(*node_allocator_, consequent );
32281 0 : details::free_node(*node_allocator_, alternative);
32282 :
32283 0 : const std::string invalid_branches =
32284 0 : ((0 == condition ) ? std::string("condition ") : "") +
32285 0 : ((0 == consequent) ? std::string("consequent") : "") ;
32286 :
32287 0 : parser_->set_error(parser_error::make_error(
32288 : parser_error::e_parser,
32289 0 : parser_->current_state().token,
32290 : "ERR249 - Invalid " + invalid_branches + " for string conditional statement",
32291 : exprtk_error_location));
32292 :
32293 0 : return error_node();
32294 0 : }
32295 : // Can the condition be immediately evaluated? if so optimise.
32296 1151 : else if (details::is_constant_node(condition))
32297 : {
32298 : // True branch
32299 0 : if (details::is_true(condition))
32300 : {
32301 0 : details::free_node(*node_allocator_, condition );
32302 0 : details::free_node(*node_allocator_, alternative);
32303 :
32304 0 : return consequent;
32305 : }
32306 : // False branch
32307 : else
32308 : {
32309 0 : details::free_node(*node_allocator_, condition );
32310 0 : details::free_node(*node_allocator_, consequent);
32311 :
32312 0 : if (alternative)
32313 0 : return alternative;
32314 : else
32315 0 : return node_allocator_->
32316 0 : allocate_c<details::string_literal_node<Type> >("");
32317 : }
32318 : }
32319 1151 : else if ((0 != consequent) && (0 != alternative))
32320 : {
32321 1151 : expression_node_ptr result =
32322 1151 : node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative);
32323 :
32324 1151 : if (result && result->valid())
32325 : {
32326 1151 : return result;
32327 : }
32328 :
32329 0 : parser_->set_error(parser_error::make_error(
32330 : parser_error::e_parser,
32331 0 : token_t(),
32332 : "ERR250 - Failed to synthesize node: conditional_string_node_t",
32333 : exprtk_error_location));
32334 :
32335 0 : details::free_node(*node_allocator_, result);
32336 : }
32337 :
32338 0 : return error_node();
32339 : }
32340 : #else
32341 : inline expression_node_ptr conditional_string(expression_node_ptr,
32342 : expression_node_ptr,
32343 : expression_node_ptr) const
32344 : {
32345 : return error_node();
32346 : }
32347 : #endif
32348 :
32349 1773 : inline expression_node_ptr conditional_vector(expression_node_ptr condition,
32350 : expression_node_ptr consequent,
32351 : expression_node_ptr alternative) const
32352 : {
32353 1773 : if ((0 == condition) || (0 == consequent))
32354 : {
32355 0 : details::free_node(*node_allocator_, condition );
32356 0 : details::free_node(*node_allocator_, consequent );
32357 0 : details::free_node(*node_allocator_, alternative);
32358 :
32359 0 : const std::string invalid_branches =
32360 0 : ((0 == condition ) ? std::string("condition ") : "") +
32361 0 : ((0 == consequent) ? std::string("consequent") : "") ;
32362 :
32363 0 : parser_->set_error(parser_error::make_error(
32364 : parser_error::e_parser,
32365 0 : parser_->current_state().token,
32366 : "ERR251 - Invalid " + invalid_branches + " for vector conditional statement",
32367 : exprtk_error_location));
32368 :
32369 0 : return error_node();
32370 0 : }
32371 : // Can the condition be immediately evaluated? if so optimise.
32372 1773 : else if (details::is_constant_node(condition))
32373 : {
32374 : // True branch
32375 880 : if (details::is_true(condition))
32376 : {
32377 440 : details::free_node(*node_allocator_, condition );
32378 440 : details::free_node(*node_allocator_, alternative);
32379 :
32380 440 : return consequent;
32381 : }
32382 : // False branch
32383 : else
32384 : {
32385 440 : details::free_node(*node_allocator_, condition );
32386 440 : details::free_node(*node_allocator_, consequent);
32387 :
32388 440 : if (alternative)
32389 440 : return alternative;
32390 : else
32391 0 : return node_allocator_->allocate<details::null_node<T> >();
32392 :
32393 : }
32394 : }
32395 893 : else if ((0 != consequent) && (0 != alternative))
32396 : {
32397 893 : return node_allocator_->
32398 893 : allocate<conditional_vector_node_t>(condition, consequent, alternative);
32399 : }
32400 : else
32401 0 : return error_node();
32402 : }
32403 :
32404 2747 : inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
32405 : {
32406 2747 : if (
32407 2747 : parser_->loop_runtime_check_ &&
32408 0 : (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
32409 : )
32410 : {
32411 0 : return parser_->loop_runtime_check_;
32412 : }
32413 :
32414 2747 : return loop_runtime_check_ptr(0);
32415 : }
32416 :
32417 6903 : inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const
32418 : {
32419 6903 : return parser_->vector_access_runtime_check_;
32420 : }
32421 :
32422 22 : inline expression_node_ptr while_loop(expression_node_ptr& condition,
32423 : expression_node_ptr& branch,
32424 : const bool break_continue_present = false) const
32425 : {
32426 22 : if (
32427 34 : !break_continue_present &&
32428 34 : !parser_->state_.return_stmt_present &&
32429 12 : details::is_constant_node(condition)
32430 : )
32431 : {
32432 0 : expression_node_ptr result = error_node();
32433 0 : if (details::is_true(condition))
32434 : {
32435 : // Infinite loops are not allowed.
32436 :
32437 0 : parser_->set_error(parser_error::make_error(
32438 : parser_error::e_parser,
32439 0 : parser_->current_state().token,
32440 : "ERR252 - Infinite loop condition without 'break' or 'return' not allowed in while-loops",
32441 : exprtk_error_location));
32442 :
32443 0 : result = error_node();
32444 : }
32445 : else
32446 0 : result = node_allocator_->allocate<details::null_node<Type> >();
32447 :
32448 0 : details::free_node(*node_allocator_, condition);
32449 0 : details::free_node(*node_allocator_, branch );
32450 :
32451 0 : return result;
32452 : }
32453 22 : else if (details::is_null_node(condition))
32454 : {
32455 0 : details::free_node(*node_allocator_,condition);
32456 :
32457 0 : return branch;
32458 : }
32459 :
32460 22 : loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop);
32461 :
32462 22 : if (!break_continue_present)
32463 : {
32464 12 : if (rtc)
32465 0 : return node_allocator_->allocate<while_loop_rtc_node_t>
32466 0 : (condition, branch, rtc);
32467 : else
32468 12 : return node_allocator_->allocate<while_loop_node_t>
32469 12 : (condition, branch);
32470 : }
32471 : #ifndef exprtk_disable_break_continue
32472 : else
32473 : {
32474 10 : if (rtc)
32475 0 : return node_allocator_->allocate<while_loop_bc_rtc_node_t>
32476 0 : (condition, branch, rtc);
32477 : else
32478 10 : return node_allocator_->allocate<while_loop_bc_node_t>
32479 10 : (condition, branch);
32480 : }
32481 : #else
32482 : return error_node();
32483 : #endif
32484 : }
32485 :
32486 82 : inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
32487 : expression_node_ptr& branch,
32488 : const bool break_continue_present = false) const
32489 : {
32490 82 : if (!break_continue_present && details::is_constant_node(condition))
32491 : {
32492 80 : if (
32493 160 : details::is_true(condition) &&
32494 80 : details::is_constant_node(branch)
32495 : )
32496 : {
32497 80 : free_node(*node_allocator_,condition);
32498 :
32499 80 : return branch;
32500 : }
32501 :
32502 0 : details::free_node(*node_allocator_, condition);
32503 0 : details::free_node(*node_allocator_, branch );
32504 :
32505 0 : return error_node();
32506 : }
32507 2 : else if (details::is_null_node(condition))
32508 : {
32509 0 : details::free_node(*node_allocator_,condition);
32510 :
32511 0 : return branch;
32512 : }
32513 :
32514 2 : loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop);
32515 :
32516 2 : if (!break_continue_present)
32517 : {
32518 1 : if (rtc)
32519 0 : return node_allocator_->allocate<repeat_until_loop_rtc_node_t>
32520 0 : (condition, branch, rtc);
32521 : else
32522 1 : return node_allocator_->allocate<repeat_until_loop_node_t>
32523 1 : (condition, branch);
32524 : }
32525 : #ifndef exprtk_disable_break_continue
32526 : else
32527 : {
32528 1 : if (rtc)
32529 0 : return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t>
32530 0 : (condition, branch, rtc);
32531 : else
32532 1 : return node_allocator_->allocate<repeat_until_loop_bc_node_t>
32533 1 : (condition, branch);
32534 : }
32535 : #else
32536 : return error_node();
32537 : #endif
32538 : }
32539 :
32540 2723 : inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
32541 : expression_node_ptr& condition,
32542 : expression_node_ptr& incrementor,
32543 : expression_node_ptr& loop_body,
32544 : bool break_continue_present = false) const
32545 : {
32546 2723 : if (
32547 4834 : !break_continue_present &&
32548 4827 : !parser_->state_.return_stmt_present &&
32549 2104 : details::is_constant_node(condition)
32550 : )
32551 : {
32552 0 : expression_node_ptr result = error_node();
32553 :
32554 0 : if (details::is_true(condition))
32555 : {
32556 : // Infinite loops are not allowed.
32557 :
32558 0 : parser_->set_error(parser_error::make_error(
32559 : parser_error::e_parser,
32560 0 : parser_->current_state().token,
32561 : "ERR253 - Infinite loop condition without 'break' or 'return' not allowed in for-loop",
32562 : exprtk_error_location));
32563 :
32564 0 : result = error_node();
32565 : }
32566 : else
32567 0 : result = node_allocator_->allocate<details::null_node<Type> >();
32568 :
32569 0 : details::free_node(*node_allocator_, initialiser);
32570 0 : details::free_node(*node_allocator_, condition );
32571 0 : details::free_node(*node_allocator_, incrementor);
32572 0 : details::free_node(*node_allocator_, loop_body );
32573 :
32574 0 : return result;
32575 : }
32576 2723 : else if (details::is_null_node(condition) || (0 == condition))
32577 : {
32578 0 : details::free_node(*node_allocator_, initialiser);
32579 0 : details::free_node(*node_allocator_, condition );
32580 0 : details::free_node(*node_allocator_, incrementor);
32581 :
32582 0 : return loop_body;
32583 : }
32584 :
32585 2723 : loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop);
32586 :
32587 2723 : if (!break_continue_present)
32588 : {
32589 2111 : if (rtc)
32590 0 : return node_allocator_->allocate<for_loop_rtc_node_t>
32591 0 : (
32592 : initialiser,
32593 : condition,
32594 : incrementor,
32595 : loop_body,
32596 : rtc
32597 0 : );
32598 : else
32599 2111 : return node_allocator_->allocate<for_loop_node_t>
32600 2111 : (
32601 : initialiser,
32602 : condition,
32603 : incrementor,
32604 : loop_body
32605 2111 : );
32606 : }
32607 : #ifndef exprtk_disable_break_continue
32608 : else
32609 : {
32610 612 : if (rtc)
32611 0 : return node_allocator_->allocate<for_loop_bc_rtc_node_t>
32612 0 : (
32613 : initialiser,
32614 : condition,
32615 : incrementor,
32616 : loop_body,
32617 : rtc
32618 0 : );
32619 : else
32620 612 : return node_allocator_->allocate<for_loop_bc_node_t>
32621 612 : (
32622 : initialiser,
32623 : condition,
32624 : incrementor,
32625 : loop_body
32626 612 : );
32627 : }
32628 : #else
32629 : return error_node();
32630 : #endif
32631 : }
32632 :
32633 : template <typename Allocator,
32634 : template <typename, typename> class Sequence>
32635 190 : inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
32636 : {
32637 190 : expression_node_ptr result = error_node();
32638 :
32639 190 : for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
32640 : {
32641 180 : expression_node_ptr condition = arg_list[(2 * i) ];
32642 180 : expression_node_ptr consequent = arg_list[(2 * i) + 1];
32643 :
32644 180 : if ((0 == result) && details::is_true(condition))
32645 : {
32646 180 : result = consequent;
32647 180 : break;
32648 : }
32649 : }
32650 :
32651 190 : if (0 == result)
32652 : {
32653 10 : result = arg_list.back();
32654 : }
32655 :
32656 740 : for (std::size_t i = 0; i < arg_list.size(); ++i)
32657 : {
32658 550 : expression_node_ptr current_expr = arg_list[i];
32659 :
32660 550 : if (current_expr && (current_expr != result))
32661 : {
32662 360 : free_node(*node_allocator_,current_expr);
32663 : }
32664 : }
32665 :
32666 190 : return result;
32667 : }
32668 :
32669 : template <typename Allocator,
32670 : template <typename, typename> class Sequence>
32671 10 : inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
32672 : {
32673 10 : expression_node_ptr result = error_node();
32674 :
32675 50 : for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
32676 : {
32677 40 : expression_node_ptr condition = arg_list[(2 * i) ];
32678 40 : expression_node_ptr consequent = arg_list[(2 * i) + 1];
32679 :
32680 40 : if (details::is_true(condition))
32681 : {
32682 40 : result = consequent;
32683 : }
32684 : }
32685 :
32686 10 : if (0 == result)
32687 : {
32688 0 : const T zero = T(0);
32689 0 : result = node_allocator_->allocate<literal_node_t>(zero);
32690 : }
32691 :
32692 90 : for (std::size_t i = 0; i < arg_list.size(); ++i)
32693 : {
32694 80 : expression_node_ptr& current_expr = arg_list[i];
32695 :
32696 80 : if (current_expr && (current_expr != result))
32697 : {
32698 70 : details::free_node(*node_allocator_,current_expr);
32699 : }
32700 : }
32701 :
32702 10 : return result;
32703 : }
32704 :
32705 : struct switch_nodes
32706 : {
32707 : typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
32708 :
32709 : #define case_stmt(N) \
32710 : if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
32711 :
32712 : struct switch_impl_1
32713 : {
32714 740 : static inline T process(const arg_list_t& arg)
32715 : {
32716 740 : case_stmt(0)
32717 :
32718 10 : assert(arg.size() == ((2 * 1) + 1));
32719 :
32720 10 : return arg.back().first->value();
32721 : }
32722 : };
32723 :
32724 : struct switch_impl_2
32725 : {
32726 11458441 : static inline T process(const arg_list_t& arg)
32727 : {
32728 11458441 : case_stmt(0) case_stmt(1)
32729 :
32730 5755024 : assert(arg.size() == ((2 * 2) + 1));
32731 :
32732 5755024 : return arg.back().first->value();
32733 : }
32734 : };
32735 :
32736 : struct switch_impl_3
32737 : {
32738 100 : static inline T process(const arg_list_t& arg)
32739 : {
32740 100 : case_stmt(0) case_stmt(1)
32741 99 : case_stmt(2)
32742 :
32743 98 : assert(arg.size() == ((2 * 3) + 1));
32744 :
32745 98 : return arg.back().first->value();
32746 : }
32747 : };
32748 :
32749 : struct switch_impl_4
32750 : {
32751 0 : static inline T process(const arg_list_t& arg)
32752 : {
32753 0 : case_stmt(0) case_stmt(1)
32754 0 : case_stmt(2) case_stmt(3)
32755 :
32756 0 : assert(arg.size() == ((2 * 4) + 1));
32757 :
32758 0 : return arg.back().first->value();
32759 : }
32760 : };
32761 :
32762 : struct switch_impl_5
32763 : {
32764 0 : static inline T process(const arg_list_t& arg)
32765 : {
32766 0 : case_stmt(0) case_stmt(1)
32767 0 : case_stmt(2) case_stmt(3)
32768 0 : case_stmt(4)
32769 :
32770 0 : assert(arg.size() == ((2 * 5) + 1));
32771 :
32772 0 : return arg.back().first->value();
32773 : }
32774 : };
32775 :
32776 : struct switch_impl_6
32777 : {
32778 136 : static inline T process(const arg_list_t& arg)
32779 : {
32780 136 : case_stmt(0) case_stmt(1)
32781 135 : case_stmt(2) case_stmt(3)
32782 133 : case_stmt(4) case_stmt(5)
32783 :
32784 132 : assert(arg.size() == ((2 * 6) + 1));
32785 :
32786 132 : return arg.back().first->value();
32787 : }
32788 : };
32789 :
32790 : struct switch_impl_7
32791 : {
32792 0 : static inline T process(const arg_list_t& arg)
32793 : {
32794 0 : case_stmt(0) case_stmt(1)
32795 0 : case_stmt(2) case_stmt(3)
32796 0 : case_stmt(4) case_stmt(5)
32797 0 : case_stmt(6)
32798 :
32799 0 : assert(arg.size() == ((2 * 7) + 1));
32800 :
32801 0 : return arg.back().first->value();
32802 : }
32803 : };
32804 :
32805 : #undef case_stmt
32806 : };
32807 :
32808 : template <typename Allocator,
32809 : template <typename, typename> class Sequence>
32810 1195 : inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
32811 : {
32812 1195 : if (arg_list.empty())
32813 0 : return error_node();
32814 1195 : else if (
32815 2390 : !all_nodes_valid(arg_list) ||
32816 1195 : (!default_statement_present && (arg_list.size() < 2))
32817 : )
32818 : {
32819 0 : details::free_all_nodes(*node_allocator_,arg_list);
32820 :
32821 0 : return error_node();
32822 : }
32823 1195 : else if (is_constant_foldable(arg_list))
32824 190 : return const_optimise_switch(arg_list);
32825 :
32826 1005 : switch ((arg_list.size() - 1) / 2)
32827 : {
32828 : #define case_stmt(N) \
32829 : case N : \
32830 : return node_allocator_-> \
32831 : allocate<details::switch_n_node \
32832 : <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \
32833 :
32834 740 : case_stmt(1)
32835 263 : case_stmt(2)
32836 1 : case_stmt(3)
32837 0 : case_stmt(4)
32838 0 : case_stmt(5)
32839 1 : case_stmt(6)
32840 0 : case_stmt(7)
32841 : #undef case_stmt
32842 :
32843 0 : default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
32844 : }
32845 : }
32846 :
32847 : template <typename Allocator,
32848 : template <typename, typename> class Sequence>
32849 190 : inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
32850 : {
32851 190 : if (!all_nodes_valid(arg_list))
32852 : {
32853 0 : details::free_all_nodes(*node_allocator_,arg_list);
32854 :
32855 0 : return error_node();
32856 : }
32857 190 : else if (is_constant_foldable(arg_list))
32858 10 : return const_optimise_mswitch(arg_list);
32859 : else
32860 180 : return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
32861 : }
32862 :
32863 84 : inline expression_node_ptr assert_call(expression_node_ptr& assert_condition,
32864 : expression_node_ptr& assert_message,
32865 : const assert_check::assert_context& context)
32866 : {
32867 : typedef details::assert_node<Type> alloc_type;
32868 :
32869 168 : expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type>
32870 84 : (assert_condition, assert_message, parser_->assert_check_, context);
32871 :
32872 84 : if (result && result->valid())
32873 : {
32874 168 : parser_->state_.activate_side_effect("assert_call()");
32875 84 : return result;
32876 : }
32877 :
32878 0 : details::free_node(*node_allocator_, result );
32879 0 : details::free_node(*node_allocator_, assert_condition);
32880 0 : details::free_node(*node_allocator_, assert_message );
32881 :
32882 0 : return error_node();
32883 : }
32884 :
32885 : #define unary_opr_switch_statements \
32886 : case_stmt(details::e_abs , details::abs_op ) \
32887 : case_stmt(details::e_acos , details::acos_op ) \
32888 : case_stmt(details::e_acosh , details::acosh_op) \
32889 : case_stmt(details::e_asin , details::asin_op ) \
32890 : case_stmt(details::e_asinh , details::asinh_op) \
32891 : case_stmt(details::e_atan , details::atan_op ) \
32892 : case_stmt(details::e_atanh , details::atanh_op) \
32893 : case_stmt(details::e_ceil , details::ceil_op ) \
32894 : case_stmt(details::e_cos , details::cos_op ) \
32895 : case_stmt(details::e_cosh , details::cosh_op ) \
32896 : case_stmt(details::e_exp , details::exp_op ) \
32897 : case_stmt(details::e_expm1 , details::expm1_op) \
32898 : case_stmt(details::e_floor , details::floor_op) \
32899 : case_stmt(details::e_log , details::log_op ) \
32900 : case_stmt(details::e_log10 , details::log10_op) \
32901 : case_stmt(details::e_log2 , details::log2_op ) \
32902 : case_stmt(details::e_log1p , details::log1p_op) \
32903 : case_stmt(details::e_neg , details::neg_op ) \
32904 : case_stmt(details::e_pos , details::pos_op ) \
32905 : case_stmt(details::e_round , details::round_op) \
32906 : case_stmt(details::e_sin , details::sin_op ) \
32907 : case_stmt(details::e_sinc , details::sinc_op ) \
32908 : case_stmt(details::e_sinh , details::sinh_op ) \
32909 : case_stmt(details::e_sqrt , details::sqrt_op ) \
32910 : case_stmt(details::e_tan , details::tan_op ) \
32911 : case_stmt(details::e_tanh , details::tanh_op ) \
32912 : case_stmt(details::e_cot , details::cot_op ) \
32913 : case_stmt(details::e_sec , details::sec_op ) \
32914 : case_stmt(details::e_csc , details::csc_op ) \
32915 : case_stmt(details::e_r2d , details::r2d_op ) \
32916 : case_stmt(details::e_d2r , details::d2r_op ) \
32917 : case_stmt(details::e_d2g , details::d2g_op ) \
32918 : case_stmt(details::e_g2d , details::g2d_op ) \
32919 : case_stmt(details::e_notl , details::notl_op ) \
32920 : case_stmt(details::e_sgn , details::sgn_op ) \
32921 : case_stmt(details::e_erf , details::erf_op ) \
32922 : case_stmt(details::e_erfc , details::erfc_op ) \
32923 : case_stmt(details::e_ncdf , details::ncdf_op ) \
32924 : case_stmt(details::e_frac , details::frac_op ) \
32925 : case_stmt(details::e_trunc , details::trunc_op) \
32926 :
32927 8332 : inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
32928 : expression_node_ptr (&branch)[1])
32929 : {
32930 8332 : T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
32931 :
32932 8332 : switch (operation)
32933 : {
32934 : #define case_stmt(op0, op1) \
32935 : case op0 : return node_allocator_-> \
32936 : allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
32937 :
32938 8332 : unary_opr_switch_statements
32939 : #undef case_stmt
32940 0 : default : return error_node();
32941 : }
32942 : }
32943 :
32944 2690 : inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
32945 : expression_node_ptr (&branch)[1])
32946 : {
32947 2690 : switch (operation)
32948 : {
32949 : #define case_stmt(op0, op1) \
32950 : case op0 : return node_allocator_-> \
32951 : allocate<typename details::unary_vector_node<Type,op1<Type> > > \
32952 : (operation, branch[0]); \
32953 :
32954 2690 : unary_opr_switch_statements
32955 : #undef case_stmt
32956 0 : default : return error_node();
32957 : }
32958 : }
32959 :
32960 59953 : inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
32961 : expression_node_ptr (&branch)[1])
32962 : {
32963 59953 : switch (operation)
32964 : {
32965 : #define case_stmt(op0, op1) \
32966 : case op0 : return node_allocator_-> \
32967 : allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
32968 :
32969 59953 : unary_opr_switch_statements
32970 : #undef case_stmt
32971 0 : default : return error_node();
32972 : }
32973 : }
32974 :
32975 720 : inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
32976 : expression_node_ptr (&branch)[3])
32977 : {
32978 720 : expression_node_ptr temp_node = error_node();
32979 :
32980 720 : switch (operation)
32981 : {
32982 : #define case_stmt(op) \
32983 : case details::e_sf##op : temp_node = node_allocator_-> \
32984 : allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
32985 : (operation, branch); \
32986 : break; \
32987 :
32988 60 : case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
32989 60 : case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
32990 60 : case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
32991 60 : case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
32992 60 : case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
32993 60 : case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
32994 60 : case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
32995 60 : case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
32996 60 : case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
32997 60 : case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
32998 60 : case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
32999 60 : case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
33000 : #undef case_stmt
33001 0 : default : return error_node();
33002 : }
33003 :
33004 720 : assert(temp_node);
33005 :
33006 720 : const T v = temp_node->value();
33007 :
33008 720 : details::free_node(*node_allocator_,temp_node);
33009 :
33010 720 : return node_allocator_->allocate<literal_node_t>(v);
33011 : }
33012 :
33013 1200 : inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
33014 : {
33015 : typedef details::variable_node<Type>* variable_ptr;
33016 :
33017 1200 : const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
33018 1200 : const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
33019 1200 : const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
33020 :
33021 1200 : switch (operation)
33022 : {
33023 : #define case_stmt(op) \
33024 : case details::e_sf##op : return node_allocator_-> \
33025 : allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
33026 : (v0, v1, v2); \
33027 :
33028 100 : case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
33029 100 : case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
33030 100 : case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
33031 100 : case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
33032 100 : case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
33033 100 : case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
33034 100 : case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
33035 100 : case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
33036 100 : case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
33037 100 : case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
33038 100 : case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
33039 100 : case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
33040 : #undef case_stmt
33041 0 : default : return error_node();
33042 : }
33043 : }
33044 :
33045 1920 : inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
33046 : {
33047 1920 : if (!all_nodes_valid(branch))
33048 0 : return error_node();
33049 1920 : else if (is_constant_foldable(branch))
33050 720 : return const_optimise_sf3(operation,branch);
33051 1200 : else if (all_nodes_variables(branch))
33052 1200 : return varnode_optimise_sf3(operation,branch);
33053 : else
33054 : {
33055 0 : switch (operation)
33056 : {
33057 : #define case_stmt(op) \
33058 : case details::e_sf##op : return node_allocator_-> \
33059 : allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
33060 : (operation, branch); \
33061 :
33062 0 : case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
33063 0 : case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
33064 0 : case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
33065 0 : case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
33066 0 : case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
33067 0 : case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
33068 0 : case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
33069 0 : case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
33070 0 : case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
33071 0 : case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
33072 0 : case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
33073 0 : case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
33074 : #undef case_stmt
33075 0 : default : return error_node();
33076 : }
33077 : }
33078 : }
33079 :
33080 815 : inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
33081 : {
33082 815 : expression_node_ptr temp_node = error_node();
33083 :
33084 815 : switch (operation)
33085 : {
33086 : #define case_stmt(op) \
33087 : case details::e_sf##op : temp_node = node_allocator_-> \
33088 : allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
33089 : (operation, branch); \
33090 : break; \
33091 :
33092 60 : case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
33093 60 : case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
33094 60 : case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
33095 60 : case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
33096 60 : case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
33097 60 : case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
33098 60 : case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
33099 60 : case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
33100 60 : case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
33101 60 : case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
33102 60 : case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
33103 80 : case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
33104 75 : case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
33105 : #undef case_stmt
33106 0 : default : return error_node();
33107 : }
33108 :
33109 815 : assert(temp_node);
33110 :
33111 815 : const T v = temp_node->value();
33112 :
33113 815 : details::free_node(*node_allocator_,temp_node);
33114 :
33115 815 : return node_allocator_->allocate<literal_node_t>(v);
33116 : }
33117 :
33118 1510 : inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
33119 : {
33120 : typedef details::variable_node<Type>* variable_ptr;
33121 :
33122 1510 : const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
33123 1510 : const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
33124 1510 : const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
33125 1510 : const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
33126 :
33127 1510 : switch (operation)
33128 : {
33129 : #define case_stmt(op) \
33130 : case details::e_sf##op : return node_allocator_-> \
33131 : allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
33132 : (v0, v1, v2, v3); \
33133 :
33134 100 : case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
33135 100 : case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
33136 100 : case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
33137 100 : case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
33138 100 : case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
33139 100 : case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
33140 100 : case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
33141 100 : case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
33142 100 : case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
33143 100 : case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
33144 100 : case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
33145 220 : case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
33146 190 : case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
33147 : #undef case_stmt
33148 0 : default : return error_node();
33149 : }
33150 : }
33151 :
33152 2325 : inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
33153 : {
33154 2325 : if (!all_nodes_valid(branch))
33155 0 : return error_node();
33156 2325 : else if (is_constant_foldable(branch))
33157 815 : return const_optimise_sf4(operation,branch);
33158 1510 : else if (all_nodes_variables(branch))
33159 1510 : return varnode_optimise_sf4(operation,branch);
33160 0 : switch (operation)
33161 : {
33162 : #define case_stmt(op) \
33163 : case details::e_sf##op : return node_allocator_-> \
33164 : allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
33165 : (operation, branch); \
33166 :
33167 0 : case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
33168 0 : case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
33169 0 : case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
33170 0 : case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
33171 0 : case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
33172 0 : case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
33173 0 : case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
33174 0 : case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
33175 0 : case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
33176 0 : case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
33177 0 : case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
33178 0 : case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
33179 0 : case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
33180 : #undef case_stmt
33181 0 : default : return error_node();
33182 : }
33183 : }
33184 :
33185 : template <typename Allocator,
33186 : template <typename, typename> class Sequence>
33187 1377 : inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
33188 : {
33189 1377 : expression_node_ptr temp_node = error_node();
33190 :
33191 1377 : switch (operation)
33192 : {
33193 : #define case_stmt(op0, op1) \
33194 : case op0 : temp_node = node_allocator_-> \
33195 : allocate<details::vararg_node<Type,op1<Type> > > \
33196 : (arg_list); \
33197 : break; \
33198 :
33199 160 : case_stmt(details::e_sum , details::vararg_add_op )
33200 160 : case_stmt(details::e_prod , details::vararg_mul_op )
33201 145 : case_stmt(details::e_avg , details::vararg_avg_op )
33202 227 : case_stmt(details::e_min , details::vararg_min_op )
33203 205 : case_stmt(details::e_max , details::vararg_max_op )
33204 240 : case_stmt(details::e_mand , details::vararg_mand_op )
33205 240 : case_stmt(details::e_mor , details::vararg_mor_op )
33206 0 : case_stmt(details::e_multi , details::vararg_multi_op)
33207 : #undef case_stmt
33208 0 : default : return error_node();
33209 : }
33210 :
33211 1377 : const T v = temp_node->value();
33212 :
33213 1377 : details::free_node(*node_allocator_,temp_node);
33214 :
33215 1377 : return node_allocator_->allocate<literal_node_t>(v);
33216 : }
33217 :
33218 24 : inline bool special_one_parameter_vararg(const details::operator_type& operation) const
33219 : {
33220 : return (
33221 24 : (details::e_sum == operation) ||
33222 0 : (details::e_prod == operation) ||
33223 0 : (details::e_avg == operation) ||
33224 24 : (details::e_min == operation) ||
33225 0 : (details::e_max == operation)
33226 24 : );
33227 : }
33228 :
33229 : template <typename Allocator,
33230 : template <typename, typename> class Sequence>
33231 2308 : inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation,
33232 : Sequence<expression_node_ptr,Allocator>& arg_list)
33233 : {
33234 2308 : switch (operation)
33235 : {
33236 : #define case_stmt(op0, op1) \
33237 : case op0 : return node_allocator_-> \
33238 : allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
33239 :
33240 1 : case_stmt(details::e_sum , details::vararg_add_op )
33241 1 : case_stmt(details::e_prod , details::vararg_mul_op )
33242 101 : case_stmt(details::e_avg , details::vararg_avg_op )
33243 2071 : case_stmt(details::e_min , details::vararg_min_op )
33244 101 : case_stmt(details::e_max , details::vararg_max_op )
33245 16 : case_stmt(details::e_mand , details::vararg_mand_op )
33246 17 : case_stmt(details::e_mor , details::vararg_mor_op )
33247 0 : case_stmt(details::e_multi , details::vararg_multi_op)
33248 : #undef case_stmt
33249 0 : default : return error_node();
33250 : }
33251 : }
33252 :
33253 : template <typename Allocator,
33254 : template <typename, typename> class Sequence>
33255 2401 : inline expression_node_ptr vectorize_func(const details::operator_type& operation,
33256 : Sequence<expression_node_ptr,Allocator>& arg_list)
33257 : {
33258 2401 : if (1 == arg_list.size())
33259 : {
33260 2401 : switch (operation)
33261 : {
33262 : #define case_stmt(op0, op1) \
33263 : case op0 : return node_allocator_-> \
33264 : allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
33265 :
33266 2016 : case_stmt(details::e_sum , details::vec_add_op)
33267 60 : case_stmt(details::e_prod , details::vec_mul_op)
33268 91 : case_stmt(details::e_avg , details::vec_avg_op)
33269 162 : case_stmt(details::e_min , details::vec_min_op)
33270 72 : case_stmt(details::e_max , details::vec_max_op)
33271 : #undef case_stmt
33272 0 : default : return error_node();
33273 : }
33274 : }
33275 : else
33276 0 : return error_node();
33277 : }
33278 :
33279 : template <typename Allocator,
33280 : template <typename, typename> class Sequence>
33281 49616 : inline expression_node_ptr vararg_function(const details::operator_type& operation,
33282 : Sequence<expression_node_ptr,Allocator>& arg_list)
33283 : {
33284 49616 : if (!all_nodes_valid(arg_list))
33285 : {
33286 0 : details::free_all_nodes(*node_allocator_,arg_list);
33287 :
33288 0 : return error_node();
33289 : }
33290 49616 : else if (is_constant_foldable(arg_list))
33291 1377 : return const_optimise_varargfunc(operation,arg_list);
33292 48239 : else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0]))
33293 2401 : return vectorize_func(operation,arg_list);
33294 45838 : else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation))
33295 24 : return arg_list[0];
33296 45814 : else if (all_nodes_variables(arg_list))
33297 2308 : return varnode_optimise_varargfunc(operation,arg_list);
33298 :
33299 : #ifndef exprtk_disable_string_capabilities
33300 43506 : if (details::e_smulti == operation)
33301 : {
33302 170 : expression_node_ptr result = node_allocator_->
33303 85 : allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
33304 85 : if (result && result->valid())
33305 : {
33306 85 : return result;
33307 : }
33308 :
33309 0 : parser_->set_error(parser_error::make_error(
33310 : parser_error::e_synthesis,
33311 0 : token_t(),
33312 : "ERR254 - Failed to synthesize node: str_vararg_node<vararg_multi_op>",
33313 : exprtk_error_location));
33314 :
33315 0 : details::free_node(*node_allocator_, result);
33316 : }
33317 : else
33318 : #endif
33319 : {
33320 43421 : expression_node_ptr result = error_node();
33321 :
33322 43421 : switch (operation)
33323 : {
33324 : #define case_stmt(op0, op1) \
33325 : case op0 : result = node_allocator_-> \
33326 : allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
33327 : break; \
33328 :
33329 3 : case_stmt(details::e_sum , details::vararg_add_op )
33330 3 : case_stmt(details::e_prod , details::vararg_mul_op )
33331 1 : case_stmt(details::e_avg , details::vararg_avg_op )
33332 1950 : case_stmt(details::e_min , details::vararg_min_op )
33333 1 : case_stmt(details::e_max , details::vararg_max_op )
33334 0 : case_stmt(details::e_mand , details::vararg_mand_op )
33335 0 : case_stmt(details::e_mor , details::vararg_mor_op )
33336 41463 : case_stmt(details::e_multi , details::vararg_multi_op)
33337 : #undef case_stmt
33338 43421 : default : return error_node();
33339 : }
33340 :
33341 43421 : if (result && result->valid())
33342 : {
33343 43421 : return result;
33344 : }
33345 :
33346 0 : parser_->set_error(parser_error::make_error(
33347 : parser_error::e_synthesis,
33348 0 : token_t(),
33349 : "ERR255 - Failed to synthesize node: vararg_node",
33350 : exprtk_error_location));
33351 :
33352 0 : details::free_node(*node_allocator_, result);
33353 : }
33354 :
33355 0 : return error_node();
33356 : }
33357 :
33358 : template <std::size_t N>
33359 60380 : inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
33360 : {
33361 : typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
33362 60380 : expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
33363 :
33364 60380 : if (0 == result)
33365 0 : return error_node();
33366 : else
33367 : {
33368 : // Can the function call be completely optimised?
33369 60380 : if (details::is_constant_node(result))
33370 120 : return result;
33371 60260 : else if (!all_nodes_valid(b))
33372 : {
33373 0 : details::free_node(*node_allocator_,result);
33374 0 : std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
33375 :
33376 0 : return error_node();
33377 : }
33378 60260 : else if (N != f->param_count)
33379 : {
33380 0 : details::free_node(*node_allocator_,result);
33381 0 : std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
33382 :
33383 0 : return error_node();
33384 : }
33385 :
33386 60260 : function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result);
33387 :
33388 60260 : if (!func_node_ptr->init_branches(b))
33389 : {
33390 0 : details::free_node(*node_allocator_,result);
33391 0 : std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
33392 :
33393 0 : return error_node();
33394 : }
33395 :
33396 60260 : if (result && result->valid())
33397 : {
33398 60260 : return result;
33399 : }
33400 :
33401 0 : parser_->set_error(parser_error::make_error(
33402 : parser_error::e_synthesis,
33403 0 : token_t(),
33404 : "ERR256 - Failed to synthesize node: function_N_node_t",
33405 : exprtk_error_location));
33406 :
33407 0 : details::free_node(*node_allocator_, result);
33408 0 : return error_node();
33409 : }
33410 : }
33411 :
33412 231 : inline expression_node_ptr function(ifunction_t* f)
33413 : {
33414 : typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
33415 231 : return node_allocator_->allocate<function_N_node_t>(f);
33416 : }
33417 :
33418 49 : inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
33419 : std::vector<expression_node_ptr>& arg_list)
33420 : {
33421 49 : if (!all_nodes_valid(arg_list))
33422 : {
33423 0 : details::free_all_nodes(*node_allocator_,arg_list);
33424 :
33425 0 : return error_node();
33426 : }
33427 :
33428 : typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
33429 :
33430 49 : expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
33431 :
33432 49 : if (
33433 49 : !arg_list.empty() &&
33434 49 : !vaf->has_side_effects() &&
33435 0 : is_constant_foldable(arg_list)
33436 : )
33437 : {
33438 0 : const Type v = result->value();
33439 0 : details::free_node(*node_allocator_,result);
33440 0 : result = node_allocator_->allocate<literal_node_t>(v);
33441 : }
33442 :
33443 98 : parser_->state_.activate_side_effect("vararg_function_call()");
33444 :
33445 49 : if (result && result->valid())
33446 : {
33447 49 : return result;
33448 : }
33449 :
33450 0 : parser_->set_error(parser_error::make_error(
33451 : parser_error::e_synthesis,
33452 0 : token_t(),
33453 : "ERR257 - Failed to synthesize node: vararg_function_node<ivararg_function_t>",
33454 : exprtk_error_location));
33455 :
33456 0 : details::free_node(*node_allocator_, result);
33457 0 : return error_node();
33458 : }
33459 :
33460 3536 : inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
33461 : std::vector<expression_node_ptr>& arg_list,
33462 : const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
33463 : {
33464 3536 : if (!all_nodes_valid(arg_list))
33465 : {
33466 0 : details::free_all_nodes(*node_allocator_,arg_list);
33467 0 : return error_node();
33468 : }
33469 :
33470 : typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1;
33471 : typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
33472 :
33473 3536 : const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
33474 :
33475 3536 : expression_node_ptr result = error_node();
33476 3536 : std::string node_name = "Unknown";
33477 :
33478 3536 : if (no_psi == param_seq_index)
33479 : {
33480 57 : result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
33481 57 : node_name = "generic_function_node<igeneric_function_t>";
33482 : }
33483 : else
33484 : {
33485 3479 : result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
33486 3479 : node_name = "multimode_genfunction_node<igeneric_function_t>";
33487 : }
33488 :
33489 3536 : alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
33490 :
33491 3536 : assert(genfunc_node_ptr);
33492 :
33493 3536 : if (
33494 3536 : !arg_list.empty() &&
33495 3521 : !gf->has_side_effects() &&
33496 7057 : parser_->state_.type_check_enabled &&
33497 0 : is_constant_foldable(arg_list)
33498 : )
33499 : {
33500 0 : genfunc_node_ptr->init_branches();
33501 :
33502 0 : const Type v = result->value();
33503 :
33504 0 : details::free_node(*node_allocator_,result);
33505 :
33506 0 : return node_allocator_->allocate<literal_node_t>(v);
33507 : }
33508 3536 : else if (genfunc_node_ptr->init_branches())
33509 : {
33510 3536 : if (result && result->valid())
33511 : {
33512 7072 : parser_->state_.activate_side_effect("generic_function_call()");
33513 3536 : return result;
33514 : }
33515 :
33516 0 : parser_->set_error(parser_error::make_error(
33517 : parser_error::e_synthesis,
33518 0 : token_t(),
33519 : "ERR258 - Failed to synthesize node: " + node_name,
33520 : exprtk_error_location));
33521 :
33522 0 : details::free_node(*node_allocator_, result);
33523 0 : return error_node();
33524 : }
33525 : else
33526 : {
33527 0 : details::free_node(*node_allocator_, result);
33528 0 : details::free_all_nodes(*node_allocator_, arg_list);
33529 :
33530 0 : return error_node();
33531 : }
33532 3536 : }
33533 :
33534 : #ifndef exprtk_disable_string_capabilities
33535 72 : inline expression_node_ptr string_function_call(igeneric_function_t* gf,
33536 : std::vector<expression_node_ptr>& arg_list,
33537 : const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
33538 : {
33539 72 : if (!all_nodes_valid(arg_list))
33540 : {
33541 0 : details::free_all_nodes(*node_allocator_,arg_list);
33542 0 : return error_node();
33543 : }
33544 :
33545 : typedef details::string_function_node <Type,igeneric_function_t> alloc_type1;
33546 : typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
33547 :
33548 72 : const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
33549 :
33550 72 : expression_node_ptr result = error_node();
33551 72 : std::string node_name = "Unknown";
33552 :
33553 72 : if (no_psi == param_seq_index)
33554 : {
33555 0 : result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
33556 0 : node_name = "string_function_node<igeneric_function_t>";
33557 : }
33558 : else
33559 : {
33560 72 : result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
33561 72 : node_name = "multimode_strfunction_node<igeneric_function_t>";
33562 : }
33563 :
33564 72 : alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
33565 :
33566 72 : assert(strfunc_node_ptr);
33567 :
33568 72 : if (
33569 72 : !arg_list.empty() &&
33570 72 : !gf->has_side_effects() &&
33571 0 : is_constant_foldable(arg_list)
33572 : )
33573 : {
33574 0 : strfunc_node_ptr->init_branches();
33575 :
33576 0 : const Type v = result->value();
33577 :
33578 0 : details::free_node(*node_allocator_,result);
33579 :
33580 0 : return node_allocator_->allocate<literal_node_t>(v);
33581 : }
33582 72 : else if (strfunc_node_ptr->init_branches())
33583 : {
33584 72 : if (result && result->valid())
33585 : {
33586 144 : parser_->state_.activate_side_effect("string_function_call()");
33587 72 : return result;
33588 : }
33589 :
33590 0 : parser_->set_error(parser_error::make_error(
33591 : parser_error::e_synthesis,
33592 0 : token_t(),
33593 : "ERR259 - Failed to synthesize node: " + node_name,
33594 : exprtk_error_location));
33595 :
33596 0 : details::free_node(*node_allocator_, result);
33597 0 : return error_node();
33598 : }
33599 : else
33600 : {
33601 0 : details::free_node (*node_allocator_,result );
33602 0 : details::free_all_nodes(*node_allocator_,arg_list);
33603 :
33604 0 : return error_node();
33605 : }
33606 72 : }
33607 : #endif
33608 :
33609 : #ifndef exprtk_disable_return_statement
33610 116 : inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
33611 : {
33612 116 : if (!all_nodes_valid(arg_list))
33613 : {
33614 0 : details::free_all_nodes(*node_allocator_,arg_list);
33615 0 : return error_node();
33616 : }
33617 :
33618 : typedef details::return_node<Type> alloc_type;
33619 :
33620 232 : expression_node_ptr result = node_allocator_->
33621 116 : allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
33622 :
33623 116 : alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
33624 :
33625 116 : assert(return_node_ptr);
33626 :
33627 116 : if (return_node_ptr->init_branches())
33628 : {
33629 116 : if (result && result->valid())
33630 : {
33631 232 : parser_->state_.activate_side_effect("return_call()");
33632 116 : return result;
33633 : }
33634 :
33635 0 : parser_->set_error(parser_error::make_error(
33636 : parser_error::e_synthesis,
33637 0 : token_t(),
33638 : "ERR260 - Failed to synthesize node: return_node",
33639 : exprtk_error_location));
33640 :
33641 0 : details::free_node(*node_allocator_, result);
33642 0 : return error_node();
33643 : }
33644 : else
33645 : {
33646 0 : details::free_node (*node_allocator_, result );
33647 0 : details::free_all_nodes(*node_allocator_, arg_list);
33648 :
33649 0 : return error_node();
33650 : }
33651 : }
33652 :
33653 111 : inline expression_node_ptr return_envelope(expression_node_ptr body,
33654 : results_context_t* rc,
33655 : bool*& return_invoked)
33656 : {
33657 : typedef details::return_envelope_node<Type> alloc_type;
33658 :
33659 111 : expression_node_ptr result = node_allocator_->
33660 111 : allocate_cr<alloc_type>(body,(*rc));
33661 :
33662 111 : return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
33663 :
33664 111 : return result;
33665 : }
33666 : #else
33667 : inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
33668 : {
33669 : return error_node();
33670 : }
33671 :
33672 : inline expression_node_ptr return_envelope(expression_node_ptr,
33673 : results_context_t*,
33674 : bool*&)
33675 : {
33676 : return error_node();
33677 : }
33678 : #endif
33679 :
33680 19542 : inline expression_node_ptr vector_element(const std::string& symbol,
33681 : vector_holder_ptr vector_base,
33682 : expression_node_ptr vec_node,
33683 : expression_node_ptr index)
33684 : {
33685 19542 : expression_node_ptr result = error_node();
33686 19542 : std::string node_name = "Unknown";
33687 :
33688 19542 : if (details::is_constant_node(index))
33689 : {
33690 14723 : const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
33691 :
33692 14723 : details::free_node(*node_allocator_,index);
33693 :
33694 14723 : if (vec_index >= vector_base->size())
33695 : {
33696 0 : parser_->set_error(parser_error::make_error(
33697 : parser_error::e_parser,
33698 0 : token_t(),
33699 : "ERR261 - Index of " + details::to_str(vec_index) + " out of range for "
33700 : "vector '" + symbol + "' of size " + details::to_str(vector_base->size()),
33701 : exprtk_error_location));
33702 :
33703 0 : details::free_node(*node_allocator_,vec_node);
33704 :
33705 2084 : return error_node();
33706 : }
33707 :
33708 14723 : if (vector_base->rebaseable())
33709 : {
33710 1894 : vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
33711 :
33712 1894 : result = (rtc) ?
33713 0 : node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
33714 1894 : node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ;
33715 :
33716 1894 : node_name = (rtc) ?
33717 : "rebasevector_elem_rtc_node_t" :
33718 : "rebasevector_elem_node_t" ;
33719 :
33720 1894 : if (result && result->valid())
33721 : {
33722 1894 : return result;
33723 : }
33724 :
33725 0 : parser_->set_error(parser_error::make_error(
33726 : parser_error::e_synthesis,
33727 0 : token_t(),
33728 : "ERR262 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
33729 : exprtk_error_location));
33730 :
33731 0 : details::free_node(*node_allocator_, result);
33732 0 : return error_node();
33733 : }
33734 12829 : else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node))
33735 : {
33736 190 : vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
33737 :
33738 190 : result = (rtc) ?
33739 0 : node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) :
33740 190 : node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ;
33741 :
33742 190 : node_name = (rtc) ?
33743 : "vector_elem_rtc_node_t" :
33744 : "vector_elem_node_t" ;
33745 :
33746 190 : if (result && result->valid())
33747 : {
33748 190 : return result;
33749 : }
33750 :
33751 0 : parser_->set_error(parser_error::make_error(
33752 : parser_error::e_synthesis,
33753 0 : token_t(),
33754 : "ERR263 - Failed to synthesize node: " + node_name + " for vector: " + symbol,
33755 : exprtk_error_location));
33756 :
33757 0 : details::free_node(*node_allocator_, result);
33758 0 : return error_node();
33759 : }
33760 :
33761 12639 : const scope_element& se = parser_->sem_.get_element(symbol,vec_index);
33762 :
33763 12639 : if (se.index == vec_index)
33764 : {
33765 1580 : result = se.var_node;
33766 1580 : details::free_node(*node_allocator_,vec_node);
33767 : }
33768 : else
33769 : {
33770 11059 : scope_element nse;
33771 11059 : nse.name = symbol;
33772 11059 : nse.active = true;
33773 11059 : nse.ref_count = 1;
33774 11059 : nse.type = scope_element::e_vecelem;
33775 11059 : nse.index = vec_index;
33776 11059 : nse.depth = parser_->state_.scope_depth;
33777 11059 : nse.data = 0;
33778 11059 : nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index]));
33779 :
33780 11059 : if (!parser_->sem_.add_element(nse))
33781 : {
33782 0 : parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
33783 :
33784 0 : parser_->sem_.free_element(nse);
33785 :
33786 0 : result = error_node();
33787 : }
33788 :
33789 11059 : details::free_node(*node_allocator_,vec_node);
33790 :
33791 : exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str()));
33792 :
33793 22118 : parser_->state_.activate_side_effect("vector_element()");
33794 :
33795 11059 : result = nse.var_node;
33796 11059 : node_name = "variable_node_t";
33797 11059 : }
33798 : }
33799 : else
33800 : {
33801 4819 : vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check();
33802 :
33803 4819 : if (vector_base->rebaseable())
33804 : {
33805 1016 : result = (rtc) ?
33806 2 : node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
33807 1014 : node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ;
33808 :
33809 1016 : node_name = (rtc) ?
33810 : "rebasevector_elem_rtc_node_t" :
33811 : "rebasevector_elem_node_t" ;
33812 : }
33813 : else
33814 : {
33815 3803 : result = rtc ?
33816 92 : node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) :
33817 3711 : node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ;
33818 :
33819 3803 : node_name = (rtc) ?
33820 : "vector_elem_rtc_node_t" :
33821 : "vector_elem_node_t" ;
33822 : }
33823 : }
33824 :
33825 17458 : if (result && result->valid())
33826 : {
33827 17458 : return result;
33828 : }
33829 :
33830 0 : parser_->set_error(parser_error::make_error(
33831 : parser_error::e_synthesis,
33832 0 : token_t(),
33833 : "ERR264 - Failed to synthesize node: " + node_name,
33834 : exprtk_error_location));
33835 :
33836 0 : details::free_node(*node_allocator_, result);
33837 0 : return error_node();
33838 19542 : }
33839 :
33840 : private:
33841 :
33842 : template <std::size_t N, typename NodePtr>
33843 686855 : inline bool is_constant_foldable(NodePtr (&b)[N]) const
33844 : {
33845 1415881 : for (std::size_t i = 0; i < N; ++i)
33846 : {
33847 1112548 : if (0 == b[i])
33848 0 : return false;
33849 1112548 : else if (!details::is_constant_node(b[i]))
33850 383522 : return false;
33851 : }
33852 :
33853 303333 : return true;
33854 : }
33855 :
33856 : template <typename NodePtr,
33857 : typename Allocator,
33858 : template <typename, typename> class Sequence>
33859 51001 : inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
33860 : {
33861 56177 : for (std::size_t i = 0; i < b.size(); ++i)
33862 : {
33863 54600 : if (0 == b[i])
33864 0 : return false;
33865 54600 : else if (!details::is_constant_node(b[i]))
33866 49424 : return false;
33867 : }
33868 :
33869 1577 : return true;
33870 : }
33871 :
33872 76654 : void lodge_assignment(symbol_type cst, expression_node_ptr node)
33873 : {
33874 153308 : parser_->state_.activate_side_effect("lodge_assignment()");
33875 :
33876 76654 : if (!parser_->dec_.collect_assignments())
33877 76650 : return;
33878 :
33879 4 : std::string symbol_name;
33880 :
33881 4 : switch (cst)
33882 : {
33883 3 : case e_st_variable : symbol_name = parser_->symtab_store_
33884 : .get_variable_name(node);
33885 3 : break;
33886 :
33887 : #ifndef exprtk_disable_string_capabilities
33888 1 : case e_st_string : symbol_name = parser_->symtab_store_
33889 : .get_stringvar_name(node);
33890 1 : break;
33891 : #endif
33892 :
33893 0 : case e_st_vector : {
33894 : typedef details::vector_holder<T> vector_holder_t;
33895 :
33896 0 : vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
33897 :
33898 0 : symbol_name = parser_->symtab_store_.get_vector_name(&vh);
33899 : }
33900 0 : break;
33901 :
33902 0 : case e_st_vecelem : {
33903 : typedef details::vector_holder<T> vector_holder_t;
33904 :
33905 0 : vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
33906 :
33907 0 : symbol_name = parser_->symtab_store_.get_vector_name(&vh);
33908 :
33909 0 : cst = e_st_vector;
33910 : }
33911 0 : break;
33912 :
33913 0 : default : return;
33914 : }
33915 :
33916 4 : if (!symbol_name.empty())
33917 : {
33918 4 : parser_->dec_.add_assignment(symbol_name,cst);
33919 : }
33920 4 : }
33921 :
33922 76682 : const void* base_ptr(expression_node_ptr node)
33923 : {
33924 76682 : if (node)
33925 : {
33926 76682 : switch(node->type())
33927 : {
33928 51074 : case details::expression_node<T>::e_variable:
33929 51074 : return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref());
33930 :
33931 585 : case details::expression_node<T>::e_vecelem:
33932 585 : return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref());
33933 :
33934 0 : case details::expression_node<T>::e_veccelem:
33935 0 : return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref());
33936 :
33937 32 : case details::expression_node<T>::e_vecelemrtc:
33938 32 : return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref());
33939 :
33940 0 : case details::expression_node<T>::e_veccelemrtc:
33941 0 : return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref());
33942 :
33943 300 : case details::expression_node<T>::e_rbvecelem:
33944 300 : return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref());
33945 :
33946 0 : case details::expression_node<T>::e_rbvecelemrtc:
33947 0 : return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref());
33948 :
33949 300 : case details::expression_node<T>::e_rbveccelem:
33950 300 : return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref());
33951 :
33952 0 : case details::expression_node<T>::e_rbveccelemrtc:
33953 0 : return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref());
33954 :
33955 4937 : case details::expression_node<T>::e_vector:
33956 4937 : return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data());
33957 :
33958 : #ifndef exprtk_disable_string_capabilities
33959 14592 : case details::expression_node<T>::e_stringvar:
33960 14592 : return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base()));
33961 :
33962 4862 : case details::expression_node<T>::e_stringvarrng:
33963 4862 : return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base()));
33964 : #endif
33965 0 : default : return reinterpret_cast<const void*>(0);
33966 : }
33967 : }
33968 :
33969 0 : return reinterpret_cast<const void*>(0);
33970 : }
33971 :
33972 76682 : bool assign_immutable_symbol(expression_node_ptr node)
33973 : {
33974 76682 : interval_t interval;
33975 76682 : const void* baseptr_addr = base_ptr(node);
33976 :
33977 : exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr));
33978 :
33979 76682 : if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval))
33980 : {
33981 28 : typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval);
33982 :
33983 28 : if (parser_->immutable_symtok_map_.end() != itr)
33984 : {
33985 28 : token_t& token = itr->second;
33986 56 : parser_->set_error(parser_error::make_error(
33987 : parser_error::e_parser,
33988 : token,
33989 28 : "ERR265 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.",
33990 : exprtk_error_location));
33991 : }
33992 : else
33993 0 : parser_->set_synthesis_error("Unable to assign symbol is immutable.");
33994 :
33995 28 : return true;
33996 : }
33997 :
33998 76654 : return false;
33999 : }
34000 :
34001 64826 : inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34002 : {
34003 64826 : if (assign_immutable_symbol(branch[0]))
34004 : {
34005 17 : return error_node();
34006 : }
34007 64809 : else if (details::is_variable_node(branch[0]))
34008 : {
34009 46190 : lodge_assignment(e_st_variable,branch[0]);
34010 46190 : return synthesize_expression<assignment_node_t,2>(operation,branch);
34011 : }
34012 18619 : else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0]))
34013 : {
34014 83 : lodge_assignment(e_st_vecelem,branch[0]);
34015 83 : return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
34016 : }
34017 18536 : else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0]))
34018 : {
34019 20 : lodge_assignment(e_st_vecelem,branch[0]);
34020 20 : return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch);
34021 : }
34022 18516 : else if (details::is_rebasevector_elem_node(branch[0]))
34023 : {
34024 0 : lodge_assignment(e_st_vecelem,branch[0]);
34025 0 : return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
34026 : }
34027 18516 : else if (details::is_rebasevector_elem_rtc_node(branch[0]))
34028 : {
34029 0 : lodge_assignment(e_st_vecelem,branch[0]);
34030 0 : return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch);
34031 : }
34032 18516 : else if (details::is_rebasevector_celem_node(branch[0]))
34033 : {
34034 0 : lodge_assignment(e_st_vecelem,branch[0]);
34035 0 : return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
34036 : }
34037 : #ifndef exprtk_disable_string_capabilities
34038 18516 : else if (details::is_string_node(branch[0]))
34039 : {
34040 11991 : lodge_assignment(e_st_string,branch[0]);
34041 11991 : return synthesize_expression<assignment_string_node_t,2>(operation, branch);
34042 : }
34043 6525 : else if (details::is_string_range_node(branch[0]))
34044 : {
34045 4850 : lodge_assignment(e_st_string,branch[0]);
34046 4850 : return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
34047 : }
34048 : #endif
34049 1675 : else if (details::is_vector_node(branch[0]))
34050 : {
34051 1675 : lodge_assignment(e_st_vector,branch[0]);
34052 :
34053 1675 : if (details::is_ivector_node(branch[1]))
34054 1471 : return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
34055 : else
34056 204 : return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
34057 : }
34058 0 : else if (details::is_literal_node(branch[0]))
34059 : {
34060 0 : parser_->set_error(parser_error::make_error(
34061 : parser_error::e_syntax,
34062 0 : parser_->current_state().token,
34063 : "ERR266 - Cannot assign value to const variable",
34064 : exprtk_error_location));
34065 :
34066 0 : return error_node();
34067 : }
34068 : else
34069 : {
34070 0 : parser_->set_error(parser_error::make_error(
34071 : parser_error::e_syntax,
34072 0 : parser_->current_state().token,
34073 : "ERR267 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
34074 : exprtk_error_location));
34075 :
34076 0 : return error_node();
34077 : }
34078 : }
34079 :
34080 11856 : inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
34081 : expression_node_ptr (&branch)[2])
34082 : {
34083 11856 : if (assign_immutable_symbol(branch[0]))
34084 : {
34085 11 : return error_node();
34086 : }
34087 :
34088 11845 : expression_node_ptr result = error_node();
34089 11845 : std::string node_name = "Unknown";
34090 :
34091 11845 : if (details::is_variable_node(branch[0]))
34092 : {
34093 4875 : lodge_assignment(e_st_variable,branch[0]);
34094 :
34095 4875 : switch (operation)
34096 : {
34097 : #define case_stmt(op0, op1) \
34098 : case op0 : result = node_allocator_-> \
34099 : template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
34100 : (operation, branch[0], branch[1]); \
34101 : node_name = "assignment_op_node"; \
34102 : break; \
34103 :
34104 4315 : case_stmt(details::e_addass , details::add_op)
34105 245 : case_stmt(details::e_subass , details::sub_op)
34106 120 : case_stmt(details::e_mulass , details::mul_op)
34107 120 : case_stmt(details::e_divass , details::div_op)
34108 75 : case_stmt(details::e_modass , details::mod_op)
34109 : #undef case_stmt
34110 0 : default : return error_node();
34111 : }
34112 : }
34113 6970 : else if (details::is_vector_elem_node(branch[0]))
34114 : {
34115 500 : lodge_assignment(e_st_vecelem,branch[0]);
34116 :
34117 500 : switch (operation)
34118 : {
34119 : #define case_stmt(op0, op1) \
34120 : case op0 : result = node_allocator_-> \
34121 : template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
34122 : (operation, branch[0], branch[1]); \
34123 : node_name = "assignment_vec_elem_op_node"; \
34124 : break; \
34125 :
34126 230 : case_stmt(details::e_addass , details::add_op)
34127 170 : case_stmt(details::e_subass , details::sub_op)
34128 50 : case_stmt(details::e_mulass , details::mul_op)
34129 50 : case_stmt(details::e_divass , details::div_op)
34130 0 : case_stmt(details::e_modass , details::mod_op)
34131 : #undef case_stmt
34132 0 : default : return error_node();
34133 : }
34134 : }
34135 6470 : else if (details::is_vector_elem_rtc_node(branch[0]))
34136 : {
34137 12 : lodge_assignment(e_st_vecelem,branch[0]);
34138 :
34139 12 : switch (operation)
34140 : {
34141 : #define case_stmt(op0, op1) \
34142 : case op0 : result = node_allocator_-> \
34143 : template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \
34144 : (operation, branch[0], branch[1]); \
34145 : node_name = "assignment_vec_elem_op_rtc_node"; \
34146 : break; \
34147 :
34148 8 : case_stmt(details::e_addass , details::add_op)
34149 4 : case_stmt(details::e_subass , details::sub_op)
34150 0 : case_stmt(details::e_mulass , details::mul_op)
34151 0 : case_stmt(details::e_divass , details::div_op)
34152 0 : case_stmt(details::e_modass , details::mod_op)
34153 : #undef case_stmt
34154 0 : default : return error_node();
34155 : }
34156 : }
34157 6458 : else if (details::is_vector_celem_rtc_node(branch[0]))
34158 : {
34159 0 : lodge_assignment(e_st_vecelem,branch[0]);
34160 :
34161 0 : switch (operation)
34162 : {
34163 : #define case_stmt(op0, op1) \
34164 : case op0 : result = node_allocator_-> \
34165 : template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \
34166 : (operation, branch[0], branch[1]); \
34167 : node_name = "assignment_vec_celem_op_rtc_node"; \
34168 : break; \
34169 :
34170 0 : case_stmt(details::e_addass , details::add_op)
34171 0 : case_stmt(details::e_subass , details::sub_op)
34172 0 : case_stmt(details::e_mulass , details::mul_op)
34173 0 : case_stmt(details::e_divass , details::div_op)
34174 0 : case_stmt(details::e_modass , details::mod_op)
34175 : #undef case_stmt
34176 0 : default : return error_node();
34177 : }
34178 : }
34179 6458 : else if (details::is_rebasevector_elem_node(branch[0]))
34180 : {
34181 300 : lodge_assignment(e_st_vecelem,branch[0]);
34182 :
34183 300 : switch (operation)
34184 : {
34185 : #define case_stmt(op0, op1) \
34186 : case op0 : result = node_allocator_-> \
34187 : template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
34188 : (operation, branch[0], branch[1]); \
34189 : node_name = "assignment_rebasevec_elem_op_node"; \
34190 : break; \
34191 :
34192 180 : case_stmt(details::e_addass , details::add_op)
34193 120 : case_stmt(details::e_subass , details::sub_op)
34194 0 : case_stmt(details::e_mulass , details::mul_op)
34195 0 : case_stmt(details::e_divass , details::div_op)
34196 0 : case_stmt(details::e_modass , details::mod_op)
34197 : #undef case_stmt
34198 0 : default : return error_node();
34199 : }
34200 : }
34201 6158 : else if (details::is_rebasevector_celem_node(branch[0]))
34202 : {
34203 300 : lodge_assignment(e_st_vecelem,branch[0]);
34204 :
34205 300 : switch (operation)
34206 : {
34207 : #define case_stmt(op0, op1) \
34208 : case op0 : result = node_allocator_-> \
34209 : template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
34210 : (operation, branch[0], branch[1]); \
34211 : node_name = "assignment_rebasevec_celem_op_node"; \
34212 : break; \
34213 :
34214 180 : case_stmt(details::e_addass , details::add_op)
34215 120 : case_stmt(details::e_subass , details::sub_op)
34216 0 : case_stmt(details::e_mulass , details::mul_op)
34217 0 : case_stmt(details::e_divass , details::div_op)
34218 0 : case_stmt(details::e_modass , details::mod_op)
34219 : #undef case_stmt
34220 0 : default : return error_node();
34221 : }
34222 : }
34223 5858 : else if (details::is_rebasevector_elem_rtc_node(branch[0]))
34224 : {
34225 0 : lodge_assignment(e_st_vecelem,branch[0]);
34226 :
34227 0 : switch (operation)
34228 : {
34229 : #define case_stmt(op0, op1) \
34230 : case op0 : result = node_allocator_-> \
34231 : template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \
34232 : (operation, branch[0], branch[1]); \
34233 : node_name = "assignment_rebasevec_elem_op_rtc_node"; \
34234 : break; \
34235 :
34236 0 : case_stmt(details::e_addass , details::add_op)
34237 0 : case_stmt(details::e_subass , details::sub_op)
34238 0 : case_stmt(details::e_mulass , details::mul_op)
34239 0 : case_stmt(details::e_divass , details::div_op)
34240 0 : case_stmt(details::e_modass , details::mod_op)
34241 : #undef case_stmt
34242 0 : default : return error_node();
34243 : }
34244 : }
34245 5858 : else if (details::is_rebasevector_celem_rtc_node(branch[0]))
34246 : {
34247 0 : lodge_assignment(e_st_vecelem,branch[0]);
34248 :
34249 0 : switch (operation)
34250 : {
34251 : #define case_stmt(op0, op1) \
34252 : case op0 : result = node_allocator_-> \
34253 : template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \
34254 : (operation, branch[0], branch[1]); \
34255 : node_name = "assignment_rebasevec_celem_op_rtc_node"; \
34256 : break; \
34257 :
34258 0 : case_stmt(details::e_addass , details::add_op)
34259 0 : case_stmt(details::e_subass , details::sub_op)
34260 0 : case_stmt(details::e_mulass , details::mul_op)
34261 0 : case_stmt(details::e_divass , details::div_op)
34262 0 : case_stmt(details::e_modass , details::mod_op)
34263 : #undef case_stmt
34264 0 : default : return error_node();
34265 : }
34266 : }
34267 5858 : else if (details::is_vector_node(branch[0]))
34268 : {
34269 3258 : lodge_assignment(e_st_vector,branch[0]);
34270 :
34271 3258 : if (details::is_ivector_node(branch[1]))
34272 : {
34273 766 : switch (operation)
34274 : {
34275 : #define case_stmt(op0, op1) \
34276 : case op0 : result = node_allocator_-> \
34277 : template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
34278 : (operation, branch[0], branch[1]); \
34279 : node_name = "assignment_rebasevec_celem_op_node"; \
34280 : break; \
34281 :
34282 526 : case_stmt(details::e_addass , details::add_op)
34283 80 : case_stmt(details::e_subass , details::sub_op)
34284 80 : case_stmt(details::e_mulass , details::mul_op)
34285 80 : case_stmt(details::e_divass , details::div_op)
34286 0 : case_stmt(details::e_modass , details::mod_op)
34287 : #undef case_stmt
34288 0 : default : return error_node();
34289 : }
34290 : }
34291 : else
34292 : {
34293 2492 : switch (operation)
34294 : {
34295 : #define case_stmt(op0, op1) \
34296 : case op0 : result = node_allocator_-> \
34297 : template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
34298 : (operation, branch[0], branch[1]); \
34299 : node_name = "assignment_vec_op_node"; \
34300 : break; \
34301 :
34302 2027 : case_stmt(details::e_addass , details::add_op)
34303 305 : case_stmt(details::e_subass , details::sub_op)
34304 80 : case_stmt(details::e_mulass , details::mul_op)
34305 80 : case_stmt(details::e_divass , details::div_op)
34306 0 : case_stmt(details::e_modass , details::mod_op)
34307 : #undef case_stmt
34308 0 : default : return error_node();
34309 : }
34310 : }
34311 : }
34312 : #ifndef exprtk_disable_string_capabilities
34313 2600 : else if (
34314 5200 : (details::e_addass == operation) &&
34315 2600 : details::is_string_node(branch[0])
34316 : )
34317 : {
34318 : typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
34319 :
34320 2600 : lodge_assignment(e_st_string,branch[0]);
34321 :
34322 2600 : result = synthesize_expression<addass_t,2>(operation,branch);
34323 2600 : node_name = "assignment_string_node<T,details::asn_addassignment>";
34324 : }
34325 : #endif
34326 : else
34327 : {
34328 0 : parser_->set_error(parser_error::make_error(
34329 : parser_error::e_syntax,
34330 0 : parser_->current_state().token,
34331 : "ERR268 - Invalid branches for assignment operator '" + details::to_str(operation) + "'",
34332 : exprtk_error_location));
34333 :
34334 0 : return error_node();
34335 : }
34336 :
34337 11845 : if (result && result->valid())
34338 : {
34339 11845 : return result;
34340 : }
34341 :
34342 0 : parser_->set_error(parser_error::make_error(
34343 : parser_error::e_synthesis,
34344 0 : token_t(),
34345 : "ERR269 - Failed to synthesize node: " + node_name,
34346 : exprtk_error_location));
34347 :
34348 0 : details::free_node(*node_allocator_, result);
34349 0 : return error_node();
34350 11845 : }
34351 :
34352 6457 : inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
34353 : expression_node_ptr (&branch)[2])
34354 : {
34355 6457 : const bool is_b0_ivec = details::is_ivector_node(branch[0]);
34356 6457 : const bool is_b1_ivec = details::is_ivector_node(branch[1]);
34357 :
34358 : #define batch_eqineq_logic_case \
34359 : case_stmt(details::e_lt , details::lt_op ) \
34360 : case_stmt(details::e_lte , details::lte_op ) \
34361 : case_stmt(details::e_gt , details::gt_op ) \
34362 : case_stmt(details::e_gte , details::gte_op ) \
34363 : case_stmt(details::e_eq , details::eq_op ) \
34364 : case_stmt(details::e_ne , details::ne_op ) \
34365 : case_stmt(details::e_equal , details::equal_op) \
34366 : case_stmt(details::e_and , details::and_op ) \
34367 : case_stmt(details::e_nand , details::nand_op ) \
34368 : case_stmt(details::e_or , details::or_op ) \
34369 : case_stmt(details::e_nor , details::nor_op ) \
34370 : case_stmt(details::e_xor , details::xor_op ) \
34371 : case_stmt(details::e_xnor , details::xnor_op ) \
34372 :
34373 6457 : expression_node_ptr result = error_node();
34374 6457 : std::string node_name = "Unknown";
34375 :
34376 6457 : if (is_b0_ivec && is_b1_ivec)
34377 : {
34378 5577 : switch (operation)
34379 : {
34380 : #define case_stmt(op0, op1) \
34381 : case op0 : result = node_allocator_-> \
34382 : template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
34383 : (operation, branch[0], branch[1]); \
34384 : node_name = "vec_binop_vecvec_node"; \
34385 : break; \
34386 :
34387 5577 : batch_eqineq_logic_case
34388 : #undef case_stmt
34389 0 : default : return error_node();
34390 : }
34391 : }
34392 880 : else if (is_b0_ivec && !is_b1_ivec)
34393 : {
34394 400 : switch (operation)
34395 : {
34396 : #define case_stmt(op0, op1) \
34397 : case op0 : result = node_allocator_-> \
34398 : template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
34399 : (operation, branch[0], branch[1]); \
34400 : node_name = "vec_binop_vecval_node"; \
34401 : break; \
34402 :
34403 400 : batch_eqineq_logic_case
34404 : #undef case_stmt
34405 0 : default : return error_node();
34406 : }
34407 : }
34408 480 : else if (!is_b0_ivec && is_b1_ivec)
34409 : {
34410 480 : switch (operation)
34411 : {
34412 : #define case_stmt(op0, op1) \
34413 : case op0 : result = node_allocator_-> \
34414 : template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
34415 : (operation, branch[0], branch[1]); \
34416 : node_name = "vec_binop_valvec_node"; \
34417 : break; \
34418 :
34419 480 : batch_eqineq_logic_case
34420 : #undef case_stmt
34421 0 : default : return error_node();
34422 : }
34423 : }
34424 : else
34425 0 : return error_node();
34426 :
34427 6457 : if (result && result->valid())
34428 : {
34429 6457 : return result;
34430 : }
34431 :
34432 0 : parser_->set_error(parser_error::make_error(
34433 : parser_error::e_synthesis,
34434 0 : token_t(),
34435 : "ERR270 - Failed to synthesize node: " + node_name,
34436 : exprtk_error_location));
34437 :
34438 0 : details::free_node(*node_allocator_, result);
34439 0 : return error_node();
34440 :
34441 : #undef batch_eqineq_logic_case
34442 6457 : }
34443 :
34444 12299 : inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
34445 : expression_node_ptr (&branch)[2])
34446 : {
34447 12299 : const bool is_b0_ivec = details::is_ivector_node(branch[0]);
34448 12299 : const bool is_b1_ivec = details::is_ivector_node(branch[1]);
34449 :
34450 : #define vector_ops \
34451 : case_stmt(details::e_add , details::add_op) \
34452 : case_stmt(details::e_sub , details::sub_op) \
34453 : case_stmt(details::e_mul , details::mul_op) \
34454 : case_stmt(details::e_div , details::div_op) \
34455 : case_stmt(details::e_mod , details::mod_op) \
34456 :
34457 12299 : expression_node_ptr result = error_node();
34458 12299 : std::string node_name = "Unknown";
34459 :
34460 12299 : if (is_b0_ivec && is_b1_ivec)
34461 : {
34462 4978 : switch (operation)
34463 : {
34464 : #define case_stmt(op0, op1) \
34465 : case op0 : result = node_allocator_-> \
34466 : template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
34467 : (operation, branch[0], branch[1]); \
34468 : node_name = "vec_binop_vecvec_node"; \
34469 : break; \
34470 :
34471 4978 : vector_ops
34472 0 : case_stmt(details::e_pow,details:: pow_op)
34473 : #undef case_stmt
34474 0 : default : return error_node();
34475 : }
34476 : }
34477 7321 : else if (is_b0_ivec && !is_b1_ivec)
34478 : {
34479 3599 : switch (operation)
34480 : {
34481 : #define case_stmt(op0, op1) \
34482 : case op0 : result = node_allocator_-> \
34483 : template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
34484 : (operation, branch[0], branch[1]); \
34485 : node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)"; \
34486 : break; \
34487 :
34488 3559 : vector_ops
34489 40 : case_stmt(details::e_pow,details:: pow_op)
34490 : #undef case_stmt
34491 0 : default : return error_node();
34492 : }
34493 : }
34494 3722 : else if (!is_b0_ivec && is_b1_ivec)
34495 : {
34496 3722 : switch (operation)
34497 : {
34498 : #define case_stmt(op0, op1) \
34499 : case op0 : result = node_allocator_-> \
34500 : template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
34501 : (operation, branch[0], branch[1]); \
34502 : node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)"; \
34503 : break; \
34504 :
34505 3722 : vector_ops
34506 : #undef case_stmt
34507 0 : default : return error_node();
34508 : }
34509 : }
34510 : else
34511 0 : return error_node();
34512 :
34513 12299 : if (result && result->valid())
34514 : {
34515 12299 : return result;
34516 : }
34517 :
34518 0 : parser_->set_error(parser_error::make_error(
34519 : parser_error::e_synthesis,
34520 0 : token_t(),
34521 : "ERR271 - Failed to synthesize node: " + node_name,
34522 : exprtk_error_location));
34523 :
34524 0 : details::free_node(*node_allocator_, result);
34525 0 : return error_node();
34526 :
34527 : #undef vector_ops
34528 12299 : }
34529 :
34530 2728 : inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
34531 : {
34532 2728 : const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
34533 2728 : const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
34534 :
34535 2728 : const bool v0_is_ivec = details::is_ivector_node (branch[0]);
34536 2728 : const bool v1_is_ivec = details::is_ivector_node (branch[1]);
34537 :
34538 : #ifndef exprtk_disable_string_capabilities
34539 2728 : const bool v0_is_str = details::is_generally_string_node(branch[0]);
34540 2728 : const bool v1_is_str = details::is_generally_string_node(branch[1]);
34541 : #endif
34542 :
34543 2728 : expression_node_ptr result = error_node();
34544 2728 : std::string node_name = "Unknown";
34545 :
34546 2728 : if (v0_is_ivar && v1_is_ivar)
34547 : {
34548 : typedef details::variable_node<T>* variable_node_ptr;
34549 :
34550 566 : variable_node_ptr v0 = variable_node_ptr(0);
34551 566 : variable_node_ptr v1 = variable_node_ptr(0);
34552 :
34553 566 : if (
34554 886 : (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
34555 320 : (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
34556 : )
34557 : {
34558 240 : result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
34559 240 : node_name = "swap_node";
34560 : }
34561 : else
34562 : {
34563 326 : result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
34564 326 : node_name = "swap_generic_node";
34565 : }
34566 566 : }
34567 2162 : else if (v0_is_ivec && v1_is_ivec)
34568 : {
34569 662 : result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
34570 662 : node_name = "swap_vecvec_node";
34571 : }
34572 : #ifndef exprtk_disable_string_capabilities
34573 1500 : else if (v0_is_str && v1_is_str)
34574 : {
34575 3000 : if (is_string_node(branch[0]) && is_string_node(branch[1]))
34576 : {
34577 0 : result = node_allocator_->allocate<details::swap_string_node<T> >
34578 0 : (branch[0], branch[1]);
34579 0 : node_name = "swap_string_node";
34580 : }
34581 : else
34582 : {
34583 3000 : result = node_allocator_->allocate<details::swap_genstrings_node<T> >
34584 1500 : (branch[0], branch[1]);
34585 1500 : node_name = "swap_genstrings_node";
34586 : }
34587 : }
34588 : #endif
34589 : else
34590 : {
34591 0 : parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
34592 0 : return error_node();
34593 : }
34594 :
34595 2728 : if (result && result->valid())
34596 : {
34597 5456 : parser_->state_.activate_side_effect("synthesize_swap_expression()");
34598 2728 : return result;
34599 : }
34600 :
34601 0 : parser_->set_error(parser_error::make_error(
34602 : parser_error::e_synthesis,
34603 0 : token_t(),
34604 : "ERR272 - Failed to synthesize node: " + node_name,
34605 : exprtk_error_location));
34606 :
34607 0 : details::free_node(*node_allocator_, result);
34608 0 : return error_node();
34609 2728 : }
34610 :
34611 : #ifndef exprtk_disable_sc_andor
34612 856 : inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34613 : {
34614 856 : expression_node_ptr result = error_node();
34615 :
34616 856 : if (details::is_constant_node(branch[0]))
34617 : {
34618 843 : if (
34619 1266 : (details::e_scand == operation) &&
34620 1266 : std::equal_to<T>()(T(0),branch[0]->value())
34621 : )
34622 210 : result = node_allocator_->allocate_c<literal_node_t>(T(0));
34623 633 : else if (
34624 1053 : (details::e_scor == operation) &&
34625 1053 : std::not_equal_to<T>()(T(0),branch[0]->value())
34626 : )
34627 210 : result = node_allocator_->allocate_c<literal_node_t>(T(1));
34628 : }
34629 :
34630 856 : if (details::is_constant_node(branch[1]) && (0 == result))
34631 : {
34632 430 : if (
34633 650 : (details::e_scand == operation) &&
34634 650 : std::equal_to<T>()(T(0),branch[1]->value())
34635 : )
34636 106 : result = node_allocator_->allocate_c<literal_node_t>(T(0));
34637 324 : else if (
34638 534 : (details::e_scor == operation) &&
34639 534 : std::not_equal_to<T>()(T(0),branch[1]->value())
34640 : )
34641 105 : result = node_allocator_->allocate_c<literal_node_t>(T(1));
34642 : }
34643 :
34644 856 : if (result)
34645 : {
34646 631 : details::free_node(*node_allocator_, branch[0]);
34647 631 : details::free_node(*node_allocator_, branch[1]);
34648 :
34649 631 : return result;
34650 : }
34651 225 : else if (details::e_scand == operation)
34652 : {
34653 120 : return synthesize_expression<scand_node_t,2>(operation, branch);
34654 : }
34655 105 : else if (details::e_scor == operation)
34656 : {
34657 105 : return synthesize_expression<scor_node_t,2>(operation, branch);
34658 : }
34659 : else
34660 0 : return error_node();
34661 : }
34662 : #else
34663 : inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
34664 : {
34665 : return error_node();
34666 : }
34667 : #endif
34668 :
34669 : #define basic_opr_switch_statements \
34670 : case_stmt(details::e_add , details::add_op) \
34671 : case_stmt(details::e_sub , details::sub_op) \
34672 : case_stmt(details::e_mul , details::mul_op) \
34673 : case_stmt(details::e_div , details::div_op) \
34674 : case_stmt(details::e_mod , details::mod_op) \
34675 : case_stmt(details::e_pow , details::pow_op) \
34676 :
34677 : #define extended_opr_switch_statements \
34678 : case_stmt(details::e_lt , details::lt_op ) \
34679 : case_stmt(details::e_lte , details::lte_op ) \
34680 : case_stmt(details::e_gt , details::gt_op ) \
34681 : case_stmt(details::e_gte , details::gte_op ) \
34682 : case_stmt(details::e_eq , details::eq_op ) \
34683 : case_stmt(details::e_ne , details::ne_op ) \
34684 : case_stmt(details::e_and , details::and_op ) \
34685 : case_stmt(details::e_nand , details::nand_op) \
34686 : case_stmt(details::e_or , details::or_op ) \
34687 : case_stmt(details::e_nor , details::nor_op ) \
34688 : case_stmt(details::e_xor , details::xor_op ) \
34689 : case_stmt(details::e_xnor , details::xnor_op) \
34690 :
34691 : #ifndef exprtk_disable_cardinal_pow_optimisation
34692 : template <typename TType, template <typename, typename> class IPowNode>
34693 62113 : inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
34694 : {
34695 62113 : switch (p)
34696 : {
34697 : #define case_stmt(cp) \
34698 : case cp : return node_allocator_-> \
34699 : allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
34700 :
34701 20138 : case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
34702 27770 : case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
34703 11085 : case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
34704 960 : case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
34705 960 : case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
34706 960 : case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
34707 240 : case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
34708 0 : case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
34709 0 : case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
34710 0 : case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
34711 0 : case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
34712 0 : case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
34713 0 : case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
34714 0 : case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
34715 0 : case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
34716 : #undef case_stmt
34717 0 : default : return error_node();
34718 : }
34719 : }
34720 :
34721 73697 : inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
34722 : {
34723 73697 : const bool not_recipricol = (c >= T(0));
34724 73697 : const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
34725 :
34726 73697 : if (0 == p)
34727 240 : return node_allocator_->allocate_c<literal_node_t>(T(1));
34728 73457 : else if (std::equal_to<T>()(T(2),c))
34729 : {
34730 11345 : return node_allocator_->
34731 11345 : template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
34732 : }
34733 : else
34734 : {
34735 62112 : if (not_recipricol)
34736 59062 : return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
34737 : else
34738 3050 : return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
34739 : }
34740 : }
34741 :
34742 653422 : inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
34743 : {
34744 653422 : return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
34745 : }
34746 :
34747 1 : inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
34748 : {
34749 1 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
34750 1 : const bool not_recipricol = (c >= T(0));
34751 1 : const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
34752 :
34753 1 : node_allocator_->free(branch[1]);
34754 :
34755 1 : if (0 == p)
34756 : {
34757 0 : details::free_all_nodes(*node_allocator_, branch);
34758 :
34759 0 : return node_allocator_->allocate_c<literal_node_t>(T(1));
34760 : }
34761 1 : else if (not_recipricol)
34762 1 : return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
34763 : else
34764 0 : return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p);
34765 : }
34766 : #else
34767 : inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
34768 : {
34769 : return error_node();
34770 : }
34771 :
34772 : inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
34773 : {
34774 : return false;
34775 : }
34776 :
34777 : inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
34778 : {
34779 : return error_node();
34780 : }
34781 : #endif
34782 :
34783 : struct synthesize_binary_ext_expression
34784 : {
34785 407007 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34786 : const details::operator_type& operation,
34787 : expression_node_ptr (&branch)[2])
34788 : {
34789 407007 : const bool left_neg = is_neg_unary_node(branch[0]);
34790 407007 : const bool right_neg = is_neg_unary_node(branch[1]);
34791 :
34792 407007 : if (left_neg && right_neg)
34793 : {
34794 200 : if (
34795 200 : (details::e_add == operation) ||
34796 200 : (details::e_sub == operation) ||
34797 200 : (details::e_mul == operation) ||
34798 80 : (details::e_div == operation)
34799 : )
34800 : {
34801 200 : if (
34802 400 : !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
34803 200 : !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
34804 : )
34805 : {
34806 0 : details::free_all_nodes(*expr_gen.node_allocator_,branch);
34807 :
34808 0 : return error_node();
34809 : }
34810 : }
34811 :
34812 200 : switch (operation)
34813 : {
34814 : // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
34815 0 : case details::e_add : return expr_gen(details::e_neg,
34816 0 : expr_gen.node_allocator_->
34817 : template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
34818 0 : (branch[0],branch[1]));
34819 :
34820 : // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
34821 0 : case details::e_sub : return expr_gen.node_allocator_->
34822 : template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
34823 0 : (branch[1],branch[0]);
34824 :
34825 200 : default : break;
34826 : }
34827 : }
34828 406807 : else if (left_neg && !right_neg)
34829 : {
34830 540 : if (
34831 540 : (details::e_add == operation) ||
34832 360 : (details::e_sub == operation) ||
34833 200 : (details::e_mul == operation) ||
34834 80 : (details::e_div == operation)
34835 : )
34836 : {
34837 540 : if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
34838 : {
34839 0 : details::free_all_nodes(*expr_gen.node_allocator_,branch);
34840 :
34841 0 : return error_node();
34842 : }
34843 :
34844 540 : switch (operation)
34845 : {
34846 : // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
34847 180 : case details::e_add : return expr_gen.node_allocator_->
34848 : template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
34849 180 : (branch[1], branch[0]);
34850 :
34851 : // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
34852 320 : case details::e_sub : return expr_gen(details::e_neg,
34853 160 : expr_gen.node_allocator_->
34854 : template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
34855 320 : (branch[0], branch[1]));
34856 :
34857 : // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
34858 240 : case details::e_mul : return expr_gen(details::e_neg,
34859 120 : expr_gen.node_allocator_->
34860 : template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
34861 240 : (branch[0], branch[1]));
34862 :
34863 : // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
34864 160 : case details::e_div : return expr_gen(details::e_neg,
34865 80 : expr_gen.node_allocator_->
34866 : template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
34867 160 : (branch[0], branch[1]));
34868 :
34869 0 : default : return error_node();
34870 : }
34871 : }
34872 : }
34873 406267 : else if (!left_neg && right_neg)
34874 : {
34875 688 : if (
34876 688 : (details::e_add == operation) ||
34877 688 : (details::e_sub == operation) ||
34878 688 : (details::e_mul == operation) ||
34879 568 : (details::e_div == operation)
34880 : )
34881 : {
34882 200 : if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
34883 : {
34884 0 : details::free_all_nodes(*expr_gen.node_allocator_,branch);
34885 :
34886 0 : return error_node();
34887 : }
34888 :
34889 200 : switch (operation)
34890 : {
34891 : // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
34892 0 : case details::e_add : return expr_gen.node_allocator_->
34893 : template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
34894 0 : (branch[0], branch[1]);
34895 :
34896 : // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
34897 0 : case details::e_sub : return expr_gen.node_allocator_->
34898 : template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
34899 0 : (branch[0], branch[1]);
34900 :
34901 : // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
34902 240 : case details::e_mul : return expr_gen(details::e_neg,
34903 120 : expr_gen.node_allocator_->
34904 : template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
34905 240 : (branch[0], branch[1]));
34906 :
34907 : // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
34908 160 : case details::e_div : return expr_gen(details::e_neg,
34909 80 : expr_gen.node_allocator_->
34910 : template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
34911 160 : (branch[0], branch[1]));
34912 :
34913 0 : default : return error_node();
34914 : }
34915 : }
34916 : }
34917 :
34918 406267 : switch (operation)
34919 : {
34920 : #define case_stmt(op0, op1) \
34921 : case op0 : return expr_gen.node_allocator_-> \
34922 : template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
34923 : (branch[0], branch[1]); \
34924 :
34925 397270 : basic_opr_switch_statements
34926 8997 : extended_opr_switch_statements
34927 : #undef case_stmt
34928 0 : default : return error_node();
34929 : }
34930 : }
34931 : };
34932 :
34933 : struct synthesize_vob_expression
34934 : {
34935 52659 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34936 : const details::operator_type& operation,
34937 : expression_node_ptr (&branch)[2])
34938 : {
34939 52659 : const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
34940 :
34941 : #ifndef exprtk_disable_enhanced_features
34942 52659 : if (details::is_sf3ext_node(branch[1]))
34943 : {
34944 37060 : expression_node_ptr result = error_node();
34945 :
34946 : const bool synthesis_result =
34947 : synthesize_sf4ext_expression::template compile_right<vtype>
34948 37060 : (expr_gen, v, operation, branch[1], result);
34949 :
34950 37060 : if (synthesis_result)
34951 : {
34952 18860 : details::free_node(*expr_gen.node_allocator_,branch[1]);
34953 18860 : return result;
34954 : }
34955 : }
34956 : #endif
34957 :
34958 33799 : if (
34959 33799 : (details::e_mul == operation) ||
34960 26875 : (details::e_div == operation)
34961 : )
34962 : {
34963 21217 : if (details::is_uv_node(branch[1]))
34964 : {
34965 : typedef details::uv_base_node<Type>* uvbn_ptr_t;
34966 :
34967 290 : details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
34968 :
34969 290 : if (details::e_neg == o)
34970 : {
34971 40 : const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
34972 :
34973 40 : details::free_node(*expr_gen.node_allocator_,branch[1]);
34974 :
34975 40 : switch (operation)
34976 : {
34977 80 : case details::e_mul : return expr_gen(details::e_neg,
34978 40 : expr_gen.node_allocator_->
34979 : template allocate_rr<typename details::
34980 40 : vov_node<Type,details::mul_op<Type> > >(v,v1));
34981 :
34982 0 : case details::e_div : return expr_gen(details::e_neg,
34983 0 : expr_gen.node_allocator_->
34984 : template allocate_rr<typename details::
34985 0 : vov_node<Type,details::div_op<Type> > >(v,v1));
34986 :
34987 0 : default : break;
34988 : }
34989 : }
34990 : }
34991 : }
34992 :
34993 33759 : switch (operation)
34994 : {
34995 : #define case_stmt(op0, op1) \
34996 : case op0 : return expr_gen.node_allocator_-> \
34997 : template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
34998 : (v, branch[1]); \
34999 :
35000 33722 : basic_opr_switch_statements
35001 37 : extended_opr_switch_statements
35002 : #undef case_stmt
35003 0 : default : return error_node();
35004 : }
35005 : }
35006 : };
35007 :
35008 : struct synthesize_bov_expression
35009 : {
35010 361546 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35011 : const details::operator_type& operation,
35012 : expression_node_ptr (&branch)[2])
35013 : {
35014 361546 : const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35015 :
35016 : #ifndef exprtk_disable_enhanced_features
35017 361546 : if (details::is_sf3ext_node(branch[0]))
35018 : {
35019 67662 : expression_node_ptr result = error_node();
35020 :
35021 : const bool synthesis_result =
35022 : synthesize_sf4ext_expression::template compile_left<vtype>
35023 67662 : (expr_gen, v, operation, branch[0], result);
35024 :
35025 67662 : if (synthesis_result)
35026 : {
35027 8575 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35028 :
35029 8575 : return result;
35030 : }
35031 : }
35032 : #endif
35033 :
35034 352971 : if (
35035 352971 : (details::e_add == operation) ||
35036 175405 : (details::e_sub == operation) ||
35037 107504 : (details::e_mul == operation) ||
35038 23049 : (details::e_div == operation)
35039 : )
35040 : {
35041 352108 : if (details::is_uv_node(branch[0]))
35042 : {
35043 : typedef details::uv_base_node<Type>* uvbn_ptr_t;
35044 :
35045 256 : details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
35046 :
35047 256 : if (details::e_neg == o)
35048 : {
35049 200 : const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
35050 :
35051 200 : details::free_node(*expr_gen.node_allocator_,branch[0]);
35052 :
35053 200 : switch (operation)
35054 : {
35055 80 : case details::e_add : return expr_gen.node_allocator_->
35056 : template allocate_rr<typename details::
35057 80 : vov_node<Type,details::sub_op<Type> > >(v,v0);
35058 :
35059 160 : case details::e_sub : return expr_gen(details::e_neg,
35060 80 : expr_gen.node_allocator_->
35061 : template allocate_rr<typename details::
35062 80 : vov_node<Type,details::add_op<Type> > >(v0,v));
35063 :
35064 80 : case details::e_mul : return expr_gen(details::e_neg,
35065 40 : expr_gen.node_allocator_->
35066 : template allocate_rr<typename details::
35067 40 : vov_node<Type,details::mul_op<Type> > >(v0,v));
35068 :
35069 0 : case details::e_div : return expr_gen(details::e_neg,
35070 0 : expr_gen.node_allocator_->
35071 : template allocate_rr<typename details::
35072 0 : vov_node<Type,details::div_op<Type> > >(v0,v));
35073 0 : default : break;
35074 : }
35075 : }
35076 : }
35077 : }
35078 :
35079 352771 : switch (operation)
35080 : {
35081 : #define case_stmt(op0, op1) \
35082 : case op0 : return expr_gen.node_allocator_-> \
35083 : template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
35084 : (branch[0], v); \
35085 :
35086 351914 : basic_opr_switch_statements
35087 857 : extended_opr_switch_statements
35088 : #undef case_stmt
35089 0 : default : return error_node();
35090 : }
35091 : }
35092 : };
35093 :
35094 : struct synthesize_cob_expression
35095 : {
35096 99132 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35097 : const details::operator_type& operation,
35098 : expression_node_ptr (&branch)[2])
35099 : {
35100 99132 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
35101 :
35102 99132 : details::free_node(*expr_gen.node_allocator_,branch[0]);
35103 :
35104 99132 : if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35105 : {
35106 650 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35107 :
35108 650 : return expr_gen(T(0));
35109 : }
35110 98482 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35111 : {
35112 100 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35113 :
35114 100 : return expr_gen(T(0));
35115 : }
35116 98382 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35117 0 : return branch[1];
35118 98382 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35119 0 : return branch[1];
35120 :
35121 98382 : if (details::is_cob_node(branch[1]))
35122 : {
35123 : // Simplify expressions of the form:
35124 : // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
35125 : // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
35126 1461 : if (
35127 1461 : (details::e_mul == operation) ||
35128 1211 : (details::e_add == operation)
35129 : )
35130 : {
35131 841 : details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
35132 :
35133 841 : if (operation == cobnode->operation())
35134 : {
35135 0 : switch (operation)
35136 : {
35137 0 : case details::e_add : cobnode->set_c(c + cobnode->c()); break;
35138 0 : case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
35139 0 : default : return error_node();
35140 : }
35141 :
35142 0 : return cobnode;
35143 : }
35144 : }
35145 :
35146 1461 : if (operation == details::e_mul)
35147 : {
35148 250 : details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
35149 250 : details::operator_type cob_opr = cobnode->operation();
35150 :
35151 250 : if (
35152 250 : (details::e_div == cob_opr) ||
35153 : (details::e_mul == cob_opr)
35154 : )
35155 : {
35156 0 : switch (cob_opr)
35157 : {
35158 0 : case details::e_div : cobnode->set_c(c * cobnode->c()); break;
35159 0 : case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
35160 0 : default : return error_node();
35161 : }
35162 :
35163 0 : return cobnode;
35164 : }
35165 : }
35166 1211 : else if (operation == details::e_div)
35167 : {
35168 250 : details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
35169 250 : details::operator_type cob_opr = cobnode->operation();
35170 :
35171 250 : if (
35172 250 : (details::e_div == cob_opr) ||
35173 : (details::e_mul == cob_opr)
35174 : )
35175 : {
35176 0 : details::expression_node<Type>* new_cobnode = error_node();
35177 :
35178 0 : switch (cob_opr)
35179 : {
35180 0 : case details::e_div : new_cobnode = expr_gen.node_allocator_->
35181 : template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
35182 0 : (c / cobnode->c(), cobnode->move_branch(0));
35183 0 : break;
35184 :
35185 0 : case details::e_mul : new_cobnode = expr_gen.node_allocator_->
35186 : template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
35187 0 : (c / cobnode->c(), cobnode->move_branch(0));
35188 0 : break;
35189 :
35190 0 : default : return error_node();
35191 : }
35192 :
35193 0 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35194 :
35195 0 : return new_cobnode;
35196 : }
35197 : }
35198 : }
35199 : #ifndef exprtk_disable_enhanced_features
35200 96921 : else if (details::is_sf3ext_node(branch[1]))
35201 : {
35202 28475 : expression_node_ptr result = error_node();
35203 :
35204 : const bool synthesis_result =
35205 : synthesize_sf4ext_expression::template compile_right<ctype>
35206 28475 : (expr_gen, c, operation, branch[1], result);
35207 :
35208 28475 : if (synthesis_result)
35209 : {
35210 10324 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35211 :
35212 10324 : return result;
35213 : }
35214 : }
35215 : #endif
35216 :
35217 88058 : switch (operation)
35218 : {
35219 : #define case_stmt(op0, op1) \
35220 : case op0 : return expr_gen.node_allocator_-> \
35221 : template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
35222 : (c, branch[1]); \
35223 :
35224 87426 : basic_opr_switch_statements
35225 632 : extended_opr_switch_statements
35226 : #undef case_stmt
35227 0 : default : return error_node();
35228 : }
35229 : }
35230 : };
35231 :
35232 : struct synthesize_boc_expression
35233 : {
35234 147008 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35235 : const details::operator_type& operation,
35236 : expression_node_ptr (&branch)[2])
35237 : {
35238 147008 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
35239 :
35240 147008 : details::free_node(*(expr_gen.node_allocator_), branch[1]);
35241 :
35242 147008 : if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35243 : {
35244 189 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35245 :
35246 189 : return expr_gen(T(0));
35247 : }
35248 146819 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35249 : {
35250 1 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35251 :
35252 1 : return expr_gen(std::numeric_limits<T>::quiet_NaN());
35253 : }
35254 146818 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35255 1 : return branch[0];
35256 146817 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35257 104 : return branch[0];
35258 :
35259 146713 : if (details::is_boc_node(branch[0]))
35260 : {
35261 : // Simplify expressions of the form:
35262 : // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
35263 : // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
35264 2175 : if (
35265 2175 : (details::e_mul == operation) ||
35266 1857 : (details::e_add == operation)
35267 : )
35268 : {
35269 983 : details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
35270 :
35271 983 : if (operation == bocnode->operation())
35272 : {
35273 0 : switch (operation)
35274 : {
35275 0 : case details::e_add : bocnode->set_c(c + bocnode->c()); break;
35276 0 : case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
35277 0 : default : return error_node();
35278 : }
35279 :
35280 0 : return bocnode;
35281 : }
35282 983 : }
35283 1192 : else if (operation == details::e_div)
35284 : {
35285 250 : details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
35286 250 : details::operator_type boc_opr = bocnode->operation();
35287 :
35288 250 : if (
35289 250 : (details::e_div == boc_opr) ||
35290 : (details::e_mul == boc_opr)
35291 : )
35292 : {
35293 0 : switch (boc_opr)
35294 : {
35295 0 : case details::e_div : bocnode->set_c(c * bocnode->c()); break;
35296 0 : case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
35297 0 : default : return error_node();
35298 : }
35299 :
35300 0 : return bocnode;
35301 : }
35302 : }
35303 942 : else if (operation == details::e_pow)
35304 : {
35305 : // (v ^ c0) ^ c1 --> v ^(c0 * c1)
35306 0 : details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
35307 0 : details::operator_type boc_opr = bocnode->operation();
35308 :
35309 0 : if (details::e_pow == boc_opr)
35310 : {
35311 0 : bocnode->set_c(bocnode->c() * c);
35312 :
35313 0 : return bocnode;
35314 : }
35315 : }
35316 : }
35317 :
35318 : #ifndef exprtk_disable_enhanced_features
35319 146713 : if (details::is_sf3ext_node(branch[0]))
35320 : {
35321 48002 : expression_node_ptr result = error_node();
35322 :
35323 : const bool synthesis_result =
35324 : synthesize_sf4ext_expression::template compile_left<ctype>
35325 48002 : (expr_gen, c, operation, branch[0], result);
35326 :
35327 48002 : if (synthesis_result)
35328 : {
35329 4521 : free_node(*expr_gen.node_allocator_, branch[0]);
35330 :
35331 4521 : return result;
35332 : }
35333 : }
35334 : #endif
35335 :
35336 142192 : switch (operation)
35337 : {
35338 : #define case_stmt(op0, op1) \
35339 : case op0 : return expr_gen.node_allocator_-> \
35340 : template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
35341 : (branch[0], c); \
35342 :
35343 132439 : basic_opr_switch_statements
35344 9753 : extended_opr_switch_statements
35345 : #undef case_stmt
35346 0 : default : return error_node();
35347 : }
35348 : }
35349 : };
35350 :
35351 : struct synthesize_cocob_expression
35352 : {
35353 7958 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35354 : const details::operator_type& operation,
35355 : expression_node_ptr (&branch)[2])
35356 : {
35357 7958 : expression_node_ptr result = error_node();
35358 :
35359 : // (cob) o c --> cob
35360 7958 : if (details::is_cob_node(branch[0]))
35361 : {
35362 4757 : details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
35363 :
35364 4757 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
35365 :
35366 4757 : if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35367 : {
35368 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35369 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35370 :
35371 0 : return expr_gen(T(0));
35372 : }
35373 4757 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35374 : {
35375 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35376 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35377 :
35378 0 : return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
35379 : }
35380 4757 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35381 : {
35382 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35383 :
35384 0 : return branch[0];
35385 : }
35386 4757 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35387 : {
35388 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35389 :
35390 0 : return branch[0];
35391 : }
35392 4757 : else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
35393 : {
35394 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35395 :
35396 0 : return branch[0];
35397 : }
35398 :
35399 7659 : const bool op_addsub = (details::e_add == cobnode->operation()) ||
35400 2902 : (details::e_sub == cobnode->operation()) ;
35401 :
35402 4757 : if (op_addsub)
35403 : {
35404 2285 : switch (operation)
35405 : {
35406 495 : case details::e_add : cobnode->set_c(cobnode->c() + c); break;
35407 1770 : case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
35408 20 : default : return error_node();
35409 : }
35410 :
35411 2265 : result = cobnode;
35412 : }
35413 2472 : else if (details::e_mul == cobnode->operation())
35414 : {
35415 1822 : switch (operation)
35416 : {
35417 215 : case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
35418 1290 : case details::e_div : cobnode->set_c(cobnode->c() / c); break;
35419 317 : default : return error_node();
35420 : }
35421 :
35422 1505 : result = cobnode;
35423 : }
35424 650 : else if (details::e_div == cobnode->operation())
35425 : {
35426 650 : if (details::e_mul == operation)
35427 : {
35428 215 : cobnode->set_c(cobnode->c() * c);
35429 215 : result = cobnode;
35430 : }
35431 435 : else if (details::e_div == operation)
35432 : {
35433 195 : result = expr_gen.node_allocator_->
35434 : template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
35435 195 : (cobnode->c() / c, cobnode->move_branch(0));
35436 :
35437 195 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35438 : }
35439 : }
35440 :
35441 4420 : if (result)
35442 : {
35443 4180 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35444 : }
35445 : }
35446 :
35447 : // c o (cob) --> cob
35448 3201 : else if (details::is_cob_node(branch[1]))
35449 : {
35450 3201 : details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
35451 :
35452 3201 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
35453 :
35454 3201 : if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35455 : {
35456 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35457 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35458 :
35459 0 : return expr_gen(T(0));
35460 : }
35461 3201 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35462 : {
35463 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35464 0 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35465 :
35466 0 : return expr_gen(T(0));
35467 : }
35468 3201 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35469 : {
35470 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35471 :
35472 0 : return branch[1];
35473 : }
35474 3201 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35475 : {
35476 0 : details::free_node(*expr_gen.node_allocator_, branch[0]);
35477 :
35478 0 : return branch[1];
35479 : }
35480 :
35481 3201 : if (details::e_add == cobnode->operation())
35482 : {
35483 580 : if (details::e_add == operation)
35484 : {
35485 165 : cobnode->set_c(c + cobnode->c());
35486 165 : result = cobnode;
35487 : }
35488 415 : else if (details::e_sub == operation)
35489 : {
35490 165 : result = expr_gen.node_allocator_->
35491 : template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
35492 165 : (c - cobnode->c(), cobnode->move_branch(0));
35493 :
35494 165 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35495 : }
35496 : }
35497 2621 : else if (details::e_sub == cobnode->operation())
35498 : {
35499 540 : if (details::e_add == operation)
35500 : {
35501 165 : cobnode->set_c(c + cobnode->c());
35502 165 : result = cobnode;
35503 : }
35504 375 : else if (details::e_sub == operation)
35505 : {
35506 125 : result = expr_gen.node_allocator_->
35507 : template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
35508 125 : (c - cobnode->c(), cobnode->move_branch(0));
35509 :
35510 125 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35511 : }
35512 : }
35513 2081 : else if (details::e_mul == cobnode->operation())
35514 : {
35515 1041 : if (details::e_mul == operation)
35516 : {
35517 335 : cobnode->set_c(c * cobnode->c());
35518 335 : result = cobnode;
35519 : }
35520 706 : else if (details::e_div == operation)
35521 : {
35522 225 : result = expr_gen.node_allocator_->
35523 : template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
35524 225 : (c / cobnode->c(), cobnode->move_branch(0));
35525 :
35526 225 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35527 : }
35528 : }
35529 1040 : else if (details::e_div == cobnode->operation())
35530 : {
35531 1040 : if (details::e_mul == operation)
35532 : {
35533 335 : cobnode->set_c(c * cobnode->c());
35534 335 : result = cobnode;
35535 : }
35536 705 : else if (details::e_div == operation)
35537 : {
35538 225 : result = expr_gen.node_allocator_->
35539 : template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
35540 225 : (c / cobnode->c(), cobnode->move_branch(0));
35541 :
35542 225 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35543 : }
35544 : }
35545 :
35546 3201 : if (result)
35547 : {
35548 1740 : details::free_node(*expr_gen.node_allocator_,branch[0]);
35549 : }
35550 : }
35551 :
35552 7621 : return result;
35553 : }
35554 : };
35555 :
35556 : struct synthesize_coboc_expression
35557 : {
35558 24432 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35559 : const details::operator_type& operation,
35560 : expression_node_ptr (&branch)[2])
35561 : {
35562 24432 : expression_node_ptr result = error_node();
35563 :
35564 : // (boc) o c --> boc
35565 24432 : if (details::is_boc_node(branch[0]))
35566 : {
35567 22177 : details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
35568 :
35569 22177 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
35570 :
35571 22177 : if (details::e_add == bocnode->operation())
35572 : {
35573 8689 : switch (operation)
35574 : {
35575 4925 : case details::e_add : bocnode->set_c(bocnode->c() + c); break;
35576 3514 : case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
35577 250 : default : return error_node();
35578 : }
35579 :
35580 8439 : result = bocnode;
35581 : }
35582 13488 : else if (details::e_mul == bocnode->operation())
35583 : {
35584 3635 : switch (operation)
35585 : {
35586 1720 : case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
35587 1395 : case details::e_div : bocnode->set_c(bocnode->c() / c); break;
35588 520 : default : return error_node();
35589 : }
35590 :
35591 3115 : result = bocnode;
35592 : }
35593 9853 : else if (details::e_sub == bocnode->operation())
35594 : {
35595 5963 : if (details::e_add == operation)
35596 : {
35597 2339 : result = expr_gen.node_allocator_->
35598 : template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
35599 2339 : (bocnode->move_branch(0), c - bocnode->c());
35600 :
35601 2339 : details::free_node(*expr_gen.node_allocator_,branch[0]);
35602 : }
35603 3624 : else if (details::e_sub == operation)
35604 : {
35605 3304 : bocnode->set_c(bocnode->c() + c);
35606 3304 : result = bocnode;
35607 : }
35608 : }
35609 3890 : else if (details::e_div == bocnode->operation())
35610 : {
35611 3890 : switch (operation)
35612 : {
35613 2175 : case details::e_div : bocnode->set_c(bocnode->c() * c); break;
35614 1240 : case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
35615 475 : default : return error_node();
35616 : }
35617 :
35618 3415 : result = bocnode;
35619 : }
35620 :
35621 20932 : if (result)
35622 : {
35623 20612 : details::free_node(*expr_gen.node_allocator_, branch[1]);
35624 : }
35625 : }
35626 :
35627 : // c o (boc) --> boc
35628 2255 : else if (details::is_boc_node(branch[1]))
35629 : {
35630 2255 : details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
35631 :
35632 2255 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
35633 :
35634 2255 : if (details::e_add == bocnode->operation())
35635 : {
35636 260 : if (details::e_add == operation)
35637 : {
35638 205 : bocnode->set_c(c + bocnode->c());
35639 205 : result = bocnode;
35640 : }
35641 55 : else if (details::e_sub == operation)
35642 : {
35643 45 : result = expr_gen.node_allocator_->
35644 : template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
35645 45 : (c - bocnode->c(), bocnode->move_branch(0));
35646 :
35647 45 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35648 : }
35649 : }
35650 1995 : else if (details::e_sub == bocnode->operation())
35651 : {
35652 190 : if (details::e_add == operation)
35653 : {
35654 45 : result = expr_gen.node_allocator_->
35655 : template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
35656 45 : (bocnode->move_branch(0), c - bocnode->c());
35657 :
35658 45 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35659 : }
35660 145 : else if (details::e_sub == operation)
35661 : {
35662 65 : result = expr_gen.node_allocator_->
35663 : template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
35664 65 : (c + bocnode->c(), bocnode->move_branch(0));
35665 :
35666 65 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35667 : }
35668 : }
35669 1805 : else if (details::e_mul == bocnode->operation())
35670 : {
35671 895 : if (details::e_mul == operation)
35672 : {
35673 125 : bocnode->set_c(c * bocnode->c());
35674 125 : result = bocnode;
35675 : }
35676 770 : else if (details::e_div == operation)
35677 : {
35678 45 : result = expr_gen.node_allocator_->
35679 : template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
35680 45 : (c / bocnode->c(), bocnode->move_branch(0));
35681 :
35682 45 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35683 : }
35684 : }
35685 910 : else if (details::e_div == bocnode->operation())
35686 : {
35687 910 : if (details::e_mul == operation)
35688 : {
35689 120 : bocnode->set_c(bocnode->c() / c);
35690 120 : result = bocnode;
35691 : }
35692 790 : else if (details::e_div == operation)
35693 : {
35694 120 : result = expr_gen.node_allocator_->
35695 : template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
35696 120 : (c * bocnode->c(), bocnode->move_branch(0));
35697 :
35698 120 : details::free_node(*expr_gen.node_allocator_,branch[1]);
35699 : }
35700 : }
35701 :
35702 2255 : if (result)
35703 : {
35704 770 : details::free_node(*expr_gen.node_allocator_,branch[0]);
35705 : }
35706 : }
35707 :
35708 23187 : return result;
35709 : }
35710 : };
35711 :
35712 : #ifndef exprtk_disable_enhanced_features
35713 2857634 : inline bool synthesize_expression(const details::operator_type& operation,
35714 : expression_node_ptr (&branch)[2],
35715 : expression_node_ptr& result)
35716 : {
35717 2857634 : result = error_node();
35718 :
35719 2857634 : if (!operation_optimisable(operation))
35720 266483 : return false;
35721 :
35722 2591151 : const std::string node_id = branch_to_id(branch);
35723 :
35724 2591151 : const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
35725 :
35726 2591151 : if (synthesize_map_.end() != itr)
35727 : {
35728 1313530 : result = itr->second((*this), operation, branch);
35729 :
35730 1313530 : return true;
35731 : }
35732 : else
35733 1277621 : return false;
35734 2591151 : }
35735 :
35736 : struct synthesize_vov_expression
35737 : {
35738 253882 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35739 : const details::operator_type& operation,
35740 : expression_node_ptr (&branch)[2])
35741 : {
35742 253882 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
35743 253882 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35744 :
35745 253882 : switch (operation)
35746 : {
35747 : #define case_stmt(op0, op1) \
35748 : case op0 : return expr_gen.node_allocator_-> \
35749 : template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
35750 : (v1, v2); \
35751 :
35752 246637 : basic_opr_switch_statements
35753 7245 : extended_opr_switch_statements
35754 : #undef case_stmt
35755 0 : default : return error_node();
35756 : }
35757 : }
35758 : };
35759 :
35760 : struct synthesize_cov_expression
35761 : {
35762 207749 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35763 : const details::operator_type& operation,
35764 : expression_node_ptr (&branch)[2])
35765 : {
35766 207749 : const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
35767 207749 : const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
35768 :
35769 207749 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
35770 :
35771 207749 : if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35772 191 : return expr_gen(T(0));
35773 207558 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35774 60 : return expr_gen(T(0));
35775 207498 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35776 61 : return static_cast<details::variable_node<Type>*>(branch[1]);
35777 207437 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35778 202 : return static_cast<details::variable_node<Type>*>(branch[1]);
35779 :
35780 207235 : switch (operation)
35781 : {
35782 : #define case_stmt(op0, op1) \
35783 : case op0 : return expr_gen.node_allocator_-> \
35784 : template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
35785 : (c, v); \
35786 :
35787 207127 : basic_opr_switch_statements
35788 108 : extended_opr_switch_statements
35789 : #undef case_stmt
35790 0 : default : return error_node();
35791 : }
35792 : }
35793 : };
35794 :
35795 : struct synthesize_voc_expression
35796 : {
35797 356546 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35798 : const details::operator_type& operation,
35799 : expression_node_ptr (&branch)[2])
35800 : {
35801 356546 : const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
35802 356546 : const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
35803 :
35804 356546 : details::free_node(*(expr_gen.node_allocator_), branch[1]);
35805 :
35806 356546 : if (expr_gen.cardinal_pow_optimisable(operation,c))
35807 : {
35808 85877 : if (std::equal_to<T>()(T(1),c))
35809 12180 : return branch[0];
35810 : else
35811 73697 : return expr_gen.cardinal_pow_optimisation(v,c);
35812 : }
35813 270669 : else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
35814 180 : return expr_gen(T(0));
35815 270489 : else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
35816 0 : return expr_gen(std::numeric_limits<T>::quiet_NaN());
35817 270489 : else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
35818 541 : return static_cast<details::variable_node<Type>*>(branch[0]);
35819 269948 : else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
35820 193 : return static_cast<details::variable_node<Type>*>(branch[0]);
35821 269755 : else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
35822 60 : return static_cast<details::variable_node<Type>*>(branch[0]);
35823 :
35824 269695 : switch (operation)
35825 : {
35826 : #define case_stmt(op0, op1) \
35827 : case op0 : return expr_gen.node_allocator_-> \
35828 : template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
35829 : (v, c); \
35830 :
35831 257499 : basic_opr_switch_statements
35832 12196 : extended_opr_switch_statements
35833 : #undef case_stmt
35834 0 : default : return error_node();
35835 : }
35836 : }
35837 : };
35838 :
35839 : struct synthesize_sf3ext_expression
35840 : {
35841 : template <typename T0, typename T1, typename T2>
35842 371080 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35843 : const details::operator_type& sf3opr,
35844 : T0 t0, T1 t1, T2 t2)
35845 : {
35846 371080 : switch (sf3opr)
35847 : {
35848 : #define case_stmt(op) \
35849 : case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
35850 : allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
35851 :
35852 37586 : case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
35853 36683 : case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
35854 98389 : case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
35855 44413 : case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
35856 52190 : case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
35857 42972 : case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
35858 38570 : case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
35859 20277 : case_stmt(28) case_stmt(29) case_stmt(30)
35860 : #undef case_stmt
35861 0 : default : return error_node();
35862 : }
35863 : }
35864 :
35865 : template <typename T0, typename T1, typename T2>
35866 377040 : static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
35867 : T0 t0, T1 t1, T2 t2,
35868 : expression_node_ptr& result)
35869 : {
35870 : details::operator_type sf3opr;
35871 :
35872 377040 : if (!expr_gen.sf3_optimisable(id,sf3opr))
35873 5960 : return false;
35874 : else
35875 371080 : result = synthesize_sf3ext_expression::template process<T0, T1, T2>
35876 371080 : (expr_gen, sf3opr, t0, t1, t2);
35877 :
35878 371080 : return true;
35879 : }
35880 : };
35881 :
35882 : struct synthesize_sf4ext_expression
35883 : {
35884 : template <typename T0, typename T1, typename T2, typename T3>
35885 97884 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35886 : const details::operator_type& sf4opr,
35887 : T0 t0, T1 t1, T2 t2, T3 t3)
35888 : {
35889 97884 : switch (sf4opr)
35890 : {
35891 : #define case_stmt0(op) \
35892 : case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
35893 : allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
35894 :
35895 : #define case_stmt1(op) \
35896 : case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
35897 : allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
35898 :
35899 3540 : case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
35900 5065 : case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
35901 4399 : case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
35902 4475 : case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
35903 4711 : case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
35904 4810 : case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
35905 4733 : case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
35906 5911 : case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
35907 3470 : case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
35908 :
35909 6670 : case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
35910 6550 : case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
35911 2725 : case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
35912 3770 : case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
35913 3385 : case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
35914 3340 : case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
35915 3500 : case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
35916 3115 : case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
35917 3560 : case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
35918 2630 : case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
35919 1990 : case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
35920 6400 : case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
35921 640 : case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
35922 1590 : case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
35923 1720 : case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
35924 5185 : case_stmt1(60) case_stmt1(61)
35925 :
35926 : #undef case_stmt0
35927 : #undef case_stmt1
35928 0 : default : return error_node();
35929 : }
35930 : }
35931 :
35932 : template <typename T0, typename T1, typename T2, typename T3>
35933 243720 : static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
35934 : T0 t0, T1 t1, T2 t2, T3 t3,
35935 : expression_node_ptr& result)
35936 : {
35937 : details::operator_type sf4opr;
35938 :
35939 243720 : if (!expr_gen.sf4_optimisable(id,sf4opr))
35940 145836 : return false;
35941 : else
35942 97884 : result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
35943 97884 : (expr_gen, sf4opr, t0, t1, t2, t3);
35944 :
35945 97884 : return true;
35946 : }
35947 :
35948 : // T o (sf3ext)
35949 : template <typename ExternalType>
35950 65535 : static inline bool compile_right(expression_generator<Type>& expr_gen,
35951 : ExternalType t,
35952 : const details::operator_type& operation,
35953 : expression_node_ptr& sf3node,
35954 : expression_node_ptr& result)
35955 : {
35956 65535 : if (!details::is_sf3ext_node(sf3node))
35957 0 : return false;
35958 :
35959 : typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
35960 :
35961 65535 : sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
35962 65535 : const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
35963 :
35964 65535 : switch (n->type())
35965 : {
35966 2785 : case details::expression_node<Type>::e_covoc : return compile_right_impl
35967 : <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
35968 2785 : (expr_gen, id, t, sf3node, result);
35969 :
35970 14845 : case details::expression_node<Type>::e_covov : return compile_right_impl
35971 : <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
35972 14845 : (expr_gen, id, t, sf3node, result);
35973 :
35974 15450 : case details::expression_node<Type>::e_vocov : return compile_right_impl
35975 : <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
35976 15450 : (expr_gen, id, t, sf3node, result);
35977 :
35978 15375 : case details::expression_node<Type>::e_vovoc : return compile_right_impl
35979 : <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
35980 15375 : (expr_gen, id, t, sf3node, result);
35981 :
35982 17080 : case details::expression_node<Type>::e_vovov : return compile_right_impl
35983 : <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
35984 17080 : (expr_gen, id, t, sf3node, result);
35985 :
35986 0 : default : return false;
35987 : }
35988 65535 : }
35989 :
35990 : // (sf3ext) o T
35991 : template <typename ExternalType>
35992 115664 : static inline bool compile_left(expression_generator<Type>& expr_gen,
35993 : ExternalType t,
35994 : const details::operator_type& operation,
35995 : expression_node_ptr& sf3node,
35996 : expression_node_ptr& result)
35997 : {
35998 115664 : if (!details::is_sf3ext_node(sf3node))
35999 0 : return false;
36000 :
36001 : typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
36002 :
36003 115664 : sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
36004 :
36005 115664 : const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
36006 :
36007 115664 : switch (n->type())
36008 : {
36009 4480 : case details::expression_node<Type>::e_covoc : return compile_left_impl
36010 : <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
36011 4480 : (expr_gen, id, t, sf3node, result);
36012 :
36013 27465 : case details::expression_node<Type>::e_covov : return compile_left_impl
36014 : <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
36015 27465 : (expr_gen, id, t, sf3node, result);
36016 :
36017 24883 : case details::expression_node<Type>::e_vocov : return compile_left_impl
36018 : <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
36019 24883 : (expr_gen, id, t, sf3node, result);
36020 :
36021 25960 : case details::expression_node<Type>::e_vovoc : return compile_left_impl
36022 : <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
36023 25960 : (expr_gen, id, t, sf3node, result);
36024 :
36025 32876 : case details::expression_node<Type>::e_vovov : return compile_left_impl
36026 : <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
36027 32876 : (expr_gen, id, t, sf3node, result);
36028 :
36029 0 : default : return false;
36030 : }
36031 115664 : }
36032 :
36033 : template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
36034 65535 : static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
36035 : const std::string& id,
36036 : ExternalType t,
36037 : expression_node_ptr& node,
36038 : expression_node_ptr& result)
36039 : {
36040 65535 : SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
36041 :
36042 65535 : if (n)
36043 : {
36044 65535 : T0 t0 = n->t0();
36045 65535 : T1 t1 = n->t1();
36046 65535 : T2 t2 = n->t2();
36047 :
36048 : return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
36049 65535 : (expr_gen, id, t, t0, t1, t2, result);
36050 : }
36051 : else
36052 0 : return false;
36053 : }
36054 :
36055 : template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
36056 115664 : static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
36057 : const std::string& id,
36058 : ExternalType t,
36059 : expression_node_ptr& node,
36060 : expression_node_ptr& result)
36061 : {
36062 115664 : SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
36063 :
36064 115664 : if (n)
36065 : {
36066 115664 : T0 t0 = n->t0();
36067 115664 : T1 t1 = n->t1();
36068 115664 : T2 t2 = n->t2();
36069 :
36070 : return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
36071 115664 : (expr_gen, id, t0, t1, t2, t, result);
36072 : }
36073 : else
36074 0 : return false;
36075 : }
36076 : };
36077 :
36078 : struct synthesize_vovov_expression0
36079 : {
36080 : typedef typename vovov_t::type0 node_type;
36081 : typedef typename vovov_t::sf3_type sf3_type;
36082 :
36083 58637 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36084 : const details::operator_type& operation,
36085 : expression_node_ptr (&branch)[2])
36086 : {
36087 : // (v0 o0 v1) o1 (v2)
36088 58637 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
36089 58637 : const Type& v0 = vov->v0();
36090 58637 : const Type& v1 = vov->v1();
36091 58637 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
36092 58637 : const details::operator_type o0 = vov->operation();
36093 58637 : const details::operator_type o1 = operation;
36094 :
36095 58637 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36096 :
36097 58637 : expression_node_ptr result = error_node();
36098 :
36099 58637 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36100 : {
36101 : // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
36102 58637 : if ((details::e_div == o0) && (details::e_div == o1))
36103 : {
36104 : const bool synthesis_result =
36105 : synthesize_sf3ext_expression::
36106 8265 : template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
36107 :
36108 : exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
36109 :
36110 8265 : return (synthesis_result) ? result : error_node();
36111 : }
36112 : }
36113 :
36114 : const bool synthesis_result =
36115 : synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
36116 50372 : (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
36117 :
36118 50372 : if (synthesis_result)
36119 49577 : return result;
36120 :
36121 795 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36122 795 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36123 :
36124 795 : if (!expr_gen.valid_operator(o0,f0))
36125 0 : return error_node();
36126 795 : else if (!expr_gen.valid_operator(o1,f1))
36127 0 : return error_node();
36128 : else
36129 795 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
36130 : }
36131 :
36132 50372 : static inline std::string id(expression_generator<Type>& expr_gen,
36133 : const details::operator_type o0,
36134 : const details::operator_type o1)
36135 : {
36136 100744 : return details::build_string()
36137 100744 : << "(t" << expr_gen.to_str(o0)
36138 100744 : << "t)" << expr_gen.to_str(o1)
36139 100744 : << "t";
36140 : }
36141 : };
36142 :
36143 : struct synthesize_vovov_expression1
36144 : {
36145 : typedef typename vovov_t::type1 node_type;
36146 : typedef typename vovov_t::sf3_type sf3_type;
36147 :
36148 21729 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36149 : const details::operator_type& operation,
36150 : expression_node_ptr (&branch)[2])
36151 : {
36152 : // (v0) o0 (v1 o1 v2)
36153 21729 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
36154 21729 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
36155 21729 : const Type& v1 = vov->v0();
36156 21729 : const Type& v2 = vov->v1();
36157 21729 : const details::operator_type o0 = operation;
36158 21729 : const details::operator_type o1 = vov->operation();
36159 :
36160 21729 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36161 :
36162 21729 : expression_node_ptr result = error_node();
36163 :
36164 21729 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36165 : {
36166 : // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
36167 21729 : if ((details::e_div == o0) && (details::e_div == o1))
36168 : {
36169 : const bool synthesis_result =
36170 : synthesize_sf3ext_expression::
36171 1190 : template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
36172 :
36173 : exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
36174 :
36175 1190 : return (synthesis_result) ? result : error_node();
36176 : }
36177 : }
36178 :
36179 : const bool synthesis_result =
36180 : synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
36181 20539 : (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
36182 :
36183 20539 : if (synthesis_result)
36184 20409 : return result;
36185 :
36186 130 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36187 130 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36188 :
36189 130 : if (!expr_gen.valid_operator(o0,f0))
36190 0 : return error_node();
36191 130 : else if (!expr_gen.valid_operator(o1,f1))
36192 0 : return error_node();
36193 : else
36194 130 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
36195 : }
36196 :
36197 20539 : static inline std::string id(expression_generator<Type>& expr_gen,
36198 : const details::operator_type o0,
36199 : const details::operator_type o1)
36200 : {
36201 41078 : return details::build_string()
36202 41078 : << "t" << expr_gen.to_str(o0)
36203 41078 : << "(t" << expr_gen.to_str(o1)
36204 41078 : << "t)";
36205 : }
36206 : };
36207 :
36208 : struct synthesize_vovoc_expression0
36209 : {
36210 : typedef typename vovoc_t::type0 node_type;
36211 : typedef typename vovoc_t::sf3_type sf3_type;
36212 :
36213 47502 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36214 : const details::operator_type& operation,
36215 : expression_node_ptr (&branch)[2])
36216 : {
36217 : // (v0 o0 v1) o1 (c)
36218 47502 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
36219 47502 : const Type& v0 = vov->v0();
36220 47502 : const Type& v1 = vov->v1();
36221 47502 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
36222 47502 : const details::operator_type o0 = vov->operation();
36223 47502 : const details::operator_type o1 = operation;
36224 :
36225 47502 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36226 47502 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36227 :
36228 47502 : expression_node_ptr result = error_node();
36229 :
36230 47502 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36231 : {
36232 : // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
36233 47502 : if ((details::e_div == o0) && (details::e_div == o1))
36234 : {
36235 : const bool synthesis_result =
36236 : synthesize_sf3ext_expression::
36237 6705 : template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
36238 :
36239 : exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
36240 :
36241 6705 : return (synthesis_result) ? result : error_node();
36242 : }
36243 : }
36244 :
36245 : const bool synthesis_result =
36246 : synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
36247 40797 : (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
36248 :
36249 40797 : if (synthesis_result)
36250 40033 : return result;
36251 :
36252 764 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36253 764 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36254 :
36255 764 : if (!expr_gen.valid_operator(o0,f0))
36256 0 : return error_node();
36257 764 : else if (!expr_gen.valid_operator(o1,f1))
36258 0 : return error_node();
36259 : else
36260 764 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
36261 : }
36262 :
36263 40797 : static inline std::string id(expression_generator<Type>& expr_gen,
36264 : const details::operator_type o0,
36265 : const details::operator_type o1)
36266 : {
36267 81594 : return details::build_string()
36268 81594 : << "(t" << expr_gen.to_str(o0)
36269 81594 : << "t)" << expr_gen.to_str(o1)
36270 81594 : << "t";
36271 : }
36272 : };
36273 :
36274 : struct synthesize_vovoc_expression1
36275 : {
36276 : typedef typename vovoc_t::type1 node_type;
36277 : typedef typename vovoc_t::sf3_type sf3_type;
36278 :
36279 24765 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36280 : const details::operator_type& operation,
36281 : expression_node_ptr (&branch)[2])
36282 : {
36283 : // (v0) o0 (v1 o1 c)
36284 24765 : const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
36285 24765 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
36286 24765 : const Type& v1 = voc->v();
36287 24765 : const Type c = voc->c();
36288 24765 : const details::operator_type o0 = operation;
36289 24765 : const details::operator_type o1 = voc->operation();
36290 :
36291 24765 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36292 :
36293 24765 : expression_node_ptr result = error_node();
36294 :
36295 24765 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36296 : {
36297 : // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
36298 24765 : if ((details::e_div == o0) && (details::e_div == o1))
36299 : {
36300 : const bool synthesis_result =
36301 : synthesize_sf3ext_expression::
36302 1365 : template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
36303 :
36304 : exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
36305 :
36306 1365 : return (synthesis_result) ? result : error_node();
36307 : }
36308 : }
36309 :
36310 : const bool synthesis_result =
36311 : synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
36312 23400 : (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
36313 :
36314 23400 : if (synthesis_result)
36315 23190 : return result;
36316 :
36317 210 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36318 210 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36319 :
36320 210 : if (!expr_gen.valid_operator(o0,f0))
36321 0 : return error_node();
36322 210 : else if (!expr_gen.valid_operator(o1,f1))
36323 0 : return error_node();
36324 : else
36325 210 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
36326 : }
36327 :
36328 23400 : static inline std::string id(expression_generator<Type>& expr_gen,
36329 : const details::operator_type o0,
36330 : const details::operator_type o1)
36331 : {
36332 46800 : return details::build_string()
36333 46800 : << "t" << expr_gen.to_str(o0)
36334 46800 : << "(t" << expr_gen.to_str(o1)
36335 46800 : << "t)";
36336 : }
36337 : };
36338 :
36339 : struct synthesize_vocov_expression0
36340 : {
36341 : typedef typename vocov_t::type0 node_type;
36342 : typedef typename vocov_t::sf3_type sf3_type;
36343 :
36344 52969 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36345 : const details::operator_type& operation,
36346 : expression_node_ptr (&branch)[2])
36347 : {
36348 : // (v0 o0 c) o1 (v1)
36349 52969 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
36350 52969 : const Type& v0 = voc->v();
36351 52969 : const Type c = voc->c();
36352 52969 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
36353 52969 : const details::operator_type o0 = voc->operation();
36354 52969 : const details::operator_type o1 = operation;
36355 :
36356 52969 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36357 :
36358 52969 : expression_node_ptr result = error_node();
36359 :
36360 52969 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36361 : {
36362 : // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
36363 52969 : if ((details::e_div == o0) && (details::e_div == o1))
36364 : {
36365 : const bool synthesis_result =
36366 : synthesize_sf3ext_expression::
36367 7400 : template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
36368 :
36369 : exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
36370 :
36371 7400 : return (synthesis_result) ? result : error_node();
36372 : }
36373 : }
36374 :
36375 : const bool synthesis_result =
36376 : synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
36377 45569 : (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
36378 :
36379 45569 : if (synthesis_result)
36380 45539 : return result;
36381 :
36382 30 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36383 30 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36384 :
36385 30 : if (!expr_gen.valid_operator(o0,f0))
36386 0 : return error_node();
36387 30 : else if (!expr_gen.valid_operator(o1,f1))
36388 0 : return error_node();
36389 : else
36390 30 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
36391 : }
36392 :
36393 45569 : static inline std::string id(expression_generator<Type>& expr_gen,
36394 : const details::operator_type o0,
36395 : const details::operator_type o1)
36396 : {
36397 91138 : return details::build_string()
36398 91138 : << "(t" << expr_gen.to_str(o0)
36399 91138 : << "t)" << expr_gen.to_str(o1)
36400 91138 : << "t";
36401 : }
36402 : };
36403 :
36404 : struct synthesize_vocov_expression1
36405 : {
36406 : typedef typename vocov_t::type1 node_type;
36407 : typedef typename vocov_t::sf3_type sf3_type;
36408 :
36409 28421 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36410 : const details::operator_type& operation,
36411 : expression_node_ptr (&branch)[2])
36412 : {
36413 : // (v0) o0 (c o1 v1)
36414 28421 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
36415 28421 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
36416 28421 : const Type c = cov->c();
36417 28421 : const Type& v1 = cov->v();
36418 28421 : const details::operator_type o0 = operation;
36419 28421 : const details::operator_type o1 = cov->operation();
36420 :
36421 28421 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36422 :
36423 28421 : expression_node_ptr result = error_node();
36424 :
36425 28421 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36426 : {
36427 : // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
36428 28421 : if ((details::e_div == o0) && (details::e_div == o1))
36429 : {
36430 : const bool synthesis_result =
36431 : synthesize_sf3ext_expression::
36432 1565 : template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
36433 :
36434 : exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
36435 :
36436 1565 : return (synthesis_result) ? result : error_node();
36437 : }
36438 : }
36439 :
36440 : const bool synthesis_result =
36441 : synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
36442 26856 : (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
36443 :
36444 26856 : if (synthesis_result)
36445 26765 : return result;
36446 :
36447 91 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36448 91 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36449 :
36450 91 : if (!expr_gen.valid_operator(o0,f0))
36451 0 : return error_node();
36452 91 : else if (!expr_gen.valid_operator(o1,f1))
36453 0 : return error_node();
36454 : else
36455 91 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
36456 : }
36457 :
36458 26856 : static inline std::string id(expression_generator<Type>& expr_gen,
36459 : const details::operator_type o0,
36460 : const details::operator_type o1)
36461 : {
36462 53712 : return details::build_string()
36463 53712 : << "t" << expr_gen.to_str(o0)
36464 53712 : << "(t" << expr_gen.to_str(o1)
36465 53712 : << "t)";
36466 : }
36467 : };
36468 :
36469 : struct synthesize_covov_expression0
36470 : {
36471 : typedef typename covov_t::type0 node_type;
36472 : typedef typename covov_t::sf3_type sf3_type;
36473 :
36474 57476 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36475 : const details::operator_type& operation,
36476 : expression_node_ptr (&branch)[2])
36477 : {
36478 : // (c o0 v0) o1 (v1)
36479 57476 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
36480 57476 : const Type c = cov->c();
36481 57476 : const Type& v0 = cov->v();
36482 57476 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
36483 57476 : const details::operator_type o0 = cov->operation();
36484 57476 : const details::operator_type o1 = operation;
36485 :
36486 57476 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36487 :
36488 57476 : expression_node_ptr result = error_node();
36489 :
36490 57476 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36491 : {
36492 : // (c / v0) / v1 --> (covov) c / (v0 * v1)
36493 57476 : if ((details::e_div == o0) && (details::e_div == o1))
36494 : {
36495 : const bool synthesis_result =
36496 : synthesize_sf3ext_expression::
36497 8415 : template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
36498 :
36499 : exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
36500 :
36501 8415 : return (synthesis_result) ? result : error_node();
36502 : }
36503 : }
36504 :
36505 : const bool synthesis_result =
36506 : synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
36507 49061 : (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
36508 :
36509 49061 : if (synthesis_result)
36510 49061 : return result;
36511 :
36512 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36513 0 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36514 :
36515 0 : if (!expr_gen.valid_operator(o0,f0))
36516 0 : return error_node();
36517 0 : else if (!expr_gen.valid_operator(o1,f1))
36518 0 : return error_node();
36519 : else
36520 0 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
36521 : }
36522 :
36523 49061 : static inline std::string id(expression_generator<Type>& expr_gen,
36524 : const details::operator_type o0,
36525 : const details::operator_type o1)
36526 : {
36527 98122 : return details::build_string()
36528 98122 : << "(t" << expr_gen.to_str(o0)
36529 98122 : << "t)" << expr_gen.to_str(o1)
36530 98122 : << "t";
36531 : }
36532 : };
36533 :
36534 : struct synthesize_covov_expression1
36535 : {
36536 : typedef typename covov_t::type1 node_type;
36537 : typedef typename covov_t::sf3_type sf3_type;
36538 :
36539 35209 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36540 : const details::operator_type& operation,
36541 : expression_node_ptr (&branch)[2])
36542 : {
36543 : // (c) o0 (v0 o1 v1)
36544 35209 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
36545 35209 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
36546 35209 : const Type& v0 = vov->v0();
36547 35209 : const Type& v1 = vov->v1();
36548 35209 : const details::operator_type o0 = operation;
36549 35209 : const details::operator_type o1 = vov->operation();
36550 :
36551 35209 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36552 35209 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36553 :
36554 35209 : expression_node_ptr result = error_node();
36555 :
36556 35209 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36557 : {
36558 : // c / (v0 / v1) --> (covov) (c * v1) / v0
36559 35209 : if ((details::e_div == o0) && (details::e_div == o1))
36560 : {
36561 : const bool synthesis_result =
36562 : synthesize_sf3ext_expression::
36563 1325 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
36564 :
36565 : exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
36566 :
36567 1325 : return (synthesis_result) ? result : error_node();
36568 : }
36569 : }
36570 :
36571 : const bool synthesis_result =
36572 : synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
36573 33884 : (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
36574 :
36575 33884 : if (synthesis_result)
36576 33823 : return result;
36577 :
36578 61 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36579 61 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36580 :
36581 61 : if (!expr_gen.valid_operator(o0,f0))
36582 0 : return error_node();
36583 61 : else if (!expr_gen.valid_operator(o1,f1))
36584 0 : return error_node();
36585 : else
36586 61 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
36587 : }
36588 :
36589 33884 : static inline std::string id(expression_generator<Type>& expr_gen,
36590 : const details::operator_type o0,
36591 : const details::operator_type o1)
36592 : {
36593 67768 : return details::build_string()
36594 67768 : << "t" << expr_gen.to_str(o0)
36595 67768 : << "(t" << expr_gen.to_str(o1)
36596 67768 : << "t)";
36597 : }
36598 : };
36599 :
36600 : struct synthesize_covoc_expression0
36601 : {
36602 : typedef typename covoc_t::type0 node_type;
36603 : typedef typename covoc_t::sf3_type sf3_type;
36604 :
36605 40734 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36606 : const details::operator_type& operation,
36607 : expression_node_ptr (&branch)[2])
36608 : {
36609 : // (c0 o0 v) o1 (c1)
36610 40734 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
36611 40734 : const Type c0 = cov->c();
36612 40734 : const Type& v = cov->v();
36613 40734 : const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
36614 40734 : const details::operator_type o0 = cov->operation();
36615 40734 : const details::operator_type o1 = operation;
36616 :
36617 40734 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36618 40734 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36619 :
36620 40734 : expression_node_ptr result = error_node();
36621 :
36622 40734 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36623 : {
36624 : // (c0 + v) + c1 --> (cov) (c0 + c1) + v
36625 40734 : if ((details::e_add == o0) && (details::e_add == o1))
36626 : {
36627 : exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
36628 :
36629 2727 : return expr_gen.node_allocator_->
36630 2727 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
36631 : }
36632 : // (c0 + v) - c1 --> (cov) (c0 - c1) + v
36633 38007 : else if ((details::e_add == o0) && (details::e_sub == o1))
36634 : {
36635 : exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
36636 :
36637 2206 : return expr_gen.node_allocator_->
36638 2206 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
36639 : }
36640 : // (c0 - v) + c1 --> (cov) (c0 + c1) - v
36641 35801 : else if ((details::e_sub == o0) && (details::e_add == o1))
36642 : {
36643 : exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
36644 :
36645 1760 : return expr_gen.node_allocator_->
36646 1760 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
36647 : }
36648 : // (c0 - v) - c1 --> (cov) (c0 - c1) - v
36649 34041 : else if ((details::e_sub == o0) && (details::e_sub == o1))
36650 : {
36651 : exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
36652 :
36653 1991 : return expr_gen.node_allocator_->
36654 1991 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
36655 : }
36656 : // (c0 * v) * c1 --> (cov) (c0 * c1) * v
36657 32050 : else if ((details::e_mul == o0) && (details::e_mul == o1))
36658 : {
36659 : exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
36660 :
36661 3375 : return expr_gen.node_allocator_->
36662 3375 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
36663 : }
36664 : // (c0 * v) / c1 --> (cov) (c0 / c1) * v
36665 28675 : else if ((details::e_mul == o0) && (details::e_div == o1))
36666 : {
36667 : exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
36668 :
36669 3097 : return expr_gen.node_allocator_->
36670 3097 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
36671 : }
36672 : // (c0 / v) * c1 --> (cov) (c0 * c1) / v
36673 25578 : else if ((details::e_div == o0) && (details::e_mul == o1))
36674 : {
36675 : exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
36676 :
36677 3290 : return expr_gen.node_allocator_->
36678 3290 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
36679 : }
36680 : // (c0 / v) / c1 --> (cov) (c0 / c1) / v
36681 22288 : else if ((details::e_div == o0) && (details::e_div == o1))
36682 : {
36683 : exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
36684 :
36685 3845 : return expr_gen.node_allocator_->
36686 3845 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
36687 : }
36688 : }
36689 :
36690 : const bool synthesis_result =
36691 : synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
36692 18443 : (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
36693 :
36694 18443 : if (synthesis_result)
36695 16833 : return result;
36696 :
36697 1610 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36698 1610 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36699 :
36700 1610 : if (!expr_gen.valid_operator(o0,f0))
36701 0 : return error_node();
36702 1610 : else if (!expr_gen.valid_operator(o1,f1))
36703 0 : return error_node();
36704 : else
36705 1610 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
36706 : }
36707 :
36708 18443 : static inline std::string id(expression_generator<Type>& expr_gen,
36709 : const details::operator_type o0,
36710 : const details::operator_type o1)
36711 : {
36712 36886 : return details::build_string()
36713 36886 : << "(t" << expr_gen.to_str(o0)
36714 36886 : << "t)" << expr_gen.to_str(o1)
36715 36886 : << "t";
36716 : }
36717 : };
36718 :
36719 : struct synthesize_covoc_expression1
36720 : {
36721 : typedef typename covoc_t::type1 node_type;
36722 : typedef typename covoc_t::sf3_type sf3_type;
36723 :
36724 14571 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36725 : const details::operator_type& operation,
36726 : expression_node_ptr (&branch)[2])
36727 : {
36728 : // (c0) o0 (v o1 c1)
36729 14571 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
36730 14571 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
36731 14571 : const Type& v = voc->v();
36732 14571 : const Type c1 = voc->c();
36733 14571 : const details::operator_type o0 = operation;
36734 14571 : const details::operator_type o1 = voc->operation();
36735 :
36736 14571 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36737 14571 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36738 :
36739 14571 : expression_node_ptr result = error_node();
36740 :
36741 14571 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36742 : {
36743 : // (c0) + (v + c1) --> (cov) (c0 + c1) + v
36744 14571 : if ((details::e_add == o0) && (details::e_add == o1))
36745 : {
36746 : exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
36747 :
36748 885 : return expr_gen.node_allocator_->
36749 885 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
36750 : }
36751 : // (c0) + (v - c1) --> (cov) (c0 - c1) + v
36752 13686 : else if ((details::e_add == o0) && (details::e_sub == o1))
36753 : {
36754 : exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
36755 :
36756 865 : return expr_gen.node_allocator_->
36757 865 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
36758 : }
36759 : // (c0) - (v + c1) --> (cov) (c0 - c1) - v
36760 12821 : else if ((details::e_sub == o0) && (details::e_add == o1))
36761 : {
36762 : exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
36763 :
36764 855 : return expr_gen.node_allocator_->
36765 855 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
36766 : }
36767 : // (c0) - (v - c1) --> (cov) (c0 + c1) - v
36768 11966 : else if ((details::e_sub == o0) && (details::e_sub == o1))
36769 : {
36770 : exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
36771 :
36772 835 : return expr_gen.node_allocator_->
36773 835 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
36774 : }
36775 : // (c0) * (v * c1) --> (voc) v * (c0 * c1)
36776 11131 : else if ((details::e_mul == o0) && (details::e_mul == o1))
36777 : {
36778 : exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
36779 :
36780 875 : return expr_gen.node_allocator_->
36781 875 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
36782 : }
36783 : // (c0) * (v / c1) --> (cov) (c0 / c1) * v
36784 10256 : else if ((details::e_mul == o0) && (details::e_div == o1))
36785 : {
36786 : exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
36787 :
36788 865 : return expr_gen.node_allocator_->
36789 865 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
36790 : }
36791 : // (c0) / (v * c1) --> (cov) (c0 / c1) / v
36792 9391 : else if ((details::e_div == o0) && (details::e_mul == o1))
36793 : {
36794 : exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
36795 :
36796 845 : return expr_gen.node_allocator_->
36797 845 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
36798 : }
36799 : // (c0) / (v / c1) --> (cov) (c0 * c1) / v
36800 8546 : else if ((details::e_div == o0) && (details::e_div == o1))
36801 : {
36802 : exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
36803 :
36804 835 : return expr_gen.node_allocator_->
36805 835 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
36806 : }
36807 : }
36808 :
36809 : const bool synthesis_result =
36810 : synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
36811 7711 : (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
36812 :
36813 7711 : if (synthesis_result)
36814 7630 : return result;
36815 :
36816 81 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36817 81 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36818 :
36819 81 : if (!expr_gen.valid_operator(o0,f0))
36820 0 : return error_node();
36821 81 : else if (!expr_gen.valid_operator(o1,f1))
36822 0 : return error_node();
36823 : else
36824 81 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
36825 : }
36826 :
36827 7711 : static inline std::string id(expression_generator<Type>& expr_gen,
36828 : const details::operator_type o0,
36829 : const details::operator_type o1)
36830 : {
36831 15422 : return details::build_string()
36832 15422 : << "t" << expr_gen.to_str(o0)
36833 15422 : << "(t" << expr_gen.to_str(o1)
36834 15422 : << "t)";
36835 : }
36836 : };
36837 :
36838 : struct synthesize_cocov_expression0
36839 : {
36840 : typedef typename cocov_t::type0 node_type;
36841 : static inline expression_node_ptr process(expression_generator<Type>&,
36842 : const details::operator_type&,
36843 : expression_node_ptr (&)[2])
36844 : {
36845 : // (c0 o0 c1) o1 (v) - Not possible.
36846 : return error_node();
36847 : }
36848 : };
36849 :
36850 : struct synthesize_cocov_expression1
36851 : {
36852 : typedef typename cocov_t::type1 node_type;
36853 : typedef typename cocov_t::sf3_type sf3_type;
36854 :
36855 16245 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36856 : const details::operator_type& operation,
36857 : expression_node_ptr (&branch)[2])
36858 : {
36859 : // (c0) o0 (c1 o1 v)
36860 16245 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
36861 16245 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
36862 16245 : const Type c1 = cov->c();
36863 16245 : const Type& v = cov->v();
36864 16245 : const details::operator_type o0 = operation;
36865 16245 : const details::operator_type o1 = cov->operation();
36866 :
36867 16245 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36868 16245 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36869 :
36870 16245 : expression_node_ptr result = error_node();
36871 :
36872 16245 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36873 : {
36874 : // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
36875 16245 : if ((details::e_add == o0) && (details::e_add == o1))
36876 : {
36877 : exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
36878 :
36879 1045 : return expr_gen.node_allocator_->
36880 1045 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
36881 : }
36882 : // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
36883 15200 : else if ((details::e_add == o0) && (details::e_sub == o1))
36884 : {
36885 : exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
36886 :
36887 1025 : return expr_gen.node_allocator_->
36888 1025 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
36889 : }
36890 : // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
36891 14175 : else if ((details::e_sub == o0) && (details::e_add == o1))
36892 : {
36893 : exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
36894 :
36895 1010 : return expr_gen.node_allocator_->
36896 1010 : template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
36897 : }
36898 : // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
36899 13165 : else if ((details::e_sub == o0) && (details::e_sub == o1))
36900 : {
36901 : exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
36902 :
36903 1010 : return expr_gen.node_allocator_->
36904 1010 : template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
36905 : }
36906 : // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
36907 12155 : else if ((details::e_mul == o0) && (details::e_mul == o1))
36908 : {
36909 : exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
36910 :
36911 885 : return expr_gen.node_allocator_->
36912 885 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
36913 : }
36914 : // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
36915 11270 : else if ((details::e_mul == o0) && (details::e_div == o1))
36916 : {
36917 : exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
36918 :
36919 875 : return expr_gen.node_allocator_->
36920 875 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
36921 : }
36922 : // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
36923 10395 : else if ((details::e_div == o0) && (details::e_mul == o1))
36924 : {
36925 : exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
36926 :
36927 840 : return expr_gen.node_allocator_->
36928 840 : template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
36929 : }
36930 : // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
36931 9555 : else if ((details::e_div == o0) && (details::e_div == o1))
36932 : {
36933 : exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
36934 :
36935 850 : return expr_gen.node_allocator_->
36936 850 : template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
36937 : }
36938 : }
36939 :
36940 : const bool synthesis_result =
36941 : synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
36942 8705 : (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
36943 :
36944 8705 : if (synthesis_result)
36945 8642 : return result;
36946 :
36947 63 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
36948 63 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
36949 :
36950 63 : if (!expr_gen.valid_operator(o0,f0))
36951 0 : return error_node();
36952 63 : else if (!expr_gen.valid_operator(o1,f1))
36953 0 : return error_node();
36954 : else
36955 63 : return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
36956 : }
36957 :
36958 8705 : static inline std::string id(expression_generator<Type>& expr_gen,
36959 : const details::operator_type o0,
36960 : const details::operator_type o1)
36961 : {
36962 17410 : return details::build_string()
36963 17410 : << "t" << expr_gen.to_str(o0)
36964 17410 : << "(t" << expr_gen.to_str(o1)
36965 17410 : << "t)";
36966 : }
36967 : };
36968 :
36969 : struct synthesize_vococ_expression0
36970 : {
36971 : typedef typename vococ_t::type0 node_type;
36972 : typedef typename vococ_t::sf3_type sf3_type;
36973 :
36974 28769 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
36975 : const details::operator_type& operation,
36976 : expression_node_ptr (&branch)[2])
36977 : {
36978 : // (v o0 c0) o1 (c1)
36979 28769 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
36980 28769 : const Type& v = voc->v();
36981 28769 : const Type& c0 = voc->c();
36982 28769 : const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
36983 28769 : const details::operator_type o0 = voc->operation();
36984 28769 : const details::operator_type o1 = operation;
36985 :
36986 28769 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
36987 28769 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
36988 :
36989 28769 : expression_node_ptr result = error_node();
36990 :
36991 28769 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
36992 : {
36993 : // (v + c0) + c1 --> (voc) v + (c0 + c1)
36994 28769 : if ((details::e_add == o0) && (details::e_add == o1))
36995 : {
36996 : exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
36997 :
36998 2430 : return expr_gen.node_allocator_->
36999 2430 : template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
37000 : }
37001 : // (v + c0) - c1 --> (voc) v + (c0 - c1)
37002 26339 : else if ((details::e_add == o0) && (details::e_sub == o1))
37003 : {
37004 : exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
37005 :
37006 2065 : return expr_gen.node_allocator_->
37007 2065 : template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
37008 : }
37009 : // (v - c0) + c1 --> (voc) v - (c0 + c1)
37010 24274 : else if ((details::e_sub == o0) && (details::e_add == o1))
37011 : {
37012 : exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
37013 :
37014 1810 : return expr_gen.node_allocator_->
37015 1810 : template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
37016 : }
37017 : // (v - c0) - c1 --> (voc) v - (c0 + c1)
37018 22464 : else if ((details::e_sub == o0) && (details::e_sub == o1))
37019 : {
37020 : exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
37021 :
37022 1745 : return expr_gen.node_allocator_->
37023 1745 : template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
37024 : }
37025 : // (v * c0) * c1 --> (voc) v * (c0 * c1)
37026 20719 : else if ((details::e_mul == o0) && (details::e_mul == o1))
37027 : {
37028 : exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
37029 :
37030 2915 : return expr_gen.node_allocator_->
37031 2915 : template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
37032 : }
37033 : // (v * c0) / c1 --> (voc) v * (c0 / c1)
37034 17804 : else if ((details::e_mul == o0) && (details::e_div == o1))
37035 : {
37036 : exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
37037 :
37038 2220 : return expr_gen.node_allocator_->
37039 2220 : template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
37040 : }
37041 : // (v / c0) * c1 --> (voc) v * (c1 / c0)
37042 15584 : else if ((details::e_div == o0) && (details::e_mul == o1))
37043 : {
37044 : exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
37045 :
37046 2726 : return expr_gen.node_allocator_->
37047 2726 : template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
37048 : }
37049 : // (v / c0) / c1 --> (voc) v / (c0 * c1)
37050 12858 : else if ((details::e_div == o0) && (details::e_div == o1))
37051 : {
37052 : exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
37053 :
37054 3150 : return expr_gen.node_allocator_->
37055 3150 : template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
37056 : }
37057 : // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
37058 9708 : else if ((details::e_pow == o0) && (details::e_pow == o1))
37059 : {
37060 : exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
37061 :
37062 40 : return expr_gen.node_allocator_->
37063 40 : template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
37064 : }
37065 : }
37066 :
37067 : const bool synthesis_result =
37068 : synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
37069 9668 : (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
37070 :
37071 9668 : if (synthesis_result)
37072 7543 : return result;
37073 :
37074 2125 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37075 2125 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37076 :
37077 2125 : if (!expr_gen.valid_operator(o0,f0))
37078 0 : return error_node();
37079 2125 : else if (!expr_gen.valid_operator(o1,f1))
37080 0 : return error_node();
37081 : else
37082 2125 : return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
37083 : }
37084 :
37085 9668 : static inline std::string id(expression_generator<Type>& expr_gen,
37086 : const details::operator_type o0,
37087 : const details::operator_type o1)
37088 : {
37089 19336 : return details::build_string()
37090 19336 : << "(t" << expr_gen.to_str(o0)
37091 19336 : << "t)" << expr_gen.to_str(o1)
37092 19336 : << "t";
37093 : }
37094 : };
37095 :
37096 : struct synthesize_vococ_expression1
37097 : {
37098 : typedef typename vococ_t::type0 node_type;
37099 :
37100 : static inline expression_node_ptr process(expression_generator<Type>&,
37101 : const details::operator_type&,
37102 : expression_node_ptr (&)[2])
37103 : {
37104 : // (v) o0 (c0 o1 c1) - Not possible.
37105 : exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
37106 : return error_node();
37107 : }
37108 : };
37109 :
37110 : struct synthesize_vovovov_expression0
37111 : {
37112 : typedef typename vovovov_t::type0 node_type;
37113 : typedef typename vovovov_t::sf4_type sf4_type;
37114 : typedef typename node_type::T0 T0;
37115 : typedef typename node_type::T1 T1;
37116 : typedef typename node_type::T2 T2;
37117 : typedef typename node_type::T3 T3;
37118 :
37119 10110 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37120 : const details::operator_type& operation,
37121 : expression_node_ptr (&branch)[2])
37122 : {
37123 : // (v0 o0 v1) o1 (v2 o2 v3)
37124 10110 : const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
37125 10110 : const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
37126 10110 : const Type& v0 = vov0->v0();
37127 10110 : const Type& v1 = vov0->v1();
37128 10110 : const Type& v2 = vov1->v0();
37129 10110 : const Type& v3 = vov1->v1();
37130 10110 : const details::operator_type o0 = vov0->operation();
37131 10110 : const details::operator_type o1 = operation;
37132 10110 : const details::operator_type o2 = vov1->operation();
37133 :
37134 10110 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37135 10110 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37136 :
37137 10110 : expression_node_ptr result = error_node();
37138 :
37139 10110 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37140 : {
37141 : // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
37142 10110 : if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37143 : {
37144 : const bool synthesis_result =
37145 : synthesize_sf4ext_expression::
37146 80 : template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
37147 :
37148 : exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
37149 :
37150 80 : return (synthesis_result) ? result : error_node();
37151 : }
37152 : // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
37153 10030 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37154 : {
37155 : const bool synthesis_result =
37156 : synthesize_sf4ext_expression::
37157 80 : template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
37158 :
37159 : exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
37160 :
37161 80 : return (synthesis_result) ? result : error_node();
37162 : }
37163 : // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
37164 9950 : else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
37165 : {
37166 : const bool synthesis_result =
37167 : synthesize_sf4ext_expression::
37168 155 : template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
37169 :
37170 : exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
37171 :
37172 155 : return (synthesis_result) ? result : error_node();
37173 : }
37174 : // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
37175 9795 : else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
37176 : {
37177 : const bool synthesis_result =
37178 : synthesize_sf4ext_expression::
37179 155 : template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
37180 :
37181 : exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
37182 :
37183 155 : return (synthesis_result) ? result : error_node();
37184 : }
37185 : // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
37186 9640 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
37187 : {
37188 : const bool synthesis_result =
37189 : synthesize_sf4ext_expression::
37190 80 : template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
37191 :
37192 : exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
37193 :
37194 80 : return (synthesis_result) ? result : error_node();
37195 : }
37196 : }
37197 :
37198 : const bool synthesis_result =
37199 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37200 9560 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
37201 :
37202 9560 : if (synthesis_result)
37203 7806 : return result;
37204 :
37205 1754 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37206 1754 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37207 1754 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37208 :
37209 1754 : if (!expr_gen.valid_operator(o0,f0))
37210 0 : return error_node();
37211 1754 : else if (!expr_gen.valid_operator(o1,f1))
37212 0 : return error_node();
37213 1754 : else if (!expr_gen.valid_operator(o2,f2))
37214 0 : return error_node();
37215 : else
37216 1754 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
37217 : }
37218 :
37219 9560 : static inline std::string id(expression_generator<Type>& expr_gen,
37220 : const details::operator_type o0,
37221 : const details::operator_type o1,
37222 : const details::operator_type o2)
37223 : {
37224 19120 : return details::build_string()
37225 19120 : << "(t" << expr_gen.to_str(o0)
37226 19120 : << "t)" << expr_gen.to_str(o1)
37227 19120 : << "(t" << expr_gen.to_str(o2)
37228 19120 : << "t)";
37229 : }
37230 : };
37231 :
37232 : struct synthesize_vovovoc_expression0
37233 : {
37234 : typedef typename vovovoc_t::type0 node_type;
37235 : typedef typename vovovoc_t::sf4_type sf4_type;
37236 : typedef typename node_type::T0 T0;
37237 : typedef typename node_type::T1 T1;
37238 : typedef typename node_type::T2 T2;
37239 : typedef typename node_type::T3 T3;
37240 :
37241 7710 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37242 : const details::operator_type& operation,
37243 : expression_node_ptr (&branch)[2])
37244 : {
37245 : // (v0 o0 v1) o1 (v2 o2 c)
37246 7710 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
37247 7710 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
37248 7710 : const Type& v0 = vov->v0();
37249 7710 : const Type& v1 = vov->v1();
37250 7710 : const Type& v2 = voc->v ();
37251 7710 : const Type c = voc->c ();
37252 7710 : const details::operator_type o0 = vov->operation();
37253 7710 : const details::operator_type o1 = operation;
37254 7710 : const details::operator_type o2 = voc->operation();
37255 :
37256 7710 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37257 7710 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37258 :
37259 7710 : expression_node_ptr result = error_node();
37260 :
37261 7710 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37262 : {
37263 : // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
37264 7710 : if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37265 : {
37266 : const bool synthesis_result =
37267 : synthesize_sf4ext_expression::
37268 80 : template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
37269 :
37270 : exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
37271 :
37272 80 : return (synthesis_result) ? result : error_node();
37273 : }
37274 : // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
37275 7630 : if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37276 : {
37277 : const bool synthesis_result =
37278 : synthesize_sf4ext_expression::
37279 80 : template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
37280 :
37281 : exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
37282 :
37283 80 : return (synthesis_result) ? result : error_node();
37284 : }
37285 : }
37286 :
37287 : const bool synthesis_result =
37288 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37289 7550 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
37290 :
37291 7550 : if (synthesis_result)
37292 7010 : return result;
37293 :
37294 540 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37295 540 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37296 540 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37297 :
37298 540 : if (!expr_gen.valid_operator(o0,f0))
37299 0 : return error_node();
37300 540 : else if (!expr_gen.valid_operator(o1,f1))
37301 0 : return error_node();
37302 540 : else if (!expr_gen.valid_operator(o2,f2))
37303 0 : return error_node();
37304 : else
37305 540 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
37306 : }
37307 :
37308 7550 : static inline std::string id(expression_generator<Type>& expr_gen,
37309 : const details::operator_type o0,
37310 : const details::operator_type o1,
37311 : const details::operator_type o2)
37312 : {
37313 15100 : return details::build_string()
37314 15100 : << "(t" << expr_gen.to_str(o0)
37315 15100 : << "t)" << expr_gen.to_str(o1)
37316 15100 : << "(t" << expr_gen.to_str(o2)
37317 15100 : << "t)";
37318 : }
37319 : };
37320 :
37321 : struct synthesize_vovocov_expression0
37322 : {
37323 : typedef typename vovocov_t::type0 node_type;
37324 : typedef typename vovocov_t::sf4_type sf4_type;
37325 : typedef typename node_type::T0 T0;
37326 : typedef typename node_type::T1 T1;
37327 : typedef typename node_type::T2 T2;
37328 : typedef typename node_type::T3 T3;
37329 :
37330 11647 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37331 : const details::operator_type& operation,
37332 : expression_node_ptr (&branch)[2])
37333 : {
37334 : // (v0 o0 v1) o1 (c o2 v2)
37335 11647 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
37336 11647 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
37337 11647 : const Type& v0 = vov->v0();
37338 11647 : const Type& v1 = vov->v1();
37339 11647 : const Type& v2 = cov->v ();
37340 11647 : const Type c = cov->c ();
37341 11647 : const details::operator_type o0 = vov->operation();
37342 11647 : const details::operator_type o1 = operation;
37343 11647 : const details::operator_type o2 = cov->operation();
37344 :
37345 11647 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37346 11647 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37347 :
37348 11647 : expression_node_ptr result = error_node();
37349 :
37350 11647 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37351 : {
37352 : // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
37353 11647 : if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37354 : {
37355 : const bool synthesis_result =
37356 : synthesize_sf4ext_expression::
37357 80 : template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
37358 :
37359 : exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
37360 :
37361 80 : return (synthesis_result) ? result : error_node();
37362 : }
37363 : // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
37364 11567 : if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37365 : {
37366 : const bool synthesis_result =
37367 : synthesize_sf4ext_expression::
37368 80 : template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
37369 :
37370 : exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
37371 :
37372 80 : return (synthesis_result) ? result : error_node();
37373 : }
37374 : }
37375 :
37376 : const bool synthesis_result =
37377 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37378 11487 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
37379 :
37380 11487 : if (synthesis_result)
37381 11092 : return result;
37382 :
37383 395 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37384 395 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37385 395 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37386 :
37387 395 : if (!expr_gen.valid_operator(o0,f0))
37388 0 : return error_node();
37389 395 : else if (!expr_gen.valid_operator(o1,f1))
37390 0 : return error_node();
37391 395 : else if (!expr_gen.valid_operator(o2,f2))
37392 0 : return error_node();
37393 : else
37394 395 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
37395 : }
37396 :
37397 11487 : static inline std::string id(expression_generator<Type>& expr_gen,
37398 : const details::operator_type o0,
37399 : const details::operator_type o1,
37400 : const details::operator_type o2)
37401 : {
37402 22974 : return details::build_string()
37403 22974 : << "(t" << expr_gen.to_str(o0)
37404 22974 : << "t)" << expr_gen.to_str(o1)
37405 22974 : << "(t" << expr_gen.to_str(o2)
37406 22974 : << "t)";
37407 : }
37408 : };
37409 :
37410 : struct synthesize_vocovov_expression0
37411 : {
37412 : typedef typename vocovov_t::type0 node_type;
37413 : typedef typename vocovov_t::sf4_type sf4_type;
37414 : typedef typename node_type::T0 T0;
37415 : typedef typename node_type::T1 T1;
37416 : typedef typename node_type::T2 T2;
37417 : typedef typename node_type::T3 T3;
37418 :
37419 7695 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37420 : const details::operator_type& operation,
37421 : expression_node_ptr (&branch)[2])
37422 : {
37423 : // (v0 o0 c) o1 (v1 o2 v2)
37424 7695 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
37425 7695 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
37426 7695 : const Type c = voc->c ();
37427 7695 : const Type& v0 = voc->v ();
37428 7695 : const Type& v1 = vov->v0();
37429 7695 : const Type& v2 = vov->v1();
37430 7695 : const details::operator_type o0 = voc->operation();
37431 7695 : const details::operator_type o1 = operation;
37432 7695 : const details::operator_type o2 = vov->operation();
37433 :
37434 7695 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37435 7695 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37436 :
37437 7695 : expression_node_ptr result = error_node();
37438 :
37439 7695 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37440 : {
37441 : // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
37442 7695 : if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37443 : {
37444 : const bool synthesis_result =
37445 : synthesize_sf4ext_expression::
37446 80 : template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
37447 :
37448 : exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
37449 :
37450 80 : return (synthesis_result) ? result : error_node();
37451 : }
37452 : // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
37453 7615 : if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37454 : {
37455 : const bool synthesis_result =
37456 : synthesize_sf4ext_expression::
37457 80 : template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
37458 :
37459 : exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
37460 :
37461 80 : return (synthesis_result) ? result : error_node();
37462 : }
37463 : }
37464 :
37465 : const bool synthesis_result =
37466 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37467 7535 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
37468 :
37469 7535 : if (synthesis_result)
37470 7100 : return result;
37471 :
37472 435 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37473 435 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37474 435 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37475 :
37476 435 : if (!expr_gen.valid_operator(o0,f0))
37477 0 : return error_node();
37478 435 : else if (!expr_gen.valid_operator(o1,f1))
37479 0 : return error_node();
37480 435 : else if (!expr_gen.valid_operator(o2,f2))
37481 0 : return error_node();
37482 : else
37483 435 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
37484 : }
37485 :
37486 7535 : static inline std::string id(expression_generator<Type>& expr_gen,
37487 : const details::operator_type o0,
37488 : const details::operator_type o1,
37489 : const details::operator_type o2)
37490 : {
37491 15070 : return details::build_string()
37492 15070 : << "(t" << expr_gen.to_str(o0)
37493 15070 : << "t)" << expr_gen.to_str(o1)
37494 15070 : << "(t" << expr_gen.to_str(o2)
37495 15070 : << "t)";
37496 : }
37497 : };
37498 :
37499 : struct synthesize_covovov_expression0
37500 : {
37501 : typedef typename covovov_t::type0 node_type;
37502 : typedef typename covovov_t::sf4_type sf4_type;
37503 : typedef typename node_type::T0 T0;
37504 : typedef typename node_type::T1 T1;
37505 : typedef typename node_type::T2 T2;
37506 : typedef typename node_type::T3 T3;
37507 :
37508 7520 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37509 : const details::operator_type& operation,
37510 : expression_node_ptr (&branch)[2])
37511 : {
37512 : // (c o0 v0) o1 (v1 o2 v2)
37513 7520 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
37514 7520 : const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
37515 7520 : const Type c = cov->c ();
37516 7520 : const Type& v0 = cov->v ();
37517 7520 : const Type& v1 = vov->v0();
37518 7520 : const Type& v2 = vov->v1();
37519 7520 : const details::operator_type o0 = cov->operation();
37520 7520 : const details::operator_type o1 = operation;
37521 7520 : const details::operator_type o2 = vov->operation();
37522 :
37523 7520 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37524 7520 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37525 :
37526 7520 : expression_node_ptr result = error_node();
37527 :
37528 7520 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37529 : {
37530 : // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
37531 7520 : if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37532 : {
37533 : const bool synthesis_result =
37534 : synthesize_sf4ext_expression::
37535 80 : template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
37536 :
37537 : exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
37538 :
37539 80 : return (synthesis_result) ? result : error_node();
37540 : }
37541 : // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
37542 7440 : if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37543 : {
37544 : const bool synthesis_result =
37545 : synthesize_sf4ext_expression::
37546 80 : template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
37547 :
37548 : exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
37549 :
37550 80 : return (synthesis_result) ? result : error_node();
37551 : }
37552 : }
37553 :
37554 : const bool synthesis_result =
37555 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37556 7360 : (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
37557 :
37558 7360 : if (synthesis_result)
37559 7045 : return result;
37560 :
37561 315 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37562 315 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37563 315 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37564 :
37565 315 : if (!expr_gen.valid_operator(o0,f0))
37566 0 : return error_node();
37567 315 : else if (!expr_gen.valid_operator(o1,f1))
37568 0 : return error_node();
37569 315 : else if (!expr_gen.valid_operator(o2,f2))
37570 0 : return error_node();
37571 : else
37572 315 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
37573 : }
37574 :
37575 7360 : static inline std::string id(expression_generator<Type>& expr_gen,
37576 : const details::operator_type o0,
37577 : const details::operator_type o1,
37578 : const details::operator_type o2)
37579 : {
37580 14720 : return details::build_string()
37581 14720 : << "(t" << expr_gen.to_str(o0)
37582 14720 : << "t)" << expr_gen.to_str(o1)
37583 14720 : << "(t" << expr_gen.to_str(o2)
37584 14720 : << "t)";
37585 : }
37586 : };
37587 :
37588 : struct synthesize_covocov_expression0
37589 : {
37590 : typedef typename covocov_t::type0 node_type;
37591 : typedef typename covocov_t::sf4_type sf4_type;
37592 : typedef typename node_type::T0 T0;
37593 : typedef typename node_type::T1 T1;
37594 : typedef typename node_type::T2 T2;
37595 : typedef typename node_type::T3 T3;
37596 :
37597 6351 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37598 : const details::operator_type& operation,
37599 : expression_node_ptr (&branch)[2])
37600 : {
37601 : // (c0 o0 v0) o1 (c1 o2 v1)
37602 6351 : const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
37603 6351 : const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
37604 6351 : const Type c0 = cov0->c();
37605 6351 : const Type& v0 = cov0->v();
37606 6351 : const Type c1 = cov1->c();
37607 6351 : const Type& v1 = cov1->v();
37608 6351 : const details::operator_type o0 = cov0->operation();
37609 6351 : const details::operator_type o1 = operation;
37610 6351 : const details::operator_type o2 = cov1->operation();
37611 :
37612 6351 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37613 6351 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37614 :
37615 6351 : expression_node_ptr result = error_node();
37616 :
37617 6351 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37618 : {
37619 : // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
37620 6351 : if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
37621 : {
37622 : const bool synthesis_result =
37623 : synthesize_sf3ext_expression::
37624 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
37625 :
37626 : exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
37627 :
37628 140 : return (synthesis_result) ? result : error_node();
37629 : }
37630 : // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
37631 6211 : else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
37632 : {
37633 : const bool synthesis_result =
37634 : synthesize_sf3ext_expression::
37635 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
37636 :
37637 : exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
37638 :
37639 140 : return (synthesis_result) ? result : error_node();
37640 : }
37641 : // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
37642 6071 : else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
37643 : {
37644 : const bool synthesis_result =
37645 : synthesize_sf3ext_expression::
37646 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
37647 :
37648 : exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
37649 :
37650 140 : return (synthesis_result) ? result : error_node();
37651 : }
37652 : // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
37653 5931 : else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
37654 : {
37655 : const bool synthesis_result =
37656 : synthesize_sf3ext_expression::
37657 640 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
37658 :
37659 : exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
37660 :
37661 320 : return (synthesis_result) ? result : error_node();
37662 : }
37663 : // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
37664 5611 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
37665 : {
37666 : const bool synthesis_result =
37667 : synthesize_sf3ext_expression::
37668 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
37669 :
37670 : exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
37671 :
37672 140 : return (synthesis_result) ? result : error_node();
37673 : }
37674 : // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
37675 5471 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37676 : {
37677 : const bool synthesis_result =
37678 : synthesize_sf3ext_expression::
37679 280 : template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
37680 :
37681 : exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
37682 :
37683 140 : return (synthesis_result) ? result : error_node();
37684 : }
37685 : // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
37686 5331 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37687 : {
37688 : const bool synthesis_result =
37689 : synthesize_sf3ext_expression::
37690 170 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
37691 :
37692 : exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
37693 :
37694 85 : return (synthesis_result) ? result : error_node();
37695 : }
37696 : // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
37697 5246 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
37698 : {
37699 : const bool synthesis_result =
37700 : synthesize_sf3ext_expression::
37701 300 : template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
37702 :
37703 : exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
37704 :
37705 150 : return (synthesis_result) ? result : error_node();
37706 : }
37707 : // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
37708 5096 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
37709 : {
37710 : const bool synthesis_result =
37711 : synthesize_sf3ext_expression::
37712 310 : template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
37713 :
37714 : exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
37715 :
37716 155 : return (synthesis_result) ? result : error_node();
37717 : }
37718 : // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
37719 4941 : else if (
37720 4941 : (std::equal_to<T>()(c0,c1)) &&
37721 800 : (details::e_mul == o0) &&
37722 6541 : (details::e_mul == o2) &&
37723 : (
37724 800 : (details::e_add == o1) ||
37725 460 : (details::e_sub == o1)
37726 : )
37727 : )
37728 : {
37729 440 : std::string specfunc;
37730 :
37731 440 : switch (o1)
37732 : {
37733 340 : case details::e_add : specfunc = "t*(t+t)"; break;
37734 100 : case details::e_sub : specfunc = "t*(t-t)"; break;
37735 0 : default : return error_node();
37736 : }
37737 :
37738 : const bool synthesis_result =
37739 : synthesize_sf3ext_expression::
37740 440 : template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
37741 :
37742 : exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
37743 :
37744 440 : return (synthesis_result) ? result : error_node();
37745 440 : }
37746 : }
37747 :
37748 : const bool synthesis_result =
37749 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37750 4501 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
37751 :
37752 4501 : if (synthesis_result)
37753 4011 : return result;
37754 :
37755 490 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
37756 490 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
37757 490 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
37758 :
37759 490 : if (!expr_gen.valid_operator(o0,f0))
37760 0 : return error_node();
37761 490 : else if (!expr_gen.valid_operator(o1,f1))
37762 0 : return error_node();
37763 490 : else if (!expr_gen.valid_operator(o2,f2))
37764 0 : return error_node();
37765 : else
37766 490 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
37767 : }
37768 :
37769 4501 : static inline std::string id(expression_generator<Type>& expr_gen,
37770 : const details::operator_type o0,
37771 : const details::operator_type o1,
37772 : const details::operator_type o2)
37773 : {
37774 9002 : return details::build_string()
37775 9002 : << "(t" << expr_gen.to_str(o0)
37776 9002 : << "t)" << expr_gen.to_str(o1)
37777 9002 : << "(t" << expr_gen.to_str(o2)
37778 9002 : << "t)";
37779 : }
37780 : };
37781 :
37782 : struct synthesize_vocovoc_expression0
37783 : {
37784 : typedef typename vocovoc_t::type0 node_type;
37785 : typedef typename vocovoc_t::sf4_type sf4_type;
37786 : typedef typename node_type::T0 T0;
37787 : typedef typename node_type::T1 T1;
37788 : typedef typename node_type::T2 T2;
37789 : typedef typename node_type::T3 T3;
37790 :
37791 7443 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
37792 : const details::operator_type& operation,
37793 : expression_node_ptr (&branch)[2])
37794 : {
37795 : // (v0 o0 c0) o1 (v1 o2 c1)
37796 7443 : const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
37797 7443 : const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
37798 7443 : const Type c0 = voc0->c();
37799 7443 : const Type& v0 = voc0->v();
37800 7443 : const Type c1 = voc1->c();
37801 7443 : const Type& v1 = voc1->v();
37802 7443 : const details::operator_type o0 = voc0->operation();
37803 7443 : const details::operator_type o1 = operation;
37804 7443 : const details::operator_type o2 = voc1->operation();
37805 :
37806 7443 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
37807 7443 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
37808 :
37809 7443 : expression_node_ptr result = error_node();
37810 :
37811 7443 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
37812 : {
37813 : // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
37814 7443 : if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
37815 : {
37816 : const bool synthesis_result =
37817 : synthesize_sf3ext_expression::
37818 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
37819 :
37820 : exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
37821 :
37822 140 : return (synthesis_result) ? result : error_node();
37823 : }
37824 : // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
37825 7303 : else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
37826 : {
37827 : const bool synthesis_result =
37828 : synthesize_sf3ext_expression::
37829 300 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
37830 :
37831 : exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
37832 :
37833 150 : return (synthesis_result) ? result : error_node();
37834 : }
37835 : // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
37836 7153 : else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
37837 : {
37838 : const bool synthesis_result =
37839 : synthesize_sf3ext_expression::
37840 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
37841 :
37842 : exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
37843 :
37844 140 : return (synthesis_result) ? result : error_node();
37845 : }
37846 : // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
37847 7013 : else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
37848 : {
37849 : const bool synthesis_result =
37850 : synthesize_sf3ext_expression::
37851 170 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
37852 :
37853 : exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
37854 :
37855 85 : return (synthesis_result) ? result : error_node();
37856 : }
37857 : // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
37858 6928 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
37859 : {
37860 : const bool synthesis_result =
37861 : synthesize_sf3ext_expression::
37862 300 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
37863 :
37864 : exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
37865 :
37866 150 : return (synthesis_result) ? result : error_node();
37867 : }
37868 : // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
37869 6778 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
37870 : {
37871 : const bool synthesis_result =
37872 : synthesize_sf3ext_expression::
37873 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
37874 :
37875 : exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
37876 :
37877 140 : return (synthesis_result) ? result : error_node();
37878 : }
37879 : // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
37880 6638 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
37881 : {
37882 : const bool synthesis_result =
37883 : synthesize_sf3ext_expression::
37884 160 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
37885 :
37886 : exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
37887 :
37888 80 : return (synthesis_result) ? result : error_node();
37889 : }
37890 : // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
37891 6558 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
37892 : {
37893 : const bool synthesis_result =
37894 : synthesize_sf3ext_expression::
37895 320 : template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
37896 :
37897 : exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
37898 :
37899 160 : return (synthesis_result) ? result : error_node();
37900 : }
37901 : // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
37902 6398 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
37903 : {
37904 : const bool synthesis_result =
37905 : synthesize_sf3ext_expression::
37906 290 : template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
37907 :
37908 : exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
37909 :
37910 145 : return (synthesis_result) ? result : error_node();
37911 : }
37912 : // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
37913 6253 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
37914 : {
37915 : const bool synthesis_result =
37916 : synthesize_sf4ext_expression::
37917 170 : template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
37918 :
37919 : exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
37920 :
37921 85 : return (synthesis_result) ? result : error_node();
37922 : }
37923 : // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
37924 6168 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
37925 : {
37926 : const bool synthesis_result =
37927 : synthesize_sf4ext_expression::
37928 170 : template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
37929 :
37930 : exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
37931 :
37932 85 : return (synthesis_result) ? result : error_node();
37933 : }
37934 : // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
37935 6083 : else if (
37936 6083 : (std::equal_to<T>()(c0,c1)) &&
37937 710 : (details::e_mul == o0) &&
37938 7293 : (details::e_mul == o2) &&
37939 : (
37940 500 : (details::e_add == o1) ||
37941 460 : (details::e_sub == o1)
37942 : )
37943 : )
37944 : {
37945 140 : std::string specfunc;
37946 :
37947 140 : switch (o1)
37948 : {
37949 40 : case details::e_add : specfunc = "t*(t+t)"; break;
37950 100 : case details::e_sub : specfunc = "t*(t-t)"; break;
37951 0 : default : return error_node();
37952 : }
37953 :
37954 : const bool synthesis_result =
37955 : synthesize_sf3ext_expression::
37956 140 : template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
37957 :
37958 : exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
37959 :
37960 140 : return (synthesis_result) ? result : error_node();
37961 140 : }
37962 : // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
37963 5943 : else if (
37964 5943 : (std::equal_to<T>()(c0,c1)) &&
37965 570 : (details::e_div == o0) &&
37966 6593 : (details::e_div == o2) &&
37967 : (
37968 80 : (details::e_add == o1) ||
37969 40 : (details::e_sub == o1)
37970 : )
37971 : )
37972 : {
37973 80 : std::string specfunc;
37974 :
37975 80 : switch (o1)
37976 : {
37977 40 : case details::e_add : specfunc = "(t+t)/t"; break;
37978 40 : case details::e_sub : specfunc = "(t-t)/t"; break;
37979 0 : default : return error_node();
37980 : }
37981 :
37982 : const bool synthesis_result =
37983 : synthesize_sf3ext_expression::
37984 80 : template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result);
37985 :
37986 : exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
37987 :
37988 80 : return (synthesis_result) ? result : error_node();
37989 80 : }
37990 : }
37991 :
37992 : const bool synthesis_result =
37993 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
37994 5863 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
37995 :
37996 5863 : if (synthesis_result)
37997 3250 : return result;
37998 :
37999 2613 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38000 2613 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
38001 2613 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
38002 :
38003 2613 : if (!expr_gen.valid_operator(o0,f0))
38004 0 : return error_node();
38005 2613 : else if (!expr_gen.valid_operator(o1,f1))
38006 0 : return error_node();
38007 2613 : else if (!expr_gen.valid_operator(o2,f2))
38008 0 : return error_node();
38009 : else
38010 2613 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
38011 : }
38012 :
38013 5863 : static inline std::string id(expression_generator<Type>& expr_gen,
38014 : const details::operator_type o0,
38015 : const details::operator_type o1,
38016 : const details::operator_type o2)
38017 : {
38018 11726 : return details::build_string()
38019 11726 : << "(t" << expr_gen.to_str(o0)
38020 11726 : << "t)" << expr_gen.to_str(o1)
38021 11726 : << "(t" << expr_gen.to_str(o2)
38022 11726 : << "t)";
38023 : }
38024 : };
38025 :
38026 : struct synthesize_covovoc_expression0
38027 : {
38028 : typedef typename covovoc_t::type0 node_type;
38029 : typedef typename covovoc_t::sf4_type sf4_type;
38030 : typedef typename node_type::T0 T0;
38031 : typedef typename node_type::T1 T1;
38032 : typedef typename node_type::T2 T2;
38033 : typedef typename node_type::T3 T3;
38034 :
38035 5100 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38036 : const details::operator_type& operation,
38037 : expression_node_ptr (&branch)[2])
38038 : {
38039 : // (c0 o0 v0) o1 (v1 o2 c1)
38040 5100 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
38041 5100 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
38042 5100 : const Type c0 = cov->c();
38043 5100 : const Type& v0 = cov->v();
38044 5100 : const Type c1 = voc->c();
38045 5100 : const Type& v1 = voc->v();
38046 5100 : const details::operator_type o0 = cov->operation();
38047 5100 : const details::operator_type o1 = operation;
38048 5100 : const details::operator_type o2 = voc->operation();
38049 :
38050 5100 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
38051 5100 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38052 :
38053 5100 : expression_node_ptr result = error_node();
38054 :
38055 5100 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
38056 : {
38057 : // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
38058 5100 : if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
38059 : {
38060 : const bool synthesis_result =
38061 : synthesize_sf3ext_expression::
38062 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
38063 :
38064 : exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
38065 :
38066 140 : return (synthesis_result) ? result : error_node();
38067 : }
38068 : // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
38069 4960 : else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
38070 : {
38071 : const bool synthesis_result =
38072 : synthesize_sf3ext_expression::
38073 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
38074 :
38075 : exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
38076 :
38077 140 : return (synthesis_result) ? result : error_node();
38078 : }
38079 : // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
38080 4820 : else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
38081 : {
38082 : const bool synthesis_result =
38083 : synthesize_sf3ext_expression::
38084 280 : template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
38085 :
38086 : exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
38087 :
38088 140 : return (synthesis_result) ? result : error_node();
38089 : }
38090 : // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
38091 4680 : else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
38092 : {
38093 : const bool synthesis_result =
38094 : synthesize_sf3ext_expression::
38095 160 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
38096 :
38097 : exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
38098 :
38099 80 : return (synthesis_result) ? result : error_node();
38100 : }
38101 : // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
38102 4600 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
38103 : {
38104 : const bool synthesis_result =
38105 : synthesize_sf3ext_expression::
38106 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
38107 :
38108 : exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
38109 :
38110 140 : return (synthesis_result) ? result : error_node();
38111 : }
38112 : // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
38113 4460 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
38114 : {
38115 : const bool synthesis_result =
38116 : synthesize_sf3ext_expression::
38117 280 : template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
38118 :
38119 : exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
38120 :
38121 140 : return (synthesis_result) ? result : error_node();
38122 : }
38123 : // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
38124 4320 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
38125 : {
38126 : const bool synthesis_result =
38127 : synthesize_sf3ext_expression::
38128 160 : template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
38129 :
38130 : exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
38131 :
38132 80 : return (synthesis_result) ? result : error_node();
38133 : }
38134 : // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
38135 4240 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
38136 : {
38137 : const bool synthesis_result =
38138 : synthesize_sf3ext_expression::
38139 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
38140 :
38141 : exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
38142 :
38143 140 : return (synthesis_result) ? result : error_node();
38144 : }
38145 : // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
38146 4100 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
38147 : {
38148 : const bool synthesis_result =
38149 : synthesize_sf3ext_expression::
38150 280 : template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
38151 :
38152 : exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
38153 :
38154 140 : return (synthesis_result) ? result : error_node();
38155 : }
38156 : // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
38157 3960 : else if (
38158 3960 : (std::equal_to<T>()(c0,c1)) &&
38159 320 : (details::e_mul == o0) &&
38160 4465 : (details::e_mul == o2) &&
38161 : (
38162 185 : (details::e_add == o1) ||
38163 55 : (details::e_sub == o1)
38164 : )
38165 : )
38166 : {
38167 185 : std::string specfunc;
38168 :
38169 185 : switch (o1)
38170 : {
38171 130 : case details::e_add : specfunc = "t*(t+t)"; break;
38172 55 : case details::e_sub : specfunc = "t*(t-t)"; break;
38173 0 : default : return error_node();
38174 : }
38175 :
38176 : const bool synthesis_result =
38177 : synthesize_sf3ext_expression::
38178 185 : template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
38179 :
38180 : exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
38181 :
38182 185 : return (synthesis_result) ? result : error_node();
38183 185 : }
38184 : }
38185 :
38186 : const bool synthesis_result =
38187 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38188 3775 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
38189 :
38190 3775 : if (synthesis_result)
38191 3645 : return result;
38192 :
38193 130 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38194 130 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
38195 130 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
38196 :
38197 130 : if (!expr_gen.valid_operator(o0,f0))
38198 0 : return error_node();
38199 130 : else if (!expr_gen.valid_operator(o1,f1))
38200 0 : return error_node();
38201 130 : else if (!expr_gen.valid_operator(o2,f2))
38202 0 : return error_node();
38203 : else
38204 130 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
38205 : }
38206 :
38207 3775 : static inline std::string id(expression_generator<Type>& expr_gen,
38208 : const details::operator_type o0,
38209 : const details::operator_type o1,
38210 : const details::operator_type o2)
38211 : {
38212 7550 : return details::build_string()
38213 7550 : << "(t" << expr_gen.to_str(o0)
38214 7550 : << "t)" << expr_gen.to_str(o1)
38215 7550 : << "(t" << expr_gen.to_str(o2)
38216 7550 : << "t)";
38217 : }
38218 : };
38219 :
38220 : struct synthesize_vococov_expression0
38221 : {
38222 : typedef typename vococov_t::type0 node_type;
38223 : typedef typename vococov_t::sf4_type sf4_type;
38224 : typedef typename node_type::T0 T0;
38225 : typedef typename node_type::T1 T1;
38226 : typedef typename node_type::T2 T2;
38227 : typedef typename node_type::T3 T3;
38228 :
38229 4750 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38230 : const details::operator_type& operation,
38231 : expression_node_ptr (&branch)[2])
38232 : {
38233 : // (v0 o0 c0) o1 (c1 o2 v1)
38234 4750 : const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
38235 4750 : const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
38236 4750 : const Type c0 = voc->c();
38237 4750 : const Type& v0 = voc->v();
38238 4750 : const Type c1 = cov->c();
38239 4750 : const Type& v1 = cov->v();
38240 4750 : const details::operator_type o0 = voc->operation();
38241 4750 : const details::operator_type o1 = operation;
38242 4750 : const details::operator_type o2 = cov->operation();
38243 :
38244 4750 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
38245 4750 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38246 :
38247 4750 : expression_node_ptr result = error_node();
38248 :
38249 4750 : if (expr_gen.parser_->settings_.strength_reduction_enabled())
38250 : {
38251 : // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
38252 4750 : if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
38253 : {
38254 : const bool synthesis_result =
38255 : synthesize_sf3ext_expression::
38256 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
38257 :
38258 : exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
38259 :
38260 140 : return (synthesis_result) ? result : error_node();
38261 : }
38262 : // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
38263 4610 : else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
38264 : {
38265 : const bool synthesis_result =
38266 : synthesize_sf3ext_expression::
38267 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
38268 :
38269 : exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
38270 :
38271 140 : return (synthesis_result) ? result : error_node();
38272 : }
38273 : // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
38274 4470 : else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
38275 : {
38276 : const bool synthesis_result =
38277 : synthesize_sf3ext_expression::
38278 280 : template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
38279 :
38280 : exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
38281 :
38282 140 : return (synthesis_result) ? result : error_node();
38283 : }
38284 : // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
38285 4330 : else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
38286 : {
38287 : const bool synthesis_result =
38288 : synthesize_sf3ext_expression::
38289 160 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
38290 :
38291 : exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
38292 :
38293 80 : return (synthesis_result) ? result : error_node();
38294 : }
38295 : // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
38296 4250 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
38297 : {
38298 : const bool synthesis_result =
38299 : synthesize_sf3ext_expression::
38300 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
38301 :
38302 : exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
38303 :
38304 140 : return (synthesis_result) ? result : error_node();
38305 : }
38306 : // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
38307 4110 : else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
38308 : {
38309 : const bool synthesis_result =
38310 : synthesize_sf3ext_expression::
38311 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
38312 :
38313 : exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
38314 :
38315 140 : return (synthesis_result) ? result : error_node();
38316 : }
38317 : // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
38318 3970 : else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
38319 : {
38320 : const bool synthesis_result =
38321 : synthesize_sf3ext_expression::
38322 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
38323 :
38324 : exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
38325 :
38326 140 : return (synthesis_result) ? result : error_node();
38327 : }
38328 : // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
38329 3830 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
38330 : {
38331 : const bool synthesis_result =
38332 : synthesize_sf3ext_expression::
38333 280 : template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
38334 :
38335 : exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
38336 :
38337 140 : return (synthesis_result) ? result : error_node();
38338 : }
38339 : // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
38340 3690 : else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
38341 : {
38342 : const bool synthesis_result =
38343 : synthesize_sf3ext_expression::
38344 160 : template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
38345 :
38346 : exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
38347 :
38348 80 : return (synthesis_result) ? result : error_node();
38349 : }
38350 : // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
38351 3610 : else if (
38352 3610 : (std::equal_to<T>()(c0,c1)) &&
38353 200 : (details::e_mul == o0) &&
38354 3890 : (details::e_mul == o2) &&
38355 : (
38356 80 : (details::e_add == o1) || (details::e_sub == o1)
38357 : )
38358 : )
38359 : {
38360 80 : std::string specfunc;
38361 :
38362 80 : switch (o1)
38363 : {
38364 40 : case details::e_add : specfunc = "t*(t+t)"; break;
38365 40 : case details::e_sub : specfunc = "t*(t-t)"; break;
38366 0 : default : return error_node();
38367 : }
38368 :
38369 : const bool synthesis_result =
38370 : synthesize_sf3ext_expression::
38371 80 : template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
38372 :
38373 : exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
38374 :
38375 80 : return (synthesis_result) ? result : error_node();
38376 80 : }
38377 : }
38378 :
38379 : const bool synthesis_result =
38380 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38381 3530 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
38382 :
38383 3530 : if (synthesis_result)
38384 3285 : return result;
38385 :
38386 245 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38387 245 : binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
38388 245 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
38389 :
38390 245 : if (!expr_gen.valid_operator(o0,f0))
38391 0 : return error_node();
38392 245 : else if (!expr_gen.valid_operator(o1,f1))
38393 0 : return error_node();
38394 245 : else if (!expr_gen.valid_operator(o2,f2))
38395 0 : return error_node();
38396 : else
38397 245 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
38398 : }
38399 :
38400 3530 : static inline std::string id(expression_generator<Type>& expr_gen,
38401 : const details::operator_type o0,
38402 : const details::operator_type o1,
38403 : const details::operator_type o2)
38404 : {
38405 7060 : return details::build_string()
38406 7060 : << "(t" << expr_gen.to_str(o0)
38407 7060 : << "t)" << expr_gen.to_str(o1)
38408 7060 : << "(t" << expr_gen.to_str(o2)
38409 7060 : << "t)";
38410 : }
38411 : };
38412 :
38413 : struct synthesize_vovovov_expression1
38414 : {
38415 : typedef typename vovovov_t::type1 node_type;
38416 : typedef typename vovovov_t::sf4_type sf4_type;
38417 : typedef typename node_type::T0 T0;
38418 : typedef typename node_type::T1 T1;
38419 : typedef typename node_type::T2 T2;
38420 : typedef typename node_type::T3 T3;
38421 :
38422 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38423 : const details::operator_type& operation,
38424 : expression_node_ptr (&branch)[2])
38425 : {
38426 : // v0 o0 (v1 o1 (v2 o2 v3))
38427 : typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
38428 :
38429 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
38430 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38431 0 : const Type& v1 = vovov->t0();
38432 0 : const Type& v2 = vovov->t1();
38433 0 : const Type& v3 = vovov->t2();
38434 0 : const details::operator_type o0 = operation;
38435 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
38436 0 : const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
38437 :
38438 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38439 0 : binary_functor_t f1 = vovov->f0();
38440 0 : binary_functor_t f2 = vovov->f1();
38441 :
38442 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38443 :
38444 0 : expression_node_ptr result = error_node();
38445 :
38446 : const bool synthesis_result =
38447 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38448 0 : (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
38449 :
38450 0 : if (synthesis_result)
38451 0 : return result;
38452 0 : else if (!expr_gen.valid_operator(o0,f0))
38453 0 : return error_node();
38454 :
38455 : exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
38456 :
38457 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
38458 : }
38459 :
38460 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38461 : const details::operator_type o0,
38462 : const details::operator_type o1,
38463 : const details::operator_type o2)
38464 : {
38465 0 : return details::build_string()
38466 0 : << "t" << expr_gen.to_str(o0)
38467 0 : << "(t" << expr_gen.to_str(o1)
38468 0 : << "(t" << expr_gen.to_str(o2)
38469 0 : << "t))";
38470 : }
38471 : };
38472 :
38473 : struct synthesize_vovovoc_expression1
38474 : {
38475 : typedef typename vovovoc_t::type1 node_type;
38476 : typedef typename vovovoc_t::sf4_type sf4_type;
38477 : typedef typename node_type::T0 T0;
38478 : typedef typename node_type::T1 T1;
38479 : typedef typename node_type::T2 T2;
38480 : typedef typename node_type::T3 T3;
38481 :
38482 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38483 : const details::operator_type& operation,
38484 : expression_node_ptr (&branch)[2])
38485 : {
38486 : // v0 o0 (v1 o1 (v2 o2 c))
38487 : typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
38488 :
38489 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
38490 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38491 0 : const Type& v1 = vovoc->t0();
38492 0 : const Type& v2 = vovoc->t1();
38493 0 : const Type c = vovoc->t2();
38494 0 : const details::operator_type o0 = operation;
38495 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
38496 0 : const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
38497 :
38498 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38499 0 : binary_functor_t f1 = vovoc->f0();
38500 0 : binary_functor_t f2 = vovoc->f1();
38501 :
38502 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38503 :
38504 0 : expression_node_ptr result = error_node();
38505 :
38506 : const bool synthesis_result =
38507 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38508 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
38509 :
38510 0 : if (synthesis_result)
38511 0 : return result;
38512 0 : else if (!expr_gen.valid_operator(o0,f0))
38513 0 : return error_node();
38514 :
38515 : exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
38516 :
38517 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
38518 : }
38519 :
38520 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38521 : const details::operator_type o0,
38522 : const details::operator_type o1,
38523 : const details::operator_type o2)
38524 : {
38525 0 : return details::build_string()
38526 0 : << "t" << expr_gen.to_str(o0)
38527 0 : << "(t" << expr_gen.to_str(o1)
38528 0 : << "(t" << expr_gen.to_str(o2)
38529 0 : << "t))";
38530 : }
38531 : };
38532 :
38533 : struct synthesize_vovocov_expression1
38534 : {
38535 : typedef typename vovocov_t::type1 node_type;
38536 : typedef typename vovocov_t::sf4_type sf4_type;
38537 : typedef typename node_type::T0 T0;
38538 : typedef typename node_type::T1 T1;
38539 : typedef typename node_type::T2 T2;
38540 : typedef typename node_type::T3 T3;
38541 :
38542 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38543 : const details::operator_type& operation,
38544 : expression_node_ptr (&branch)[2])
38545 : {
38546 : // v0 o0 (v1 o1 (c o2 v2))
38547 : typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
38548 :
38549 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
38550 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38551 0 : const Type& v1 = vocov->t0();
38552 0 : const Type c = vocov->t1();
38553 0 : const Type& v2 = vocov->t2();
38554 0 : const details::operator_type o0 = operation;
38555 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
38556 0 : const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
38557 :
38558 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38559 0 : binary_functor_t f1 = vocov->f0();
38560 0 : binary_functor_t f2 = vocov->f1();
38561 :
38562 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38563 :
38564 0 : expression_node_ptr result = error_node();
38565 :
38566 : const bool synthesis_result =
38567 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38568 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
38569 :
38570 0 : if (synthesis_result)
38571 0 : return result;
38572 0 : if (!expr_gen.valid_operator(o0,f0))
38573 0 : return error_node();
38574 :
38575 : exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
38576 :
38577 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
38578 : }
38579 :
38580 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38581 : const details::operator_type o0,
38582 : const details::operator_type o1,
38583 : const details::operator_type o2)
38584 : {
38585 0 : return details::build_string()
38586 0 : << "t" << expr_gen.to_str(o0)
38587 0 : << "(t" << expr_gen.to_str(o1)
38588 0 : << "(t" << expr_gen.to_str(o2)
38589 0 : << "t))";
38590 : }
38591 : };
38592 :
38593 : struct synthesize_vocovov_expression1
38594 : {
38595 : typedef typename vocovov_t::type1 node_type;
38596 : typedef typename vocovov_t::sf4_type sf4_type;
38597 : typedef typename node_type::T0 T0;
38598 : typedef typename node_type::T1 T1;
38599 : typedef typename node_type::T2 T2;
38600 : typedef typename node_type::T3 T3;
38601 :
38602 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38603 : const details::operator_type& operation,
38604 : expression_node_ptr (&branch)[2])
38605 : {
38606 : // v0 o0 (c o1 (v1 o2 v2))
38607 : typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
38608 :
38609 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
38610 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38611 0 : const Type c = covov->t0();
38612 0 : const Type& v1 = covov->t1();
38613 0 : const Type& v2 = covov->t2();
38614 0 : const details::operator_type o0 = operation;
38615 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f0());
38616 0 : const details::operator_type o2 = expr_gen.get_operator(covov->f1());
38617 :
38618 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38619 0 : binary_functor_t f1 = covov->f0();
38620 0 : binary_functor_t f2 = covov->f1();
38621 :
38622 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38623 :
38624 0 : expression_node_ptr result = error_node();
38625 :
38626 : const bool synthesis_result =
38627 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38628 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
38629 :
38630 0 : if (synthesis_result)
38631 0 : return result;
38632 0 : else if (!expr_gen.valid_operator(o0,f0))
38633 0 : return error_node();
38634 :
38635 : exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
38636 :
38637 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
38638 : }
38639 :
38640 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38641 : const details::operator_type o0,
38642 : const details::operator_type o1,
38643 : const details::operator_type o2)
38644 : {
38645 0 : return details::build_string()
38646 0 : << "t" << expr_gen.to_str(o0)
38647 0 : << "(t" << expr_gen.to_str(o1)
38648 0 : << "(t" << expr_gen.to_str(o2)
38649 0 : << "t))";
38650 : }
38651 : };
38652 :
38653 : struct synthesize_covovov_expression1
38654 : {
38655 : typedef typename covovov_t::type1 node_type;
38656 : typedef typename covovov_t::sf4_type sf4_type;
38657 : typedef typename node_type::T0 T0;
38658 : typedef typename node_type::T1 T1;
38659 : typedef typename node_type::T2 T2;
38660 : typedef typename node_type::T3 T3;
38661 :
38662 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38663 : const details::operator_type& operation,
38664 : expression_node_ptr (&branch)[2])
38665 : {
38666 : // c o0 (v0 o1 (v1 o2 v2))
38667 : typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
38668 :
38669 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
38670 0 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
38671 0 : const Type& v0 = vovov->t0();
38672 0 : const Type& v1 = vovov->t1();
38673 0 : const Type& v2 = vovov->t2();
38674 0 : const details::operator_type o0 = operation;
38675 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
38676 0 : const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
38677 :
38678 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38679 0 : binary_functor_t f1 = vovov->f0();
38680 0 : binary_functor_t f2 = vovov->f1();
38681 :
38682 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
38683 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38684 :
38685 0 : expression_node_ptr result = error_node();
38686 :
38687 : const bool synthesis_result =
38688 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38689 0 : (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
38690 :
38691 0 : if (synthesis_result)
38692 0 : return result;
38693 0 : if (!expr_gen.valid_operator(o0,f0))
38694 0 : return error_node();
38695 :
38696 : exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
38697 :
38698 0 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
38699 : }
38700 :
38701 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38702 : const details::operator_type o0,
38703 : const details::operator_type o1,
38704 : const details::operator_type o2)
38705 : {
38706 0 : return details::build_string()
38707 0 : << "t" << expr_gen.to_str(o0)
38708 0 : << "(t" << expr_gen.to_str(o1)
38709 0 : << "(t" << expr_gen.to_str(o2)
38710 0 : << "t))";
38711 : }
38712 : };
38713 :
38714 : struct synthesize_covocov_expression1
38715 : {
38716 : typedef typename covocov_t::type1 node_type;
38717 : typedef typename covocov_t::sf4_type sf4_type;
38718 : typedef typename node_type::T0 T0;
38719 : typedef typename node_type::T1 T1;
38720 : typedef typename node_type::T2 T2;
38721 : typedef typename node_type::T3 T3;
38722 :
38723 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38724 : const details::operator_type& operation,
38725 : expression_node_ptr (&branch)[2])
38726 : {
38727 : // c0 o0 (v0 o1 (c1 o2 v1))
38728 : typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
38729 :
38730 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
38731 0 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
38732 0 : const Type& v0 = vocov->t0();
38733 0 : const Type c1 = vocov->t1();
38734 0 : const Type& v1 = vocov->t2();
38735 0 : const details::operator_type o0 = operation;
38736 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
38737 0 : const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
38738 :
38739 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38740 0 : binary_functor_t f1 = vocov->f0();
38741 0 : binary_functor_t f2 = vocov->f1();
38742 :
38743 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
38744 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38745 :
38746 0 : expression_node_ptr result = error_node();
38747 :
38748 : const bool synthesis_result =
38749 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38750 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
38751 :
38752 0 : if (synthesis_result)
38753 0 : return result;
38754 0 : else if (!expr_gen.valid_operator(o0,f0))
38755 0 : return error_node();
38756 :
38757 : exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
38758 :
38759 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
38760 : }
38761 :
38762 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38763 : const details::operator_type o0,
38764 : const details::operator_type o1,
38765 : const details::operator_type o2)
38766 : {
38767 0 : return details::build_string()
38768 0 : << "t" << expr_gen.to_str(o0)
38769 0 : << "(t" << expr_gen.to_str(o1)
38770 0 : << "(t" << expr_gen.to_str(o2)
38771 0 : << "t))";
38772 : }
38773 : };
38774 :
38775 : struct synthesize_vocovoc_expression1
38776 : {
38777 : typedef typename vocovoc_t::type1 node_type;
38778 : typedef typename vocovoc_t::sf4_type sf4_type;
38779 : typedef typename node_type::T0 T0;
38780 : typedef typename node_type::T1 T1;
38781 : typedef typename node_type::T2 T2;
38782 : typedef typename node_type::T3 T3;
38783 :
38784 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38785 : const details::operator_type& operation,
38786 : expression_node_ptr (&branch)[2])
38787 : {
38788 : // v0 o0 (c0 o1 (v1 o2 c2))
38789 : typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
38790 :
38791 0 : const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
38792 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38793 0 : const Type c0 = covoc->t0();
38794 0 : const Type& v1 = covoc->t1();
38795 0 : const Type c1 = covoc->t2();
38796 0 : const details::operator_type o0 = operation;
38797 0 : const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
38798 0 : const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
38799 :
38800 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38801 0 : binary_functor_t f1 = covoc->f0();
38802 0 : binary_functor_t f2 = covoc->f1();
38803 :
38804 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38805 :
38806 0 : expression_node_ptr result = error_node();
38807 :
38808 : const bool synthesis_result =
38809 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38810 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
38811 :
38812 0 : if (synthesis_result)
38813 0 : return result;
38814 0 : else if (!expr_gen.valid_operator(o0,f0))
38815 0 : return error_node();
38816 :
38817 : exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
38818 :
38819 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
38820 : }
38821 :
38822 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38823 : const details::operator_type o0,
38824 : const details::operator_type o1,
38825 : const details::operator_type o2)
38826 : {
38827 0 : return details::build_string()
38828 0 : << "t" << expr_gen.to_str(o0)
38829 0 : << "(t" << expr_gen.to_str(o1)
38830 0 : << "(t" << expr_gen.to_str(o2)
38831 0 : << "t))";
38832 : }
38833 : };
38834 :
38835 : struct synthesize_covovoc_expression1
38836 : {
38837 : typedef typename covovoc_t::type1 node_type;
38838 : typedef typename covovoc_t::sf4_type sf4_type;
38839 : typedef typename node_type::T0 T0;
38840 : typedef typename node_type::T1 T1;
38841 : typedef typename node_type::T2 T2;
38842 : typedef typename node_type::T3 T3;
38843 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38844 : const details::operator_type& operation,
38845 : expression_node_ptr (&branch)[2])
38846 : {
38847 : // c0 o0 (v0 o1 (v1 o2 c1))
38848 : typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
38849 :
38850 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
38851 0 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
38852 0 : const Type& v0 = vovoc->t0();
38853 0 : const Type& v1 = vovoc->t1();
38854 0 : const Type c1 = vovoc->t2();
38855 0 : const details::operator_type o0 = operation;
38856 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
38857 0 : const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
38858 :
38859 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38860 0 : binary_functor_t f1 = vovoc->f0();
38861 0 : binary_functor_t f2 = vovoc->f1();
38862 :
38863 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
38864 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38865 :
38866 0 : expression_node_ptr result = error_node();
38867 :
38868 : const bool synthesis_result =
38869 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38870 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
38871 :
38872 0 : if (synthesis_result)
38873 0 : return result;
38874 0 : else if (!expr_gen.valid_operator(o0,f0))
38875 0 : return error_node();
38876 :
38877 : exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
38878 :
38879 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
38880 : }
38881 :
38882 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38883 : const details::operator_type o0,
38884 : const details::operator_type o1,
38885 : const details::operator_type o2)
38886 : {
38887 0 : return details::build_string()
38888 0 : << "t" << expr_gen.to_str(o0)
38889 0 : << "(t" << expr_gen.to_str(o1)
38890 0 : << "(t" << expr_gen.to_str(o2)
38891 0 : << "t))";
38892 : }
38893 : };
38894 :
38895 : struct synthesize_vococov_expression1
38896 : {
38897 : typedef typename vococov_t::type1 node_type;
38898 : typedef typename vococov_t::sf4_type sf4_type;
38899 : typedef typename node_type::T0 T0;
38900 : typedef typename node_type::T1 T1;
38901 : typedef typename node_type::T2 T2;
38902 : typedef typename node_type::T3 T3;
38903 :
38904 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38905 : const details::operator_type& operation,
38906 : expression_node_ptr (&branch)[2])
38907 : {
38908 : // v0 o0 (c0 o1 (c1 o2 v1))
38909 : typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
38910 :
38911 0 : const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
38912 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38913 0 : const Type c0 = cocov->t0();
38914 0 : const Type c1 = cocov->t1();
38915 0 : const Type& v1 = cocov->t2();
38916 0 : const details::operator_type o0 = operation;
38917 0 : const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
38918 0 : const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
38919 :
38920 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38921 0 : binary_functor_t f1 = cocov->f0();
38922 0 : binary_functor_t f2 = cocov->f1();
38923 :
38924 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38925 :
38926 0 : expression_node_ptr result = error_node();
38927 :
38928 : const bool synthesis_result =
38929 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38930 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
38931 :
38932 0 : if (synthesis_result)
38933 0 : return result;
38934 0 : else if (!expr_gen.valid_operator(o0,f0))
38935 0 : return error_node();
38936 :
38937 : exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
38938 :
38939 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
38940 : }
38941 :
38942 0 : static inline std::string id(expression_generator<Type>& expr_gen,
38943 : const details::operator_type o0,
38944 : const details::operator_type o1,
38945 : const details::operator_type o2)
38946 : {
38947 0 : return details::build_string()
38948 0 : << "t" << expr_gen.to_str(o0)
38949 0 : << "(t" << expr_gen.to_str(o1)
38950 0 : << "(t" << expr_gen.to_str(o2)
38951 0 : << "t))";
38952 : }
38953 : };
38954 :
38955 : struct synthesize_vovovov_expression2
38956 : {
38957 : typedef typename vovovov_t::type2 node_type;
38958 : typedef typename vovovov_t::sf4_type sf4_type;
38959 : typedef typename node_type::T0 T0;
38960 : typedef typename node_type::T1 T1;
38961 : typedef typename node_type::T2 T2;
38962 : typedef typename node_type::T3 T3;
38963 :
38964 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
38965 : const details::operator_type& operation,
38966 : expression_node_ptr (&branch)[2])
38967 : {
38968 : // v0 o0 ((v1 o1 v2) o2 v3)
38969 : typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
38970 :
38971 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
38972 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
38973 0 : const Type& v1 = vovov->t0();
38974 0 : const Type& v2 = vovov->t1();
38975 0 : const Type& v3 = vovov->t2();
38976 0 : const details::operator_type o0 = operation;
38977 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
38978 0 : const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
38979 :
38980 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
38981 0 : binary_functor_t f1 = vovov->f0();
38982 0 : binary_functor_t f2 = vovov->f1();
38983 :
38984 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
38985 :
38986 0 : expression_node_ptr result = error_node();
38987 :
38988 : const bool synthesis_result =
38989 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
38990 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
38991 :
38992 0 : if (synthesis_result)
38993 0 : return result;
38994 0 : else if (!expr_gen.valid_operator(o0,f0))
38995 0 : return error_node();
38996 :
38997 : exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
38998 :
38999 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
39000 : }
39001 :
39002 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39003 : const details::operator_type o0,
39004 : const details::operator_type o1,
39005 : const details::operator_type o2)
39006 : {
39007 0 : return details::build_string()
39008 0 : << "t" << expr_gen.to_str(o0)
39009 0 : << "((t" << expr_gen.to_str(o1)
39010 0 : << "t)" << expr_gen.to_str(o2)
39011 0 : << "t)";
39012 : }
39013 : };
39014 :
39015 : struct synthesize_vovovoc_expression2
39016 : {
39017 : typedef typename vovovoc_t::type2 node_type;
39018 : typedef typename vovovoc_t::sf4_type sf4_type;
39019 : typedef typename node_type::T0 T0;
39020 : typedef typename node_type::T1 T1;
39021 : typedef typename node_type::T2 T2;
39022 : typedef typename node_type::T3 T3;
39023 :
39024 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39025 : const details::operator_type& operation,
39026 : expression_node_ptr (&branch)[2])
39027 : {
39028 : // v0 o0 ((v1 o1 v2) o2 c)
39029 : typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
39030 :
39031 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
39032 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
39033 0 : const Type& v1 = vovoc->t0();
39034 0 : const Type& v2 = vovoc->t1();
39035 0 : const Type c = vovoc->t2();
39036 0 : const details::operator_type o0 = operation;
39037 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
39038 0 : const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
39039 :
39040 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39041 0 : binary_functor_t f1 = vovoc->f0();
39042 0 : binary_functor_t f2 = vovoc->f1();
39043 :
39044 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39045 :
39046 0 : expression_node_ptr result = error_node();
39047 :
39048 : const bool synthesis_result =
39049 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39050 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
39051 :
39052 0 : if (synthesis_result)
39053 0 : return result;
39054 0 : else if (!expr_gen.valid_operator(o0,f0))
39055 0 : return error_node();
39056 :
39057 : exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
39058 :
39059 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
39060 : }
39061 :
39062 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39063 : const details::operator_type o0,
39064 : const details::operator_type o1,
39065 : const details::operator_type o2)
39066 : {
39067 0 : return details::build_string()
39068 0 : << "t" << expr_gen.to_str(o0)
39069 0 : << "((t" << expr_gen.to_str(o1)
39070 0 : << "t)" << expr_gen.to_str(o2)
39071 0 : << "t)";
39072 : }
39073 : };
39074 :
39075 : struct synthesize_vovocov_expression2
39076 : {
39077 : typedef typename vovocov_t::type2 node_type;
39078 : typedef typename vovocov_t::sf4_type sf4_type;
39079 : typedef typename node_type::T0 T0;
39080 : typedef typename node_type::T1 T1;
39081 : typedef typename node_type::T2 T2;
39082 : typedef typename node_type::T3 T3;
39083 :
39084 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39085 : const details::operator_type& operation,
39086 : expression_node_ptr (&branch)[2])
39087 : {
39088 : // v0 o0 ((v1 o1 c) o2 v2)
39089 : typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
39090 :
39091 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
39092 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
39093 0 : const Type& v1 = vocov->t0();
39094 0 : const Type c = vocov->t1();
39095 0 : const Type& v2 = vocov->t2();
39096 0 : const details::operator_type o0 = operation;
39097 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
39098 0 : const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
39099 :
39100 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39101 0 : binary_functor_t f1 = vocov->f0();
39102 0 : binary_functor_t f2 = vocov->f1();
39103 :
39104 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39105 :
39106 0 : expression_node_ptr result = error_node();
39107 :
39108 : const bool synthesis_result =
39109 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39110 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
39111 :
39112 0 : if (synthesis_result)
39113 0 : return result;
39114 0 : else if (!expr_gen.valid_operator(o0,f0))
39115 0 : return error_node();
39116 :
39117 : exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
39118 :
39119 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
39120 : }
39121 :
39122 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39123 : const details::operator_type o0,
39124 : const details::operator_type o1,
39125 : const details::operator_type o2)
39126 : {
39127 0 : return details::build_string()
39128 0 : << "t" << expr_gen.to_str(o0)
39129 0 : << "((t" << expr_gen.to_str(o1)
39130 0 : << "t)" << expr_gen.to_str(o2)
39131 0 : << "t)";
39132 : }
39133 : };
39134 :
39135 : struct synthesize_vocovov_expression2
39136 : {
39137 : typedef typename vocovov_t::type2 node_type;
39138 : typedef typename vocovov_t::sf4_type sf4_type;
39139 : typedef typename node_type::T0 T0;
39140 : typedef typename node_type::T1 T1;
39141 : typedef typename node_type::T2 T2;
39142 : typedef typename node_type::T3 T3;
39143 :
39144 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39145 : const details::operator_type& operation,
39146 : expression_node_ptr (&branch)[2])
39147 : {
39148 : // v0 o0 ((c o1 v1) o2 v2)
39149 : typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
39150 :
39151 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
39152 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
39153 0 : const Type c = covov->t0();
39154 0 : const Type& v1 = covov->t1();
39155 0 : const Type& v2 = covov->t2();
39156 0 : const details::operator_type o0 = operation;
39157 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f0());
39158 0 : const details::operator_type o2 = expr_gen.get_operator(covov->f1());
39159 :
39160 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39161 0 : binary_functor_t f1 = covov->f0();
39162 0 : binary_functor_t f2 = covov->f1();
39163 :
39164 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39165 :
39166 0 : expression_node_ptr result = error_node();
39167 :
39168 : const bool synthesis_result =
39169 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39170 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
39171 :
39172 0 : if (synthesis_result)
39173 0 : return result;
39174 0 : else if (!expr_gen.valid_operator(o0,f0))
39175 0 : return error_node();
39176 :
39177 : exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
39178 :
39179 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
39180 : }
39181 :
39182 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39183 : const details::operator_type o0,
39184 : const details::operator_type o1,
39185 : const details::operator_type o2)
39186 : {
39187 0 : return details::build_string()
39188 0 : << "t" << expr_gen.to_str(o0)
39189 0 : << "((t" << expr_gen.to_str(o1)
39190 0 : << "t)" << expr_gen.to_str(o2)
39191 0 : << "t)";
39192 : }
39193 : };
39194 :
39195 : struct synthesize_covovov_expression2
39196 : {
39197 : typedef typename covovov_t::type2 node_type;
39198 : typedef typename covovov_t::sf4_type sf4_type;
39199 : typedef typename node_type::T0 T0;
39200 : typedef typename node_type::T1 T1;
39201 : typedef typename node_type::T2 T2;
39202 : typedef typename node_type::T3 T3;
39203 :
39204 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39205 : const details::operator_type& operation,
39206 : expression_node_ptr (&branch)[2])
39207 : {
39208 : // c o0 ((v1 o1 v2) o2 v3)
39209 : typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
39210 :
39211 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
39212 0 : const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
39213 0 : const Type& v0 = vovov->t0();
39214 0 : const Type& v1 = vovov->t1();
39215 0 : const Type& v2 = vovov->t2();
39216 0 : const details::operator_type o0 = operation;
39217 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
39218 0 : const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
39219 :
39220 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39221 0 : binary_functor_t f1 = vovov->f0();
39222 0 : binary_functor_t f2 = vovov->f1();
39223 :
39224 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39225 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39226 :
39227 0 : expression_node_ptr result = error_node();
39228 :
39229 : const bool synthesis_result =
39230 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39231 0 : (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
39232 :
39233 0 : if (synthesis_result)
39234 0 : return result;
39235 0 : else if (!expr_gen.valid_operator(o0,f0))
39236 0 : return error_node();
39237 :
39238 : exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
39239 :
39240 0 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
39241 : }
39242 :
39243 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39244 : const details::operator_type o0,
39245 : const details::operator_type o1,
39246 : const details::operator_type o2)
39247 : {
39248 0 : return details::build_string()
39249 0 : << "t" << expr_gen.to_str(o0)
39250 0 : << "((t" << expr_gen.to_str(o1)
39251 0 : << "t)" << expr_gen.to_str(o2)
39252 0 : << "t)";
39253 : }
39254 : };
39255 :
39256 : struct synthesize_covocov_expression2
39257 : {
39258 : typedef typename covocov_t::type2 node_type;
39259 : typedef typename covocov_t::sf4_type sf4_type;
39260 : typedef typename node_type::T0 T0;
39261 : typedef typename node_type::T1 T1;
39262 : typedef typename node_type::T2 T2;
39263 : typedef typename node_type::T3 T3;
39264 :
39265 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39266 : const details::operator_type& operation,
39267 : expression_node_ptr (&branch)[2])
39268 : {
39269 : // c0 o0 ((v0 o1 c1) o2 v1)
39270 : typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
39271 :
39272 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
39273 0 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
39274 0 : const Type& v0 = vocov->t0();
39275 0 : const Type c1 = vocov->t1();
39276 0 : const Type& v1 = vocov->t2();
39277 0 : const details::operator_type o0 = operation;
39278 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
39279 0 : const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
39280 :
39281 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39282 0 : binary_functor_t f1 = vocov->f0();
39283 0 : binary_functor_t f2 = vocov->f1();
39284 :
39285 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39286 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39287 :
39288 0 : expression_node_ptr result = error_node();
39289 :
39290 : const bool synthesis_result =
39291 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39292 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
39293 :
39294 0 : if (synthesis_result)
39295 0 : return result;
39296 0 : else if (!expr_gen.valid_operator(o0,f0))
39297 0 : return error_node();
39298 :
39299 : exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
39300 :
39301 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
39302 : }
39303 :
39304 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39305 : const details::operator_type o0,
39306 : const details::operator_type o1,
39307 : const details::operator_type o2)
39308 : {
39309 0 : return details::build_string()
39310 0 : << "t" << expr_gen.to_str(o0)
39311 0 : << "((t" << expr_gen.to_str(o1)
39312 0 : << "t)" << expr_gen.to_str(o2)
39313 0 : << "t)";
39314 : }
39315 : };
39316 :
39317 : struct synthesize_vocovoc_expression2
39318 : {
39319 : typedef typename vocovoc_t::type2 node_type;
39320 : typedef typename vocovoc_t::sf4_type sf4_type;
39321 : typedef typename node_type::T0 T0;
39322 : typedef typename node_type::T1 T1;
39323 : typedef typename node_type::T2 T2;
39324 : typedef typename node_type::T3 T3;
39325 :
39326 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39327 : const details::operator_type& operation,
39328 : expression_node_ptr (&branch)[2])
39329 : {
39330 : // v0 o0 ((c0 o1 v1) o2 c1)
39331 : typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
39332 :
39333 0 : const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
39334 0 : const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
39335 0 : const Type c0 = covoc->t0();
39336 0 : const Type& v1 = covoc->t1();
39337 0 : const Type c1 = covoc->t2();
39338 0 : const details::operator_type o0 = operation;
39339 0 : const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
39340 0 : const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
39341 :
39342 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39343 0 : binary_functor_t f1 = covoc->f0();
39344 0 : binary_functor_t f2 = covoc->f1();
39345 :
39346 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39347 :
39348 0 : expression_node_ptr result = error_node();
39349 :
39350 : const bool synthesis_result =
39351 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39352 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
39353 :
39354 0 : if (synthesis_result)
39355 0 : return result;
39356 0 : else if (!expr_gen.valid_operator(o0,f0))
39357 0 : return error_node();
39358 :
39359 : exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
39360 :
39361 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
39362 : }
39363 :
39364 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39365 : const details::operator_type o0,
39366 : const details::operator_type o1,
39367 : const details::operator_type o2)
39368 : {
39369 0 : return details::build_string()
39370 0 : << "t" << expr_gen.to_str(o0)
39371 0 : << "((t" << expr_gen.to_str(o1)
39372 0 : << "t)" << expr_gen.to_str(o2)
39373 0 : << "t)";
39374 : }
39375 : };
39376 :
39377 : struct synthesize_covovoc_expression2
39378 : {
39379 : typedef typename covovoc_t::type2 node_type;
39380 : typedef typename covovoc_t::sf4_type sf4_type;
39381 : typedef typename node_type::T0 T0;
39382 : typedef typename node_type::T1 T1;
39383 : typedef typename node_type::T2 T2;
39384 : typedef typename node_type::T3 T3;
39385 :
39386 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39387 : const details::operator_type& operation,
39388 : expression_node_ptr (&branch)[2])
39389 : {
39390 : // c0 o0 ((v0 o1 v1) o2 c1)
39391 : typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
39392 :
39393 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
39394 0 : const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
39395 0 : const Type& v0 = vovoc->t0();
39396 0 : const Type& v1 = vovoc->t1();
39397 0 : const Type c1 = vovoc->t2();
39398 0 : const details::operator_type o0 = operation;
39399 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
39400 0 : const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
39401 :
39402 0 : binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
39403 0 : binary_functor_t f1 = vovoc->f0();
39404 0 : binary_functor_t f2 = vovoc->f1();
39405 :
39406 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39407 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39408 :
39409 0 : expression_node_ptr result = error_node();
39410 :
39411 : const bool synthesis_result =
39412 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39413 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
39414 :
39415 0 : if (synthesis_result)
39416 0 : return result;
39417 0 : else if (!expr_gen.valid_operator(o0,f0))
39418 0 : return error_node();
39419 :
39420 : exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
39421 :
39422 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
39423 : }
39424 :
39425 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39426 : const details::operator_type o0,
39427 : const details::operator_type o1,
39428 : const details::operator_type o2)
39429 : {
39430 0 : return details::build_string()
39431 0 : << "t" << expr_gen.to_str(o0)
39432 0 : << "((t" << expr_gen.to_str(o1)
39433 0 : << "t)" << expr_gen.to_str(o2)
39434 0 : << "t)";
39435 : }
39436 : };
39437 :
39438 : struct synthesize_vococov_expression2
39439 : {
39440 : typedef typename vococov_t::type2 node_type;
39441 : static inline expression_node_ptr process(expression_generator<Type>&,
39442 : const details::operator_type&,
39443 : expression_node_ptr (&)[2])
39444 : {
39445 : // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
39446 : exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
39447 : return error_node();
39448 : }
39449 :
39450 : static inline std::string id(expression_generator<Type>&,
39451 : const details::operator_type,
39452 : const details::operator_type,
39453 : const details::operator_type)
39454 : {
39455 : return "INVALID";
39456 : }
39457 : };
39458 :
39459 : struct synthesize_vovovov_expression3
39460 : {
39461 : typedef typename vovovov_t::type3 node_type;
39462 : typedef typename vovovov_t::sf4_type sf4_type;
39463 : typedef typename node_type::T0 T0;
39464 : typedef typename node_type::T1 T1;
39465 : typedef typename node_type::T2 T2;
39466 : typedef typename node_type::T3 T3;
39467 :
39468 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39469 : const details::operator_type& operation,
39470 : expression_node_ptr (&branch)[2])
39471 : {
39472 : // ((v0 o0 v1) o1 v2) o2 v3
39473 : typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
39474 :
39475 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
39476 0 : const Type& v0 = vovov->t0();
39477 0 : const Type& v1 = vovov->t1();
39478 0 : const Type& v2 = vovov->t2();
39479 0 : const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39480 0 : const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
39481 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
39482 0 : const details::operator_type o2 = operation;
39483 :
39484 0 : binary_functor_t f0 = vovov->f0();
39485 0 : binary_functor_t f1 = vovov->f1();
39486 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39487 :
39488 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39489 :
39490 0 : expression_node_ptr result = error_node();
39491 :
39492 : const bool synthesis_result =
39493 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39494 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
39495 :
39496 0 : if (synthesis_result)
39497 0 : return result;
39498 0 : else if (!expr_gen.valid_operator(o2,f2))
39499 0 : return error_node();
39500 :
39501 : exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
39502 :
39503 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
39504 : }
39505 :
39506 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39507 : const details::operator_type o0,
39508 : const details::operator_type o1,
39509 : const details::operator_type o2)
39510 : {
39511 0 : return details::build_string()
39512 0 : << "((t" << expr_gen.to_str(o0)
39513 0 : << "t)" << expr_gen.to_str(o1)
39514 0 : << "t)" << expr_gen.to_str(o2)
39515 0 : << "t";
39516 : }
39517 : };
39518 :
39519 : struct synthesize_vovovoc_expression3
39520 : {
39521 : typedef typename vovovoc_t::type3 node_type;
39522 : typedef typename vovovoc_t::sf4_type sf4_type;
39523 : typedef typename node_type::T0 T0;
39524 : typedef typename node_type::T1 T1;
39525 : typedef typename node_type::T2 T2;
39526 : typedef typename node_type::T3 T3;
39527 :
39528 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39529 : const details::operator_type& operation,
39530 : expression_node_ptr (&branch)[2])
39531 : {
39532 : // ((v0 o0 v1) o1 v2) o2 c
39533 : typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
39534 :
39535 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
39536 0 : const Type& v0 = vovov->t0();
39537 0 : const Type& v1 = vovov->t1();
39538 0 : const Type& v2 = vovov->t2();
39539 0 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
39540 0 : const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
39541 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
39542 0 : const details::operator_type o2 = operation;
39543 :
39544 0 : binary_functor_t f0 = vovov->f0();
39545 0 : binary_functor_t f1 = vovov->f1();
39546 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39547 :
39548 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39549 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39550 :
39551 0 : expression_node_ptr result = error_node();
39552 :
39553 : const bool synthesis_result =
39554 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39555 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
39556 :
39557 0 : if (synthesis_result)
39558 0 : return result;
39559 0 : else if (!expr_gen.valid_operator(o2,f2))
39560 0 : return error_node();
39561 :
39562 : exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
39563 :
39564 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
39565 : }
39566 :
39567 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39568 : const details::operator_type o0,
39569 : const details::operator_type o1,
39570 : const details::operator_type o2)
39571 : {
39572 0 : return details::build_string()
39573 0 : << "((t" << expr_gen.to_str(o0)
39574 0 : << "t)" << expr_gen.to_str(o1)
39575 0 : << "t)" << expr_gen.to_str(o2)
39576 0 : << "t";
39577 : }
39578 : };
39579 :
39580 : struct synthesize_vovocov_expression3
39581 : {
39582 : typedef typename vovocov_t::type3 node_type;
39583 : typedef typename vovocov_t::sf4_type sf4_type;
39584 : typedef typename node_type::T0 T0;
39585 : typedef typename node_type::T1 T1;
39586 : typedef typename node_type::T2 T2;
39587 : typedef typename node_type::T3 T3;
39588 :
39589 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39590 : const details::operator_type& operation,
39591 : expression_node_ptr (&branch)[2])
39592 : {
39593 : // ((v0 o0 v1) o1 c) o2 v2
39594 : typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
39595 :
39596 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
39597 0 : const Type& v0 = vovoc->t0();
39598 0 : const Type& v1 = vovoc->t1();
39599 0 : const Type c = vovoc->t2();
39600 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39601 0 : const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
39602 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
39603 0 : const details::operator_type o2 = operation;
39604 :
39605 0 : binary_functor_t f0 = vovoc->f0();
39606 0 : binary_functor_t f1 = vovoc->f1();
39607 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39608 :
39609 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39610 :
39611 0 : expression_node_ptr result = error_node();
39612 :
39613 : const bool synthesis_result =
39614 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39615 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
39616 :
39617 0 : if (synthesis_result)
39618 0 : return result;
39619 0 : else if (!expr_gen.valid_operator(o2,f2))
39620 0 : return error_node();
39621 :
39622 : exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
39623 :
39624 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
39625 : }
39626 :
39627 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39628 : const details::operator_type o0,
39629 : const details::operator_type o1,
39630 : const details::operator_type o2)
39631 : {
39632 0 : return details::build_string()
39633 0 : << "((t" << expr_gen.to_str(o0)
39634 0 : << "t)" << expr_gen.to_str(o1)
39635 0 : << "t)" << expr_gen.to_str(o2)
39636 0 : << "t";
39637 : }
39638 : };
39639 :
39640 : struct synthesize_vocovov_expression3
39641 : {
39642 : typedef typename vocovov_t::type3 node_type;
39643 : typedef typename vocovov_t::sf4_type sf4_type;
39644 : typedef typename node_type::T0 T0;
39645 : typedef typename node_type::T1 T1;
39646 : typedef typename node_type::T2 T2;
39647 : typedef typename node_type::T3 T3;
39648 :
39649 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39650 : const details::operator_type& operation,
39651 : expression_node_ptr (&branch)[2])
39652 : {
39653 : // ((v0 o0 c) o1 v1) o2 v2
39654 : typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
39655 :
39656 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
39657 0 : const Type& v0 = vocov->t0();
39658 0 : const Type c = vocov->t1();
39659 0 : const Type& v1 = vocov->t2();
39660 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39661 0 : const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
39662 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
39663 0 : const details::operator_type o2 = operation;
39664 :
39665 0 : binary_functor_t f0 = vocov->f0();
39666 0 : binary_functor_t f1 = vocov->f1();
39667 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39668 :
39669 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39670 :
39671 0 : expression_node_ptr result = error_node();
39672 :
39673 : const bool synthesis_result =
39674 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39675 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
39676 :
39677 0 : if (synthesis_result)
39678 0 : return result;
39679 0 : else if (!expr_gen.valid_operator(o2,f2))
39680 0 : return error_node();
39681 :
39682 : exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
39683 :
39684 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
39685 : }
39686 :
39687 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39688 : const details::operator_type o0,
39689 : const details::operator_type o1,
39690 : const details::operator_type o2)
39691 : {
39692 0 : return details::build_string()
39693 0 : << "((t" << expr_gen.to_str(o0)
39694 0 : << "t)" << expr_gen.to_str(o1)
39695 0 : << "t)" << expr_gen.to_str(o2)
39696 0 : << "t";
39697 : }
39698 : };
39699 :
39700 : struct synthesize_covovov_expression3
39701 : {
39702 : typedef typename covovov_t::type3 node_type;
39703 : typedef typename covovov_t::sf4_type sf4_type;
39704 : typedef typename node_type::T0 T0;
39705 : typedef typename node_type::T1 T1;
39706 : typedef typename node_type::T2 T2;
39707 : typedef typename node_type::T3 T3;
39708 :
39709 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39710 : const details::operator_type& operation,
39711 : expression_node_ptr (&branch)[2])
39712 : {
39713 : // ((c o0 v0) o1 v1) o2 v2
39714 : typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
39715 :
39716 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
39717 0 : const Type c = covov->t0();
39718 0 : const Type& v0 = covov->t1();
39719 0 : const Type& v1 = covov->t2();
39720 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39721 0 : const details::operator_type o0 = expr_gen.get_operator(covov->f0());
39722 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f1());
39723 0 : const details::operator_type o2 = operation;
39724 :
39725 0 : binary_functor_t f0 = covov->f0();
39726 0 : binary_functor_t f1 = covov->f1();
39727 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39728 :
39729 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39730 :
39731 0 : expression_node_ptr result = error_node();
39732 :
39733 : const bool synthesis_result =
39734 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39735 0 : (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
39736 :
39737 0 : if (synthesis_result)
39738 0 : return result;
39739 0 : else if (!expr_gen.valid_operator(o2,f2))
39740 0 : return error_node();
39741 :
39742 : exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
39743 :
39744 0 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
39745 : }
39746 :
39747 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39748 : const details::operator_type o0,
39749 : const details::operator_type o1,
39750 : const details::operator_type o2)
39751 : {
39752 0 : return details::build_string()
39753 0 : << "((t" << expr_gen.to_str(o0)
39754 0 : << "t)" << expr_gen.to_str(o1)
39755 0 : << "t)" << expr_gen.to_str(o2)
39756 0 : << "t";
39757 : }
39758 : };
39759 :
39760 : struct synthesize_covocov_expression3
39761 : {
39762 : typedef typename covocov_t::type3 node_type;
39763 : typedef typename covocov_t::sf4_type sf4_type;
39764 : typedef typename node_type::T0 T0;
39765 : typedef typename node_type::T1 T1;
39766 : typedef typename node_type::T2 T2;
39767 : typedef typename node_type::T3 T3;
39768 :
39769 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39770 : const details::operator_type& operation,
39771 : expression_node_ptr (&branch)[2])
39772 : {
39773 : // ((c0 o0 v0) o1 c1) o2 v1
39774 : typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
39775 :
39776 0 : const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
39777 0 : const Type c0 = covoc->t0();
39778 0 : const Type& v0 = covoc->t1();
39779 0 : const Type c1 = covoc->t2();
39780 0 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39781 0 : const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
39782 0 : const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
39783 0 : const details::operator_type o2 = operation;
39784 :
39785 0 : binary_functor_t f0 = covoc->f0();
39786 0 : binary_functor_t f1 = covoc->f1();
39787 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39788 :
39789 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39790 :
39791 0 : expression_node_ptr result = error_node();
39792 :
39793 : const bool synthesis_result =
39794 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39795 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
39796 :
39797 0 : if (synthesis_result)
39798 0 : return result;
39799 0 : else if (!expr_gen.valid_operator(o2,f2))
39800 0 : return error_node();
39801 :
39802 : exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
39803 :
39804 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
39805 : }
39806 :
39807 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39808 : const details::operator_type o0,
39809 : const details::operator_type o1,
39810 : const details::operator_type o2)
39811 : {
39812 0 : return details::build_string()
39813 0 : << "((t" << expr_gen.to_str(o0)
39814 0 : << "t)" << expr_gen.to_str(o1)
39815 0 : << "t)" << expr_gen.to_str(o2)
39816 0 : << "t";
39817 : }
39818 : };
39819 :
39820 : struct synthesize_vocovoc_expression3
39821 : {
39822 : typedef typename vocovoc_t::type3 node_type;
39823 : typedef typename vocovoc_t::sf4_type sf4_type;
39824 : typedef typename node_type::T0 T0;
39825 : typedef typename node_type::T1 T1;
39826 : typedef typename node_type::T2 T2;
39827 : typedef typename node_type::T3 T3;
39828 :
39829 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39830 : const details::operator_type& operation,
39831 : expression_node_ptr (&branch)[2])
39832 : {
39833 : // ((v0 o0 c0) o1 v1) o2 c1
39834 : typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
39835 :
39836 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
39837 0 : const Type& v0 = vocov->t0();
39838 0 : const Type c0 = vocov->t1();
39839 0 : const Type& v1 = vocov->t2();
39840 0 : const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
39841 0 : const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
39842 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
39843 0 : const details::operator_type o2 = operation;
39844 :
39845 0 : binary_functor_t f0 = vocov->f0();
39846 0 : binary_functor_t f1 = vocov->f1();
39847 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39848 :
39849 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39850 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39851 :
39852 0 : expression_node_ptr result = error_node();
39853 :
39854 : const bool synthesis_result =
39855 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39856 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
39857 :
39858 0 : if (synthesis_result)
39859 0 : return result;
39860 0 : else if (!expr_gen.valid_operator(o2,f2))
39861 0 : return error_node();
39862 :
39863 : exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
39864 :
39865 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
39866 : }
39867 :
39868 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39869 : const details::operator_type o0,
39870 : const details::operator_type o1,
39871 : const details::operator_type o2)
39872 : {
39873 0 : return details::build_string()
39874 0 : << "((t" << expr_gen.to_str(o0)
39875 0 : << "t)" << expr_gen.to_str(o1)
39876 0 : << "t)" << expr_gen.to_str(o2)
39877 0 : << "t";
39878 : }
39879 : };
39880 :
39881 : struct synthesize_covovoc_expression3
39882 : {
39883 : typedef typename covovoc_t::type3 node_type;
39884 : typedef typename covovoc_t::sf4_type sf4_type;
39885 : typedef typename node_type::T0 T0;
39886 : typedef typename node_type::T1 T1;
39887 : typedef typename node_type::T2 T2;
39888 : typedef typename node_type::T3 T3;
39889 :
39890 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39891 : const details::operator_type& operation,
39892 : expression_node_ptr (&branch)[2])
39893 : {
39894 : // ((c0 o0 v0) o1 v1) o2 c1
39895 : typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
39896 :
39897 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
39898 0 : const Type c0 = covov->t0();
39899 0 : const Type& v0 = covov->t1();
39900 0 : const Type& v1 = covov->t2();
39901 0 : const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
39902 0 : const details::operator_type o0 = expr_gen.get_operator(covov->f0());
39903 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f1());
39904 0 : const details::operator_type o2 = operation;
39905 :
39906 0 : binary_functor_t f0 = covov->f0();
39907 0 : binary_functor_t f1 = covov->f1();
39908 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39909 :
39910 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39911 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
39912 :
39913 0 : expression_node_ptr result = error_node();
39914 :
39915 : const bool synthesis_result =
39916 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39917 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
39918 :
39919 0 : if (synthesis_result)
39920 0 : return result;
39921 0 : else if (!expr_gen.valid_operator(o2,f2))
39922 0 : return error_node();
39923 :
39924 : exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
39925 :
39926 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
39927 : }
39928 :
39929 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39930 : const details::operator_type o0,
39931 : const details::operator_type o1,
39932 : const details::operator_type o2)
39933 : {
39934 0 : return details::build_string()
39935 0 : << "((t" << expr_gen.to_str(o0)
39936 0 : << "t)" << expr_gen.to_str(o1)
39937 0 : << "t)" << expr_gen.to_str(o2)
39938 0 : << "t";
39939 : }
39940 : };
39941 :
39942 : struct synthesize_vococov_expression3
39943 : {
39944 : typedef typename vococov_t::type3 node_type;
39945 : typedef typename vococov_t::sf4_type sf4_type;
39946 : typedef typename node_type::T0 T0;
39947 : typedef typename node_type::T1 T1;
39948 : typedef typename node_type::T2 T2;
39949 : typedef typename node_type::T3 T3;
39950 :
39951 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
39952 : const details::operator_type& operation,
39953 : expression_node_ptr (&branch)[2])
39954 : {
39955 : // ((v0 o0 c0) o1 c1) o2 v1
39956 : typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
39957 :
39958 0 : const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
39959 0 : const Type& v0 = vococ->t0();
39960 0 : const Type c0 = vococ->t1();
39961 0 : const Type c1 = vococ->t2();
39962 0 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
39963 0 : const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
39964 0 : const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
39965 0 : const details::operator_type o2 = operation;
39966 :
39967 0 : binary_functor_t f0 = vococ->f0();
39968 0 : binary_functor_t f1 = vococ->f1();
39969 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
39970 :
39971 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
39972 :
39973 0 : expression_node_ptr result = error_node();
39974 :
39975 : const bool synthesis_result =
39976 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
39977 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
39978 :
39979 0 : if (synthesis_result)
39980 0 : return result;
39981 0 : else if (!expr_gen.valid_operator(o2,f2))
39982 0 : return error_node();
39983 :
39984 : exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
39985 :
39986 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
39987 : }
39988 :
39989 0 : static inline std::string id(expression_generator<Type>& expr_gen,
39990 : const details::operator_type o0,
39991 : const details::operator_type o1,
39992 : const details::operator_type o2)
39993 : {
39994 0 : return details::build_string()
39995 0 : << "((t" << expr_gen.to_str(o0)
39996 0 : << "t)" << expr_gen.to_str(o1)
39997 0 : << "t)" << expr_gen.to_str(o2)
39998 0 : << "t";
39999 : }
40000 : };
40001 :
40002 : struct synthesize_vovovov_expression4
40003 : {
40004 : typedef typename vovovov_t::type4 node_type;
40005 : typedef typename vovovov_t::sf4_type sf4_type;
40006 : typedef typename node_type::T0 T0;
40007 : typedef typename node_type::T1 T1;
40008 : typedef typename node_type::T2 T2;
40009 : typedef typename node_type::T3 T3;
40010 :
40011 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40012 : const details::operator_type& operation,
40013 : expression_node_ptr (&branch)[2])
40014 : {
40015 : // (v0 o0 (v1 o1 v2)) o2 v3
40016 : typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
40017 :
40018 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
40019 0 : const Type& v0 = vovov->t0();
40020 0 : const Type& v1 = vovov->t1();
40021 0 : const Type& v2 = vovov->t2();
40022 0 : const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
40023 0 : const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
40024 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
40025 0 : const details::operator_type o2 = operation;
40026 :
40027 0 : binary_functor_t f0 = vovov->f0();
40028 0 : binary_functor_t f1 = vovov->f1();
40029 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40030 :
40031 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40032 :
40033 0 : expression_node_ptr result = error_node();
40034 :
40035 : const bool synthesis_result =
40036 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40037 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
40038 :
40039 0 : if (synthesis_result)
40040 0 : return result;
40041 0 : else if (!expr_gen.valid_operator(o2,f2))
40042 0 : return error_node();
40043 :
40044 : exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
40045 :
40046 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
40047 : }
40048 :
40049 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40050 : const details::operator_type o0,
40051 : const details::operator_type o1,
40052 : const details::operator_type o2)
40053 : {
40054 0 : return details::build_string()
40055 0 : << "(t" << expr_gen.to_str(o0)
40056 0 : << "(t" << expr_gen.to_str(o1)
40057 0 : << "t)" << expr_gen.to_str(o2)
40058 0 : << "t";
40059 : }
40060 : };
40061 :
40062 : struct synthesize_vovovoc_expression4
40063 : {
40064 : typedef typename vovovoc_t::type4 node_type;
40065 : typedef typename vovovoc_t::sf4_type sf4_type;
40066 : typedef typename node_type::T0 T0;
40067 : typedef typename node_type::T1 T1;
40068 : typedef typename node_type::T2 T2;
40069 : typedef typename node_type::T3 T3;
40070 :
40071 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40072 : const details::operator_type& operation,
40073 : expression_node_ptr (&branch)[2])
40074 : {
40075 : // ((v0 o0 (v1 o1 v2)) o2 c)
40076 : typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
40077 :
40078 0 : const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
40079 0 : const Type& v0 = vovov->t0();
40080 0 : const Type& v1 = vovov->t1();
40081 0 : const Type& v2 = vovov->t2();
40082 0 : const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
40083 0 : const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
40084 0 : const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
40085 0 : const details::operator_type o2 = operation;
40086 :
40087 0 : binary_functor_t f0 = vovov->f0();
40088 0 : binary_functor_t f1 = vovov->f1();
40089 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40090 :
40091 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40092 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
40093 :
40094 0 : expression_node_ptr result = error_node();
40095 :
40096 : const bool synthesis_result =
40097 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40098 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
40099 :
40100 0 : if (synthesis_result)
40101 0 : return result;
40102 0 : else if (!expr_gen.valid_operator(o2,f2))
40103 0 : return error_node();
40104 :
40105 : exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
40106 :
40107 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
40108 : }
40109 :
40110 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40111 : const details::operator_type o0,
40112 : const details::operator_type o1,
40113 : const details::operator_type o2)
40114 : {
40115 0 : return details::build_string()
40116 0 : << "(t" << expr_gen.to_str(o0)
40117 0 : << "(t" << expr_gen.to_str(o1)
40118 0 : << "t)" << expr_gen.to_str(o2)
40119 0 : << "t";
40120 : }
40121 : };
40122 :
40123 : struct synthesize_vovocov_expression4
40124 : {
40125 : typedef typename vovocov_t::type4 node_type;
40126 : typedef typename vovocov_t::sf4_type sf4_type;
40127 : typedef typename node_type::T0 T0;
40128 : typedef typename node_type::T1 T1;
40129 : typedef typename node_type::T2 T2;
40130 : typedef typename node_type::T3 T3;
40131 :
40132 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40133 : const details::operator_type& operation,
40134 : expression_node_ptr (&branch)[2])
40135 : {
40136 : // ((v0 o0 (v1 o1 c)) o2 v1)
40137 : typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
40138 :
40139 0 : const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
40140 0 : const Type& v0 = vovoc->t0();
40141 0 : const Type& v1 = vovoc->t1();
40142 0 : const Type c = vovoc->t2();
40143 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
40144 0 : const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
40145 0 : const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
40146 0 : const details::operator_type o2 = operation;
40147 :
40148 0 : binary_functor_t f0 = vovoc->f0();
40149 0 : binary_functor_t f1 = vovoc->f1();
40150 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40151 :
40152 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40153 :
40154 0 : expression_node_ptr result = error_node();
40155 :
40156 : const bool synthesis_result =
40157 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40158 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
40159 :
40160 0 : if (synthesis_result)
40161 0 : return result;
40162 0 : else if (!expr_gen.valid_operator(o2,f2))
40163 0 : return error_node();
40164 :
40165 : exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
40166 :
40167 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
40168 : }
40169 :
40170 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40171 : const details::operator_type o0,
40172 : const details::operator_type o1,
40173 : const details::operator_type o2)
40174 : {
40175 0 : return details::build_string()
40176 0 : << "(t" << expr_gen.to_str(o0)
40177 0 : << "(t" << expr_gen.to_str(o1)
40178 0 : << "t)" << expr_gen.to_str(o2)
40179 0 : << "t";
40180 : }
40181 : };
40182 :
40183 : struct synthesize_vocovov_expression4
40184 : {
40185 : typedef typename vocovov_t::type4 node_type;
40186 : typedef typename vocovov_t::sf4_type sf4_type;
40187 : typedef typename node_type::T0 T0;
40188 : typedef typename node_type::T1 T1;
40189 : typedef typename node_type::T2 T2;
40190 : typedef typename node_type::T3 T3;
40191 :
40192 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40193 : const details::operator_type& operation,
40194 : expression_node_ptr (&branch)[2])
40195 : {
40196 : // ((v0 o0 (c o1 v1)) o2 v2)
40197 : typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
40198 :
40199 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
40200 0 : const Type& v0 = vocov->t0();
40201 0 : const Type c = vocov->t1();
40202 0 : const Type& v1 = vocov->t2();
40203 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
40204 0 : const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
40205 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
40206 0 : const details::operator_type o2 = operation;
40207 :
40208 0 : binary_functor_t f0 = vocov->f0();
40209 0 : binary_functor_t f1 = vocov->f1();
40210 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40211 :
40212 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40213 0 : expression_node_ptr result = error_node();
40214 :
40215 : const bool synthesis_result =
40216 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40217 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
40218 :
40219 0 : if (synthesis_result)
40220 0 : return result;
40221 0 : else if (!expr_gen.valid_operator(o2,f2))
40222 0 : return error_node();
40223 :
40224 : exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
40225 :
40226 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
40227 : }
40228 :
40229 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40230 : const details::operator_type o0,
40231 : const details::operator_type o1,
40232 : const details::operator_type o2)
40233 : {
40234 0 : return details::build_string()
40235 0 : << "(t" << expr_gen.to_str(o0)
40236 0 : << "(t" << expr_gen.to_str(o1)
40237 0 : << "t)" << expr_gen.to_str(o2)
40238 0 : << "t";
40239 : }
40240 : };
40241 :
40242 : struct synthesize_covovov_expression4
40243 : {
40244 : typedef typename covovov_t::type4 node_type;
40245 : typedef typename covovov_t::sf4_type sf4_type;
40246 : typedef typename node_type::T0 T0;
40247 : typedef typename node_type::T1 T1;
40248 : typedef typename node_type::T2 T2;
40249 : typedef typename node_type::T3 T3;
40250 :
40251 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40252 : const details::operator_type& operation,
40253 : expression_node_ptr (&branch)[2])
40254 : {
40255 : // ((c o0 (v0 o1 v1)) o2 v2)
40256 : typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
40257 :
40258 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
40259 0 : const Type c = covov->t0();
40260 0 : const Type& v0 = covov->t1();
40261 0 : const Type& v1 = covov->t2();
40262 0 : const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
40263 0 : const details::operator_type o0 = expr_gen.get_operator(covov->f0());
40264 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f1());
40265 0 : const details::operator_type o2 = operation;
40266 :
40267 0 : binary_functor_t f0 = covov->f0();
40268 0 : binary_functor_t f1 = covov->f1();
40269 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40270 :
40271 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40272 :
40273 0 : expression_node_ptr result = error_node();
40274 :
40275 : const bool synthesis_result =
40276 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40277 0 : (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
40278 :
40279 0 : if (synthesis_result)
40280 0 : return result;
40281 0 : else if (!expr_gen.valid_operator(o2,f2))
40282 0 : return error_node();
40283 :
40284 : exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
40285 :
40286 0 : return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
40287 : }
40288 :
40289 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40290 : const details::operator_type o0,
40291 : const details::operator_type o1,
40292 : const details::operator_type o2)
40293 : {
40294 0 : return details::build_string()
40295 0 : << "(t" << expr_gen.to_str(o0)
40296 0 : << "(t" << expr_gen.to_str(o1)
40297 0 : << "t)" << expr_gen.to_str(o2)
40298 0 : << "t";
40299 : }
40300 : };
40301 :
40302 : struct synthesize_covocov_expression4
40303 : {
40304 : typedef typename covocov_t::type4 node_type;
40305 : typedef typename covocov_t::sf4_type sf4_type;
40306 : typedef typename node_type::T0 T0;
40307 : typedef typename node_type::T1 T1;
40308 : typedef typename node_type::T2 T2;
40309 : typedef typename node_type::T3 T3;
40310 :
40311 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40312 : const details::operator_type& operation,
40313 : expression_node_ptr (&branch)[2])
40314 : {
40315 : // ((c0 o0 (v0 o1 c1)) o2 v1)
40316 : typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
40317 :
40318 0 : const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
40319 0 : const Type c0 = covoc->t0();
40320 0 : const Type& v0 = covoc->t1();
40321 0 : const Type c1 = covoc->t2();
40322 0 : const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
40323 0 : const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
40324 0 : const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
40325 0 : const details::operator_type o2 = operation;
40326 :
40327 0 : binary_functor_t f0 = covoc->f0();
40328 0 : binary_functor_t f1 = covoc->f1();
40329 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40330 :
40331 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40332 :
40333 0 : expression_node_ptr result = error_node();
40334 :
40335 : const bool synthesis_result =
40336 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40337 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
40338 :
40339 0 : if (synthesis_result)
40340 0 : return result;
40341 0 : else if (!expr_gen.valid_operator(o2,f2))
40342 0 : return error_node();
40343 :
40344 : exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
40345 :
40346 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
40347 : }
40348 :
40349 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40350 : const details::operator_type o0,
40351 : const details::operator_type o1,
40352 : const details::operator_type o2)
40353 : {
40354 0 : return details::build_string()
40355 0 : << "(t" << expr_gen.to_str(o0)
40356 0 : << "(t" << expr_gen.to_str(o1)
40357 0 : << "t)" << expr_gen.to_str(o2)
40358 0 : << "t";
40359 : }
40360 : };
40361 :
40362 : struct synthesize_vocovoc_expression4
40363 : {
40364 : typedef typename vocovoc_t::type4 node_type;
40365 : typedef typename vocovoc_t::sf4_type sf4_type;
40366 : typedef typename node_type::T0 T0;
40367 : typedef typename node_type::T1 T1;
40368 : typedef typename node_type::T2 T2;
40369 : typedef typename node_type::T3 T3;
40370 :
40371 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40372 : const details::operator_type& operation,
40373 : expression_node_ptr (&branch)[2])
40374 : {
40375 : // ((v0 o0 (c0 o1 v1)) o2 c1)
40376 : typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
40377 :
40378 0 : const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
40379 0 : const Type& v0 = vocov->t0();
40380 0 : const Type c0 = vocov->t1();
40381 0 : const Type& v1 = vocov->t2();
40382 0 : const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
40383 0 : const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
40384 0 : const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
40385 0 : const details::operator_type o2 = operation;
40386 :
40387 0 : binary_functor_t f0 = vocov->f0();
40388 0 : binary_functor_t f1 = vocov->f1();
40389 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40390 :
40391 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40392 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
40393 :
40394 0 : expression_node_ptr result = error_node();
40395 :
40396 : const bool synthesis_result =
40397 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40398 0 : (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
40399 :
40400 0 : if (synthesis_result)
40401 0 : return result;
40402 0 : else if (!expr_gen.valid_operator(o2,f2))
40403 0 : return error_node();
40404 :
40405 : exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
40406 :
40407 0 : return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
40408 : }
40409 :
40410 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40411 : const details::operator_type o0,
40412 : const details::operator_type o1,
40413 : const details::operator_type o2)
40414 : {
40415 0 : return details::build_string()
40416 0 : << "(t" << expr_gen.to_str(o0)
40417 0 : << "(t" << expr_gen.to_str(o1)
40418 0 : << "t)" << expr_gen.to_str(o2)
40419 0 : << "t";
40420 : }
40421 : };
40422 :
40423 : struct synthesize_covovoc_expression4
40424 : {
40425 : typedef typename covovoc_t::type4 node_type;
40426 : typedef typename covovoc_t::sf4_type sf4_type;
40427 : typedef typename node_type::T0 T0;
40428 : typedef typename node_type::T1 T1;
40429 : typedef typename node_type::T2 T2;
40430 : typedef typename node_type::T3 T3;
40431 :
40432 0 : static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
40433 : const details::operator_type& operation,
40434 : expression_node_ptr (&branch)[2])
40435 : {
40436 : // ((c0 o0 (v0 o1 v1)) o2 c1)
40437 : typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
40438 :
40439 0 : const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
40440 0 : const Type c0 = covov->t0();
40441 0 : const Type& v0 = covov->t1();
40442 0 : const Type& v1 = covov->t2();
40443 0 : const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
40444 0 : const details::operator_type o0 = expr_gen.get_operator(covov->f0());
40445 0 : const details::operator_type o1 = expr_gen.get_operator(covov->f1());
40446 0 : const details::operator_type o2 = operation;
40447 :
40448 0 : binary_functor_t f0 = covov->f0();
40449 0 : binary_functor_t f1 = covov->f1();
40450 0 : binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
40451 :
40452 0 : details::free_node(*(expr_gen.node_allocator_),branch[0]);
40453 0 : details::free_node(*(expr_gen.node_allocator_),branch[1]);
40454 :
40455 0 : expression_node_ptr result = error_node();
40456 :
40457 : const bool synthesis_result =
40458 : synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
40459 0 : (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
40460 :
40461 0 : if (synthesis_result)
40462 0 : return result;
40463 0 : else if (!expr_gen.valid_operator(o2,f2))
40464 0 : return error_node();
40465 :
40466 : exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
40467 :
40468 0 : return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
40469 : }
40470 :
40471 0 : static inline std::string id(expression_generator<Type>& expr_gen,
40472 : const details::operator_type o0,
40473 : const details::operator_type o1,
40474 : const details::operator_type o2)
40475 : {
40476 0 : return details::build_string()
40477 0 : << "(t" << expr_gen.to_str(o0)
40478 0 : << "(t" << expr_gen.to_str(o1)
40479 0 : << "t)" << expr_gen.to_str(o2)
40480 0 : << "t";
40481 : }
40482 : };
40483 :
40484 : struct synthesize_vococov_expression4
40485 : {
40486 : typedef typename vococov_t::type4 node_type;
40487 : static inline expression_node_ptr process(expression_generator<Type>&,
40488 : const details::operator_type&,
40489 : expression_node_ptr (&)[2])
40490 : {
40491 : // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
40492 : exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
40493 : return error_node();
40494 : }
40495 :
40496 : static inline std::string id(expression_generator<Type>&,
40497 : const details::operator_type,
40498 : const details::operator_type,
40499 : const details::operator_type)
40500 : {
40501 : return "INVALID";
40502 : }
40503 : };
40504 : #endif
40505 :
40506 900 : inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
40507 : {
40508 : // Definition: uv o uv
40509 900 : details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
40510 900 : details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
40511 900 : const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
40512 900 : const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
40513 900 : unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
40514 900 : unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
40515 900 : binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
40516 :
40517 900 : if (!valid_operator(o0,u0))
40518 0 : return error_node();
40519 900 : else if (!valid_operator(o1,u1))
40520 0 : return error_node();
40521 900 : else if (!valid_operator(operation,f))
40522 0 : return error_node();
40523 :
40524 900 : expression_node_ptr result = error_node();
40525 :
40526 900 : if (
40527 900 : (details::e_neg == o0) &&
40528 280 : (details::e_neg == o1)
40529 : )
40530 : {
40531 280 : switch (operation)
40532 : {
40533 : // (-v0 + -v1) --> -(v0 + v1)
40534 0 : case details::e_add : result = (*this)(details::e_neg,
40535 0 : node_allocator_->
40536 : allocate_rr<typename details::
40537 : vov_node<Type,details::add_op<Type> > >(v0, v1));
40538 : exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
40539 0 : break;
40540 :
40541 : // (-v0 - -v1) --> (v1 - v0)
40542 0 : case details::e_sub : result = node_allocator_->
40543 : allocate_rr<typename details::
40544 0 : vov_node<Type,details::sub_op<Type> > >(v1, v0);
40545 : exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
40546 0 : break;
40547 :
40548 : // (-v0 * -v1) --> (v0 * v1)
40549 160 : case details::e_mul : result = node_allocator_->
40550 : allocate_rr<typename details::
40551 160 : vov_node<Type,details::mul_op<Type> > >(v0, v1);
40552 : exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
40553 160 : break;
40554 :
40555 : // (-v0 / -v1) --> (v0 / v1)
40556 120 : case details::e_div : result = node_allocator_->
40557 : allocate_rr<typename details::
40558 120 : vov_node<Type,details::div_op<Type> > >(v0, v1);
40559 : exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
40560 120 : break;
40561 :
40562 0 : default : break;
40563 : }
40564 : }
40565 :
40566 900 : if (0 == result)
40567 : {
40568 620 : result = node_allocator_->
40569 620 : allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
40570 : }
40571 :
40572 900 : details::free_all_nodes(*node_allocator_,branch);
40573 900 : return result;
40574 : }
40575 :
40576 : #undef basic_opr_switch_statements
40577 : #undef extended_opr_switch_statements
40578 : #undef unary_opr_switch_statements
40579 :
40580 : #ifndef exprtk_disable_string_capabilities
40581 :
40582 : #define string_opr_switch_statements \
40583 : case_stmt(details::e_lt , details::lt_op ) \
40584 : case_stmt(details::e_lte , details::lte_op ) \
40585 : case_stmt(details::e_gt , details::gt_op ) \
40586 : case_stmt(details::e_gte , details::gte_op ) \
40587 : case_stmt(details::e_eq , details::eq_op ) \
40588 : case_stmt(details::e_ne , details::ne_op ) \
40589 : case_stmt(details::e_in , details::in_op ) \
40590 : case_stmt(details::e_like , details::like_op ) \
40591 : case_stmt(details::e_ilike , details::ilike_op) \
40592 :
40593 : template <typename T0, typename T1>
40594 3690 : inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
40595 : T0 s0, T1 s1,
40596 : range_t rp0)
40597 : {
40598 3690 : switch (opr)
40599 : {
40600 : #define case_stmt(op0, op1) \
40601 : case op0 : return node_allocator_-> \
40602 : allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
40603 : (s0, s1, rp0); \
40604 :
40605 3690 : string_opr_switch_statements
40606 : #undef case_stmt
40607 0 : default : return error_node();
40608 : }
40609 : }
40610 :
40611 : template <typename T0, typename T1>
40612 3560 : inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
40613 : T0 s0, T1 s1,
40614 : range_t rp1)
40615 : {
40616 3560 : switch (opr)
40617 : {
40618 : #define case_stmt(op0, op1) \
40619 : case op0 : return node_allocator_-> \
40620 : allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
40621 : (s0, s1, rp1); \
40622 :
40623 3560 : string_opr_switch_statements
40624 : #undef case_stmt
40625 0 : default : return error_node();
40626 : }
40627 : }
40628 :
40629 : template <typename T0, typename T1>
40630 3355 : inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
40631 : T0 s0, T1 s1,
40632 : range_t rp0, range_t rp1)
40633 : {
40634 3355 : switch (opr)
40635 : {
40636 : #define case_stmt(op0, op1) \
40637 : case op0 : return node_allocator_-> \
40638 : allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
40639 : (s0, s1, rp0, rp1); \
40640 :
40641 3355 : string_opr_switch_statements
40642 : #undef case_stmt
40643 0 : default : return error_node();
40644 : }
40645 : }
40646 :
40647 : template <typename T0, typename T1>
40648 20042 : inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
40649 : {
40650 20042 : switch (opr)
40651 : {
40652 : #define case_stmt(op0, op1) \
40653 : case op0 : return node_allocator_-> \
40654 : allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
40655 :
40656 20042 : string_opr_switch_statements
40657 : #undef case_stmt
40658 0 : default : return error_node();
40659 : }
40660 : }
40661 :
40662 6111 : inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40663 : {
40664 6111 : std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
40665 6111 : std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
40666 :
40667 6111 : return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
40668 : }
40669 :
40670 1100 : inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40671 : {
40672 1100 : std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
40673 1100 : std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
40674 1100 : range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
40675 :
40676 1100 : static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
40677 :
40678 1100 : details::free_node(*node_allocator_,branch[0]);
40679 :
40680 2200 : return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
40681 : }
40682 :
40683 1100 : inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40684 : {
40685 1100 : std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
40686 1100 : std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
40687 1100 : range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
40688 :
40689 1100 : static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
40690 :
40691 1100 : details::free_node(*node_allocator_,branch[1]);
40692 :
40693 2200 : return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
40694 : }
40695 :
40696 150 : inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40697 : {
40698 150 : std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
40699 150 : std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
40700 150 : range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
40701 :
40702 150 : static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
40703 :
40704 150 : details::free_node(*node_allocator_,branch[1]);
40705 :
40706 300 : return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
40707 150 : }
40708 :
40709 1255 : inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40710 : {
40711 1255 : std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
40712 1255 : std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
40713 1255 : range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
40714 1255 : range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
40715 :
40716 1255 : static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
40717 1255 : static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
40718 :
40719 1255 : details::free_node(*node_allocator_,branch[0]);
40720 1255 : details::free_node(*node_allocator_,branch[1]);
40721 :
40722 2510 : return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
40723 : }
40724 :
40725 10196 : inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40726 : {
40727 10196 : std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
40728 10196 : std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
40729 :
40730 10196 : details::free_node(*node_allocator_,branch[1]);
40731 :
40732 20392 : return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
40733 10196 : }
40734 :
40735 1930 : inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40736 : {
40737 1930 : std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
40738 1930 : std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref();
40739 :
40740 1930 : details::free_node(*node_allocator_,branch[0]);
40741 :
40742 3860 : return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
40743 1930 : }
40744 :
40745 1610 : inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40746 : {
40747 1610 : std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
40748 1610 : std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref ();
40749 1610 : range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range();
40750 :
40751 1610 : static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
40752 :
40753 1610 : details::free_node(*node_allocator_,branch[0]);
40754 1610 : details::free_node(*node_allocator_,branch[1]);
40755 :
40756 3220 : return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
40757 1610 : }
40758 :
40759 1640 : inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40760 : {
40761 1640 : std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref ();
40762 1640 : std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
40763 1640 : range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range();
40764 :
40765 1640 : static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
40766 :
40767 1640 : details::free_node(*node_allocator_,branch[0]);
40768 1640 : details::free_node(*node_allocator_,branch[1]);
40769 :
40770 3280 : return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
40771 1640 : }
40772 :
40773 500 : inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40774 : {
40775 500 : std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref ();
40776 500 : std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
40777 500 : range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range();
40778 500 : range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
40779 :
40780 500 : static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
40781 500 : static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
40782 :
40783 500 : details::free_node(*node_allocator_,branch[0]);
40784 500 : details::free_node(*node_allocator_,branch[1]);
40785 :
40786 1000 : return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
40787 500 : }
40788 :
40789 6462 : inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40790 : {
40791 6462 : const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
40792 6462 : const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
40793 :
40794 6462 : expression_node_ptr result = error_node();
40795 :
40796 6462 : if (details::e_add == opr)
40797 3082 : result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
40798 3380 : else if (details::e_in == opr)
40799 160 : result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
40800 3220 : else if (details::e_like == opr)
40801 620 : result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
40802 2600 : else if (details::e_ilike == opr)
40803 795 : result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
40804 : else
40805 : {
40806 1805 : expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
40807 :
40808 1805 : const Type v = temp->value();
40809 :
40810 1805 : details::free_node(*node_allocator_,temp);
40811 :
40812 1805 : result = node_allocator_->allocate<literal_node_t>(v);
40813 : }
40814 :
40815 6462 : details::free_all_nodes(*node_allocator_,branch);
40816 :
40817 6462 : return result;
40818 6462 : }
40819 :
40820 700 : inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40821 : {
40822 700 : const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str ();
40823 700 : std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
40824 700 : range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
40825 :
40826 700 : static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
40827 :
40828 700 : details::free_node(*node_allocator_,branch[0]);
40829 700 : details::free_node(*node_allocator_,branch[1]);
40830 :
40831 1400 : return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
40832 700 : }
40833 :
40834 250 : inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40835 : {
40836 250 : std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
40837 250 : std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref ();
40838 250 : range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
40839 :
40840 250 : static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
40841 :
40842 250 : details::free_node(*node_allocator_,branch[0]);
40843 :
40844 500 : return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
40845 250 : }
40846 :
40847 500 : inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40848 : {
40849 500 : const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
40850 500 : std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref ();
40851 500 : const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
40852 500 : const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range();
40853 :
40854 500 : static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
40855 500 : static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
40856 :
40857 500 : details::free_node(*node_allocator_,branch[0]);
40858 500 : details::free_node(*node_allocator_,branch[1]);
40859 :
40860 1000 : return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
40861 500 : }
40862 :
40863 700 : inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40864 : {
40865 700 : const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
40866 700 : const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str ();
40867 700 : const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
40868 :
40869 700 : static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
40870 :
40871 700 : details::free_all_nodes(*node_allocator_,branch);
40872 :
40873 1400 : return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
40874 700 : }
40875 :
40876 1100 : inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40877 : {
40878 1100 : const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
40879 1100 : const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
40880 1100 : const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
40881 1100 : const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
40882 :
40883 1100 : static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
40884 1100 : static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
40885 :
40886 1100 : details::free_all_nodes(*node_allocator_,branch);
40887 :
40888 2200 : return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
40889 1100 : }
40890 :
40891 4846 : inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40892 : {
40893 4846 : switch (opr)
40894 : {
40895 : #define case_stmt(op0, op1) \
40896 : case op0 : return node_allocator_-> \
40897 : allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
40898 : (opr, branch[0], branch[1]); \
40899 :
40900 4846 : string_opr_switch_statements
40901 : #undef case_stmt
40902 0 : default : return error_node();
40903 : }
40904 : }
40905 :
40906 : #undef string_opr_switch_statements
40907 : #endif
40908 :
40909 : #ifndef exprtk_disable_string_capabilities
40910 45322 : inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
40911 : {
40912 45322 : if ((0 == branch[0]) || (0 == branch[1]))
40913 : {
40914 0 : details::free_all_nodes(*node_allocator_,branch);
40915 :
40916 0 : return error_node();
40917 : }
40918 :
40919 45322 : const bool b0_is_s = details::is_string_node (branch[0]);
40920 45322 : const bool b0_is_cs = details::is_const_string_node (branch[0]);
40921 45322 : const bool b0_is_sr = details::is_string_range_node (branch[0]);
40922 45322 : const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
40923 :
40924 45322 : const bool b1_is_s = details::is_string_node (branch[1]);
40925 45322 : const bool b1_is_cs = details::is_const_string_node (branch[1]);
40926 45322 : const bool b1_is_sr = details::is_string_range_node (branch[1]);
40927 45322 : const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
40928 :
40929 45322 : const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
40930 45022 : details::is_genricstring_range_node(branch[0]) ||
40931 43722 : details::is_string_concat_node (branch[0]) ||
40932 41922 : details::is_string_function_node (branch[0]) ||
40933 41904 : details::is_string_condition_node (branch[0]) ||
40934 131548 : details::is_string_ccondition_node (branch[0]) ||
40935 41204 : details::is_string_vararg_node (branch[0]) ;
40936 :
40937 45322 : const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
40938 45322 : details::is_genricstring_range_node(branch[1]) ||
40939 45322 : details::is_string_concat_node (branch[1]) ||
40940 44466 : details::is_string_function_node (branch[1]) ||
40941 44454 : details::is_string_condition_node (branch[1]) ||
40942 134692 : details::is_string_ccondition_node (branch[1]) ||
40943 44048 : details::is_string_vararg_node (branch[1]) ;
40944 :
40945 45322 : if (details::e_add == opr)
40946 : {
40947 8254 : if (!b0_is_cs || !b1_is_cs)
40948 : {
40949 5172 : return synthesize_expression<string_concat_node_t,2>(opr,branch);
40950 : }
40951 : }
40952 :
40953 40150 : if (b0_is_gen || b1_is_gen)
40954 : {
40955 4846 : return synthesize_strogen_expression(opr,branch);
40956 : }
40957 35304 : else if (b0_is_s)
40958 : {
40959 17557 : if (b1_is_s ) return synthesize_sos_expression (opr,branch);
40960 11446 : else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
40961 1250 : else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
40962 150 : else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
40963 : }
40964 17747 : else if (b0_is_cs)
40965 : {
40966 10702 : if (b1_is_s ) return synthesize_csos_expression (opr,branch);
40967 8772 : else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
40968 2310 : else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
40969 700 : else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
40970 : }
40971 7045 : else if (b0_is_sr)
40972 : {
40973 4495 : if (b1_is_s ) return synthesize_sros_expression (opr,branch);
40974 3395 : else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
40975 2140 : else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
40976 500 : else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
40977 : }
40978 2550 : else if (b0_is_csr)
40979 : {
40980 2550 : if (b1_is_s ) return synthesize_csros_expression (opr,branch);
40981 2300 : else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
40982 1800 : else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
40983 1100 : else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
40984 : }
40985 :
40986 0 : return error_node();
40987 : }
40988 : #else
40989 : inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
40990 : {
40991 : details::free_all_nodes(*node_allocator_,branch);
40992 : return error_node();
40993 : }
40994 : #endif
40995 :
40996 : #ifndef exprtk_disable_string_capabilities
40997 355 : inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
40998 : {
40999 355 : if (details::e_inrange != opr)
41000 0 : return error_node();
41001 355 : else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
41002 : {
41003 0 : details::free_all_nodes(*node_allocator_,branch);
41004 :
41005 0 : return error_node();
41006 : }
41007 355 : else if (
41008 355 : details::is_const_string_node(branch[0]) &&
41009 410 : details::is_const_string_node(branch[1]) &&
41010 55 : details::is_const_string_node(branch[2])
41011 : )
41012 : {
41013 55 : const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
41014 55 : const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
41015 55 : const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
41016 :
41017 55 : const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
41018 :
41019 55 : details::free_all_nodes(*node_allocator_,branch);
41020 :
41021 55 : return node_allocator_->allocate_c<details::literal_node<Type> >(v);
41022 55 : }
41023 300 : else if (
41024 300 : details::is_string_node(branch[0]) &&
41025 400 : details::is_string_node(branch[1]) &&
41026 100 : details::is_string_node(branch[2])
41027 : )
41028 : {
41029 50 : std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
41030 50 : std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
41031 50 : std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
41032 :
41033 : typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
41034 :
41035 50 : return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
41036 : }
41037 250 : else if (
41038 250 : details::is_const_string_node(branch[0]) &&
41039 400 : details::is_string_node(branch[1]) &&
41040 150 : details::is_const_string_node(branch[2])
41041 : )
41042 : {
41043 50 : std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
41044 50 : std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref();
41045 50 : std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
41046 :
41047 : typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
41048 :
41049 50 : details::free_node(*node_allocator_,branch[0]);
41050 50 : details::free_node(*node_allocator_,branch[2]);
41051 :
41052 50 : return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
41053 50 : }
41054 200 : else if (
41055 200 : details::is_string_node(branch[0]) &&
41056 250 : details::is_const_string_node(branch[1]) &&
41057 50 : details::is_string_node(branch[2])
41058 : )
41059 : {
41060 50 : std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref();
41061 50 : std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
41062 50 : std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref();
41063 :
41064 : typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
41065 :
41066 50 : details::free_node(*node_allocator_,branch[1]);
41067 :
41068 50 : return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
41069 50 : }
41070 150 : else if (
41071 150 : details::is_string_node(branch[0]) &&
41072 200 : details::is_string_node(branch[1]) &&
41073 50 : details::is_const_string_node(branch[2])
41074 : )
41075 : {
41076 50 : std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref();
41077 50 : std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref();
41078 50 : std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
41079 :
41080 : typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
41081 :
41082 50 : details::free_node(*node_allocator_,branch[2]);
41083 :
41084 50 : return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
41085 50 : }
41086 100 : else if (
41087 100 : details::is_const_string_node(branch[0]) &&
41088 200 : details:: is_string_node(branch[1]) &&
41089 100 : details:: is_string_node(branch[2])
41090 : )
41091 : {
41092 100 : std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
41093 100 : std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref();
41094 100 : std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref();
41095 :
41096 : typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
41097 :
41098 100 : details::free_node(*node_allocator_,branch[0]);
41099 :
41100 100 : return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
41101 100 : }
41102 : else
41103 0 : return error_node();
41104 : }
41105 : #else
41106 : inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
41107 : {
41108 : details::free_all_nodes(*node_allocator_,branch);
41109 : return error_node();
41110 : }
41111 : #endif
41112 :
41113 255 : inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
41114 : {
41115 : /*
41116 : Note: The following are the type promotion rules
41117 : that relate to operations that include 'null':
41118 : 0. null ==/!= null --> true false
41119 : 1. null operation null --> null
41120 : 2. x ==/!= null --> true/false
41121 : 3. null ==/!= x --> true/false
41122 : 4. x operation null --> x
41123 : 5. null operation x --> x
41124 : */
41125 :
41126 : typedef typename details::null_eq_node<T> nulleq_node_t;
41127 :
41128 255 : const bool b0_null = details::is_null_node(branch[0]);
41129 255 : const bool b1_null = details::is_null_node(branch[1]);
41130 :
41131 255 : if (b0_null && b1_null)
41132 : {
41133 60 : expression_node_ptr result = error_node();
41134 :
41135 60 : if (details::e_eq == operation)
41136 60 : result = node_allocator_->allocate_c<literal_node_t>(T(1));
41137 0 : else if (details::e_ne == operation)
41138 0 : result = node_allocator_->allocate_c<literal_node_t>(T(0));
41139 :
41140 60 : if (result)
41141 : {
41142 60 : details::free_node(*node_allocator_,branch[0]);
41143 60 : details::free_node(*node_allocator_,branch[1]);
41144 :
41145 60 : return result;
41146 : }
41147 :
41148 0 : details::free_node(*node_allocator_,branch[1]);
41149 :
41150 0 : return branch[0];
41151 : }
41152 195 : else if (details::e_eq == operation)
41153 : {
41154 195 : expression_node_ptr result = node_allocator_->
41155 195 : allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
41156 :
41157 195 : details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
41158 :
41159 195 : return result;
41160 : }
41161 0 : else if (details::e_ne == operation)
41162 : {
41163 0 : expression_node_ptr result = node_allocator_->
41164 0 : allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
41165 :
41166 0 : details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
41167 :
41168 0 : return result;
41169 : }
41170 0 : else if (b0_null)
41171 : {
41172 0 : details::free_node(*node_allocator_,branch[0]);
41173 0 : branch[0] = branch[1];
41174 0 : branch[1] = error_node();
41175 : }
41176 0 : else if (b1_null)
41177 : {
41178 0 : details::free_node(*node_allocator_,branch[1]);
41179 0 : branch[1] = error_node();
41180 : }
41181 :
41182 0 : if (
41183 0 : (details::e_add == operation) || (details::e_sub == operation) ||
41184 0 : (details::e_mul == operation) || (details::e_div == operation) ||
41185 0 : (details::e_mod == operation) || (details::e_pow == operation)
41186 : )
41187 : {
41188 0 : return branch[0];
41189 : }
41190 :
41191 0 : details::free_node(*node_allocator_, branch[0]);
41192 :
41193 0 : if (
41194 0 : (details::e_lt == operation) || (details::e_lte == operation) ||
41195 0 : (details::e_gt == operation) || (details::e_gte == operation) ||
41196 0 : (details::e_and == operation) || (details::e_nand == operation) ||
41197 0 : (details::e_or == operation) || (details::e_nor == operation) ||
41198 0 : (details::e_xor == operation) || (details::e_xnor == operation) ||
41199 0 : (details::e_in == operation) || (details::e_like == operation) ||
41200 0 : (details::e_ilike == operation)
41201 : )
41202 : {
41203 0 : return node_allocator_->allocate_c<literal_node_t>(T(0));
41204 : }
41205 :
41206 0 : return node_allocator_->allocate<details::null_node<Type> >();
41207 : }
41208 :
41209 : template <typename NodeType, std::size_t N>
41210 622242 : inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
41211 : {
41212 622242 : if (
41213 622242 : (details::e_in == operation) ||
41214 622230 : (details::e_like == operation) ||
41215 622230 : (details::e_ilike == operation)
41216 : )
41217 : {
41218 12 : free_all_nodes(*node_allocator_,branch);
41219 :
41220 12 : return error_node();
41221 : }
41222 622230 : else if (!details::all_nodes_valid<N>(branch))
41223 : {
41224 0 : free_all_nodes(*node_allocator_,branch);
41225 :
41226 0 : return error_node();
41227 : }
41228 622230 : else if ((details::e_default != operation))
41229 : {
41230 : // Attempt simple constant folding optimisation.
41231 622230 : expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
41232 :
41233 622230 : if (is_constant_foldable<N>(branch))
41234 : {
41235 299252 : const Type v = expression_point->value();
41236 299252 : details::free_node(*node_allocator_,expression_point);
41237 :
41238 299252 : return node_allocator_->allocate<literal_node_t>(v);
41239 : }
41240 :
41241 322978 : if (expression_point && expression_point->valid())
41242 : {
41243 322978 : return expression_point;
41244 : }
41245 :
41246 0 : parser_->set_error(parser_error::make_error(
41247 : parser_error::e_parser,
41248 0 : token_t(),
41249 : "ERR273 - Failed to synthesize node: NodeType",
41250 : exprtk_error_location));
41251 :
41252 0 : details::free_node(*node_allocator_, expression_point);
41253 : }
41254 :
41255 0 : return error_node();
41256 : }
41257 :
41258 : template <typename NodeType, std::size_t N>
41259 60380 : inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
41260 : {
41261 60380 : if (!details::all_nodes_valid<N>(branch))
41262 : {
41263 0 : free_all_nodes(*node_allocator_,branch);
41264 :
41265 0 : return error_node();
41266 : }
41267 :
41268 : typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
41269 :
41270 : // Attempt simple constant folding optimisation.
41271 :
41272 60380 : expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
41273 60380 : function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
41274 :
41275 60380 : if (0 == func_node_ptr)
41276 : {
41277 0 : free_all_nodes(*node_allocator_,branch);
41278 :
41279 0 : return error_node();
41280 : }
41281 : else
41282 60380 : func_node_ptr->init_branches(branch);
41283 :
41284 60380 : if (is_constant_foldable<N>(branch) && !f->has_side_effects())
41285 : {
41286 120 : Type v = expression_point->value();
41287 120 : details::free_node(*node_allocator_,expression_point);
41288 :
41289 120 : return node_allocator_->allocate<literal_node_t>(v);
41290 : }
41291 :
41292 120520 : parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
41293 :
41294 60260 : return expression_point;
41295 : }
41296 :
41297 : bool strength_reduction_enabled_;
41298 : details::node_allocator* node_allocator_;
41299 : synthesize_map_t synthesize_map_;
41300 : unary_op_map_t* unary_op_map_;
41301 : binary_op_map_t* binary_op_map_;
41302 : inv_binary_op_map_t* inv_binary_op_map_;
41303 : sf3_map_t* sf3_map_;
41304 : sf4_map_t* sf4_map_;
41305 : parser_t* parser_;
41306 : }; // class expression_generator
41307 :
41308 43680 : inline void set_error(const parser_error::type& error_type)
41309 : {
41310 43680 : error_list_.push_back(error_type);
41311 43680 : }
41312 :
41313 : inline void remove_last_error()
41314 : {
41315 : if (!error_list_.empty())
41316 : {
41317 : error_list_.pop_back();
41318 : }
41319 : }
41320 :
41321 0 : inline void set_synthesis_error(const std::string& synthesis_error_message)
41322 : {
41323 0 : if (synthesis_error_.empty())
41324 : {
41325 0 : synthesis_error_ = synthesis_error_message;
41326 : }
41327 0 : }
41328 :
41329 359159 : inline void register_local_vars(expression<T>& e)
41330 : {
41331 450721 : for (std::size_t i = 0; i < sem_.size(); ++i)
41332 : {
41333 91562 : scope_element& se = sem_.get_element(i);
41334 :
41335 91562 : if (
41336 91562 : (scope_element::e_variable == se.type) ||
41337 46690 : (scope_element::e_literal == se.type) ||
41338 44055 : (scope_element::e_vecelem == se.type)
41339 : )
41340 : {
41341 58561 : if (se.var_node)
41342 : {
41343 58561 : e.register_local_var(se.var_node);
41344 : }
41345 :
41346 58561 : if (se.data)
41347 : {
41348 44872 : e.register_local_data(se.data, 1, 0);
41349 : }
41350 : }
41351 33001 : else if (scope_element::e_vector == se.type)
41352 : {
41353 23261 : if (se.vec_node)
41354 : {
41355 23261 : e.register_local_var(se.vec_node);
41356 : }
41357 :
41358 23261 : if (se.data)
41359 : {
41360 23261 : e.register_local_data(se.data, se.size, 1);
41361 : }
41362 : }
41363 : #ifndef exprtk_disable_string_capabilities
41364 9740 : else if (scope_element::e_string == se.type)
41365 : {
41366 9740 : if (se.str_node)
41367 : {
41368 9740 : e.register_local_var(se.str_node);
41369 : }
41370 :
41371 9740 : if (se.data)
41372 : {
41373 9740 : e.register_local_data(se.data, se.size, 2);
41374 : }
41375 : }
41376 : #endif
41377 :
41378 91562 : se.var_node = 0;
41379 91562 : se.vec_node = 0;
41380 : #ifndef exprtk_disable_string_capabilities
41381 91562 : se.str_node = 0;
41382 : #endif
41383 91562 : se.data = 0;
41384 91562 : se.ref_count = 0;
41385 91562 : se.active = false;
41386 : }
41387 359159 : }
41388 :
41389 359159 : inline void register_return_results(expression<T>& e)
41390 : {
41391 359159 : e.register_return_results(results_context_);
41392 359159 : results_context_ = 0;
41393 359159 : }
41394 :
41395 108660 : inline void load_unary_operations_map(unary_op_map_t& m)
41396 : {
41397 : #define register_unary_op(Op, UnaryFunctor) \
41398 : m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
41399 :
41400 108660 : register_unary_op(details::e_abs , details::abs_op )
41401 108660 : register_unary_op(details::e_acos , details::acos_op )
41402 108660 : register_unary_op(details::e_acosh , details::acosh_op)
41403 108660 : register_unary_op(details::e_asin , details::asin_op )
41404 108660 : register_unary_op(details::e_asinh , details::asinh_op)
41405 108660 : register_unary_op(details::e_atanh , details::atanh_op)
41406 108660 : register_unary_op(details::e_ceil , details::ceil_op )
41407 108660 : register_unary_op(details::e_cos , details::cos_op )
41408 108660 : register_unary_op(details::e_cosh , details::cosh_op )
41409 108660 : register_unary_op(details::e_exp , details::exp_op )
41410 108660 : register_unary_op(details::e_expm1 , details::expm1_op)
41411 108660 : register_unary_op(details::e_floor , details::floor_op)
41412 108660 : register_unary_op(details::e_log , details::log_op )
41413 108660 : register_unary_op(details::e_log10 , details::log10_op)
41414 108660 : register_unary_op(details::e_log2 , details::log2_op )
41415 108660 : register_unary_op(details::e_log1p , details::log1p_op)
41416 108660 : register_unary_op(details::e_neg , details::neg_op )
41417 108660 : register_unary_op(details::e_pos , details::pos_op )
41418 108660 : register_unary_op(details::e_round , details::round_op)
41419 108660 : register_unary_op(details::e_sin , details::sin_op )
41420 108660 : register_unary_op(details::e_sinc , details::sinc_op )
41421 108660 : register_unary_op(details::e_sinh , details::sinh_op )
41422 108660 : register_unary_op(details::e_sqrt , details::sqrt_op )
41423 108660 : register_unary_op(details::e_tan , details::tan_op )
41424 108660 : register_unary_op(details::e_tanh , details::tanh_op )
41425 108660 : register_unary_op(details::e_cot , details::cot_op )
41426 108660 : register_unary_op(details::e_sec , details::sec_op )
41427 108660 : register_unary_op(details::e_csc , details::csc_op )
41428 108660 : register_unary_op(details::e_r2d , details::r2d_op )
41429 108660 : register_unary_op(details::e_d2r , details::d2r_op )
41430 108660 : register_unary_op(details::e_d2g , details::d2g_op )
41431 108660 : register_unary_op(details::e_g2d , details::g2d_op )
41432 108660 : register_unary_op(details::e_notl , details::notl_op )
41433 108660 : register_unary_op(details::e_sgn , details::sgn_op )
41434 108660 : register_unary_op(details::e_erf , details::erf_op )
41435 108660 : register_unary_op(details::e_erfc , details::erfc_op )
41436 108660 : register_unary_op(details::e_ncdf , details::ncdf_op )
41437 108660 : register_unary_op(details::e_frac , details::frac_op )
41438 108660 : register_unary_op(details::e_trunc , details::trunc_op)
41439 : #undef register_unary_op
41440 108660 : }
41441 :
41442 108660 : inline void load_binary_operations_map(binary_op_map_t& m)
41443 : {
41444 : typedef typename binary_op_map_t::value_type value_type;
41445 :
41446 : #define register_binary_op(Op, BinaryFunctor) \
41447 : m.insert(value_type(Op,BinaryFunctor<T>::process)); \
41448 :
41449 108660 : register_binary_op(details::e_add , details::add_op )
41450 108660 : register_binary_op(details::e_sub , details::sub_op )
41451 108660 : register_binary_op(details::e_mul , details::mul_op )
41452 108660 : register_binary_op(details::e_div , details::div_op )
41453 108660 : register_binary_op(details::e_mod , details::mod_op )
41454 108660 : register_binary_op(details::e_pow , details::pow_op )
41455 108660 : register_binary_op(details::e_lt , details::lt_op )
41456 108660 : register_binary_op(details::e_lte , details::lte_op )
41457 108660 : register_binary_op(details::e_gt , details::gt_op )
41458 108660 : register_binary_op(details::e_gte , details::gte_op )
41459 108660 : register_binary_op(details::e_eq , details::eq_op )
41460 108660 : register_binary_op(details::e_ne , details::ne_op )
41461 108660 : register_binary_op(details::e_and , details::and_op )
41462 108660 : register_binary_op(details::e_nand , details::nand_op)
41463 108660 : register_binary_op(details::e_or , details::or_op )
41464 108660 : register_binary_op(details::e_nor , details::nor_op )
41465 108660 : register_binary_op(details::e_xor , details::xor_op )
41466 108660 : register_binary_op(details::e_xnor , details::xnor_op)
41467 : #undef register_binary_op
41468 108660 : }
41469 :
41470 108660 : inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
41471 : {
41472 : typedef typename inv_binary_op_map_t::value_type value_type;
41473 :
41474 : #define register_binary_op(Op, BinaryFunctor) \
41475 : m.insert(value_type(BinaryFunctor<T>::process,Op)); \
41476 :
41477 108660 : register_binary_op(details::e_add , details::add_op )
41478 108660 : register_binary_op(details::e_sub , details::sub_op )
41479 108660 : register_binary_op(details::e_mul , details::mul_op )
41480 108660 : register_binary_op(details::e_div , details::div_op )
41481 108660 : register_binary_op(details::e_mod , details::mod_op )
41482 108660 : register_binary_op(details::e_pow , details::pow_op )
41483 108660 : register_binary_op(details::e_lt , details::lt_op )
41484 108660 : register_binary_op(details::e_lte , details::lte_op )
41485 108660 : register_binary_op(details::e_gt , details::gt_op )
41486 108660 : register_binary_op(details::e_gte , details::gte_op )
41487 108660 : register_binary_op(details::e_eq , details::eq_op )
41488 108660 : register_binary_op(details::e_ne , details::ne_op )
41489 108660 : register_binary_op(details::e_and , details::and_op )
41490 108660 : register_binary_op(details::e_nand , details::nand_op)
41491 108660 : register_binary_op(details::e_or , details::or_op )
41492 108660 : register_binary_op(details::e_nor , details::nor_op )
41493 108660 : register_binary_op(details::e_xor , details::xor_op )
41494 108660 : register_binary_op(details::e_xnor , details::xnor_op)
41495 : #undef register_binary_op
41496 108660 : }
41497 :
41498 108660 : inline void load_sf3_map(sf3_map_t& sf3_map)
41499 : {
41500 : typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
41501 :
41502 : #define register_sf3(Op) \
41503 : sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
41504 :
41505 108660 : register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
41506 108660 : register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
41507 108660 : register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
41508 108660 : register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
41509 108660 : register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
41510 108660 : register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
41511 108660 : register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
41512 108660 : register_sf3(28) register_sf3(29) register_sf3(30)
41513 : #undef register_sf3
41514 :
41515 : #define register_sf3_extid(Id, Op) \
41516 : sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
41517 :
41518 217320 : register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
41519 : #undef register_sf3_extid
41520 108660 : }
41521 :
41522 108660 : inline void load_sf4_map(sf4_map_t& sf4_map)
41523 : {
41524 : typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
41525 :
41526 : #define register_sf4(Op) \
41527 : sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
41528 :
41529 108660 : register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
41530 108660 : register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
41531 108660 : register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
41532 108660 : register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
41533 108660 : register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
41534 108660 : register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
41535 108660 : register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
41536 108660 : register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
41537 108660 : register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
41538 : #undef register_sf4
41539 :
41540 : #define register_sf4ext(Op) \
41541 : sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
41542 :
41543 108660 : register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
41544 108660 : register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
41545 108660 : register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
41546 108660 : register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
41547 108660 : register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
41548 108660 : register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
41549 108660 : register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
41550 108660 : register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
41551 108660 : register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
41552 108660 : register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
41553 108660 : register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
41554 108660 : register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
41555 108660 : register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
41556 108660 : register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
41557 108660 : register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
41558 108660 : register_sf4ext(60) register_sf4ext(61)
41559 : #undef register_sf4ext
41560 108660 : }
41561 :
41562 116 : inline results_context_t& results_ctx()
41563 : {
41564 116 : if (0 == results_context_)
41565 : {
41566 111 : results_context_ = new results_context_t();
41567 : }
41568 :
41569 116 : return (*results_context_);
41570 : }
41571 :
41572 391685 : inline void return_cleanup()
41573 : {
41574 : #ifndef exprtk_disable_return_statement
41575 391685 : if (results_context_)
41576 : {
41577 0 : delete results_context_;
41578 0 : results_context_ = 0;
41579 : }
41580 :
41581 391685 : state_.return_stmt_present = false;
41582 : #endif
41583 391685 : }
41584 :
41585 : private:
41586 :
41587 : parser(const parser<T>&) exprtk_delete;
41588 : parser<T>& operator=(const parser<T>&) exprtk_delete;
41589 :
41590 : settings_store settings_;
41591 : expression_generator<T> expression_generator_;
41592 : details::node_allocator node_allocator_;
41593 : symtab_store symtab_store_;
41594 : dependent_entity_collector dec_;
41595 : std::deque<parser_error::type> error_list_;
41596 : std::deque<bool> brkcnt_list_;
41597 : parser_state state_;
41598 : bool resolve_unknown_symbol_;
41599 : results_context_t* results_context_;
41600 : unknown_symbol_resolver* unknown_symbol_resolver_;
41601 : unknown_symbol_resolver default_usr_;
41602 : base_ops_map_t base_ops_map_;
41603 : unary_op_map_t unary_op_map_;
41604 : binary_op_map_t binary_op_map_;
41605 : inv_binary_op_map_t inv_binary_op_map_;
41606 : sf3_map_t sf3_map_;
41607 : sf4_map_t sf4_map_;
41608 : std::string synthesis_error_;
41609 : scope_element_manager sem_;
41610 : std::vector<state_t> current_state_stack_;
41611 :
41612 : immutable_memory_map_t immutable_memory_map_;
41613 : immutable_symtok_map_t immutable_symtok_map_;
41614 :
41615 : lexer::helper::helper_assembly helper_assembly_;
41616 :
41617 : lexer::helper::commutative_inserter commutative_inserter_;
41618 : lexer::helper::operator_joiner operator_joiner_2_;
41619 : lexer::helper::operator_joiner operator_joiner_3_;
41620 : lexer::helper::symbol_replacer symbol_replacer_;
41621 : lexer::helper::bracket_checker bracket_checker_;
41622 : lexer::helper::numeric_checker<T> numeric_checker_;
41623 : lexer::helper::sequence_validator sequence_validator_;
41624 : lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
41625 :
41626 : loop_runtime_check_ptr loop_runtime_check_;
41627 : vector_access_runtime_check_ptr vector_access_runtime_check_;
41628 : compilation_check_ptr compilation_check_ptr_;
41629 : assert_check_ptr assert_check_;
41630 : std::set<std::string> assert_ids_;
41631 :
41632 : template <typename ParserType>
41633 : friend void details::disable_type_checking(ParserType& p);
41634 : }; // class parser
41635 :
41636 : namespace details
41637 : {
41638 : template <typename T>
41639 : struct collector_helper
41640 : {
41641 : typedef exprtk::symbol_table<T> symbol_table_t;
41642 : typedef exprtk::expression<T> expression_t;
41643 : typedef exprtk::parser<T> parser_t;
41644 : typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
41645 : typedef typename parser_t::unknown_symbol_resolver usr_t;
41646 :
41647 : struct resolve_as_vector : public usr_t
41648 : {
41649 : typedef exprtk::parser<T> parser_t;
41650 :
41651 : using usr_t::process;
41652 :
41653 4 : resolve_as_vector()
41654 4 : : usr_t(usr_t::e_usrmode_extended)
41655 4 : {}
41656 :
41657 6 : virtual bool process(const std::string& unknown_symbol,
41658 : symbol_table_t& symbol_table,
41659 : std::string&) exprtk_override
41660 : {
41661 : static T v[1];
41662 6 : symbol_table.add_vector(unknown_symbol,v);
41663 6 : return true;
41664 : }
41665 : };
41666 :
41667 4 : static inline bool collection_pass(const std::string& expression_string,
41668 : std::set<std::string>& symbol_set,
41669 : const bool collect_variables,
41670 : const bool collect_functions,
41671 : const bool vector_pass,
41672 : symbol_table_t& ext_symbol_table)
41673 : {
41674 4 : symbol_table_t symbol_table;
41675 4 : expression_t expression;
41676 4 : parser_t parser;
41677 :
41678 4 : resolve_as_vector vect_resolver;
41679 :
41680 4 : expression.register_symbol_table(symbol_table );
41681 4 : expression.register_symbol_table(ext_symbol_table);
41682 :
41683 4 : if (vector_pass)
41684 2 : parser.enable_unknown_symbol_resolver(&vect_resolver);
41685 : else
41686 2 : parser.enable_unknown_symbol_resolver();
41687 :
41688 4 : if (collect_variables)
41689 2 : parser.dec().collect_variables() = true;
41690 :
41691 4 : if (collect_functions)
41692 2 : parser.dec().collect_functions() = true;
41693 :
41694 4 : bool pass_result = false;
41695 :
41696 4 : details::disable_type_checking(parser);
41697 :
41698 4 : if (parser.compile(expression_string, expression))
41699 : {
41700 2 : pass_result = true;
41701 :
41702 2 : std::deque<symbol_t> symb_list;
41703 2 : parser.dec().symbols(symb_list);
41704 :
41705 9 : for (std::size_t i = 0; i < symb_list.size(); ++i)
41706 : {
41707 7 : symbol_set.insert(symb_list[i].first);
41708 : }
41709 2 : }
41710 :
41711 4 : return pass_result;
41712 4 : }
41713 : };
41714 : }
41715 :
41716 : template <typename Allocator,
41717 : template <typename, typename> class Sequence>
41718 1 : inline bool collect_variables(const std::string& expression,
41719 : Sequence<std::string, Allocator>& symbol_list)
41720 : {
41721 : typedef double T;
41722 : typedef details::collector_helper<T> collect_t;
41723 :
41724 1 : collect_t::symbol_table_t null_symbol_table;
41725 :
41726 1 : std::set<std::string> symbol_set;
41727 :
41728 : const bool variable_pass = collect_t::collection_pass
41729 1 : (expression, symbol_set, true, false, false, null_symbol_table);
41730 : const bool vector_pass = collect_t::collection_pass
41731 1 : (expression, symbol_set, true, false, true, null_symbol_table);
41732 :
41733 1 : if (!variable_pass && !vector_pass)
41734 0 : return false;
41735 :
41736 1 : std::set<std::string>::iterator itr = symbol_set.begin();
41737 :
41738 5 : while (symbol_set.end() != itr)
41739 : {
41740 4 : symbol_list.push_back(*itr);
41741 4 : ++itr;
41742 : }
41743 :
41744 1 : return true;
41745 1 : }
41746 :
41747 : template <typename T,
41748 : typename Allocator,
41749 : template <typename, typename> class Sequence>
41750 : inline bool collect_variables(const std::string& expression,
41751 : exprtk::symbol_table<T>& extrnl_symbol_table,
41752 : Sequence<std::string, Allocator>& symbol_list)
41753 : {
41754 : typedef details::collector_helper<T> collect_t;
41755 :
41756 : std::set<std::string> symbol_set;
41757 :
41758 : const bool variable_pass = collect_t::collection_pass
41759 : (expression, symbol_set, true, false, false, extrnl_symbol_table);
41760 : const bool vector_pass = collect_t::collection_pass
41761 : (expression, symbol_set, true, false, true, extrnl_symbol_table);
41762 :
41763 : if (!variable_pass && !vector_pass)
41764 : return false;
41765 :
41766 : std::set<std::string>::iterator itr = symbol_set.begin();
41767 :
41768 : while (symbol_set.end() != itr)
41769 : {
41770 : symbol_list.push_back(*itr);
41771 : ++itr;
41772 : }
41773 :
41774 : return true;
41775 : }
41776 :
41777 : template <typename Allocator,
41778 : template <typename, typename> class Sequence>
41779 1 : inline bool collect_functions(const std::string& expression,
41780 : Sequence<std::string, Allocator>& symbol_list)
41781 : {
41782 : typedef double T;
41783 : typedef details::collector_helper<T> collect_t;
41784 :
41785 1 : collect_t::symbol_table_t null_symbol_table;
41786 :
41787 1 : std::set<std::string> symbol_set;
41788 :
41789 : const bool variable_pass = collect_t::collection_pass
41790 1 : (expression, symbol_set, false, true, false, null_symbol_table);
41791 : const bool vector_pass = collect_t::collection_pass
41792 1 : (expression, symbol_set, false, true, true, null_symbol_table);
41793 :
41794 1 : if (!variable_pass && !vector_pass)
41795 0 : return false;
41796 :
41797 1 : std::set<std::string>::iterator itr = symbol_set.begin();
41798 :
41799 4 : while (symbol_set.end() != itr)
41800 : {
41801 3 : symbol_list.push_back(*itr);
41802 3 : ++itr;
41803 : }
41804 :
41805 1 : return true;
41806 1 : }
41807 :
41808 : template <typename T,
41809 : typename Allocator,
41810 : template <typename, typename> class Sequence>
41811 : inline bool collect_functions(const std::string& expression,
41812 : exprtk::symbol_table<T>& extrnl_symbol_table,
41813 : Sequence<std::string, Allocator>& symbol_list)
41814 : {
41815 : typedef details::collector_helper<T> collect_t;
41816 :
41817 : std::set<std::string> symbol_set;
41818 :
41819 : const bool variable_pass = collect_t::collection_pass
41820 : (expression, symbol_set, false, true, false, extrnl_symbol_table);
41821 : const bool vector_pass = collect_t::collection_pass
41822 : (expression, symbol_set, false, true, true, extrnl_symbol_table);
41823 :
41824 : if (!variable_pass && !vector_pass)
41825 : return false;
41826 :
41827 : std::set<std::string>::iterator itr = symbol_set.begin();
41828 :
41829 : while (symbol_set.end() != itr)
41830 : {
41831 : symbol_list.push_back(*itr);
41832 : ++itr;
41833 : }
41834 :
41835 : return true;
41836 : }
41837 :
41838 : template <typename T>
41839 2 : inline T integrate(const expression<T>& e,
41840 : T& x,
41841 : const T& r0, const T& r1,
41842 : const std::size_t number_of_intervals = 1000000)
41843 : {
41844 2 : if (r0 > r1)
41845 0 : return T(0);
41846 :
41847 2 : const T h = (r1 - r0) / (T(2) * number_of_intervals);
41848 2 : T total_area = T(0);
41849 :
41850 2000002 : for (std::size_t i = 0; i < number_of_intervals; ++i)
41851 : {
41852 2000000 : x = r0 + T(2) * i * h;
41853 2000000 : const T y0 = e.value(); x += h;
41854 2000000 : const T y1 = e.value(); x += h;
41855 2000000 : const T y2 = e.value(); x += h;
41856 2000000 : total_area += h * (y0 + T(4) * y1 + y2) / T(3);
41857 : }
41858 :
41859 2 : return total_area;
41860 : }
41861 :
41862 : template <typename T>
41863 1 : inline T integrate(const expression<T>& e,
41864 : const std::string& variable_name,
41865 : const T& r0, const T& r1,
41866 : const std::size_t number_of_intervals = 1000000)
41867 : {
41868 1 : const symbol_table<T>& sym_table = e.get_symbol_table();
41869 :
41870 1 : if (!sym_table.valid())
41871 : {
41872 0 : return std::numeric_limits<T>::quiet_NaN();
41873 : }
41874 :
41875 1 : details::variable_node<T>* var = sym_table.get_variable(variable_name);
41876 :
41877 1 : if (var)
41878 : {
41879 1 : T& x = var->ref();
41880 1 : const T x_original = x;
41881 1 : const T result = integrate(e, x, r0, r1, number_of_intervals);
41882 1 : x = x_original;
41883 :
41884 1 : return result;
41885 : }
41886 :
41887 0 : return std::numeric_limits<T>::quiet_NaN();
41888 : }
41889 :
41890 : template <typename T>
41891 8000000 : inline T derivative(const expression<T>& e,
41892 : T& x,
41893 4000000 : const T& h = T(0.00000001))
41894 : {
41895 8000000 : const T x_init = x;
41896 8000000 : const T _2h = T(2) * h;
41897 :
41898 8000000 : x = x_init + _2h;
41899 8000000 : const T y0 = e.value();
41900 8000000 : x = x_init + h;
41901 8000000 : const T y1 = e.value();
41902 8000000 : x = x_init - h;
41903 8000000 : const T y2 = e.value();
41904 8000000 : x = x_init - _2h;
41905 8000000 : const T y3 = e.value();
41906 8000000 : x = x_init;
41907 :
41908 8000000 : return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
41909 : }
41910 :
41911 : template <typename T>
41912 8000000 : inline T second_derivative(const expression<T>& e,
41913 : T& x,
41914 4000000 : const T& h = T(0.00001))
41915 : {
41916 8000000 : const T x_init = x;
41917 8000000 : const T _2h = T(2) * h;
41918 :
41919 8000000 : const T y = e.value();
41920 8000000 : x = x_init + _2h;
41921 8000000 : const T y0 = e.value();
41922 8000000 : x = x_init + h;
41923 8000000 : const T y1 = e.value();
41924 8000000 : x = x_init - h;
41925 8000000 : const T y2 = e.value();
41926 8000000 : x = x_init - _2h;
41927 8000000 : const T y3 = e.value();
41928 8000000 : x = x_init;
41929 :
41930 8000000 : return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
41931 : }
41932 :
41933 : template <typename T>
41934 8000000 : inline T third_derivative(const expression<T>& e,
41935 : T& x,
41936 4000000 : const T& h = T(0.0001))
41937 : {
41938 8000000 : const T x_init = x;
41939 8000000 : const T _2h = T(2) * h;
41940 :
41941 8000000 : x = x_init + _2h;
41942 8000000 : const T y0 = e.value();
41943 8000000 : x = x_init + h;
41944 8000000 : const T y1 = e.value();
41945 8000000 : x = x_init - h;
41946 8000000 : const T y2 = e.value();
41947 8000000 : x = x_init - _2h;
41948 8000000 : const T y3 = e.value();
41949 8000000 : x = x_init;
41950 :
41951 8000000 : return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
41952 : }
41953 :
41954 : template <typename T>
41955 4000000 : inline T derivative(const expression<T>& e,
41956 : const std::string& variable_name,
41957 8000000 : const T& h = T(0.00000001))
41958 : {
41959 4000000 : const symbol_table<T>& sym_table = e.get_symbol_table();
41960 :
41961 4000000 : if (!sym_table.valid())
41962 : {
41963 0 : return std::numeric_limits<T>::quiet_NaN();
41964 : }
41965 :
41966 4000000 : details::variable_node<T>* var = sym_table.get_variable(variable_name);
41967 :
41968 4000000 : if (var)
41969 : {
41970 4000000 : T& x = var->ref();
41971 4000000 : const T x_original = x;
41972 4000000 : const T result = derivative(e, x, h);
41973 4000000 : x = x_original;
41974 :
41975 4000000 : return result;
41976 : }
41977 :
41978 0 : return std::numeric_limits<T>::quiet_NaN();
41979 : }
41980 :
41981 : template <typename T>
41982 4000000 : inline T second_derivative(const expression<T>& e,
41983 : const std::string& variable_name,
41984 8000000 : const T& h = T(0.00001))
41985 : {
41986 4000000 : const symbol_table<T>& sym_table = e.get_symbol_table();
41987 :
41988 4000000 : if (!sym_table.valid())
41989 : {
41990 0 : return std::numeric_limits<T>::quiet_NaN();
41991 : }
41992 :
41993 4000000 : details::variable_node<T>* var = sym_table.get_variable(variable_name);
41994 :
41995 4000000 : if (var)
41996 : {
41997 4000000 : T& x = var->ref();
41998 4000000 : const T x_original = x;
41999 4000000 : const T result = second_derivative(e, x, h);
42000 4000000 : x = x_original;
42001 :
42002 4000000 : return result;
42003 : }
42004 :
42005 0 : return std::numeric_limits<T>::quiet_NaN();
42006 : }
42007 :
42008 : template <typename T>
42009 4000000 : inline T third_derivative(const expression<T>& e,
42010 : const std::string& variable_name,
42011 8000000 : const T& h = T(0.0001))
42012 : {
42013 4000000 : const symbol_table<T>& sym_table = e.get_symbol_table();
42014 :
42015 4000000 : if (!sym_table.valid())
42016 : {
42017 0 : return std::numeric_limits<T>::quiet_NaN();
42018 : }
42019 :
42020 4000000 : details::variable_node<T>* var = sym_table.get_variable(variable_name);
42021 :
42022 4000000 : if (var)
42023 : {
42024 4000000 : T& x = var->ref();
42025 4000000 : const T x_original = x;
42026 4000000 : const T result = third_derivative(e, x, h);
42027 4000000 : x = x_original;
42028 :
42029 4000000 : return result;
42030 : }
42031 :
42032 0 : return std::numeric_limits<T>::quiet_NaN();
42033 : }
42034 :
42035 : /*
42036 : Note: The following 'compute' routines are simple helpers,
42037 : for quickly setting up the required pieces of code in order
42038 : to evaluate an expression. By virtue of how they operate
42039 : there will be an overhead with regards to their setup and
42040 : teardown and hence should not be used in time critical
42041 : sections of code.
42042 : Furthermore they only assume a small sub set of variables,
42043 : no string variables or user defined functions.
42044 : */
42045 : template <typename T>
42046 : inline bool compute(const std::string& expression_string, T& result)
42047 : {
42048 : // No variables
42049 : symbol_table<T> symbol_table;
42050 : symbol_table.add_constants();
42051 :
42052 : expression<T> expression;
42053 : expression.register_symbol_table(symbol_table);
42054 :
42055 : parser<T> parser;
42056 :
42057 : if (parser.compile(expression_string,expression))
42058 : {
42059 : result = expression.value();
42060 :
42061 : return true;
42062 : }
42063 : else
42064 : return false;
42065 : }
42066 :
42067 : template <typename T>
42068 : inline bool compute(const std::string& expression_string,
42069 : const T& x,
42070 : T& result)
42071 : {
42072 : // Only 'x'
42073 : static const std::string x_var("x");
42074 :
42075 : symbol_table<T> symbol_table;
42076 : symbol_table.add_constants();
42077 : symbol_table.add_constant(x_var,x);
42078 :
42079 : expression<T> expression;
42080 : expression.register_symbol_table(symbol_table);
42081 :
42082 : parser<T> parser;
42083 :
42084 : if (parser.compile(expression_string,expression))
42085 : {
42086 : result = expression.value();
42087 :
42088 : return true;
42089 : }
42090 : else
42091 : return false;
42092 : }
42093 :
42094 : template <typename T>
42095 : inline bool compute(const std::string& expression_string,
42096 : const T&x, const T& y,
42097 : T& result)
42098 : {
42099 : // Only 'x' and 'y'
42100 : static const std::string x_var("x");
42101 : static const std::string y_var("y");
42102 :
42103 : symbol_table<T> symbol_table;
42104 : symbol_table.add_constants();
42105 : symbol_table.add_constant(x_var,x);
42106 : symbol_table.add_constant(y_var,y);
42107 :
42108 : expression<T> expression;
42109 : expression.register_symbol_table(symbol_table);
42110 :
42111 : parser<T> parser;
42112 :
42113 : if (parser.compile(expression_string,expression))
42114 : {
42115 : result = expression.value();
42116 :
42117 : return true;
42118 : }
42119 : else
42120 : return false;
42121 : }
42122 :
42123 : template <typename T>
42124 : inline bool compute(const std::string& expression_string,
42125 : const T& x, const T& y, const T& z,
42126 : T& result)
42127 : {
42128 : // Only 'x', 'y' or 'z'
42129 : static const std::string x_var("x");
42130 : static const std::string y_var("y");
42131 : static const std::string z_var("z");
42132 :
42133 : symbol_table<T> symbol_table;
42134 : symbol_table.add_constants();
42135 : symbol_table.add_constant(x_var,x);
42136 : symbol_table.add_constant(y_var,y);
42137 : symbol_table.add_constant(z_var,z);
42138 :
42139 : expression<T> expression;
42140 : expression.register_symbol_table(symbol_table);
42141 :
42142 : parser<T> parser;
42143 :
42144 : if (parser.compile(expression_string,expression))
42145 : {
42146 : result = expression.value();
42147 :
42148 : return true;
42149 : }
42150 : else
42151 : return false;
42152 : }
42153 :
42154 : template <typename T, std::size_t N>
42155 : class polynomial : public ifunction<T>
42156 : {
42157 : private:
42158 :
42159 : template <typename Type, std::size_t NumberOfCoefficients>
42160 : struct poly_impl { };
42161 :
42162 : template <typename Type>
42163 : struct poly_impl <Type,12>
42164 : {
42165 1015 : static inline T evaluate(const Type x,
42166 : const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
42167 : const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
42168 : const Type c2, const Type c1, const Type c0)
42169 : {
42170 : // 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
42171 1015 : 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);
42172 : }
42173 : };
42174 :
42175 : template <typename Type>
42176 : struct poly_impl <Type,11>
42177 : {
42178 1015 : static inline T evaluate(const Type x,
42179 : const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
42180 : const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
42181 : const Type c1, const Type c0)
42182 : {
42183 : // 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
42184 1015 : return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42185 : }
42186 : };
42187 :
42188 : template <typename Type>
42189 : struct poly_impl <Type,10>
42190 : {
42191 1015 : static inline T evaluate(const Type x,
42192 : const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
42193 : const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
42194 : const Type c0)
42195 : {
42196 : // 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
42197 1015 : return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42198 : }
42199 : };
42200 :
42201 : template <typename Type>
42202 : struct poly_impl <Type,9>
42203 : {
42204 1015 : static inline T evaluate(const Type x,
42205 : const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
42206 : const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
42207 : {
42208 : // 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
42209 1015 : return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42210 : }
42211 : };
42212 :
42213 : template <typename Type>
42214 : struct poly_impl <Type,8>
42215 : {
42216 1015 : static inline T evaluate(const Type x,
42217 : const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
42218 : const Type c3, const Type c2, const Type c1, const Type c0)
42219 : {
42220 : // 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
42221 1015 : return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42222 : }
42223 : };
42224 :
42225 : template <typename Type>
42226 : struct poly_impl <Type,7>
42227 : {
42228 1015 : static inline T evaluate(const Type x,
42229 : const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
42230 : const Type c2, const Type c1, const Type c0)
42231 : {
42232 : // 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
42233 1015 : return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42234 : }
42235 : };
42236 :
42237 : template <typename Type>
42238 : struct poly_impl <Type,6>
42239 : {
42240 1015 : static inline T evaluate(const Type x,
42241 : const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
42242 : const Type c1, const Type c0)
42243 : {
42244 : // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
42245 1015 : return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42246 : }
42247 : };
42248 :
42249 : template <typename Type>
42250 : struct poly_impl <Type,5>
42251 : {
42252 1015 : static inline T evaluate(const Type x,
42253 : const Type c5, const Type c4, const Type c3, const Type c2,
42254 : const Type c1, const Type c0)
42255 : {
42256 : // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
42257 1015 : return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
42258 : }
42259 : };
42260 :
42261 : template <typename Type>
42262 : struct poly_impl <Type,4>
42263 : {
42264 1015 : static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
42265 : {
42266 : // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
42267 1015 : return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
42268 : }
42269 : };
42270 :
42271 : template <typename Type>
42272 : struct poly_impl <Type,3>
42273 : {
42274 1015 : static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
42275 : {
42276 : // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
42277 1015 : return (((c3 * x + c2) * x + c1) * x + c0);
42278 : }
42279 : };
42280 :
42281 : template <typename Type>
42282 : struct poly_impl <Type,2>
42283 : {
42284 1015 : static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
42285 : {
42286 : // p(x) = c_2x^2 + c_1x^1 + c_0x^0
42287 1015 : return ((c2 * x + c1) * x + c0);
42288 : }
42289 : };
42290 :
42291 : template <typename Type>
42292 : struct poly_impl <Type,1>
42293 : {
42294 1015 : static inline T evaluate(const Type x, const Type c1, const Type c0)
42295 : {
42296 : // p(x) = c_1x^1 + c_0x^0
42297 1015 : return (c1 * x + c0);
42298 : }
42299 : };
42300 :
42301 : public:
42302 :
42303 : using ifunction<T>::operator();
42304 :
42305 128736 : polynomial()
42306 128736 : : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
42307 : {
42308 128736 : disable_has_side_effects(*this);
42309 128736 : }
42310 :
42311 128736 : virtual ~polynomial()
42312 128736 : {}
42313 :
42314 : #define poly_rtrn(NN) \
42315 : return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
42316 :
42317 1015 : inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override
42318 : {
42319 1015 : poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
42320 : }
42321 :
42322 1015 : inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override
42323 : {
42324 1015 : poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
42325 : }
42326 :
42327 1015 : inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
42328 : {
42329 1015 : poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
42330 : }
42331 :
42332 1015 : inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1,
42333 : const T& c0) exprtk_override
42334 : {
42335 1015 : poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
42336 : }
42337 :
42338 1015 : inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2,
42339 : const T& c1, const T& c0) exprtk_override
42340 : {
42341 1015 : poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
42342 : }
42343 :
42344 1015 : inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3,
42345 : const T& c2, const T& c1, const T& c0) exprtk_override
42346 : {
42347 1015 : poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
42348 : }
42349 :
42350 1015 : inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4,
42351 : const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
42352 : {
42353 1015 : poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
42354 : }
42355 :
42356 1015 : inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5,
42357 : const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
42358 : {
42359 1015 : poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
42360 : }
42361 :
42362 1015 : inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6,
42363 : const T& c5, const T& c4, const T& c3, const T& c2, const T& c1,
42364 : const T& c0) exprtk_override
42365 : {
42366 1015 : poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
42367 : }
42368 :
42369 1015 : inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7,
42370 : const T& c6, const T& c5, const T& c4, const T& c3, const T& c2,
42371 : const T& c1, const T& c0) exprtk_override
42372 : {
42373 1015 : poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
42374 : }
42375 :
42376 1015 : inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8,
42377 : const T& c7, const T& c6, const T& c5, const T& c4, const T& c3,
42378 : const T& c2, const T& c1, const T& c0) exprtk_override
42379 : {
42380 1015 : poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
42381 : }
42382 :
42383 1015 : inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9,
42384 : const T& c8, const T& c7, const T& c6, const T& c5, const T& c4,
42385 : const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override
42386 : {
42387 1015 : poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
42388 : }
42389 :
42390 : #undef poly_rtrn
42391 :
42392 0 : inline virtual T operator() () exprtk_override
42393 : {
42394 0 : return std::numeric_limits<T>::quiet_NaN();
42395 : }
42396 :
42397 0 : inline virtual T operator() (const T&) exprtk_override
42398 : {
42399 0 : return std::numeric_limits<T>::quiet_NaN();
42400 : }
42401 :
42402 0 : inline virtual T operator() (const T&, const T&) exprtk_override
42403 : {
42404 0 : return std::numeric_limits<T>::quiet_NaN();
42405 : }
42406 : };
42407 :
42408 : template <typename T>
42409 : class function_compositor
42410 : {
42411 : public:
42412 :
42413 : typedef exprtk::expression<T> expression_t;
42414 : typedef exprtk::symbol_table<T> symbol_table_t;
42415 : typedef exprtk::parser<T> parser_t;
42416 : typedef typename parser_t::settings_store settings_t;
42417 :
42418 : struct function
42419 : {
42420 : function()
42421 : {}
42422 :
42423 700 : function(const std::string& n)
42424 700 : : name_(n)
42425 700 : {}
42426 :
42427 1 : function(const std::string& name,
42428 : const std::string& expression)
42429 1 : : name_(name)
42430 1 : , expression_(expression)
42431 1 : {}
42432 :
42433 19 : function(const std::string& name,
42434 : const std::string& expression,
42435 : const std::string& v0)
42436 19 : : name_(name)
42437 19 : , expression_(expression)
42438 : {
42439 19 : v_.push_back(v0);
42440 19 : }
42441 :
42442 4 : function(const std::string& name,
42443 : const std::string& expression,
42444 : const std::string& v0, const std::string& v1)
42445 4 : : name_(name)
42446 4 : , expression_(expression)
42447 : {
42448 4 : v_.push_back(v0); v_.push_back(v1);
42449 4 : }
42450 :
42451 1 : function(const std::string& name,
42452 : const std::string& expression,
42453 : const std::string& v0, const std::string& v1,
42454 : const std::string& v2)
42455 1 : : name_(name)
42456 1 : , expression_(expression)
42457 : {
42458 1 : v_.push_back(v0); v_.push_back(v1);
42459 1 : v_.push_back(v2);
42460 1 : }
42461 :
42462 2 : function(const std::string& name,
42463 : const std::string& expression,
42464 : const std::string& v0, const std::string& v1,
42465 : const std::string& v2, const std::string& v3)
42466 2 : : name_(name)
42467 2 : , expression_(expression)
42468 : {
42469 2 : v_.push_back(v0); v_.push_back(v1);
42470 2 : v_.push_back(v2); v_.push_back(v3);
42471 2 : }
42472 :
42473 : function(const std::string& name,
42474 : const std::string& expression,
42475 : const std::string& v0, const std::string& v1,
42476 : const std::string& v2, const std::string& v3,
42477 : const std::string& v4)
42478 : : name_(name)
42479 : , expression_(expression)
42480 : {
42481 : v_.push_back(v0); v_.push_back(v1);
42482 : v_.push_back(v2); v_.push_back(v3);
42483 : v_.push_back(v4);
42484 : }
42485 :
42486 : inline function& name(const std::string& n)
42487 : {
42488 : name_ = n;
42489 : return (*this);
42490 : }
42491 :
42492 700 : inline function& expression(const std::string& e)
42493 : {
42494 700 : expression_ = e;
42495 700 : return (*this);
42496 : }
42497 :
42498 2100 : inline function& var(const std::string& v)
42499 : {
42500 2100 : v_.push_back(v);
42501 2100 : return (*this);
42502 : }
42503 :
42504 : inline function& vars(const std::string& v0,
42505 : const std::string& v1)
42506 : {
42507 : v_.push_back(v0);
42508 : v_.push_back(v1);
42509 : return (*this);
42510 : }
42511 :
42512 : inline function& vars(const std::string& v0,
42513 : const std::string& v1,
42514 : const std::string& v2)
42515 : {
42516 : v_.push_back(v0);
42517 : v_.push_back(v1);
42518 : v_.push_back(v2);
42519 : return (*this);
42520 : }
42521 :
42522 : inline function& vars(const std::string& v0,
42523 : const std::string& v1,
42524 : const std::string& v2,
42525 : const std::string& v3)
42526 : {
42527 : v_.push_back(v0);
42528 : v_.push_back(v1);
42529 : v_.push_back(v2);
42530 : v_.push_back(v3);
42531 : return (*this);
42532 : }
42533 :
42534 : inline function& vars(const std::string& v0,
42535 : const std::string& v1,
42536 : const std::string& v2,
42537 : const std::string& v3,
42538 : const std::string& v4)
42539 : {
42540 : v_.push_back(v0);
42541 : v_.push_back(v1);
42542 : v_.push_back(v2);
42543 : v_.push_back(v3);
42544 : v_.push_back(v4);
42545 : return (*this);
42546 : }
42547 :
42548 : std::string name_;
42549 : std::string expression_;
42550 : std::deque<std::string> v_;
42551 : };
42552 :
42553 : private:
42554 :
42555 : struct base_func : public exprtk::ifunction<T>
42556 : {
42557 : typedef const T& type;
42558 : typedef exprtk::ifunction<T> function_t;
42559 : typedef std::vector<T*> varref_t;
42560 : typedef std::vector<T> var_t;
42561 : typedef std::pair<T*,std::size_t> lvarref_t;
42562 : typedef std::vector<lvarref_t> lvr_vec_t;
42563 :
42564 : using exprtk::ifunction<T>::operator();
42565 :
42566 727 : base_func(const std::size_t& pc = 0)
42567 : : exprtk::ifunction<T>(pc)
42568 727 : , local_var_stack_size(0)
42569 727 : , stack_depth(0)
42570 : {
42571 727 : v.resize(pc);
42572 727 : }
42573 :
42574 727 : virtual ~base_func()
42575 727 : {}
42576 :
42577 : #define exprtk_assign(Index) \
42578 : (*v[Index]) = v##Index; \
42579 :
42580 45706176 : inline void update(const T& v0)
42581 : {
42582 45706176 : exprtk_assign(0)
42583 45706176 : }
42584 :
42585 116833 : inline void update(const T& v0, const T& v1)
42586 : {
42587 116833 : exprtk_assign(0) exprtk_assign(1)
42588 116833 : }
42589 :
42590 12900 : inline void update(const T& v0, const T& v1, const T& v2)
42591 : {
42592 12900 : exprtk_assign(0) exprtk_assign(1)
42593 12900 : exprtk_assign(2)
42594 12900 : }
42595 :
42596 4264 : inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
42597 : {
42598 4264 : exprtk_assign(0) exprtk_assign(1)
42599 4264 : exprtk_assign(2) exprtk_assign(3)
42600 4264 : }
42601 :
42602 1000 : inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
42603 : {
42604 1000 : exprtk_assign(0) exprtk_assign(1)
42605 1000 : exprtk_assign(2) exprtk_assign(3)
42606 1000 : exprtk_assign(4)
42607 1000 : }
42608 :
42609 200 : inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
42610 : {
42611 200 : exprtk_assign(0) exprtk_assign(1)
42612 200 : exprtk_assign(2) exprtk_assign(3)
42613 200 : exprtk_assign(4) exprtk_assign(5)
42614 200 : }
42615 :
42616 : #ifdef exprtk_assign
42617 : #undef exprtk_assign
42618 : #endif
42619 :
42620 727 : inline function_t& setup(expression_t& expr)
42621 : {
42622 727 : expression = expr;
42623 :
42624 : typedef typename expression_t::control_block::local_data_list_t ldl_t;
42625 :
42626 727 : const ldl_t ldl = expr.local_data_list();
42627 :
42628 727 : std::vector<std::size_t> index_list;
42629 :
42630 5043 : for (std::size_t i = 0; i < ldl.size(); ++i)
42631 : {
42632 4316 : if (ldl[i].size)
42633 : {
42634 2158 : index_list.push_back(i);
42635 : }
42636 : }
42637 :
42638 727 : std::size_t input_param_count = 0;
42639 :
42640 2885 : for (std::size_t i = 0; i < index_list.size(); ++i)
42641 : {
42642 2158 : const std::size_t index = index_list[i];
42643 :
42644 2158 : if (i < (index_list.size() - v.size()))
42645 : {
42646 20 : lv.push_back(
42647 0 : std::make_pair(
42648 20 : reinterpret_cast<T*>(ldl[index].pointer),
42649 20 : ldl[index].size));
42650 :
42651 20 : local_var_stack_size += ldl[index].size;
42652 : }
42653 : else
42654 2138 : v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
42655 : }
42656 :
42657 727 : clear_stack();
42658 :
42659 727 : return (*this);
42660 727 : }
42661 :
42662 45841373 : inline void pre()
42663 : {
42664 45841373 : if (stack_depth++)
42665 : {
42666 45705335 : if (!v.empty())
42667 : {
42668 45705335 : var_t var_stack(v.size(),T(0));
42669 45705335 : copy(v,var_stack);
42670 45705335 : param_stack.push_back(var_stack);
42671 45705335 : }
42672 :
42673 45705335 : if (!lv.empty())
42674 : {
42675 4950 : var_t local_var_stack(local_var_stack_size,T(0));
42676 4950 : copy(lv,local_var_stack);
42677 4950 : local_stack.push_back(local_var_stack);
42678 4950 : }
42679 : }
42680 45841373 : }
42681 :
42682 45841373 : inline void post()
42683 : {
42684 45841373 : if (--stack_depth)
42685 : {
42686 45705335 : if (!v.empty())
42687 : {
42688 45705335 : copy(param_stack.back(),v);
42689 45705335 : param_stack.pop_back();
42690 : }
42691 :
42692 45705335 : if (!lv.empty())
42693 : {
42694 4950 : copy(local_stack.back(),lv);
42695 4950 : local_stack.pop_back();
42696 : }
42697 : }
42698 45841373 : }
42699 :
42700 45705335 : void copy(const varref_t& src_v, var_t& dest_v)
42701 : {
42702 91488223 : for (std::size_t i = 0; i < src_v.size(); ++i)
42703 : {
42704 45782888 : dest_v[i] = (*src_v[i]);
42705 : }
42706 45705335 : }
42707 :
42708 45705335 : void copy(const var_t& src_v, varref_t& dest_v)
42709 : {
42710 91488223 : for (std::size_t i = 0; i < src_v.size(); ++i)
42711 : {
42712 45782888 : (*dest_v[i]) = src_v[i];
42713 : }
42714 45705335 : }
42715 :
42716 4950 : void copy(const lvr_vec_t& src_v, var_t& dest_v)
42717 : {
42718 4950 : typename var_t::iterator itr = dest_v.begin();
42719 : typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
42720 :
42721 9900 : for (std::size_t i = 0; i < src_v.size(); ++i)
42722 : {
42723 4950 : lvarref_t vr = src_v[i];
42724 :
42725 4950 : if (1 == vr.second)
42726 4950 : *itr++ = (*vr.first);
42727 : else
42728 : {
42729 0 : std::copy(vr.first, vr.first + vr.second, itr);
42730 0 : itr += static_cast<diff_t>(vr.second);
42731 : }
42732 : }
42733 4950 : }
42734 :
42735 4950 : void copy(const var_t& src_v, lvr_vec_t& dest_v)
42736 : {
42737 4950 : typename var_t::const_iterator itr = src_v.begin();
42738 : typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
42739 :
42740 9900 : for (std::size_t i = 0; i < src_v.size(); ++i)
42741 : {
42742 4950 : lvarref_t vr = dest_v[i];
42743 :
42744 4950 : if (1 == vr.second)
42745 4950 : (*vr.first) = *itr++;
42746 : else
42747 : {
42748 0 : std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
42749 0 : itr += static_cast<diff_t>(vr.second);
42750 : }
42751 : }
42752 4950 : }
42753 :
42754 727 : inline void clear_stack()
42755 : {
42756 2865 : for (std::size_t i = 0; i < v.size(); ++i)
42757 : {
42758 2138 : (*v[i]) = 0;
42759 : }
42760 727 : }
42761 :
42762 45918873 : inline virtual T value(expression_t& e)
42763 : {
42764 45918873 : return e.value();
42765 : }
42766 :
42767 : expression_t expression;
42768 : varref_t v;
42769 : lvr_vec_t lv;
42770 : std::size_t local_var_stack_size;
42771 : std::size_t stack_depth;
42772 : std::deque<var_t> param_stack;
42773 : std::deque<var_t> local_stack;
42774 : };
42775 :
42776 : typedef std::map<std::string,base_func*> funcparam_t;
42777 :
42778 : struct func_0param : public base_func
42779 : {
42780 : using exprtk::ifunction<T>::operator();
42781 :
42782 101 : func_0param() : base_func(0) {}
42783 :
42784 77500 : inline T operator() () exprtk_override
42785 : {
42786 77500 : return this->value(base_func::expression);
42787 : }
42788 : };
42789 :
42790 : typedef const T& type;
42791 :
42792 : template <typename BaseFuncType>
42793 : struct scoped_bft
42794 : {
42795 45841373 : explicit scoped_bft(BaseFuncType& bft)
42796 45841373 : : bft_(bft)
42797 : {
42798 45841373 : bft_.pre ();
42799 45841373 : }
42800 :
42801 45841373 : ~scoped_bft()
42802 : {
42803 45841373 : bft_.post();
42804 45841373 : }
42805 :
42806 : BaseFuncType& bft_;
42807 :
42808 : private:
42809 :
42810 : scoped_bft(const scoped_bft&) exprtk_delete;
42811 : scoped_bft& operator=(const scoped_bft&) exprtk_delete;
42812 : };
42813 :
42814 : struct func_1param : public base_func
42815 : {
42816 : using exprtk::ifunction<T>::operator();
42817 :
42818 119 : func_1param() : base_func(1) {}
42819 :
42820 45706176 : inline T operator() (type v0) exprtk_override
42821 : {
42822 45706176 : scoped_bft<func_1param> sb(*this);
42823 45706176 : base_func::update(v0);
42824 91412352 : return this->value(base_func::expression);
42825 45706176 : }
42826 : };
42827 :
42828 : struct func_2param : public base_func
42829 : {
42830 : using exprtk::ifunction<T>::operator();
42831 :
42832 104 : func_2param() : base_func(2) {}
42833 :
42834 116833 : inline T operator() (type v0, type v1) exprtk_override
42835 : {
42836 116833 : scoped_bft<func_2param> sb(*this);
42837 116833 : base_func::update(v0, v1);
42838 233666 : return this->value(base_func::expression);
42839 116833 : }
42840 : };
42841 :
42842 : struct func_3param : public base_func
42843 : {
42844 : using exprtk::ifunction<T>::operator();
42845 :
42846 101 : func_3param() : base_func(3) {}
42847 :
42848 12900 : inline T operator() (type v0, type v1, type v2) exprtk_override
42849 : {
42850 12900 : scoped_bft<func_3param> sb(*this);
42851 12900 : base_func::update(v0, v1, v2);
42852 25800 : return this->value(base_func::expression);
42853 12900 : }
42854 : };
42855 :
42856 : struct func_4param : public base_func
42857 : {
42858 : using exprtk::ifunction<T>::operator();
42859 :
42860 102 : func_4param() : base_func(4) {}
42861 :
42862 4264 : inline T operator() (type v0, type v1, type v2, type v3) exprtk_override
42863 : {
42864 4264 : scoped_bft<func_4param> sb(*this);
42865 4264 : base_func::update(v0, v1, v2, v3);
42866 8528 : return this->value(base_func::expression);
42867 4264 : }
42868 : };
42869 :
42870 : struct func_5param : public base_func
42871 : {
42872 : using exprtk::ifunction<T>::operator();
42873 :
42874 100 : func_5param() : base_func(5) {}
42875 :
42876 1000 : inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override
42877 : {
42878 1000 : scoped_bft<func_5param> sb(*this);
42879 1000 : base_func::update(v0, v1, v2, v3, v4);
42880 2000 : return this->value(base_func::expression);
42881 1000 : }
42882 : };
42883 :
42884 : struct func_6param : public base_func
42885 : {
42886 : using exprtk::ifunction<T>::operator();
42887 :
42888 100 : func_6param() : base_func(6) {}
42889 :
42890 200 : inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override
42891 : {
42892 200 : scoped_bft<func_6param> sb(*this);
42893 200 : base_func::update(v0, v1, v2, v3, v4, v5);
42894 400 : return this->value(base_func::expression);
42895 200 : }
42896 : };
42897 :
42898 0 : static T return_value(expression_t& e)
42899 : {
42900 : typedef exprtk::results_context<T> results_context_t;
42901 : typedef typename results_context_t::type_store_t type_t;
42902 : typedef typename type_t::scalar_view scalar_t;
42903 :
42904 0 : const T result = e.value();
42905 :
42906 0 : if (e.return_invoked())
42907 : {
42908 : // Due to the post compilation checks, it can be safely
42909 : // assumed that there will be at least one parameter
42910 : // and that the first parameter will always be scalar.
42911 0 : return scalar_t(e.results()[0])();
42912 : }
42913 :
42914 0 : return result;
42915 : }
42916 :
42917 : #define def_fp_retval(N) \
42918 : struct func_##N##param_retval exprtk_final : public func_##N##param \
42919 : { \
42920 : inline T value(expression_t& e) exprtk_override \
42921 : { \
42922 : return return_value(e); \
42923 : } \
42924 : }; \
42925 :
42926 0 : def_fp_retval(0)
42927 0 : def_fp_retval(1)
42928 0 : def_fp_retval(2)
42929 0 : def_fp_retval(3)
42930 0 : def_fp_retval(4)
42931 0 : def_fp_retval(5)
42932 0 : def_fp_retval(6)
42933 :
42934 : #undef def_fp_retval
42935 :
42936 : template <typename Allocator,
42937 : template <typename, typename> class Sequence>
42938 727 : inline bool add(const std::string& name,
42939 : const std::string& expression,
42940 : const Sequence<std::string,Allocator>& var_list,
42941 : const bool override = false)
42942 : {
42943 727 : const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
42944 :
42945 727 : if (expr_map_.end() != itr)
42946 : {
42947 0 : if (!override)
42948 : {
42949 : exprtk_debug(("Compositor error(add): function '%s' already defined\n",
42950 : name.c_str()));
42951 :
42952 0 : return false;
42953 : }
42954 :
42955 0 : remove(name, var_list.size());
42956 : }
42957 :
42958 727 : if (compile_expression(name, expression, var_list))
42959 : {
42960 727 : const std::size_t n = var_list.size();
42961 :
42962 727 : fp_map_[n][name]->setup(expr_map_[name]);
42963 :
42964 727 : return true;
42965 : }
42966 : else
42967 : {
42968 : exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
42969 : name.c_str()));
42970 :
42971 0 : return false;
42972 : }
42973 : }
42974 :
42975 : public:
42976 :
42977 103 : function_compositor()
42978 103 : : parser_(settings_t::default_compile_all_opts +
42979 : settings_t::e_disable_zero_return)
42980 206 : , fp_map_(7)
42981 103 : , load_variables_(false)
42982 309 : , load_vectors_(false)
42983 103 : {}
42984 :
42985 3 : explicit function_compositor(const symbol_table_t& st)
42986 3 : : symbol_table_(st)
42987 3 : , parser_(settings_t::default_compile_all_opts +
42988 : settings_t::e_disable_zero_return)
42989 6 : , fp_map_(7)
42990 3 : , load_variables_(false)
42991 6 : , load_vectors_(false)
42992 3 : {}
42993 :
42994 106 : ~function_compositor()
42995 : {
42996 106 : clear();
42997 106 : }
42998 :
42999 103 : inline symbol_table_t& symbol_table()
43000 : {
43001 103 : return symbol_table_;
43002 : }
43003 :
43004 : inline const symbol_table_t& symbol_table() const
43005 : {
43006 : return symbol_table_;
43007 : }
43008 :
43009 : inline void add_auxiliary_symtab(symbol_table_t& symtab)
43010 : {
43011 : auxiliary_symtab_list_.push_back(&symtab);
43012 : }
43013 :
43014 : void load_variables(const bool load = true)
43015 : {
43016 : load_variables_ = load;
43017 : }
43018 :
43019 : void load_vectors(const bool load = true)
43020 : {
43021 : load_vectors_ = load;
43022 : }
43023 :
43024 106 : void clear()
43025 : {
43026 106 : symbol_table_.clear();
43027 106 : expr_map_ .clear();
43028 :
43029 848 : for (std::size_t i = 0; i < fp_map_.size(); ++i)
43030 : {
43031 742 : typename funcparam_t::iterator itr = fp_map_[i].begin();
43032 742 : typename funcparam_t::iterator end = fp_map_[i].end ();
43033 :
43034 1469 : while (itr != end)
43035 : {
43036 727 : delete itr->second;
43037 727 : ++itr;
43038 : }
43039 :
43040 742 : fp_map_[i].clear();
43041 : }
43042 106 : }
43043 :
43044 727 : inline bool add(const function& f, const bool override = false)
43045 : {
43046 727 : return add(f.name_, f.expression_, f.v_,override);
43047 : }
43048 :
43049 : inline std::string error() const
43050 : {
43051 : if (!error_list_.empty())
43052 : {
43053 : return error_list_[0].diagnostic;
43054 : }
43055 : else
43056 : return std::string("No Error");
43057 : }
43058 :
43059 : inline std::size_t error_count() const
43060 : {
43061 : return error_list_.size();
43062 : }
43063 :
43064 : inline parser_error::type get_error(const std::size_t& index) const
43065 : {
43066 : if (index < error_list_.size())
43067 : {
43068 : return error_list_[index];
43069 : }
43070 :
43071 : throw std::invalid_argument("compositor::get_error() - Invalid error index specified");
43072 : }
43073 :
43074 : private:
43075 :
43076 : template <typename Allocator,
43077 : template <typename, typename> class Sequence>
43078 727 : bool compile_expression(const std::string& name,
43079 : const std::string& expression,
43080 : const Sequence<std::string,Allocator>& input_var_list,
43081 : bool return_present = false)
43082 : {
43083 727 : expression_t compiled_expression;
43084 727 : symbol_table_t local_symbol_table;
43085 :
43086 727 : local_symbol_table.load_from(symbol_table_);
43087 727 : local_symbol_table.add_constants();
43088 :
43089 727 : if (load_variables_)
43090 : {
43091 0 : local_symbol_table.load_variables_from(symbol_table_);
43092 : }
43093 :
43094 727 : if (load_vectors_)
43095 : {
43096 0 : local_symbol_table.load_vectors_from(symbol_table_);
43097 : }
43098 :
43099 727 : error_list_.clear();
43100 :
43101 727 : if (!valid(name,input_var_list.size()))
43102 : {
43103 0 : parser_error::type error =
43104 : parser_error::make_error(
43105 : parser_error::e_parser,
43106 0 : lexer::token(),
43107 : "ERR274 - Function '" + name + "' is an invalid overload",
43108 : exprtk_error_location);
43109 :
43110 0 : error_list_.push_back(error);
43111 0 : return false;
43112 0 : }
43113 :
43114 2181 : if (!forward(name,
43115 727 : input_var_list.size(),
43116 : local_symbol_table,
43117 : return_present))
43118 0 : return false;
43119 :
43120 727 : compiled_expression.register_symbol_table(local_symbol_table);
43121 :
43122 727 : for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
43123 : {
43124 0 : compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
43125 : }
43126 :
43127 727 : std::string mod_expression;
43128 :
43129 2865 : for (std::size_t i = 0; i < input_var_list.size(); ++i)
43130 : {
43131 2138 : mod_expression += " var " + input_var_list[i] + "{};\n";
43132 : }
43133 :
43134 727 : if (
43135 727 : ('{' == details::front(expression)) &&
43136 0 : ('}' == details::back (expression))
43137 : )
43138 0 : mod_expression += "~" + expression + ";";
43139 : else
43140 727 : mod_expression += "~{" + expression + "};";
43141 :
43142 727 : if (!parser_.compile(mod_expression,compiled_expression))
43143 : {
43144 : exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str()));
43145 : exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str()));
43146 :
43147 0 : remove(name,input_var_list.size());
43148 :
43149 0 : for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index)
43150 : {
43151 0 : error_list_.push_back(parser_.get_error(err_index));
43152 : }
43153 :
43154 0 : return false;
43155 : }
43156 :
43157 727 : if (!return_present && parser_.dec().return_present())
43158 : {
43159 0 : remove(name,input_var_list.size());
43160 0 : return compile_expression(name, expression, input_var_list, true);
43161 : }
43162 :
43163 : // Make sure every return point has a scalar as its first parameter
43164 727 : if (parser_.dec().return_present())
43165 : {
43166 : typedef std::vector<std::string> str_list_t;
43167 :
43168 0 : str_list_t ret_param_list = parser_.dec().return_param_type_list();
43169 :
43170 0 : for (std::size_t i = 0; i < ret_param_list.size(); ++i)
43171 : {
43172 0 : const std::string& params = ret_param_list[i];
43173 :
43174 0 : if (params.empty() || ('T' != params[0]))
43175 : {
43176 : exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
43177 : name.c_str()));
43178 :
43179 0 : remove(name,input_var_list.size());
43180 :
43181 0 : return false;
43182 : }
43183 : }
43184 0 : }
43185 :
43186 727 : expr_map_[name] = compiled_expression;
43187 :
43188 727 : exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
43189 :
43190 727 : if (symbol_table_.add_function(name,ifunc))
43191 727 : return true;
43192 : else
43193 : {
43194 : exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
43195 : name.c_str()));
43196 0 : return false;
43197 : }
43198 727 : }
43199 :
43200 727 : inline bool symbol_used(const std::string& symbol) const
43201 : {
43202 : return (
43203 727 : symbol_table_.is_variable (symbol) ||
43204 727 : symbol_table_.is_stringvar (symbol) ||
43205 727 : symbol_table_.is_function (symbol) ||
43206 2181 : symbol_table_.is_vector (symbol) ||
43207 727 : symbol_table_.is_vararg_function(symbol)
43208 727 : );
43209 : }
43210 :
43211 727 : inline bool valid(const std::string& name,
43212 : const std::size_t& arg_count) const
43213 : {
43214 727 : if (arg_count > 6)
43215 0 : return false;
43216 727 : else if (symbol_used(name))
43217 0 : return false;
43218 727 : else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
43219 0 : return false;
43220 : else
43221 727 : return true;
43222 : }
43223 :
43224 727 : inline bool forward(const std::string& name,
43225 : const std::size_t& arg_count,
43226 : symbol_table_t& sym_table,
43227 : const bool ret_present = false)
43228 : {
43229 727 : switch (arg_count)
43230 : {
43231 : #define case_stmt(N) \
43232 : case N : (fp_map_[arg_count])[name] = \
43233 : (!ret_present) ? static_cast<base_func*> \
43234 : (new func_##N##param) : \
43235 : static_cast<base_func*> \
43236 : (new func_##N##param_retval) ; \
43237 : break; \
43238 :
43239 324 : case_stmt(0) case_stmt(1) case_stmt(2)
43240 303 : case_stmt(3) case_stmt(4) case_stmt(5)
43241 100 : case_stmt(6)
43242 : #undef case_stmt
43243 : }
43244 :
43245 727 : exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
43246 :
43247 727 : return sym_table.add_function(name,ifunc);
43248 : }
43249 :
43250 0 : inline void remove(const std::string& name, const std::size_t& arg_count)
43251 : {
43252 0 : if (arg_count > 6)
43253 0 : return;
43254 :
43255 0 : const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
43256 :
43257 0 : if (expr_map_.end() != em_itr)
43258 : {
43259 0 : expr_map_.erase(em_itr);
43260 : }
43261 :
43262 0 : const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
43263 :
43264 0 : if (fp_map_[arg_count].end() != fp_itr)
43265 : {
43266 0 : delete fp_itr->second;
43267 0 : fp_map_[arg_count].erase(fp_itr);
43268 : }
43269 :
43270 0 : symbol_table_.remove_function(name);
43271 : }
43272 :
43273 : private:
43274 :
43275 : symbol_table_t symbol_table_;
43276 : parser_t parser_;
43277 : std::map<std::string,expression_t> expr_map_;
43278 : std::vector<funcparam_t> fp_map_;
43279 : std::vector<symbol_table_t*> auxiliary_symtab_list_;
43280 : std::deque<parser_error::type> error_list_;
43281 : bool load_variables_;
43282 : bool load_vectors_;
43283 : }; // class function_compositor
43284 :
43285 : } // namespace exprtk
43286 :
43287 : #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
43288 : # ifndef NOMINMAX
43289 : # define NOMINMAX
43290 : # endif
43291 : # ifndef WIN32_LEAN_AND_MEAN
43292 : # define WIN32_LEAN_AND_MEAN
43293 : # endif
43294 : # include <windows.h>
43295 : # include <ctime>
43296 : #else
43297 : # include <ctime>
43298 : # include <sys/time.h>
43299 : # include <sys/types.h>
43300 : #endif
43301 :
43302 : namespace exprtk
43303 : {
43304 : class timer
43305 : {
43306 : public:
43307 :
43308 : #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
43309 : timer()
43310 : : in_use_(false)
43311 : , start_time_{ 0 }
43312 : , stop_time_ { 0 }
43313 : {
43314 : QueryPerformanceFrequency(&clock_frequency_);
43315 : }
43316 :
43317 : inline void start()
43318 : {
43319 : in_use_ = true;
43320 : QueryPerformanceCounter(&start_time_);
43321 : }
43322 :
43323 : inline void stop()
43324 : {
43325 : QueryPerformanceCounter(&stop_time_);
43326 : in_use_ = false;
43327 : }
43328 :
43329 : inline double time() const
43330 : {
43331 : return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
43332 : }
43333 :
43334 : #else
43335 :
43336 23 : timer()
43337 23 : : in_use_(false)
43338 : {
43339 23 : start_time_.tv_sec = 0;
43340 23 : start_time_.tv_usec = 0;
43341 :
43342 23 : stop_time_.tv_sec = 0;
43343 23 : stop_time_.tv_usec = 0;
43344 23 : }
43345 :
43346 23 : inline void start()
43347 : {
43348 23 : in_use_ = true;
43349 23 : gettimeofday(&start_time_,0);
43350 23 : }
43351 :
43352 23 : inline void stop()
43353 : {
43354 23 : gettimeofday(&stop_time_, 0);
43355 23 : in_use_ = false;
43356 23 : }
43357 :
43358 23 : inline unsigned long long int usec_time() const
43359 : {
43360 23 : if (!in_use_)
43361 : {
43362 23 : if (stop_time_.tv_sec >= start_time_.tv_sec)
43363 : {
43364 23 : return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) +
43365 23 : static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
43366 : }
43367 : else
43368 0 : return std::numeric_limits<details::_uint64_t>::max();
43369 : }
43370 : else
43371 0 : return std::numeric_limits<details::_uint64_t>::max();
43372 : }
43373 :
43374 23 : inline double time() const
43375 : {
43376 23 : return usec_time() * 0.000001;
43377 : }
43378 :
43379 : #endif
43380 :
43381 : inline bool in_use() const
43382 : {
43383 : return in_use_;
43384 : }
43385 :
43386 : private:
43387 :
43388 : bool in_use_;
43389 :
43390 : #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
43391 : LARGE_INTEGER start_time_;
43392 : LARGE_INTEGER stop_time_;
43393 : LARGE_INTEGER clock_frequency_;
43394 : #else
43395 : struct timeval start_time_;
43396 : struct timeval stop_time_;
43397 : #endif
43398 : };
43399 :
43400 : template <typename T>
43401 : struct type_defs
43402 : {
43403 : typedef symbol_table<T> symbol_table_t;
43404 : typedef expression<T> expression_t;
43405 : typedef parser<T> parser_t;
43406 : typedef parser_error::type error_t;
43407 : typedef function_compositor<T> compositor_t;
43408 : typedef typename compositor_t::function function_t;
43409 : };
43410 :
43411 : } // namespace exprtk
43412 :
43413 : #ifndef exprtk_disable_rtl_io
43414 : namespace exprtk
43415 : {
43416 : namespace rtl { namespace io { namespace details
43417 : {
43418 : template <typename T>
43419 0 : inline void print_type(const std::string& fmt,
43420 : const T v,
43421 : exprtk::details::numeric::details::real_type_tag)
43422 : {
43423 : #if defined(__clang__)
43424 : #pragma clang diagnostic push
43425 : #pragma clang diagnostic ignored "-Wformat-nonliteral"
43426 : #elif defined(__GNUC__) || defined(__GNUG__)
43427 : #pragma GCC diagnostic push
43428 : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
43429 : #elif defined(_MSC_VER)
43430 : #endif
43431 :
43432 0 : printf(fmt.c_str(), v);
43433 :
43434 : #if defined(__clang__)
43435 : #pragma clang diagnostic pop
43436 : #elif defined(__GNUC__) || defined(__GNUG__)
43437 : #pragma GCC diagnostic pop
43438 : #elif defined(_MSC_VER)
43439 : #endif
43440 0 : }
43441 :
43442 : template <typename T>
43443 : struct print_impl
43444 : {
43445 : typedef typename igeneric_function<T>::generic_type generic_type;
43446 : typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
43447 : typedef typename generic_type::scalar_view scalar_t;
43448 : typedef typename generic_type::vector_view vector_t;
43449 : typedef typename generic_type::string_view string_t;
43450 : typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
43451 :
43452 0 : static void process(const std::string& scalar_format, parameter_list_t parameters)
43453 : {
43454 0 : for (std::size_t i = 0; i < parameters.size(); ++i)
43455 : {
43456 0 : generic_type& gt = parameters[i];
43457 :
43458 0 : switch (gt.type)
43459 : {
43460 0 : case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
43461 0 : break;
43462 :
43463 0 : case generic_type::e_vector : print(scalar_format,vector_t(gt));
43464 0 : break;
43465 :
43466 0 : case generic_type::e_string : print(string_t(gt));
43467 0 : break;
43468 :
43469 0 : default : continue;
43470 : }
43471 : }
43472 0 : }
43473 :
43474 0 : static inline void print(const std::string& scalar_format, const scalar_t& s)
43475 : {
43476 0 : print_type(scalar_format,s(),num_type());
43477 0 : }
43478 :
43479 0 : static inline void print(const std::string& scalar_format, const vector_t& v)
43480 : {
43481 0 : for (std::size_t i = 0; i < v.size(); ++i)
43482 : {
43483 0 : print_type(scalar_format,v[i],num_type());
43484 :
43485 0 : if ((i + 1) < v.size())
43486 0 : printf(" ");
43487 : }
43488 0 : }
43489 :
43490 0 : static inline void print(const string_t& s)
43491 : {
43492 0 : printf("%s",to_str(s).c_str());
43493 0 : }
43494 : };
43495 :
43496 : } // namespace exprtk::rtl::io::details
43497 :
43498 : template <typename T>
43499 : struct print exprtk_final : public exprtk::igeneric_function<T>
43500 : {
43501 : typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
43502 :
43503 : using exprtk::igeneric_function<T>::operator();
43504 :
43505 30 : explicit print(const std::string& scalar_format = "%10.5f")
43506 90 : : scalar_format_(scalar_format)
43507 : {
43508 30 : exprtk::enable_zero_parameters(*this);
43509 30 : }
43510 :
43511 0 : inline T operator() (parameter_list_t parameters) exprtk_override
43512 : {
43513 0 : details::print_impl<T>::process(scalar_format_,parameters);
43514 0 : return T(0);
43515 : }
43516 :
43517 : std::string scalar_format_;
43518 : };
43519 :
43520 : template <typename T>
43521 : struct println exprtk_final : public exprtk::igeneric_function<T>
43522 : {
43523 : typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
43524 :
43525 : using exprtk::igeneric_function<T>::operator();
43526 :
43527 30 : explicit println(const std::string& scalar_format = "%10.5f")
43528 90 : : scalar_format_(scalar_format)
43529 : {
43530 30 : exprtk::enable_zero_parameters(*this);
43531 30 : }
43532 :
43533 0 : inline T operator() (parameter_list_t parameters) exprtk_override
43534 : {
43535 0 : details::print_impl<T>::process(scalar_format_,parameters);
43536 0 : printf("\n");
43537 0 : return T(0);
43538 : }
43539 :
43540 : std::string scalar_format_;
43541 : };
43542 :
43543 : template <typename T>
43544 : struct package
43545 : {
43546 : print <T> p;
43547 : println<T> pl;
43548 :
43549 30 : bool register_package(exprtk::symbol_table<T>& symtab)
43550 : {
43551 : #define exprtk_register_function(FunctionName, FunctionType) \
43552 : if (!symtab.add_function(FunctionName,FunctionType)) \
43553 : { \
43554 : exprtk_debug(( \
43555 : "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
43556 : FunctionName)); \
43557 : return false; \
43558 : } \
43559 :
43560 90 : exprtk_register_function("print" , p )
43561 90 : exprtk_register_function("println", pl)
43562 : #undef exprtk_register_function
43563 :
43564 30 : return true;
43565 : }
43566 : };
43567 :
43568 : } // namespace exprtk::rtl::io
43569 : } // namespace exprtk::rtl
43570 : } // namespace exprtk
43571 : #endif
43572 :
43573 : #ifndef exprtk_disable_rtl_io_file
43574 : #include <fstream>
43575 : namespace exprtk
43576 : {
43577 : namespace rtl { namespace io { namespace file { namespace details
43578 : {
43579 : using ::exprtk::details::char_ptr;
43580 : using ::exprtk::details::char_cptr;
43581 :
43582 : enum file_mode
43583 : {
43584 : e_error = 0,
43585 : e_read = 1,
43586 : e_write = 2,
43587 : e_rdwrt = 4
43588 : };
43589 :
43590 : struct file_descriptor
43591 : {
43592 : file_descriptor(const std::string& fname, const std::string& access)
43593 : : stream_ptr(0)
43594 : , mode(get_file_mode(access))
43595 : , file_name(fname)
43596 : {}
43597 :
43598 : void* stream_ptr;
43599 : file_mode mode;
43600 : std::string file_name;
43601 :
43602 : bool open()
43603 : {
43604 : if (e_read == mode)
43605 : {
43606 : std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
43607 :
43608 : if (!(*stream))
43609 : {
43610 : file_name.clear();
43611 : delete stream;
43612 :
43613 : return false;
43614 : }
43615 :
43616 : stream_ptr = stream;
43617 :
43618 : return true;
43619 : }
43620 : else if (e_write == mode)
43621 : {
43622 : std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
43623 :
43624 : if (!(*stream))
43625 : {
43626 : file_name.clear();
43627 : delete stream;
43628 :
43629 : return false;
43630 : }
43631 :
43632 : stream_ptr = stream;
43633 :
43634 : return true;
43635 : }
43636 : else if (e_rdwrt == mode)
43637 : {
43638 : std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
43639 :
43640 : if (!(*stream))
43641 : {
43642 : file_name.clear();
43643 : delete stream;
43644 :
43645 : return false;
43646 : }
43647 :
43648 : stream_ptr = stream;
43649 :
43650 : return true;
43651 : }
43652 :
43653 : return false;
43654 : }
43655 :
43656 : template <typename Stream, typename Ptr>
43657 : void close(Ptr& p)
43658 : {
43659 : Stream* stream = reinterpret_cast<Stream*>(p);
43660 : stream->close();
43661 : delete stream;
43662 : p = reinterpret_cast<Ptr>(0);
43663 : }
43664 :
43665 : bool close()
43666 : {
43667 : switch (mode)
43668 : {
43669 : case e_read : close<std::ifstream>(stream_ptr);
43670 : break;
43671 :
43672 : case e_write : close<std::ofstream>(stream_ptr);
43673 : break;
43674 :
43675 : case e_rdwrt : close<std::fstream> (stream_ptr);
43676 : break;
43677 :
43678 : default : return false;
43679 : }
43680 :
43681 : return true;
43682 : }
43683 :
43684 : template <typename View>
43685 : bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
43686 : {
43687 : switch (mode)
43688 : {
43689 : case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
43690 : write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
43691 : break;
43692 :
43693 : case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
43694 : write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
43695 : break;
43696 :
43697 : default : return false;
43698 : }
43699 :
43700 : return true;
43701 : }
43702 :
43703 : template <typename View>
43704 : bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
43705 : {
43706 : switch (mode)
43707 : {
43708 : case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
43709 : read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t));
43710 : break;
43711 :
43712 : case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
43713 : read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t));
43714 : break;
43715 :
43716 : default : return false;
43717 : }
43718 :
43719 : return true;
43720 : }
43721 :
43722 : bool getline(std::string& s)
43723 : {
43724 : switch (mode)
43725 : {
43726 : case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
43727 : case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
43728 : default : return false;
43729 : }
43730 : }
43731 :
43732 : bool eof() const
43733 : {
43734 : switch (mode)
43735 : {
43736 : case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
43737 : case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
43738 : case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
43739 : default : return true;
43740 : }
43741 : }
43742 :
43743 : file_mode get_file_mode(const std::string& access) const
43744 : {
43745 : if (access.empty() || access.size() > 2)
43746 : return e_error;
43747 :
43748 : std::size_t w_cnt = 0;
43749 : std::size_t r_cnt = 0;
43750 :
43751 : for (std::size_t i = 0; i < access.size(); ++i)
43752 : {
43753 : switch (std::tolower(access[i]))
43754 : {
43755 : case 'r' : r_cnt++; break;
43756 : case 'w' : w_cnt++; break;
43757 : default : return e_error;
43758 : }
43759 : }
43760 :
43761 : if ((0 == r_cnt) && (0 == w_cnt))
43762 : return e_error;
43763 : else if ((r_cnt > 1) || (w_cnt > 1))
43764 : return e_error;
43765 : else if ((1 == r_cnt) && (1 == w_cnt))
43766 : return e_rdwrt;
43767 : else if (1 == r_cnt)
43768 : return e_read;
43769 : else
43770 : return e_write;
43771 : }
43772 : };
43773 :
43774 : template <typename T>
43775 : file_descriptor* make_handle(T v)
43776 : {
43777 : const std::size_t fd_size = sizeof(details::file_descriptor*);
43778 : details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
43779 :
43780 : std::memcpy(reinterpret_cast<char_ptr >(&fd),
43781 : reinterpret_cast<char_cptr>(&v ),
43782 : fd_size);
43783 : return fd;
43784 : }
43785 :
43786 : template <typename T>
43787 : void perform_check()
43788 : {
43789 : #ifdef _MSC_VER
43790 : #pragma warning(push)
43791 : #pragma warning(disable: 4127)
43792 : #endif
43793 : if (sizeof(T) < sizeof(void*))
43794 : {
43795 : throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
43796 : }
43797 : #ifdef _MSC_VER
43798 : #pragma warning(pop)
43799 : #endif
43800 : assert(sizeof(T) <= sizeof(void*));
43801 : }
43802 :
43803 : } // namespace exprtk::rtl::io::file::details
43804 :
43805 : template <typename T>
43806 : class open exprtk_final : public exprtk::igeneric_function<T>
43807 : {
43808 : public:
43809 :
43810 : typedef typename exprtk::igeneric_function<T> igfun_t;
43811 : typedef typename igfun_t::parameter_list_t parameter_list_t;
43812 : typedef typename igfun_t::generic_type generic_type;
43813 : typedef typename generic_type::string_view string_t;
43814 :
43815 : using igfun_t::operator();
43816 :
43817 : open()
43818 : : exprtk::igeneric_function<T>("S|SS")
43819 : { details::perform_check<T>(); }
43820 :
43821 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
43822 : {
43823 : const std::string file_name = to_str(string_t(parameters[0]));
43824 :
43825 : if (file_name.empty())
43826 : {
43827 : return T(0);
43828 : }
43829 :
43830 : if ((1 == ps_index) && (0 == string_t(parameters[1]).size()))
43831 : {
43832 : return T(0);
43833 : }
43834 :
43835 : const std::string access =
43836 : (0 == ps_index) ? "r" : to_str(string_t(parameters[1]));
43837 :
43838 : details::file_descriptor* fd = new details::file_descriptor(file_name,access);
43839 :
43840 : if (fd->open())
43841 : {
43842 : T t = T(0);
43843 :
43844 : const std::size_t fd_size = sizeof(details::file_descriptor*);
43845 :
43846 : std::memcpy(reinterpret_cast<char*>(&t ),
43847 : reinterpret_cast<char*>(&fd),
43848 : fd_size);
43849 : return t;
43850 : }
43851 : else
43852 : {
43853 : delete fd;
43854 : return T(0);
43855 : }
43856 : }
43857 : };
43858 :
43859 : template <typename T>
43860 : struct close exprtk_final : public exprtk::ifunction<T>
43861 : {
43862 : using exprtk::ifunction<T>::operator();
43863 :
43864 : close()
43865 : : exprtk::ifunction<T>(1)
43866 : { details::perform_check<T>(); }
43867 :
43868 : inline T operator() (const T& v) exprtk_override
43869 : {
43870 : details::file_descriptor* fd = details::make_handle(v);
43871 :
43872 : if (!fd->close())
43873 : return T(0);
43874 :
43875 : delete fd;
43876 :
43877 : return T(1);
43878 : }
43879 : };
43880 :
43881 : template <typename T>
43882 : class write exprtk_final : public exprtk::igeneric_function<T>
43883 : {
43884 : public:
43885 :
43886 : typedef typename exprtk::igeneric_function<T> igfun_t;
43887 : typedef typename igfun_t::parameter_list_t parameter_list_t;
43888 : typedef typename igfun_t::generic_type generic_type;
43889 : typedef typename generic_type::string_view string_t;
43890 : typedef typename generic_type::scalar_view scalar_t;
43891 : typedef typename generic_type::vector_view vector_t;
43892 :
43893 : using igfun_t::operator();
43894 :
43895 : write()
43896 : : igfun_t("TS|TST|TV|TVT")
43897 : { details::perform_check<T>(); }
43898 :
43899 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
43900 : {
43901 : details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
43902 :
43903 : switch (ps_index)
43904 : {
43905 : case 0 : {
43906 : const string_t buffer(parameters[1]);
43907 : const std::size_t amount = buffer.size();
43908 : return T(fd->write(buffer, amount) ? 1 : 0);
43909 : }
43910 :
43911 : case 1 : {
43912 : const string_t buffer(parameters[1]);
43913 : const std::size_t amount =
43914 : std::min(buffer.size(),
43915 : static_cast<std::size_t>(scalar_t(parameters[2])()));
43916 : return T(fd->write(buffer, amount) ? 1 : 0);
43917 : }
43918 :
43919 : case 2 : {
43920 : const vector_t vec(parameters[1]);
43921 : const std::size_t amount = vec.size();
43922 : return T(fd->write(vec, amount) ? 1 : 0);
43923 : }
43924 :
43925 : case 3 : {
43926 : const vector_t vec(parameters[1]);
43927 : const std::size_t amount =
43928 : std::min(vec.size(),
43929 : static_cast<std::size_t>(scalar_t(parameters[2])()));
43930 : return T(fd->write(vec, amount) ? 1 : 0);
43931 : }
43932 : }
43933 :
43934 : return T(0);
43935 : }
43936 : };
43937 :
43938 : template <typename T>
43939 : class read exprtk_final : public exprtk::igeneric_function<T>
43940 : {
43941 : public:
43942 :
43943 : typedef typename exprtk::igeneric_function<T> igfun_t;
43944 : typedef typename igfun_t::parameter_list_t parameter_list_t;
43945 : typedef typename igfun_t::generic_type generic_type;
43946 : typedef typename generic_type::string_view string_t;
43947 : typedef typename generic_type::scalar_view scalar_t;
43948 : typedef typename generic_type::vector_view vector_t;
43949 :
43950 : using igfun_t::operator();
43951 :
43952 : read()
43953 : : igfun_t("TS|TST|TV|TVT")
43954 : { details::perform_check<T>(); }
43955 :
43956 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
43957 : {
43958 : details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
43959 :
43960 : switch (ps_index)
43961 : {
43962 : case 0 : {
43963 : string_t buffer(parameters[1]);
43964 : const std::size_t amount = buffer.size();
43965 : return T(fd->read(buffer,amount) ? 1 : 0);
43966 : }
43967 :
43968 : case 1 : {
43969 : string_t buffer(parameters[1]);
43970 : const std::size_t amount =
43971 : std::min(buffer.size(),
43972 : static_cast<std::size_t>(scalar_t(parameters[2])()));
43973 : return T(fd->read(buffer,amount) ? 1 : 0);
43974 : }
43975 :
43976 : case 2 : {
43977 : vector_t vec(parameters[1]);
43978 : const std::size_t amount = vec.size();
43979 : return T(fd->read(vec,amount) ? 1 : 0);
43980 : }
43981 :
43982 : case 3 : {
43983 : vector_t vec(parameters[1]);
43984 : const std::size_t amount =
43985 : std::min(vec.size(),
43986 : static_cast<std::size_t>(scalar_t(parameters[2])()));
43987 : return T(fd->read(vec,amount) ? 1 : 0);
43988 : }
43989 : }
43990 :
43991 : return T(0);
43992 : }
43993 : };
43994 :
43995 : template <typename T>
43996 : class getline exprtk_final : public exprtk::igeneric_function<T>
43997 : {
43998 : public:
43999 :
44000 : typedef typename exprtk::igeneric_function<T> igfun_t;
44001 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44002 : typedef typename igfun_t::generic_type generic_type;
44003 : typedef typename generic_type::string_view string_t;
44004 : typedef typename generic_type::scalar_view scalar_t;
44005 :
44006 : using igfun_t::operator();
44007 :
44008 : getline()
44009 : : igfun_t("T",igfun_t::e_rtrn_string)
44010 : { details::perform_check<T>(); }
44011 :
44012 : inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override
44013 : {
44014 : details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
44015 : return T(fd->getline(result) ? 1 : 0);
44016 : }
44017 : };
44018 :
44019 : template <typename T>
44020 : struct eof exprtk_final : public exprtk::ifunction<T>
44021 : {
44022 : using exprtk::ifunction<T>::operator();
44023 :
44024 : eof()
44025 : : exprtk::ifunction<T>(1)
44026 : { details::perform_check<T>(); }
44027 :
44028 : inline T operator() (const T& v) exprtk_override
44029 : {
44030 : details::file_descriptor* fd = details::make_handle(v);
44031 : return (fd->eof() ? T(1) : T(0));
44032 : }
44033 : };
44034 :
44035 : template <typename T>
44036 : struct package
44037 : {
44038 : open <T> o;
44039 : close <T> c;
44040 : write <T> w;
44041 : read <T> r;
44042 : getline<T> g;
44043 : eof <T> e;
44044 :
44045 : bool register_package(exprtk::symbol_table<T>& symtab)
44046 : {
44047 : #define exprtk_register_function(FunctionName, FunctionType) \
44048 : if (!symtab.add_function(FunctionName,FunctionType)) \
44049 : { \
44050 : exprtk_debug(( \
44051 : "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
44052 : FunctionName)); \
44053 : return false; \
44054 : } \
44055 :
44056 : exprtk_register_function("open" , o)
44057 : exprtk_register_function("close" , c)
44058 : exprtk_register_function("write" , w)
44059 : exprtk_register_function("read" , r)
44060 : exprtk_register_function("getline" , g)
44061 : exprtk_register_function("eof" , e)
44062 : #undef exprtk_register_function
44063 :
44064 : return true;
44065 : }
44066 : };
44067 :
44068 : } // namespace exprtk::rtl::io::file
44069 : } // namespace exprtk::rtl::io
44070 : } // namespace exprtk::rtl
44071 : } // namespace exprtk
44072 : #endif
44073 :
44074 : #ifndef exprtk_disable_rtl_vecops
44075 : namespace exprtk
44076 : {
44077 : namespace rtl { namespace vecops {
44078 :
44079 : namespace helper
44080 : {
44081 : template <typename Vector>
44082 2953 : inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
44083 : {
44084 2953 : if (r0 > (v.size() - 1))
44085 0 : return true;
44086 2953 : else if (r1 > (v.size() - 1))
44087 0 : return true;
44088 2953 : else if (r1 < r0)
44089 0 : return true;
44090 : else
44091 2953 : return false;
44092 : }
44093 :
44094 : template <typename T>
44095 : struct load_vector_range
44096 : {
44097 : typedef typename exprtk::igeneric_function<T> igfun_t;
44098 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44099 : typedef typename igfun_t::generic_type generic_type;
44100 : typedef typename generic_type::scalar_view scalar_t;
44101 : typedef typename generic_type::vector_view vector_t;
44102 :
44103 806 : static inline bool process(parameter_list_t& parameters,
44104 : std::size_t& r0, std::size_t& r1,
44105 : const std::size_t& r0_prmidx,
44106 : const std::size_t& r1_prmidx,
44107 : const std::size_t vec_idx = 0)
44108 : {
44109 806 : if (r0_prmidx >= parameters.size())
44110 0 : return false;
44111 :
44112 806 : if (r1_prmidx >= parameters.size())
44113 0 : return false;
44114 :
44115 806 : if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
44116 0 : return false;
44117 :
44118 806 : if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
44119 0 : return false;
44120 :
44121 806 : return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
44122 : }
44123 : };
44124 : }
44125 :
44126 : namespace details
44127 : {
44128 : template <typename T>
44129 560 : inline void kahan_sum(T& sum, T& error, const T v)
44130 : {
44131 560 : const T x = v - error;
44132 560 : const T y = sum + x;
44133 560 : error = (y - sum) - x;
44134 560 : sum = y;
44135 560 : }
44136 :
44137 : } // namespace exprtk::rtl::details
44138 :
44139 : template <typename T>
44140 : class all_true exprtk_final : public exprtk::igeneric_function<T>
44141 : {
44142 : public:
44143 :
44144 : typedef typename exprtk::igeneric_function<T> igfun_t;
44145 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44146 : typedef typename igfun_t::generic_type generic_type;
44147 : typedef typename generic_type::vector_view vector_t;
44148 :
44149 : using igfun_t::operator();
44150 :
44151 32 : all_true()
44152 64 : : exprtk::igeneric_function<T>("V|VTT")
44153 : /*
44154 : Overloads:
44155 : 0. V - vector
44156 : 1. VTT - vector, r0, r1
44157 : */
44158 32 : {}
44159 :
44160 1505 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44161 : {
44162 1505 : const vector_t vec(parameters[0]);
44163 :
44164 1505 : std::size_t r0 = 0;
44165 1505 : std::size_t r1 = vec.size() - 1;
44166 :
44167 1505 : if (
44168 1505 : (1 == ps_index) &&
44169 1505 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44170 : )
44171 : {
44172 0 : return std::numeric_limits<T>::quiet_NaN();
44173 : }
44174 :
44175 10955 : for (std::size_t i = r0; i <= r1; ++i)
44176 : {
44177 9452 : if (vec[i] == T(0))
44178 : {
44179 2 : return T(0);
44180 : }
44181 : }
44182 :
44183 1503 : return T(1);
44184 : }
44185 : };
44186 :
44187 : template <typename T>
44188 : class all_false exprtk_final : public exprtk::igeneric_function<T>
44189 : {
44190 : public:
44191 :
44192 : typedef typename exprtk::igeneric_function<T> igfun_t;
44193 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44194 : typedef typename igfun_t::generic_type generic_type;
44195 : typedef typename generic_type::vector_view vector_t;
44196 :
44197 : using igfun_t::operator();
44198 :
44199 32 : all_false()
44200 64 : : exprtk::igeneric_function<T>("V|VTT")
44201 : /*
44202 : Overloads:
44203 : 0. V - vector
44204 : 1. VTT - vector, r0, r1
44205 : */
44206 32 : {}
44207 :
44208 263 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44209 : {
44210 263 : const vector_t vec(parameters[0]);
44211 :
44212 263 : std::size_t r0 = 0;
44213 263 : std::size_t r1 = vec.size() - 1;
44214 :
44215 263 : if (
44216 263 : (1 == ps_index) &&
44217 263 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44218 : )
44219 : {
44220 0 : return std::numeric_limits<T>::quiet_NaN();
44221 : }
44222 :
44223 1552 : for (std::size_t i = r0; i <= r1; ++i)
44224 : {
44225 1291 : if (vec[i] != T(0))
44226 : {
44227 2 : return T(0);
44228 : }
44229 : }
44230 :
44231 261 : return T(1);
44232 : }
44233 : };
44234 :
44235 : template <typename T>
44236 : class any_true exprtk_final : public exprtk::igeneric_function<T>
44237 : {
44238 : public:
44239 :
44240 : typedef typename exprtk::igeneric_function<T> igfun_t;
44241 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44242 : typedef typename igfun_t::generic_type generic_type;
44243 : typedef typename generic_type::vector_view vector_t;
44244 :
44245 : using igfun_t::operator();
44246 :
44247 32 : any_true()
44248 64 : : exprtk::igeneric_function<T>("V|VTT")
44249 : /*
44250 : Overloads:
44251 : 0. V - vector
44252 : 1. VTT - vector, r0, r1
44253 : */
44254 32 : {}
44255 :
44256 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44257 : {
44258 4 : const vector_t vec(parameters[0]);
44259 :
44260 4 : std::size_t r0 = 0;
44261 4 : std::size_t r1 = vec.size() - 1;
44262 :
44263 4 : if (
44264 4 : (1 == ps_index) &&
44265 4 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44266 : )
44267 : {
44268 0 : return std::numeric_limits<T>::quiet_NaN();
44269 : }
44270 :
44271 25 : for (std::size_t i = r0; i <= r1; ++i)
44272 : {
44273 24 : if (vec[i] != T(0))
44274 : {
44275 3 : return T(1);
44276 : }
44277 : }
44278 :
44279 1 : return T(0);
44280 : }
44281 : };
44282 :
44283 : template <typename T>
44284 : class any_false exprtk_final : public exprtk::igeneric_function<T>
44285 : {
44286 : public:
44287 :
44288 : typedef typename exprtk::igeneric_function<T> igfun_t;
44289 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44290 : typedef typename igfun_t::generic_type generic_type;
44291 : typedef typename generic_type::vector_view vector_t;
44292 :
44293 : using igfun_t::operator();
44294 :
44295 32 : any_false()
44296 64 : : exprtk::igeneric_function<T>("V|VTT")
44297 : /*
44298 : Overloads:
44299 : 0. V - vector
44300 : 1. VTT - vector, r0, r1
44301 : */
44302 32 : {}
44303 :
44304 5 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44305 : {
44306 5 : const vector_t vec(parameters[0]);
44307 :
44308 5 : std::size_t r0 = 0;
44309 5 : std::size_t r1 = vec.size() - 1;
44310 :
44311 5 : if (
44312 5 : (1 == ps_index) &&
44313 5 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44314 : )
44315 : {
44316 0 : return std::numeric_limits<T>::quiet_NaN();
44317 : }
44318 :
44319 26 : for (std::size_t i = r0; i <= r1; ++i)
44320 : {
44321 25 : if (vec[i] == T(0))
44322 : {
44323 4 : return T(1);
44324 : }
44325 : }
44326 :
44327 1 : return T(0);
44328 : }
44329 : };
44330 :
44331 : template <typename T>
44332 : class count exprtk_final : public exprtk::igeneric_function<T>
44333 : {
44334 : public:
44335 :
44336 : typedef typename exprtk::igeneric_function<T> igfun_t;
44337 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44338 : typedef typename igfun_t::generic_type generic_type;
44339 : typedef typename generic_type::vector_view vector_t;
44340 :
44341 : using igfun_t::operator();
44342 :
44343 32 : count()
44344 64 : : exprtk::igeneric_function<T>("V|VTT")
44345 : /*
44346 : Overloads:
44347 : 0. V - vector
44348 : 1. VTT - vector, r0, r1
44349 : */
44350 32 : {}
44351 :
44352 6 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44353 : {
44354 6 : const vector_t vec(parameters[0]);
44355 :
44356 6 : std::size_t r0 = 0;
44357 6 : std::size_t r1 = vec.size() - 1;
44358 :
44359 6 : if (
44360 6 : (1 == ps_index) &&
44361 6 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44362 : )
44363 : {
44364 0 : return std::numeric_limits<T>::quiet_NaN();
44365 : }
44366 :
44367 6 : std::size_t cnt = 0;
44368 :
44369 60 : for (std::size_t i = r0; i <= r1; ++i)
44370 : {
44371 54 : if (vec[i] != T(0)) ++cnt;
44372 : }
44373 :
44374 6 : return T(cnt);
44375 : }
44376 : };
44377 :
44378 : template <typename T>
44379 : class copy exprtk_final : public exprtk::igeneric_function<T>
44380 : {
44381 : public:
44382 :
44383 : typedef typename exprtk::igeneric_function<T> igfun_t;
44384 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44385 : typedef typename igfun_t::generic_type generic_type;
44386 : typedef typename generic_type::scalar_view scalar_t;
44387 : typedef typename generic_type::vector_view vector_t;
44388 :
44389 : using igfun_t::operator();
44390 :
44391 32 : copy()
44392 64 : : exprtk::igeneric_function<T>("VV|VTTVTT")
44393 : /*
44394 : Overloads:
44395 : 0. VV - x(vector), y(vector)
44396 : 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
44397 : */
44398 32 : {}
44399 :
44400 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44401 : {
44402 4 : const vector_t x(parameters[0]);
44403 4 : vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
44404 :
44405 4 : std::size_t xr0 = 0;
44406 4 : std::size_t xr1 = x.size() - 1;
44407 :
44408 4 : std::size_t yr0 = 0;
44409 4 : std::size_t yr1 = y.size() - 1;
44410 :
44411 4 : if (1 == ps_index)
44412 : {
44413 3 : if (
44414 6 : !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
44415 6 : !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
44416 : )
44417 0 : return T(0);
44418 : }
44419 :
44420 4 : const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
44421 :
44422 12 : std::copy(
44423 4 : x.begin() + xr0,
44424 4 : x.begin() + xr0 + n,
44425 4 : y.begin() + yr0);
44426 :
44427 4 : return T(n);
44428 : }
44429 : };
44430 :
44431 : template <typename T>
44432 : class rol exprtk_final : public exprtk::igeneric_function<T>
44433 : {
44434 : public:
44435 :
44436 : typedef typename exprtk::igeneric_function<T> igfun_t;
44437 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44438 : typedef typename igfun_t::generic_type generic_type;
44439 : typedef typename generic_type::scalar_view scalar_t;
44440 : typedef typename generic_type::vector_view vector_t;
44441 :
44442 : using igfun_t::operator();
44443 :
44444 32 : rol()
44445 64 : : exprtk::igeneric_function<T>("VT|VTTT")
44446 : /*
44447 : Overloads:
44448 : 0. VT - vector, N
44449 : 1. VTTT - vector, N, r0, r1
44450 : */
44451 32 : {}
44452 :
44453 3 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44454 : {
44455 3 : vector_t vec(parameters[0]);
44456 :
44457 3 : std::size_t n = 0;
44458 3 : std::size_t r0 = 0;
44459 3 : std::size_t r1 = vec.size() - 1;
44460 :
44461 3 : if (!scalar_t(parameters[1]).to_uint(n))
44462 0 : return T(0);
44463 :
44464 3 : if (
44465 4 : (1 == ps_index) &&
44466 4 : !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
44467 : )
44468 0 : return T(0);
44469 :
44470 3 : const std::size_t dist = r1 - r0 + 1;
44471 3 : const std::size_t shift = n % dist;
44472 :
44473 9 : std::rotate(
44474 3 : vec.begin() + r0,
44475 3 : vec.begin() + r0 + shift,
44476 3 : vec.begin() + r1 + 1);
44477 :
44478 3 : return T(1);
44479 : }
44480 : };
44481 :
44482 : template <typename T>
44483 : class ror exprtk_final : public exprtk::igeneric_function<T>
44484 : {
44485 : public:
44486 :
44487 : typedef typename exprtk::igeneric_function<T> igfun_t;
44488 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44489 : typedef typename igfun_t::generic_type generic_type;
44490 : typedef typename generic_type::scalar_view scalar_t;
44491 : typedef typename generic_type::vector_view vector_t;
44492 :
44493 : using igfun_t::operator();
44494 :
44495 32 : ror()
44496 64 : : exprtk::igeneric_function<T>("VT|VTTT")
44497 : /*
44498 : Overloads:
44499 : 0. VT - vector, N
44500 : 1. VTTT - vector, N, r0, r1
44501 : */
44502 32 : {}
44503 :
44504 3 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44505 : {
44506 3 : vector_t vec(parameters[0]);
44507 :
44508 3 : std::size_t n = 0;
44509 3 : std::size_t r0 = 0;
44510 3 : std::size_t r1 = vec.size() - 1;
44511 :
44512 3 : if (!scalar_t(parameters[1]).to_uint(n))
44513 0 : return T(0);
44514 :
44515 3 : if (
44516 4 : (1 == ps_index) &&
44517 4 : !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
44518 : )
44519 0 : return T(0);
44520 :
44521 3 : const std::size_t dist = r1 - r0 + 1;
44522 3 : const std::size_t shift = (dist - (n % dist)) % dist;
44523 :
44524 9 : std::rotate(
44525 3 : vec.begin() + r0,
44526 3 : vec.begin() + r0 + shift,
44527 3 : vec.begin() + r1 + 1);
44528 :
44529 3 : return T(1);
44530 : }
44531 : };
44532 :
44533 : template <typename T>
44534 : class reverse exprtk_final : public exprtk::igeneric_function<T>
44535 : {
44536 : public:
44537 :
44538 : typedef typename exprtk::igeneric_function<T> igfun_t;
44539 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44540 : typedef typename igfun_t::generic_type generic_type;
44541 : typedef typename generic_type::scalar_view scalar_t;
44542 : typedef typename generic_type::vector_view vector_t;
44543 :
44544 : using igfun_t::operator();
44545 :
44546 32 : reverse()
44547 64 : : exprtk::igeneric_function<T>("V|VTT")
44548 : /*
44549 : Overloads:
44550 : 0. V - vector
44551 : 1. VTT - vector, r0, r1
44552 : */
44553 32 : {}
44554 :
44555 100 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44556 : {
44557 100 : vector_t vec(parameters[0]);
44558 :
44559 100 : std::size_t r0 = 0;
44560 100 : std::size_t r1 = vec.size() - 1;
44561 :
44562 100 : if (
44563 175 : (1 == ps_index) &&
44564 175 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44565 : )
44566 0 : return T(0);
44567 :
44568 100 : std::reverse(vec.begin() + r0, vec.begin() + r1 + 1);
44569 :
44570 100 : return T(1);
44571 : }
44572 : };
44573 :
44574 : template <typename T>
44575 : class shift_left exprtk_final : public exprtk::igeneric_function<T>
44576 : {
44577 : public:
44578 :
44579 : typedef typename exprtk::igeneric_function<T> igfun_t;
44580 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44581 : typedef typename igfun_t::generic_type generic_type;
44582 : typedef typename generic_type::scalar_view scalar_t;
44583 : typedef typename generic_type::vector_view vector_t;
44584 :
44585 : using igfun_t::operator();
44586 :
44587 32 : shift_left()
44588 64 : : exprtk::igeneric_function<T>("VT|VTTT")
44589 : /*
44590 : Overloads:
44591 : 0. VT - vector, N
44592 : 1. VTTT - vector, N, r0, r1
44593 : */
44594 32 : {}
44595 :
44596 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44597 : {
44598 4 : vector_t vec(parameters[0]);
44599 :
44600 4 : std::size_t n = 0;
44601 4 : std::size_t r0 = 0;
44602 4 : std::size_t r1 = vec.size() - 1;
44603 :
44604 4 : if (!scalar_t(parameters[1]).to_uint(n))
44605 0 : return T(0);
44606 :
44607 4 : if (
44608 5 : (1 == ps_index) &&
44609 5 : !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
44610 : )
44611 0 : return T(0);
44612 :
44613 4 : const std::size_t dist = r1 - r0 + 1;
44614 :
44615 4 : if (n > dist)
44616 0 : return T(0);
44617 :
44618 12 : std::rotate(
44619 4 : vec.begin() + r0,
44620 4 : vec.begin() + r0 + n,
44621 4 : vec.begin() + r1 + 1);
44622 :
44623 16 : for (std::size_t i = r1 - n + 1; i <= r1; ++i)
44624 : {
44625 12 : vec[i] = T(0);
44626 : }
44627 :
44628 4 : return T(1);
44629 : }
44630 : };
44631 :
44632 : template <typename T>
44633 : class shift_right exprtk_final : public exprtk::igeneric_function<T>
44634 : {
44635 : public:
44636 :
44637 : typedef typename exprtk::igeneric_function<T> igfun_t;
44638 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44639 : typedef typename igfun_t::generic_type generic_type;
44640 : typedef typename generic_type::scalar_view scalar_t;
44641 : typedef typename generic_type::vector_view vector_t;
44642 :
44643 : using igfun_t::operator();
44644 :
44645 32 : shift_right()
44646 64 : : exprtk::igeneric_function<T>("VT|VTTT")
44647 : /*
44648 : Overloads:
44649 : 0. VT - vector, N
44650 : 1. VTTT - vector, N, r0, r1
44651 : */
44652 32 : {}
44653 :
44654 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44655 : {
44656 4 : vector_t vec(parameters[0]);
44657 :
44658 4 : std::size_t n = 0;
44659 4 : std::size_t r0 = 0;
44660 4 : std::size_t r1 = vec.size() - 1;
44661 :
44662 4 : if (!scalar_t(parameters[1]).to_uint(n))
44663 0 : return T(0);
44664 :
44665 4 : if (
44666 5 : (1 == ps_index) &&
44667 5 : !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
44668 : )
44669 0 : return T(0);
44670 :
44671 4 : const std::size_t dist = r1 - r0 + 1;
44672 :
44673 4 : if (n > dist)
44674 0 : return T(0);
44675 :
44676 4 : const std::size_t shift = (dist - (n % dist)) % dist;
44677 :
44678 12 : std::rotate(
44679 4 : vec.begin() + r0,
44680 4 : vec.begin() + r0 + shift,
44681 4 : vec.begin() + r1 + 1);
44682 :
44683 16 : for (std::size_t i = r0; i < r0 + n; ++i)
44684 : {
44685 12 : vec[i] = T(0);
44686 : }
44687 :
44688 4 : return T(1);
44689 : }
44690 : };
44691 :
44692 : template <typename T>
44693 : class sort exprtk_final : public exprtk::igeneric_function<T>
44694 : {
44695 : public:
44696 :
44697 : typedef typename exprtk::igeneric_function<T> igfun_t;
44698 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44699 : typedef typename igfun_t::generic_type generic_type;
44700 : typedef typename generic_type::string_view string_t;
44701 : typedef typename generic_type::vector_view vector_t;
44702 :
44703 : using igfun_t::operator();
44704 :
44705 32 : sort()
44706 64 : : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
44707 : /*
44708 : Overloads:
44709 : 0. V - vector
44710 : 1. VTT - vector, r0, r1
44711 : 2. VS - vector, string
44712 : 3. VSTT - vector, string, r0, r1
44713 : */
44714 32 : {}
44715 :
44716 20 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44717 : {
44718 20 : vector_t vec(parameters[0]);
44719 :
44720 20 : std::size_t r0 = 0;
44721 20 : std::size_t r1 = vec.size() - 1;
44722 :
44723 20 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
44724 0 : return T(0);
44725 20 : if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
44726 0 : return T(0);
44727 :
44728 20 : bool ascending = true;
44729 :
44730 20 : if ((2 == ps_index) || (3 == ps_index))
44731 : {
44732 24 : if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
44733 6 : ascending = true;
44734 12 : else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
44735 6 : ascending = false;
44736 : else
44737 0 : return T(0);
44738 : }
44739 :
44740 20 : if (ascending)
44741 28 : std::sort(
44742 14 : vec.begin() + r0,
44743 14 : vec.begin() + r1 + 1,
44744 : std::less<T>());
44745 : else
44746 12 : std::sort(
44747 6 : vec.begin() + r0,
44748 6 : vec.begin() + r1 + 1,
44749 : std::greater<T>());
44750 :
44751 20 : return T(1);
44752 : }
44753 : };
44754 :
44755 : template <typename T>
44756 : class nthelement exprtk_final : public exprtk::igeneric_function<T>
44757 : {
44758 : public:
44759 :
44760 : typedef typename exprtk::igeneric_function<T> igfun_t;
44761 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44762 : typedef typename igfun_t::generic_type generic_type;
44763 : typedef typename generic_type::scalar_view scalar_t;
44764 : typedef typename generic_type::vector_view vector_t;
44765 :
44766 : using igfun_t::operator();
44767 :
44768 32 : nthelement()
44769 64 : : exprtk::igeneric_function<T>("VT|VTTT")
44770 : /*
44771 : Overloads:
44772 : 0. VT - vector, nth-element
44773 : 1. VTTT - vector, nth-element, r0, r1
44774 : */
44775 32 : {}
44776 :
44777 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44778 : {
44779 4 : vector_t vec(parameters[0]);
44780 :
44781 4 : std::size_t n = 0;
44782 4 : std::size_t r0 = 0;
44783 4 : std::size_t r1 = vec.size() - 1;
44784 :
44785 4 : if (!scalar_t(parameters[1]).to_uint(n))
44786 0 : return T(0);
44787 :
44788 4 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
44789 : {
44790 0 : return std::numeric_limits<T>::quiet_NaN();
44791 : }
44792 :
44793 12 : std::nth_element(
44794 4 : vec.begin() + r0,
44795 4 : vec.begin() + r0 + n ,
44796 4 : vec.begin() + r1 + 1);
44797 :
44798 4 : return T(1);
44799 : }
44800 : };
44801 :
44802 : template <typename T>
44803 : class assign exprtk_final : public exprtk::igeneric_function<T>
44804 : {
44805 : public:
44806 :
44807 : typedef typename exprtk::igeneric_function<T> igfun_t;
44808 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44809 : typedef typename igfun_t::generic_type generic_type;
44810 : typedef typename generic_type::scalar_view scalar_t;
44811 : typedef typename generic_type::vector_view vector_t;
44812 :
44813 : using igfun_t::operator();
44814 :
44815 32 : assign()
44816 64 : : exprtk::igeneric_function<T>("VT|VTTT|VTTTT")
44817 : /*
44818 : Overloads:
44819 : 0. VT - vector, V
44820 : 1. VTTT - vector, V, r0, r1
44821 : 2. VTTTT - vector, V, r0, r1, SS
44822 : */
44823 32 : {}
44824 :
44825 380 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44826 : {
44827 380 : vector_t vec(parameters[0]);
44828 :
44829 380 : const T assign_value = scalar_t(parameters[1]);
44830 :
44831 380 : const std::size_t step_size = (2 != ps_index) ? 1 :
44832 230 : static_cast<std::size_t>(scalar_t(parameters.back())());
44833 :
44834 380 : std::size_t r0 = 0;
44835 380 : std::size_t r1 = vec.size() - 1;
44836 :
44837 380 : if (
44838 760 : ((ps_index == 1) || (ps_index == 2)) &&
44839 760 : !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
44840 : )
44841 : {
44842 0 : return T(0);
44843 : }
44844 :
44845 2080 : for (std::size_t i = r0; i <= r1; i += step_size)
44846 : {
44847 1700 : vec[i] = assign_value;
44848 : }
44849 :
44850 380 : return T(1);
44851 : }
44852 : };
44853 :
44854 : template <typename T>
44855 : class iota exprtk_final : public exprtk::igeneric_function<T>
44856 : {
44857 : public:
44858 :
44859 : typedef typename exprtk::igeneric_function<T> igfun_t;
44860 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44861 : typedef typename igfun_t::generic_type generic_type;
44862 : typedef typename generic_type::scalar_view scalar_t;
44863 : typedef typename generic_type::vector_view vector_t;
44864 :
44865 : using igfun_t::operator();
44866 :
44867 32 : iota()
44868 64 : : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT")
44869 : /*
44870 : Overloads:
44871 : 0. VTT - vector, SV, SS
44872 : 1. VT - vector, SV, SS (+1)
44873 : 2. VTTT - vector, r0, r1, SV, SS
44874 : 3. VTT - vector, r0, r1, SV, SS (+1)
44875 :
44876 : Where:
44877 : 1. SV - Start value
44878 : 2. SS - Step size
44879 : */
44880 32 : {}
44881 :
44882 318 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44883 : {
44884 318 : vector_t vec(parameters[0]);
44885 :
44886 636 : const T start_value = (ps_index <= 1) ?
44887 55 : scalar_t(parameters[1]) :
44888 263 : scalar_t(parameters[3]) ;
44889 :
44890 616 : const T step_size = ((0 == ps_index) || (2 == ps_index)) ?
44891 298 : scalar_t(parameters.back())() :
44892 : T(1) ;
44893 :
44894 318 : std::size_t r0 = 0;
44895 318 : std::size_t r1 = vec.size() - 1;
44896 :
44897 318 : if (
44898 581 : ((ps_index == 2) || (ps_index == 3)) &&
44899 581 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44900 : )
44901 : {
44902 0 : return T(0);
44903 : }
44904 :
44905 1820 : for (std::size_t i = r0; i <= r1; ++i)
44906 : {
44907 1502 : vec[i] = start_value + ((i - r0) * step_size);
44908 : }
44909 :
44910 318 : return T(1);
44911 : }
44912 : };
44913 :
44914 : template <typename T>
44915 : class sumk exprtk_final : public exprtk::igeneric_function<T>
44916 : {
44917 : public:
44918 :
44919 : typedef typename exprtk::igeneric_function<T> igfun_t;
44920 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44921 : typedef typename igfun_t::generic_type generic_type;
44922 : typedef typename generic_type::scalar_view scalar_t;
44923 : typedef typename generic_type::vector_view vector_t;
44924 :
44925 : using igfun_t::operator();
44926 :
44927 32 : sumk()
44928 64 : : exprtk::igeneric_function<T>("V|VTT|VTTT")
44929 : /*
44930 : Overloads:
44931 : 0. V - vector
44932 : 1. VTT - vector, r0, r1
44933 : 2. VTTT - vector, r0, r1, stride
44934 : */
44935 32 : {}
44936 :
44937 80 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44938 : {
44939 80 : const vector_t vec(parameters[0]);
44940 :
44941 80 : const std::size_t stride = (2 != ps_index) ? 1 :
44942 40 : static_cast<std::size_t>(scalar_t(parameters[3])());
44943 :
44944 80 : std::size_t r0 = 0;
44945 80 : std::size_t r1 = vec.size() - 1;
44946 :
44947 80 : if (
44948 140 : ((1 == ps_index) || (2 == ps_index)) &&
44949 140 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
44950 : )
44951 : {
44952 0 : return std::numeric_limits<T>::quiet_NaN();
44953 : }
44954 :
44955 80 : T result = T(0);
44956 80 : T error = T(0);
44957 :
44958 640 : for (std::size_t i = r0; i <= r1; i += stride)
44959 : {
44960 560 : details::kahan_sum(result, error, vec[i]);
44961 : }
44962 :
44963 80 : return result;
44964 : }
44965 : };
44966 :
44967 : template <typename T>
44968 : class axpy exprtk_final : public exprtk::igeneric_function<T>
44969 : {
44970 : public:
44971 :
44972 : typedef typename exprtk::igeneric_function<T> igfun_t;
44973 : typedef typename igfun_t::parameter_list_t parameter_list_t;
44974 : typedef typename igfun_t::generic_type generic_type;
44975 : typedef typename generic_type::scalar_view scalar_t;
44976 : typedef typename generic_type::vector_view vector_t;
44977 :
44978 : using igfun_t::operator();
44979 :
44980 32 : axpy()
44981 64 : : exprtk::igeneric_function<T>("TVV|TVVTT")
44982 : /*
44983 : y <- ax + y
44984 : Overloads:
44985 : 0. TVV - a, x(vector), y(vector)
44986 : 1. TVVTT - a, x(vector), y(vector), r0, r1
44987 : */
44988 32 : {}
44989 :
44990 51 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
44991 : {
44992 51 : const vector_t x(parameters[1]);
44993 51 : vector_t y(parameters[2]);
44994 :
44995 51 : std::size_t r0 = 0;
44996 51 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
44997 :
44998 51 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
44999 0 : return std::numeric_limits<T>::quiet_NaN();
45000 51 : else if (helper::invalid_range(y, r0, r1))
45001 0 : return std::numeric_limits<T>::quiet_NaN();
45002 :
45003 51 : const T a = scalar_t(parameters[0])();
45004 :
45005 254 : for (std::size_t i = r0; i <= r1; ++i)
45006 : {
45007 203 : y[i] = (a * x[i]) + y[i];
45008 : }
45009 :
45010 51 : return T(1);
45011 : }
45012 : };
45013 :
45014 : template <typename T>
45015 : class axpby exprtk_final : public exprtk::igeneric_function<T>
45016 : {
45017 : public:
45018 :
45019 : typedef typename exprtk::igeneric_function<T> igfun_t;
45020 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45021 : typedef typename igfun_t::generic_type generic_type;
45022 : typedef typename generic_type::scalar_view scalar_t;
45023 : typedef typename generic_type::vector_view vector_t;
45024 :
45025 : using igfun_t::operator();
45026 :
45027 32 : axpby()
45028 64 : : exprtk::igeneric_function<T>("TVTV|TVTVTT")
45029 : /*
45030 : y <- ax + by
45031 : Overloads:
45032 : 0. TVTV - a, x(vector), b, y(vector)
45033 : 1. TVTVTT - a, x(vector), b, y(vector), r0, r1
45034 : */
45035 32 : {}
45036 :
45037 41 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45038 : {
45039 41 : const vector_t x(parameters[1]);
45040 41 : vector_t y(parameters[3]);
45041 :
45042 41 : std::size_t r0 = 0;
45043 41 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45044 :
45045 41 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
45046 0 : return std::numeric_limits<T>::quiet_NaN();
45047 41 : else if (helper::invalid_range(y, r0, r1))
45048 0 : return std::numeric_limits<T>::quiet_NaN();
45049 :
45050 41 : const T a = scalar_t(parameters[0])();
45051 41 : const T b = scalar_t(parameters[2])();
45052 :
45053 204 : for (std::size_t i = r0; i <= r1; ++i)
45054 : {
45055 163 : y[i] = (a * x[i]) + (b * y[i]);
45056 : }
45057 :
45058 41 : return T(1);
45059 : }
45060 : };
45061 :
45062 : template <typename T>
45063 : class axpyz exprtk_final : public exprtk::igeneric_function<T>
45064 : {
45065 : public:
45066 :
45067 : typedef typename exprtk::igeneric_function<T> igfun_t;
45068 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45069 : typedef typename igfun_t::generic_type generic_type;
45070 : typedef typename generic_type::scalar_view scalar_t;
45071 : typedef typename generic_type::vector_view vector_t;
45072 :
45073 : using igfun_t::operator();
45074 :
45075 32 : axpyz()
45076 64 : : exprtk::igeneric_function<T>("TVVV|TVVVTT")
45077 : /*
45078 : z <- ax + y
45079 : Overloads:
45080 : 0. TVVV - a, x(vector), y(vector), z(vector)
45081 : 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
45082 : */
45083 32 : {}
45084 :
45085 41 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45086 : {
45087 41 : const vector_t x(parameters[1]);
45088 41 : const vector_t y(parameters[2]);
45089 41 : vector_t z(parameters[3]);
45090 :
45091 41 : std::size_t r0 = 0;
45092 41 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45093 :
45094 41 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
45095 0 : return std::numeric_limits<T>::quiet_NaN();
45096 41 : else if (helper::invalid_range(y, r0, r1))
45097 0 : return std::numeric_limits<T>::quiet_NaN();
45098 41 : else if (helper::invalid_range(z, r0, r1))
45099 0 : return std::numeric_limits<T>::quiet_NaN();
45100 :
45101 41 : const T a = scalar_t(parameters[0])();
45102 :
45103 204 : for (std::size_t i = r0; i <= r1; ++i)
45104 : {
45105 163 : z[i] = (a * x[i]) + y[i];
45106 : }
45107 :
45108 41 : return T(1);
45109 : }
45110 : };
45111 :
45112 : template <typename T>
45113 : class axpbyz exprtk_final : public exprtk::igeneric_function<T>
45114 : {
45115 : public:
45116 :
45117 : typedef typename exprtk::igeneric_function<T> igfun_t;
45118 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45119 : typedef typename igfun_t::generic_type generic_type;
45120 : typedef typename generic_type::scalar_view scalar_t;
45121 : typedef typename generic_type::vector_view vector_t;
45122 :
45123 : using igfun_t::operator();
45124 :
45125 32 : axpbyz()
45126 64 : : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
45127 : /*
45128 : z <- ax + by
45129 : Overloads:
45130 : 0. TVTVV - a, x(vector), b, y(vector), z(vector)
45131 : 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
45132 : */
45133 32 : {}
45134 :
45135 41 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45136 : {
45137 41 : const vector_t x(parameters[1]);
45138 41 : const vector_t y(parameters[3]);
45139 41 : vector_t z(parameters[4]);
45140 :
45141 41 : std::size_t r0 = 0;
45142 41 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45143 :
45144 41 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
45145 0 : return std::numeric_limits<T>::quiet_NaN();
45146 41 : else if (helper::invalid_range(y, r0, r1))
45147 0 : return std::numeric_limits<T>::quiet_NaN();
45148 41 : else if (helper::invalid_range(z, r0, r1))
45149 0 : return std::numeric_limits<T>::quiet_NaN();
45150 :
45151 41 : const T a = scalar_t(parameters[0])();
45152 41 : const T b = scalar_t(parameters[2])();
45153 :
45154 204 : for (std::size_t i = r0; i <= r1; ++i)
45155 : {
45156 163 : z[i] = (a * x[i]) + (b * y[i]);
45157 : }
45158 :
45159 41 : return T(1);
45160 : }
45161 : };
45162 :
45163 : template <typename T>
45164 : class axpbsy exprtk_final : public exprtk::igeneric_function<T>
45165 : {
45166 : public:
45167 :
45168 : typedef typename exprtk::igeneric_function<T> igfun_t;
45169 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45170 : typedef typename igfun_t::generic_type generic_type;
45171 : typedef typename generic_type::scalar_view scalar_t;
45172 : typedef typename generic_type::vector_view vector_t;
45173 :
45174 : using igfun_t::operator();
45175 :
45176 32 : axpbsy()
45177 64 : : exprtk::igeneric_function<T>("TVTTV|TVTTVTT")
45178 : /*
45179 : y <- ax + by
45180 : Overloads:
45181 : 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector)
45182 : 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
45183 : */
45184 32 : {}
45185 :
45186 0 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45187 : {
45188 0 : const vector_t x(parameters[1]);
45189 0 : vector_t y(parameters[4]);
45190 :
45191 0 : std::size_t r0 = 0;
45192 0 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45193 :
45194 0 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1))
45195 0 : return std::numeric_limits<T>::quiet_NaN();
45196 0 : else if (helper::invalid_range(y, r0, r1))
45197 0 : return std::numeric_limits<T>::quiet_NaN();
45198 :
45199 0 : const T a = scalar_t(parameters[0])();
45200 0 : const T b = scalar_t(parameters[2])();
45201 :
45202 0 : const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
45203 :
45204 0 : for (std::size_t i = r0; i <= r1; ++i)
45205 : {
45206 0 : y[i] = (a * x[i]) + (b * y[i + s]);
45207 : }
45208 :
45209 0 : return T(1);
45210 : }
45211 : };
45212 :
45213 : template <typename T>
45214 : class axpbsyz exprtk_final : public exprtk::igeneric_function<T>
45215 : {
45216 : public:
45217 :
45218 : typedef typename exprtk::igeneric_function<T> igfun_t;
45219 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45220 : typedef typename igfun_t::generic_type generic_type;
45221 : typedef typename generic_type::scalar_view scalar_t;
45222 : typedef typename generic_type::vector_view vector_t;
45223 :
45224 : using igfun_t::operator();
45225 :
45226 32 : axpbsyz()
45227 64 : : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT")
45228 : /*
45229 : z <- ax + by
45230 : Overloads:
45231 : 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector)
45232 : 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1
45233 : */
45234 32 : {}
45235 :
45236 0 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45237 : {
45238 0 : const vector_t x(parameters[1]);
45239 0 : const vector_t y(parameters[4]);
45240 0 : vector_t z(parameters[5]);
45241 :
45242 0 : std::size_t r0 = 0;
45243 0 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45244 :
45245 0 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1))
45246 0 : return std::numeric_limits<T>::quiet_NaN();
45247 0 : else if (helper::invalid_range(y, r0, r1))
45248 0 : return std::numeric_limits<T>::quiet_NaN();
45249 0 : else if (helper::invalid_range(z, r0, r1))
45250 0 : return std::numeric_limits<T>::quiet_NaN();
45251 :
45252 0 : const T a = scalar_t(parameters[0])();
45253 0 : const T b = scalar_t(parameters[2])();
45254 :
45255 0 : const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])());
45256 :
45257 0 : for (std::size_t i = r0; i <= r1; ++i)
45258 : {
45259 0 : z[i] = (a * x[i]) + (b * y[i + s]);
45260 : }
45261 :
45262 0 : return T(1);
45263 : }
45264 : };
45265 :
45266 : template <typename T>
45267 : class axpbz exprtk_final : public exprtk::igeneric_function<T>
45268 : {
45269 : public:
45270 :
45271 : typedef typename exprtk::igeneric_function<T> igfun_t;
45272 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45273 : typedef typename igfun_t::generic_type generic_type;
45274 : typedef typename generic_type::scalar_view scalar_t;
45275 : typedef typename generic_type::vector_view vector_t;
45276 :
45277 : using igfun_t::operator();
45278 :
45279 32 : axpbz()
45280 64 : : exprtk::igeneric_function<T>("TVTV|TVTVTT")
45281 : /*
45282 : z <- ax + b
45283 : Overloads:
45284 : 0. TVTV - a, x(vector), b, z(vector)
45285 : 1. TVTVTT - a, x(vector), b, z(vector), r0, r1
45286 : */
45287 32 : {}
45288 :
45289 51 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45290 : {
45291 51 : const vector_t x(parameters[1]);
45292 51 : vector_t z(parameters[3]);
45293 :
45294 51 : std::size_t r0 = 0;
45295 51 : std::size_t r1 = x.size() - 1;
45296 :
45297 51 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
45298 0 : return std::numeric_limits<T>::quiet_NaN();
45299 51 : else if (helper::invalid_range(z, r0, r1))
45300 0 : return std::numeric_limits<T>::quiet_NaN();
45301 :
45302 51 : const T a = scalar_t(parameters[0])();
45303 51 : const T b = scalar_t(parameters[2])();
45304 :
45305 254 : for (std::size_t i = r0; i <= r1; ++i)
45306 : {
45307 203 : z[i] = (a * x[i]) + b;
45308 : }
45309 :
45310 51 : return T(1);
45311 : }
45312 : };
45313 :
45314 : template <typename T>
45315 : class diff exprtk_final : public exprtk::igeneric_function<T>
45316 : {
45317 : public:
45318 :
45319 : typedef typename exprtk::igeneric_function<T> igfun_t;
45320 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45321 : typedef typename igfun_t::generic_type generic_type;
45322 : typedef typename generic_type::scalar_view scalar_t;
45323 : typedef typename generic_type::vector_view vector_t;
45324 :
45325 : using igfun_t::operator();
45326 :
45327 32 : diff()
45328 64 : : exprtk::igeneric_function<T>("VV|VVT")
45329 : /*
45330 : x_(i - stride) - x_i
45331 : Overloads:
45332 : 0. VV - x(vector), y(vector)
45333 : 1. VVT - x(vector), y(vector), stride
45334 : */
45335 32 : {}
45336 :
45337 20 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45338 : {
45339 20 : const vector_t x(parameters[0]);
45340 20 : vector_t y(parameters[1]);
45341 :
45342 20 : const std::size_t r0 = 0;
45343 20 : const std::size_t r1 = std::min(x.size(),y.size()) - 1;
45344 :
45345 30 : const std::size_t stride = (1 != ps_index) ? 1 :
45346 10 : std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])()));
45347 :
45348 50 : for (std::size_t i = 0; i < stride; ++i)
45349 : {
45350 30 : y[i] = std::numeric_limits<T>::quiet_NaN();
45351 : }
45352 :
45353 150 : for (std::size_t i = (r0 + stride); i <= r1; ++i)
45354 : {
45355 130 : y[i] = x[i] - x[i - stride];
45356 : }
45357 :
45358 20 : return T(1);
45359 : }
45360 : };
45361 :
45362 : template <typename T>
45363 : class dot exprtk_final : public exprtk::igeneric_function<T>
45364 : {
45365 : public:
45366 :
45367 : typedef typename exprtk::igeneric_function<T> igfun_t;
45368 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45369 : typedef typename igfun_t::generic_type generic_type;
45370 : typedef typename generic_type::scalar_view scalar_t;
45371 : typedef typename generic_type::vector_view vector_t;
45372 :
45373 : using igfun_t::operator();
45374 :
45375 32 : dot()
45376 64 : : exprtk::igeneric_function<T>("VV|VVTT")
45377 : /*
45378 : Overloads:
45379 : 0. VV - x(vector), y(vector)
45380 : 1. VVTT - x(vector), y(vector), r0, r1
45381 : */
45382 32 : {}
45383 :
45384 1840 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45385 : {
45386 1840 : const vector_t x(parameters[0]);
45387 1840 : const vector_t y(parameters[1]);
45388 :
45389 1840 : std::size_t r0 = 0;
45390 1840 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45391 :
45392 1840 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
45393 0 : return std::numeric_limits<T>::quiet_NaN();
45394 1840 : else if (helper::invalid_range(y, r0, r1))
45395 0 : return std::numeric_limits<T>::quiet_NaN();
45396 :
45397 1840 : T result = T(0);
45398 :
45399 11080 : for (std::size_t i = r0; i <= r1; ++i)
45400 : {
45401 9240 : result += (x[i] * y[i]);
45402 : }
45403 :
45404 1840 : return result;
45405 : }
45406 : };
45407 :
45408 : template <typename T>
45409 : class dotk exprtk_final : public exprtk::igeneric_function<T>
45410 : {
45411 : public:
45412 :
45413 : typedef typename exprtk::igeneric_function<T> igfun_t;
45414 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45415 : typedef typename igfun_t::generic_type generic_type;
45416 : typedef typename generic_type::scalar_view scalar_t;
45417 : typedef typename generic_type::vector_view vector_t;
45418 :
45419 : using igfun_t::operator();
45420 :
45421 32 : dotk()
45422 64 : : exprtk::igeneric_function<T>("VV|VVTT")
45423 : /*
45424 : Overloads:
45425 : 0. VV - x(vector), y(vector)
45426 : 1. VVTT - x(vector), y(vector), r0, r1
45427 : */
45428 32 : {}
45429 :
45430 0 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45431 : {
45432 0 : const vector_t x(parameters[0]);
45433 0 : const vector_t y(parameters[1]);
45434 :
45435 0 : std::size_t r0 = 0;
45436 0 : std::size_t r1 = std::min(x.size(),y.size()) - 1;
45437 :
45438 0 : if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
45439 0 : return std::numeric_limits<T>::quiet_NaN();
45440 0 : else if (helper::invalid_range(y, r0, r1))
45441 0 : return std::numeric_limits<T>::quiet_NaN();
45442 :
45443 0 : T result = T(0);
45444 0 : T error = T(0);
45445 :
45446 0 : for (std::size_t i = r0; i <= r1; ++i)
45447 : {
45448 0 : details::kahan_sum(result, error, (x[i] * y[i]));
45449 : }
45450 :
45451 0 : return result;
45452 : }
45453 : };
45454 :
45455 : template <typename T>
45456 : class threshold_below exprtk_final : public exprtk::igeneric_function<T>
45457 : {
45458 : public:
45459 :
45460 : typedef typename exprtk::igeneric_function<T> igfun_t;
45461 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45462 : typedef typename igfun_t::generic_type generic_type;
45463 : typedef typename generic_type::scalar_view scalar_t;
45464 : typedef typename generic_type::vector_view vector_t;
45465 :
45466 : using igfun_t::operator();
45467 :
45468 32 : threshold_below()
45469 64 : : exprtk::igeneric_function<T>("VTT|VTTTT")
45470 : /*
45471 : Overloads:
45472 : 0. VTT - vector, TV, SV
45473 : 1. VTTTT - vector, r0, r1, TV, SV
45474 :
45475 : Where:
45476 : TV - Threshold value
45477 : SV - Snap-to value
45478 : */
45479 32 : {}
45480 :
45481 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45482 : {
45483 4 : vector_t vec(parameters[0]);
45484 :
45485 8 : const T threshold_value = (0 == ps_index) ?
45486 1 : scalar_t(parameters[1]) :
45487 3 : scalar_t(parameters[3]) ;
45488 :
45489 4 : const T snap_value = scalar_t(parameters.back());
45490 :
45491 4 : std::size_t r0 = 0;
45492 4 : std::size_t r1 = vec.size() - 1;
45493 :
45494 4 : if (
45495 7 : (1 == ps_index) &&
45496 7 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
45497 : )
45498 : {
45499 0 : return T(0);
45500 : }
45501 :
45502 22 : for (std::size_t i = r0; i <= r1; ++i)
45503 : {
45504 18 : if (vec[i] < threshold_value)
45505 : {
45506 6 : vec[i] = snap_value;
45507 : }
45508 : }
45509 :
45510 4 : return T(1);
45511 : }
45512 : };
45513 :
45514 : template <typename T>
45515 : class threshold_above exprtk_final : public exprtk::igeneric_function<T>
45516 : {
45517 : public:
45518 :
45519 : typedef typename exprtk::igeneric_function<T> igfun_t;
45520 : typedef typename igfun_t::parameter_list_t parameter_list_t;
45521 : typedef typename igfun_t::generic_type generic_type;
45522 : typedef typename generic_type::scalar_view scalar_t;
45523 : typedef typename generic_type::vector_view vector_t;
45524 :
45525 : using igfun_t::operator();
45526 :
45527 32 : threshold_above()
45528 64 : : exprtk::igeneric_function<T>("VTT|VTTTT")
45529 : /*
45530 : Overloads:
45531 : 0. VTT - vector, TV, SV
45532 : 1. VTTTT - vector, r0, r1, TV, SV
45533 :
45534 : Where:
45535 : TV - Threshold value
45536 : SV - Snap-to value
45537 : */
45538 32 : {}
45539 :
45540 4 : inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override
45541 : {
45542 4 : vector_t vec(parameters[0]);
45543 :
45544 8 : const T threshold_value = (0 == ps_index) ?
45545 1 : scalar_t(parameters[1]) :
45546 3 : scalar_t(parameters[3]) ;
45547 :
45548 4 : const T snap_value = scalar_t(parameters.back());
45549 :
45550 4 : std::size_t r0 = 0;
45551 4 : std::size_t r1 = vec.size() - 1;
45552 :
45553 4 : if (
45554 7 : (1 == ps_index) &&
45555 7 : !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
45556 : )
45557 : {
45558 0 : return T(0);
45559 : }
45560 :
45561 22 : for (std::size_t i = r0; i <= r1; ++i)
45562 : {
45563 18 : if (vec[i] > threshold_value)
45564 : {
45565 8 : vec[i] = snap_value;
45566 : }
45567 : }
45568 :
45569 4 : return T(1);
45570 : }
45571 : };
45572 :
45573 : template <typename T>
45574 : struct package
45575 : {
45576 : all_true <T> at;
45577 : all_false <T> af;
45578 : any_true <T> nt;
45579 : any_false <T> nf;
45580 : count <T> c;
45581 : copy <T> cp;
45582 : rol <T> rl;
45583 : ror <T> rr;
45584 : reverse <T> rev;
45585 : shift_left <T> sl;
45586 : shift_right <T> sr;
45587 : sort <T> st;
45588 : nthelement <T> ne;
45589 : assign <T> an;
45590 : iota <T> ia;
45591 : sumk <T> sk;
45592 : axpy <T> b1_axpy;
45593 : axpby <T> b1_axpby;
45594 : axpyz <T> b1_axpyz;
45595 : axpbyz <T> b1_axpbyz;
45596 : axpbsy <T> b1_axpbsy;
45597 : axpbsyz <T> b1_axpbsyz;
45598 : axpbz <T> b1_axpbz;
45599 : diff <T> df;
45600 : dot <T> dt;
45601 : dotk <T> dtk;
45602 : threshold_above<T> ta;
45603 : threshold_below<T> tb;
45604 :
45605 32 : bool register_package(exprtk::symbol_table<T>& symtab)
45606 : {
45607 : #define exprtk_register_function(FunctionName, FunctionType) \
45608 : if (!symtab.add_function(FunctionName,FunctionType)) \
45609 : { \
45610 : exprtk_debug(( \
45611 : "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
45612 : FunctionName)); \
45613 : return false; \
45614 : } \
45615 :
45616 96 : exprtk_register_function("all_true" , at )
45617 96 : exprtk_register_function("all_false" , af )
45618 96 : exprtk_register_function("any_true" , nt )
45619 96 : exprtk_register_function("any_false" , nf )
45620 96 : exprtk_register_function("count" , c )
45621 96 : exprtk_register_function("copy" , cp )
45622 96 : exprtk_register_function("rotate_left" , rl )
45623 96 : exprtk_register_function("rol" , rl )
45624 96 : exprtk_register_function("rotate_right" , rr )
45625 96 : exprtk_register_function("ror" , rr )
45626 96 : exprtk_register_function("reverse" , rev )
45627 96 : exprtk_register_function("shftl" , sl )
45628 96 : exprtk_register_function("shftr" , sr )
45629 96 : exprtk_register_function("sort" , st )
45630 96 : exprtk_register_function("nth_element" , ne )
45631 96 : exprtk_register_function("assign" , an )
45632 96 : exprtk_register_function("iota" , ia )
45633 96 : exprtk_register_function("sumk" , sk )
45634 96 : exprtk_register_function("axpy" , b1_axpy )
45635 96 : exprtk_register_function("axpby" , b1_axpby )
45636 96 : exprtk_register_function("axpyz" , b1_axpyz )
45637 96 : exprtk_register_function("axpbyz" , b1_axpbyz )
45638 96 : exprtk_register_function("axpbsy" , b1_axpbsy )
45639 96 : exprtk_register_function("axpbsyz" , b1_axpbsyz)
45640 96 : exprtk_register_function("axpbz" , b1_axpbz )
45641 96 : exprtk_register_function("diff" , df )
45642 96 : exprtk_register_function("dot" , dt )
45643 96 : exprtk_register_function("dotk" , dtk )
45644 96 : exprtk_register_function("threshold_above" , ta )
45645 96 : exprtk_register_function("threshold_below" , tb )
45646 : #undef exprtk_register_function
45647 :
45648 32 : return true;
45649 : }
45650 : };
45651 :
45652 : } // namespace exprtk::rtl::vecops
45653 : } // namespace exprtk::rtl
45654 : } // namespace exprtk
45655 : #endif
45656 :
45657 : namespace exprtk
45658 : {
45659 : namespace information
45660 : {
45661 : using ::exprtk::details::char_cptr;
45662 :
45663 : static char_cptr library = "Mathematical Expression Toolkit";
45664 : static char_cptr version = "2.7182818284590452353602874713526624977"
45665 : "572470936999595749669676277240766303535"
45666 : "475945713821785251664274274663919320030"
45667 : "599218174135966290435729003342952605956";
45668 : static char_cptr date = "20240101";
45669 : static char_cptr min_cpp = "199711L";
45670 :
45671 : static inline std::string data()
45672 : {
45673 : static const std::string info_str = std::string(library) +
45674 : std::string(" v") + std::string(version) +
45675 : std::string(" (") + date + std::string(")") +
45676 : std::string(" (") + min_cpp + std::string(")");
45677 : return info_str;
45678 : }
45679 :
45680 : } // namespace information
45681 :
45682 : #ifdef exprtk_debug
45683 : #undef exprtk_debug
45684 : #endif
45685 :
45686 : #ifdef exprtk_error_location
45687 : #undef exprtk_error_location
45688 : #endif
45689 :
45690 : #ifdef exprtk_fallthrough
45691 : #undef exprtk_fallthrough
45692 : #endif
45693 :
45694 : #ifdef exprtk_override
45695 : #undef exprtk_override
45696 : #endif
45697 :
45698 : #ifdef exprtk_final
45699 : #undef exprtk_final
45700 : #endif
45701 :
45702 : #ifdef exprtk_delete
45703 : #undef exprtk_delete
45704 : #endif
45705 :
45706 : } // namespace exprtk
45707 :
45708 : #endif
|