]> sigrok.org Git - pulseview.git/blame - pv/exprtk.hpp
Fix handling of 64 channel devices
[pulseview.git] / pv / exprtk.hpp
CommitLineData
4640a84e
SA
1/*
2 ******************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * Author: Arash Partow (1999-2020) *
6 * URL: http://www.partow.net/programming/exprtk/index.html *
7 * *
8 * Copyright notice: *
9 * Free use of the C++ Mathematical Expression Toolkit Library is *
10 * permitted under the guidelines and in accordance with the most *
11 * current version of the MIT License. *
12 * http://www.opensource.org/licenses/MIT *
13 * *
14 * Example expressions: *
15 * (00) (y + x / y) * (x - y / x) *
16 * (01) (x^2 / sin(2 * pi / y)) - x / 2 *
17 * (02) sqrt(1 - (x^2)) *
18 * (03) 1 - sin(2 * x) + cos(pi / y) *
19 * (04) a * exp(2 * t) + c *
20 * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) *
21 * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
22 * (07) z := x + sin(2 * pi / y) *
23 * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
24 * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
25 * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) *
26 * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
27 * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
28 * *
29 ******************************************************************
30*/
31
32
33#ifndef INCLUDE_EXPRTK_HPP
34#define INCLUDE_EXPRTK_HPP
35
36
37#include <algorithm>
38#include <cctype>
39#include <cmath>
40#include <complex>
41#include <cstdio>
42#include <cstdlib>
43#include <cstring>
44#include <deque>
45#include <exception>
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
59namespace 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 defined(__GNUC__) && (__GNUC__ >= 7)
71
72 #define exprtk_disable_fallthrough_begin \
73 _Pragma ("GCC diagnostic push") \
74 _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
75
76 #define exprtk_disable_fallthrough_end \
77 _Pragma ("GCC diagnostic pop") \
78
79 #else
80 #define exprtk_disable_fallthrough_begin (void)0;
81 #define exprtk_disable_fallthrough_end (void)0;
82 #endif
83
84 namespace details
85 {
86 typedef unsigned char uchar_t;
87 typedef char char_t;
88 typedef uchar_t* uchar_ptr;
89 typedef char_t* char_ptr;
90 typedef uchar_t const* uchar_cptr;
91 typedef char_t const* char_cptr;
92 typedef unsigned long long int _uint64_t;
93 typedef long long int _int64_t;
94
95 inline bool is_whitespace(const char_t c)
96 {
97 return (' ' == c) || ('\n' == c) ||
98 ('\r' == c) || ('\t' == c) ||
99 ('\b' == c) || ('\v' == c) ||
100 ('\f' == c) ;
101 }
102
103 inline bool is_operator_char(const char_t c)
104 {
105 return ('+' == c) || ('-' == c) ||
106 ('*' == c) || ('/' == c) ||
107 ('^' == c) || ('<' == c) ||
108 ('>' == c) || ('=' == c) ||
109 (',' == c) || ('!' == c) ||
110 ('(' == c) || (')' == c) ||
111 ('[' == c) || (']' == c) ||
112 ('{' == c) || ('}' == c) ||
113 ('%' == c) || (':' == c) ||
114 ('?' == c) || ('&' == c) ||
115 ('|' == c) || (';' == c) ;
116 }
117
118 inline bool is_letter(const char_t c)
119 {
120 return (('a' <= c) && (c <= 'z')) ||
121 (('A' <= c) && (c <= 'Z')) ;
122 }
123
124 inline bool is_digit(const char_t c)
125 {
126 return ('0' <= c) && (c <= '9');
127 }
128
129 inline bool is_letter_or_digit(const char_t c)
130 {
131 return is_letter(c) || is_digit(c);
132 }
133
134 inline bool is_left_bracket(const char_t c)
135 {
136 return ('(' == c) || ('[' == c) || ('{' == c);
137 }
138
139 inline bool is_right_bracket(const char_t c)
140 {
141 return (')' == c) || (']' == c) || ('}' == c);
142 }
143
144 inline bool is_bracket(const char_t c)
145 {
146 return is_left_bracket(c) || is_right_bracket(c);
147 }
148
149 inline bool is_sign(const char_t c)
150 {
151 return ('+' == c) || ('-' == c);
152 }
153
154 inline bool is_invalid(const char_t c)
155 {
156 return !is_whitespace (c) &&
157 !is_operator_char(c) &&
158 !is_letter (c) &&
159 !is_digit (c) &&
160 ('.' != c) &&
161 ('_' != c) &&
162 ('$' != c) &&
163 ('~' != c) &&
164 ('\'' != c);
165 }
166
167 #ifndef exprtk_disable_caseinsensitivity
168 inline void case_normalise(std::string& s)
169 {
170 for (std::size_t i = 0; i < s.size(); ++i)
171 {
172 s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
173 }
174 }
175
176 inline bool imatch(const char_t c1, const char_t c2)
177 {
178 return std::tolower(c1) == std::tolower(c2);
179 }
180
181 inline bool imatch(const std::string& s1, const std::string& s2)
182 {
183 if (s1.size() == s2.size())
184 {
185 for (std::size_t i = 0; i < s1.size(); ++i)
186 {
187 if (std::tolower(s1[i]) != std::tolower(s2[i]))
188 {
189 return false;
190 }
191 }
192
193 return true;
194 }
195
196 return false;
197 }
198
199 struct ilesscompare
200 {
201 inline bool operator() (const std::string& s1, const std::string& s2) const
202 {
203 const std::size_t length = std::min(s1.size(),s2.size());
204
205 for (std::size_t i = 0; i < length; ++i)
206 {
207 const char_t c1 = static_cast<char>(std::tolower(s1[i]));
208 const char_t c2 = static_cast<char>(std::tolower(s2[i]));
209
210 if (c1 > c2)
211 return false;
212 else if (c1 < c2)
213 return true;
214 }
215
216 return s1.size() < s2.size();
217 }
218 };
219
220 #else
221 inline void case_normalise(std::string&)
222 {}
223
224 inline bool imatch(const char_t c1, const char_t c2)
225 {
226 return c1 == c2;
227 }
228
229 inline bool imatch(const std::string& s1, const std::string& s2)
230 {
231 return s1 == s2;
232 }
233
234 struct ilesscompare
235 {
236 inline bool operator() (const std::string& s1, const std::string& s2) const
237 {
238 return s1 < s2;
239 }
240 };
241 #endif
242
243 inline bool is_valid_sf_symbol(const std::string& symbol)
244 {
245 // Special function: $f12 or $F34
246 return (4 == symbol.size()) &&
247 ('$' == symbol[0]) &&
248 imatch('f',symbol[1]) &&
249 is_digit(symbol[2]) &&
250 is_digit(symbol[3]);
251 }
252
253 inline const char_t& front(const std::string& s)
254 {
255 return s[0];
256 }
257
258 inline const char_t& back(const std::string& s)
259 {
260 return s[s.size() - 1];
261 }
262
263 inline std::string to_str(int i)
264 {
265 if (0 == i)
266 return std::string("0");
267
268 std::string result;
269
270 if (i < 0)
271 {
272 for ( ; i; i /= 10)
273 {
274 result += '0' + char(-(i % 10));
275 }
276
277 result += '-';
278 }
279 else
280 {
281 for ( ; i; i /= 10)
282 {
283 result += '0' + char(i % 10);
284 }
285 }
286
287 std::reverse(result.begin(), result.end());
288
289 return result;
290 }
291
292 inline std::string to_str(std::size_t i)
293 {
294 return to_str(static_cast<int>(i));
295 }
296
297 inline bool is_hex_digit(const std::string::value_type digit)
298 {
299 return (('0' <= digit) && (digit <= '9')) ||
300 (('A' <= digit) && (digit <= 'F')) ||
301 (('a' <= digit) && (digit <= 'f')) ;
302 }
303
304 inline uchar_t hex_to_bin(uchar_t h)
305 {
306 if (('0' <= h) && (h <= '9'))
307 return (h - '0');
308 else
309 return static_cast<unsigned char>(std::toupper(h) - 'A');
310 }
311
312 template <typename Iterator>
313 inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
314 {
315 if (
316 (end != (itr )) &&
317 (end != (itr + 1)) &&
318 (end != (itr + 2)) &&
319 (end != (itr + 3)) &&
320 ('0' == *(itr )) &&
321 (
322 ('x' == *(itr + 1)) ||
323 ('X' == *(itr + 1))
324 ) &&
325 (is_hex_digit(*(itr + 2))) &&
326 (is_hex_digit(*(itr + 3)))
327 )
328 {
329 result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
330 hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
331 itr += 3;
332 }
333 else
334 result = '\0';
335 }
336
337 inline void cleanup_escapes(std::string& s)
338 {
339 typedef std::string::iterator str_itr_t;
340
341 str_itr_t itr1 = s.begin();
342 str_itr_t itr2 = s.begin();
343 str_itr_t end = s.end ();
344
345 std::size_t removal_count = 0;
346
347 while (end != itr1)
348 {
349 if ('\\' == (*itr1))
350 {
351 ++removal_count;
352
353 if (end == ++itr1)
354 break;
355 else if ('\\' != (*itr1))
356 {
357 switch (*itr1)
358 {
359 case 'n' : (*itr1) = '\n'; break;
360 case 'r' : (*itr1) = '\r'; break;
361 case 't' : (*itr1) = '\t'; break;
362 case '0' : parse_hex(itr1, end, (*itr1));
363 removal_count += 3;
364 break;
365 }
366
367 continue;
368 }
369 }
370
371 if (itr1 != itr2)
372 {
373 (*itr2) = (*itr1);
374 }
375
376 ++itr1;
377 ++itr2;
378 }
379
380 s.resize(s.size() - removal_count);
381 }
382
383 class build_string
384 {
385 public:
386
387 build_string(const std::size_t& initial_size = 64)
388 {
389 data_.reserve(initial_size);
390 }
391
392 inline build_string& operator << (const std::string& s)
393 {
394 data_ += s;
395 return (*this);
396 }
397
398 inline build_string& operator << (char_cptr s)
399 {
400 data_ += std::string(s);
401 return (*this);
402 }
403
404 inline operator std::string () const
405 {
406 return data_;
407 }
408
409 inline std::string as_string() const
410 {
411 return data_;
412 }
413
414 private:
415
416 std::string data_;
417 };
418
419 static const std::string reserved_words[] =
420 {
421 "break", "case", "continue", "default", "false", "for",
422 "if", "else", "ilike", "in", "like", "and", "nand", "nor",
423 "not", "null", "or", "repeat", "return", "shl", "shr",
424 "swap", "switch", "true", "until", "var", "while", "xnor",
425 "xor", "&", "|"
426 };
427
428 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
429
430 static const std::string reserved_symbols[] =
431 {
432 "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
433 "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
434 "continue", "cos", "cosh", "cot", "csc", "default",
435 "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
436 "expm1", "false", "floor", "for", "frac", "grad2deg",
437 "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
438 "like", "log", "log10", "log2", "logn", "log1p", "mand",
439 "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
440 "not", "not_equal", "null", "or", "pow", "rad2deg",
441 "repeat", "return", "root", "round", "roundn", "sec", "sgn",
442 "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
443 "switch", "tan", "tanh", "true", "trunc", "until", "var",
444 "while", "xnor", "xor", "&", "|"
445 };
446
447 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
448
449 static const std::string base_function_list[] =
450 {
451 "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
452 "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
453 "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
454 "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
455 "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
456 "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
457 "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
458 "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
459 "rad2deg", "grad2deg"
460 };
461
462 static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
463
464 static const std::string logic_ops_list[] =
465 {
466 "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
467 };
468
469 static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
470
471 static const std::string cntrl_struct_list[] =
472 {
473 "if", "switch", "for", "while", "repeat", "return"
474 };
475
476 static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
477
478 static const std::string arithmetic_ops_list[] =
479 {
480 "+", "-", "*", "/", "%", "^"
481 };
482
483 static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
484
485 static const std::string assignment_ops_list[] =
486 {
487 ":=", "+=", "-=",
488 "*=", "/=", "%="
489 };
490
491 static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
492
493 static const std::string inequality_ops_list[] =
494 {
495 "<", "<=", "==",
496 "=", "!=", "<>",
497 ">=", ">"
498 };
499
500 static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
501
502 inline bool is_reserved_word(const std::string& symbol)
503 {
504 for (std::size_t i = 0; i < reserved_words_size; ++i)
505 {
506 if (imatch(symbol, reserved_words[i]))
507 {
508 return true;
509 }
510 }
511
512 return false;
513 }
514
515 inline bool is_reserved_symbol(const std::string& symbol)
516 {
517 for (std::size_t i = 0; i < reserved_symbols_size; ++i)
518 {
519 if (imatch(symbol, reserved_symbols[i]))
520 {
521 return true;
522 }
523 }
524
525 return false;
526 }
527
528 inline bool is_base_function(const std::string& function_name)
529 {
530 for (std::size_t i = 0; i < base_function_list_size; ++i)
531 {
532 if (imatch(function_name, base_function_list[i]))
533 {
534 return true;
535 }
536 }
537
538 return false;
539 }
540
541 inline bool is_control_struct(const std::string& cntrl_strct)
542 {
543 for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
544 {
545 if (imatch(cntrl_strct, cntrl_struct_list[i]))
546 {
547 return true;
548 }
549 }
550
551 return false;
552 }
553
554 inline bool is_logic_opr(const std::string& lgc_opr)
555 {
556 for (std::size_t i = 0; i < logic_ops_list_size; ++i)
557 {
558 if (imatch(lgc_opr, logic_ops_list[i]))
559 {
560 return true;
561 }
562 }
563
564 return false;
565 }
566
567 struct cs_match
568 {
569 static inline bool cmp(const char_t c0, const char_t c1)
570 {
571 return (c0 == c1);
572 }
573 };
574
575 struct cis_match
576 {
577 static inline bool cmp(const char_t c0, const char_t c1)
578 {
579 return (std::tolower(c0) == std::tolower(c1));
580 }
581 };
582
583 template <typename Iterator, typename Compare>
584 inline bool match_impl(const Iterator pattern_begin,
585 const Iterator pattern_end ,
586 const Iterator data_begin ,
587 const Iterator data_end ,
588 const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
589 const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
590 {
591 const Iterator null_itr(0);
592
593 Iterator d_itr = data_begin;
594 Iterator p_itr = pattern_begin;
595 Iterator tb_p_itr = null_itr;
596 Iterator tb_d_itr = null_itr;
597
598 while (d_itr != data_end)
599 {
600 if (zero_or_more == *p_itr)
601 {
602 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
603 {
604 ++p_itr;
605 }
606
607 if (pattern_end == p_itr)
608 return true;
609
610 const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
611
612 while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
613 {
614 ++d_itr;
615 }
616
617 tb_p_itr = p_itr;
618 tb_d_itr = d_itr;
619
620 continue;
621 }
622 else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
623 {
624 if (null_itr == tb_d_itr)
625 return false;
626
627 d_itr = tb_d_itr++;
628 p_itr = tb_p_itr;
629
630 continue;
631 }
632
633 ++p_itr;
634 ++d_itr;
635 }
636
637 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
638 {
639 ++p_itr;
640 }
641
642 return (pattern_end == p_itr);
643 }
644
645 inline bool wc_match(const std::string& wild_card,
646 const std::string& str)
647 {
648 return match_impl<char_cptr,cs_match>(wild_card.data(),
649 wild_card.data() + wild_card.size(),
650 str.data(),
651 str.data() + str.size(),
652 '*',
653 '?');
654 }
655
656 inline bool wc_imatch(const std::string& wild_card,
657 const std::string& str)
658 {
659 return match_impl<char_cptr,cis_match>(wild_card.data(),
660 wild_card.data() + wild_card.size(),
661 str.data(),
662 str.data() + str.size(),
663 '*',
664 '?');
665 }
666
667 inline bool sequence_match(const std::string& pattern,
668 const std::string& str,
669 std::size_t& diff_index,
670 char_t& diff_value)
671 {
672 if (str.empty())
673 {
674 return ("Z" == pattern);
675 }
676 else if ('*' == pattern[0])
677 return false;
678
679 typedef std::string::const_iterator itr_t;
680
681 itr_t p_itr = pattern.begin();
682 itr_t s_itr = str .begin();
683
684 itr_t p_end = pattern.end();
685 itr_t s_end = str .end();
686
687 while ((s_end != s_itr) && (p_end != p_itr))
688 {
689 if ('*' == (*p_itr))
690 {
691 const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
692
693 if ('*' == target)
694 {
695 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
696 diff_value = static_cast<char>(std::toupper(*p_itr));
697
698 return false;
699 }
700 else
701 ++p_itr;
702
703 while (s_itr != s_end)
704 {
705 if (target != std::toupper(*s_itr))
706 break;
707 else
708 ++s_itr;
709 }
710
711 continue;
712 }
713 else if (
714 ('?' != *p_itr) &&
715 std::toupper(*p_itr) != std::toupper(*s_itr)
716 )
717 {
718 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
719 diff_value = static_cast<char>(std::toupper(*p_itr));
720
721 return false;
722 }
723
724 ++p_itr;
725 ++s_itr;
726 }
727
728 return (
729 (s_end == s_itr) &&
730 (
731 (p_end == p_itr) ||
732 ('*' == *p_itr)
733 )
734 );
735 }
736
737 static const double pow10[] = {
738 1.0,
739 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
740 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
741 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
742 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
743 };
744
745 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
746
747 namespace numeric
748 {
749 namespace constant
750 {
751 static const double e = 2.71828182845904523536028747135266249775724709369996;
752 static const double pi = 3.14159265358979323846264338327950288419716939937510;
753 static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
754 static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
755 static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
756 static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
757 static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
758 static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
759 static const double log2 = 0.69314718055994530941723212145817656807550013436026;
760 static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
761 }
762
763 namespace details
764 {
765 struct unknown_type_tag { unknown_type_tag() {} };
766 struct real_type_tag { real_type_tag () {} };
767 struct complex_type_tag { complex_type_tag() {} };
768 struct int_type_tag { int_type_tag () {} };
769
770 template <typename T>
771 struct number_type
772 {
773 typedef unknown_type_tag type;
774 number_type() {}
775 };
776
777 #define exprtk_register_real_type_tag(T) \
778 template<> struct number_type<T> \
779 { typedef real_type_tag type; number_type() {} }; \
780
781 #define exprtk_register_complex_type_tag(T) \
782 template<> struct number_type<std::complex<T> > \
783 { typedef complex_type_tag type; number_type() {} }; \
784
785 #define exprtk_register_int_type_tag(T) \
786 template<> struct number_type<T> \
787 { typedef int_type_tag type; number_type() {} }; \
788
789 exprtk_register_real_type_tag(double )
790 exprtk_register_real_type_tag(long double)
791 exprtk_register_real_type_tag(float )
792
793 exprtk_register_complex_type_tag(double )
794 exprtk_register_complex_type_tag(long double)
795 exprtk_register_complex_type_tag(float )
796
797 exprtk_register_int_type_tag(short )
798 exprtk_register_int_type_tag(int )
799 exprtk_register_int_type_tag(_int64_t )
800 exprtk_register_int_type_tag(unsigned short)
801 exprtk_register_int_type_tag(unsigned int )
802 exprtk_register_int_type_tag(_uint64_t )
803
804 #undef exprtk_register_real_type_tag
805 #undef exprtk_register_int_type_tag
806
807 template <typename T>
808 struct epsilon_type
809 {
810 static inline T value()
811 {
812 const T epsilon = T(0.0000000001);
813 return epsilon;
814 }
815 };
816
817 template <>
818 struct epsilon_type <float>
819 {
820 static inline float value()
821 {
822 const float epsilon = float(0.000001f);
823 return epsilon;
824 }
825 };
826
827 template <>
828 struct epsilon_type <long double>
829 {
830 static inline long double value()
831 {
832 const long double epsilon = (long double)(0.000000000001);
833 return epsilon;
834 }
835 };
836
837 template <typename T>
838 inline bool is_nan_impl(const T v, real_type_tag)
839 {
840 return std::not_equal_to<T>()(v,v);
841 }
842
843 template <typename T>
844 inline int to_int32_impl(const T v, real_type_tag)
845 {
846 return static_cast<int>(v);
847 }
848
849 template <typename T>
850 inline _int64_t to_int64_impl(const T v, real_type_tag)
851 {
852 return static_cast<_int64_t>(v);
853 }
854
855 template <typename T>
856 inline bool is_true_impl(const T v)
857 {
858 return std::not_equal_to<T>()(T(0),v);
859 }
860
861 template <typename T>
862 inline bool is_false_impl(const T v)
863 {
864 return std::equal_to<T>()(T(0),v);
865 }
866
867 template <typename T>
868 inline T abs_impl(const T v, real_type_tag)
869 {
870 return ((v < T(0)) ? -v : v);
871 }
872
873 template <typename T>
874 inline T min_impl(const T v0, const T v1, real_type_tag)
875 {
876 return std::min<T>(v0,v1);
877 }
878
879 template <typename T>
880 inline T max_impl(const T v0, const T v1, real_type_tag)
881 {
882 return std::max<T>(v0,v1);
883 }
884
885 template <typename T>
886 inline T equal_impl(const T v0, const T v1, real_type_tag)
887 {
888 const T epsilon = epsilon_type<T>::value();
889 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);
890 }
891
892 inline float equal_impl(const float v0, const float v1, real_type_tag)
893 {
894 const float epsilon = epsilon_type<float>::value();
895 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;
896 }
897
898 template <typename T>
899 inline T equal_impl(const T v0, const T v1, int_type_tag)
900 {
901 return (v0 == v1) ? 1 : 0;
902 }
903
904 template <typename T>
905 inline T expm1_impl(const T v, real_type_tag)
906 {
907 // return std::expm1<T>(v);
908 if (abs_impl(v,real_type_tag()) < T(0.00001))
909 return v + (T(0.5) * v * v);
910 else
911 return std::exp(v) - T(1);
912 }
913
914 template <typename T>
915 inline T expm1_impl(const T v, int_type_tag)
916 {
917 return T(std::exp<double>(v)) - T(1);
918 }
919
920 template <typename T>
921 inline T nequal_impl(const T v0, const T v1, real_type_tag)
922 {
923 typedef real_type_tag rtg;
924 const T epsilon = epsilon_type<T>::value();
925 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);
926 }
927
928 inline float nequal_impl(const float v0, const float v1, real_type_tag)
929 {
930 typedef real_type_tag rtg;
931 const float epsilon = epsilon_type<float>::value();
932 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;
933 }
934
935 template <typename T>
936 inline T nequal_impl(const T v0, const T v1, int_type_tag)
937 {
938 return (v0 != v1) ? 1 : 0;
939 }
940
941 template <typename T>
942 inline T modulus_impl(const T v0, const T v1, real_type_tag)
943 {
944 return std::fmod(v0,v1);
945 }
946
947 template <typename T>
948 inline T modulus_impl(const T v0, const T v1, int_type_tag)
949 {
950 return v0 % v1;
951 }
952
953 template <typename T>
954 inline T pow_impl(const T v0, const T v1, real_type_tag)
955 {
956 return std::pow(v0,v1);
957 }
958
959 template <typename T>
960 inline T pow_impl(const T v0, const T v1, int_type_tag)
961 {
962 return std::pow(static_cast<double>(v0),static_cast<double>(v1));
963 }
964
965 template <typename T>
966 inline T logn_impl(const T v0, const T v1, real_type_tag)
967 {
968 return std::log(v0) / std::log(v1);
969 }
970
971 template <typename T>
972 inline T logn_impl(const T v0, const T v1, int_type_tag)
973 {
974 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
975 }
976
977 template <typename T>
978 inline T log1p_impl(const T v, real_type_tag)
979 {
980 if (v > T(-1))
981 {
982 if (abs_impl(v,real_type_tag()) > T(0.0001))
983 {
984 return std::log(T(1) + v);
985 }
986 else
987 return (T(-0.5) * v + T(1)) * v;
988 }
989 else
990 return std::numeric_limits<T>::quiet_NaN();
991 }
992
993 template <typename T>
994 inline T log1p_impl(const T v, int_type_tag)
995 {
996 if (v > T(-1))
997 {
998 return std::log(T(1) + v);
999 }
1000 else
1001 return std::numeric_limits<T>::quiet_NaN();
1002 }
1003
1004 template <typename T>
1005 inline T root_impl(const T v0, const T v1, real_type_tag)
1006 {
1007 if (v1 < T(0))
1008 return std::numeric_limits<T>::quiet_NaN();
1009
1010 const std::size_t n = static_cast<std::size_t>(v1);
1011
1012 if ((v0 < T(0)) && (0 == (n % 2)))
1013 return std::numeric_limits<T>::quiet_NaN();
1014
1015 return std::pow(v0, T(1) / n);
1016 }
1017
1018 template <typename T>
1019 inline T root_impl(const T v0, const T v1, int_type_tag)
1020 {
1021 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1022 }
1023
1024 template <typename T>
1025 inline T round_impl(const T v, real_type_tag)
1026 {
1027 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1028 }
1029
1030 template <typename T>
1031 inline T roundn_impl(const T v0, const T v1, real_type_tag)
1032 {
1033 const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
1034 const T p10 = T(pow10[index]);
1035
1036 if (v0 < T(0))
1037 return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1038 else
1039 return T(std::floor((v0 * p10) + T(0.5)) / p10);
1040 }
1041
1042 template <typename T>
1043 inline T roundn_impl(const T v0, const T, int_type_tag)
1044 {
1045 return v0;
1046 }
1047
1048 template <typename T>
1049 inline T hypot_impl(const T v0, const T v1, real_type_tag)
1050 {
1051 return std::sqrt((v0 * v0) + (v1 * v1));
1052 }
1053
1054 template <typename T>
1055 inline T hypot_impl(const T v0, const T v1, int_type_tag)
1056 {
1057 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1058 }
1059
1060 template <typename T>
1061 inline T atan2_impl(const T v0, const T v1, real_type_tag)
1062 {
1063 return std::atan2(v0,v1);
1064 }
1065
1066 template <typename T>
1067 inline T atan2_impl(const T, const T, int_type_tag)
1068 {
1069 return 0;
1070 }
1071
1072 template <typename T>
1073 inline T shr_impl(const T v0, const T v1, real_type_tag)
1074 {
1075 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1076 }
1077
1078 template <typename T>
1079 inline T shr_impl(const T v0, const T v1, int_type_tag)
1080 {
1081 return v0 >> v1;
1082 }
1083
1084 template <typename T>
1085 inline T shl_impl(const T v0, const T v1, real_type_tag)
1086 {
1087 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1088 }
1089
1090 template <typename T>
1091 inline T shl_impl(const T v0, const T v1, int_type_tag)
1092 {
1093 return v0 << v1;
1094 }
1095
1096 template <typename T>
1097 inline T sgn_impl(const T v, real_type_tag)
1098 {
1099 if (v > T(0)) return T(+1);
1100 else if (v < T(0)) return T(-1);
1101 else return T( 0);
1102 }
1103
1104 template <typename T>
1105 inline T sgn_impl(const T v, int_type_tag)
1106 {
1107 if (v > T(0)) return T(+1);
1108 else if (v < T(0)) return T(-1);
1109 else return T( 0);
1110 }
1111
1112 template <typename T>
1113 inline T and_impl(const T v0, const T v1, real_type_tag)
1114 {
1115 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1116 }
1117
1118 template <typename T>
1119 inline T and_impl(const T v0, const T v1, int_type_tag)
1120 {
1121 return v0 && v1;
1122 }
1123
1124 template <typename T>
1125 inline T nand_impl(const T v0, const T v1, real_type_tag)
1126 {
1127 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1128 }
1129
1130 template <typename T>
1131 inline T nand_impl(const T v0, const T v1, int_type_tag)
1132 {
1133 return !(v0 && v1);
1134 }
1135
1136 template <typename T>
1137 inline T or_impl(const T v0, const T v1, real_type_tag)
1138 {
1139 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1140 }
1141
1142 template <typename T>
1143 inline T or_impl(const T v0, const T v1, int_type_tag)
1144 {
1145 return (v0 || v1);
1146 }
1147
1148 template <typename T>
1149 inline T nor_impl(const T v0, const T v1, real_type_tag)
1150 {
1151 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1152 }
1153
1154 template <typename T>
1155 inline T nor_impl(const T v0, const T v1, int_type_tag)
1156 {
1157 return !(v0 || v1);
1158 }
1159
1160 template <typename T>
1161 inline T xor_impl(const T v0, const T v1, real_type_tag)
1162 {
1163 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1164 }
1165
1166 template <typename T>
1167 inline T xor_impl(const T v0, const T v1, int_type_tag)
1168 {
1169 return v0 ^ v1;
1170 }
1171
1172 template <typename T>
1173 inline T xnor_impl(const T v0, const T v1, real_type_tag)
1174 {
1175 const bool v0_true = is_true_impl(v0);
1176 const bool v1_true = is_true_impl(v1);
1177
1178 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1179 return T(1);
1180 else
1181 return T(0);
1182 }
1183
1184 template <typename T>
1185 inline T xnor_impl(const T v0, const T v1, int_type_tag)
1186 {
1187 const bool v0_true = is_true_impl(v0);
1188 const bool v1_true = is_true_impl(v1);
1189
1190 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1191 return T(1);
1192 else
1193 return T(0);
1194 }
1195
1196 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1197 #define exprtk_define_erf(TT,impl) \
1198 inline TT erf_impl(TT v) { return impl(v); } \
1199
1200 exprtk_define_erf( float,::erff)
1201 exprtk_define_erf( double,::erf )
1202 exprtk_define_erf(long double,::erfl)
1203 #undef exprtk_define_erf
1204 #endif
1205
1206 template <typename T>
1207 inline T erf_impl(T v, real_type_tag)
1208 {
1209 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1210 // Credits: Abramowitz & Stegun Equations 7.1.25-28
1211 static const T c[] = {
1212 T( 1.26551223), T(1.00002368),
1213 T( 0.37409196), T(0.09678418),
1214 T(-0.18628806), T(0.27886807),
1215 T(-1.13520398), T(1.48851587),
1216 T(-0.82215223), T(0.17087277)
1217 };
1218
1219 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1220
1221 T result = T(1) - t * std::exp((-v * v) -
1222 c[0] + t * (c[1] + t *
1223 (c[2] + t * (c[3] + t *
1224 (c[4] + t * (c[5] + t *
1225 (c[6] + t * (c[7] + t *
1226 (c[8] + t * (c[9]))))))))));
1227
1228 return (v >= T(0)) ? result : -result;
1229 #else
1230 return erf_impl(v);
1231 #endif
1232 }
1233
1234 template <typename T>
1235 inline T erf_impl(T v, int_type_tag)
1236 {
1237 return erf_impl(static_cast<double>(v),real_type_tag());
1238 }
1239
1240 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1241 #define exprtk_define_erfc(TT,impl) \
1242 inline TT erfc_impl(TT v) { return impl(v); } \
1243
1244 exprtk_define_erfc( float,::erfcf)
1245 exprtk_define_erfc( double,::erfc )
1246 exprtk_define_erfc(long double,::erfcl)
1247 #undef exprtk_define_erfc
1248 #endif
1249
1250 template <typename T>
1251 inline T erfc_impl(T v, real_type_tag)
1252 {
1253 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1254 return T(1) - erf_impl(v,real_type_tag());
1255 #else
1256 return erfc_impl(v);
1257 #endif
1258 }
1259
1260 template <typename T>
1261 inline T erfc_impl(T v, int_type_tag)
1262 {
1263 return erfc_impl(static_cast<double>(v),real_type_tag());
1264 }
1265
1266 template <typename T>
1267 inline T ncdf_impl(T v, real_type_tag)
1268 {
1269 T cnd = T(0.5) * (T(1) + erf_impl(
1270 abs_impl(v,real_type_tag()) /
1271 T(numeric::constant::sqrt2),real_type_tag()));
1272 return (v < T(0)) ? (T(1) - cnd) : cnd;
1273 }
1274
1275 template <typename T>
1276 inline T ncdf_impl(T v, int_type_tag)
1277 {
1278 return ncdf_impl(static_cast<double>(v),real_type_tag());
1279 }
1280
1281 template <typename T>
1282 inline T sinc_impl(T v, real_type_tag)
1283 {
1284 if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1285 return(std::sin(v) / v);
1286 else
1287 return T(1);
1288 }
1289
1290 template <typename T>
1291 inline T sinc_impl(T v, int_type_tag)
1292 {
1293 return sinc_impl(static_cast<double>(v),real_type_tag());
1294 }
1295
1296 template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
1297 template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
1298 template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
1299 template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
1300 template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
1301 template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
1302 template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1303 template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
1304 template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1305 template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
1306 template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1307 template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
1308 template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1309 template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1310 template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
1311 template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
1312 template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
1313 template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1314 template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1315 template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
1316 template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1317 template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1318 template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1319 template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1320 template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1321 template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
1322 template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
1323 template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
1324 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)); }
1325 template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1326 template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
1327
1328 template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1329 template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); }
1330
1331 template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1332 template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
1333 template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
1334 template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1335 template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1336 template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
1337 template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
1338 template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
1339 template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
1340 template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
1341 template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
1342 template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1343 template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
1344 template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
1345 template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1346 template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1347 template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1348 template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1349 template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1350 template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1351 template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1352 template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1353 template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1354 template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1355 template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356 template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1357 template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1358 template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1359 template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1360
1361 template <typename T>
1362 inline bool is_integer_impl(const T& v, real_type_tag)
1363 {
1364 return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1365 }
1366
1367 template <typename T>
1368 inline bool is_integer_impl(const T&, int_type_tag)
1369 {
1370 return true;
1371 }
1372 }
1373
1374 template <typename Type>
1375 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1376
1377 template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
1378 template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
1379 template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
1380 template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1381
1382 template <typename T>
1383 inline int to_int32(const T v)
1384 {
1385 const typename details::number_type<T>::type num_type;
1386 return to_int32_impl(v, num_type);
1387 }
1388
1389 template <typename T>
1390 inline _int64_t to_int64(const T v)
1391 {
1392 const typename details::number_type<T>::type num_type;
1393 return to_int64_impl(v, num_type);
1394 }
1395
1396 template <typename T>
1397 inline bool is_nan(const T v)
1398 {
1399 const typename details::number_type<T>::type num_type;
1400 return is_nan_impl(v, num_type);
1401 }
1402
1403 template <typename T>
1404 inline T min(const T v0, const T v1)
1405 {
1406 const typename details::number_type<T>::type num_type;
1407 return min_impl(v0, v1, num_type);
1408 }
1409
1410 template <typename T>
1411 inline T max(const T v0, const T v1)
1412 {
1413 const typename details::number_type<T>::type num_type;
1414 return max_impl(v0, v1, num_type);
1415 }
1416
1417 template <typename T>
1418 inline T equal(const T v0, const T v1)
1419 {
1420 const typename details::number_type<T>::type num_type;
1421 return equal_impl(v0, v1, num_type);
1422 }
1423
1424 template <typename T>
1425 inline T nequal(const T v0, const T v1)
1426 {
1427 const typename details::number_type<T>::type num_type;
1428 return nequal_impl(v0, v1, num_type);
1429 }
1430
1431 template <typename T>
1432 inline T modulus(const T v0, const T v1)
1433 {
1434 const typename details::number_type<T>::type num_type;
1435 return modulus_impl(v0, v1, num_type);
1436 }
1437
1438 template <typename T>
1439 inline T pow(const T v0, const T v1)
1440 {
1441 const typename details::number_type<T>::type num_type;
1442 return pow_impl(v0, v1, num_type);
1443 }
1444
1445 template <typename T>
1446 inline T logn(const T v0, const T v1)
1447 {
1448 const typename details::number_type<T>::type num_type;
1449 return logn_impl(v0, v1, num_type);
1450 }
1451
1452 template <typename T>
1453 inline T root(const T v0, const T v1)
1454 {
1455 const typename details::number_type<T>::type num_type;
1456 return root_impl(v0, v1, num_type);
1457 }
1458
1459 template <typename T>
1460 inline T roundn(const T v0, const T v1)
1461 {
1462 const typename details::number_type<T>::type num_type;
1463 return roundn_impl(v0, v1, num_type);
1464 }
1465
1466 template <typename T>
1467 inline T hypot(const T v0, const T v1)
1468 {
1469 const typename details::number_type<T>::type num_type;
1470 return hypot_impl(v0, v1, num_type);
1471 }
1472
1473 template <typename T>
1474 inline T atan2(const T v0, const T v1)
1475 {
1476 const typename details::number_type<T>::type num_type;
1477 return atan2_impl(v0, v1, num_type);
1478 }
1479
1480 template <typename T>
1481 inline T shr(const T v0, const T v1)
1482 {
1483 const typename details::number_type<T>::type num_type;
1484 return shr_impl(v0, v1, num_type);
1485 }
1486
1487 template <typename T>
1488 inline T shl(const T v0, const T v1)
1489 {
1490 const typename details::number_type<T>::type num_type;
1491 return shl_impl(v0, v1, num_type);
1492 }
1493
1494 template <typename T>
1495 inline T and_opr(const T v0, const T v1)
1496 {
1497 const typename details::number_type<T>::type num_type;
1498 return and_impl(v0, v1, num_type);
1499 }
1500
1501 template <typename T>
1502 inline T nand_opr(const T v0, const T v1)
1503 {
1504 const typename details::number_type<T>::type num_type;
1505 return nand_impl(v0, v1, num_type);
1506 }
1507
1508 template <typename T>
1509 inline T or_opr(const T v0, const T v1)
1510 {
1511 const typename details::number_type<T>::type num_type;
1512 return or_impl(v0, v1, num_type);
1513 }
1514
1515 template <typename T>
1516 inline T nor_opr(const T v0, const T v1)
1517 {
1518 const typename details::number_type<T>::type num_type;
1519 return nor_impl(v0, v1, num_type);
1520 }
1521
1522 template <typename T>
1523 inline T xor_opr(const T v0, const T v1)
1524 {
1525 const typename details::number_type<T>::type num_type;
1526 return xor_impl(v0, v1, num_type);
1527 }
1528
1529 template <typename T>
1530 inline T xnor_opr(const T v0, const T v1)
1531 {
1532 const typename details::number_type<T>::type num_type;
1533 return xnor_impl(v0, v1, num_type);
1534 }
1535
1536 template <typename T>
1537 inline bool is_integer(const T v)
1538 {
1539 const typename details::number_type<T>::type num_type;
1540 return is_integer_impl(v, num_type);
1541 }
1542
1543 template <typename T, unsigned int N>
1544 struct fast_exp
1545 {
1546 static inline T result(T v)
1547 {
1548 unsigned int k = N;
1549 T l = T(1);
1550
1551 while (k)
1552 {
1553 if (k & 1)
1554 {
1555 l *= v;
1556 --k;
1557 }
1558
1559 v *= v;
1560 k >>= 1;
1561 }
1562
1563 return l;
1564 }
1565 };
1566
1567 template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
1568 template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
1569 template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
1570 template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
1571 template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
1572 template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
1573 template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
1574 template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
1575 template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
1576 template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
1577 template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
1578
1579 #define exprtk_define_unary_function(FunctionName) \
1580 template <typename T> \
1581 inline T FunctionName (const T v) \
1582 { \
1583 const typename details::number_type<T>::type num_type; \
1584 return FunctionName##_impl(v,num_type); \
1585 } \
1586
1587 exprtk_define_unary_function(abs )
1588 exprtk_define_unary_function(acos )
1589 exprtk_define_unary_function(acosh)
1590 exprtk_define_unary_function(asin )
1591 exprtk_define_unary_function(asinh)
1592 exprtk_define_unary_function(atan )
1593 exprtk_define_unary_function(atanh)
1594 exprtk_define_unary_function(ceil )
1595 exprtk_define_unary_function(cos )
1596 exprtk_define_unary_function(cosh )
1597 exprtk_define_unary_function(exp )
1598 exprtk_define_unary_function(expm1)
1599 exprtk_define_unary_function(floor)
1600 exprtk_define_unary_function(log )
1601 exprtk_define_unary_function(log10)
1602 exprtk_define_unary_function(log2 )
1603 exprtk_define_unary_function(log1p)
1604 exprtk_define_unary_function(neg )
1605 exprtk_define_unary_function(pos )
1606 exprtk_define_unary_function(round)
1607 exprtk_define_unary_function(sin )
1608 exprtk_define_unary_function(sinc )
1609 exprtk_define_unary_function(sinh )
1610 exprtk_define_unary_function(sqrt )
1611 exprtk_define_unary_function(tan )
1612 exprtk_define_unary_function(tanh )
1613 exprtk_define_unary_function(cot )
1614 exprtk_define_unary_function(sec )
1615 exprtk_define_unary_function(csc )
1616 exprtk_define_unary_function(r2d )
1617 exprtk_define_unary_function(d2r )
1618 exprtk_define_unary_function(d2g )
1619 exprtk_define_unary_function(g2d )
1620 exprtk_define_unary_function(notl )
1621 exprtk_define_unary_function(sgn )
1622 exprtk_define_unary_function(erf )
1623 exprtk_define_unary_function(erfc )
1624 exprtk_define_unary_function(ncdf )
1625 exprtk_define_unary_function(frac )
1626 exprtk_define_unary_function(trunc)
1627 #undef exprtk_define_unary_function
1628 }
1629
1630 template <typename T>
1631 inline T compute_pow10(T d, const int exponent)
1632 {
1633 static const double fract10[] =
1634 {
1635 0.0,
1636 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,
1637 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,
1638 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,
1639 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,
1640 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,
1641 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,
1642 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,
1643 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,
1644 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,
1645 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,
1646 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,
1647 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,
1648 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,
1649 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,
1650 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,
1651 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,
1652 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,
1653 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,
1654 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,
1655 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,
1656 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,
1657 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,
1658 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,
1659 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,
1660 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,
1661 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,
1662 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,
1663 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,
1664 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,
1665 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,
1666 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1667 };
1668
1669 static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1670
1671 const int e = std::abs(exponent);
1672
1673 if (exponent >= std::numeric_limits<T>::min_exponent10)
1674 {
1675 if (e < fract10_size)
1676 {
1677 if (exponent > 0)
1678 return T(d * fract10[e]);
1679 else
1680 return T(d / fract10[e]);
1681 }
1682 else
1683 return T(d * std::pow(10.0, 10.0 * exponent));
1684 }
1685 else
1686 {
1687 d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1688 return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1689 }
1690 }
1691
1692 template <typename Iterator, typename T>
1693 inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1694 {
1695 if (itr == end)
1696 return false;
1697
1698 const bool negative = ('-' == (*itr));
1699
1700 if (negative || ('+' == (*itr)))
1701 {
1702 if (end == ++itr)
1703 return false;
1704 }
1705
1706 static const uchar_t zero = static_cast<uchar_t>('0');
1707
1708 while ((end != itr) && (zero == (*itr))) ++itr;
1709
1710 bool return_result = true;
1711 unsigned int digit = 0;
1712 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1713
1714 if (length <= 4)
1715 {
1716 exprtk_disable_fallthrough_begin
1717 switch (length)
1718 {
1719 #ifdef exprtk_use_lut
1720
1721 #define exprtk_process_digit \
1722 if ((digit = details::digit_table[(int)*itr++]) < 10) \
1723 result = result * 10 + (digit); \
1724 else \
1725 { \
1726 return_result = false; \
1727 break; \
1728 } \
1729
1730 #else
1731
1732 #define exprtk_process_digit \
1733 if ((digit = (*itr++ - zero)) < 10) \
1734 result = result * T(10) + digit; \
1735 else \
1736 { \
1737 return_result = false; \
1738 break; \
1739 } \
1740
1741 #endif
1742
1743 case 4 : exprtk_process_digit
1744 case 3 : exprtk_process_digit
1745 case 2 : exprtk_process_digit
1746 case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1747
1748 #undef exprtk_process_digit
1749 }
1750 exprtk_disable_fallthrough_end
1751 }
1752 else
1753 return_result = false;
1754
1755 if (length && return_result)
1756 {
1757 result = result * 10 + static_cast<T>(digit);
1758 ++itr;
1759 }
1760
1761 result = negative ? -result : result;
1762 return return_result;
1763 }
1764
1765 template <typename Iterator, typename T>
1766 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1767 {
1768 typedef typename std::iterator_traits<Iterator>::value_type type;
1769
1770 static const std::size_t nan_length = 3;
1771
1772 if (std::distance(itr,end) != static_cast<int>(nan_length))
1773 return false;
1774
1775 if (static_cast<type>('n') == (*itr))
1776 {
1777 if (
1778 (static_cast<type>('a') != *(itr + 1)) ||
1779 (static_cast<type>('n') != *(itr + 2))
1780 )
1781 {
1782 return false;
1783 }
1784 }
1785 else if (
1786 (static_cast<type>('A') != *(itr + 1)) ||
1787 (static_cast<type>('N') != *(itr + 2))
1788 )
1789 {
1790 return false;
1791 }
1792
1793 t = std::numeric_limits<T>::quiet_NaN();
1794
1795 return true;
1796 }
1797
1798 template <typename Iterator, typename T>
1799 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1800 {
1801 static const char_t inf_uc[] = "INFINITY";
1802 static const char_t inf_lc[] = "infinity";
1803 static const std::size_t inf_length = 8;
1804
1805 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1806
1807 if ((3 != length) && (inf_length != length))
1808 return false;
1809
1810 char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1811
1812 while (end != itr)
1813 {
1814 if (*inf_itr == static_cast<char>(*itr))
1815 {
1816 ++itr;
1817 ++inf_itr;
1818 continue;
1819 }
1820 else
1821 return false;
1822 }
1823
1824 if (negative)
1825 t = -std::numeric_limits<T>::infinity();
1826 else
1827 t = std::numeric_limits<T>::infinity();
1828
1829 return true;
1830 }
1831
1832 template <typename Iterator, typename T>
1833 inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1834 {
1835 if (end == itr_external) return false;
1836
1837 Iterator itr = itr_external;
1838
1839 T d = T(0);
1840
1841 const bool negative = ('-' == (*itr));
1842
1843 if (negative || '+' == (*itr))
1844 {
1845 if (end == ++itr)
1846 return false;
1847 }
1848
1849 bool instate = false;
1850
1851 static const char_t zero = static_cast<uchar_t>('0');
1852
1853 #define parse_digit_1(d) \
1854 if ((digit = (*itr - zero)) < 10) \
1855 { d = d * T(10) + digit; } \
1856 else \
1857 { break; } \
1858 if (end == ++itr) break; \
1859
1860 #define parse_digit_2(d) \
1861 if ((digit = (*itr - zero)) < 10) \
1862 { d = d * T(10) + digit; } \
1863 else { break; } \
1864 ++itr; \
1865
1866 if ('.' != (*itr))
1867 {
1868 const Iterator curr = itr;
1869
1870 while ((end != itr) && (zero == (*itr))) ++itr;
1871
1872 unsigned int digit;
1873
1874 while (end != itr)
1875 {
1876 // Note: For 'physical' superscalar architectures it
1877 // is advised that the following loop be: 4xPD1 and 1xPD2
1878 #ifdef exprtk_enable_superscalar
1879 parse_digit_1(d)
1880 parse_digit_1(d)
1881 #endif
1882 parse_digit_1(d)
1883 parse_digit_1(d)
1884 parse_digit_2(d)
1885 }
1886
1887 if (curr != itr) instate = true;
1888 }
1889
1890 int exponent = 0;
1891
1892 if (end != itr)
1893 {
1894 if ('.' == (*itr))
1895 {
1896 const Iterator curr = ++itr;
1897 unsigned int digit;
1898 T tmp_d = T(0);
1899
1900 while (end != itr)
1901 {
1902 #ifdef exprtk_enable_superscalar
1903 parse_digit_1(tmp_d)
1904 parse_digit_1(tmp_d)
1905 parse_digit_1(tmp_d)
1906 #endif
1907 parse_digit_1(tmp_d)
1908 parse_digit_1(tmp_d)
1909 parse_digit_2(tmp_d)
1910 }
1911
1912 if (curr != itr)
1913 {
1914 instate = true;
1915 d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
1916 }
1917
1918 #undef parse_digit_1
1919 #undef parse_digit_2
1920 }
1921
1922 if (end != itr)
1923 {
1924 typename std::iterator_traits<Iterator>::value_type c = (*itr);
1925
1926 if (('e' == c) || ('E' == c))
1927 {
1928 int exp = 0;
1929
1930 if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1931 {
1932 if (end == itr)
1933 return false;
1934 else
1935 c = (*itr);
1936 }
1937
1938 exponent += exp;
1939 }
1940
1941 if (end != itr)
1942 {
1943 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1944 ++itr;
1945 else if ('#' == c)
1946 {
1947 if (end == ++itr)
1948 return false;
1949 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1950 {
1951 if (('i' == (*itr)) || ('I' == (*itr)))
1952 {
1953 return parse_inf(itr, end, t, negative);
1954 }
1955 else if (('n' == (*itr)) || ('N' == (*itr)))
1956 {
1957 return parse_nan(itr, end, t);
1958 }
1959 else
1960 return false;
1961 }
1962 else
1963 return false;
1964 }
1965 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1966 {
1967 if (('i' == (*itr)) || ('I' == (*itr)))
1968 {
1969 return parse_inf(itr, end, t, negative);
1970 }
1971 else if (('n' == (*itr)) || ('N' == (*itr)))
1972 {
1973 return parse_nan(itr, end, t);
1974 }
1975 else
1976 return false;
1977 }
1978 else
1979 return false;
1980 }
1981 }
1982 }
1983
1984 if ((end != itr) || (!instate))
1985 return false;
1986 else if (exponent)
1987 d = compute_pow10(d,exponent);
1988
1989 t = static_cast<T>((negative) ? -d : d);
1990 return true;
1991 }
1992
1993 template <typename T>
1994 inline bool string_to_real(const std::string& s, T& t)
1995 {
1996 const typename numeric::details::number_type<T>::type num_type;
1997
1998 char_cptr begin = s.data();
1999 char_cptr end = s.data() + s.size();
2000
2001 return string_to_real(begin, end, t, num_type);
2002 }
2003
2004 template <typename T>
2005 struct functor_t
2006 {
2007 /*
2008 Note: The following definitions for Type, may require tweaking
2009 based on the compiler and target architecture. The benchmark
2010 should provide enough information to make the right choice.
2011 */
2012 //typedef T Type;
2013 //typedef const T Type;
2014 typedef const T& Type;
2015 typedef T& RefType;
2016 typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2017 typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2018 typedef T (*bfunc_t)(Type t0, Type t1);
2019 typedef T (*ufunc_t)(Type t0);
2020 };
2021
2022 } // namespace details
2023
2024 namespace lexer
2025 {
2026 struct token
2027 {
2028 enum token_type
2029 {
2030 e_none = 0, e_error = 1, e_err_symbol = 2,
2031 e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
2032 e_eof = 6, e_number = 7, e_symbol = 8,
2033 e_string = 9, e_assign = 10, e_addass = 11,
2034 e_subass = 12, e_mulass = 13, e_divass = 14,
2035 e_modass = 15, e_shr = 16, e_shl = 17,
2036 e_lte = 18, e_ne = 19, e_gte = 20,
2037 e_swap = 21, e_lt = '<', e_gt = '>',
2038 e_eq = '=', e_rbracket = ')', e_lbracket = '(',
2039 e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
2040 e_lcrlbracket = '{', e_comma = ',', e_add = '+',
2041 e_sub = '-', e_div = '/', e_mul = '*',
2042 e_mod = '%', e_pow = '^', e_colon = ':',
2043 e_ternary = '?'
2044 };
2045
2046 token()
2047 : type(e_none),
2048 value(""),
2049 position(std::numeric_limits<std::size_t>::max())
2050 {}
2051
2052 void clear()
2053 {
2054 type = e_none;
2055 value = "";
2056 position = std::numeric_limits<std::size_t>::max();
2057 }
2058
2059 template <typename Iterator>
2060 inline token& set_operator(const token_type tt,
2061 const Iterator begin, const Iterator end,
2062 const Iterator base_begin = Iterator(0))
2063 {
2064 type = tt;
2065 value.assign(begin,end);
2066 if (base_begin)
2067 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2068 return (*this);
2069 }
2070
2071 template <typename Iterator>
2072 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2073 {
2074 type = e_symbol;
2075 value.assign(begin,end);
2076 if (base_begin)
2077 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2078 return (*this);
2079 }
2080
2081 template <typename Iterator>
2082 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2083 {
2084 type = e_number;
2085 value.assign(begin,end);
2086 if (base_begin)
2087 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2088 return (*this);
2089 }
2090
2091 template <typename Iterator>
2092 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2093 {
2094 type = e_string;
2095 value.assign(begin,end);
2096 if (base_begin)
2097 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2098 return (*this);
2099 }
2100
2101 inline token& set_string(const std::string& s, const std::size_t p)
2102 {
2103 type = e_string;
2104 value = s;
2105 position = p;
2106 return (*this);
2107 }
2108
2109 template <typename Iterator>
2110 inline token& set_error(const token_type et,
2111 const Iterator begin, const Iterator end,
2112 const Iterator base_begin = Iterator(0))
2113 {
2114 if (
2115 (e_error == et) ||
2116 (e_err_symbol == et) ||
2117 (e_err_number == et) ||
2118 (e_err_string == et) ||
2119 (e_err_sfunc == et)
2120 )
2121 {
2122 type = et;
2123 }
2124 else
2125 type = e_error;
2126
2127 value.assign(begin,end);
2128
2129 if (base_begin)
2130 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2131
2132 return (*this);
2133 }
2134
2135 static inline std::string to_str(token_type t)
2136 {
2137 switch (t)
2138 {
2139 case e_none : return "NONE";
2140 case e_error : return "ERROR";
2141 case e_err_symbol : return "ERROR_SYMBOL";
2142 case e_err_number : return "ERROR_NUMBER";
2143 case e_err_string : return "ERROR_STRING";
2144 case e_eof : return "EOF";
2145 case e_number : return "NUMBER";
2146 case e_symbol : return "SYMBOL";
2147 case e_string : return "STRING";
2148 case e_assign : return ":=";
2149 case e_addass : return "+=";
2150 case e_subass : return "-=";
2151 case e_mulass : return "*=";
2152 case e_divass : return "/=";
2153 case e_modass : return "%=";
2154 case e_shr : return ">>";
2155 case e_shl : return "<<";
2156 case e_lte : return "<=";
2157 case e_ne : return "!=";
2158 case e_gte : return ">=";
2159 case e_lt : return "<";
2160 case e_gt : return ">";
2161 case e_eq : return "=";
2162 case e_rbracket : return ")";
2163 case e_lbracket : return "(";
2164 case e_rsqrbracket : return "]";
2165 case e_lsqrbracket : return "[";
2166 case e_rcrlbracket : return "}";
2167 case e_lcrlbracket : return "{";
2168 case e_comma : return ",";
2169 case e_add : return "+";
2170 case e_sub : return "-";
2171 case e_div : return "/";
2172 case e_mul : return "*";
2173 case e_mod : return "%";
2174 case e_pow : return "^";
2175 case e_colon : return ":";
2176 case e_ternary : return "?";
2177 case e_swap : return "<=>";
2178 default : return "UNKNOWN";
2179 }
2180 }
2181
2182 inline bool is_error() const
2183 {
2184 return (
2185 (e_error == type) ||
2186 (e_err_symbol == type) ||
2187 (e_err_number == type) ||
2188 (e_err_string == type) ||
2189 (e_err_sfunc == type)
2190 );
2191 }
2192
2193 token_type type;
2194 std::string value;
2195 std::size_t position;
2196 };
2197
2198 class generator
2199 {
2200 public:
2201
2202 typedef token token_t;
2203 typedef std::vector<token_t> token_list_t;
2204 typedef std::vector<token_t>::iterator token_list_itr_t;
2205 typedef details::char_t char_t;
2206
2207 generator()
2208 : base_itr_(0),
2209 s_itr_ (0),
2210 s_end_ (0)
2211 {
2212 clear();
2213 }
2214
2215 inline void clear()
2216 {
2217 base_itr_ = 0;
2218 s_itr_ = 0;
2219 s_end_ = 0;
2220 token_list_.clear();
2221 token_itr_ = token_list_.end();
2222 store_token_itr_ = token_list_.end();
2223 }
2224
2225 inline bool process(const std::string& str)
2226 {
2227 base_itr_ = str.data();
2228 s_itr_ = str.data();
2229 s_end_ = str.data() + str.size();
2230
2231 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2232 token_list_.clear();
2233
2234 while (!is_end(s_itr_))
2235 {
2236 scan_token();
2237
2238 if (!token_list_.empty() && token_list_.back().is_error())
2239 return false;
2240 }
2241
2242 return true;
2243 }
2244
2245 inline bool empty() const
2246 {
2247 return token_list_.empty();
2248 }
2249
2250 inline std::size_t size() const
2251 {
2252 return token_list_.size();
2253 }
2254
2255 inline void begin()
2256 {
2257 token_itr_ = token_list_.begin();
2258 store_token_itr_ = token_list_.begin();
2259 }
2260
2261 inline void store()
2262 {
2263 store_token_itr_ = token_itr_;
2264 }
2265
2266 inline void restore()
2267 {
2268 token_itr_ = store_token_itr_;
2269 }
2270
2271 inline token_t& next_token()
2272 {
2273 if (token_list_.end() != token_itr_)
2274 {
2275 return *token_itr_++;
2276 }
2277 else
2278 return eof_token_;
2279 }
2280
2281 inline token_t& peek_next_token()
2282 {
2283 if (token_list_.end() != token_itr_)
2284 {
2285 return *token_itr_;
2286 }
2287 else
2288 return eof_token_;
2289 }
2290
2291 inline token_t& operator[](const std::size_t& index)
2292 {
2293 if (index < token_list_.size())
2294 return token_list_[index];
2295 else
2296 return eof_token_;
2297 }
2298
2299 inline token_t operator[](const std::size_t& index) const
2300 {
2301 if (index < token_list_.size())
2302 return token_list_[index];
2303 else
2304 return eof_token_;
2305 }
2306
2307 inline bool finished() const
2308 {
2309 return (token_list_.end() == token_itr_);
2310 }
2311
2312 inline void insert_front(token_t::token_type tk_type)
2313 {
2314 if (
2315 !token_list_.empty() &&
2316 (token_list_.end() != token_itr_)
2317 )
2318 {
2319 token_t t = *token_itr_;
2320
2321 t.type = tk_type;
2322 token_itr_ = token_list_.insert(token_itr_,t);
2323 }
2324 }
2325
2326 inline std::string substr(const std::size_t& begin, const std::size_t& end)
2327 {
2328 const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2329 const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
2330
2331 return std::string(begin_itr,end_itr);
2332 }
2333
2334 inline std::string remaining() const
2335 {
2336 if (finished())
2337 return "";
2338 else if (token_list_.begin() != token_itr_)
2339 return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2340 else
2341 return std::string(base_itr_ + token_itr_->position, s_end_);
2342 }
2343
2344 private:
2345
2346 inline bool is_end(details::char_cptr itr)
2347 {
2348 return (s_end_ == itr);
2349 }
2350
2351 inline bool is_comment_start(details::char_cptr itr)
2352 {
2353 #ifndef exprtk_disable_comments
2354 const char_t c0 = *(itr + 0);
2355 const char_t c1 = *(itr + 1);
2356
2357 if ('#' == c0)
2358 return true;
2359 else if (!is_end(itr + 1))
2360 {
2361 if (('/' == c0) && ('/' == c1)) return true;
2362 if (('/' == c0) && ('*' == c1)) return true;
2363 }
2364 #endif
2365 return false;
2366 }
2367
2368 inline void skip_whitespace()
2369 {
2370 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2371 {
2372 ++s_itr_;
2373 }
2374 }
2375
2376 inline void skip_comments()
2377 {
2378 #ifndef exprtk_disable_comments
2379 // The following comment styles are supported:
2380 // 1. // .... \n
2381 // 2. # .... \n
2382 // 3. /* .... */
2383 struct test
2384 {
2385 static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2386 {
2387 mode = 0;
2388 if ('#' == c0) { mode = 1; incr = 1; }
2389 else if ('/' == c0)
2390 {
2391 if ('/' == c1) { mode = 1; incr = 2; }
2392 else if ('*' == c1) { mode = 2; incr = 2; }
2393 }
2394 return (0 != mode);
2395 }
2396
2397 static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2398 {
2399 if (
2400 ((1 == mode) && ('\n' == c0)) ||
2401 ((2 == mode) && ( '*' == c0) && ('/' == c1))
2402 )
2403 {
2404 mode = 0;
2405 return true;
2406 }
2407 else
2408 return false;
2409 }
2410 };
2411
2412 int mode = 0;
2413 int increment = 0;
2414
2415 if (is_end(s_itr_))
2416 return;
2417 else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2418 return;
2419
2420 details::char_cptr cmt_start = s_itr_;
2421
2422 s_itr_ += increment;
2423
2424 while (!is_end(s_itr_))
2425 {
2426 if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2427 {
2428 ++s_itr_;
2429 return;
2430 }
2431
2432 if ((2 == mode))
2433 {
2434 if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2435 {
2436 s_itr_ += 2;
2437 return;
2438 }
2439 }
2440
2441 ++s_itr_;
2442 }
2443
2444 if (2 == mode)
2445 {
2446 token_t t;
2447 t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2448 token_list_.push_back(t);
2449 }
2450 #endif
2451 }
2452
2453 inline void scan_token()
2454 {
2455 if (details::is_whitespace(*s_itr_))
2456 {
2457 skip_whitespace();
2458 return;
2459 }
2460 else if (is_comment_start(s_itr_))
2461 {
2462 skip_comments();
2463 return;
2464 }
2465 else if (details::is_operator_char(*s_itr_))
2466 {
2467 scan_operator();
2468 return;
2469 }
2470 else if (details::is_letter(*s_itr_))
2471 {
2472 scan_symbol();
2473 return;
2474 }
2475 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2476 {
2477 scan_number();
2478 return;
2479 }
2480 else if ('$' == (*s_itr_))
2481 {
2482 scan_special_function();
2483 return;
2484 }
2485 #ifndef exprtk_disable_string_capabilities
2486 else if ('\'' == (*s_itr_))
2487 {
2488 scan_string();
2489 return;
2490 }
2491 #endif
2492 else if ('~' == (*s_itr_))
2493 {
2494 token_t t;
2495 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2496 token_list_.push_back(t);
2497 ++s_itr_;
2498 return;
2499 }
2500 else
2501 {
2502 token_t t;
2503 t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2504 token_list_.push_back(t);
2505 ++s_itr_;
2506 }
2507 }
2508
2509 inline void scan_operator()
2510 {
2511 token_t t;
2512
2513 const char_t c0 = s_itr_[0];
2514
2515 if (!is_end(s_itr_ + 1))
2516 {
2517 const char_t c1 = s_itr_[1];
2518
2519 if (!is_end(s_itr_ + 2))
2520 {
2521 const char_t c2 = s_itr_[2];
2522
2523 if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2524 {
2525 t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2526 token_list_.push_back(t);
2527 s_itr_ += 3;
2528 return;
2529 }
2530 }
2531
2532 token_t::token_type ttype = token_t::e_none;
2533
2534 if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2535 else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2536 else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2537 else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2538 else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2539 else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2540 else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2541 else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2542 else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2543 else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2544 else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2545 else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2546 else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2547
2548 if (token_t::e_none != ttype)
2549 {
2550 t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2551 token_list_.push_back(t);
2552 s_itr_ += 2;
2553 return;
2554 }
2555 }
2556
2557 if ('<' == c0)
2558 t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2559 else if ('>' == c0)
2560 t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2561 else if (';' == c0)
2562 t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2563 else if ('&' == c0)
2564 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2565 else if ('|' == c0)
2566 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2567 else
2568 t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2569
2570 token_list_.push_back(t);
2571 ++s_itr_;
2572 }
2573
2574 inline void scan_symbol()
2575 {
2576 details::char_cptr initial_itr = s_itr_;
2577
2578 while (!is_end(s_itr_))
2579 {
2580 if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2581 {
2582 if ('.' != (*s_itr_))
2583 break;
2584 /*
2585 Permit symbols that contain a 'dot'
2586 Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2587 Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2588 */
2589 if (
2590 (s_itr_ != initial_itr) &&
2591 !is_end(s_itr_ + 1) &&
2592 !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2593 ('_' != (*(s_itr_ + 1)))
2594 )
2595 break;
2596 }
2597
2598 ++s_itr_;
2599 }
2600
2601 token_t t;
2602 t.set_symbol(initial_itr,s_itr_,base_itr_);
2603 token_list_.push_back(t);
2604 }
2605
2606 inline void scan_number()
2607 {
2608 /*
2609 Attempt to match a valid numeric value in one of the following formats:
2610 (01) 123456
2611 (02) 123456.
2612 (03) 123.456
2613 (04) 123.456e3
2614 (05) 123.456E3
2615 (06) 123.456e+3
2616 (07) 123.456E+3
2617 (08) 123.456e-3
2618 (09) 123.456E-3
2619 (00) .1234
2620 (11) .1234e3
2621 (12) .1234E+3
2622 (13) .1234e+3
2623 (14) .1234E-3
2624 (15) .1234e-3
2625 */
2626
2627 details::char_cptr initial_itr = s_itr_;
2628 bool dot_found = false;
2629 bool e_found = false;
2630 bool post_e_sign_found = false;
2631 bool post_e_digit_found = false;
2632 token_t t;
2633
2634 while (!is_end(s_itr_))
2635 {
2636 if ('.' == (*s_itr_))
2637 {
2638 if (dot_found)
2639 {
2640 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2641 token_list_.push_back(t);
2642 return;
2643 }
2644
2645 dot_found = true;
2646 ++s_itr_;
2647
2648 continue;
2649 }
2650 else if ('e' == std::tolower(*s_itr_))
2651 {
2652 const char_t& c = *(s_itr_ + 1);
2653
2654 if (is_end(s_itr_ + 1))
2655 {
2656 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2657 token_list_.push_back(t);
2658
2659 return;
2660 }
2661 else if (
2662 ('+' != c) &&
2663 ('-' != c) &&
2664 !details::is_digit(c)
2665 )
2666 {
2667 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2668 token_list_.push_back(t);
2669
2670 return;
2671 }
2672
2673 e_found = true;
2674 ++s_itr_;
2675
2676 continue;
2677 }
2678 else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2679 {
2680 if (post_e_sign_found)
2681 {
2682 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2683 token_list_.push_back(t);
2684
2685 return;
2686 }
2687
2688 post_e_sign_found = true;
2689 ++s_itr_;
2690
2691 continue;
2692 }
2693 else if (e_found && details::is_digit(*s_itr_))
2694 {
2695 post_e_digit_found = true;
2696 ++s_itr_;
2697
2698 continue;
2699 }
2700 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2701 break;
2702 else
2703 ++s_itr_;
2704 }
2705
2706 t.set_numeric(initial_itr, s_itr_, base_itr_);
2707 token_list_.push_back(t);
2708
2709 return;
2710 }
2711
2712 inline void scan_special_function()
2713 {
2714 details::char_cptr initial_itr = s_itr_;
2715 token_t t;
2716
2717 // $fdd(x,x,x) = at least 11 chars
2718 if (std::distance(s_itr_,s_end_) < 11)
2719 {
2720 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2721 token_list_.push_back(t);
2722
2723 return;
2724 }
2725
2726 if (
2727 !(('$' == *s_itr_) &&
2728 (details::imatch ('f',*(s_itr_ + 1))) &&
2729 (details::is_digit(*(s_itr_ + 2))) &&
2730 (details::is_digit(*(s_itr_ + 3))))
2731 )
2732 {
2733 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2734 token_list_.push_back(t);
2735
2736 return;
2737 }
2738
2739 s_itr_ += 4; // $fdd = 4chars
2740
2741 t.set_symbol(initial_itr, s_itr_, base_itr_);
2742 token_list_.push_back(t);
2743
2744 return;
2745 }
2746
2747 #ifndef exprtk_disable_string_capabilities
2748 inline void scan_string()
2749 {
2750 details::char_cptr initial_itr = s_itr_ + 1;
2751 token_t t;
2752
2753 if (std::distance(s_itr_,s_end_) < 2)
2754 {
2755 t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2756 token_list_.push_back(t);
2757 return;
2758 }
2759
2760 ++s_itr_;
2761
2762 bool escaped_found = false;
2763 bool escaped = false;
2764
2765 while (!is_end(s_itr_))
2766 {
2767 if (!escaped && ('\\' == *s_itr_))
2768 {
2769 escaped_found = true;
2770 escaped = true;
2771 ++s_itr_;
2772
2773 continue;
2774 }
2775 else if (!escaped)
2776 {
2777 if ('\'' == *s_itr_)
2778 break;
2779 }
2780 else if (escaped)
2781 {
2782 if (!is_end(s_itr_) && ('0' == *(s_itr_)))
2783 {
2784 /*
2785 Note: The following 'awkward' conditional is
2786 due to various broken msvc compilers.
2787 */
2788 #if defined(_MSC_VER) && (_MSC_VER == 1600)
2789 const bool within_range = !is_end(s_itr_ + 2) &&
2790 !is_end(s_itr_ + 3) ;
2791 #else
2792 const bool within_range = !is_end(s_itr_ + 1) &&
2793 !is_end(s_itr_ + 2) &&
2794 !is_end(s_itr_ + 3) ;
2795 #endif
2796
2797 const bool x_seperator = ('x' == *(s_itr_ + 1)) ||
2798 ('X' == *(s_itr_ + 1)) ;
2799
2800 const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2801 details::is_hex_digit(*(s_itr_ + 3)) ;
2802
2803 if (!within_range || !x_seperator || !both_digits)
2804 {
2805 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2806 token_list_.push_back(t);
2807
2808 return;
2809 }
2810 else
2811 s_itr_ += 3;
2812 }
2813
2814 escaped = false;
2815 }
2816
2817 ++s_itr_;
2818 }
2819
2820 if (is_end(s_itr_))
2821 {
2822 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2823 token_list_.push_back(t);
2824
2825 return;
2826 }
2827
2828 if (!escaped_found)
2829 t.set_string(initial_itr, s_itr_, base_itr_);
2830 else
2831 {
2832 std::string parsed_string(initial_itr,s_itr_);
2833
2834 details::cleanup_escapes(parsed_string);
2835
2836 t.set_string(
2837 parsed_string,
2838 static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2839 }
2840
2841 token_list_.push_back(t);
2842 ++s_itr_;
2843
2844 return;
2845 }
2846 #endif
2847
2848 private:
2849
2850 token_list_t token_list_;
2851 token_list_itr_t token_itr_;
2852 token_list_itr_t store_token_itr_;
2853 token_t eof_token_;
2854 details::char_cptr base_itr_;
2855 details::char_cptr s_itr_;
2856 details::char_cptr s_end_;
2857
2858 friend class token_scanner;
2859 friend class token_modifier;
2860 friend class token_inserter;
2861 friend class token_joiner;
2862 };
2863
2864 class helper_interface
2865 {
2866 public:
2867
2868 virtual void init() { }
2869 virtual void reset() { }
2870 virtual bool result() { return true; }
2871 virtual std::size_t process(generator&) { return 0; }
2872 virtual ~helper_interface() { }
2873 };
2874
2875 class token_scanner : public helper_interface
2876 {
2877 public:
2878
2879 virtual ~token_scanner()
2880 {}
2881
2882 explicit token_scanner(const std::size_t& stride)
2883 : stride_(stride)
2884 {
2885 if (stride > 4)
2886 {
2887 throw std::invalid_argument("token_scanner() - Invalid stride value");
2888 }
2889 }
2890
2891 inline std::size_t process(generator& g)
2892 {
2893 if (g.token_list_.size() >= stride_)
2894 {
2895 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2896 {
2897 token t;
2898
2899 switch (stride_)
2900 {
2901 case 1 :
2902 {
2903 const token& t0 = g.token_list_[i];
2904
2905 if (!operator()(t0))
2906 {
2907 return i;
2908 }
2909 }
2910 break;
2911
2912 case 2 :
2913 {
2914 const token& t0 = g.token_list_[i ];
2915 const token& t1 = g.token_list_[i + 1];
2916
2917 if (!operator()(t0, t1))
2918 {
2919 return i;
2920 }
2921 }
2922 break;
2923
2924 case 3 :
2925 {
2926 const token& t0 = g.token_list_[i ];
2927 const token& t1 = g.token_list_[i + 1];
2928 const token& t2 = g.token_list_[i + 2];
2929
2930 if (!operator()(t0, t1, t2))
2931 {
2932 return i;
2933 }
2934 }
2935 break;
2936
2937 case 4 :
2938 {
2939 const token& t0 = g.token_list_[i ];
2940 const token& t1 = g.token_list_[i + 1];
2941 const token& t2 = g.token_list_[i + 2];
2942 const token& t3 = g.token_list_[i + 3];
2943
2944 if (!operator()(t0, t1, t2, t3))
2945 {
2946 return i;
2947 }
2948 }
2949 break;
2950 }
2951 }
2952 }
2953
2954 return (g.token_list_.size() - stride_ + 1);
2955 }
2956
2957 virtual bool operator() (const token&)
2958 {
2959 return false;
2960 }
2961
2962 virtual bool operator() (const token&, const token&)
2963 {
2964 return false;
2965 }
2966
2967 virtual bool operator() (const token&, const token&, const token&)
2968 {
2969 return false;
2970 }
2971
2972 virtual bool operator() (const token&, const token&, const token&, const token&)
2973 {
2974 return false;
2975 }
2976
2977 private:
2978
2979 const std::size_t stride_;
2980 };
2981
2982 class token_modifier : public helper_interface
2983 {
2984 public:
2985
2986 inline std::size_t process(generator& g)
2987 {
2988 std::size_t changes = 0;
2989
2990 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
2991 {
2992 if (modify(g.token_list_[i])) changes++;
2993 }
2994
2995 return changes;
2996 }
2997
2998 virtual bool modify(token& t) = 0;
2999 };
3000
3001 class token_inserter : public helper_interface
3002 {
3003 public:
3004
3005 explicit token_inserter(const std::size_t& stride)
3006 : stride_(stride)
3007 {
3008 if (stride > 5)
3009 {
3010 throw std::invalid_argument("token_inserter() - Invalid stride value");
3011 }
3012 }
3013
3014 inline std::size_t process(generator& g)
3015 {
3016 if (g.token_list_.empty())
3017 return 0;
3018 else if (g.token_list_.size() < stride_)
3019 return 0;
3020
3021 std::size_t changes = 0;
3022
3023 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3024 {
3025 int insert_index = -1;
3026 token t;
3027
3028 switch (stride_)
3029 {
3030 case 1 : insert_index = insert(g.token_list_[i],t);
3031 break;
3032
3033 case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3034 break;
3035
3036 case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3037 break;
3038
3039 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);
3040 break;
3041
3042 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);
3043 break;
3044 }
3045
3046 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3047
3048 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3049 {
3050 g.token_list_.insert(
3051 g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
3052
3053 changes++;
3054 }
3055 }
3056
3057 return changes;
3058 }
3059
3060 #define token_inserter_empty_body \
3061 { \
3062 return -1; \
3063 } \
3064
3065 inline virtual int insert(const token&, token&)
3066 token_inserter_empty_body
3067
3068 inline virtual int insert(const token&, const token&, token&)
3069 token_inserter_empty_body
3070
3071 inline virtual int insert(const token&, const token&, const token&, token&)
3072 token_inserter_empty_body
3073
3074 inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3075 token_inserter_empty_body
3076
3077 inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3078 token_inserter_empty_body
3079
3080 #undef token_inserter_empty_body
3081
3082 private:
3083
3084 const std::size_t stride_;
3085 };
3086
3087 class token_joiner : public helper_interface
3088 {
3089 public:
3090
3091 explicit token_joiner(const std::size_t& stride)
3092 : stride_(stride)
3093 {}
3094
3095 inline std::size_t process(generator& g)
3096 {
3097 if (g.token_list_.empty())
3098 return 0;
3099
3100 switch (stride_)
3101 {
3102 case 2 : return process_stride_2(g);
3103 case 3 : return process_stride_3(g);
3104 default : return 0;
3105 }
3106 }
3107
3108 virtual bool join(const token&, const token&, token&) { return false; }
3109 virtual bool join(const token&, const token&, const token&, token&) { return false; }
3110
3111 private:
3112
3113 inline std::size_t process_stride_2(generator& g)
3114 {
3115 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3116
3117 if (g.token_list_.size() < 2)
3118 return 0;
3119
3120 std::size_t changes = 0;
3121
3122 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3123 {
3124 token t;
3125
3126 while (join(g[i], g[i + 1], t))
3127 {
3128 g.token_list_[i] = t;
3129
3130 g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
3131
3132 ++changes;
3133
3134 if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
3135 break;
3136 }
3137 }
3138
3139 return changes;
3140 }
3141
3142 inline std::size_t process_stride_3(generator& g)
3143 {
3144 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3145
3146 if (g.token_list_.size() < 3)
3147 return 0;
3148
3149 std::size_t changes = 0;
3150
3151 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3152 {
3153 token t;
3154
3155 while (join(g[i], g[i + 1], g[i + 2], t))
3156 {
3157 g.token_list_[i] = t;
3158
3159 g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
3160 g.token_list_.begin() + static_cast<diff_t>(i + 3));
3161 ++changes;
3162
3163 if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
3164 break;
3165 }
3166 }
3167
3168 return changes;
3169 }
3170
3171 const std::size_t stride_;
3172 };
3173
3174 namespace helper
3175 {
3176
3177 inline void dump(lexer::generator& generator)
3178 {
3179 for (std::size_t i = 0; i < generator.size(); ++i)
3180 {
3181 lexer::token t = generator[i];
3182 printf("Token[%02d] @ %03d %6s --> '%s'\n",
3183 static_cast<int>(i),
3184 static_cast<int>(t.position),
3185 t.to_str(t.type).c_str(),
3186 t.value.c_str());
3187 }
3188 }
3189
3190 class commutative_inserter : public lexer::token_inserter
3191 {
3192 public:
3193
3194 using lexer::token_inserter::insert;
3195
3196 commutative_inserter()
3197 : lexer::token_inserter(2)
3198 {}
3199
3200 inline void ignore_symbol(const std::string& symbol)
3201 {
3202 ignore_set_.insert(symbol);
3203 }
3204
3205 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3206 {
3207 bool match = false;
3208 new_token.type = lexer::token::e_mul;
3209 new_token.value = "*";
3210 new_token.position = t1.position;
3211
3212 if (t0.type == lexer::token::e_symbol)
3213 {
3214 if (ignore_set_.end() != ignore_set_.find(t0.value))
3215 {
3216 return -1;
3217 }
3218 else if (!t0.value.empty() && ('$' == t0.value[0]))
3219 {
3220 return -1;
3221 }
3222 }
3223
3224 if (t1.type == lexer::token::e_symbol)
3225 {
3226 if (ignore_set_.end() != ignore_set_.find(t1.value))
3227 {
3228 return -1;
3229 }
3230 }
3231 if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
3232 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
3233 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3234 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3235 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
3236 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
3237 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
3238 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
3239 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
3240 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3241 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3242 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
3243
3244 return (match) ? 1 : -1;
3245 }
3246
3247 private:
3248
3249 std::set<std::string,details::ilesscompare> ignore_set_;
3250 };
3251
3252 class operator_joiner : public token_joiner
3253 {
3254 public:
3255
3256 explicit operator_joiner(const std::size_t& stride)
3257 : token_joiner(stride)
3258 {}
3259
3260 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3261 {
3262 // ': =' --> ':='
3263 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3264 {
3265 t.type = lexer::token::e_assign;
3266 t.value = ":=";
3267 t.position = t0.position;
3268
3269 return true;
3270 }
3271 // '+ =' --> '+='
3272 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3273 {
3274 t.type = lexer::token::e_addass;
3275 t.value = "+=";
3276 t.position = t0.position;
3277
3278 return true;
3279 }
3280 // '- =' --> '-='
3281 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3282 {
3283 t.type = lexer::token::e_subass;
3284 t.value = "-=";
3285 t.position = t0.position;
3286
3287 return true;
3288 }
3289 // '* =' --> '*='
3290 else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3291 {
3292 t.type = lexer::token::e_mulass;
3293 t.value = "*=";
3294 t.position = t0.position;
3295
3296 return true;
3297 }
3298 // '/ =' --> '/='
3299 else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3300 {
3301 t.type = lexer::token::e_divass;
3302 t.value = "/=";
3303 t.position = t0.position;
3304
3305 return true;
3306 }
3307 // '% =' --> '%='
3308 else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3309 {
3310 t.type = lexer::token::e_modass;
3311 t.value = "%=";
3312 t.position = t0.position;
3313
3314 return true;
3315 }
3316 // '> =' --> '>='
3317 else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3318 {
3319 t.type = lexer::token::e_gte;
3320 t.value = ">=";
3321 t.position = t0.position;
3322
3323 return true;
3324 }
3325 // '< =' --> '<='
3326 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3327 {
3328 t.type = lexer::token::e_lte;
3329 t.value = "<=";
3330 t.position = t0.position;
3331
3332 return true;
3333 }
3334 // '= =' --> '=='
3335 else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3336 {
3337 t.type = lexer::token::e_eq;
3338 t.value = "==";
3339 t.position = t0.position;
3340
3341 return true;
3342 }
3343 // '! =' --> '!='
3344 else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3345 {
3346 t.type = lexer::token::e_ne;
3347 t.value = "!=";
3348 t.position = t0.position;
3349
3350 return true;
3351 }
3352 // '< >' --> '<>'
3353 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3354 {
3355 t.type = lexer::token::e_ne;
3356 t.value = "<>";
3357 t.position = t0.position;
3358
3359 return true;
3360 }
3361 // '<= >' --> '<=>'
3362 else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3363 {
3364 t.type = lexer::token::e_swap;
3365 t.value = "<=>";
3366 t.position = t0.position;
3367
3368 return true;
3369 }
3370 // '+ -' --> '-'
3371 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3372 {
3373 t.type = lexer::token::e_sub;
3374 t.value = "-";
3375 t.position = t0.position;
3376
3377 return true;
3378 }
3379 // '- +' --> '-'
3380 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3381 {
3382 t.type = lexer::token::e_sub;
3383 t.value = "-";
3384 t.position = t0.position;
3385
3386 return true;
3387 }
3388 // '- -' --> '+'
3389 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3390 {
3391 /*
3392 Note: May need to reconsider this when wanting to implement
3393 pre/postfix decrement operator
3394 */
3395 t.type = lexer::token::e_add;
3396 t.value = "+";
3397 t.position = t0.position;
3398
3399 return true;
3400 }
3401 else
3402 return false;
3403 }
3404
3405 inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3406 {
3407 // '[ * ]' --> '[*]'
3408 if (
3409 (t0.type == lexer::token::e_lsqrbracket) &&
3410 (t1.type == lexer::token::e_mul ) &&
3411 (t2.type == lexer::token::e_rsqrbracket)
3412 )
3413 {
3414 t.type = lexer::token::e_symbol;
3415 t.value = "[*]";
3416 t.position = t0.position;
3417
3418 return true;
3419 }
3420 else
3421 return false;
3422 }
3423 };
3424
3425 class bracket_checker : public lexer::token_scanner
3426 {
3427 public:
3428
3429 using lexer::token_scanner::operator();
3430
3431 bracket_checker()
3432 : token_scanner(1),
3433 state_(true)
3434 {}
3435
3436 bool result()
3437 {
3438 if (!stack_.empty())
3439 {
3440 lexer::token t;
3441 t.value = stack_.top().first;
3442 t.position = stack_.top().second;
3443 error_token_ = t;
3444 state_ = false;
3445
3446 return false;
3447 }
3448 else
3449 return state_;
3450 }
3451
3452 lexer::token error_token()
3453 {
3454 return error_token_;
3455 }
3456
3457 void reset()
3458 {
3459 // Why? because msvc doesn't support swap properly.
3460 stack_ = std::stack<std::pair<char,std::size_t> >();
3461 state_ = true;
3462 error_token_.clear();
3463 }
3464
3465 bool operator() (const lexer::token& t)
3466 {
3467 if (
3468 !t.value.empty() &&
3469 (lexer::token::e_string != t.type) &&
3470 (lexer::token::e_symbol != t.type) &&
3471 exprtk::details::is_bracket(t.value[0])
3472 )
3473 {
3474 details::char_t c = t.value[0];
3475
3476 if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
3477 else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3478 else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3479 else if (exprtk::details::is_right_bracket(c))
3480 {
3481 if (stack_.empty())
3482 {
3483 state_ = false;
3484 error_token_ = t;
3485
3486 return false;
3487 }
3488 else if (c != stack_.top().first)
3489 {
3490 state_ = false;
3491 error_token_ = t;
3492
3493 return false;
3494 }
3495 else
3496 stack_.pop();
3497 }
3498 }
3499
3500 return true;
3501 }
3502
3503 private:
3504
3505 bool state_;
3506 std::stack<std::pair<char,std::size_t> > stack_;
3507 lexer::token error_token_;
3508 };
3509
3510 class numeric_checker : public lexer::token_scanner
3511 {
3512 public:
3513
3514 using lexer::token_scanner::operator();
3515
3516 numeric_checker()
3517 : token_scanner (1),
3518 current_index_(0)
3519 {}
3520
3521 bool result()
3522 {
3523 return error_list_.empty();
3524 }
3525
3526 void reset()
3527 {
3528 error_list_.clear();
3529 current_index_ = 0;
3530 }
3531
3532 bool operator() (const lexer::token& t)
3533 {
3534 if (token::e_number == t.type)
3535 {
3536 double v;
3537
3538 if (!exprtk::details::string_to_real(t.value,v))
3539 {
3540 error_list_.push_back(current_index_);
3541 }
3542 }
3543
3544 ++current_index_;
3545
3546 return true;
3547 }
3548
3549 std::size_t error_count() const
3550 {
3551 return error_list_.size();
3552 }
3553
3554 std::size_t error_index(const std::size_t& i)
3555 {
3556 if (i < error_list_.size())
3557 return error_list_[i];
3558 else
3559 return std::numeric_limits<std::size_t>::max();
3560 }
3561
3562 void clear_errors()
3563 {
3564 error_list_.clear();
3565 }
3566
3567 private:
3568
3569 std::size_t current_index_;
3570 std::vector<std::size_t> error_list_;
3571 };
3572
3573 class symbol_replacer : public lexer::token_modifier
3574 {
3575 private:
3576
3577 typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3578
3579 public:
3580
3581 bool remove(const std::string& target_symbol)
3582 {
3583 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3584
3585 if (replace_map_.end() == itr)
3586 return false;
3587
3588 replace_map_.erase(itr);
3589
3590 return true;
3591 }
3592
3593 bool add_replace(const std::string& target_symbol,
3594 const std::string& replace_symbol,
3595 const lexer::token::token_type token_type = lexer::token::e_symbol)
3596 {
3597 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3598
3599 if (replace_map_.end() != itr)
3600 {
3601 return false;
3602 }
3603
3604 replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3605
3606 return true;
3607 }
3608
3609 void clear()
3610 {
3611 replace_map_.clear();
3612 }
3613
3614 private:
3615
3616 bool modify(lexer::token& t)
3617 {
3618 if (lexer::token::e_symbol == t.type)
3619 {
3620 if (replace_map_.empty())
3621 return false;
3622
3623 const replace_map_t::iterator itr = replace_map_.find(t.value);
3624
3625 if (replace_map_.end() != itr)
3626 {
3627 t.value = itr->second.first;
3628 t.type = itr->second.second;
3629
3630 return true;
3631 }
3632 }
3633
3634 return false;
3635 }
3636
3637 replace_map_t replace_map_;
3638 };
3639
3640 class sequence_validator : public lexer::token_scanner
3641 {
3642 private:
3643
3644 typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3645 typedef std::set<token_pair_t> set_t;
3646
3647 public:
3648
3649 using lexer::token_scanner::operator();
3650
3651 sequence_validator()
3652 : lexer::token_scanner(2)
3653 {
3654 add_invalid(lexer::token::e_number, lexer::token::e_number);
3655 add_invalid(lexer::token::e_string, lexer::token::e_string);
3656 add_invalid(lexer::token::e_number, lexer::token::e_string);
3657 add_invalid(lexer::token::e_string, lexer::token::e_number);
3658
3659 add_invalid_set1(lexer::token::e_assign );
3660 add_invalid_set1(lexer::token::e_shr );
3661 add_invalid_set1(lexer::token::e_shl );
3662 add_invalid_set1(lexer::token::e_lte );
3663 add_invalid_set1(lexer::token::e_ne );
3664 add_invalid_set1(lexer::token::e_gte );
3665 add_invalid_set1(lexer::token::e_lt );
3666 add_invalid_set1(lexer::token::e_gt );
3667 add_invalid_set1(lexer::token::e_eq );
3668 add_invalid_set1(lexer::token::e_comma );
3669 add_invalid_set1(lexer::token::e_add );
3670 add_invalid_set1(lexer::token::e_sub );
3671 add_invalid_set1(lexer::token::e_div );
3672 add_invalid_set1(lexer::token::e_mul );
3673 add_invalid_set1(lexer::token::e_mod );
3674 add_invalid_set1(lexer::token::e_pow );
3675 add_invalid_set1(lexer::token::e_colon );
3676 add_invalid_set1(lexer::token::e_ternary);
3677 }
3678
3679 bool result()
3680 {
3681 return error_list_.empty();
3682 }
3683
3684 bool operator() (const lexer::token& t0, const lexer::token& t1)
3685 {
3686 const set_t::value_type p = std::make_pair(t0.type,t1.type);
3687
3688 if (invalid_bracket_check(t0.type,t1.type))
3689 {
3690 error_list_.push_back(std::make_pair(t0,t1));
3691 }
3692 else if (invalid_comb_.find(p) != invalid_comb_.end())
3693 {
3694 error_list_.push_back(std::make_pair(t0,t1));
3695 }
3696
3697 return true;
3698 }
3699
3700 std::size_t error_count() const
3701 {
3702 return error_list_.size();
3703 }
3704
3705 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3706 {
3707 if (index < error_list_.size())
3708 {
3709 return error_list_[index];
3710 }
3711 else
3712 {
3713 static const lexer::token error_token;
3714 return std::make_pair(error_token,error_token);
3715 }
3716 }
3717
3718 void clear_errors()
3719 {
3720 error_list_.clear();
3721 }
3722
3723 private:
3724
3725 void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
3726 {
3727 invalid_comb_.insert(std::make_pair(base,t));
3728 }
3729
3730 void add_invalid_set1(lexer::token::token_type t)
3731 {
3732 add_invalid(t, lexer::token::e_assign);
3733 add_invalid(t, lexer::token::e_shr );
3734 add_invalid(t, lexer::token::e_shl );
3735 add_invalid(t, lexer::token::e_lte );
3736 add_invalid(t, lexer::token::e_ne );
3737 add_invalid(t, lexer::token::e_gte );
3738 add_invalid(t, lexer::token::e_lt );
3739 add_invalid(t, lexer::token::e_gt );
3740 add_invalid(t, lexer::token::e_eq );
3741 add_invalid(t, lexer::token::e_comma );
3742 add_invalid(t, lexer::token::e_div );
3743 add_invalid(t, lexer::token::e_mul );
3744 add_invalid(t, lexer::token::e_mod );
3745 add_invalid(t, lexer::token::e_pow );
3746 add_invalid(t, lexer::token::e_colon );
3747 }
3748
3749 bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
3750 {
3751 if (details::is_right_bracket(static_cast<char>(base)))
3752 {
3753 switch (t)
3754 {
3755 case lexer::token::e_assign : return (']' != base);
3756 case lexer::token::e_string : return (')' != base);
3757 default : return false;
3758 }
3759 }
3760 else if (details::is_left_bracket(static_cast<char>(base)))
3761 {
3762 if (details::is_right_bracket(static_cast<char>(t)))
3763 return false;
3764 else if (details::is_left_bracket(static_cast<char>(t)))
3765 return false;
3766 else
3767 {
3768 switch (t)
3769 {
3770 case lexer::token::e_number : return false;
3771 case lexer::token::e_symbol : return false;
3772 case lexer::token::e_string : return false;
3773 case lexer::token::e_add : return false;
3774 case lexer::token::e_sub : return false;
3775 case lexer::token::e_colon : return false;
3776 case lexer::token::e_ternary : return false;
3777 default : return true ;
3778 }
3779 }
3780 }
3781 else if (details::is_right_bracket(static_cast<char>(t)))
3782 {
3783 switch (base)
3784 {
3785 case lexer::token::e_number : return false;
3786 case lexer::token::e_symbol : return false;
3787 case lexer::token::e_string : return false;
3788 case lexer::token::e_eof : return false;
3789 case lexer::token::e_colon : return false;
3790 case lexer::token::e_ternary : return false;
3791 default : return true ;
3792 }
3793 }
3794 else if (details::is_left_bracket(static_cast<char>(t)))
3795 {
3796 switch (base)
3797 {
3798 case lexer::token::e_rbracket : return true;
3799 case lexer::token::e_rsqrbracket : return true;
3800 case lexer::token::e_rcrlbracket : return true;
3801 default : return false;
3802 }
3803 }
3804
3805 return false;
3806 }
3807
3808 set_t invalid_comb_;
3809 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3810 };
3811
3812 class sequence_validator_3tokens : public lexer::token_scanner
3813 {
3814 private:
3815
3816 typedef lexer::token::token_type token_t;
3817 typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3818 typedef std::set<token_triplet_t> set_t;
3819
3820 public:
3821
3822 using lexer::token_scanner::operator();
3823
3824 sequence_validator_3tokens()
3825 : lexer::token_scanner(3)
3826 {
3827 add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
3828 add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
3829 add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
3830
3831 add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add );
3832 add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub );
3833 add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div );
3834 add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul );
3835 add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod );
3836 add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow );
3837
3838 add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add );
3839 add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub );
3840 add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div );
3841 add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul );
3842 add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod );
3843 add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow );
3844 }
3845
3846 bool result()
3847 {
3848 return error_list_.empty();
3849 }
3850
3851 bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3852 {
3853 const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3854
3855 if (invalid_comb_.find(p) != invalid_comb_.end())
3856 {
3857 error_list_.push_back(std::make_pair(t0,t1));
3858 }
3859
3860 return true;
3861 }
3862
3863 std::size_t error_count() const
3864 {
3865 return error_list_.size();
3866 }
3867
3868 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3869 {
3870 if (index < error_list_.size())
3871 {
3872 return error_list_[index];
3873 }
3874 else
3875 {
3876 static const lexer::token error_token;
3877 return std::make_pair(error_token,error_token);
3878 }
3879 }
3880
3881 void clear_errors()
3882 {
3883 error_list_.clear();
3884 }
3885
3886 private:
3887
3888 void add_invalid(token_t t0, token_t t1, token_t t2)
3889 {
3890 invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3891 }
3892
3893 set_t invalid_comb_;
3894 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3895 };
3896
3897 struct helper_assembly
3898 {
3899 inline bool register_scanner(lexer::token_scanner* scanner)
3900 {
3901 if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
3902 token_scanner_list.end (),
3903 scanner))
3904 {
3905 return false;
3906 }
3907
3908 token_scanner_list.push_back(scanner);
3909
3910 return true;
3911 }
3912
3913 inline bool register_modifier(lexer::token_modifier* modifier)
3914 {
3915 if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
3916 token_modifier_list.end (),
3917 modifier))
3918 {
3919 return false;
3920 }
3921
3922 token_modifier_list.push_back(modifier);
3923
3924 return true;
3925 }
3926
3927 inline bool register_joiner(lexer::token_joiner* joiner)
3928 {
3929 if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
3930 token_joiner_list.end (),
3931 joiner))
3932 {
3933 return false;
3934 }
3935
3936 token_joiner_list.push_back(joiner);
3937
3938 return true;
3939 }
3940
3941 inline bool register_inserter(lexer::token_inserter* inserter)
3942 {
3943 if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
3944 token_inserter_list.end (),
3945 inserter))
3946 {
3947 return false;
3948 }
3949
3950 token_inserter_list.push_back(inserter);
3951
3952 return true;
3953 }
3954
3955 inline bool run_modifiers(lexer::generator& g)
3956 {
3957 error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
3958
3959 for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
3960 {
3961 lexer::token_modifier& modifier = (*token_modifier_list[i]);
3962
3963 modifier.reset();
3964 modifier.process(g);
3965
3966 if (!modifier.result())
3967 {
3968 error_token_modifier = token_modifier_list[i];
3969
3970 return false;
3971 }
3972 }
3973
3974 return true;
3975 }
3976
3977 inline bool run_joiners(lexer::generator& g)
3978 {
3979 error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
3980
3981 for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
3982 {
3983 lexer::token_joiner& joiner = (*token_joiner_list[i]);
3984
3985 joiner.reset();
3986 joiner.process(g);
3987
3988 if (!joiner.result())
3989 {
3990 error_token_joiner = token_joiner_list[i];
3991
3992 return false;
3993 }
3994 }
3995
3996 return true;
3997 }
3998
3999 inline bool run_inserters(lexer::generator& g)
4000 {
4001 error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4002
4003 for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4004 {
4005 lexer::token_inserter& inserter = (*token_inserter_list[i]);
4006
4007 inserter.reset();
4008 inserter.process(g);
4009
4010 if (!inserter.result())
4011 {
4012 error_token_inserter = token_inserter_list[i];
4013
4014 return false;
4015 }
4016 }
4017
4018 return true;
4019 }
4020
4021 inline bool run_scanners(lexer::generator& g)
4022 {
4023 error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4024
4025 for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4026 {
4027 lexer::token_scanner& scanner = (*token_scanner_list[i]);
4028
4029 scanner.reset();
4030 scanner.process(g);
4031
4032 if (!scanner.result())
4033 {
4034 error_token_scanner = token_scanner_list[i];
4035
4036 return false;
4037 }
4038 }
4039
4040 return true;
4041 }
4042
4043 std::vector<lexer::token_scanner*> token_scanner_list;
4044 std::vector<lexer::token_modifier*> token_modifier_list;
4045 std::vector<lexer::token_joiner*> token_joiner_list;
4046 std::vector<lexer::token_inserter*> token_inserter_list;
4047
4048 lexer::token_scanner* error_token_scanner;
4049 lexer::token_modifier* error_token_modifier;
4050 lexer::token_joiner* error_token_joiner;
4051 lexer::token_inserter* error_token_inserter;
4052 };
4053 }
4054
4055 class parser_helper
4056 {
4057 public:
4058
4059 typedef token token_t;
4060 typedef generator generator_t;
4061
4062 inline bool init(const std::string& str)
4063 {
4064 if (!lexer_.process(str))
4065 {
4066 return false;
4067 }
4068
4069 lexer_.begin();
4070
4071 next_token();
4072
4073 return true;
4074 }
4075
4076 inline generator_t& lexer()
4077 {
4078 return lexer_;
4079 }
4080
4081 inline const generator_t& lexer() const
4082 {
4083 return lexer_;
4084 }
4085
4086 inline void store_token()
4087 {
4088 lexer_.store();
4089 store_current_token_ = current_token_;
4090 }
4091
4092 inline void restore_token()
4093 {
4094 lexer_.restore();
4095 current_token_ = store_current_token_;
4096 }
4097
4098 inline void next_token()
4099 {
4100 current_token_ = lexer_.next_token();
4101 }
4102
4103 inline const token_t& current_token() const
4104 {
4105 return current_token_;
4106 }
4107
4108 enum token_advance_mode
4109 {
4110 e_hold = 0,
4111 e_advance = 1
4112 };
4113
4114 inline void advance_token(const token_advance_mode mode)
4115 {
4116 if (e_advance == mode)
4117 {
4118 next_token();
4119 }
4120 }
4121
4122 inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4123 {
4124 if (current_token().type != ttype)
4125 {
4126 return false;
4127 }
4128
4129 advance_token(mode);
4130
4131 return true;
4132 }
4133
4134 inline bool token_is(const token_t::token_type& ttype,
4135 const std::string& value,
4136 const token_advance_mode mode = e_advance)
4137 {
4138 if (
4139 (current_token().type != ttype) ||
4140 !exprtk::details::imatch(value,current_token().value)
4141 )
4142 {
4143 return false;
4144 }
4145
4146 advance_token(mode);
4147
4148 return true;
4149 }
4150
4151 inline bool peek_token_is(const token_t::token_type& ttype)
4152 {
4153 return (lexer_.peek_next_token().type == ttype);
4154 }
4155
4156 inline bool peek_token_is(const std::string& s)
4157 {
4158 return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4159 }
4160
4161 private:
4162
4163 generator_t lexer_;
4164 token_t current_token_;
4165 token_t store_current_token_;
4166 };
4167 }
4168
4169 template <typename T>
4170 class vector_view
4171 {
4172 public:
4173
4174 typedef T* data_ptr_t;
4175
4176 vector_view(data_ptr_t data, const std::size_t& size)
4177 : size_(size),
4178 data_(data),
4179 data_ref_(0)
4180 {}
4181
4182 vector_view(const vector_view<T>& vv)
4183 : size_(vv.size_),
4184 data_(vv.data_),
4185 data_ref_(0)
4186 {}
4187
4188 inline void rebase(data_ptr_t data)
4189 {
4190 data_ = data;
4191
4192 if (!data_ref_.empty())
4193 {
4194 for (std::size_t i = 0; i < data_ref_.size(); ++i)
4195 {
4196 (*data_ref_[i]) = data;
4197 }
4198 }
4199 }
4200
4201 inline data_ptr_t data() const
4202 {
4203 return data_;
4204 }
4205
4206 inline std::size_t size() const
4207 {
4208 return size_;
4209 }
4210
4211 inline const T& operator[](const std::size_t index) const
4212 {
4213 return data_[index];
4214 }
4215
4216 inline T& operator[](const std::size_t index)
4217 {
4218 return data_[index];
4219 }
4220
4221 void set_ref(data_ptr_t* data_ref)
4222 {
4223 data_ref_.push_back(data_ref);
4224 }
4225
4226 private:
4227
4228 const std::size_t size_;
4229 data_ptr_t data_;
4230 std::vector<data_ptr_t*> data_ref_;
4231 };
4232
4233 template <typename T>
4234 inline vector_view<T> make_vector_view(T* data,
4235 const std::size_t size, const std::size_t offset = 0)
4236 {
4237 return vector_view<T>(data + offset, size);
4238 }
4239
4240 template <typename T>
4241 inline vector_view<T> make_vector_view(std::vector<T>& v,
4242 const std::size_t size, const std::size_t offset = 0)
4243 {
4244 return vector_view<T>(v.data() + offset, size);
4245 }
4246
4247 template <typename T> class results_context;
4248
4249 template <typename T>
4250 struct type_store
4251 {
4252 enum store_type
4253 {
4254 e_unknown,
4255 e_scalar ,
4256 e_vector ,
4257 e_string
4258 };
4259
4260 type_store()
4261 : data(0),
4262 size(0),
4263 type(e_unknown)
4264 {}
4265
4266 union
4267 {
4268 void* data;
4269 T* vec_data;
4270 };
4271
4272 std::size_t size;
4273 store_type type;
4274
4275 class parameter_list
4276 {
4277 public:
4278
4279 parameter_list(std::vector<type_store>& pl)
4280 : parameter_list_(pl)
4281 {}
4282
4283 inline bool empty() const
4284 {
4285 return parameter_list_.empty();
4286 }
4287
4288 inline std::size_t size() const
4289 {
4290 return parameter_list_.size();
4291 }
4292
4293 inline type_store& operator[](const std::size_t& index)
4294 {
4295 return parameter_list_[index];
4296 }
4297
4298 inline const type_store& operator[](const std::size_t& index) const
4299 {
4300 return parameter_list_[index];
4301 }
4302
4303 inline type_store& front()
4304 {
4305 return parameter_list_[0];
4306 }
4307
4308 inline const type_store& front() const
4309 {
4310 return parameter_list_[0];
4311 }
4312
4313 inline type_store& back()
4314 {
4315 return parameter_list_.back();
4316 }
4317
4318 inline const type_store& back() const
4319 {
4320 return parameter_list_.back();
4321 }
4322
4323 private:
4324
4325 std::vector<type_store>& parameter_list_;
4326
4327 friend class results_context<T>;
4328 };
4329
4330 template <typename ViewType>
4331 struct type_view
4332 {
4333 typedef type_store<T> type_store_t;
4334 typedef ViewType value_t;
4335
4336 type_view(type_store_t& ts)
4337 : ts_(ts),
4338 data_(reinterpret_cast<value_t*>(ts_.data))
4339 {}
4340
4341 type_view(const type_store_t& ts)
4342 : ts_(const_cast<type_store_t&>(ts)),
4343 data_(reinterpret_cast<value_t*>(ts_.data))
4344 {}
4345
4346 inline std::size_t size() const
4347 {
4348 return ts_.size;
4349 }
4350
4351 inline value_t& operator[](const std::size_t& i)
4352 {
4353 return data_[i];
4354 }
4355
4356 inline const value_t& operator[](const std::size_t& i) const
4357 {
4358 return data_[i];
4359 }
4360
4361 inline const value_t* begin() const { return data_; }
4362 inline value_t* begin() { return data_; }
4363
4364 inline const value_t* end() const
4365 {
4366 return static_cast<value_t*>(data_ + ts_.size);
4367 }
4368
4369 inline value_t* end()
4370 {
4371 return static_cast<value_t*>(data_ + ts_.size);
4372 }
4373
4374 type_store_t& ts_;
4375 value_t* data_;
4376 };
4377
4378 typedef type_view<T> vector_view;
4379 typedef type_view<char> string_view;
4380
4381 struct scalar_view
4382 {
4383 typedef type_store<T> type_store_t;
4384 typedef T value_t;
4385
4386 scalar_view(type_store_t& ts)
4387 : v_(*reinterpret_cast<value_t*>(ts.data))
4388 {}
4389
4390 scalar_view(const type_store_t& ts)
4391 : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4392 {}
4393
4394 inline value_t& operator() ()
4395 {
4396 return v_;
4397 }
4398
4399 inline const value_t& operator() () const
4400 {
4401 return v_;
4402 }
4403
4404 template <typename IntType>
4405 inline bool to_int(IntType& i) const
4406 {
4407 if (!exprtk::details::numeric::is_integer(v_))
4408 return false;
4409
4410 i = static_cast<IntType>(v_);
4411
4412 return true;
4413 }
4414
4415 template <typename UIntType>
4416 inline bool to_uint(UIntType& u) const
4417 {
4418 if (v_ < T(0))
4419 return false;
4420 else if (!exprtk::details::numeric::is_integer(v_))
4421 return false;
4422
4423 u = static_cast<UIntType>(v_);
4424
4425 return true;
4426 }
4427
4428 T& v_;
4429 };
4430 };
4431
4432 template <typename StringView>
4433 inline std::string to_str(const StringView& view)
4434 {
4435 return std::string(view.begin(),view.size());
4436 }
4437
4438 #ifndef exprtk_disable_return_statement
4439 namespace details
4440 {
4441 template <typename T> class return_node;
4442 template <typename T> class return_envelope_node;
4443 }
4444 #endif
4445
4446 template <typename T>
4447 class results_context
4448 {
4449 public:
4450
4451 typedef type_store<T> type_store_t;
4452
4453 results_context()
4454 : results_available_(false)
4455 {}
4456
4457 inline std::size_t count() const
4458 {
4459 if (results_available_)
4460 return parameter_list_.size();
4461 else
4462 return 0;
4463 }
4464
4465 inline type_store_t& operator[](const std::size_t& index)
4466 {
4467 return parameter_list_[index];
4468 }
4469
4470 inline const type_store_t& operator[](const std::size_t& index) const
4471 {
4472 return parameter_list_[index];
4473 }
4474
4475 private:
4476
4477 inline void clear()
4478 {
4479 results_available_ = false;
4480 }
4481
4482 typedef std::vector<type_store_t> ts_list_t;
4483 typedef typename type_store_t::parameter_list parameter_list_t;
4484
4485 inline void assign(const parameter_list_t& pl)
4486 {
4487 parameter_list_ = pl.parameter_list_;
4488 results_available_ = true;
4489 }
4490
4491 bool results_available_;
4492 ts_list_t parameter_list_;
4493
4494 #ifndef exprtk_disable_return_statement
4495 friend class details::return_node<T>;
4496 friend class details::return_envelope_node<T>;
4497 #endif
4498 };
4499
4500 namespace details
4501 {
4502 enum operator_type
4503 {
4504 e_default , e_null , e_add , e_sub ,
4505 e_mul , e_div , e_mod , e_pow ,
4506 e_atan2 , e_min , e_max , e_avg ,
4507 e_sum , e_prod , e_lt , e_lte ,
4508 e_eq , e_equal , e_ne , e_nequal ,
4509 e_gte , e_gt , e_and , e_nand ,
4510 e_or , e_nor , e_xor , e_xnor ,
4511 e_mand , e_mor , e_scand , e_scor ,
4512 e_shr , e_shl , e_abs , e_acos ,
4513 e_acosh , e_asin , e_asinh , e_atan ,
4514 e_atanh , e_ceil , e_cos , e_cosh ,
4515 e_exp , e_expm1 , e_floor , e_log ,
4516 e_log10 , e_log2 , e_log1p , e_logn ,
4517 e_neg , e_pos , e_round , e_roundn ,
4518 e_root , e_sqrt , e_sin , e_sinc ,
4519 e_sinh , e_sec , e_csc , e_tan ,
4520 e_tanh , e_cot , e_clamp , e_iclamp ,
4521 e_inrange , e_sgn , e_r2d , e_d2r ,
4522 e_d2g , e_g2d , e_hypot , e_notl ,
4523 e_erf , e_erfc , e_ncdf , e_frac ,
4524 e_trunc , e_assign , e_addass , e_subass ,
4525 e_mulass , e_divass , e_modass , e_in ,
4526 e_like , e_ilike , e_multi , e_smulti ,
4527 e_swap ,
4528
4529 // Do not add new functions/operators after this point.
4530 e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4531 e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4532 e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4533 e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4534 e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4535 e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4536 e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4537 e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4538 e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4539 e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4540 e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4541 e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4542 e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4543 e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4544 e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4545 e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4546 e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4547 e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4548 e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4549 e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4550 e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4551 e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4552 e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4553 e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4554 e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4555 e_sffinal = 1100,
4556 e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4557 e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4558 e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4559 e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4560 e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4561 e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4562 e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4563 e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4564 e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4565 e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4566 e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4567 e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4568 e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4569 e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4570 e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4571 e_sf4ext60 = 2060, e_sf4ext61 = 2061
4572 };
4573
4574 inline std::string to_str(const operator_type opr)
4575 {
4576 switch (opr)
4577 {
4578 case e_add : return "+" ;
4579 case e_sub : return "-" ;
4580 case e_mul : return "*" ;
4581 case e_div : return "/" ;
4582 case e_mod : return "%" ;
4583 case e_pow : return "^" ;
4584 case e_assign : return ":=" ;
4585 case e_addass : return "+=" ;
4586 case e_subass : return "-=" ;
4587 case e_mulass : return "*=" ;
4588 case e_divass : return "/=" ;
4589 case e_modass : return "%=" ;
4590 case e_lt : return "<" ;
4591 case e_lte : return "<=" ;
4592 case e_eq : return "==" ;
4593 case e_equal : return "=" ;
4594 case e_ne : return "!=" ;
4595 case e_nequal : return "<>" ;
4596 case e_gte : return ">=" ;
4597 case e_gt : return ">" ;
4598 case e_and : return "and" ;
4599 case e_or : return "or" ;
4600 case e_xor : return "xor" ;
4601 case e_nand : return "nand";
4602 case e_nor : return "nor" ;
4603 case e_xnor : return "xnor";
4604 default : return "N/A" ;
4605 }
4606 }
4607
4608 struct base_operation_t
4609 {
4610 base_operation_t(const operator_type t, const unsigned int& np)
4611 : type(t),
4612 num_params(np)
4613 {}
4614
4615 operator_type type;
4616 unsigned int num_params;
4617 };
4618
4619 namespace loop_unroll
4620 {
4621 #ifndef exprtk_disable_superscalar_unroll
4622 const unsigned int global_loop_batch_size = 16;
4623 #else
4624 const unsigned int global_loop_batch_size = 4;
4625 #endif
4626
4627 struct details
4628 {
4629 details(const std::size_t& vsize,
4630 const unsigned int loop_batch_size = global_loop_batch_size)
4631 : batch_size(loop_batch_size ),
4632 remainder (vsize % batch_size),
4633 upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4634 {}
4635
4636 unsigned int batch_size;
4637 int remainder;
4638 int upper_bound;
4639 };
4640 }
4641
4642 #ifdef exprtk_enable_debugging
4643 inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4644 {
4645 if (size)
4646 exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4647 else
4648 exprtk_debug(("%s - addr: %p size: %d\n",
4649 s.c_str(),
4650 ptr,
4651 static_cast<unsigned int>(size)));
4652 }
4653 #else
4654 inline void dump_ptr(const std::string&, const void*) {}
4655 inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4656 #endif
4657
4658 template <typename T>
4659 class vec_data_store
4660 {
4661 public:
4662
4663 typedef vec_data_store<T> type;
4664 typedef T* data_t;
4665
4666 private:
4667
4668 struct control_block
4669 {
4670 control_block()
4671 : ref_count(1),
4672 size (0),
4673 data (0),
4674 destruct (true)
4675 {}
4676
4677 control_block(const std::size_t& dsize)
4678 : ref_count(1 ),
4679 size (dsize),
4680 data (0 ),
4681 destruct (true )
4682 { create_data(); }
4683
4684 control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4685 : ref_count(1 ),
4686 size (dsize ),
4687 data (dptr ),
4688 destruct (dstrct)
4689 {}
4690
4691 ~control_block()
4692 {
4693 if (data && destruct && (0 == ref_count))
4694 {
4695 dump_ptr("~control_block() data",data);
4696 delete[] data;
4697 data = reinterpret_cast<data_t>(0);
4698 }
4699 }
4700
4701 static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4702 {
4703 if (dsize)
4704 {
4705 if (0 == data_ptr)
4706 return (new control_block(dsize));
4707 else
4708 return (new control_block(dsize, data_ptr, dstrct));
4709 }
4710 else
4711 return (new control_block);
4712 }
4713
4714 static inline void destroy(control_block*& cntrl_blck)
4715 {
4716 if (cntrl_blck)
4717 {
4718 if (
4719 (0 != cntrl_blck->ref_count) &&
4720 (0 == --cntrl_blck->ref_count)
4721 )
4722 {
4723 delete cntrl_blck;
4724 }
4725
4726 cntrl_blck = 0;
4727 }
4728 }
4729
4730 std::size_t ref_count;
4731 std::size_t size;
4732 data_t data;
4733 bool destruct;
4734
4735 private:
4736
4737 control_block(const control_block&);
4738 control_block& operator=(const control_block&);
4739
4740 inline void create_data()
4741 {
4742 destruct = true;
4743 data = new T[size];
4744 std::fill_n(data,size,T(0));
4745 dump_ptr("control_block::create_data() - data",data,size);
4746 }
4747 };
4748
4749 public:
4750
4751 vec_data_store()
4752 : control_block_(control_block::create(0))
4753 {}
4754
4755 vec_data_store(const std::size_t& size)
4756 : control_block_(control_block::create(size,(data_t)(0),true))
4757 {}
4758
4759 vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4760 : control_block_(control_block::create(size, data, dstrct))
4761 {}
4762
4763 vec_data_store(const type& vds)
4764 {
4765 control_block_ = vds.control_block_;
4766 control_block_->ref_count++;
4767 }
4768
4769 ~vec_data_store()
4770 {
4771 control_block::destroy(control_block_);
4772 }
4773
4774 type& operator=(const type& vds)
4775 {
4776 if (this != &vds)
4777 {
4778 std::size_t final_size = min_size(control_block_, vds.control_block_);
4779
4780 vds.control_block_->size = final_size;
4781 control_block_->size = final_size;
4782
4783 if (control_block_->destruct || (0 == control_block_->data))
4784 {
4785 control_block::destroy(control_block_);
4786
4787 control_block_ = vds.control_block_;
4788 control_block_->ref_count++;
4789 }
4790 }
4791
4792 return (*this);
4793 }
4794
4795 inline data_t data()
4796 {
4797 return control_block_->data;
4798 }
4799
4800 inline data_t data() const
4801 {
4802 return control_block_->data;
4803 }
4804
4805 inline std::size_t size()
4806 {
4807 return control_block_->size;
4808 }
4809
4810 inline std::size_t size() const
4811 {
4812 return control_block_->size;
4813 }
4814
4815 inline data_t& ref()
4816 {
4817 return control_block_->data;
4818 }
4819
4820 inline void dump() const
4821 {
4822 #ifdef exprtk_enable_debugging
4823 exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4824 size(),
4825 data(),
4826 (control_block_->destruct ? 'T' : 'F')));
4827
4828 for (std::size_t i = 0; i < size(); ++i)
4829 {
4830 if (5 == i)
4831 exprtk_debug(("\n"));
4832
4833 exprtk_debug(("%15.10f ",data()[i]));
4834 }
4835 exprtk_debug(("\n"));
4836 #endif
4837 }
4838
4839 static inline void match_sizes(type& vds0, type& vds1)
4840 {
4841 std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4842 vds0.control_block_->size = size;
4843 vds1.control_block_->size = size;
4844 }
4845
4846 private:
4847
4848 static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4849 {
4850 const std::size_t size0 = cb0->size;
4851 const std::size_t size1 = cb1->size;
4852
4853 if (size0 && size1)
4854 return std::min(size0,size1);
4855 else
4856 return (size0) ? size0 : size1;
4857 }
4858
4859 control_block* control_block_;
4860 };
4861
4862 namespace numeric
4863 {
4864 namespace details
4865 {
4866 template <typename T>
4867 inline T process_impl(const operator_type operation, const T arg)
4868 {
4869 switch (operation)
4870 {
4871 case e_abs : return numeric::abs (arg);
4872 case e_acos : return numeric::acos (arg);
4873 case e_acosh : return numeric::acosh(arg);
4874 case e_asin : return numeric::asin (arg);
4875 case e_asinh : return numeric::asinh(arg);
4876 case e_atan : return numeric::atan (arg);
4877 case e_atanh : return numeric::atanh(arg);
4878 case e_ceil : return numeric::ceil (arg);
4879 case e_cos : return numeric::cos (arg);
4880 case e_cosh : return numeric::cosh (arg);
4881 case e_exp : return numeric::exp (arg);
4882 case e_expm1 : return numeric::expm1(arg);
4883 case e_floor : return numeric::floor(arg);
4884 case e_log : return numeric::log (arg);
4885 case e_log10 : return numeric::log10(arg);
4886 case e_log2 : return numeric::log2 (arg);
4887 case e_log1p : return numeric::log1p(arg);
4888 case e_neg : return numeric::neg (arg);
4889 case e_pos : return numeric::pos (arg);
4890 case e_round : return numeric::round(arg);
4891 case e_sin : return numeric::sin (arg);
4892 case e_sinc : return numeric::sinc (arg);
4893 case e_sinh : return numeric::sinh (arg);
4894 case e_sqrt : return numeric::sqrt (arg);
4895 case e_tan : return numeric::tan (arg);
4896 case e_tanh : return numeric::tanh (arg);
4897 case e_cot : return numeric::cot (arg);
4898 case e_sec : return numeric::sec (arg);
4899 case e_csc : return numeric::csc (arg);
4900 case e_r2d : return numeric::r2d (arg);
4901 case e_d2r : return numeric::d2r (arg);
4902 case e_d2g : return numeric::d2g (arg);
4903 case e_g2d : return numeric::g2d (arg);
4904 case e_notl : return numeric::notl (arg);
4905 case e_sgn : return numeric::sgn (arg);
4906 case e_erf : return numeric::erf (arg);
4907 case e_erfc : return numeric::erfc (arg);
4908 case e_ncdf : return numeric::ncdf (arg);
4909 case e_frac : return numeric::frac (arg);
4910 case e_trunc : return numeric::trunc(arg);
4911
4912 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
4913 return std::numeric_limits<T>::quiet_NaN();
4914 }
4915 }
4916
4917 template <typename T>
4918 inline T process_impl(const operator_type operation, const T arg0, const T arg1)
4919 {
4920 switch (operation)
4921 {
4922 case e_add : return (arg0 + arg1);
4923 case e_sub : return (arg0 - arg1);
4924 case e_mul : return (arg0 * arg1);
4925 case e_div : return (arg0 / arg1);
4926 case e_mod : return modulus<T>(arg0,arg1);
4927 case e_pow : return pow<T>(arg0,arg1);
4928 case e_atan2 : return atan2<T>(arg0,arg1);
4929 case e_min : return std::min<T>(arg0,arg1);
4930 case e_max : return std::max<T>(arg0,arg1);
4931 case e_logn : return logn<T>(arg0,arg1);
4932 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4933 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4934 case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4935 case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4936 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4937 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4938 case e_and : return and_opr <T>(arg0,arg1);
4939 case e_nand : return nand_opr<T>(arg0,arg1);
4940 case e_or : return or_opr <T>(arg0,arg1);
4941 case e_nor : return nor_opr <T>(arg0,arg1);
4942 case e_xor : return xor_opr <T>(arg0,arg1);
4943 case e_xnor : return xnor_opr<T>(arg0,arg1);
4944 case e_root : return root <T>(arg0,arg1);
4945 case e_roundn : return roundn <T>(arg0,arg1);
4946 case e_equal : return equal (arg0,arg1);
4947 case e_nequal : return nequal (arg0,arg1);
4948 case e_hypot : return hypot <T>(arg0,arg1);
4949 case e_shr : return shr <T>(arg0,arg1);
4950 case e_shl : return shl <T>(arg0,arg1);
4951
4952 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
4953 return std::numeric_limits<T>::quiet_NaN();
4954 }
4955 }
4956
4957 template <typename T>
4958 inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
4959 {
4960 switch (operation)
4961 {
4962 case e_add : return (arg0 + arg1);
4963 case e_sub : return (arg0 - arg1);
4964 case e_mul : return (arg0 * arg1);
4965 case e_div : return (arg0 / arg1);
4966 case e_mod : return arg0 % arg1;
4967 case e_pow : return pow<T>(arg0,arg1);
4968 case e_min : return std::min<T>(arg0,arg1);
4969 case e_max : return std::max<T>(arg0,arg1);
4970 case e_logn : return logn<T>(arg0,arg1);
4971 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4972 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4973 case e_eq : return (arg0 == arg1) ? T(1) : T(0);
4974 case e_ne : return (arg0 != arg1) ? T(1) : T(0);
4975 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4976 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4977 case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
4978 case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
4979 case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
4980 case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
4981 case e_xor : return arg0 ^ arg1;
4982 case e_xnor : return !(arg0 ^ arg1);
4983 case e_root : return root<T>(arg0,arg1);
4984 case e_equal : return arg0 == arg1;
4985 case e_nequal : return arg0 != arg1;
4986 case e_hypot : return hypot<T>(arg0,arg1);
4987 case e_shr : return arg0 >> arg1;
4988 case e_shl : return arg0 << arg1;
4989
4990 default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
4991 return std::numeric_limits<T>::quiet_NaN();
4992 }
4993 }
4994 }
4995
4996 template <typename T>
4997 inline T process(const operator_type operation, const T arg)
4998 {
4999 return exprtk::details::numeric::details::process_impl(operation,arg);
5000 }
5001
5002 template <typename T>
5003 inline T process(const operator_type operation, const T arg0, const T arg1)
5004 {
5005 return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5006 }
5007 }
5008
5009 template <typename T>
5010 class expression_node
5011 {
5012 public:
5013
5014 enum node_type
5015 {
5016 e_none , e_null , e_constant , e_unary ,
5017 e_binary , e_binary_ext , e_trinary , e_quaternary ,
5018 e_vararg , e_conditional , e_while , e_repeat ,
5019 e_for , e_switch , e_mswitch , e_return ,
5020 e_retenv , e_variable , e_stringvar , e_stringconst ,
5021 e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat ,
5022 e_stringvarsize , e_strswap , e_stringsize , e_stringvararg ,
5023 e_function , e_vafunction , e_genfunction , e_strfunction ,
5024 e_strcondition , e_strccondition , e_add , e_sub ,
5025 e_mul , e_div , e_mod , e_pow ,
5026 e_lt , e_lte , e_gt , e_gte ,
5027 e_eq , e_ne , e_and , e_nand ,
5028 e_or , e_nor , e_xor , e_xnor ,
5029 e_in , e_like , e_ilike , e_inranges ,
5030 e_ipow , e_ipowinv , e_abs , e_acos ,
5031 e_acosh , e_asin , e_asinh , e_atan ,
5032 e_atanh , e_ceil , e_cos , e_cosh ,
5033 e_exp , e_expm1 , e_floor , e_log ,
5034 e_log10 , e_log2 , e_log1p , e_neg ,
5035 e_pos , e_round , e_sin , e_sinc ,
5036 e_sinh , e_sqrt , e_tan , e_tanh ,
5037 e_cot , e_sec , e_csc , e_r2d ,
5038 e_d2r , e_d2g , e_g2d , e_notl ,
5039 e_sgn , e_erf , e_erfc , e_ncdf ,
5040 e_frac , e_trunc , e_uvouv , e_vov ,
5041 e_cov , e_voc , e_vob , e_bov ,
5042 e_cob , e_boc , e_vovov , e_vovoc ,
5043 e_vocov , e_covov , e_covoc , e_vovovov ,
5044 e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
5045 e_covocov , e_vocovoc , e_covovoc , e_vococov ,
5046 e_sf3ext , e_sf4ext , e_nulleq , e_strass ,
5047 e_vector , e_vecelem , e_rbvecelem , e_rbveccelem ,
5048 e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass ,
5049 e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq ,
5050 e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith ,
5051 e_valvecarith , e_vecunaryop , e_break , e_continue ,
5052 e_swap
5053 };
5054
5055 typedef T value_type;
5056 typedef expression_node<T>* expression_ptr;
5057
5058 virtual ~expression_node()
5059 {}
5060
5061 inline virtual T value() const
5062 {
5063 return std::numeric_limits<T>::quiet_NaN();
5064 }
5065
5066 inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5067 {
5068 return reinterpret_cast<expression_ptr>(index * 0);
5069 }
5070
5071 inline virtual node_type type() const
5072 {
5073 return e_none;
5074 }
5075 };
5076
5077 template <typename T>
5078 inline bool is_generally_string_node(const expression_node<T>* node);
5079
5080 inline bool is_true(const double v)
5081 {
5082 return std::not_equal_to<double>()(0.0,v);
5083 }
5084
5085 inline bool is_true(const long double v)
5086 {
5087 return std::not_equal_to<long double>()(0.0L,v);
5088 }
5089
5090 inline bool is_true(const float v)
5091 {
5092 return std::not_equal_to<float>()(0.0f,v);
5093 }
5094
5095 template <typename T>
5096 inline bool is_true(const std::complex<T>& v)
5097 {
5098 return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5099 }
5100
5101 template <typename T>
5102 inline bool is_true(const expression_node<T>* node)
5103 {
5104 return std::not_equal_to<T>()(T(0),node->value());
5105 }
5106
5107 template <typename T>
5108 inline bool is_false(const expression_node<T>* node)
5109 {
5110 return std::equal_to<T>()(T(0),node->value());
5111 }
5112
5113 template <typename T>
5114 inline bool is_unary_node(const expression_node<T>* node)
5115 {
5116 return node && (details::expression_node<T>::e_unary == node->type());
5117 }
5118
5119 template <typename T>
5120 inline bool is_neg_unary_node(const expression_node<T>* node)
5121 {
5122 return node && (details::expression_node<T>::e_neg == node->type());
5123 }
5124
5125 template <typename T>
5126 inline bool is_binary_node(const expression_node<T>* node)
5127 {
5128 return node && (details::expression_node<T>::e_binary == node->type());
5129 }
5130
5131 template <typename T>
5132 inline bool is_variable_node(const expression_node<T>* node)
5133 {
5134 return node && (details::expression_node<T>::e_variable == node->type());
5135 }
5136
5137 template <typename T>
5138 inline bool is_ivariable_node(const expression_node<T>* node)
5139 {
5140 return node &&
5141 (
5142 details::expression_node<T>::e_variable == node->type() ||
5143 details::expression_node<T>::e_vecelem == node->type() ||
5144 details::expression_node<T>::e_rbvecelem == node->type() ||
5145 details::expression_node<T>::e_rbveccelem == node->type()
5146 );
5147 }
5148
5149 template <typename T>
5150 inline bool is_vector_elem_node(const expression_node<T>* node)
5151 {
5152 return node && (details::expression_node<T>::e_vecelem == node->type());
5153 }
5154
5155 template <typename T>
5156 inline bool is_rebasevector_elem_node(const expression_node<T>* node)
5157 {
5158 return node && (details::expression_node<T>::e_rbvecelem == node->type());
5159 }
5160
5161 template <typename T>
5162 inline bool is_rebasevector_celem_node(const expression_node<T>* node)
5163 {
5164 return node && (details::expression_node<T>::e_rbveccelem == node->type());
5165 }
5166
5167 template <typename T>
5168 inline bool is_vector_node(const expression_node<T>* node)
5169 {
5170 return node && (details::expression_node<T>::e_vector == node->type());
5171 }
5172
5173 template <typename T>
5174 inline bool is_ivector_node(const expression_node<T>* node)
5175 {
5176 if (node)
5177 {
5178 switch (node->type())
5179 {
5180 case details::expression_node<T>::e_vector :
5181 case details::expression_node<T>::e_vecvalass :
5182 case details::expression_node<T>::e_vecvecass :
5183 case details::expression_node<T>::e_vecopvalass :
5184 case details::expression_node<T>::e_vecopvecass :
5185 case details::expression_node<T>::e_vecvecswap :
5186 case details::expression_node<T>::e_vecvecarith :
5187 case details::expression_node<T>::e_vecvalarith :
5188 case details::expression_node<T>::e_valvecarith :
5189 case details::expression_node<T>::e_vecunaryop : return true;
5190 default : return false;
5191 }
5192 }
5193 else
5194 return false;
5195 }
5196
5197 template <typename T>
5198 inline bool is_constant_node(const expression_node<T>* node)
5199 {
5200 return node && (details::expression_node<T>::e_constant == node->type());
5201 }
5202
5203 template <typename T>
5204 inline bool is_null_node(const expression_node<T>* node)
5205 {
5206 return node && (details::expression_node<T>::e_null == node->type());
5207 }
5208
5209 template <typename T>
5210 inline bool is_break_node(const expression_node<T>* node)
5211 {
5212 return node && (details::expression_node<T>::e_break == node->type());
5213 }
5214
5215 template <typename T>
5216 inline bool is_continue_node(const expression_node<T>* node)
5217 {
5218 return node && (details::expression_node<T>::e_continue == node->type());
5219 }
5220
5221 template <typename T>
5222 inline bool is_swap_node(const expression_node<T>* node)
5223 {
5224 return node && (details::expression_node<T>::e_swap == node->type());
5225 }
5226
5227 template <typename T>
5228 inline bool is_function(const expression_node<T>* node)
5229 {
5230 return node && (details::expression_node<T>::e_function == node->type());
5231 }
5232
5233 template <typename T>
5234 inline bool is_return_node(const expression_node<T>* node)
5235 {
5236 return node && (details::expression_node<T>::e_return == node->type());
5237 }
5238
5239 template <typename T> class unary_node;
5240
5241 template <typename T>
5242 inline bool is_negate_node(const expression_node<T>* node)
5243 {
5244 if (node && is_unary_node(node))
5245 {
5246 return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5247 }
5248 else
5249 return false;
5250 }
5251
5252 template <typename T>
5253 inline bool branch_deletable(expression_node<T>* node)
5254 {
5255 return !is_variable_node(node) &&
5256 !is_string_node (node) ;
5257 }
5258
5259 template <std::size_t N, typename T>
5260 inline bool all_nodes_valid(expression_node<T>* (&b)[N])
5261 {
5262 for (std::size_t i = 0; i < N; ++i)
5263 {
5264 if (0 == b[i]) return false;
5265 }
5266
5267 return true;
5268 }
5269
5270 template <typename T,
5271 typename Allocator,
5272 template <typename, typename> class Sequence>
5273 inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5274 {
5275 for (std::size_t i = 0; i < b.size(); ++i)
5276 {
5277 if (0 == b[i]) return false;
5278 }
5279
5280 return true;
5281 }
5282
5283 template <std::size_t N, typename T>
5284 inline bool all_nodes_variables(expression_node<T>* (&b)[N])
5285 {
5286 for (std::size_t i = 0; i < N; ++i)
5287 {
5288 if (0 == b[i])
5289 return false;
5290 else if (!is_variable_node(b[i]))
5291 return false;
5292 }
5293
5294 return true;
5295 }
5296
5297 template <typename T,
5298 typename Allocator,
5299 template <typename, typename> class Sequence>
5300 inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5301 {
5302 for (std::size_t i = 0; i < b.size(); ++i)
5303 {
5304 if (0 == b[i])
5305 return false;
5306 else if (!is_variable_node(b[i]))
5307 return false;
5308 }
5309
5310 return true;
5311 }
5312
5313 template <typename NodeAllocator, typename T, std::size_t N>
5314 inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5315 {
5316 for (std::size_t i = 0; i < N; ++i)
5317 {
5318 free_node(node_allocator,b[i]);
5319 }
5320 }
5321
5322 template <typename NodeAllocator,
5323 typename T,
5324 typename Allocator,
5325 template <typename, typename> class Sequence>
5326 inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5327 {
5328 for (std::size_t i = 0; i < b.size(); ++i)
5329 {
5330 free_node(node_allocator,b[i]);
5331 }
5332
5333 b.clear();
5334 }
5335
5336 template <typename NodeAllocator, typename T>
5337 inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
5338 {
5339 if (0 != node)
5340 {
5341 if (
5342 (is_variable_node(node) || is_string_node(node)) ||
5343 force_delete
5344 )
5345 return;
5346
5347 node_allocator.free(node);
5348 node = reinterpret_cast<expression_node<T>*>(0);
5349 }
5350 }
5351
5352 template <typename T>
5353 inline void destroy_node(expression_node<T>*& node)
5354 {
5355 delete node;
5356 node = reinterpret_cast<expression_node<T>*>(0);
5357 }
5358
5359 template <typename Type>
5360 class vector_holder
5361 {
5362 private:
5363
5364 typedef Type value_type;
5365 typedef value_type* value_ptr;
5366 typedef const value_ptr const_value_ptr;
5367
5368 class vector_holder_base
5369 {
5370 public:
5371
5372 virtual ~vector_holder_base() {}
5373
5374 inline value_ptr operator[](const std::size_t& index) const
5375 {
5376 return value_at(index);
5377 }
5378
5379 inline std::size_t size() const
5380 {
5381 return vector_size();
5382 }
5383
5384 inline value_ptr data() const
5385 {
5386 return value_at(0);
5387 }
5388
5389 virtual inline bool rebaseable() const
5390 {
5391 return false;
5392 }
5393
5394 virtual void set_ref(value_ptr*) {}
5395
5396 protected:
5397
5398 virtual value_ptr value_at(const std::size_t&) const = 0;
5399 virtual std::size_t vector_size() const = 0;
5400 };
5401
5402 class array_vector_impl : public vector_holder_base
5403 {
5404 public:
5405
5406 array_vector_impl(const Type* vec, const std::size_t& vec_size)
5407 : vec_(vec),
5408 size_(vec_size)
5409 {}
5410
5411 protected:
5412
5413 value_ptr value_at(const std::size_t& index) const
5414 {
5415 if (index < size_)
5416 return const_cast<const_value_ptr>(vec_ + index);
5417 else
5418 return const_value_ptr(0);
5419 }
5420
5421 std::size_t vector_size() const
5422 {
5423 return size_;
5424 }
5425
5426 private:
5427
5428 array_vector_impl operator=(const array_vector_impl&);
5429
5430 const Type* vec_;
5431 const std::size_t size_;
5432 };
5433
5434 template <typename Allocator,
5435 template <typename, typename> class Sequence>
5436 class sequence_vector_impl : public vector_holder_base
5437 {
5438 public:
5439
5440 typedef Sequence<Type,Allocator> sequence_t;
5441
5442 sequence_vector_impl(sequence_t& seq)
5443 : sequence_(seq)
5444 {}
5445
5446 protected:
5447
5448 value_ptr value_at(const std::size_t& index) const
5449 {
5450 return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5451 }
5452
5453 std::size_t vector_size() const
5454 {
5455 return sequence_.size();
5456 }
5457
5458 private:
5459
5460 sequence_vector_impl operator=(const sequence_vector_impl&);
5461
5462 sequence_t& sequence_;
5463 };
5464
5465 class vector_view_impl : public vector_holder_base
5466 {
5467 public:
5468
5469 typedef exprtk::vector_view<Type> vector_view_t;
5470
5471 vector_view_impl(vector_view_t& vec_view)
5472 : vec_view_(vec_view)
5473 {}
5474
5475 void set_ref(value_ptr* ref)
5476 {
5477 vec_view_.set_ref(ref);
5478 }
5479
5480 virtual inline bool rebaseable() const
5481 {
5482 return true;
5483 }
5484
5485 protected:
5486
5487 value_ptr value_at(const std::size_t& index) const
5488 {
5489 return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5490 }
5491
5492 std::size_t vector_size() const
5493 {
5494 return vec_view_.size();
5495 }
5496
5497 private:
5498
5499 vector_view_impl operator=(const vector_view_impl&);
5500
5501 vector_view_t& vec_view_;
5502 };
5503
5504 public:
5505
5506 typedef typename details::vec_data_store<Type> vds_t;
5507
5508 vector_holder(Type* vec, const std::size_t& vec_size)
5509 : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5510 {}
5511
5512 vector_holder(const vds_t& vds)
5513 : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5514 {}
5515
5516 template <typename Allocator>
5517 vector_holder(std::vector<Type,Allocator>& vec)
5518 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5519 {}
5520
5521 vector_holder(exprtk::vector_view<Type>& vec)
5522 : vector_holder_base_(new(buffer)vector_view_impl(vec))
5523 {}
5524
5525 inline value_ptr operator[](const std::size_t& index) const
5526 {
5527 return (*vector_holder_base_)[index];
5528 }
5529
5530 inline std::size_t size() const
5531 {
5532 return vector_holder_base_->size();
5533 }
5534
5535 inline value_ptr data() const
5536 {
5537 return vector_holder_base_->data();
5538 }
5539
5540 void set_ref(value_ptr* ref)
5541 {
5542 vector_holder_base_->set_ref(ref);
5543 }
5544
5545 bool rebaseable() const
5546 {
5547 return vector_holder_base_->rebaseable();
5548 }
5549
5550 private:
5551
5552 mutable vector_holder_base* vector_holder_base_;
5553 uchar_t buffer[64];
5554 };
5555
5556 template <typename T>
5557 class null_node : public expression_node<T>
5558 {
5559 public:
5560
5561 inline T value() const
5562 {
5563 return std::numeric_limits<T>::quiet_NaN();
5564 }
5565
5566 inline typename expression_node<T>::node_type type() const
5567 {
5568 return expression_node<T>::e_null;
5569 }
5570 };
5571
5572 template <typename T>
5573 class null_eq_node : public expression_node<T>
5574 {
5575 public:
5576
5577 typedef expression_node<T>* expression_ptr;
5578
5579 null_eq_node(expression_ptr brnch, const bool equality = true)
5580 : branch_(brnch),
5581 branch_deletable_(branch_deletable(branch_)),
5582 equality_(equality)
5583 {}
5584
5585 ~null_eq_node()
5586 {
5587 if (branch_ && branch_deletable_)
5588 {
5589 destroy_node(branch_);
5590 }
5591 }
5592
5593 inline T value() const
5594 {
5595 const T v = branch_->value();
5596 const bool result = details::numeric::is_nan(v);
5597
5598 if (result)
5599 return (equality_) ? T(1) : T(0);
5600 else
5601 return (equality_) ? T(0) : T(1);
5602 }
5603
5604 inline typename expression_node<T>::node_type type() const
5605 {
5606 return expression_node<T>::e_nulleq;
5607 }
5608
5609 inline operator_type operation() const
5610 {
5611 return details::e_eq;
5612 }
5613
5614 inline expression_node<T>* branch(const std::size_t&) const
5615 {
5616 return branch_;
5617 }
5618
5619 private:
5620
5621 expression_ptr branch_;
5622 const bool branch_deletable_;
5623 bool equality_;
5624 };
5625
5626 template <typename T>
5627 class literal_node : public expression_node<T>
5628 {
5629 public:
5630
5631 explicit literal_node(const T& v)
5632 : value_(v)
5633 {}
5634
5635 inline T value() const
5636 {
5637 return value_;
5638 }
5639
5640 inline typename expression_node<T>::node_type type() const
5641 {
5642 return expression_node<T>::e_constant;
5643 }
5644
5645 inline expression_node<T>* branch(const std::size_t&) const
5646 {
5647 return reinterpret_cast<expression_node<T>*>(0);
5648 }
5649
5650 private:
5651
5652 literal_node(literal_node<T>&) {}
5653 literal_node<T>& operator=(literal_node<T>&) { return (*this); }
5654
5655 const T value_;
5656 };
5657
5658 template <typename T>
5659 struct range_pack;
5660
5661 template <typename T>
5662 struct range_data_type;
5663
5664 template <typename T>
5665 class range_interface
5666 {
5667 public:
5668
5669 typedef range_pack<T> range_t;
5670
5671 virtual ~range_interface()
5672 {}
5673
5674 virtual range_t& range_ref() = 0;
5675
5676 virtual const range_t& range_ref() const = 0;
5677 };
5678
5679 #ifndef exprtk_disable_string_capabilities
5680 template <typename T>
5681 class string_base_node
5682 {
5683 public:
5684
5685 typedef range_data_type<T> range_data_type_t;
5686
5687 virtual ~string_base_node()
5688 {}
5689
5690 virtual std::string str () const = 0;
5691
5692 virtual char_cptr base() const = 0;
5693
5694 virtual std::size_t size() const = 0;
5695 };
5696
5697 template <typename T>
5698 class string_literal_node : public expression_node <T>,
5699 public string_base_node<T>,
5700 public range_interface <T>
5701 {
5702 public:
5703
5704 typedef range_pack<T> range_t;
5705
5706 explicit string_literal_node(const std::string& v)
5707 : value_(v)
5708 {
5709 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
5710 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
5711 rp_.cache.first = rp_.n0_c.second;
5712 rp_.cache.second = rp_.n1_c.second;
5713 }
5714
5715 inline T value() const
5716 {
5717 return std::numeric_limits<T>::quiet_NaN();
5718 }
5719
5720 inline typename expression_node<T>::node_type type() const
5721 {
5722 return expression_node<T>::e_stringconst;
5723 }
5724
5725 inline expression_node<T>* branch(const std::size_t&) const
5726 {
5727 return reinterpret_cast<expression_node<T>*>(0);
5728 }
5729
5730 std::string str() const
5731 {
5732 return value_;
5733 }
5734
5735 char_cptr base() const
5736 {
5737 return value_.data();
5738 }
5739
5740 std::size_t size() const
5741 {
5742 return value_.size();
5743 }
5744
5745 range_t& range_ref()
5746 {
5747 return rp_;
5748 }
5749
5750 const range_t& range_ref() const
5751 {
5752 return rp_;
5753 }
5754
5755 private:
5756
5757 string_literal_node(const string_literal_node<T>&);
5758 string_literal_node<T>& operator=(const string_literal_node<T>&);
5759
5760 const std::string value_;
5761 range_t rp_;
5762 };
5763 #endif
5764
5765 template <typename T>
5766 class unary_node : public expression_node<T>
5767 {
5768 public:
5769
5770 typedef expression_node<T>* expression_ptr;
5771
5772 unary_node(const operator_type& opr,
5773 expression_ptr brnch)
5774 : operation_(opr),
5775 branch_(brnch),
5776 branch_deletable_(branch_deletable(branch_))
5777 {}
5778
5779 ~unary_node()
5780 {
5781 if (branch_ && branch_deletable_)
5782 {
5783 destroy_node(branch_);
5784 }
5785 }
5786
5787 inline T value() const
5788 {
5789 const T arg = branch_->value();
5790
5791 return numeric::process<T>(operation_,arg);
5792 }
5793
5794 inline typename expression_node<T>::node_type type() const
5795 {
5796 return expression_node<T>::e_unary;
5797 }
5798
5799 inline operator_type operation() const
5800 {
5801 return operation_;
5802 }
5803
5804 inline expression_node<T>* branch(const std::size_t&) const
5805 {
5806 return branch_;
5807 }
5808
5809 inline void release()
5810 {
5811 branch_deletable_ = false;
5812 }
5813
5814 protected:
5815
5816 operator_type operation_;
5817 expression_ptr branch_;
5818 bool branch_deletable_;
5819 };
5820
5821 template <typename T, std::size_t D, bool B>
5822 struct construct_branch_pair
5823 {
5824 template <std::size_t N>
5825 static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
5826 {}
5827 };
5828
5829 template <typename T, std::size_t D>
5830 struct construct_branch_pair<T,D,true>
5831 {
5832 template <std::size_t N>
5833 static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
5834 {
5835 if (b)
5836 {
5837 branch[D] = std::make_pair(b,branch_deletable(b));
5838 }
5839 }
5840 };
5841
5842 template <std::size_t N, typename T>
5843 inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
5844 expression_node<T>* b0,
5845 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
5846 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
5847 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
5848 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
5849 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
5850 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
5851 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
5852 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
5853 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
5854 {
5855 construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
5856 construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
5857 construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
5858 construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
5859 construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
5860 construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
5861 construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
5862 construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
5863 construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
5864 construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
5865 }
5866
5867 struct cleanup_branches
5868 {
5869 template <typename T, std::size_t N>
5870 static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
5871 {
5872 for (std::size_t i = 0; i < N; ++i)
5873 {
5874 if (branch[i].first && branch[i].second)
5875 {
5876 destroy_node(branch[i].first);
5877 }
5878 }
5879 }
5880
5881 template <typename T,
5882 typename Allocator,
5883 template <typename, typename> class Sequence>
5884 static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
5885 {
5886 for (std::size_t i = 0; i < branch.size(); ++i)
5887 {
5888 if (branch[i].first && branch[i].second)
5889 {
5890 destroy_node(branch[i].first);
5891 }
5892 }
5893 }
5894 };
5895
5896 template <typename T>
5897 class binary_node : public expression_node<T>
5898 {
5899 public:
5900
5901 typedef expression_node<T>* expression_ptr;
5902 typedef std::pair<expression_ptr,bool> branch_t;
5903
5904 binary_node(const operator_type& opr,
5905 expression_ptr branch0,
5906 expression_ptr branch1)
5907 : operation_(opr)
5908 {
5909 init_branches<2>(branch_, branch0, branch1);
5910 }
5911
5912 ~binary_node()
5913 {
5914 cleanup_branches::execute<T,2>(branch_);
5915 }
5916
5917 inline T value() const
5918 {
5919 const T arg0 = branch_[0].first->value();
5920 const T arg1 = branch_[1].first->value();
5921
5922 return numeric::process<T>(operation_,arg0,arg1);
5923 }
5924
5925 inline typename expression_node<T>::node_type type() const
5926 {
5927 return expression_node<T>::e_binary;
5928 }
5929
5930 inline operator_type operation()
5931 {
5932 return operation_;
5933 }
5934
5935 inline expression_node<T>* branch(const std::size_t& index = 0) const
5936 {
5937 if (0 == index)
5938 return branch_[0].first;
5939 else if (1 == index)
5940 return branch_[1].first;
5941 else
5942 return reinterpret_cast<expression_ptr>(0);
5943 }
5944
5945 protected:
5946
5947 operator_type operation_;
5948 branch_t branch_[2];
5949 };
5950
5951 template <typename T, typename Operation>
5952 class binary_ext_node : public expression_node<T>
5953 {
5954 public:
5955
5956 typedef expression_node<T>* expression_ptr;
5957 typedef std::pair<expression_ptr,bool> branch_t;
5958
5959 binary_ext_node(expression_ptr branch0, expression_ptr branch1)
5960 {
5961 init_branches<2>(branch_, branch0, branch1);
5962 }
5963
5964 ~binary_ext_node()
5965 {
5966 cleanup_branches::execute<T,2>(branch_);
5967 }
5968
5969 inline T value() const
5970 {
5971 const T arg0 = branch_[0].first->value();
5972 const T arg1 = branch_[1].first->value();
5973
5974 return Operation::process(arg0,arg1);
5975 }
5976
5977 inline typename expression_node<T>::node_type type() const
5978 {
5979 return expression_node<T>::e_binary_ext;
5980 }
5981
5982 inline operator_type operation()
5983 {
5984 return Operation::operation();
5985 }
5986
5987 inline expression_node<T>* branch(const std::size_t& index = 0) const
5988 {
5989 if (0 == index)
5990 return branch_[0].first;
5991 else if (1 == index)
5992 return branch_[1].first;
5993 else
5994 return reinterpret_cast<expression_ptr>(0);
5995 }
5996
5997 protected:
5998
5999 branch_t branch_[2];
6000 };
6001
6002 template <typename T>
6003 class trinary_node : public expression_node<T>
6004 {
6005 public:
6006
6007 typedef expression_node<T>* expression_ptr;
6008 typedef std::pair<expression_ptr,bool> branch_t;
6009
6010 trinary_node(const operator_type& opr,
6011 expression_ptr branch0,
6012 expression_ptr branch1,
6013 expression_ptr branch2)
6014 : operation_(opr)
6015 {
6016 init_branches<3>(branch_, branch0, branch1, branch2);
6017 }
6018
6019 ~trinary_node()
6020 {
6021 cleanup_branches::execute<T,3>(branch_);
6022 }
6023
6024 inline T value() const
6025 {
6026 const T arg0 = branch_[0].first->value();
6027 const T arg1 = branch_[1].first->value();
6028 const T arg2 = branch_[2].first->value();
6029
6030 switch (operation_)
6031 {
6032 case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6033
6034 case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6035
6036 case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
6037 return arg1;
6038 else
6039 return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
6040
6041 default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6042 return std::numeric_limits<T>::quiet_NaN();
6043 }
6044 }
6045
6046 inline typename expression_node<T>::node_type type() const
6047 {
6048 return expression_node<T>::e_trinary;
6049 }
6050
6051 protected:
6052
6053 operator_type operation_;
6054 branch_t branch_[3];
6055 };
6056
6057 template <typename T>
6058 class quaternary_node : public expression_node<T>
6059 {
6060 public:
6061
6062 typedef expression_node<T>* expression_ptr;
6063 typedef std::pair<expression_ptr,bool> branch_t;
6064
6065 quaternary_node(const operator_type& opr,
6066 expression_ptr branch0,
6067 expression_ptr branch1,
6068 expression_ptr branch2,
6069 expression_ptr branch3)
6070 : operation_(opr)
6071 {
6072 init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6073 }
6074
6075 ~quaternary_node()
6076 {
6077 cleanup_branches::execute<T,4>(branch_);
6078 }
6079
6080 inline T value() const
6081 {
6082 return std::numeric_limits<T>::quiet_NaN();
6083 }
6084
6085 inline typename expression_node<T>::node_type type() const
6086 {
6087 return expression_node<T>::e_quaternary;
6088 }
6089
6090 protected:
6091
6092 operator_type operation_;
6093 branch_t branch_[4];
6094 };
6095
6096 template <typename T>
6097 class conditional_node : public expression_node<T>
6098 {
6099 public:
6100
6101 typedef expression_node<T>* expression_ptr;
6102
6103 conditional_node(expression_ptr test,
6104 expression_ptr consequent,
6105 expression_ptr alternative)
6106 : test_(test),
6107 consequent_(consequent),
6108 alternative_(alternative),
6109 test_deletable_(branch_deletable(test_)),
6110 consequent_deletable_(branch_deletable(consequent_)),
6111 alternative_deletable_(branch_deletable(alternative_))
6112 {}
6113
6114 ~conditional_node()
6115 {
6116 if (test_ && test_deletable_)
6117 {
6118 destroy_node(test_);
6119 }
6120
6121 if (consequent_ && consequent_deletable_ )
6122 {
6123 destroy_node(consequent_);
6124 }
6125
6126 if (alternative_ && alternative_deletable_)
6127 {
6128 destroy_node(alternative_);
6129 }
6130 }
6131
6132 inline T value() const
6133 {
6134 if (is_true(test_))
6135 return consequent_->value();
6136 else
6137 return alternative_->value();
6138 }
6139
6140 inline typename expression_node<T>::node_type type() const
6141 {
6142 return expression_node<T>::e_conditional;
6143 }
6144
6145 private:
6146
6147 expression_ptr test_;
6148 expression_ptr consequent_;
6149 expression_ptr alternative_;
6150 const bool test_deletable_;
6151 const bool consequent_deletable_;
6152 const bool alternative_deletable_;
6153 };
6154
6155 template <typename T>
6156 class cons_conditional_node : public expression_node<T>
6157 {
6158 public:
6159
6160 // Consequent only conditional statement node
6161 typedef expression_node<T>* expression_ptr;
6162
6163 cons_conditional_node(expression_ptr test,
6164 expression_ptr consequent)
6165 : test_(test),
6166 consequent_(consequent),
6167 test_deletable_(branch_deletable(test_)),
6168 consequent_deletable_(branch_deletable(consequent_))
6169 {}
6170
6171 ~cons_conditional_node()
6172 {
6173 if (test_ && test_deletable_)
6174 {
6175 destroy_node(test_);
6176 }
6177
6178 if (consequent_ && consequent_deletable_)
6179 {
6180 destroy_node(consequent_);
6181 }
6182 }
6183
6184 inline T value() const
6185 {
6186 if (is_true(test_))
6187 return consequent_->value();
6188 else
6189 return std::numeric_limits<T>::quiet_NaN();
6190 }
6191
6192 inline typename expression_node<T>::node_type type() const
6193 {
6194 return expression_node<T>::e_conditional;
6195 }
6196
6197 private:
6198
6199 expression_ptr test_;
6200 expression_ptr consequent_;
6201 const bool test_deletable_;
6202 const bool consequent_deletable_;
6203 };
6204
6205 #ifndef exprtk_disable_break_continue
6206 template <typename T>
6207 class break_exception
6208 {
6209 public:
6210
6211 break_exception(const T& v)
6212 : value(v)
6213 {}
6214
6215 T value;
6216 };
6217
6218 class continue_exception
6219 {};
6220
6221 template <typename T>
6222 class break_node : public expression_node<T>
6223 {
6224 public:
6225
6226 typedef expression_node<T>* expression_ptr;
6227
6228 break_node(expression_ptr ret = expression_ptr(0))
6229 : return_(ret),
6230 return_deletable_(branch_deletable(return_))
6231 {}
6232
6233 ~break_node()
6234 {
6235 if (return_deletable_)
6236 {
6237 destroy_node(return_);
6238 }
6239 }
6240
6241 inline T value() const
6242 {
6243 throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
6244 #ifndef _MSC_VER
6245 return std::numeric_limits<T>::quiet_NaN();
6246 #endif
6247 }
6248
6249 inline typename expression_node<T>::node_type type() const
6250 {
6251 return expression_node<T>::e_break;
6252 }
6253
6254 private:
6255
6256 expression_ptr return_;
6257 const bool return_deletable_;
6258 };
6259
6260 template <typename T>
6261 class continue_node : public expression_node<T>
6262 {
6263 public:
6264
6265 inline T value() const
6266 {
6267 throw continue_exception();
6268 #ifndef _MSC_VER
6269 return std::numeric_limits<T>::quiet_NaN();
6270 #endif
6271 }
6272
6273 inline typename expression_node<T>::node_type type() const
6274 {
6275 return expression_node<T>::e_break;
6276 }
6277 };
6278 #endif
6279
6280 template <typename T>
6281 class while_loop_node : public expression_node<T>
6282 {
6283 public:
6284
6285 typedef expression_node<T>* expression_ptr;
6286
6287 while_loop_node(expression_ptr condition, expression_ptr loop_body)
6288 : condition_(condition),
6289 loop_body_(loop_body),
6290 condition_deletable_(branch_deletable(condition_)),
6291 loop_body_deletable_(branch_deletable(loop_body_))
6292 {}
6293
6294 ~while_loop_node()
6295 {
6296 if (condition_ && condition_deletable_)
6297 {
6298 destroy_node(condition_);
6299 }
6300
6301 if (loop_body_ && loop_body_deletable_)
6302 {
6303 destroy_node(loop_body_);
6304 }
6305 }
6306
6307 inline T value() const
6308 {
6309 T result = T(0);
6310
6311 while (is_true(condition_))
6312 {
6313 result = loop_body_->value();
6314 }
6315
6316 return result;
6317 }
6318
6319 inline typename expression_node<T>::node_type type() const
6320 {
6321 return expression_node<T>::e_while;
6322 }
6323
6324 private:
6325
6326 expression_ptr condition_;
6327 expression_ptr loop_body_;
6328 const bool condition_deletable_;
6329 const bool loop_body_deletable_;
6330 };
6331
6332 template <typename T>
6333 class repeat_until_loop_node : public expression_node<T>
6334 {
6335 public:
6336
6337 typedef expression_node<T>* expression_ptr;
6338
6339 repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
6340 : condition_(condition),
6341 loop_body_(loop_body),
6342 condition_deletable_(branch_deletable(condition_)),
6343 loop_body_deletable_(branch_deletable(loop_body_))
6344 {}
6345
6346 ~repeat_until_loop_node()
6347 {
6348 if (condition_ && condition_deletable_)
6349 {
6350 destroy_node(condition_);
6351 }
6352
6353 if (loop_body_ && loop_body_deletable_)
6354 {
6355 destroy_node(loop_body_);
6356 }
6357 }
6358
6359 inline T value() const
6360 {
6361 T result = T(0);
6362
6363 do
6364 {
6365 result = loop_body_->value();
6366 }
6367 while (is_false(condition_));
6368
6369 return result;
6370 }
6371
6372 inline typename expression_node<T>::node_type type() const
6373 {
6374 return expression_node<T>::e_repeat;
6375 }
6376
6377 private:
6378
6379 expression_ptr condition_;
6380 expression_ptr loop_body_;
6381 const bool condition_deletable_;
6382 const bool loop_body_deletable_;
6383 };
6384
6385 template <typename T>
6386 class for_loop_node : public expression_node<T>
6387 {
6388 public:
6389
6390 typedef expression_node<T>* expression_ptr;
6391
6392 for_loop_node(expression_ptr initialiser,
6393 expression_ptr condition,
6394 expression_ptr incrementor,
6395 expression_ptr loop_body)
6396 : initialiser_(initialiser),
6397 condition_ (condition ),
6398 incrementor_(incrementor),
6399 loop_body_ (loop_body ),
6400 initialiser_deletable_(branch_deletable(initialiser_)),
6401 condition_deletable_ (branch_deletable(condition_ )),
6402 incrementor_deletable_(branch_deletable(incrementor_)),
6403 loop_body_deletable_ (branch_deletable(loop_body_ ))
6404 {}
6405
6406 ~for_loop_node()
6407 {
6408 if (initialiser_ && initialiser_deletable_)
6409 {
6410 destroy_node(initialiser_);
6411 }
6412
6413 if (condition_ && condition_deletable_)
6414 {
6415 destroy_node(condition_);
6416 }
6417
6418 if (incrementor_ && incrementor_deletable_)
6419 {
6420 destroy_node(incrementor_);
6421 }
6422
6423 if (loop_body_ && loop_body_deletable_)
6424 {
6425 destroy_node(loop_body_);
6426 }
6427 }
6428
6429 inline T value() const
6430 {
6431 T result = T(0);
6432
6433 if (initialiser_)
6434 initialiser_->value();
6435
6436 if (incrementor_)
6437 {
6438 while (is_true(condition_))
6439 {
6440 result = loop_body_->value();
6441 incrementor_->value();
6442 }
6443 }
6444 else
6445 {
6446 while (is_true(condition_))
6447 {
6448 result = loop_body_->value();
6449 }
6450 }
6451
6452 return result;
6453 }
6454
6455 inline typename expression_node<T>::node_type type() const
6456 {
6457 return expression_node<T>::e_for;
6458 }
6459
6460 private:
6461
6462 expression_ptr initialiser_ ;
6463 expression_ptr condition_ ;
6464 expression_ptr incrementor_ ;
6465 expression_ptr loop_body_ ;
6466 const bool initialiser_deletable_;
6467 const bool condition_deletable_ ;
6468 const bool incrementor_deletable_;
6469 const bool loop_body_deletable_ ;
6470 };
6471
6472 #ifndef exprtk_disable_break_continue
6473 template <typename T>
6474 class while_loop_bc_node : public expression_node<T>
6475 {
6476 public:
6477
6478 typedef expression_node<T>* expression_ptr;
6479
6480 while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6481 : condition_(condition),
6482 loop_body_(loop_body),
6483 condition_deletable_(branch_deletable(condition_)),
6484 loop_body_deletable_(branch_deletable(loop_body_))
6485 {}
6486
6487 ~while_loop_bc_node()
6488 {
6489 if (condition_ && condition_deletable_)
6490 {
6491 destroy_node(condition_);
6492 }
6493
6494 if (loop_body_ && loop_body_deletable_)
6495 {
6496 destroy_node(loop_body_);
6497 }
6498 }
6499
6500 inline T value() const
6501 {
6502 T result = T(0);
6503
6504 while (is_true(condition_))
6505 {
6506 try
6507 {
6508 result = loop_body_->value();
6509 }
6510 catch(const break_exception<T>& e)
6511 {
6512 return e.value;
6513 }
6514 catch(const continue_exception&)
6515 {}
6516 }
6517
6518 return result;
6519 }
6520
6521 inline typename expression_node<T>::node_type type() const
6522 {
6523 return expression_node<T>::e_while;
6524 }
6525
6526 private:
6527
6528 expression_ptr condition_;
6529 expression_ptr loop_body_;
6530 const bool condition_deletable_;
6531 const bool loop_body_deletable_;
6532 };
6533
6534 template <typename T>
6535 class repeat_until_loop_bc_node : public expression_node<T>
6536 {
6537 public:
6538
6539 typedef expression_node<T>* expression_ptr;
6540
6541 repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6542 : condition_(condition),
6543 loop_body_(loop_body),
6544 condition_deletable_(branch_deletable(condition_)),
6545 loop_body_deletable_(branch_deletable(loop_body_))
6546 {}
6547
6548 ~repeat_until_loop_bc_node()
6549 {
6550 if (condition_ && condition_deletable_)
6551 {
6552 destroy_node(condition_);
6553 }
6554
6555 if (loop_body_ && loop_body_deletable_)
6556 {
6557 destroy_node(loop_body_);
6558 }
6559 }
6560
6561 inline T value() const
6562 {
6563 T result = T(0);
6564
6565 do
6566 {
6567 try
6568 {
6569 result = loop_body_->value();
6570 }
6571 catch(const break_exception<T>& e)
6572 {
6573 return e.value;
6574 }
6575 catch(const continue_exception&)
6576 {}
6577 }
6578 while (is_false(condition_));
6579
6580 return result;
6581 }
6582
6583 inline typename expression_node<T>::node_type type() const
6584 {
6585 return expression_node<T>::e_repeat;
6586 }
6587
6588 private:
6589
6590 expression_ptr condition_;
6591 expression_ptr loop_body_;
6592 const bool condition_deletable_;
6593 const bool loop_body_deletable_;
6594 };
6595
6596 template <typename T>
6597 class for_loop_bc_node : public expression_node<T>
6598 {
6599 public:
6600
6601 typedef expression_node<T>* expression_ptr;
6602
6603 for_loop_bc_node(expression_ptr initialiser,
6604 expression_ptr condition,
6605 expression_ptr incrementor,
6606 expression_ptr loop_body)
6607 : initialiser_(initialiser),
6608 condition_ (condition ),
6609 incrementor_(incrementor),
6610 loop_body_ (loop_body ),
6611 initialiser_deletable_(branch_deletable(initialiser_)),
6612 condition_deletable_ (branch_deletable(condition_ )),
6613 incrementor_deletable_(branch_deletable(incrementor_)),
6614 loop_body_deletable_ (branch_deletable(loop_body_ ))
6615 {}
6616
6617 ~for_loop_bc_node()
6618 {
6619 if (initialiser_ && initialiser_deletable_)
6620 {
6621 destroy_node(initialiser_);
6622 }
6623
6624 if (condition_ && condition_deletable_)
6625 {
6626 destroy_node(condition_);
6627 }
6628
6629 if (incrementor_ && incrementor_deletable_)
6630 {
6631 destroy_node(incrementor_);
6632 }
6633
6634 if (loop_body_ && loop_body_deletable_)
6635 {
6636 destroy_node(loop_body_);
6637 }
6638 }
6639
6640 inline T value() const
6641 {
6642 T result = T(0);
6643
6644 if (initialiser_)
6645 initialiser_->value();
6646
6647 if (incrementor_)
6648 {
6649 while (is_true(condition_))
6650 {
6651 try
6652 {
6653 result = loop_body_->value();
6654 }
6655 catch(const break_exception<T>& e)
6656 {
6657 return e.value;
6658 }
6659 catch(const continue_exception&)
6660 {}
6661
6662 incrementor_->value();
6663 }
6664 }
6665 else
6666 {
6667 while (is_true(condition_))
6668 {
6669 try
6670 {
6671 result = loop_body_->value();
6672 }
6673 catch(const break_exception<T>& e)
6674 {
6675 return e.value;
6676 }
6677 catch(const continue_exception&)
6678 {}
6679 }
6680 }
6681
6682 return result;
6683 }
6684
6685 inline typename expression_node<T>::node_type type() const
6686 {
6687 return expression_node<T>::e_for;
6688 }
6689
6690 private:
6691
6692 expression_ptr initialiser_;
6693 expression_ptr condition_ ;
6694 expression_ptr incrementor_;
6695 expression_ptr loop_body_ ;
6696 const bool initialiser_deletable_;
6697 const bool condition_deletable_ ;
6698 const bool incrementor_deletable_;
6699 const bool loop_body_deletable_ ;
6700 };
6701 #endif
6702
6703 template <typename T>
6704 class switch_node : public expression_node<T>
6705 {
6706 public:
6707
6708 typedef expression_node<T>* expression_ptr;
6709
6710 template <typename Allocator,
6711 template <typename, typename> class Sequence>
6712 explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6713 {
6714 if (1 != (arg_list.size() & 1))
6715 return;
6716
6717 arg_list_.resize(arg_list.size());
6718 delete_branch_.resize(arg_list.size());
6719
6720 for (std::size_t i = 0; i < arg_list.size(); ++i)
6721 {
6722 if (arg_list[i])
6723 {
6724 arg_list_[i] = arg_list[i];
6725 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6726 }
6727 else
6728 {
6729 arg_list_.clear();
6730 delete_branch_.clear();
6731 return;
6732 }
6733 }
6734 }
6735
6736 ~switch_node()
6737 {
6738 for (std::size_t i = 0; i < arg_list_.size(); ++i)
6739 {
6740 if (arg_list_[i] && delete_branch_[i])
6741 {
6742 destroy_node(arg_list_[i]);
6743 }
6744 }
6745 }
6746
6747 inline T value() const
6748 {
6749 if (!arg_list_.empty())
6750 {
6751 const std::size_t upper_bound = (arg_list_.size() - 1);
6752
6753 for (std::size_t i = 0; i < upper_bound; i += 2)
6754 {
6755 expression_ptr condition = arg_list_[i ];
6756 expression_ptr consequent = arg_list_[i + 1];
6757
6758 if (is_true(condition))
6759 {
6760 return consequent->value();
6761 }
6762 }
6763
6764 return arg_list_[upper_bound]->value();
6765 }
6766 else
6767 return std::numeric_limits<T>::quiet_NaN();
6768 }
6769
6770 inline typename expression_node<T>::node_type type() const
6771 {
6772 return expression_node<T>::e_switch;
6773 }
6774
6775 protected:
6776
6777 std::vector<expression_ptr> arg_list_;
6778 std::vector<unsigned char> delete_branch_;
6779 };
6780
6781 template <typename T, typename Switch_N>
6782 class switch_n_node : public switch_node<T>
6783 {
6784 public:
6785
6786 typedef expression_node<T>* expression_ptr;
6787
6788 template <typename Allocator,
6789 template <typename, typename> class Sequence>
6790 explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
6791 : switch_node<T>(arg_list)
6792 {}
6793
6794 inline T value() const
6795 {
6796 return Switch_N::process(switch_node<T>::arg_list_);
6797 }
6798 };
6799
6800 template <typename T>
6801 class multi_switch_node : public expression_node<T>
6802 {
6803 public:
6804
6805 typedef expression_node<T>* expression_ptr;
6806
6807 template <typename Allocator,
6808 template <typename, typename> class Sequence>
6809 explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6810 {
6811 if (0 != (arg_list.size() & 1))
6812 return;
6813
6814 arg_list_.resize(arg_list.size());
6815 delete_branch_.resize(arg_list.size());
6816
6817 for (std::size_t i = 0; i < arg_list.size(); ++i)
6818 {
6819 if (arg_list[i])
6820 {
6821 arg_list_[i] = arg_list[i];
6822 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6823 }
6824 else
6825 {
6826 arg_list_.clear();
6827 delete_branch_.clear();
6828 return;
6829 }
6830 }
6831 }
6832
6833 ~multi_switch_node()
6834 {
6835 for (std::size_t i = 0; i < arg_list_.size(); ++i)
6836 {
6837 if (arg_list_[i] && delete_branch_[i])
6838 {
6839 destroy_node(arg_list_[i]);
6840 }
6841 }
6842 }
6843
6844 inline T value() const
6845 {
6846 T result = T(0);
6847
6848 if (arg_list_.empty())
6849 {
6850 return std::numeric_limits<T>::quiet_NaN();
6851 }
6852
6853 const std::size_t upper_bound = (arg_list_.size() - 1);
6854
6855 for (std::size_t i = 0; i < upper_bound; i += 2)
6856 {
6857 expression_ptr condition = arg_list_[i ];
6858 expression_ptr consequent = arg_list_[i + 1];
6859
6860 if (is_true(condition))
6861 {
6862 result = consequent->value();
6863 }
6864 }
6865
6866 return result;
6867 }
6868
6869 inline typename expression_node<T>::node_type type() const
6870 {
6871 return expression_node<T>::e_mswitch;
6872 }
6873
6874 private:
6875
6876 std::vector<expression_ptr> arg_list_;
6877 std::vector<unsigned char> delete_branch_;
6878 };
6879
6880 template <typename T>
6881 class ivariable
6882 {
6883 public:
6884
6885 virtual ~ivariable()
6886 {}
6887
6888 virtual T& ref() = 0;
6889 virtual const T& ref() const = 0;
6890 };
6891
6892 template <typename T>
6893 class variable_node : public expression_node<T>,
6894 public ivariable <T>
6895 {
6896 public:
6897
6898 static T null_value;
6899
6900 explicit variable_node()
6901 : value_(&null_value)
6902 {}
6903
6904 explicit variable_node(T& v)
6905 : value_(&v)
6906 {}
6907
6908 inline bool operator <(const variable_node<T>& v) const
6909 {
6910 return this < (&v);
6911 }
6912
6913 inline T value() const
6914 {
6915 return (*value_);
6916 }
6917
6918 inline T& ref()
6919 {
6920 return (*value_);
6921 }
6922
6923 inline const T& ref() const
6924 {
6925 return (*value_);
6926 }
6927
6928 inline typename expression_node<T>::node_type type() const
6929 {
6930 return expression_node<T>::e_variable;
6931 }
6932
6933 private:
6934
6935 T* value_;
6936 };
6937
6938 template <typename T>
6939 T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
6940
6941 template <typename T>
6942 struct range_pack
6943 {
6944 typedef expression_node<T>* expression_node_ptr;
6945 typedef std::pair<std::size_t,std::size_t> cached_range_t;
6946
6947 range_pack()
6948 : n0_e (std::make_pair(false,expression_node_ptr(0))),
6949 n1_e (std::make_pair(false,expression_node_ptr(0))),
6950 n0_c (std::make_pair(false,0)),
6951 n1_c (std::make_pair(false,0)),
6952 cache(std::make_pair(0,0))
6953 {}
6954
6955 void clear()
6956 {
6957 n0_e = std::make_pair(false,expression_node_ptr(0));
6958 n1_e = std::make_pair(false,expression_node_ptr(0));
6959 n0_c = std::make_pair(false,0);
6960 n1_c = std::make_pair(false,0);
6961 cache = std::make_pair(0,0);
6962 }
6963
6964 void free()
6965 {
6966 if (n0_e.first && n0_e.second)
6967 {
6968 n0_e.first = false;
6969
6970 if (
6971 !is_variable_node(n0_e.second) &&
6972 !is_string_node (n0_e.second)
6973 )
6974 {
6975 destroy_node(n0_e.second);
6976 }
6977 }
6978
6979 if (n1_e.first && n1_e.second)
6980 {
6981 n1_e.first = false;
6982
6983 if (
6984 !is_variable_node(n1_e.second) &&
6985 !is_string_node (n1_e.second)
6986 )
6987 {
6988 destroy_node(n1_e.second);
6989 }
6990 }
6991 }
6992
6993 bool const_range()
6994 {
6995 return ( n0_c.first && n1_c.first) &&
6996 (!n0_e.first && !n1_e.first);
6997 }
6998
6999 bool var_range()
7000 {
7001 return ( n0_e.first && n1_e.first) &&
7002 (!n0_c.first && !n1_c.first);
7003 }
7004
7005 bool operator() (std::size_t& r0, std::size_t& r1,
7006 const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
7007 {
7008 if (n0_c.first)
7009 r0 = n0_c.second;
7010 else if (n0_e.first)
7011 {
7012 const T r0_value = n0_e.second->value();
7013
7014 if (r0_value < 0)
7015 return false;
7016 else
7017 r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
7018 }
7019 else
7020 return false;
7021
7022 if (n1_c.first)
7023 r1 = n1_c.second;
7024 else if (n1_e.first)
7025 {
7026 const T r1_value = n1_e.second->value();
7027
7028 if (r1_value < 0)
7029 return false;
7030 else
7031 r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
7032 }
7033 else
7034 return false;
7035
7036 if (
7037 (std::numeric_limits<std::size_t>::max() != size) &&
7038 (std::numeric_limits<std::size_t>::max() == r1 )
7039 )
7040 {
7041 r1 = size - 1;
7042 }
7043
7044 cache.first = r0;
7045 cache.second = r1;
7046
7047 return (r0 <= r1);
7048 }
7049
7050 inline std::size_t const_size() const
7051 {
7052 return (n1_c.second - n0_c.second + 1);
7053 }
7054
7055 inline std::size_t cache_size() const
7056 {
7057 return (cache.second - cache.first + 1);
7058 }
7059
7060 std::pair<bool,expression_node_ptr> n0_e;
7061 std::pair<bool,expression_node_ptr> n1_e;
7062 std::pair<bool,std::size_t > n0_c;
7063 std::pair<bool,std::size_t > n1_c;
7064 mutable cached_range_t cache;
7065 };
7066
7067 template <typename T>
7068 class string_base_node;
7069
7070 template <typename T>
7071 struct range_data_type
7072 {
7073 typedef range_pack<T> range_t;
7074 typedef string_base_node<T>* strbase_ptr_t;
7075
7076 range_data_type()
7077 : range(0),
7078 data (0),
7079 size (0),
7080 type_size(0),
7081 str_node (0)
7082 {}
7083
7084 range_t* range;
7085 void* data;
7086 std::size_t size;
7087 std::size_t type_size;
7088 strbase_ptr_t str_node;
7089 };
7090
7091 template <typename T> class vector_node;
7092
7093 template <typename T>
7094 class vector_interface
7095 {
7096 public:
7097
7098 typedef vector_node<T>* vector_node_ptr;
7099 typedef vec_data_store<T> vds_t;
7100
7101 virtual ~vector_interface()
7102 {}
7103
7104 virtual std::size_t size () const = 0;
7105
7106 virtual vector_node_ptr vec() const = 0;
7107
7108 virtual vector_node_ptr vec() = 0;
7109
7110 virtual vds_t& vds () = 0;
7111
7112 virtual const vds_t& vds () const = 0;
7113
7114 virtual bool side_effect () const { return false; }
7115 };
7116
7117 template <typename T>
7118 class vector_node : public expression_node <T>,
7119 public vector_interface<T>
7120 {
7121 public:
7122
7123 typedef expression_node<T>* expression_ptr;
7124 typedef vector_holder<T> vector_holder_t;
7125 typedef vector_node<T>* vector_node_ptr;
7126 typedef vec_data_store<T> vds_t;
7127
7128 explicit vector_node(vector_holder_t* vh)
7129 : vector_holder_(vh),
7130 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7131 {
7132 vector_holder_->set_ref(&vds_.ref());
7133 }
7134
7135 vector_node(const vds_t& vds, vector_holder_t* vh)
7136 : vector_holder_(vh),
7137 vds_(vds)
7138 {}
7139
7140 inline T value() const
7141 {
7142 return vds().data()[0];
7143 }
7144
7145 vector_node_ptr vec() const
7146 {
7147 return const_cast<vector_node_ptr>(this);
7148 }
7149
7150 vector_node_ptr vec()
7151 {
7152 return this;
7153 }
7154
7155 inline typename expression_node<T>::node_type type() const
7156 {
7157 return expression_node<T>::e_vector;
7158 }
7159
7160 std::size_t size() const
7161 {
7162 return vds().size();
7163 }
7164
7165 vds_t& vds()
7166 {
7167 return vds_;
7168 }
7169
7170 const vds_t& vds() const
7171 {
7172 return vds_;
7173 }
7174
7175 inline vector_holder_t& vec_holder()
7176 {
7177 return (*vector_holder_);
7178 }
7179
7180 private:
7181
7182 vector_holder_t* vector_holder_;
7183 vds_t vds_;
7184 };
7185
7186 template <typename T>
7187 class vector_elem_node : public expression_node<T>,
7188 public ivariable <T>
7189 {
7190 public:
7191
7192 typedef expression_node<T>* expression_ptr;
7193 typedef vector_holder<T> vector_holder_t;
7194 typedef vector_holder_t* vector_holder_ptr;
7195
7196 vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7197 : index_(index),
7198 vec_holder_(vec_holder),
7199 vector_base_((*vec_holder)[0]),
7200 index_deletable_(branch_deletable(index_))
7201 {}
7202
7203 ~vector_elem_node()
7204 {
7205 if (index_ && index_deletable_)
7206 {
7207 destroy_node(index_);
7208 }
7209 }
7210
7211 inline T value() const
7212 {
7213 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7214 }
7215
7216 inline T& ref()
7217 {
7218 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7219 }
7220
7221 inline const T& ref() const
7222 {
7223 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7224 }
7225
7226 inline typename expression_node<T>::node_type type() const
7227 {
7228 return expression_node<T>::e_vecelem;
7229 }
7230
7231 inline vector_holder_t& vec_holder()
7232 {
7233 return (*vec_holder_);
7234 }
7235
7236 private:
7237
7238 expression_ptr index_;
7239 vector_holder_ptr vec_holder_;
7240 T* vector_base_;
7241 const bool index_deletable_;
7242 };
7243
7244 template <typename T>
7245 class rebasevector_elem_node : public expression_node<T>,
7246 public ivariable <T>
7247 {
7248 public:
7249
7250 typedef expression_node<T>* expression_ptr;
7251 typedef vector_holder<T> vector_holder_t;
7252 typedef vector_holder_t* vector_holder_ptr;
7253 typedef vec_data_store<T> vds_t;
7254
7255 rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7256 : index_(index),
7257 index_deletable_(branch_deletable(index_)),
7258 vector_holder_(vec_holder),
7259 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7260 {
7261 vector_holder_->set_ref(&vds_.ref());
7262 }
7263
7264 ~rebasevector_elem_node()
7265 {
7266 if (index_ && index_deletable_)
7267 {
7268 destroy_node(index_);
7269 }
7270 }
7271
7272 inline T value() const
7273 {
7274 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7275 }
7276
7277 inline T& ref()
7278 {
7279 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7280 }
7281
7282 inline const T& ref() const
7283 {
7284 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7285 }
7286
7287 inline typename expression_node<T>::node_type type() const
7288 {
7289 return expression_node<T>::e_rbvecelem;
7290 }
7291
7292 inline vector_holder_t& vec_holder()
7293 {
7294 return (*vector_holder_);
7295 }
7296
7297 private:
7298
7299 expression_ptr index_;
7300 const bool index_deletable_;
7301 vector_holder_ptr vector_holder_;
7302 vds_t vds_;
7303 };
7304
7305 template <typename T>
7306 class rebasevector_celem_node : public expression_node<T>,
7307 public ivariable <T>
7308 {
7309 public:
7310
7311 typedef expression_node<T>* expression_ptr;
7312 typedef vector_holder<T> vector_holder_t;
7313 typedef vector_holder_t* vector_holder_ptr;
7314 typedef vec_data_store<T> vds_t;
7315
7316 rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
7317 : index_(index),
7318 vector_holder_(vec_holder),
7319 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7320 {
7321 vector_holder_->set_ref(&vds_.ref());
7322 }
7323
7324 inline T value() const
7325 {
7326 return *(vds_.data() + index_);
7327 }
7328
7329 inline T& ref()
7330 {
7331 return *(vds_.data() + index_);
7332 }
7333
7334 inline const T& ref() const
7335 {
7336 return *(vds_.data() + index_);
7337 }
7338
7339 inline typename expression_node<T>::node_type type() const
7340 {
7341 return expression_node<T>::e_rbveccelem;
7342 }
7343
7344 inline vector_holder_t& vec_holder()
7345 {
7346 return (*vector_holder_);
7347 }
7348
7349 private:
7350
7351 const std::size_t index_;
7352 vector_holder_ptr vector_holder_;
7353 vds_t vds_;
7354 };
7355
7356 template <typename T>
7357 class vector_assignment_node : public expression_node<T>
7358 {
7359 public:
7360
7361 typedef expression_node<T>* expression_ptr;
7362
7363 vector_assignment_node(T* vector_base,
7364 const std::size_t& size,
7365 const std::vector<expression_ptr>& initialiser_list,
7366 const bool single_value_initialse)
7367 : vector_base_(vector_base),
7368 initialiser_list_(initialiser_list),
7369 size_(size),
7370 single_value_initialse_(single_value_initialse)
7371 {}
7372
7373 ~vector_assignment_node()
7374 {
7375 for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
7376 {
7377 if (branch_deletable(initialiser_list_[i]))
7378 {
7379 destroy_node(initialiser_list_[i]);
7380 }
7381 }
7382 }
7383
7384 inline T value() const
7385 {
7386 if (single_value_initialse_)
7387 {
7388 for (std::size_t i = 0; i < size_; ++i)
7389 {
7390 *(vector_base_ + i) = initialiser_list_[0]->value();
7391 }
7392 }
7393 else
7394 {
7395 std::size_t il_size = initialiser_list_.size();
7396
7397 for (std::size_t i = 0; i < il_size; ++i)
7398 {
7399 *(vector_base_ + i) = initialiser_list_[i]->value();
7400 }
7401
7402 if (il_size < size_)
7403 {
7404 for (std::size_t i = il_size; i < size_; ++i)
7405 {
7406 *(vector_base_ + i) = T(0);
7407 }
7408 }
7409 }
7410
7411 return *(vector_base_);
7412 }
7413
7414 inline typename expression_node<T>::node_type type() const
7415 {
7416 return expression_node<T>::e_vecdefass;
7417 }
7418
7419 private:
7420
7421 vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
7422
7423 mutable T* vector_base_;
7424 std::vector<expression_ptr> initialiser_list_;
7425 const std::size_t size_;
7426 const bool single_value_initialse_;
7427 };
7428
7429 template <typename T>
7430 class swap_node : public expression_node<T>
7431 {
7432 public:
7433
7434 typedef expression_node<T>* expression_ptr;
7435 typedef variable_node<T>* variable_node_ptr;
7436
7437 swap_node(variable_node_ptr var0, variable_node_ptr var1)
7438 : var0_(var0),
7439 var1_(var1)
7440 {}
7441
7442 inline T value() const
7443 {
7444 std::swap(var0_->ref(),var1_->ref());
7445 return var1_->ref();
7446 }
7447
7448 inline typename expression_node<T>::node_type type() const
7449 {
7450 return expression_node<T>::e_swap;
7451 }
7452
7453 private:
7454
7455 variable_node_ptr var0_;
7456 variable_node_ptr var1_;
7457 };
7458
7459 template <typename T>
7460 class swap_generic_node : public binary_node<T>
7461 {
7462 public:
7463
7464 typedef expression_node<T>* expression_ptr;
7465 typedef ivariable<T>* ivariable_ptr;
7466
7467 swap_generic_node(expression_ptr var0, expression_ptr var1)
7468 : binary_node<T>(details::e_swap, var0, var1),
7469 var0_(dynamic_cast<ivariable_ptr>(var0)),
7470 var1_(dynamic_cast<ivariable_ptr>(var1))
7471 {}
7472
7473 inline T value() const
7474 {
7475 std::swap(var0_->ref(),var1_->ref());
7476 return var1_->ref();
7477 }
7478
7479 inline typename expression_node<T>::node_type type() const
7480 {
7481 return expression_node<T>::e_swap;
7482 }
7483
7484 private:
7485
7486 ivariable_ptr var0_;
7487 ivariable_ptr var1_;
7488 };
7489
7490 template <typename T>
7491 class swap_vecvec_node : public binary_node <T>,
7492 public vector_interface<T>
7493 {
7494 public:
7495
7496 typedef expression_node<T>* expression_ptr;
7497 typedef vector_node<T>* vector_node_ptr;
7498 typedef vec_data_store<T> vds_t;
7499
7500 swap_vecvec_node(expression_ptr branch0,
7501 expression_ptr branch1)
7502 : binary_node<T>(details::e_swap, branch0, branch1),
7503 vec0_node_ptr_(0),
7504 vec1_node_ptr_(0),
7505 vec_size_ (0),
7506 initialised_ (false)
7507 {
7508 if (is_ivector_node(binary_node<T>::branch_[0].first))
7509 {
7510 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7511
7512 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
7513 {
7514 vec0_node_ptr_ = vi->vec();
7515 vds() = vi->vds();
7516 }
7517 }
7518
7519 if (is_ivector_node(binary_node<T>::branch_[1].first))
7520 {
7521 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7522
7523 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
7524 {
7525 vec1_node_ptr_ = vi->vec();
7526 }
7527 }
7528
7529 if (vec0_node_ptr_ && vec1_node_ptr_)
7530 {
7531 vec_size_ = std::min(vec0_node_ptr_->vds().size(),
7532 vec1_node_ptr_->vds().size());
7533
7534 initialised_ = true;
7535 }
7536 }
7537
7538 inline T value() const
7539 {
7540 if (initialised_)
7541 {
7542 binary_node<T>::branch_[0].first->value();
7543 binary_node<T>::branch_[1].first->value();
7544
7545 T* vec0 = vec0_node_ptr_->vds().data();
7546 T* vec1 = vec1_node_ptr_->vds().data();
7547
7548 for (std::size_t i = 0; i < vec_size_; ++i)
7549 {
7550 std::swap(vec0[i],vec1[i]);
7551 }
7552
7553 return vec1_node_ptr_->value();
7554 }
7555 else
7556 return std::numeric_limits<T>::quiet_NaN();
7557 }
7558
7559 vector_node_ptr vec() const
7560 {
7561 return vec0_node_ptr_;
7562 }
7563
7564 vector_node_ptr vec()
7565 {
7566 return vec0_node_ptr_;
7567 }
7568
7569 inline typename expression_node<T>::node_type type() const
7570 {
7571 return expression_node<T>::e_vecvecswap;
7572 }
7573
7574 std::size_t size() const
7575 {
7576 return vec_size_;
7577 }
7578
7579 vds_t& vds()
7580 {
7581 return vds_;
7582 }
7583
7584 const vds_t& vds() const
7585 {
7586 return vds_;
7587 }
7588
7589 private:
7590
7591 vector_node<T>* vec0_node_ptr_;
7592 vector_node<T>* vec1_node_ptr_;
7593 std::size_t vec_size_;
7594 bool initialised_;
7595 vds_t vds_;
7596 };
7597
7598 #ifndef exprtk_disable_string_capabilities
7599 template <typename T>
7600 class stringvar_node : public expression_node <T>,
7601 public string_base_node<T>,
7602 public range_interface <T>
7603 {
7604 public:
7605
7606 typedef range_pack<T> range_t;
7607
7608 static std::string null_value;
7609
7610 explicit stringvar_node()
7611 : value_(&null_value)
7612 {}
7613
7614 explicit stringvar_node(std::string& v)
7615 : value_(&v)
7616 {
7617 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7618 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
7619 rp_.cache.first = rp_.n0_c.second;
7620 rp_.cache.second = rp_.n1_c.second;
7621 }
7622
7623 inline bool operator <(const stringvar_node<T>& v) const
7624 {
7625 return this < (&v);
7626 }
7627
7628 inline T value() const
7629 {
7630 rp_.n1_c.second = (*value_).size() - 1;
7631 rp_.cache.second = rp_.n1_c.second;
7632
7633 return std::numeric_limits<T>::quiet_NaN();
7634 }
7635
7636 std::string str() const
7637 {
7638 return ref();
7639 }
7640
7641 char_cptr base() const
7642 {
7643 return &(*value_)[0];
7644 }
7645
7646 std::size_t size() const
7647 {
7648 return ref().size();
7649 }
7650
7651 std::string& ref()
7652 {
7653 return (*value_);
7654 }
7655
7656 const std::string& ref() const
7657 {
7658 return (*value_);
7659 }
7660
7661 range_t& range_ref()
7662 {
7663 return rp_;
7664 }
7665
7666 const range_t& range_ref() const
7667 {
7668 return rp_;
7669 }
7670
7671 inline typename expression_node<T>::node_type type() const
7672 {
7673 return expression_node<T>::e_stringvar;
7674 }
7675
7676 private:
7677
7678 std::string* value_;
7679 mutable range_t rp_;
7680 };
7681
7682 template <typename T>
7683 std::string stringvar_node<T>::null_value = std::string("");
7684
7685 template <typename T>
7686 class string_range_node : public expression_node <T>,
7687 public string_base_node<T>,
7688 public range_interface <T>
7689 {
7690 public:
7691
7692 typedef range_pack<T> range_t;
7693
7694 static std::string null_value;
7695
7696 explicit string_range_node(std::string& v, const range_t& rp)
7697 : value_(&v),
7698 rp_(rp)
7699 {}
7700
7701 virtual ~string_range_node()
7702 {
7703 rp_.free();
7704 }
7705
7706 inline bool operator <(const string_range_node<T>& v) const
7707 {
7708 return this < (&v);
7709 }
7710
7711 inline T value() const
7712 {
7713 return std::numeric_limits<T>::quiet_NaN();
7714 }
7715
7716 inline std::string str() const
7717 {
7718 return (*value_);
7719 }
7720
7721 char_cptr base() const
7722 {
7723 return &(*value_)[0];
7724 }
7725
7726 std::size_t size() const
7727 {
7728 return ref().size();
7729 }
7730
7731 inline range_t range() const
7732 {
7733 return rp_;
7734 }
7735
7736 inline virtual std::string& ref()
7737 {
7738 return (*value_);
7739 }
7740
7741 inline virtual const std::string& ref() const
7742 {
7743 return (*value_);
7744 }
7745
7746 inline range_t& range_ref()
7747 {
7748 return rp_;
7749 }
7750
7751 inline const range_t& range_ref() const
7752 {
7753 return rp_;
7754 }
7755
7756 inline typename expression_node<T>::node_type type() const
7757 {
7758 return expression_node<T>::e_stringvarrng;
7759 }
7760
7761 private:
7762
7763 std::string* value_;
7764 range_t rp_;
7765 };
7766
7767 template <typename T>
7768 std::string string_range_node<T>::null_value = std::string("");
7769
7770 template <typename T>
7771 class const_string_range_node : public expression_node <T>,
7772 public string_base_node<T>,
7773 public range_interface <T>
7774 {
7775 public:
7776
7777 typedef range_pack<T> range_t;
7778
7779 explicit const_string_range_node(const std::string& v, const range_t& rp)
7780 : value_(v),
7781 rp_(rp)
7782 {}
7783
7784 ~const_string_range_node()
7785 {
7786 rp_.free();
7787 }
7788
7789 inline T value() const
7790 {
7791 return std::numeric_limits<T>::quiet_NaN();
7792 }
7793
7794 std::string str() const
7795 {
7796 return value_;
7797 }
7798
7799 char_cptr base() const
7800 {
7801 return value_.data();
7802 }
7803
7804 std::size_t size() const
7805 {
7806 return value_.size();
7807 }
7808
7809 range_t range() const
7810 {
7811 return rp_;
7812 }
7813
7814 range_t& range_ref()
7815 {
7816 return rp_;
7817 }
7818
7819 const range_t& range_ref() const
7820 {
7821 return rp_;
7822 }
7823
7824 inline typename expression_node<T>::node_type type() const
7825 {
7826 return expression_node<T>::e_cstringvarrng;
7827 }
7828
7829 private:
7830
7831 const_string_range_node<T>& operator=(const const_string_range_node<T>&);
7832
7833 const std::string value_;
7834 range_t rp_;
7835 };
7836
7837 template <typename T>
7838 class generic_string_range_node : public expression_node <T>,
7839 public string_base_node<T>,
7840 public range_interface <T>
7841 {
7842 public:
7843
7844 typedef expression_node <T>* expression_ptr;
7845 typedef stringvar_node <T>* strvar_node_ptr;
7846 typedef string_base_node<T>* str_base_ptr;
7847 typedef range_pack <T> range_t;
7848 typedef range_t* range_ptr;
7849 typedef range_interface<T> irange_t;
7850 typedef irange_t* irange_ptr;
7851
7852 generic_string_range_node(expression_ptr str_branch, const range_t& brange)
7853 : initialised_(false),
7854 branch_(str_branch),
7855 branch_deletable_(branch_deletable(branch_)),
7856 str_base_ptr_ (0),
7857 str_range_ptr_(0),
7858 base_range_(brange)
7859 {
7860 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7861 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7862 range_.cache.first = range_.n0_c.second;
7863 range_.cache.second = range_.n1_c.second;
7864
7865 if (is_generally_string_node(branch_))
7866 {
7867 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
7868
7869 if (0 == str_base_ptr_)
7870 return;
7871
7872 str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
7873
7874 if (0 == str_range_ptr_)
7875 return;
7876 }
7877
7878 initialised_ = (str_base_ptr_ && str_range_ptr_);
7879 }
7880
7881 ~generic_string_range_node()
7882 {
7883 base_range_.free();
7884
7885 if (branch_ && branch_deletable_)
7886 {
7887 destroy_node(branch_);
7888 }
7889 }
7890
7891 inline T value() const
7892 {
7893 if (initialised_)
7894 {
7895 branch_->value();
7896
7897 std::size_t str_r0 = 0;
7898 std::size_t str_r1 = 0;
7899
7900 std::size_t r0 = 0;
7901 std::size_t r1 = 0;
7902
7903 range_t& range = str_range_ptr_->range_ref();
7904
7905 const std::size_t base_str_size = str_base_ptr_->size();
7906
7907 if (
7908 range (str_r0, str_r1, base_str_size) &&
7909 base_range_( r0, r1, base_str_size)
7910 )
7911 {
7912 const std::size_t size = (r1 - r0) + 1;
7913
7914 range_.n1_c.second = size - 1;
7915 range_.cache.second = range_.n1_c.second;
7916
7917 value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
7918 }
7919 }
7920
7921 return std::numeric_limits<T>::quiet_NaN();
7922 }
7923
7924 std::string str() const
7925 {
7926 return value_;
7927 }
7928
7929 char_cptr base() const
7930 {
7931 return &value_[0];
7932 }
7933
7934 std::size_t size() const
7935 {
7936 return value_.size();
7937 }
7938
7939 range_t& range_ref()
7940 {
7941 return range_;
7942 }
7943
7944 const range_t& range_ref() const
7945 {
7946 return range_;
7947 }
7948
7949 inline typename expression_node<T>::node_type type() const
7950 {
7951 return expression_node<T>::e_strgenrange;
7952 }
7953
7954 private:
7955
7956 bool initialised_;
7957 expression_ptr branch_;
7958 const bool branch_deletable_;
7959 str_base_ptr str_base_ptr_;
7960 irange_ptr str_range_ptr_;
7961 mutable range_t base_range_;
7962 mutable range_t range_;
7963 mutable std::string value_;
7964 };
7965
7966 template <typename T>
7967 class string_concat_node : public binary_node <T>,
7968 public string_base_node<T>,
7969 public range_interface <T>
7970 {
7971 public:
7972
7973 typedef expression_node <T>* expression_ptr;
7974 typedef string_base_node<T>* str_base_ptr;
7975 typedef range_pack <T> range_t;
7976 typedef range_t* range_ptr;
7977 typedef range_interface<T> irange_t;
7978 typedef irange_t* irange_ptr;
7979
7980 string_concat_node(const operator_type& opr,
7981 expression_ptr branch0,
7982 expression_ptr branch1)
7983 : binary_node<T>(opr, branch0, branch1),
7984 initialised_(false),
7985 str0_base_ptr_ (0),
7986 str1_base_ptr_ (0),
7987 str0_range_ptr_(0),
7988 str1_range_ptr_(0)
7989 {
7990 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7991 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7992
7993 range_.cache.first = range_.n0_c.second;
7994 range_.cache.second = range_.n1_c.second;
7995
7996 if (is_generally_string_node(binary_node<T>::branch_[0].first))
7997 {
7998 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
7999
8000 if (0 == str0_base_ptr_)
8001 return;
8002
8003 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8004
8005 if (0 == str0_range_ptr_)
8006 return;
8007 }
8008
8009 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8010 {
8011 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8012
8013 if (0 == str1_base_ptr_)
8014 return;
8015
8016 str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8017
8018 if (0 == str1_range_ptr_)
8019 return;
8020 }
8021
8022 initialised_ = str0_base_ptr_ &&
8023 str1_base_ptr_ &&
8024 str0_range_ptr_ &&
8025 str1_range_ptr_ ;
8026 }
8027
8028 inline T value() const
8029 {
8030 if (initialised_)
8031 {
8032 binary_node<T>::branch_[0].first->value();
8033 binary_node<T>::branch_[1].first->value();
8034
8035 std::size_t str0_r0 = 0;
8036 std::size_t str0_r1 = 0;
8037
8038 std::size_t str1_r0 = 0;
8039 std::size_t str1_r1 = 0;
8040
8041 range_t& range0 = str0_range_ptr_->range_ref();
8042 range_t& range1 = str1_range_ptr_->range_ref();
8043
8044 if (
8045 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8046 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8047 )
8048 {
8049 const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8050 const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8051
8052 value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8053 value_.append(str1_base_ptr_->base() + str1_r0, size1);
8054
8055 range_.n1_c.second = value_.size() - 1;
8056 range_.cache.second = range_.n1_c.second;
8057 }
8058 }
8059
8060 return std::numeric_limits<T>::quiet_NaN();
8061 }
8062
8063 std::string str() const
8064 {
8065 return value_;
8066 }
8067
8068 char_cptr base() const
8069 {
8070 return &value_[0];
8071 }
8072
8073 std::size_t size() const
8074 {
8075 return value_.size();
8076 }
8077
8078 range_t& range_ref()
8079 {
8080 return range_;
8081 }
8082
8083 const range_t& range_ref() const
8084 {
8085 return range_;
8086 }
8087
8088 inline typename expression_node<T>::node_type type() const
8089 {
8090 return expression_node<T>::e_strconcat;
8091 }
8092
8093 private:
8094
8095 bool initialised_;
8096 str_base_ptr str0_base_ptr_;
8097 str_base_ptr str1_base_ptr_;
8098 irange_ptr str0_range_ptr_;
8099 irange_ptr str1_range_ptr_;
8100 mutable range_t range_;
8101 mutable std::string value_;
8102 };
8103
8104 template <typename T>
8105 class swap_string_node : public binary_node <T>,
8106 public string_base_node<T>,
8107 public range_interface <T>
8108 {
8109 public:
8110
8111 typedef expression_node <T>* expression_ptr;
8112 typedef stringvar_node <T>* strvar_node_ptr;
8113 typedef string_base_node<T>* str_base_ptr;
8114 typedef range_pack <T> range_t;
8115 typedef range_t* range_ptr;
8116 typedef range_interface<T> irange_t;
8117 typedef irange_t* irange_ptr;
8118
8119 swap_string_node(expression_ptr branch0, expression_ptr branch1)
8120 : binary_node<T>(details::e_swap, branch0, branch1),
8121 initialised_(false),
8122 str0_node_ptr_(0),
8123 str1_node_ptr_(0)
8124 {
8125 if (is_string_node(binary_node<T>::branch_[0].first))
8126 {
8127 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8128 }
8129
8130 if (is_string_node(binary_node<T>::branch_[1].first))
8131 {
8132 str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8133 }
8134
8135 initialised_ = (str0_node_ptr_ && str1_node_ptr_);
8136 }
8137
8138 inline T value() const
8139 {
8140 if (initialised_)
8141 {
8142 binary_node<T>::branch_[0].first->value();
8143 binary_node<T>::branch_[1].first->value();
8144
8145 std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
8146 }
8147
8148 return std::numeric_limits<T>::quiet_NaN();
8149 }
8150
8151 std::string str() const
8152 {
8153 return str0_node_ptr_->str();
8154 }
8155
8156 char_cptr base() const
8157 {
8158 return str0_node_ptr_->base();
8159 }
8160
8161 std::size_t size() const
8162 {
8163 return str0_node_ptr_->size();
8164 }
8165
8166 range_t& range_ref()
8167 {
8168 return str0_node_ptr_->range_ref();
8169 }
8170
8171 const range_t& range_ref() const
8172 {
8173 return str0_node_ptr_->range_ref();
8174 }
8175
8176 inline typename expression_node<T>::node_type type() const
8177 {
8178 return expression_node<T>::e_strswap;
8179 }
8180
8181 private:
8182
8183 bool initialised_;
8184 strvar_node_ptr str0_node_ptr_;
8185 strvar_node_ptr str1_node_ptr_;
8186 };
8187
8188 template <typename T>
8189 class swap_genstrings_node : public binary_node<T>
8190 {
8191 public:
8192
8193 typedef expression_node <T>* expression_ptr;
8194 typedef string_base_node<T>* str_base_ptr;
8195 typedef range_pack <T> range_t;
8196 typedef range_t* range_ptr;
8197 typedef range_interface<T> irange_t;
8198 typedef irange_t* irange_ptr;
8199
8200 swap_genstrings_node(expression_ptr branch0,
8201 expression_ptr branch1)
8202 : binary_node<T>(details::e_default, branch0, branch1),
8203 str0_base_ptr_ (0),
8204 str1_base_ptr_ (0),
8205 str0_range_ptr_(0),
8206 str1_range_ptr_(0),
8207 initialised_(false)
8208 {
8209 if (is_generally_string_node(binary_node<T>::branch_[0].first))
8210 {
8211 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8212
8213 if (0 == str0_base_ptr_)
8214 return;
8215
8216 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8217
8218 if (0 == range)
8219 return;
8220
8221 str0_range_ptr_ = &(range->range_ref());
8222 }
8223
8224 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8225 {
8226 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8227
8228 if (0 == str1_base_ptr_)
8229 return;
8230
8231 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8232
8233 if (0 == range)
8234 return;
8235
8236 str1_range_ptr_ = &(range->range_ref());
8237 }
8238
8239 initialised_ = str0_base_ptr_ &&
8240 str1_base_ptr_ &&
8241 str0_range_ptr_ &&
8242 str1_range_ptr_ ;
8243 }
8244
8245 inline T value() const
8246 {
8247 if (initialised_)
8248 {
8249 binary_node<T>::branch_[0].first->value();
8250 binary_node<T>::branch_[1].first->value();
8251
8252 std::size_t str0_r0 = 0;
8253 std::size_t str0_r1 = 0;
8254
8255 std::size_t str1_r0 = 0;
8256 std::size_t str1_r1 = 0;
8257
8258 range_t& range0 = (*str0_range_ptr_);
8259 range_t& range1 = (*str1_range_ptr_);
8260
8261 if (
8262 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8263 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8264 )
8265 {
8266 const std::size_t size0 = range0.cache_size();
8267 const std::size_t size1 = range1.cache_size();
8268 const std::size_t max_size = std::min(size0,size1);
8269
8270 char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8271 char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8272
8273 loop_unroll::details lud(max_size);
8274 char_cptr upper_bound = s0 + lud.upper_bound;
8275
8276 while (s0 < upper_bound)
8277 {
8278 #define exprtk_loop(N) \
8279 std::swap(s0[N], s1[N]); \
8280
8281 exprtk_loop( 0) exprtk_loop( 1)
8282 exprtk_loop( 2) exprtk_loop( 3)
8283 #ifndef exprtk_disable_superscalar_unroll
8284 exprtk_loop( 4) exprtk_loop( 5)
8285 exprtk_loop( 6) exprtk_loop( 7)
8286 exprtk_loop( 8) exprtk_loop( 9)
8287 exprtk_loop(10) exprtk_loop(11)
8288 exprtk_loop(12) exprtk_loop(13)
8289 exprtk_loop(14) exprtk_loop(15)
8290 #endif
8291
8292 s0 += lud.batch_size;
8293 s1 += lud.batch_size;
8294 }
8295
8296 int i = 0;
8297
8298 exprtk_disable_fallthrough_begin
8299 switch (lud.remainder)
8300 {
8301 #define case_stmt(N) \
8302 case N : { std::swap(s0[i], s1[i]); ++i; } \
8303
8304 #ifndef exprtk_disable_superscalar_unroll
8305 case_stmt(15) case_stmt(14)
8306 case_stmt(13) case_stmt(12)
8307 case_stmt(11) case_stmt(10)
8308 case_stmt( 9) case_stmt( 8)
8309 case_stmt( 7) case_stmt( 6)
8310 case_stmt( 5) case_stmt( 4)
8311 #endif
8312 case_stmt( 3) case_stmt( 2)
8313 case_stmt( 1)
8314 }
8315 exprtk_disable_fallthrough_end
8316
8317 #undef exprtk_loop
8318 #undef case_stmt
8319 }
8320 }
8321
8322 return std::numeric_limits<T>::quiet_NaN();
8323 }
8324
8325 inline typename expression_node<T>::node_type type() const
8326 {
8327 return expression_node<T>::e_strswap;
8328 }
8329
8330 private:
8331
8332 swap_genstrings_node(swap_genstrings_node<T>&);
8333 swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
8334
8335 str_base_ptr str0_base_ptr_;
8336 str_base_ptr str1_base_ptr_;
8337 range_ptr str0_range_ptr_;
8338 range_ptr str1_range_ptr_;
8339 bool initialised_;
8340 };
8341
8342 template <typename T>
8343 class stringvar_size_node : public expression_node<T>
8344 {
8345 public:
8346
8347 static std::string null_value;
8348
8349 explicit stringvar_size_node()
8350 : value_(&null_value)
8351 {}
8352
8353 explicit stringvar_size_node(std::string& v)
8354 : value_(&v)
8355 {}
8356
8357 inline T value() const
8358 {
8359 return T((*value_).size());
8360 }
8361
8362 inline typename expression_node<T>::node_type type() const
8363 {
8364 return expression_node<T>::e_stringvarsize;
8365 }
8366
8367 private:
8368
8369 std::string* value_;
8370 };
8371
8372 template <typename T>
8373 std::string stringvar_size_node<T>::null_value = std::string("");
8374
8375 template <typename T>
8376 class string_size_node : public expression_node<T>
8377 {
8378 public:
8379
8380 typedef expression_node <T>* expression_ptr;
8381 typedef string_base_node<T>* str_base_ptr;
8382
8383 explicit string_size_node(expression_ptr brnch)
8384 : branch_(brnch),
8385 branch_deletable_(branch_deletable(branch_)),
8386 str_base_ptr_(0)
8387 {
8388 if (is_generally_string_node(branch_))
8389 {
8390 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
8391
8392 if (0 == str_base_ptr_)
8393 return;
8394 }
8395 }
8396
8397 ~string_size_node()
8398 {
8399 if (branch_ && branch_deletable_)
8400 {
8401 destroy_node(branch_);
8402 }
8403 }
8404
8405 inline T value() const
8406 {
8407 T result = std::numeric_limits<T>::quiet_NaN();
8408
8409 if (str_base_ptr_)
8410 {
8411 branch_->value();
8412 result = T(str_base_ptr_->size());
8413 }
8414
8415 return result;
8416 }
8417
8418 inline typename expression_node<T>::node_type type() const
8419 {
8420 return expression_node<T>::e_stringsize;
8421 }
8422
8423 private:
8424
8425 expression_ptr branch_;
8426 const bool branch_deletable_;
8427 str_base_ptr str_base_ptr_;
8428 };
8429
8430 struct asn_assignment
8431 {
8432 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8433 { s.assign(data,size); }
8434 };
8435
8436 struct asn_addassignment
8437 {
8438 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8439 { s.append(data,size); }
8440 };
8441
8442 template <typename T, typename AssignmentProcess = asn_assignment>
8443 class assignment_string_node : public binary_node <T>,
8444 public string_base_node<T>,
8445 public range_interface <T>
8446 {
8447 public:
8448
8449 typedef expression_node <T>* expression_ptr;
8450 typedef stringvar_node <T>* strvar_node_ptr;
8451 typedef string_base_node<T>* str_base_ptr;
8452 typedef range_pack <T> range_t;
8453 typedef range_t* range_ptr;
8454 typedef range_interface<T> irange_t;
8455 typedef irange_t* irange_ptr;
8456
8457 assignment_string_node(const operator_type& opr,
8458 expression_ptr branch0,
8459 expression_ptr branch1)
8460 : binary_node<T>(opr, branch0, branch1),
8461 initialised_(false),
8462 str0_base_ptr_ (0),
8463 str1_base_ptr_ (0),
8464 str0_node_ptr_ (0),
8465 str1_range_ptr_(0)
8466 {
8467 if (is_string_node(binary_node<T>::branch_[0].first))
8468 {
8469 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8470
8471 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8472 }
8473
8474 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8475 {
8476 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8477
8478 if (0 == str1_base_ptr_)
8479 return;
8480
8481 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8482
8483 if (0 == range)
8484 return;
8485
8486 str1_range_ptr_ = &(range->range_ref());
8487 }
8488
8489 initialised_ = str0_base_ptr_ &&
8490 str1_base_ptr_ &&
8491 str0_node_ptr_ &&
8492 str1_range_ptr_ ;
8493 }
8494
8495 inline T value() const
8496 {
8497 if (initialised_)
8498 {
8499 binary_node<T>::branch_[1].first->value();
8500
8501 std::size_t r0 = 0;
8502 std::size_t r1 = 0;
8503
8504 range_t& range = (*str1_range_ptr_);
8505
8506 if (range(r0, r1, str1_base_ptr_->size()))
8507 {
8508 AssignmentProcess::execute(str0_node_ptr_->ref(),
8509 str1_base_ptr_->base() + r0,
8510 (r1 - r0) + 1);
8511
8512 binary_node<T>::branch_[0].first->value();
8513 }
8514 }
8515
8516 return std::numeric_limits<T>::quiet_NaN();
8517 }
8518
8519 std::string str() const
8520 {
8521 return str0_node_ptr_->str();
8522 }
8523
8524 char_cptr base() const
8525 {
8526 return str0_node_ptr_->base();
8527 }
8528
8529 std::size_t size() const
8530 {
8531 return str0_node_ptr_->size();
8532 }
8533
8534 range_t& range_ref()
8535 {
8536 return str0_node_ptr_->range_ref();
8537 }
8538
8539 const range_t& range_ref() const
8540 {
8541 return str0_node_ptr_->range_ref();
8542 }
8543
8544 inline typename expression_node<T>::node_type type() const
8545 {
8546 return expression_node<T>::e_strass;
8547 }
8548
8549 private:
8550
8551 bool initialised_;
8552 str_base_ptr str0_base_ptr_;
8553 str_base_ptr str1_base_ptr_;
8554 strvar_node_ptr str0_node_ptr_;
8555 range_ptr str1_range_ptr_;
8556 };
8557
8558 template <typename T, typename AssignmentProcess = asn_assignment>
8559 class assignment_string_range_node : public binary_node <T>,
8560 public string_base_node<T>,
8561 public range_interface <T>
8562 {
8563 public:
8564
8565 typedef expression_node <T>* expression_ptr;
8566 typedef stringvar_node <T>* strvar_node_ptr;
8567 typedef string_base_node<T>* str_base_ptr;
8568 typedef range_pack <T> range_t;
8569 typedef range_t* range_ptr;
8570 typedef range_interface<T> irange_t;
8571 typedef irange_t* irange_ptr;
8572
8573 assignment_string_range_node(const operator_type& opr,
8574 expression_ptr branch0,
8575 expression_ptr branch1)
8576 : binary_node<T>(opr, branch0, branch1),
8577 initialised_(false),
8578 str0_base_ptr_ (0),
8579 str1_base_ptr_ (0),
8580 str0_node_ptr_ (0),
8581 str0_range_ptr_(0),
8582 str1_range_ptr_(0)
8583 {
8584 if (is_string_range_node(binary_node<T>::branch_[0].first))
8585 {
8586 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8587
8588 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8589
8590 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8591
8592 if (0 == range)
8593 return;
8594
8595 str0_range_ptr_ = &(range->range_ref());
8596 }
8597
8598 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8599 {
8600 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8601
8602 if (0 == str1_base_ptr_)
8603 return;
8604
8605 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8606
8607 if (0 == range)
8608 return;
8609
8610 str1_range_ptr_ = &(range->range_ref());
8611 }
8612
8613 initialised_ = str0_base_ptr_ &&
8614 str1_base_ptr_ &&
8615 str0_node_ptr_ &&
8616 str0_range_ptr_ &&
8617 str1_range_ptr_ ;
8618 }
8619
8620 inline T value() const
8621 {
8622 if (initialised_)
8623 {
8624 binary_node<T>::branch_[0].first->value();
8625 binary_node<T>::branch_[1].first->value();
8626
8627 std::size_t s0_r0 = 0;
8628 std::size_t s0_r1 = 0;
8629
8630 std::size_t s1_r0 = 0;
8631 std::size_t s1_r1 = 0;
8632
8633 range_t& range0 = (*str0_range_ptr_);
8634 range_t& range1 = (*str1_range_ptr_);
8635
8636 if (
8637 range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
8638 range1(s1_r0, s1_r1, str1_base_ptr_->size())
8639 )
8640 {
8641 std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
8642
8643 std::copy(str1_base_ptr_->base() + s1_r0,
8644 str1_base_ptr_->base() + s1_r0 + size,
8645 const_cast<char_ptr>(base() + s0_r0));
8646 }
8647 }
8648
8649 return std::numeric_limits<T>::quiet_NaN();
8650 }
8651
8652 std::string str() const
8653 {
8654 return str0_node_ptr_->str();
8655 }
8656
8657 char_cptr base() const
8658 {
8659 return str0_node_ptr_->base();
8660 }
8661
8662 std::size_t size() const
8663 {
8664 return str0_node_ptr_->size();
8665 }
8666
8667 range_t& range_ref()
8668 {
8669 return str0_node_ptr_->range_ref();
8670 }
8671
8672 const range_t& range_ref() const
8673 {
8674 return str0_node_ptr_->range_ref();
8675 }
8676
8677 inline typename expression_node<T>::node_type type() const
8678 {
8679 return expression_node<T>::e_strass;
8680 }
8681
8682 private:
8683
8684 bool initialised_;
8685 str_base_ptr str0_base_ptr_;
8686 str_base_ptr str1_base_ptr_;
8687 strvar_node_ptr str0_node_ptr_;
8688 range_ptr str0_range_ptr_;
8689 range_ptr str1_range_ptr_;
8690 };
8691
8692 template <typename T>
8693 class conditional_string_node : public trinary_node <T>,
8694 public string_base_node<T>,
8695 public range_interface <T>
8696 {
8697 public:
8698
8699 typedef expression_node <T>* expression_ptr;
8700 typedef string_base_node<T>* str_base_ptr;
8701 typedef range_pack <T> range_t;
8702 typedef range_t* range_ptr;
8703 typedef range_interface<T> irange_t;
8704 typedef irange_t* irange_ptr;
8705
8706 conditional_string_node(expression_ptr test,
8707 expression_ptr consequent,
8708 expression_ptr alternative)
8709 : trinary_node<T>(details::e_default,consequent,alternative,test),
8710 initialised_(false),
8711 str0_base_ptr_ (0),
8712 str1_base_ptr_ (0),
8713 str0_range_ptr_(0),
8714 str1_range_ptr_(0),
8715 test_ (test),
8716 consequent_ (consequent),
8717 alternative_(alternative)
8718 {
8719 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8720 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8721
8722 range_.cache.first = range_.n0_c.second;
8723 range_.cache.second = range_.n1_c.second;
8724
8725 if (is_generally_string_node(trinary_node<T>::branch_[0].first))
8726 {
8727 str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
8728
8729 if (0 == str0_base_ptr_)
8730 return;
8731
8732 str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
8733
8734 if (0 == str0_range_ptr_)
8735 return;
8736 }
8737
8738 if (is_generally_string_node(trinary_node<T>::branch_[1].first))
8739 {
8740 str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
8741
8742 if (0 == str1_base_ptr_)
8743 return;
8744
8745 str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
8746
8747 if (0 == str1_range_ptr_)
8748 return;
8749 }
8750
8751 initialised_ = str0_base_ptr_ &&
8752 str1_base_ptr_ &&
8753 str0_range_ptr_ &&
8754 str1_range_ptr_ ;
8755
8756 }
8757
8758 inline T value() const
8759 {
8760 if (initialised_)
8761 {
8762 std::size_t r0 = 0;
8763 std::size_t r1 = 0;
8764
8765 if (is_true(test_))
8766 {
8767 consequent_->value();
8768
8769 range_t& range = str0_range_ptr_->range_ref();
8770
8771 if (range(r0, r1, str0_base_ptr_->size()))
8772 {
8773 const std::size_t size = (r1 - r0) + 1;
8774
8775 value_.assign(str0_base_ptr_->base() + r0, size);
8776
8777 range_.n1_c.second = value_.size() - 1;
8778 range_.cache.second = range_.n1_c.second;
8779
8780 return T(1);
8781 }
8782 }
8783 else
8784 {
8785 alternative_->value();
8786
8787 range_t& range = str1_range_ptr_->range_ref();
8788
8789 if (range(r0, r1, str1_base_ptr_->size()))
8790 {
8791 const std::size_t size = (r1 - r0) + 1;
8792
8793 value_.assign(str1_base_ptr_->base() + r0, size);
8794
8795 range_.n1_c.second = value_.size() - 1;
8796 range_.cache.second = range_.n1_c.second;
8797
8798 return T(0);
8799 }
8800 }
8801 }
8802
8803 return std::numeric_limits<T>::quiet_NaN();
8804 }
8805
8806 std::string str() const
8807 {
8808 return value_;
8809 }
8810
8811 char_cptr base() const
8812 {
8813 return &value_[0];
8814 }
8815
8816 std::size_t size() const
8817 {
8818 return value_.size();
8819 }
8820
8821 range_t& range_ref()
8822 {
8823 return range_;
8824 }
8825
8826 const range_t& range_ref() const
8827 {
8828 return range_;
8829 }
8830
8831 inline typename expression_node<T>::node_type type() const
8832 {
8833 return expression_node<T>::e_strcondition;
8834 }
8835
8836 private:
8837
8838 bool initialised_;
8839 str_base_ptr str0_base_ptr_;
8840 str_base_ptr str1_base_ptr_;
8841 irange_ptr str0_range_ptr_;
8842 irange_ptr str1_range_ptr_;
8843 mutable range_t range_;
8844 mutable std::string value_;
8845
8846 expression_ptr test_;
8847 expression_ptr consequent_;
8848 expression_ptr alternative_;
8849 };
8850
8851 template <typename T>
8852 class cons_conditional_str_node : public binary_node <T>,
8853 public string_base_node<T>,
8854 public range_interface <T>
8855 {
8856 public:
8857
8858 typedef expression_node <T>* expression_ptr;
8859 typedef string_base_node<T>* str_base_ptr;
8860 typedef range_pack <T> range_t;
8861 typedef range_t* range_ptr;
8862 typedef range_interface<T> irange_t;
8863 typedef irange_t* irange_ptr;
8864
8865 cons_conditional_str_node(expression_ptr test,
8866 expression_ptr consequent)
8867 : binary_node<T>(details::e_default, consequent, test),
8868 initialised_(false),
8869 str0_base_ptr_ (0),
8870 str0_range_ptr_(0),
8871 test_ (test),
8872 consequent_(consequent)
8873 {
8874 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8875 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8876
8877 range_.cache.first = range_.n0_c.second;
8878 range_.cache.second = range_.n1_c.second;
8879
8880 if (is_generally_string_node(binary_node<T>::branch_[0].first))
8881 {
8882 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8883
8884 if (0 == str0_base_ptr_)
8885 return;
8886
8887 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8888
8889 if (0 == str0_range_ptr_)
8890 return;
8891 }
8892
8893 initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
8894 }
8895
8896 inline T value() const
8897 {
8898 if (initialised_)
8899 {
8900 if (is_true(test_))
8901 {
8902 consequent_->value();
8903
8904 range_t& range = str0_range_ptr_->range_ref();
8905
8906 std::size_t r0 = 0;
8907 std::size_t r1 = 0;
8908
8909 if (range(r0, r1, str0_base_ptr_->size()))
8910 {
8911 const std::size_t size = (r1 - r0) + 1;
8912
8913 value_.assign(str0_base_ptr_->base() + r0, size);
8914
8915 range_.n1_c.second = value_.size() - 1;
8916 range_.cache.second = range_.n1_c.second;
8917
8918 return T(1);
8919 }
8920 }
8921 }
8922
8923 return std::numeric_limits<T>::quiet_NaN();
8924 }
8925
8926 std::string str() const
8927 {
8928 return value_;
8929 }
8930
8931 char_cptr base() const
8932 {
8933 return &value_[0];
8934 }
8935
8936 std::size_t size() const
8937 {
8938 return value_.size();
8939 }
8940
8941 range_t& range_ref()
8942 {
8943 return range_;
8944 }
8945
8946 const range_t& range_ref() const
8947 {
8948 return range_;
8949 }
8950
8951 inline typename expression_node<T>::node_type type() const
8952 {
8953 return expression_node<T>::e_strccondition;
8954 }
8955
8956 private:
8957
8958 bool initialised_;
8959 str_base_ptr str0_base_ptr_;
8960 irange_ptr str0_range_ptr_;
8961 mutable range_t range_;
8962 mutable std::string value_;
8963
8964 expression_ptr test_;
8965 expression_ptr consequent_;
8966 };
8967
8968 template <typename T, typename VarArgFunction>
8969 class str_vararg_node : public expression_node <T>,
8970 public string_base_node<T>,
8971 public range_interface <T>
8972 {
8973 public:
8974
8975 typedef expression_node <T>* expression_ptr;
8976 typedef string_base_node<T>* str_base_ptr;
8977 typedef range_pack <T> range_t;
8978 typedef range_t* range_ptr;
8979 typedef range_interface<T> irange_t;
8980 typedef irange_t* irange_ptr;
8981
8982 template <typename Allocator,
8983 template <typename, typename> class Sequence>
8984 explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
8985 : final_node_(arg_list.back()),
8986 final_deletable_(branch_deletable(final_node_)),
8987 initialised_(false),
8988 str_base_ptr_ (0),
8989 str_range_ptr_(0)
8990 {
8991 if (0 == final_node_)
8992 return;
8993 else if (!is_generally_string_node(final_node_))
8994 return;
8995
8996 str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
8997
8998 if (0 == str_base_ptr_)
8999 return;
9000
9001 str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
9002
9003 if (0 == str_range_ptr_)
9004 return;
9005
9006 initialised_ = str_base_ptr_ && str_range_ptr_;
9007
9008 if (arg_list.size() > 1)
9009 {
9010 const std::size_t arg_list_size = arg_list.size() - 1;
9011
9012 arg_list_.resize(arg_list_size);
9013 delete_branch_.resize(arg_list_size);
9014
9015 for (std::size_t i = 0; i < arg_list_size; ++i)
9016 {
9017 if (arg_list[i])
9018 {
9019 arg_list_[i] = arg_list[i];
9020 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9021 }
9022 else
9023 {
9024 arg_list_ .clear();
9025 delete_branch_.clear();
9026 return;
9027 }
9028 }
9029 }
9030 }
9031
9032 ~str_vararg_node()
9033 {
9034 if (final_node_ && final_deletable_)
9035 {
9036 destroy_node(final_node_);
9037 }
9038
9039 for (std::size_t i = 0; i < arg_list_.size(); ++i)
9040 {
9041 if (arg_list_[i] && delete_branch_[i])
9042 {
9043 destroy_node(arg_list_[i]);
9044 }
9045 }
9046 }
9047
9048 inline T value() const
9049 {
9050 if (!arg_list_.empty())
9051 {
9052 VarArgFunction::process(arg_list_);
9053 }
9054
9055 final_node_->value();
9056
9057 return std::numeric_limits<T>::quiet_NaN();
9058 }
9059
9060 std::string str() const
9061 {
9062 return str_base_ptr_->str();
9063 }
9064
9065 char_cptr base() const
9066 {
9067 return str_base_ptr_->base();
9068 }
9069
9070 std::size_t size() const
9071 {
9072 return str_base_ptr_->size();
9073 }
9074
9075 range_t& range_ref()
9076 {
9077 return str_range_ptr_->range_ref();
9078 }
9079
9080 const range_t& range_ref() const
9081 {
9082 return str_range_ptr_->range_ref();
9083 }
9084
9085 inline typename expression_node<T>::node_type type() const
9086 {
9087 return expression_node<T>::e_stringvararg;
9088 }
9089
9090 private:
9091
9092 expression_ptr final_node_;
9093 bool final_deletable_;
9094 bool initialised_;
9095 str_base_ptr str_base_ptr_;
9096 irange_ptr str_range_ptr_;
9097 std::vector<expression_ptr> arg_list_;
9098 std::vector<unsigned char> delete_branch_;
9099 };
9100 #endif
9101
9102 template <typename T, std::size_t N>
9103 inline T axn(T a, T x)
9104 {
9105 // a*x^n
9106 return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
9107 }
9108
9109 template <typename T, std::size_t N>
9110 inline T axnb(T a, T x, T b)
9111 {
9112 // a*x^n+b
9113 return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
9114 }
9115
9116 template <typename T>
9117 struct sf_base
9118 {
9119 typedef typename details::functor_t<T>::Type Type;
9120 typedef typename details::functor_t<T> functor_t;
9121 typedef typename functor_t::qfunc_t quaternary_functor_t;
9122 typedef typename functor_t::tfunc_t trinary_functor_t;
9123 typedef typename functor_t::bfunc_t binary_functor_t;
9124 typedef typename functor_t::ufunc_t unary_functor_t;
9125 };
9126
9127 #define define_sfop3(NN,OP0,OP1) \
9128 template <typename T> \
9129 struct sf##NN##_op : public sf_base<T> \
9130 { \
9131 typedef typename sf_base<T>::Type const Type; \
9132 static inline T process(Type x, Type y, Type z) \
9133 { \
9134 return (OP0); \
9135 } \
9136 static inline std::string id() \
9137 { \
9138 return OP1; \
9139 } \
9140 }; \
9141
9142 define_sfop3(00,(x + y) / z ,"(t+t)/t")
9143 define_sfop3(01,(x + y) * z ,"(t+t)*t")
9144 define_sfop3(02,(x + y) - z ,"(t+t)-t")
9145 define_sfop3(03,(x + y) + z ,"(t+t)+t")
9146 define_sfop3(04,(x - y) + z ,"(t-t)+t")
9147 define_sfop3(05,(x - y) / z ,"(t-t)/t")
9148 define_sfop3(06,(x - y) * z ,"(t-t)*t")
9149 define_sfop3(07,(x * y) + z ,"(t*t)+t")
9150 define_sfop3(08,(x * y) - z ,"(t*t)-t")
9151 define_sfop3(09,(x * y) / z ,"(t*t)/t")
9152 define_sfop3(10,(x * y) * z ,"(t*t)*t")
9153 define_sfop3(11,(x / y) + z ,"(t/t)+t")
9154 define_sfop3(12,(x / y) - z ,"(t/t)-t")
9155 define_sfop3(13,(x / y) / z ,"(t/t)/t")
9156 define_sfop3(14,(x / y) * z ,"(t/t)*t")
9157 define_sfop3(15,x / (y + z) ,"t/(t+t)")
9158 define_sfop3(16,x / (y - z) ,"t/(t-t)")
9159 define_sfop3(17,x / (y * z) ,"t/(t*t)")
9160 define_sfop3(18,x / (y / z) ,"t/(t/t)")
9161 define_sfop3(19,x * (y + z) ,"t*(t+t)")
9162 define_sfop3(20,x * (y - z) ,"t*(t-t)")
9163 define_sfop3(21,x * (y * z) ,"t*(t*t)")
9164 define_sfop3(22,x * (y / z) ,"t*(t/t)")
9165 define_sfop3(23,x - (y + z) ,"t-(t+t)")
9166 define_sfop3(24,x - (y - z) ,"t-(t-t)")
9167 define_sfop3(25,x - (y / z) ,"t-(t/t)")
9168 define_sfop3(26,x - (y * z) ,"t-(t*t)")
9169 define_sfop3(27,x + (y * z) ,"t+(t*t)")
9170 define_sfop3(28,x + (y / z) ,"t+(t/t)")
9171 define_sfop3(29,x + (y + z) ,"t+(t+t)")
9172 define_sfop3(30,x + (y - z) ,"t+(t-t)")
9173 define_sfop3(31,(axnb<T,2>(x,y,z))," ")
9174 define_sfop3(32,(axnb<T,3>(x,y,z))," ")
9175 define_sfop3(33,(axnb<T,4>(x,y,z))," ")
9176 define_sfop3(34,(axnb<T,5>(x,y,z))," ")
9177 define_sfop3(35,(axnb<T,6>(x,y,z))," ")
9178 define_sfop3(36,(axnb<T,7>(x,y,z))," ")
9179 define_sfop3(37,(axnb<T,8>(x,y,z))," ")
9180 define_sfop3(38,(axnb<T,9>(x,y,z))," ")
9181 define_sfop3(39,x * numeric::log(y) + z,"")
9182 define_sfop3(40,x * numeric::log(y) - z,"")
9183 define_sfop3(41,x * numeric::log10(y) + z,"")
9184 define_sfop3(42,x * numeric::log10(y) - z,"")
9185 define_sfop3(43,x * numeric::sin(y) + z ,"")
9186 define_sfop3(44,x * numeric::sin(y) - z ,"")
9187 define_sfop3(45,x * numeric::cos(y) + z ,"")
9188 define_sfop3(46,x * numeric::cos(y) - z ,"")
9189 define_sfop3(47,details::is_true(x) ? y : z,"")
9190
9191 #define define_sfop4(NN,OP0,OP1) \
9192 template <typename T> \
9193 struct sf##NN##_op : public sf_base<T> \
9194 { \
9195 typedef typename sf_base<T>::Type const Type; \
9196 static inline T process(Type x, Type y, Type z, Type w) \
9197 { \
9198 return (OP0); \
9199 } \
9200 static inline std::string id() { return OP1; } \
9201 }; \
9202
9203 define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9204 define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9205 define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9206 define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9207 define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9208 define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9209 define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9210 define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9211 define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9212 define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9213 define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9214 define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9215 define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9216 define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9217 define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9218 define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9219 define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9220 define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9221 define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9222 define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9223 define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9224 define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9225 define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9226 define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9227 define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9228 define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9229 define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9230 define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9231 define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9232 define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9233 define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9234 define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9235 define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9236 define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9237 define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9238 define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9239
9240 define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9241 define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9242 define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9243 define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9244 define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9245 define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9246 define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9247 define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9248 define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9249 define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9250 define_sfop4(94,((x < y) ? z : w),"")
9251 define_sfop4(95,((x <= y) ? z : w),"")
9252 define_sfop4(96,((x > y) ? z : w),"")
9253 define_sfop4(97,((x >= y) ? z : w),"")
9254 define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9255 define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9256
9257 define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9258 define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9259 define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9260 define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9261 define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9262 define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9263 define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9264 define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9265 define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9266 define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9267 define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9268 define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9269 define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9270 define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9271 define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9272 define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9273 define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9274 define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9275 define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9276 define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9277 define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9278 define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9279 define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9280 define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9281 define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9282 define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9283 define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9284 define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9285 define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9286 define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9287 define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9288 define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9289 define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9290 define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9291 define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9292 define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9293 define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9294 define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9295 define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9296 define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9297 define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9298 define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9299 define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9300 define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9301 define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9302 define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9303 define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9304 define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9305 define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9306 define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9307 define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9308 define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9309 define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9310 define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9311 define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9312 define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9313 define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9314 define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9315 define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9316 define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9317 define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9318 define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9319
9320 #undef define_sfop3
9321 #undef define_sfop4
9322
9323 template <typename T, typename SpecialFunction>
9324 class sf3_node : public trinary_node<T>
9325 {
9326 public:
9327
9328 typedef expression_node<T>* expression_ptr;
9329
9330 sf3_node(const operator_type& opr,
9331 expression_ptr branch0,
9332 expression_ptr branch1,
9333 expression_ptr branch2)
9334 : trinary_node<T>(opr, branch0, branch1, branch2)
9335 {}
9336
9337 inline T value() const
9338 {
9339 const T x = trinary_node<T>::branch_[0].first->value();
9340 const T y = trinary_node<T>::branch_[1].first->value();
9341 const T z = trinary_node<T>::branch_[2].first->value();
9342
9343 return SpecialFunction::process(x, y, z);
9344 }
9345 };
9346
9347 template <typename T, typename SpecialFunction>
9348 class sf4_node : public quaternary_node<T>
9349 {
9350 public:
9351
9352 typedef expression_node<T>* expression_ptr;
9353
9354 sf4_node(const operator_type& opr,
9355 expression_ptr branch0,
9356 expression_ptr branch1,
9357 expression_ptr branch2,
9358 expression_ptr branch3)
9359 : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9360 {}
9361
9362 inline T value() const
9363 {
9364 const T x = quaternary_node<T>::branch_[0].first->value();
9365 const T y = quaternary_node<T>::branch_[1].first->value();
9366 const T z = quaternary_node<T>::branch_[2].first->value();
9367 const T w = quaternary_node<T>::branch_[3].first->value();
9368
9369 return SpecialFunction::process(x, y, z, w);
9370 }
9371 };
9372
9373 template <typename T, typename SpecialFunction>
9374 class sf3_var_node : public expression_node<T>
9375 {
9376 public:
9377
9378 typedef expression_node<T>* expression_ptr;
9379
9380 sf3_var_node(const T& v0, const T& v1, const T& v2)
9381 : v0_(v0),
9382 v1_(v1),
9383 v2_(v2)
9384 {}
9385
9386 inline T value() const
9387 {
9388 return SpecialFunction::process(v0_, v1_, v2_);
9389 }
9390
9391 inline typename expression_node<T>::node_type type() const
9392 {
9393 return expression_node<T>::e_trinary;
9394 }
9395
9396 private:
9397
9398 sf3_var_node(sf3_var_node<T,SpecialFunction>&);
9399 sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
9400
9401 const T& v0_;
9402 const T& v1_;
9403 const T& v2_;
9404 };
9405
9406 template <typename T, typename SpecialFunction>
9407 class sf4_var_node : public expression_node<T>
9408 {
9409 public:
9410
9411 typedef expression_node<T>* expression_ptr;
9412
9413 sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9414 : v0_(v0),
9415 v1_(v1),
9416 v2_(v2),
9417 v3_(v3)
9418 {}
9419
9420 inline T value() const
9421 {
9422 return SpecialFunction::process(v0_, v1_, v2_, v3_);
9423 }
9424
9425 inline typename expression_node<T>::node_type type() const
9426 {
9427 return expression_node<T>::e_trinary;
9428 }
9429
9430 private:
9431
9432 sf4_var_node(sf4_var_node<T,SpecialFunction>&);
9433 sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
9434
9435 const T& v0_;
9436 const T& v1_;
9437 const T& v2_;
9438 const T& v3_;
9439 };
9440
9441 template <typename T, typename VarArgFunction>
9442 class vararg_node : public expression_node<T>
9443 {
9444 public:
9445
9446 typedef expression_node<T>* expression_ptr;
9447
9448 template <typename Allocator,
9449 template <typename, typename> class Sequence>
9450 explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9451 {
9452 arg_list_ .resize(arg_list.size());
9453 delete_branch_.resize(arg_list.size());
9454
9455 for (std::size_t i = 0; i < arg_list.size(); ++i)
9456 {
9457 if (arg_list[i])
9458 {
9459 arg_list_[i] = arg_list[i];
9460 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9461 }
9462 else
9463 {
9464 arg_list_.clear();
9465 delete_branch_.clear();
9466 return;
9467 }
9468 }
9469 }
9470
9471 ~vararg_node()
9472 {
9473 for (std::size_t i = 0; i < arg_list_.size(); ++i)
9474 {
9475 if (arg_list_[i] && delete_branch_[i])
9476 {
9477 destroy_node(arg_list_[i]);
9478 }
9479 }
9480 }
9481
9482 inline T value() const
9483 {
9484 return VarArgFunction::process(arg_list_);
9485 }
9486
9487 inline typename expression_node<T>::node_type type() const
9488 {
9489 return expression_node<T>::e_vararg;
9490 }
9491
9492 private:
9493
9494 std::vector<expression_ptr> arg_list_;
9495 std::vector<unsigned char> delete_branch_;
9496 };
9497
9498 template <typename T, typename VarArgFunction>
9499 class vararg_varnode : public expression_node<T>
9500 {
9501 public:
9502
9503 typedef expression_node<T>* expression_ptr;
9504
9505 template <typename Allocator,
9506 template <typename, typename> class Sequence>
9507 explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
9508 {
9509 arg_list_.resize(arg_list.size());
9510
9511 for (std::size_t i = 0; i < arg_list.size(); ++i)
9512 {
9513 if (arg_list[i] && is_variable_node(arg_list[i]))
9514 {
9515 variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
9516 arg_list_[i] = (&var_node_ptr->ref());
9517 }
9518 else
9519 {
9520 arg_list_.clear();
9521 return;
9522 }
9523 }
9524 }
9525
9526 inline T value() const
9527 {
9528 if (!arg_list_.empty())
9529 return VarArgFunction::process(arg_list_);
9530 else
9531 return std::numeric_limits<T>::quiet_NaN();
9532 }
9533
9534 inline typename expression_node<T>::node_type type() const
9535 {
9536 return expression_node<T>::e_vararg;
9537 }
9538
9539 private:
9540
9541 std::vector<const T*> arg_list_;
9542 };
9543
9544 template <typename T, typename VecFunction>
9545 class vectorize_node : public expression_node<T>
9546 {
9547 public:
9548
9549 typedef expression_node<T>* expression_ptr;
9550
9551 explicit vectorize_node(const expression_ptr v)
9552 : ivec_ptr_(0),
9553 v_(v),
9554 v_deletable_(branch_deletable(v_))
9555 {
9556 if (is_ivector_node(v))
9557 {
9558 ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
9559 }
9560 else
9561 ivec_ptr_ = 0;
9562 }
9563
9564 ~vectorize_node()
9565 {
9566 if (v_ && v_deletable_)
9567 {
9568 destroy_node(v_);
9569 }
9570 }
9571
9572 inline T value() const
9573 {
9574 if (ivec_ptr_)
9575 {
9576 v_->value();
9577 return VecFunction::process(ivec_ptr_);
9578 }
9579 else
9580 return std::numeric_limits<T>::quiet_NaN();
9581 }
9582
9583 inline typename expression_node<T>::node_type type() const
9584 {
9585 return expression_node<T>::e_vecfunc;
9586 }
9587
9588 private:
9589
9590 vector_interface<T>* ivec_ptr_;
9591 expression_ptr v_;
9592 const bool v_deletable_;
9593 };
9594
9595 template <typename T>
9596 class assignment_node : public binary_node<T>
9597 {
9598 public:
9599
9600 typedef expression_node<T>* expression_ptr;
9601
9602 assignment_node(const operator_type& opr,
9603 expression_ptr branch0,
9604 expression_ptr branch1)
9605 : binary_node<T>(opr, branch0, branch1),
9606 var_node_ptr_(0)
9607 {
9608 if (is_variable_node(binary_node<T>::branch_[0].first))
9609 {
9610 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
9611 }
9612 }
9613
9614 inline T value() const
9615 {
9616 if (var_node_ptr_)
9617 {
9618 T& result = var_node_ptr_->ref();
9619
9620 result = binary_node<T>::branch_[1].first->value();
9621
9622 return result;
9623 }
9624 else
9625 return std::numeric_limits<T>::quiet_NaN();
9626 }
9627
9628 private:
9629
9630 variable_node<T>* var_node_ptr_;
9631 };
9632
9633 template <typename T>
9634 class assignment_vec_elem_node : public binary_node<T>
9635 {
9636 public:
9637
9638 typedef expression_node<T>* expression_ptr;
9639
9640 assignment_vec_elem_node(const operator_type& opr,
9641 expression_ptr branch0,
9642 expression_ptr branch1)
9643 : binary_node<T>(opr, branch0, branch1),
9644 vec_node_ptr_(0)
9645 {
9646 if (is_vector_elem_node(binary_node<T>::branch_[0].first))
9647 {
9648 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9649 }
9650 }
9651
9652 inline T value() const
9653 {
9654 if (vec_node_ptr_)
9655 {
9656 T& result = vec_node_ptr_->ref();
9657
9658 result = binary_node<T>::branch_[1].first->value();
9659
9660 return result;
9661 }
9662 else
9663 return std::numeric_limits<T>::quiet_NaN();
9664 }
9665
9666 private:
9667
9668 vector_elem_node<T>* vec_node_ptr_;
9669 };
9670
9671 template <typename T>
9672 class assignment_rebasevec_elem_node : public binary_node<T>
9673 {
9674 public:
9675
9676 typedef expression_node<T>* expression_ptr;
9677
9678 assignment_rebasevec_elem_node(const operator_type& opr,
9679 expression_ptr branch0,
9680 expression_ptr branch1)
9681 : binary_node<T>(opr, branch0, branch1),
9682 rbvec_node_ptr_(0)
9683 {
9684 if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
9685 {
9686 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9687 }
9688 }
9689
9690 inline T value() const
9691 {
9692 if (rbvec_node_ptr_)
9693 {
9694 T& result = rbvec_node_ptr_->ref();
9695
9696 result = binary_node<T>::branch_[1].first->value();
9697
9698 return result;
9699 }
9700 else
9701 return std::numeric_limits<T>::quiet_NaN();
9702 }
9703
9704 private:
9705
9706 rebasevector_elem_node<T>* rbvec_node_ptr_;
9707 };
9708
9709 template <typename T>
9710 class assignment_rebasevec_celem_node : public binary_node<T>
9711 {
9712 public:
9713
9714 typedef expression_node<T>* expression_ptr;
9715
9716 assignment_rebasevec_celem_node(const operator_type& opr,
9717 expression_ptr branch0,
9718 expression_ptr branch1)
9719 : binary_node<T>(opr, branch0, branch1),
9720 rbvec_node_ptr_(0)
9721 {
9722 if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
9723 {
9724 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
9725 }
9726 }
9727
9728 inline T value() const
9729 {
9730 if (rbvec_node_ptr_)
9731 {
9732 T& result = rbvec_node_ptr_->ref();
9733
9734 result = binary_node<T>::branch_[1].first->value();
9735
9736 return result;
9737 }
9738 else
9739 return std::numeric_limits<T>::quiet_NaN();
9740 }
9741
9742 private:
9743
9744 rebasevector_celem_node<T>* rbvec_node_ptr_;
9745 };
9746
9747 template <typename T>
9748 class assignment_vec_node : public binary_node <T>,
9749 public vector_interface<T>
9750 {
9751 public:
9752
9753 typedef expression_node<T>* expression_ptr;
9754 typedef vector_node<T>* vector_node_ptr;
9755 typedef vec_data_store<T> vds_t;
9756
9757 assignment_vec_node(const operator_type& opr,
9758 expression_ptr branch0,
9759 expression_ptr branch1)
9760 : binary_node<T>(opr, branch0, branch1),
9761 vec_node_ptr_(0)
9762 {
9763 if (is_vector_node(binary_node<T>::branch_[0].first))
9764 {
9765 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9766 vds() = vec_node_ptr_->vds();
9767 }
9768 }
9769
9770 inline T value() const
9771 {
9772 if (vec_node_ptr_)
9773 {
9774 const T v = binary_node<T>::branch_[1].first->value();
9775
9776 T* vec = vds().data();
9777
9778 loop_unroll::details lud(size());
9779 const T* upper_bound = vec + lud.upper_bound;
9780
9781 while (vec < upper_bound)
9782 {
9783 #define exprtk_loop(N) \
9784 vec[N] = v; \
9785
9786 exprtk_loop( 0) exprtk_loop( 1)
9787 exprtk_loop( 2) exprtk_loop( 3)
9788 #ifndef exprtk_disable_superscalar_unroll
9789 exprtk_loop( 4) exprtk_loop( 5)
9790 exprtk_loop( 6) exprtk_loop( 7)
9791 exprtk_loop( 8) exprtk_loop( 9)
9792 exprtk_loop(10) exprtk_loop(11)
9793 exprtk_loop(12) exprtk_loop(13)
9794 exprtk_loop(14) exprtk_loop(15)
9795 #endif
9796
9797 vec += lud.batch_size;
9798 }
9799
9800 exprtk_disable_fallthrough_begin
9801 switch (lud.remainder)
9802 {
9803 #define case_stmt(N) \
9804 case N : *vec++ = v; \
9805
9806 #ifndef exprtk_disable_superscalar_unroll
9807 case_stmt(15) case_stmt(14)
9808 case_stmt(13) case_stmt(12)
9809 case_stmt(11) case_stmt(10)
9810 case_stmt( 9) case_stmt( 8)
9811 case_stmt( 7) case_stmt( 6)
9812 case_stmt( 5) case_stmt( 4)
9813 #endif
9814 case_stmt( 3) case_stmt( 2)
9815 case_stmt( 1)
9816 }
9817 exprtk_disable_fallthrough_end
9818
9819 #undef exprtk_loop
9820 #undef case_stmt
9821
9822 return vec_node_ptr_->value();
9823 }
9824 else
9825 return std::numeric_limits<T>::quiet_NaN();
9826 }
9827
9828 vector_node_ptr vec() const
9829 {
9830 return vec_node_ptr_;
9831 }
9832
9833 vector_node_ptr vec()
9834 {
9835 return vec_node_ptr_;
9836 }
9837
9838 inline typename expression_node<T>::node_type type() const
9839 {
9840 return expression_node<T>::e_vecvalass;
9841 }
9842
9843 std::size_t size() const
9844 {
9845 return vds().size();
9846 }
9847
9848 vds_t& vds()
9849 {
9850 return vds_;
9851 }
9852
9853 const vds_t& vds() const
9854 {
9855 return vds_;
9856 }
9857
9858 private:
9859
9860 vector_node<T>* vec_node_ptr_;
9861 vds_t vds_;
9862 };
9863
9864 template <typename T>
9865 class assignment_vecvec_node : public binary_node <T>,
9866 public vector_interface<T>
9867 {
9868 public:
9869
9870 typedef expression_node<T>* expression_ptr;
9871 typedef vector_node<T>* vector_node_ptr;
9872 typedef vec_data_store<T> vds_t;
9873
9874 assignment_vecvec_node(const operator_type& opr,
9875 expression_ptr branch0,
9876 expression_ptr branch1)
9877 : binary_node<T>(opr, branch0, branch1),
9878 vec0_node_ptr_(0),
9879 vec1_node_ptr_(0),
9880 initialised_(false),
9881 src_is_ivec_(false)
9882 {
9883 if (is_vector_node(binary_node<T>::branch_[0].first))
9884 {
9885 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9886 vds() = vec0_node_ptr_->vds();
9887 }
9888
9889 if (is_vector_node(binary_node<T>::branch_[1].first))
9890 {
9891 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
9892 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
9893 }
9894 else if (is_ivector_node(binary_node<T>::branch_[1].first))
9895 {
9896 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9897
9898 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
9899 {
9900 vec1_node_ptr_ = vi->vec();
9901
9902 if (!vi->side_effect())
9903 {
9904 vi->vds() = vds();
9905 src_is_ivec_ = true;
9906 }
9907 else
9908 vds_t::match_sizes(vds(),vi->vds());
9909 }
9910 }
9911
9912 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
9913 }
9914
9915 inline T value() const
9916 {
9917 if (initialised_)
9918 {
9919 binary_node<T>::branch_[1].first->value();
9920
9921 if (src_is_ivec_)
9922 return vec0_node_ptr_->value();
9923
9924 T* vec0 = vec0_node_ptr_->vds().data();
9925 T* vec1 = vec1_node_ptr_->vds().data();
9926
9927 loop_unroll::details lud(size());
9928 const T* upper_bound = vec0 + lud.upper_bound;
9929
9930 while (vec0 < upper_bound)
9931 {
9932 #define exprtk_loop(N) \
9933 vec0[N] = vec1[N]; \
9934
9935 exprtk_loop( 0) exprtk_loop( 1)
9936 exprtk_loop( 2) exprtk_loop( 3)
9937 #ifndef exprtk_disable_superscalar_unroll
9938 exprtk_loop( 4) exprtk_loop( 5)
9939 exprtk_loop( 6) exprtk_loop( 7)
9940 exprtk_loop( 8) exprtk_loop( 9)
9941 exprtk_loop(10) exprtk_loop(11)
9942 exprtk_loop(12) exprtk_loop(13)
9943 exprtk_loop(14) exprtk_loop(15)
9944 #endif
9945
9946 vec0 += lud.batch_size;
9947 vec1 += lud.batch_size;
9948 }
9949
9950 exprtk_disable_fallthrough_begin
9951 switch (lud.remainder)
9952 {
9953 #define case_stmt(N) \
9954 case N : *vec0++ = *vec1++; \
9955
9956 #ifndef exprtk_disable_superscalar_unroll
9957 case_stmt(15) case_stmt(14)
9958 case_stmt(13) case_stmt(12)
9959 case_stmt(11) case_stmt(10)
9960 case_stmt( 9) case_stmt( 8)
9961 case_stmt( 7) case_stmt( 6)
9962 case_stmt( 5) case_stmt( 4)
9963 #endif
9964 case_stmt( 3) case_stmt( 2)
9965 case_stmt( 1)
9966 }
9967 exprtk_disable_fallthrough_end
9968
9969 #undef exprtk_loop
9970 #undef case_stmt
9971
9972 return vec0_node_ptr_->value();
9973 }
9974 else
9975 return std::numeric_limits<T>::quiet_NaN();
9976 }
9977
9978 vector_node_ptr vec() const
9979 {
9980 return vec0_node_ptr_;
9981 }
9982
9983 vector_node_ptr vec()
9984 {
9985 return vec0_node_ptr_;
9986 }
9987
9988 inline typename expression_node<T>::node_type type() const
9989 {
9990 return expression_node<T>::e_vecvecass;
9991 }
9992
9993 std::size_t size() const
9994 {
9995 return vds().size();
9996 }
9997
9998 vds_t& vds()
9999 {
10000 return vds_;
10001 }
10002
10003 const vds_t& vds() const
10004 {
10005 return vds_;
10006 }
10007
10008 private:
10009
10010 vector_node<T>* vec0_node_ptr_;
10011 vector_node<T>* vec1_node_ptr_;
10012 bool initialised_;
10013 bool src_is_ivec_;
10014 vds_t vds_;
10015 };
10016
10017 template <typename T, typename Operation>
10018 class assignment_op_node : public binary_node<T>
10019 {
10020 public:
10021
10022 typedef expression_node<T>* expression_ptr;
10023
10024 assignment_op_node(const operator_type& opr,
10025 expression_ptr branch0,
10026 expression_ptr branch1)
10027 : binary_node<T>(opr, branch0, branch1),
10028 var_node_ptr_(0)
10029 {
10030 if (is_variable_node(binary_node<T>::branch_[0].first))
10031 {
10032 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10033 }
10034 }
10035
10036 inline T value() const
10037 {
10038 if (var_node_ptr_)
10039 {
10040 T& v = var_node_ptr_->ref();
10041 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10042
10043 return v;
10044 }
10045 else
10046 return std::numeric_limits<T>::quiet_NaN();
10047 }
10048
10049 private:
10050
10051 variable_node<T>* var_node_ptr_;
10052 };
10053
10054 template <typename T, typename Operation>
10055 class assignment_vec_elem_op_node : public binary_node<T>
10056 {
10057 public:
10058
10059 typedef expression_node<T>* expression_ptr;
10060
10061 assignment_vec_elem_op_node(const operator_type& opr,
10062 expression_ptr branch0,
10063 expression_ptr branch1)
10064 : binary_node<T>(opr, branch0, branch1),
10065 vec_node_ptr_(0)
10066 {
10067 if (is_vector_elem_node(binary_node<T>::branch_[0].first))
10068 {
10069 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10070 }
10071 }
10072
10073 inline T value() const
10074 {
10075 if (vec_node_ptr_)
10076 {
10077 T& v = vec_node_ptr_->ref();
10078 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10079
10080 return v;
10081 }
10082 else
10083 return std::numeric_limits<T>::quiet_NaN();
10084 }
10085
10086 private:
10087
10088 vector_elem_node<T>* vec_node_ptr_;
10089 };
10090
10091 template <typename T, typename Operation>
10092 class assignment_rebasevec_elem_op_node : public binary_node<T>
10093 {
10094 public:
10095
10096 typedef expression_node<T>* expression_ptr;
10097
10098 assignment_rebasevec_elem_op_node(const operator_type& opr,
10099 expression_ptr branch0,
10100 expression_ptr branch1)
10101 : binary_node<T>(opr, branch0, branch1),
10102 rbvec_node_ptr_(0)
10103 {
10104 if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
10105 {
10106 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10107 }
10108 }
10109
10110 inline T value() const
10111 {
10112 if (rbvec_node_ptr_)
10113 {
10114 T& v = rbvec_node_ptr_->ref();
10115 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10116
10117 return v;
10118 }
10119 else
10120 return std::numeric_limits<T>::quiet_NaN();
10121 }
10122
10123 private:
10124
10125 rebasevector_elem_node<T>* rbvec_node_ptr_;
10126 };
10127
10128 template <typename T, typename Operation>
10129 class assignment_rebasevec_celem_op_node : public binary_node<T>
10130 {
10131 public:
10132
10133 typedef expression_node<T>* expression_ptr;
10134
10135 assignment_rebasevec_celem_op_node(const operator_type& opr,
10136 expression_ptr branch0,
10137 expression_ptr branch1)
10138 : binary_node<T>(opr, branch0, branch1),
10139 rbvec_node_ptr_(0)
10140 {
10141 if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
10142 {
10143 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10144 }
10145 }
10146
10147 inline T value() const
10148 {
10149 if (rbvec_node_ptr_)
10150 {
10151 T& v = rbvec_node_ptr_->ref();
10152 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10153
10154 return v;
10155 }
10156 else
10157 return std::numeric_limits<T>::quiet_NaN();
10158 }
10159
10160 private:
10161
10162 rebasevector_celem_node<T>* rbvec_node_ptr_;
10163 };
10164
10165 template <typename T, typename Operation>
10166 class assignment_vec_op_node : public binary_node <T>,
10167 public vector_interface<T>
10168 {
10169 public:
10170
10171 typedef expression_node<T>* expression_ptr;
10172 typedef vector_node<T>* vector_node_ptr;
10173 typedef vec_data_store<T> vds_t;
10174
10175 assignment_vec_op_node(const operator_type& opr,
10176 expression_ptr branch0,
10177 expression_ptr branch1)
10178 : binary_node<T>(opr, branch0, branch1),
10179 vec_node_ptr_(0)
10180 {
10181 if (is_vector_node(binary_node<T>::branch_[0].first))
10182 {
10183 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10184 vds() = vec_node_ptr_->vds();
10185 }
10186 }
10187
10188 inline T value() const
10189 {
10190 if (vec_node_ptr_)
10191 {
10192 const T v = binary_node<T>::branch_[1].first->value();
10193
10194 T* vec = vds().data();
10195
10196 loop_unroll::details lud(size());
10197 const T* upper_bound = vec + lud.upper_bound;
10198
10199 while (vec < upper_bound)
10200 {
10201 #define exprtk_loop(N) \
10202 Operation::assign(vec[N],v); \
10203
10204 exprtk_loop( 0) exprtk_loop( 1)
10205 exprtk_loop( 2) exprtk_loop( 3)
10206 #ifndef exprtk_disable_superscalar_unroll
10207 exprtk_loop( 4) exprtk_loop( 5)
10208 exprtk_loop( 6) exprtk_loop( 7)
10209 exprtk_loop( 8) exprtk_loop( 9)
10210 exprtk_loop(10) exprtk_loop(11)
10211 exprtk_loop(12) exprtk_loop(13)
10212 exprtk_loop(14) exprtk_loop(15)
10213 #endif
10214
10215 vec += lud.batch_size;
10216 }
10217
10218 exprtk_disable_fallthrough_begin
10219 switch (lud.remainder)
10220 {
10221 #define case_stmt(N) \
10222 case N : Operation::assign(*vec++,v); \
10223
10224 #ifndef exprtk_disable_superscalar_unroll
10225 case_stmt(15) case_stmt(14)
10226 case_stmt(13) case_stmt(12)
10227 case_stmt(11) case_stmt(10)
10228 case_stmt( 9) case_stmt( 8)
10229 case_stmt( 7) case_stmt( 6)
10230 case_stmt( 5) case_stmt( 4)
10231 #endif
10232 case_stmt( 3) case_stmt( 2)
10233 case_stmt( 1)
10234 }
10235 exprtk_disable_fallthrough_end
10236
10237
10238 #undef exprtk_loop
10239 #undef case_stmt
10240
10241 return vec_node_ptr_->value();
10242 }
10243 else
10244 return std::numeric_limits<T>::quiet_NaN();
10245 }
10246
10247 vector_node_ptr vec() const
10248 {
10249 return vec_node_ptr_;
10250 }
10251
10252 vector_node_ptr vec()
10253 {
10254 return vec_node_ptr_;
10255 }
10256
10257 inline typename expression_node<T>::node_type type() const
10258 {
10259 return expression_node<T>::e_vecopvalass;
10260 }
10261
10262 std::size_t size() const
10263 {
10264 return vds().size();
10265 }
10266
10267 vds_t& vds()
10268 {
10269 return vds_;
10270 }
10271
10272 const vds_t& vds() const
10273 {
10274 return vds_;
10275 }
10276
10277 bool side_effect() const
10278 {
10279 return true;
10280 }
10281
10282 private:
10283
10284 vector_node<T>* vec_node_ptr_;
10285 vds_t vds_;
10286 };
10287
10288 template <typename T, typename Operation>
10289 class assignment_vecvec_op_node : public binary_node <T>,
10290 public vector_interface<T>
10291 {
10292 public:
10293
10294 typedef expression_node<T>* expression_ptr;
10295 typedef vector_node<T>* vector_node_ptr;
10296 typedef vec_data_store<T> vds_t;
10297
10298 assignment_vecvec_op_node(const operator_type& opr,
10299 expression_ptr branch0,
10300 expression_ptr branch1)
10301 : binary_node<T>(opr, branch0, branch1),
10302 vec0_node_ptr_(0),
10303 vec1_node_ptr_(0),
10304 initialised_(false)
10305 {
10306 if (is_vector_node(binary_node<T>::branch_[0].first))
10307 {
10308 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10309 vds() = vec0_node_ptr_->vds();
10310 }
10311
10312 if (is_vector_node(binary_node<T>::branch_[1].first))
10313 {
10314 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10315 vec1_node_ptr_->vds() = vds();
10316 }
10317 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10318 {
10319 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10320
10321 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10322 {
10323 vec1_node_ptr_ = vi->vec();
10324 vec1_node_ptr_->vds() = vds();
10325 }
10326 else
10327 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10328 }
10329
10330 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10331 }
10332
10333 inline T value() const
10334 {
10335 if (initialised_)
10336 {
10337 binary_node<T>::branch_[0].first->value();
10338 binary_node<T>::branch_[1].first->value();
10339
10340 T* vec0 = vec0_node_ptr_->vds().data();
10341 const T* vec1 = vec1_node_ptr_->vds().data();
10342
10343 loop_unroll::details lud(size());
10344 const T* upper_bound = vec0 + lud.upper_bound;
10345
10346 while (vec0 < upper_bound)
10347 {
10348 #define exprtk_loop(N) \
10349 vec0[N] = Operation::process(vec0[N], vec1[N]); \
10350
10351 exprtk_loop( 0) exprtk_loop( 1)
10352 exprtk_loop( 2) exprtk_loop( 3)
10353 #ifndef exprtk_disable_superscalar_unroll
10354 exprtk_loop( 4) exprtk_loop( 5)
10355 exprtk_loop( 6) exprtk_loop( 7)
10356 exprtk_loop( 8) exprtk_loop( 9)
10357 exprtk_loop(10) exprtk_loop(11)
10358 exprtk_loop(12) exprtk_loop(13)
10359 exprtk_loop(14) exprtk_loop(15)
10360 #endif
10361
10362 vec0 += lud.batch_size;
10363 vec1 += lud.batch_size;
10364 }
10365
10366 int i = 0;
10367
10368 exprtk_disable_fallthrough_begin
10369 switch (lud.remainder)
10370 {
10371 #define case_stmt(N) \
10372 case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10373
10374 #ifndef exprtk_disable_superscalar_unroll
10375 case_stmt(15) case_stmt(14)
10376 case_stmt(13) case_stmt(12)
10377 case_stmt(11) case_stmt(10)
10378 case_stmt( 9) case_stmt( 8)
10379 case_stmt( 7) case_stmt( 6)
10380 case_stmt( 5) case_stmt( 4)
10381 #endif
10382 case_stmt( 3) case_stmt( 2)
10383 case_stmt( 1)
10384 }
10385 exprtk_disable_fallthrough_end
10386
10387 #undef exprtk_loop
10388 #undef case_stmt
10389
10390 return vec0_node_ptr_->value();
10391 }
10392 else
10393 return std::numeric_limits<T>::quiet_NaN();
10394 }
10395
10396 vector_node_ptr vec() const
10397 {
10398 return vec0_node_ptr_;
10399 }
10400
10401 vector_node_ptr vec()
10402 {
10403 return vec0_node_ptr_;
10404 }
10405
10406 inline typename expression_node<T>::node_type type() const
10407 {
10408 return expression_node<T>::e_vecopvecass;
10409 }
10410
10411 std::size_t size() const
10412 {
10413 return vds().size();
10414 }
10415
10416 vds_t& vds()
10417 {
10418 return vds_;
10419 }
10420
10421 const vds_t& vds() const
10422 {
10423 return vds_;
10424 }
10425
10426 bool side_effect() const
10427 {
10428 return true;
10429 }
10430
10431 private:
10432
10433 vector_node<T>* vec0_node_ptr_;
10434 vector_node<T>* vec1_node_ptr_;
10435 bool initialised_;
10436 vds_t vds_;
10437 };
10438
10439 template <typename T, typename Operation>
10440 class vec_binop_vecvec_node : public binary_node <T>,
10441 public vector_interface<T>
10442 {
10443 public:
10444
10445 typedef expression_node<T>* expression_ptr;
10446 typedef vector_node<T>* vector_node_ptr;
10447 typedef vector_holder<T>* vector_holder_ptr;
10448 typedef vec_data_store<T> vds_t;
10449
10450 vec_binop_vecvec_node(const operator_type& opr,
10451 expression_ptr branch0,
10452 expression_ptr branch1)
10453 : binary_node<T>(opr, branch0, branch1),
10454 vec0_node_ptr_(0),
10455 vec1_node_ptr_(0),
10456 temp_ (0),
10457 temp_vec_node_(0),
10458 initialised_(false)
10459 {
10460 bool v0_is_ivec = false;
10461 bool v1_is_ivec = false;
10462
10463 if (is_vector_node(binary_node<T>::branch_[0].first))
10464 {
10465 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10466 }
10467 else if (is_ivector_node(binary_node<T>::branch_[0].first))
10468 {
10469 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10470
10471 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10472 {
10473 vec0_node_ptr_ = vi->vec();
10474 v0_is_ivec = true;
10475 }
10476 }
10477
10478 if (is_vector_node(binary_node<T>::branch_[1].first))
10479 {
10480 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10481 }
10482 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10483 {
10484 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10485
10486 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10487 {
10488 vec1_node_ptr_ = vi->vec();
10489 v1_is_ivec = true;
10490 }
10491 }
10492
10493 if (vec0_node_ptr_ && vec1_node_ptr_)
10494 {
10495 vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
10496 vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
10497
10498 if (v0_is_ivec && (vec0.size() <= vec1.size()))
10499 vds_ = vds_t(vec0_node_ptr_->vds());
10500 else if (v1_is_ivec && (vec1.size() <= vec0.size()))
10501 vds_ = vds_t(vec1_node_ptr_->vds());
10502 else
10503 vds_ = vds_t(std::min(vec0.size(),vec1.size()));
10504
10505 temp_ = new vector_holder<T>(vds().data(),vds().size());
10506 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10507
10508 initialised_ = true;
10509 }
10510 }
10511
10512 ~vec_binop_vecvec_node()
10513 {
10514 delete temp_;
10515 delete temp_vec_node_;
10516 }
10517
10518 inline T value() const
10519 {
10520 if (initialised_)
10521 {
10522 binary_node<T>::branch_[0].first->value();
10523 binary_node<T>::branch_[1].first->value();
10524
10525 const T* vec0 = vec0_node_ptr_->vds().data();
10526 const T* vec1 = vec1_node_ptr_->vds().data();
10527 T* vec2 = vds().data();
10528
10529 loop_unroll::details lud(size());
10530 const T* upper_bound = vec2 + lud.upper_bound;
10531
10532 while (vec2 < upper_bound)
10533 {
10534 #define exprtk_loop(N) \
10535 vec2[N] = Operation::process(vec0[N], vec1[N]); \
10536
10537 exprtk_loop( 0) exprtk_loop( 1)
10538 exprtk_loop( 2) exprtk_loop( 3)
10539 #ifndef exprtk_disable_superscalar_unroll
10540 exprtk_loop( 4) exprtk_loop( 5)
10541 exprtk_loop( 6) exprtk_loop( 7)
10542 exprtk_loop( 8) exprtk_loop( 9)
10543 exprtk_loop(10) exprtk_loop(11)
10544 exprtk_loop(12) exprtk_loop(13)
10545 exprtk_loop(14) exprtk_loop(15)
10546 #endif
10547
10548 vec0 += lud.batch_size;
10549 vec1 += lud.batch_size;
10550 vec2 += lud.batch_size;
10551 }
10552
10553 int i = 0;
10554
10555 exprtk_disable_fallthrough_begin
10556 switch (lud.remainder)
10557 {
10558 #define case_stmt(N) \
10559 case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10560
10561 #ifndef exprtk_disable_superscalar_unroll
10562 case_stmt(15) case_stmt(14)
10563 case_stmt(13) case_stmt(12)
10564 case_stmt(11) case_stmt(10)
10565 case_stmt( 9) case_stmt( 8)
10566 case_stmt( 7) case_stmt( 6)
10567 case_stmt( 5) case_stmt( 4)
10568 #endif
10569 case_stmt( 3) case_stmt( 2)
10570 case_stmt( 1)
10571 }
10572 exprtk_disable_fallthrough_end
10573
10574 #undef exprtk_loop
10575 #undef case_stmt
10576
10577 return (vds().data())[0];
10578 }
10579 else
10580 return std::numeric_limits<T>::quiet_NaN();
10581 }
10582
10583 vector_node_ptr vec() const
10584 {
10585 return temp_vec_node_;
10586 }
10587
10588 vector_node_ptr vec()
10589 {
10590 return temp_vec_node_;
10591 }
10592
10593 inline typename expression_node<T>::node_type type() const
10594 {
10595 return expression_node<T>::e_vecvecarith;
10596 }
10597
10598 std::size_t size() const
10599 {
10600 return vds_.size();
10601 }
10602
10603 vds_t& vds()
10604 {
10605 return vds_;
10606 }
10607
10608 const vds_t& vds() const
10609 {
10610 return vds_;
10611 }
10612
10613 private:
10614
10615 vector_node_ptr vec0_node_ptr_;
10616 vector_node_ptr vec1_node_ptr_;
10617 vector_holder_ptr temp_;
10618 vector_node_ptr temp_vec_node_;
10619 bool initialised_;
10620 vds_t vds_;
10621 };
10622
10623 template <typename T, typename Operation>
10624 class vec_binop_vecval_node : public binary_node <T>,
10625 public vector_interface<T>
10626 {
10627 public:
10628
10629 typedef expression_node<T>* expression_ptr;
10630 typedef vector_node<T>* vector_node_ptr;
10631 typedef vector_holder<T>* vector_holder_ptr;
10632 typedef vec_data_store<T> vds_t;
10633
10634 vec_binop_vecval_node(const operator_type& opr,
10635 expression_ptr branch0,
10636 expression_ptr branch1)
10637 : binary_node<T>(opr, branch0, branch1),
10638 vec0_node_ptr_(0),
10639 temp_ (0),
10640 temp_vec_node_(0)
10641 {
10642 bool v0_is_ivec = false;
10643
10644 if (is_vector_node(binary_node<T>::branch_[0].first))
10645 {
10646 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10647 }
10648 else if (is_ivector_node(binary_node<T>::branch_[0].first))
10649 {
10650 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10651
10652 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10653 {
10654 vec0_node_ptr_ = vi->vec();
10655 v0_is_ivec = true;
10656 }
10657 }
10658
10659 if (vec0_node_ptr_)
10660 {
10661 if (v0_is_ivec)
10662 vds() = vec0_node_ptr_->vds();
10663 else
10664 vds() = vds_t(vec0_node_ptr_->size());
10665
10666 temp_ = new vector_holder<T>(vds());
10667 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10668 }
10669 }
10670
10671 ~vec_binop_vecval_node()
10672 {
10673 delete temp_;
10674 delete temp_vec_node_;
10675 }
10676
10677 inline T value() const
10678 {
10679 if (vec0_node_ptr_)
10680 {
10681 binary_node<T>::branch_[0].first->value();
10682 const T v = binary_node<T>::branch_[1].first->value();
10683
10684 const T* vec0 = vec0_node_ptr_->vds().data();
10685 T* vec1 = vds().data();
10686
10687 loop_unroll::details lud(size());
10688 const T* upper_bound = vec0 + lud.upper_bound;
10689
10690 while (vec0 < upper_bound)
10691 {
10692 #define exprtk_loop(N) \
10693 vec1[N] = Operation::process(vec0[N], v); \
10694
10695 exprtk_loop( 0) exprtk_loop( 1)
10696 exprtk_loop( 2) exprtk_loop( 3)
10697 #ifndef exprtk_disable_superscalar_unroll
10698 exprtk_loop( 4) exprtk_loop( 5)
10699 exprtk_loop( 6) exprtk_loop( 7)
10700 exprtk_loop( 8) exprtk_loop( 9)
10701 exprtk_loop(10) exprtk_loop(11)
10702 exprtk_loop(12) exprtk_loop(13)
10703 exprtk_loop(14) exprtk_loop(15)
10704 #endif
10705
10706 vec0 += lud.batch_size;
10707 vec1 += lud.batch_size;
10708 }
10709
10710 int i = 0;
10711
10712 exprtk_disable_fallthrough_begin
10713 switch (lud.remainder)
10714 {
10715 #define case_stmt(N) \
10716 case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
10717
10718 #ifndef exprtk_disable_superscalar_unroll
10719 case_stmt(15) case_stmt(14)
10720 case_stmt(13) case_stmt(12)
10721 case_stmt(11) case_stmt(10)
10722 case_stmt( 9) case_stmt( 8)
10723 case_stmt( 7) case_stmt( 6)
10724 case_stmt( 5) case_stmt( 4)
10725 #endif
10726 case_stmt( 3) case_stmt( 2)
10727 case_stmt( 1)
10728 }
10729 exprtk_disable_fallthrough_end
10730
10731 #undef exprtk_loop
10732 #undef case_stmt
10733
10734 return (vds().data())[0];
10735 }
10736 else
10737 return std::numeric_limits<T>::quiet_NaN();
10738 }
10739
10740 vector_node_ptr vec() const
10741 {
10742 return temp_vec_node_;
10743 }
10744
10745 vector_node_ptr vec()
10746 {
10747 return temp_vec_node_;
10748 }
10749
10750 inline typename expression_node<T>::node_type type() const
10751 {
10752 return expression_node<T>::e_vecvalarith;
10753 }
10754
10755 std::size_t size() const
10756 {
10757 return vds().size();
10758 }
10759
10760 vds_t& vds()
10761 {
10762 return vds_;
10763 }
10764
10765 const vds_t& vds() const
10766 {
10767 return vds_;
10768 }
10769
10770 private:
10771
10772 vector_node_ptr vec0_node_ptr_;
10773 vector_holder_ptr temp_;
10774 vector_node_ptr temp_vec_node_;
10775 vds_t vds_;
10776 };
10777
10778 template <typename T, typename Operation>
10779 class vec_binop_valvec_node : public binary_node <T>,
10780 public vector_interface<T>
10781 {
10782 public:
10783
10784 typedef expression_node<T>* expression_ptr;
10785 typedef vector_node<T>* vector_node_ptr;
10786 typedef vector_holder<T>* vector_holder_ptr;
10787 typedef vec_data_store<T> vds_t;
10788
10789 vec_binop_valvec_node(const operator_type& opr,
10790 expression_ptr branch0,
10791 expression_ptr branch1)
10792 : binary_node<T>(opr, branch0, branch1),
10793 vec1_node_ptr_(0),
10794 temp_ (0),
10795 temp_vec_node_(0)
10796 {
10797 bool v1_is_ivec = false;
10798
10799 if (is_vector_node(binary_node<T>::branch_[1].first))
10800 {
10801 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10802 }
10803 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10804 {
10805 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10806
10807 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10808 {
10809 vec1_node_ptr_ = vi->vec();
10810 v1_is_ivec = true;
10811 }
10812 }
10813
10814 if (vec1_node_ptr_)
10815 {
10816 if (v1_is_ivec)
10817 vds() = vec1_node_ptr_->vds();
10818 else
10819 vds() = vds_t(vec1_node_ptr_->size());
10820
10821 temp_ = new vector_holder<T>(vds());
10822 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10823 }
10824 }
10825
10826 ~vec_binop_valvec_node()
10827 {
10828 delete temp_;
10829 delete temp_vec_node_;
10830 }
10831
10832 inline T value() const
10833 {
10834 if (vec1_node_ptr_)
10835 {
10836 const T v = binary_node<T>::branch_[0].first->value();
10837 binary_node<T>::branch_[1].first->value();
10838
10839 T* vec0 = vds().data();
10840 const T* vec1 = vec1_node_ptr_->vds().data();
10841
10842 loop_unroll::details lud(size());
10843 const T* upper_bound = vec0 + lud.upper_bound;
10844
10845 while (vec0 < upper_bound)
10846 {
10847 #define exprtk_loop(N) \
10848 vec0[N] = Operation::process(v, vec1[N]); \
10849
10850 exprtk_loop( 0) exprtk_loop( 1)
10851 exprtk_loop( 2) exprtk_loop( 3)
10852 #ifndef exprtk_disable_superscalar_unroll
10853 exprtk_loop( 4) exprtk_loop( 5)
10854 exprtk_loop( 6) exprtk_loop( 7)
10855 exprtk_loop( 8) exprtk_loop( 9)
10856 exprtk_loop(10) exprtk_loop(11)
10857 exprtk_loop(12) exprtk_loop(13)
10858 exprtk_loop(14) exprtk_loop(15)
10859 #endif
10860
10861 vec0 += lud.batch_size;
10862 vec1 += lud.batch_size;
10863 }
10864
10865 int i = 0;
10866
10867 exprtk_disable_fallthrough_begin
10868 switch (lud.remainder)
10869 {
10870 #define case_stmt(N) \
10871 case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
10872
10873 #ifndef exprtk_disable_superscalar_unroll
10874 case_stmt(15) case_stmt(14)
10875 case_stmt(13) case_stmt(12)
10876 case_stmt(11) case_stmt(10)
10877 case_stmt( 9) case_stmt( 8)
10878 case_stmt( 7) case_stmt( 6)
10879 case_stmt( 5) case_stmt( 4)
10880 #endif
10881 case_stmt( 3) case_stmt( 2)
10882 case_stmt( 1)
10883 }
10884 exprtk_disable_fallthrough_end
10885
10886 #undef exprtk_loop
10887 #undef case_stmt
10888
10889 return (vds().data())[0];
10890 }
10891 else
10892 return std::numeric_limits<T>::quiet_NaN();
10893 }
10894
10895 vector_node_ptr vec() const
10896 {
10897 return temp_vec_node_;
10898 }
10899
10900 vector_node_ptr vec()
10901 {
10902 return temp_vec_node_;
10903 }
10904
10905 inline typename expression_node<T>::node_type type() const
10906 {
10907 return expression_node<T>::e_vecvalarith;
10908 }
10909
10910 std::size_t size() const
10911 {
10912 return vds().size();
10913 }
10914
10915 vds_t& vds()
10916 {
10917 return vds_;
10918 }
10919
10920 const vds_t& vds() const
10921 {
10922 return vds_;
10923 }
10924
10925 private:
10926
10927 vector_node_ptr vec1_node_ptr_;
10928 vector_holder_ptr temp_;
10929 vector_node_ptr temp_vec_node_;
10930 vds_t vds_;
10931 };
10932
10933 template <typename T, typename Operation>
10934 class unary_vector_node : public unary_node <T>,
10935 public vector_interface<T>
10936 {
10937 public:
10938
10939 typedef expression_node<T>* expression_ptr;
10940 typedef vector_node<T>* vector_node_ptr;
10941 typedef vector_holder<T>* vector_holder_ptr;
10942 typedef vec_data_store<T> vds_t;
10943
10944 unary_vector_node(const operator_type& opr, expression_ptr branch0)
10945 : unary_node<T>(opr, branch0),
10946 vec0_node_ptr_(0),
10947 temp_ (0),
10948 temp_vec_node_(0)
10949 {
10950 bool vec0_is_ivec = false;
10951
10952 if (is_vector_node(unary_node<T>::branch_))
10953 {
10954 vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
10955 }
10956 else if (is_ivector_node(unary_node<T>::branch_))
10957 {
10958 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10959
10960 if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
10961 {
10962 vec0_node_ptr_ = vi->vec();
10963 vec0_is_ivec = true;
10964 }
10965 }
10966
10967 if (vec0_node_ptr_)
10968 {
10969 if (vec0_is_ivec)
10970 vds_ = vec0_node_ptr_->vds();
10971 else
10972 vds_ = vds_t(vec0_node_ptr_->size());
10973
10974 temp_ = new vector_holder<T>(vds());
10975 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10976 }
10977 }
10978
10979 ~unary_vector_node()
10980 {
10981 delete temp_;
10982 delete temp_vec_node_;
10983 }
10984
10985 inline T value() const
10986 {
10987 unary_node<T>::branch_->value();
10988
10989 if (vec0_node_ptr_)
10990 {
10991 const T* vec0 = vec0_node_ptr_->vds().data();
10992 T* vec1 = vds().data();
10993
10994 loop_unroll::details lud(size());
10995 const T* upper_bound = vec0 + lud.upper_bound;
10996
10997 while (vec0 < upper_bound)
10998 {
10999 #define exprtk_loop(N) \
11000 vec1[N] = Operation::process(vec0[N]); \
11001
11002 exprtk_loop( 0) exprtk_loop( 1)
11003 exprtk_loop( 2) exprtk_loop( 3)
11004 #ifndef exprtk_disable_superscalar_unroll
11005 exprtk_loop( 4) exprtk_loop( 5)
11006 exprtk_loop( 6) exprtk_loop( 7)
11007 exprtk_loop( 8) exprtk_loop( 9)
11008 exprtk_loop(10) exprtk_loop(11)
11009 exprtk_loop(12) exprtk_loop(13)
11010 exprtk_loop(14) exprtk_loop(15)
11011 #endif
11012
11013 vec0 += lud.batch_size;
11014 vec1 += lud.batch_size;
11015 }
11016
11017 int i = 0;
11018
11019 exprtk_disable_fallthrough_begin
11020 switch (lud.remainder)
11021 {
11022 #define case_stmt(N) \
11023 case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11024
11025 #ifndef exprtk_disable_superscalar_unroll
11026 case_stmt(15) case_stmt(14)
11027 case_stmt(13) case_stmt(12)
11028 case_stmt(11) case_stmt(10)
11029 case_stmt( 9) case_stmt( 8)
11030 case_stmt( 7) case_stmt( 6)
11031 case_stmt( 5) case_stmt( 4)
11032 #endif
11033 case_stmt( 3) case_stmt( 2)
11034 case_stmt( 1)
11035 }
11036 exprtk_disable_fallthrough_end
11037
11038 #undef exprtk_loop
11039 #undef case_stmt
11040
11041 return (vds().data())[0];
11042 }
11043 else
11044 return std::numeric_limits<T>::quiet_NaN();
11045 }
11046
11047 vector_node_ptr vec() const
11048 {
11049 return temp_vec_node_;
11050 }
11051
11052 vector_node_ptr vec()
11053 {
11054 return temp_vec_node_;
11055 }
11056
11057 inline typename expression_node<T>::node_type type() const
11058 {
11059 return expression_node<T>::e_vecunaryop;
11060 }
11061
11062 std::size_t size() const
11063 {
11064 return vds().size();
11065 }
11066
11067 vds_t& vds()
11068 {
11069 return vds_;
11070 }
11071
11072 const vds_t& vds() const
11073 {
11074 return vds_;
11075 }
11076
11077 private:
11078
11079 vector_node_ptr vec0_node_ptr_;
11080 vector_holder_ptr temp_;
11081 vector_node_ptr temp_vec_node_;
11082 vds_t vds_;
11083 };
11084
11085 template <typename T>
11086 class scand_node : public binary_node<T>
11087 {
11088 public:
11089
11090 typedef expression_node<T>* expression_ptr;
11091
11092 scand_node(const operator_type& opr,
11093 expression_ptr branch0,
11094 expression_ptr branch1)
11095 : binary_node<T>(opr, branch0, branch1)
11096 {}
11097
11098 inline T value() const
11099 {
11100 return (
11101 std::not_equal_to<T>()
11102 (T(0),binary_node<T>::branch_[0].first->value()) &&
11103 std::not_equal_to<T>()
11104 (T(0),binary_node<T>::branch_[1].first->value())
11105 ) ? T(1) : T(0);
11106 }
11107 };
11108
11109 template <typename T>
11110 class scor_node : public binary_node<T>
11111 {
11112 public:
11113
11114 typedef expression_node<T>* expression_ptr;
11115
11116 scor_node(const operator_type& opr,
11117 expression_ptr branch0,
11118 expression_ptr branch1)
11119 : binary_node<T>(opr, branch0, branch1)
11120 {}
11121
11122 inline T value() const
11123 {
11124 return (
11125 std::not_equal_to<T>()
11126 (T(0),binary_node<T>::branch_[0].first->value()) ||
11127 std::not_equal_to<T>()
11128 (T(0),binary_node<T>::branch_[1].first->value())
11129 ) ? T(1) : T(0);
11130 }
11131 };
11132
11133 template <typename T, typename IFunction, std::size_t N>
11134 class function_N_node : public expression_node<T>
11135 {
11136 public:
11137
11138 // Function of N paramters.
11139 typedef expression_node<T>* expression_ptr;
11140 typedef std::pair<expression_ptr,bool> branch_t;
11141 typedef IFunction ifunction;
11142
11143 explicit function_N_node(ifunction* func)
11144 : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11145 parameter_count_(func->param_count)
11146 {}
11147
11148 ~function_N_node()
11149 {
11150 cleanup_branches::execute<T,N>(branch_);
11151 }
11152
11153 template <std::size_t NumBranches>
11154 bool init_branches(expression_ptr (&b)[NumBranches])
11155 {
11156 // Needed for incompetent and broken msvc compiler versions
11157 #ifdef _MSC_VER
11158 #pragma warning(push)
11159 #pragma warning(disable: 4127)
11160 #endif
11161 if (N != NumBranches)
11162 return false;
11163 else
11164 {
11165 for (std::size_t i = 0; i < NumBranches; ++i)
11166 {
11167 if (b[i])
11168 branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11169 else
11170 return false;
11171 }
11172 return true;
11173 }
11174 #ifdef _MSC_VER
11175 #pragma warning(pop)
11176 #endif
11177 }
11178
11179 inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11180 {
11181 return this < (&fn);
11182 }
11183
11184 inline T value() const
11185 {
11186 // Needed for incompetent and broken msvc compiler versions
11187 #ifdef _MSC_VER
11188 #pragma warning(push)
11189 #pragma warning(disable: 4127)
11190 #endif
11191 if ((0 == function_) || (0 == N))
11192 return std::numeric_limits<T>::quiet_NaN();
11193 else
11194 {
11195 T v[N];
11196 evaluate_branches<T,N>::execute(v,branch_);
11197 return invoke<T,N>::execute(*function_,v);
11198 }
11199 #ifdef _MSC_VER
11200 #pragma warning(pop)
11201 #endif
11202 }
11203
11204 template <typename T_, std::size_t BranchCount>
11205 struct evaluate_branches
11206 {
11207 static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11208 {
11209 for (std::size_t i = 0; i < BranchCount; ++i)
11210 {
11211 v[i] = b[i].first->value();
11212 }
11213 }
11214 };
11215
11216 template <typename T_>
11217 struct evaluate_branches <T_,5>
11218 {
11219 static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11220 {
11221 v[0] = b[0].first->value();
11222 v[1] = b[1].first->value();
11223 v[2] = b[2].first->value();
11224 v[3] = b[3].first->value();
11225 v[4] = b[4].first->value();
11226 }
11227 };
11228
11229 template <typename T_>
11230 struct evaluate_branches <T_,4>
11231 {
11232 static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11233 {
11234 v[0] = b[0].first->value();
11235 v[1] = b[1].first->value();
11236 v[2] = b[2].first->value();
11237 v[3] = b[3].first->value();
11238 }
11239 };
11240
11241 template <typename T_>
11242 struct evaluate_branches <T_,3>
11243 {
11244 static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11245 {
11246 v[0] = b[0].first->value();
11247 v[1] = b[1].first->value();
11248 v[2] = b[2].first->value();
11249 }
11250 };
11251
11252 template <typename T_>
11253 struct evaluate_branches <T_,2>
11254 {
11255 static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11256 {
11257 v[0] = b[0].first->value();
11258 v[1] = b[1].first->value();
11259 }
11260 };
11261
11262 template <typename T_>
11263 struct evaluate_branches <T_,1>
11264 {
11265 static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11266 {
11267 v[0] = b[0].first->value();
11268 }
11269 };
11270
11271 template <typename T_, std::size_t ParamCount>
11272 struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11273
11274 template <typename T_>
11275 struct invoke<T_,20>
11276 {
11277 static inline T_ execute(ifunction& f, T_ (&v)[20])
11278 { 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]); }
11279 };
11280
11281 template <typename T_>
11282 struct invoke<T_,19>
11283 {
11284 static inline T_ execute(ifunction& f, T_ (&v)[19])
11285 { 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]); }
11286 };
11287
11288 template <typename T_>
11289 struct invoke<T_,18>
11290 {
11291 static inline T_ execute(ifunction& f, T_ (&v)[18])
11292 { 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]); }
11293 };
11294
11295 template <typename T_>
11296 struct invoke<T_,17>
11297 {
11298 static inline T_ execute(ifunction& f, T_ (&v)[17])
11299 { 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]); }
11300 };
11301
11302 template <typename T_>
11303 struct invoke<T_,16>
11304 {
11305 static inline T_ execute(ifunction& f, T_ (&v)[16])
11306 { 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]); }
11307 };
11308
11309 template <typename T_>
11310 struct invoke<T_,15>
11311 {
11312 static inline T_ execute(ifunction& f, T_ (&v)[15])
11313 { 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]); }
11314 };
11315
11316 template <typename T_>
11317 struct invoke<T_,14>
11318 {
11319 static inline T_ execute(ifunction& f, T_ (&v)[14])
11320 { 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]); }
11321 };
11322
11323 template <typename T_>
11324 struct invoke<T_,13>
11325 {
11326 static inline T_ execute(ifunction& f, T_ (&v)[13])
11327 { 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]); }
11328 };
11329
11330 template <typename T_>
11331 struct invoke<T_,12>
11332 {
11333 static inline T_ execute(ifunction& f, T_ (&v)[12])
11334 { 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]); }
11335 };
11336
11337 template <typename T_>
11338 struct invoke<T_,11>
11339 {
11340 static inline T_ execute(ifunction& f, T_ (&v)[11])
11341 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
11342 };
11343
11344 template <typename T_>
11345 struct invoke<T_,10>
11346 {
11347 static inline T_ execute(ifunction& f, T_ (&v)[10])
11348 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11349 };
11350
11351 template <typename T_>
11352 struct invoke<T_,9>
11353 {
11354 static inline T_ execute(ifunction& f, T_ (&v)[9])
11355 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11356 };
11357
11358 template <typename T_>
11359 struct invoke<T_,8>
11360 {
11361 static inline T_ execute(ifunction& f, T_ (&v)[8])
11362 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11363 };
11364
11365 template <typename T_>
11366 struct invoke<T_,7>
11367 {
11368 static inline T_ execute(ifunction& f, T_ (&v)[7])
11369 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11370 };
11371
11372 template <typename T_>
11373 struct invoke<T_,6>
11374 {
11375 static inline T_ execute(ifunction& f, T_ (&v)[6])
11376 { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11377 };
11378
11379 template <typename T_>
11380 struct invoke<T_,5>
11381 {
11382 static inline T_ execute(ifunction& f, T_ (&v)[5])
11383 { return f(v[0],v[1],v[2],v[3],v[4]); }
11384 };
11385
11386 template <typename T_>
11387 struct invoke<T_,4>
11388 {
11389 static inline T_ execute(ifunction& f, T_ (&v)[4])
11390 { return f(v[0],v[1],v[2],v[3]); }
11391 };
11392
11393 template <typename T_>
11394 struct invoke<T_,3>
11395 {
11396 static inline T_ execute(ifunction& f, T_ (&v)[3])
11397 { return f(v[0],v[1],v[2]); }
11398 };
11399
11400 template <typename T_>
11401 struct invoke<T_,2>
11402 {
11403 static inline T_ execute(ifunction& f, T_ (&v)[2])
11404 { return f(v[0],v[1]); }
11405 };
11406
11407 template <typename T_>
11408 struct invoke<T_,1>
11409 {
11410 static inline T_ execute(ifunction& f, T_ (&v)[1])
11411 { return f(v[0]); }
11412 };
11413
11414 inline typename expression_node<T>::node_type type() const
11415 {
11416 return expression_node<T>::e_function;
11417 }
11418
11419 private:
11420
11421 ifunction* function_;
11422 std::size_t parameter_count_;
11423 branch_t branch_[N];
11424 };
11425
11426 template <typename T, typename IFunction>
11427 class function_N_node<T,IFunction,0> : public expression_node<T>
11428 {
11429 public:
11430
11431 typedef expression_node<T>* expression_ptr;
11432 typedef IFunction ifunction;
11433
11434 explicit function_N_node(ifunction* func)
11435 : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
11436 {}
11437
11438 inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
11439 {
11440 return this < (&fn);
11441 }
11442
11443 inline T value() const
11444 {
11445 if (function_)
11446 return (*function_)();
11447 else
11448 return std::numeric_limits<T>::quiet_NaN();
11449 }
11450
11451 inline typename expression_node<T>::node_type type() const
11452 {
11453 return expression_node<T>::e_function;
11454 }
11455
11456 private:
11457
11458 ifunction* function_;
11459 };
11460
11461 template <typename T, typename VarArgFunction>
11462 class vararg_function_node : public expression_node<T>
11463 {
11464 public:
11465
11466 typedef expression_node<T>* expression_ptr;
11467
11468 vararg_function_node(VarArgFunction* func,
11469 const std::vector<expression_ptr>& arg_list)
11470 : function_(func),
11471 arg_list_(arg_list)
11472 {
11473 value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
11474 }
11475
11476 ~vararg_function_node()
11477 {
11478 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11479 {
11480 if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
11481 {
11482 destroy_node(arg_list_[i]);
11483 }
11484 }
11485 }
11486
11487 inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
11488 {
11489 return this < (&fn);
11490 }
11491
11492 inline T value() const
11493 {
11494 if (function_)
11495 {
11496 populate_value_list();
11497 return (*function_)(value_list_);
11498 }
11499 else
11500 return std::numeric_limits<T>::quiet_NaN();
11501 }
11502
11503 inline typename expression_node<T>::node_type type() const
11504 {
11505 return expression_node<T>::e_vafunction;
11506 }
11507
11508 private:
11509
11510 inline void populate_value_list() const
11511 {
11512 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11513 {
11514 value_list_[i] = arg_list_[i]->value();
11515 }
11516 }
11517
11518 VarArgFunction* function_;
11519 std::vector<expression_ptr> arg_list_;
11520 mutable std::vector<T> value_list_;
11521 };
11522
11523 template <typename T, typename GenericFunction>
11524 class generic_function_node : public expression_node<T>
11525 {
11526 public:
11527
11528 typedef type_store<T> type_store_t;
11529 typedef expression_node<T>* expression_ptr;
11530 typedef variable_node<T> variable_node_t;
11531 typedef vector_node<T> vector_node_t;
11532 typedef variable_node_t* variable_node_ptr_t;
11533 typedef vector_node_t* vector_node_ptr_t;
11534 typedef range_interface<T> range_interface_t;
11535 typedef range_data_type<T> range_data_type_t;
11536 typedef range_pack<T> range_t;
11537 typedef std::pair<expression_ptr,bool> branch_t;
11538 typedef std::pair<void*,std::size_t> void_t;
11539 typedef std::vector<T> tmp_vs_t;
11540 typedef std::vector<type_store_t> typestore_list_t;
11541 typedef std::vector<range_data_type_t> range_list_t;
11542
11543 generic_function_node(const std::vector<expression_ptr>& arg_list,
11544 GenericFunction* func = (GenericFunction*)(0))
11545 : function_(func),
11546 arg_list_(arg_list)
11547 {}
11548
11549 virtual ~generic_function_node()
11550 {
11551 cleanup_branches::execute(branch_);
11552 }
11553
11554 virtual bool init_branches()
11555 {
11556 expr_as_vec1_store_.resize(arg_list_.size(),T(0) );
11557 typestore_list_ .resize(arg_list_.size(),type_store_t() );
11558 range_list_ .resize(arg_list_.size(),range_data_type_t());
11559 branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
11560
11561 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11562 {
11563 type_store_t& ts = typestore_list_[i];
11564
11565 if (0 == arg_list_[i])
11566 return false;
11567 else if (is_ivector_node(arg_list_[i]))
11568 {
11569 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11570
11571 if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
11572 return false;
11573
11574 ts.size = vi->size();
11575 ts.data = vi->vds().data();
11576 ts.type = type_store_t::e_vector;
11577 vi->vec()->vec_holder().set_ref(&ts.vec_data);
11578 }
11579 #ifndef exprtk_disable_string_capabilities
11580 else if (is_generally_string_node(arg_list_[i]))
11581 {
11582 string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
11583
11584 if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
11585 return false;
11586
11587 ts.size = sbn->size();
11588 ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
11589 ts.type = type_store_t::e_string;
11590
11591 range_list_[i].data = ts.data;
11592 range_list_[i].size = ts.size;
11593 range_list_[i].type_size = sizeof(char);
11594 range_list_[i].str_node = sbn;
11595
11596 range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
11597
11598 if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
11599 return false;
11600
11601 range_t& rp = ri->range_ref();
11602
11603 if (
11604 rp.const_range() &&
11605 is_const_string_range_node(arg_list_[i])
11606 )
11607 {
11608 ts.size = rp.const_size();
11609 ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
11610 range_list_[i].range = reinterpret_cast<range_t*>(0);
11611 }
11612 else
11613 range_list_[i].range = &(ri->range_ref());
11614 }
11615 #endif
11616 else if (is_variable_node(arg_list_[i]))
11617 {
11618 variable_node_ptr_t var = variable_node_ptr_t(0);
11619
11620 if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
11621 return false;
11622
11623 ts.size = 1;
11624 ts.data = &var->ref();
11625 ts.type = type_store_t::e_scalar;
11626 }
11627 else
11628 {
11629 ts.size = 1;
11630 ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
11631 ts.type = type_store_t::e_scalar;
11632 }
11633
11634 branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
11635 }
11636
11637 return true;
11638 }
11639
11640 inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
11641 {
11642 return this < (&fn);
11643 }
11644
11645 inline T value() const
11646 {
11647 if (function_)
11648 {
11649 if (populate_value_list())
11650 {
11651 typedef typename GenericFunction::parameter_list_t parameter_list_t;
11652
11653 return (*function_)(parameter_list_t(typestore_list_));
11654 }
11655 }
11656
11657 return std::numeric_limits<T>::quiet_NaN();
11658 }
11659
11660 inline typename expression_node<T>::node_type type() const
11661 {
11662 return expression_node<T>::e_genfunction;
11663 }
11664
11665 protected:
11666
11667 inline virtual bool populate_value_list() const
11668 {
11669 for (std::size_t i = 0; i < branch_.size(); ++i)
11670 {
11671 expr_as_vec1_store_[i] = branch_[i].first->value();
11672 }
11673
11674 for (std::size_t i = 0; i < branch_.size(); ++i)
11675 {
11676 range_data_type_t& rdt = range_list_[i];
11677
11678 if (rdt.range)
11679 {
11680 range_t& rp = (*rdt.range);
11681 std::size_t r0 = 0;
11682 std::size_t r1 = 0;
11683
11684 if (rp(r0,r1,rdt.size))
11685 {
11686 type_store_t& ts = typestore_list_[i];
11687
11688 ts.size = rp.cache_size();
11689 #ifndef exprtk_disable_string_capabilities
11690 if (ts.type == type_store_t::e_string)
11691 ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
11692 else
11693 #endif
11694 ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
11695 }
11696 else
11697 return false;
11698 }
11699 }
11700
11701 return true;
11702 }
11703
11704 GenericFunction* function_;
11705 mutable typestore_list_t typestore_list_;
11706
11707 private:
11708
11709 std::vector<expression_ptr> arg_list_;
11710 std::vector<branch_t> branch_;
11711 mutable tmp_vs_t expr_as_vec1_store_;
11712 mutable range_list_t range_list_;
11713 };
11714
11715 #ifndef exprtk_disable_string_capabilities
11716 template <typename T, typename StringFunction>
11717 class string_function_node : public generic_function_node<T,StringFunction>,
11718 public string_base_node<T>,
11719 public range_interface <T>
11720 {
11721 public:
11722
11723 typedef generic_function_node<T,StringFunction> gen_function_t;
11724 typedef range_pack<T> range_t;
11725
11726 string_function_node(StringFunction* func,
11727 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11728 : gen_function_t(arg_list,func)
11729 {
11730 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11731 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11732 range_.cache.first = range_.n0_c.second;
11733 range_.cache.second = range_.n1_c.second;
11734 }
11735
11736 inline bool operator <(const string_function_node<T,StringFunction>& fn) const
11737 {
11738 return this < (&fn);
11739 }
11740
11741 inline T value() const
11742 {
11743 if (gen_function_t::function_)
11744 {
11745 if (gen_function_t::populate_value_list())
11746 {
11747 typedef typename StringFunction::parameter_list_t parameter_list_t;
11748
11749 const T result = (*gen_function_t::function_)
11750 (
11751 ret_string_,
11752 parameter_list_t(gen_function_t::typestore_list_)
11753 );
11754
11755 range_.n1_c.second = ret_string_.size() - 1;
11756 range_.cache.second = range_.n1_c.second;
11757
11758 return result;
11759 }
11760 }
11761
11762 return std::numeric_limits<T>::quiet_NaN();
11763 }
11764
11765 inline typename expression_node<T>::node_type type() const
11766 {
11767 return expression_node<T>::e_strfunction;
11768 }
11769
11770 std::string str() const
11771 {
11772 return ret_string_;
11773 }
11774
11775 char_cptr base() const
11776 {
11777 return &ret_string_[0];
11778 }
11779
11780 std::size_t size() const
11781 {
11782 return ret_string_.size();
11783 }
11784
11785 range_t& range_ref()
11786 {
11787 return range_;
11788 }
11789
11790 const range_t& range_ref() const
11791 {
11792 return range_;
11793 }
11794
11795 protected:
11796
11797 mutable range_t range_;
11798 mutable std::string ret_string_;
11799 };
11800 #endif
11801
11802 template <typename T, typename GenericFunction>
11803 class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
11804 {
11805 public:
11806
11807 typedef generic_function_node<T,GenericFunction> gen_function_t;
11808 typedef range_pack<T> range_t;
11809
11810 multimode_genfunction_node(GenericFunction* func,
11811 const std::size_t& param_seq_index,
11812 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11813 : gen_function_t(arg_list,func),
11814 param_seq_index_(param_seq_index)
11815 {}
11816
11817 inline T value() const
11818 {
11819 if (gen_function_t::function_)
11820 {
11821 if (gen_function_t::populate_value_list())
11822 {
11823 typedef typename GenericFunction::parameter_list_t parameter_list_t;
11824
11825 return (*gen_function_t::function_)
11826 (
11827 param_seq_index_,
11828 parameter_list_t(gen_function_t::typestore_list_)
11829 );
11830 }
11831 }
11832
11833 return std::numeric_limits<T>::quiet_NaN();
11834 }
11835
11836 inline typename expression_node<T>::node_type type() const
11837 {
11838 return expression_node<T>::e_genfunction;
11839 }
11840
11841 private:
11842
11843 std::size_t param_seq_index_;
11844 };
11845
11846 #ifndef exprtk_disable_string_capabilities
11847 template <typename T, typename StringFunction>
11848 class multimode_strfunction_node : public string_function_node<T,StringFunction>
11849 {
11850 public:
11851
11852 typedef string_function_node<T,StringFunction> str_function_t;
11853 typedef range_pack<T> range_t;
11854
11855 multimode_strfunction_node(StringFunction* func,
11856 const std::size_t& param_seq_index,
11857 const std::vector<typename str_function_t::expression_ptr>& arg_list)
11858 : str_function_t(func,arg_list),
11859 param_seq_index_(param_seq_index)
11860 {}
11861
11862 inline T value() const
11863 {
11864 if (str_function_t::function_)
11865 {
11866 if (str_function_t::populate_value_list())
11867 {
11868 typedef typename StringFunction::parameter_list_t parameter_list_t;
11869
11870 const T result = (*str_function_t::function_)
11871 (
11872 param_seq_index_,
11873 str_function_t::ret_string_,
11874 parameter_list_t(str_function_t::typestore_list_)
11875 );
11876
11877 str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1;
11878 str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
11879
11880 return result;
11881 }
11882 }
11883
11884 return std::numeric_limits<T>::quiet_NaN();
11885 }
11886
11887 inline typename expression_node<T>::node_type type() const
11888 {
11889 return expression_node<T>::e_strfunction;
11890 }
11891
11892 private:
11893
11894 const std::size_t param_seq_index_;
11895 };
11896 #endif
11897
11898 class return_exception
11899 {};
11900
11901 template <typename T>
11902 class null_igenfunc
11903 {
11904 public:
11905
11906 virtual ~null_igenfunc()
11907 {}
11908
11909 typedef type_store<T> generic_type;
11910 typedef typename generic_type::parameter_list parameter_list_t;
11911
11912 inline virtual T operator() (parameter_list_t)
11913 {
11914 return std::numeric_limits<T>::quiet_NaN();
11915 }
11916 };
11917
11918 #ifndef exprtk_disable_return_statement
11919 template <typename T>
11920 class return_node : public generic_function_node<T,null_igenfunc<T> >
11921 {
11922 public:
11923
11924 typedef null_igenfunc<T> igeneric_function_t;
11925 typedef igeneric_function_t* igeneric_function_ptr;
11926 typedef generic_function_node<T,igeneric_function_t> gen_function_t;
11927 typedef results_context<T> results_context_t;
11928
11929 return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
11930 results_context_t& rc)
11931 : gen_function_t (arg_list),
11932 results_context_(&rc)
11933 {}
11934
11935 inline T value() const
11936 {
11937 if (
11938 (0 != results_context_) &&
11939 gen_function_t::populate_value_list()
11940 )
11941 {
11942 typedef typename type_store<T>::parameter_list parameter_list_t;
11943
11944 results_context_->
11945 assign(parameter_list_t(gen_function_t::typestore_list_));
11946
11947 throw return_exception();
11948 }
11949
11950 return std::numeric_limits<T>::quiet_NaN();
11951 }
11952
11953 inline typename expression_node<T>::node_type type() const
11954 {
11955 return expression_node<T>::e_return;
11956 }
11957
11958 private:
11959
11960 results_context_t* results_context_;
11961 };
11962
11963 template <typename T>
11964 class return_envelope_node : public expression_node<T>
11965 {
11966 public:
11967
11968 typedef expression_node<T>* expression_ptr;
11969 typedef results_context<T> results_context_t;
11970
11971 return_envelope_node(expression_ptr body, results_context_t& rc)
11972 : results_context_(&rc ),
11973 return_invoked_ (false),
11974 body_ (body ),
11975 body_deletable_ (branch_deletable(body_))
11976 {}
11977
11978 ~return_envelope_node()
11979 {
11980 if (body_ && body_deletable_)
11981 {
11982 destroy_node(body_);
11983 }
11984 }
11985
11986 inline T value() const
11987 {
11988 try
11989 {
11990 return_invoked_ = false;
11991 results_context_->clear();
11992
11993 return body_->value();
11994 }
11995 catch(const return_exception&)
11996 {
11997 return_invoked_ = true;
11998 return std::numeric_limits<T>::quiet_NaN();
11999 }
12000 }
12001
12002 inline typename expression_node<T>::node_type type() const
12003 {
12004 return expression_node<T>::e_retenv;
12005 }
12006
12007 inline bool* retinvk_ptr()
12008 {
12009 return &return_invoked_;
12010 }
12011
12012 private:
12013
12014 results_context_t* results_context_;
12015 mutable bool return_invoked_;
12016 expression_ptr body_;
12017 const bool body_deletable_;
12018 };
12019 #endif
12020
12021 #define exprtk_define_unary_op(OpName) \
12022 template <typename T> \
12023 struct OpName##_op \
12024 { \
12025 typedef typename functor_t<T>::Type Type; \
12026 typedef typename expression_node<T>::node_type node_t; \
12027 \
12028 static inline T process(Type v) \
12029 { \
12030 return numeric:: OpName (v); \
12031 } \
12032 \
12033 static inline node_t type() \
12034 { \
12035 return expression_node<T>::e_##OpName; \
12036 } \
12037 \
12038 static inline details::operator_type operation() \
12039 { \
12040 return details::e_##OpName; \
12041 } \
12042 }; \
12043
12044 exprtk_define_unary_op(abs )
12045 exprtk_define_unary_op(acos )
12046 exprtk_define_unary_op(acosh)
12047 exprtk_define_unary_op(asin )
12048 exprtk_define_unary_op(asinh)
12049 exprtk_define_unary_op(atan )
12050 exprtk_define_unary_op(atanh)
12051 exprtk_define_unary_op(ceil )
12052 exprtk_define_unary_op(cos )
12053 exprtk_define_unary_op(cosh )
12054 exprtk_define_unary_op(cot )
12055 exprtk_define_unary_op(csc )
12056 exprtk_define_unary_op(d2g )
12057 exprtk_define_unary_op(d2r )
12058 exprtk_define_unary_op(erf )
12059 exprtk_define_unary_op(erfc )
12060 exprtk_define_unary_op(exp )
12061 exprtk_define_unary_op(expm1)
12062 exprtk_define_unary_op(floor)
12063 exprtk_define_unary_op(frac )
12064 exprtk_define_unary_op(g2d )
12065 exprtk_define_unary_op(log )
12066 exprtk_define_unary_op(log10)
12067 exprtk_define_unary_op(log2 )
12068 exprtk_define_unary_op(log1p)
12069 exprtk_define_unary_op(ncdf )
12070 exprtk_define_unary_op(neg )
12071 exprtk_define_unary_op(notl )
12072 exprtk_define_unary_op(pos )
12073 exprtk_define_unary_op(r2d )
12074 exprtk_define_unary_op(round)
12075 exprtk_define_unary_op(sec )
12076 exprtk_define_unary_op(sgn )
12077 exprtk_define_unary_op(sin )
12078 exprtk_define_unary_op(sinc )
12079 exprtk_define_unary_op(sinh )
12080 exprtk_define_unary_op(sqrt )
12081 exprtk_define_unary_op(tan )
12082 exprtk_define_unary_op(tanh )
12083 exprtk_define_unary_op(trunc)
12084 #undef exprtk_define_unary_op
12085
12086 template <typename T>
12087 struct opr_base
12088 {
12089 typedef typename details::functor_t<T>::Type Type;
12090 typedef typename details::functor_t<T>::RefType RefType;
12091 typedef typename details::functor_t<T> functor_t;
12092 typedef typename functor_t::qfunc_t quaternary_functor_t;
12093 typedef typename functor_t::tfunc_t trinary_functor_t;
12094 typedef typename functor_t::bfunc_t binary_functor_t;
12095 typedef typename functor_t::ufunc_t unary_functor_t;
12096 };
12097
12098 template <typename T>
12099 struct add_op : public opr_base<T>
12100 {
12101 typedef typename opr_base<T>::Type Type;
12102 typedef typename opr_base<T>::RefType RefType;
12103
12104 static inline T process(Type t1, Type t2) { return t1 + t2; }
12105 static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
12106 static inline void assign(RefType t1, Type t2) { t1 += t2; }
12107 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
12108 static inline details::operator_type operation() { return details::e_add; }
12109 };
12110
12111 template <typename T>
12112 struct mul_op : public opr_base<T>
12113 {
12114 typedef typename opr_base<T>::Type Type;
12115 typedef typename opr_base<T>::RefType RefType;
12116
12117 static inline T process(Type t1, Type t2) { return t1 * t2; }
12118 static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
12119 static inline void assign(RefType t1, Type t2) { t1 *= t2; }
12120 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
12121 static inline details::operator_type operation() { return details::e_mul; }
12122 };
12123
12124 template <typename T>
12125 struct sub_op : public opr_base<T>
12126 {
12127 typedef typename opr_base<T>::Type Type;
12128 typedef typename opr_base<T>::RefType RefType;
12129
12130 static inline T process(Type t1, Type t2) { return t1 - t2; }
12131 static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
12132 static inline void assign(RefType t1, Type t2) { t1 -= t2; }
12133 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
12134 static inline details::operator_type operation() { return details::e_sub; }
12135 };
12136
12137 template <typename T>
12138 struct div_op : public opr_base<T>
12139 {
12140 typedef typename opr_base<T>::Type Type;
12141 typedef typename opr_base<T>::RefType RefType;
12142
12143 static inline T process(Type t1, Type t2) { return t1 / t2; }
12144 static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
12145 static inline void assign(RefType t1, Type t2) { t1 /= t2; }
12146 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
12147 static inline details::operator_type operation() { return details::e_div; }
12148 };
12149
12150 template <typename T>
12151 struct mod_op : public opr_base<T>
12152 {
12153 typedef typename opr_base<T>::Type Type;
12154 typedef typename opr_base<T>::RefType RefType;
12155
12156 static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
12157 static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
12158 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
12159 static inline details::operator_type operation() { return details::e_mod; }
12160 };
12161
12162 template <typename T>
12163 struct pow_op : public opr_base<T>
12164 {
12165 typedef typename opr_base<T>::Type Type;
12166 typedef typename opr_base<T>::RefType RefType;
12167
12168 static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
12169 static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
12170 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
12171 static inline details::operator_type operation() { return details::e_pow; }
12172 };
12173
12174 template <typename T>
12175 struct lt_op : public opr_base<T>
12176 {
12177 typedef typename opr_base<T>::Type Type;
12178
12179 static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
12180 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
12181 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
12182 static inline details::operator_type operation() { return details::e_lt; }
12183 };
12184
12185 template <typename T>
12186 struct lte_op : public opr_base<T>
12187 {
12188 typedef typename opr_base<T>::Type Type;
12189
12190 static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12191 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12192 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
12193 static inline details::operator_type operation() { return details::e_lte; }
12194 };
12195
12196 template <typename T>
12197 struct gt_op : public opr_base<T>
12198 {
12199 typedef typename opr_base<T>::Type Type;
12200
12201 static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
12202 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
12203 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
12204 static inline details::operator_type operation() { return details::e_gt; }
12205 };
12206
12207 template <typename T>
12208 struct gte_op : public opr_base<T>
12209 {
12210 typedef typename opr_base<T>::Type Type;
12211
12212 static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12213 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12214 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
12215 static inline details::operator_type operation() { return details::e_gte; }
12216 };
12217
12218 template <typename T>
12219 struct eq_op : public opr_base<T>
12220 {
12221 typedef typename opr_base<T>::Type Type;
12222 static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12223 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12224 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12225 static inline details::operator_type operation() { return details::e_eq; }
12226 };
12227
12228 template <typename T>
12229 struct equal_op : public opr_base<T>
12230 {
12231 typedef typename opr_base<T>::Type Type;
12232
12233 static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
12234 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12235 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12236 static inline details::operator_type operation() { return details::e_equal; }
12237 };
12238
12239 template <typename T>
12240 struct ne_op : public opr_base<T>
12241 {
12242 typedef typename opr_base<T>::Type Type;
12243
12244 static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12245 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
12246 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
12247 static inline details::operator_type operation() { return details::e_ne; }
12248 };
12249
12250 template <typename T>
12251 struct and_op : public opr_base<T>
12252 {
12253 typedef typename opr_base<T>::Type Type;
12254
12255 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
12256 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
12257 static inline details::operator_type operation() { return details::e_and; }
12258 };
12259
12260 template <typename T>
12261 struct nand_op : public opr_base<T>
12262 {
12263 typedef typename opr_base<T>::Type Type;
12264
12265 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
12266 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
12267 static inline details::operator_type operation() { return details::e_nand; }
12268 };
12269
12270 template <typename T>
12271 struct or_op : public opr_base<T>
12272 {
12273 typedef typename opr_base<T>::Type Type;
12274
12275 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
12276 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
12277 static inline details::operator_type operation() { return details::e_or; }
12278 };
12279
12280 template <typename T>
12281 struct nor_op : public opr_base<T>
12282 {
12283 typedef typename opr_base<T>::Type Type;
12284
12285 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
12286 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12287 static inline details::operator_type operation() { return details::e_nor; }
12288 };
12289
12290 template <typename T>
12291 struct xor_op : public opr_base<T>
12292 {
12293 typedef typename opr_base<T>::Type Type;
12294
12295 static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
12296 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12297 static inline details::operator_type operation() { return details::e_xor; }
12298 };
12299
12300 template <typename T>
12301 struct xnor_op : public opr_base<T>
12302 {
12303 typedef typename opr_base<T>::Type Type;
12304
12305 static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
12306 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12307 static inline details::operator_type operation() { return details::e_xnor; }
12308 };
12309
12310 template <typename T>
12311 struct in_op : public opr_base<T>
12312 {
12313 typedef typename opr_base<T>::Type Type;
12314
12315 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12316 static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
12317 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
12318 static inline details::operator_type operation() { return details::e_in; }
12319 };
12320
12321 template <typename T>
12322 struct like_op : public opr_base<T>
12323 {
12324 typedef typename opr_base<T>::Type Type;
12325
12326 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12327 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
12328 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
12329 static inline details::operator_type operation() { return details::e_like; }
12330 };
12331
12332 template <typename T>
12333 struct ilike_op : public opr_base<T>
12334 {
12335 typedef typename opr_base<T>::Type Type;
12336
12337 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12338 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
12339 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
12340 static inline details::operator_type operation() { return details::e_ilike; }
12341 };
12342
12343 template <typename T>
12344 struct inrange_op : public opr_base<T>
12345 {
12346 typedef typename opr_base<T>::Type Type;
12347
12348 static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
12349 static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12350 {
12351 return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12352 }
12353 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
12354 static inline details::operator_type operation() { return details::e_inrange; }
12355 };
12356
12357 template <typename T>
12358 inline T value(details::expression_node<T>* n)
12359 {
12360 return n->value();
12361 }
12362
12363 template <typename T>
12364 inline T value(T* t)
12365 {
12366 return (*t);
12367 }
12368
12369 template <typename T>
12370 struct vararg_add_op : public opr_base<T>
12371 {
12372 typedef typename opr_base<T>::Type Type;
12373
12374 template <typename Type,
12375 typename Allocator,
12376 template <typename, typename> class Sequence>
12377 static inline T process(const Sequence<Type,Allocator>& arg_list)
12378 {
12379 switch (arg_list.size())
12380 {
12381 case 0 : return T(0);
12382 case 1 : return process_1(arg_list);
12383 case 2 : return process_2(arg_list);
12384 case 3 : return process_3(arg_list);
12385 case 4 : return process_4(arg_list);
12386 case 5 : return process_5(arg_list);
12387 default :
12388 {
12389 T result = T(0);
12390
12391 for (std::size_t i = 0; i < arg_list.size(); ++i)
12392 {
12393 result += value(arg_list[i]);
12394 }
12395
12396 return result;
12397 }
12398 }
12399 }
12400
12401 template <typename Sequence>
12402 static inline T process_1(const Sequence& arg_list)
12403 {
12404 return value(arg_list[0]);
12405 }
12406
12407 template <typename Sequence>
12408 static inline T process_2(const Sequence& arg_list)
12409 {
12410 return value(arg_list[0]) + value(arg_list[1]);
12411 }
12412
12413 template <typename Sequence>
12414 static inline T process_3(const Sequence& arg_list)
12415 {
12416 return value(arg_list[0]) + value(arg_list[1]) +
12417 value(arg_list[2]) ;
12418 }
12419
12420 template <typename Sequence>
12421 static inline T process_4(const Sequence& arg_list)
12422 {
12423 return value(arg_list[0]) + value(arg_list[1]) +
12424 value(arg_list[2]) + value(arg_list[3]) ;
12425 }
12426
12427 template <typename Sequence>
12428 static inline T process_5(const Sequence& arg_list)
12429 {
12430 return value(arg_list[0]) + value(arg_list[1]) +
12431 value(arg_list[2]) + value(arg_list[3]) +
12432 value(arg_list[4]) ;
12433 }
12434 };
12435
12436 template <typename T>
12437 struct vararg_mul_op : public opr_base<T>
12438 {
12439 typedef typename opr_base<T>::Type Type;
12440
12441 template <typename Type,
12442 typename Allocator,
12443 template <typename, typename> class Sequence>
12444 static inline T process(const Sequence<Type,Allocator>& arg_list)
12445 {
12446 switch (arg_list.size())
12447 {
12448 case 0 : return T(0);
12449 case 1 : return process_1(arg_list);
12450 case 2 : return process_2(arg_list);
12451 case 3 : return process_3(arg_list);
12452 case 4 : return process_4(arg_list);
12453 case 5 : return process_5(arg_list);
12454 default :
12455 {
12456 T result = T(value(arg_list[0]));
12457
12458 for (std::size_t i = 1; i < arg_list.size(); ++i)
12459 {
12460 result *= value(arg_list[i]);
12461 }
12462
12463 return result;
12464 }
12465 }
12466 }
12467
12468 template <typename Sequence>
12469 static inline T process_1(const Sequence& arg_list)
12470 {
12471 return value(arg_list[0]);
12472 }
12473
12474 template <typename Sequence>
12475 static inline T process_2(const Sequence& arg_list)
12476 {
12477 return value(arg_list[0]) * value(arg_list[1]);
12478 }
12479
12480 template <typename Sequence>
12481 static inline T process_3(const Sequence& arg_list)
12482 {
12483 return value(arg_list[0]) * value(arg_list[1]) *
12484 value(arg_list[2]) ;
12485 }
12486
12487 template <typename Sequence>
12488 static inline T process_4(const Sequence& arg_list)
12489 {
12490 return value(arg_list[0]) * value(arg_list[1]) *
12491 value(arg_list[2]) * value(arg_list[3]) ;
12492 }
12493
12494 template <typename Sequence>
12495 static inline T process_5(const Sequence& arg_list)
12496 {
12497 return value(arg_list[0]) * value(arg_list[1]) *
12498 value(arg_list[2]) * value(arg_list[3]) *
12499 value(arg_list[4]) ;
12500 }
12501 };
12502
12503 template <typename T>
12504 struct vararg_avg_op : public opr_base<T>
12505 {
12506 typedef typename opr_base<T>::Type Type;
12507
12508 template <typename Type,
12509 typename Allocator,
12510 template <typename, typename> class Sequence>
12511 static inline T process(const Sequence<Type,Allocator>& arg_list)
12512 {
12513 switch (arg_list.size())
12514 {
12515 case 0 : return T(0);
12516 case 1 : return process_1(arg_list);
12517 case 2 : return process_2(arg_list);
12518 case 3 : return process_3(arg_list);
12519 case 4 : return process_4(arg_list);
12520 case 5 : return process_5(arg_list);
12521 default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
12522 }
12523 }
12524
12525 template <typename Sequence>
12526 static inline T process_1(const Sequence& arg_list)
12527 {
12528 return value(arg_list[0]);
12529 }
12530
12531 template <typename Sequence>
12532 static inline T process_2(const Sequence& arg_list)
12533 {
12534 return (value(arg_list[0]) + value(arg_list[1])) / T(2);
12535 }
12536
12537 template <typename Sequence>
12538 static inline T process_3(const Sequence& arg_list)
12539 {
12540 return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
12541 }
12542
12543 template <typename Sequence>
12544 static inline T process_4(const Sequence& arg_list)
12545 {
12546 return (value(arg_list[0]) + value(arg_list[1]) +
12547 value(arg_list[2]) + value(arg_list[3])) / T(4);
12548 }
12549
12550 template <typename Sequence>
12551 static inline T process_5(const Sequence& arg_list)
12552 {
12553 return (value(arg_list[0]) + value(arg_list[1]) +
12554 value(arg_list[2]) + value(arg_list[3]) +
12555 value(arg_list[4])) / T(5);
12556 }
12557 };
12558
12559 template <typename T>
12560 struct vararg_min_op : public opr_base<T>
12561 {
12562 typedef typename opr_base<T>::Type Type;
12563
12564 template <typename Type,
12565 typename Allocator,
12566 template <typename, typename> class Sequence>
12567 static inline T process(const Sequence<Type,Allocator>& arg_list)
12568 {
12569 switch (arg_list.size())
12570 {
12571 case 0 : return T(0);
12572 case 1 : return process_1(arg_list);
12573 case 2 : return process_2(arg_list);
12574 case 3 : return process_3(arg_list);
12575 case 4 : return process_4(arg_list);
12576 case 5 : return process_5(arg_list);
12577 default :
12578 {
12579 T result = T(value(arg_list[0]));
12580
12581 for (std::size_t i = 1; i < arg_list.size(); ++i)
12582 {
12583 const T v = value(arg_list[i]);
12584
12585 if (v < result)
12586 result = v;
12587 }
12588
12589 return result;
12590 }
12591 }
12592 }
12593
12594 template <typename Sequence>
12595 static inline T process_1(const Sequence& arg_list)
12596 {
12597 return value(arg_list[0]);
12598 }
12599
12600 template <typename Sequence>
12601 static inline T process_2(const Sequence& arg_list)
12602 {
12603 return std::min<T>(value(arg_list[0]),value(arg_list[1]));
12604 }
12605
12606 template <typename Sequence>
12607 static inline T process_3(const Sequence& arg_list)
12608 {
12609 return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12610 }
12611
12612 template <typename Sequence>
12613 static inline T process_4(const Sequence& arg_list)
12614 {
12615 return std::min<T>(
12616 std::min<T>(value(arg_list[0]), value(arg_list[1])),
12617 std::min<T>(value(arg_list[2]), value(arg_list[3])));
12618 }
12619
12620 template <typename Sequence>
12621 static inline T process_5(const Sequence& arg_list)
12622 {
12623 return std::min<T>(
12624 std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
12625 std::min<T>(value(arg_list[2]), value(arg_list[3]))),
12626 value(arg_list[4]));
12627 }
12628 };
12629
12630 template <typename T>
12631 struct vararg_max_op : public opr_base<T>
12632 {
12633 typedef typename opr_base<T>::Type Type;
12634
12635 template <typename Type,
12636 typename Allocator,
12637 template <typename, typename> class Sequence>
12638 static inline T process(const Sequence<Type,Allocator>& arg_list)
12639 {
12640 switch (arg_list.size())
12641 {
12642 case 0 : return T(0);
12643 case 1 : return process_1(arg_list);
12644 case 2 : return process_2(arg_list);
12645 case 3 : return process_3(arg_list);
12646 case 4 : return process_4(arg_list);
12647 case 5 : return process_5(arg_list);
12648 default :
12649 {
12650 T result = T(value(arg_list[0]));
12651
12652 for (std::size_t i = 1; i < arg_list.size(); ++i)
12653 {
12654 const T v = value(arg_list[i]);
12655
12656 if (v > result)
12657 result = v;
12658 }
12659
12660 return result;
12661 }
12662 }
12663 }
12664
12665 template <typename Sequence>
12666 static inline T process_1(const Sequence& arg_list)
12667 {
12668 return value(arg_list[0]);
12669 }
12670
12671 template <typename Sequence>
12672 static inline T process_2(const Sequence& arg_list)
12673 {
12674 return std::max<T>(value(arg_list[0]),value(arg_list[1]));
12675 }
12676
12677 template <typename Sequence>
12678 static inline T process_3(const Sequence& arg_list)
12679 {
12680 return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12681 }
12682
12683 template <typename Sequence>
12684 static inline T process_4(const Sequence& arg_list)
12685 {
12686 return std::max<T>(
12687 std::max<T>(value(arg_list[0]), value(arg_list[1])),
12688 std::max<T>(value(arg_list[2]), value(arg_list[3])));
12689 }
12690
12691 template <typename Sequence>
12692 static inline T process_5(const Sequence& arg_list)
12693 {
12694 return std::max<T>(
12695 std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
12696 std::max<T>(value(arg_list[2]), value(arg_list[3]))),
12697 value(arg_list[4]));
12698 }
12699 };
12700
12701 template <typename T>
12702 struct vararg_mand_op : public opr_base<T>
12703 {
12704 typedef typename opr_base<T>::Type Type;
12705
12706 template <typename Type,
12707 typename Allocator,
12708 template <typename, typename> class Sequence>
12709 static inline T process(const Sequence<Type,Allocator>& arg_list)
12710 {
12711 switch (arg_list.size())
12712 {
12713 case 1 : return process_1(arg_list);
12714 case 2 : return process_2(arg_list);
12715 case 3 : return process_3(arg_list);
12716 case 4 : return process_4(arg_list);
12717 case 5 : return process_5(arg_list);
12718 default :
12719 {
12720 for (std::size_t i = 0; i < arg_list.size(); ++i)
12721 {
12722 if (std::equal_to<T>()(T(0), value(arg_list[i])))
12723 return T(0);
12724 }
12725
12726 return T(1);
12727 }
12728 }
12729 }
12730
12731 template <typename Sequence>
12732 static inline T process_1(const Sequence& arg_list)
12733 {
12734 return std::not_equal_to<T>()
12735 (T(0), value(arg_list[0])) ? T(1) : T(0);
12736 }
12737
12738 template <typename Sequence>
12739 static inline T process_2(const Sequence& arg_list)
12740 {
12741 return (
12742 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12743 std::not_equal_to<T>()(T(0), value(arg_list[1]))
12744 ) ? T(1) : T(0);
12745 }
12746
12747 template <typename Sequence>
12748 static inline T process_3(const Sequence& arg_list)
12749 {
12750 return (
12751 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12752 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12753 std::not_equal_to<T>()(T(0), value(arg_list[2]))
12754 ) ? T(1) : T(0);
12755 }
12756
12757 template <typename Sequence>
12758 static inline T process_4(const Sequence& arg_list)
12759 {
12760 return (
12761 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12762 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12763 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12764 std::not_equal_to<T>()(T(0), value(arg_list[3]))
12765 ) ? T(1) : T(0);
12766 }
12767
12768 template <typename Sequence>
12769 static inline T process_5(const Sequence& arg_list)
12770 {
12771 return (
12772 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12773 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12774 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12775 std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
12776 std::not_equal_to<T>()(T(0), value(arg_list[4]))
12777 ) ? T(1) : T(0);
12778 }
12779 };
12780
12781 template <typename T>
12782 struct vararg_mor_op : public opr_base<T>
12783 {
12784 typedef typename opr_base<T>::Type Type;
12785
12786 template <typename Type,
12787 typename Allocator,
12788 template <typename, typename> class Sequence>
12789 static inline T process(const Sequence<Type,Allocator>& arg_list)
12790 {
12791 switch (arg_list.size())
12792 {
12793 case 1 : return process_1(arg_list);
12794 case 2 : return process_2(arg_list);
12795 case 3 : return process_3(arg_list);
12796 case 4 : return process_4(arg_list);
12797 case 5 : return process_5(arg_list);
12798 default :
12799 {
12800 for (std::size_t i = 0; i < arg_list.size(); ++i)
12801 {
12802 if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
12803 return T(1);
12804 }
12805
12806 return T(0);
12807 }
12808 }
12809 }
12810
12811 template <typename Sequence>
12812 static inline T process_1(const Sequence& arg_list)
12813 {
12814 return std::not_equal_to<T>()
12815 (T(0), value(arg_list[0])) ? T(1) : T(0);
12816 }
12817
12818 template <typename Sequence>
12819 static inline T process_2(const Sequence& arg_list)
12820 {
12821 return (
12822 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12823 std::not_equal_to<T>()(T(0), value(arg_list[1]))
12824 ) ? T(1) : T(0);
12825 }
12826
12827 template <typename Sequence>
12828 static inline T process_3(const Sequence& arg_list)
12829 {
12830 return (
12831 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12832 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12833 std::not_equal_to<T>()(T(0), value(arg_list[2]))
12834 ) ? T(1) : T(0);
12835 }
12836
12837 template <typename Sequence>
12838 static inline T process_4(const Sequence& arg_list)
12839 {
12840 return (
12841 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12842 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12843 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12844 std::not_equal_to<T>()(T(0), value(arg_list[3]))
12845 ) ? T(1) : T(0);
12846 }
12847
12848 template <typename Sequence>
12849 static inline T process_5(const Sequence& arg_list)
12850 {
12851 return (
12852 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12853 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12854 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12855 std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
12856 std::not_equal_to<T>()(T(0), value(arg_list[4]))
12857 ) ? T(1) : T(0);
12858 }
12859 };
12860
12861 template <typename T>
12862 struct vararg_multi_op : public opr_base<T>
12863 {
12864 typedef typename opr_base<T>::Type Type;
12865
12866 template <typename Type,
12867 typename Allocator,
12868 template <typename, typename> class Sequence>
12869 static inline T process(const Sequence<Type,Allocator>& arg_list)
12870 {
12871 switch (arg_list.size())
12872 {
12873 case 0 : return std::numeric_limits<T>::quiet_NaN();
12874 case 1 : return process_1(arg_list);
12875 case 2 : return process_2(arg_list);
12876 case 3 : return process_3(arg_list);
12877 case 4 : return process_4(arg_list);
12878 case 5 : return process_5(arg_list);
12879 case 6 : return process_6(arg_list);
12880 case 7 : return process_7(arg_list);
12881 case 8 : return process_8(arg_list);
12882 default :
12883 {
12884 for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
12885 {
12886 value(arg_list[i]);
12887 }
12888
12889 return value(arg_list.back());
12890 }
12891 }
12892 }
12893
12894 template <typename Sequence>
12895 static inline T process_1(const Sequence& arg_list)
12896 {
12897 return value(arg_list[0]);
12898 }
12899
12900 template <typename Sequence>
12901 static inline T process_2(const Sequence& arg_list)
12902 {
12903 value(arg_list[0]);
12904 return value(arg_list[1]);
12905 }
12906
12907 template <typename Sequence>
12908 static inline T process_3(const Sequence& arg_list)
12909 {
12910 value(arg_list[0]);
12911 value(arg_list[1]);
12912 return value(arg_list[2]);
12913 }
12914
12915 template <typename Sequence>
12916 static inline T process_4(const Sequence& arg_list)
12917 {
12918 value(arg_list[0]);
12919 value(arg_list[1]);
12920 value(arg_list[2]);
12921 return value(arg_list[3]);
12922 }
12923
12924 template <typename Sequence>
12925 static inline T process_5(const Sequence& arg_list)
12926 {
12927 value(arg_list[0]);
12928 value(arg_list[1]);
12929 value(arg_list[2]);
12930 value(arg_list[3]);
12931 return value(arg_list[4]);
12932 }
12933
12934 template <typename Sequence>
12935 static inline T process_6(const Sequence& arg_list)
12936 {
12937 value(arg_list[0]);
12938 value(arg_list[1]);
12939 value(arg_list[2]);
12940 value(arg_list[3]);
12941 value(arg_list[4]);
12942 return value(arg_list[5]);
12943 }
12944
12945 template <typename Sequence>
12946 static inline T process_7(const Sequence& arg_list)
12947 {
12948 value(arg_list[0]);
12949 value(arg_list[1]);
12950 value(arg_list[2]);
12951 value(arg_list[3]);
12952 value(arg_list[4]);
12953 value(arg_list[5]);
12954 return value(arg_list[6]);
12955 }
12956
12957 template <typename Sequence>
12958 static inline T process_8(const Sequence& arg_list)
12959 {
12960 value(arg_list[0]);
12961 value(arg_list[1]);
12962 value(arg_list[2]);
12963 value(arg_list[3]);
12964 value(arg_list[4]);
12965 value(arg_list[5]);
12966 value(arg_list[6]);
12967 return value(arg_list[7]);
12968 }
12969 };
12970
12971 template <typename T>
12972 struct vec_add_op
12973 {
12974 typedef vector_interface<T>* ivector_ptr;
12975
12976 static inline T process(const ivector_ptr v)
12977 {
12978 const T* vec = v->vec()->vds().data();
12979 const std::size_t vec_size = v->vec()->vds().size();
12980
12981 loop_unroll::details lud(vec_size);
12982
12983 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
12984 {
12985 T result = T(0);
12986 int i = 0;
12987
12988 exprtk_disable_fallthrough_begin
12989 switch (vec_size)
12990 {
12991 #define case_stmt(N) \
12992 case N : result += vec[i++]; \
12993
12994 #ifndef exprtk_disable_superscalar_unroll
12995 case_stmt(16) case_stmt(15)
12996 case_stmt(14) case_stmt(13)
12997 case_stmt(12) case_stmt(11)
12998 case_stmt(10) case_stmt( 9)
12999 case_stmt( 8) case_stmt( 7)
13000 case_stmt( 6) case_stmt( 5)
13001 #endif
13002 case_stmt( 4) case_stmt( 3)
13003 case_stmt( 2) case_stmt( 1)
13004 }
13005 exprtk_disable_fallthrough_end
13006
13007 #undef case_stmt
13008
13009 return result;
13010 }
13011
13012 T r[] = {
13013 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
13014 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
13015 };
13016
13017 const T* upper_bound = vec + lud.upper_bound;
13018
13019 while (vec < upper_bound)
13020 {
13021 #define exprtk_loop(N) \
13022 r[N] += vec[N]; \
13023
13024 exprtk_loop( 0) exprtk_loop( 1)
13025 exprtk_loop( 2) exprtk_loop( 3)
13026 #ifndef exprtk_disable_superscalar_unroll
13027 exprtk_loop( 4) exprtk_loop( 5)
13028 exprtk_loop( 6) exprtk_loop( 7)
13029 exprtk_loop( 8) exprtk_loop( 9)
13030 exprtk_loop(10) exprtk_loop(11)
13031 exprtk_loop(12) exprtk_loop(13)
13032 exprtk_loop(14) exprtk_loop(15)
13033 #endif
13034
13035 vec += lud.batch_size;
13036 }
13037
13038 int i = 0;
13039
13040 exprtk_disable_fallthrough_begin
13041 switch (lud.remainder)
13042 {
13043 #define case_stmt(N) \
13044 case N : r[0] += vec[i++]; \
13045
13046 #ifndef exprtk_disable_superscalar_unroll
13047 case_stmt(15) case_stmt(14)
13048 case_stmt(13) case_stmt(12)
13049 case_stmt(11) case_stmt(10)
13050 case_stmt( 9) case_stmt( 8)
13051 case_stmt( 7) case_stmt( 6)
13052 case_stmt( 5) case_stmt( 4)
13053 #endif
13054 case_stmt( 3) case_stmt( 2)
13055 case_stmt( 1)
13056 }
13057 exprtk_disable_fallthrough_end
13058
13059 #undef exprtk_loop
13060 #undef case_stmt
13061
13062 return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13063 #ifndef exprtk_disable_superscalar_unroll
13064 + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13065 + (r[ 8] + r[ 9] + r[10] + r[11])
13066 + (r[12] + r[13] + r[14] + r[15])
13067 #endif
13068 ;
13069 }
13070 };
13071
13072 template <typename T>
13073 struct vec_mul_op
13074 {
13075 typedef vector_interface<T>* ivector_ptr;
13076
13077 static inline T process(const ivector_ptr v)
13078 {
13079 const T* vec = v->vec()->vds().data();
13080 const std::size_t vec_size = v->vec()->vds().size();
13081
13082 loop_unroll::details lud(vec_size);
13083
13084 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13085 {
13086 T result = T(1);
13087 int i = 0;
13088
13089 exprtk_disable_fallthrough_begin
13090 switch (vec_size)
13091 {
13092 #define case_stmt(N) \
13093 case N : result *= vec[i++]; \
13094
13095 #ifndef exprtk_disable_superscalar_unroll
13096 case_stmt(16) case_stmt(15)
13097 case_stmt(14) case_stmt(13)
13098 case_stmt(12) case_stmt(11)
13099 case_stmt(10) case_stmt( 9)
13100 case_stmt( 8) case_stmt( 7)
13101 case_stmt( 6) case_stmt( 5)
13102 #endif
13103 case_stmt( 4) case_stmt( 3)
13104 case_stmt( 2) case_stmt( 1)
13105 }
13106 exprtk_disable_fallthrough_end
13107
13108 #undef case_stmt
13109
13110 return result;
13111 }
13112
13113 T r[] = {
13114 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13115 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13116 };
13117
13118 const T* upper_bound = vec + lud.upper_bound;
13119
13120 while (vec < upper_bound)
13121 {
13122 #define exprtk_loop(N) \
13123 r[N] *= vec[N]; \
13124
13125 exprtk_loop( 0) exprtk_loop( 1)
13126 exprtk_loop( 2) exprtk_loop( 3)
13127 #ifndef exprtk_disable_superscalar_unroll
13128 exprtk_loop( 4) exprtk_loop( 5)
13129 exprtk_loop( 6) exprtk_loop( 7)
13130 exprtk_loop( 8) exprtk_loop( 9)
13131 exprtk_loop(10) exprtk_loop(11)
13132 exprtk_loop(12) exprtk_loop(13)
13133 exprtk_loop(14) exprtk_loop(15)
13134 #endif
13135
13136 vec += lud.batch_size;
13137 }
13138
13139 int i = 0;
13140
13141 exprtk_disable_fallthrough_begin
13142 switch (lud.remainder)
13143 {
13144 #define case_stmt(N) \
13145 case N : r[0] *= vec[i++]; \
13146
13147 #ifndef exprtk_disable_superscalar_unroll
13148 case_stmt(15) case_stmt(14)
13149 case_stmt(13) case_stmt(12)
13150 case_stmt(11) case_stmt(10)
13151 case_stmt( 9) case_stmt( 8)
13152 case_stmt( 7) case_stmt( 6)
13153 case_stmt( 5) case_stmt( 4)
13154 #endif
13155 case_stmt( 3) case_stmt( 2)
13156 case_stmt( 1)
13157 }
13158 exprtk_disable_fallthrough_end
13159
13160 #undef exprtk_loop
13161 #undef case_stmt
13162
13163 return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13164 #ifndef exprtk_disable_superscalar_unroll
13165 + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13166 + (r[ 8] * r[ 9] * r[10] * r[11])
13167 + (r[12] * r[13] * r[14] * r[15])
13168 #endif
13169 ;
13170 }
13171 };
13172
13173 template <typename T>
13174 struct vec_avg_op
13175 {
13176 typedef vector_interface<T>* ivector_ptr;
13177
13178 static inline T process(const ivector_ptr v)
13179 {
13180 const std::size_t vec_size = v->vec()->vds().size();
13181
13182 return vec_add_op<T>::process(v) / vec_size;
13183 }
13184 };
13185
13186 template <typename T>
13187 struct vec_min_op
13188 {
13189 typedef vector_interface<T>* ivector_ptr;
13190
13191 static inline T process(const ivector_ptr v)
13192 {
13193 const T* vec = v->vec()->vds().data();
13194 const std::size_t vec_size = v->vec()->vds().size();
13195
13196 T result = vec[0];
13197
13198 for (std::size_t i = 1; i < vec_size; ++i)
13199 {
13200 T v_i = vec[i];
13201
13202 if (v_i < result)
13203 result = v_i;
13204 }
13205
13206 return result;
13207 }
13208 };
13209
13210 template <typename T>
13211 struct vec_max_op
13212 {
13213 typedef vector_interface<T>* ivector_ptr;
13214
13215 static inline T process(const ivector_ptr v)
13216 {
13217 const T* vec = v->vec()->vds().data();
13218 const std::size_t vec_size = v->vec()->vds().size();
13219
13220 T result = vec[0];
13221
13222 for (std::size_t i = 1; i < vec_size; ++i)
13223 {
13224 T v_i = vec[i];
13225
13226 if (v_i > result)
13227 result = v_i;
13228 }
13229
13230 return result;
13231 }
13232 };
13233
13234 template <typename T>
13235 class vov_base_node : public expression_node<T>
13236 {
13237 public:
13238
13239 virtual ~vov_base_node()
13240 {}
13241
13242 inline virtual operator_type operation() const
13243 {
13244 return details::e_default;
13245 }
13246
13247 virtual const T& v0() const = 0;
13248
13249 virtual const T& v1() const = 0;
13250 };
13251
13252 template <typename T>
13253 class cov_base_node : public expression_node<T>
13254 {
13255 public:
13256
13257 virtual ~cov_base_node()
13258 {}
13259
13260 inline virtual operator_type operation() const
13261 {
13262 return details::e_default;
13263 }
13264
13265 virtual const T c() const = 0;
13266
13267 virtual const T& v() const = 0;
13268 };
13269
13270 template <typename T>
13271 class voc_base_node : public expression_node<T>
13272 {
13273 public:
13274
13275 virtual ~voc_base_node()
13276 {}
13277
13278 inline virtual operator_type operation() const
13279 {
13280 return details::e_default;
13281 }
13282
13283 virtual const T c() const = 0;
13284
13285 virtual const T& v() const = 0;
13286 };
13287
13288 template <typename T>
13289 class vob_base_node : public expression_node<T>
13290 {
13291 public:
13292
13293 virtual ~vob_base_node()
13294 {}
13295
13296 virtual const T& v() const = 0;
13297 };
13298
13299 template <typename T>
13300 class bov_base_node : public expression_node<T>
13301 {
13302 public:
13303
13304 virtual ~bov_base_node()
13305 {}
13306
13307 virtual const T& v() const = 0;
13308 };
13309
13310 template <typename T>
13311 class cob_base_node : public expression_node<T>
13312 {
13313 public:
13314
13315 virtual ~cob_base_node()
13316 {}
13317
13318 inline virtual operator_type operation() const
13319 {
13320 return details::e_default;
13321 }
13322
13323 virtual const T c() const = 0;
13324
13325 virtual void set_c(const T) = 0;
13326
13327 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13328 };
13329
13330 template <typename T>
13331 class boc_base_node : public expression_node<T>
13332 {
13333 public:
13334
13335 virtual ~boc_base_node()
13336 {}
13337
13338 inline virtual operator_type operation() const
13339 {
13340 return details::e_default;
13341 }
13342
13343 virtual const T c() const = 0;
13344
13345 virtual void set_c(const T) = 0;
13346
13347 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13348 };
13349
13350 template <typename T>
13351 class uv_base_node : public expression_node<T>
13352 {
13353 public:
13354
13355 virtual ~uv_base_node()
13356 {}
13357
13358 inline virtual operator_type operation() const
13359 {
13360 return details::e_default;
13361 }
13362
13363 virtual const T& v() const = 0;
13364 };
13365
13366 template <typename T>
13367 class sos_base_node : public expression_node<T>
13368 {
13369 public:
13370
13371 virtual ~sos_base_node()
13372 {}
13373
13374 inline virtual operator_type operation() const
13375 {
13376 return details::e_default;
13377 }
13378 };
13379
13380 template <typename T>
13381 class sosos_base_node : public expression_node<T>
13382 {
13383 public:
13384
13385 virtual ~sosos_base_node()
13386 {}
13387
13388 inline virtual operator_type operation() const
13389 {
13390 return details::e_default;
13391 }
13392 };
13393
13394 template <typename T>
13395 class T0oT1oT2_base_node : public expression_node<T>
13396 {
13397 public:
13398
13399 virtual ~T0oT1oT2_base_node()
13400 {}
13401
13402 virtual std::string type_id() const = 0;
13403 };
13404
13405 template <typename T>
13406 class T0oT1oT2oT3_base_node : public expression_node<T>
13407 {
13408 public:
13409
13410 virtual ~T0oT1oT2oT3_base_node()
13411 {}
13412
13413 virtual std::string type_id() const = 0;
13414 };
13415
13416 template <typename T, typename Operation>
13417 class unary_variable_node : public uv_base_node<T>
13418 {
13419 public:
13420
13421 typedef expression_node<T>* expression_ptr;
13422 typedef Operation operation_t;
13423
13424 explicit unary_variable_node(const T& var)
13425 : v_(var)
13426 {}
13427
13428 inline T value() const
13429 {
13430 return Operation::process(v_);
13431 }
13432
13433 inline typename expression_node<T>::node_type type() const
13434 {
13435 return Operation::type();
13436 }
13437
13438 inline operator_type operation() const
13439 {
13440 return Operation::operation();
13441 }
13442
13443 inline const T& v() const
13444 {
13445 return v_;
13446 }
13447
13448 private:
13449
13450 unary_variable_node(unary_variable_node<T,Operation>&);
13451 unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
13452
13453 const T& v_;
13454 };
13455
13456 template <typename T>
13457 class uvouv_node : public expression_node<T>
13458 {
13459 public:
13460
13461 // UOpr1(v0) Op UOpr2(v1)
13462
13463 typedef expression_node<T>* expression_ptr;
13464 typedef typename details::functor_t<T> functor_t;
13465 typedef typename functor_t::bfunc_t bfunc_t;
13466 typedef typename functor_t::ufunc_t ufunc_t;
13467
13468 explicit uvouv_node(const T& var0,const T& var1,
13469 ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
13470 : v0_(var0),
13471 v1_(var1),
13472 u0_(uf0 ),
13473 u1_(uf1 ),
13474 f_ (bf )
13475 {}
13476
13477 inline T value() const
13478 {
13479 return f_(u0_(v0_),u1_(v1_));
13480 }
13481
13482 inline typename expression_node<T>::node_type type() const
13483 {
13484 return expression_node<T>::e_uvouv;
13485 }
13486
13487 inline operator_type operation() const
13488 {
13489 return details::e_default;
13490 }
13491
13492 inline const T& v0()
13493 {
13494 return v0_;
13495 }
13496
13497 inline const T& v1()
13498 {
13499 return v1_;
13500 }
13501
13502 inline ufunc_t u0()
13503 {
13504 return u0_;
13505 }
13506
13507 inline ufunc_t u1()
13508 {
13509 return u1_;
13510 }
13511
13512 inline ufunc_t f()
13513 {
13514 return f_;
13515 }
13516
13517 private:
13518
13519 uvouv_node(uvouv_node<T>&);
13520 uvouv_node<T>& operator=(uvouv_node<T>&);
13521
13522 const T& v0_;
13523 const T& v1_;
13524 const ufunc_t u0_;
13525 const ufunc_t u1_;
13526 const bfunc_t f_;
13527 };
13528
13529 template <typename T, typename Operation>
13530 class unary_branch_node : public expression_node<T>
13531 {
13532 public:
13533
13534 typedef expression_node<T>* expression_ptr;
13535 typedef Operation operation_t;
13536
13537 explicit unary_branch_node(expression_ptr brnch)
13538 : branch_(brnch),
13539 branch_deletable_(branch_deletable(branch_))
13540 {}
13541
13542 ~unary_branch_node()
13543 {
13544 if (branch_ && branch_deletable_)
13545 {
13546 destroy_node(branch_);
13547 }
13548 }
13549
13550 inline T value() const
13551 {
13552 return Operation::process(branch_->value());
13553 }
13554
13555 inline typename expression_node<T>::node_type type() const
13556 {
13557 return Operation::type();
13558 }
13559
13560 inline operator_type operation() const
13561 {
13562 return Operation::operation();
13563 }
13564
13565 inline expression_node<T>* branch(const std::size_t&) const
13566 {
13567 return branch_;
13568 }
13569
13570 inline void release()
13571 {
13572 branch_deletable_ = false;
13573 }
13574
13575 private:
13576
13577 unary_branch_node(unary_branch_node<T,Operation>&);
13578 unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
13579
13580 expression_ptr branch_;
13581 bool branch_deletable_;
13582 };
13583
13584 template <typename T> struct is_const { enum {result = 0}; };
13585 template <typename T> struct is_const <const T> { enum {result = 1}; };
13586 template <typename T> struct is_const_ref { enum {result = 0}; };
13587 template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
13588 template <typename T> struct is_ref { enum {result = 0}; };
13589 template <typename T> struct is_ref<T&> { enum {result = 1}; };
13590 template <typename T> struct is_ref<const T&> { enum {result = 0}; };
13591
13592 template <std::size_t State>
13593 struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
13594
13595 template <>
13596 struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
13597
13598 #define exprtk_crtype(Type) \
13599 param_to_str<is_const_ref< Type >::result>::result() \
13600
13601 template <typename T>
13602 struct T0oT1oT2process
13603 {
13604 typedef typename details::functor_t<T> functor_t;
13605 typedef typename functor_t::bfunc_t bfunc_t;
13606
13607 struct mode0
13608 {
13609 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13610 {
13611 // (T0 o0 T1) o1 T2
13612 return bf1(bf0(t0,t1),t2);
13613 }
13614
13615 template <typename T0, typename T1, typename T2>
13616 static inline std::string id()
13617 {
13618 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13619 exprtk_crtype(T1) + ")o(" +
13620 exprtk_crtype(T2) + ")" ;
13621 return result;
13622 }
13623 };
13624
13625 struct mode1
13626 {
13627 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13628 {
13629 // T0 o0 (T1 o1 T2)
13630 return bf0(t0,bf1(t1,t2));
13631 }
13632
13633 template <typename T0, typename T1, typename T2>
13634 static inline std::string id()
13635 {
13636 static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
13637 exprtk_crtype(T1) + "o" +
13638 exprtk_crtype(T2) + ")" ;
13639 return result;
13640 }
13641 };
13642 };
13643
13644 template <typename T>
13645 struct T0oT1oT20T3process
13646 {
13647 typedef typename details::functor_t<T> functor_t;
13648 typedef typename functor_t::bfunc_t bfunc_t;
13649
13650 struct mode0
13651 {
13652 static inline T process(const T& t0, const T& t1,
13653 const T& t2, const T& t3,
13654 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13655 {
13656 // (T0 o0 T1) o1 (T2 o2 T3)
13657 return bf1(bf0(t0,t1),bf2(t2,t3));
13658 }
13659
13660 template <typename T0, typename T1, typename T2, typename T3>
13661 static inline std::string id()
13662 {
13663 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13664 exprtk_crtype(T1) + ")o" +
13665 "(" + exprtk_crtype(T2) + "o" +
13666 exprtk_crtype(T3) + ")" ;
13667 return result;
13668 }
13669 };
13670
13671 struct mode1
13672 {
13673 static inline T process(const T& t0, const T& t1,
13674 const T& t2, const T& t3,
13675 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13676 {
13677 // (T0 o0 (T1 o1 (T2 o2 T3))
13678 return bf0(t0,bf1(t1,bf2(t2,t3)));
13679 }
13680 template <typename T0, typename T1, typename T2, typename T3>
13681 static inline std::string id()
13682 {
13683 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13684 exprtk_crtype(T1) + ")o(" +
13685 exprtk_crtype(T2) + "o" +
13686 exprtk_crtype(T3) + "))" ;
13687 return result;
13688 }
13689 };
13690
13691 struct mode2
13692 {
13693 static inline T process(const T& t0, const T& t1,
13694 const T& t2, const T& t3,
13695 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13696 {
13697 // (T0 o0 ((T1 o1 T2) o2 T3)
13698 return bf0(t0,bf2(bf1(t1,t2),t3));
13699 }
13700
13701 template <typename T0, typename T1, typename T2, typename T3>
13702 static inline std::string id()
13703 {
13704 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13705 exprtk_crtype(T1) + "o" +
13706 exprtk_crtype(T2) + ")o(" +
13707 exprtk_crtype(T3) + "))" ;
13708 return result;
13709 }
13710 };
13711
13712 struct mode3
13713 {
13714 static inline T process(const T& t0, const T& t1,
13715 const T& t2, const T& t3,
13716 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13717 {
13718 // (((T0 o0 T1) o1 T2) o2 T3)
13719 return bf2(bf1(bf0(t0,t1),t2),t3);
13720 }
13721
13722 template <typename T0, typename T1, typename T2, typename T3>
13723 static inline std::string id()
13724 {
13725 static const std::string result = "((" + exprtk_crtype(T0) + "o" +
13726 exprtk_crtype(T1) + ")o(" +
13727 exprtk_crtype(T2) + "))o(" +
13728 exprtk_crtype(T3) + ")";
13729 return result;
13730 }
13731 };
13732
13733 struct mode4
13734 {
13735 static inline T process(const T& t0, const T& t1,
13736 const T& t2, const T& t3,
13737 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13738 {
13739 // ((T0 o0 (T1 o1 T2)) o2 T3
13740 return bf2(bf0(t0,bf1(t1,t2)),t3);
13741 }
13742
13743 template <typename T0, typename T1, typename T2, typename T3>
13744 static inline std::string id()
13745 {
13746 static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
13747 exprtk_crtype(T1) + "o" +
13748 exprtk_crtype(T2) + "))o(" +
13749 exprtk_crtype(T3) + ")" ;
13750 return result;
13751 }
13752 };
13753 };
13754
13755 #undef exprtk_crtype
13756
13757 template <typename T, typename T0, typename T1>
13758 struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
13759 template <typename T, typename T0, typename T1>
13760 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
13761
13762 #define synthesis_node_type_define(T0_,T1_,v_) \
13763 template <typename T, typename T0, typename T1> \
13764 struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
13765 template <typename T, typename T0, typename T1> \
13766 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
13767
13768 synthesis_node_type_define(const T0&, const T1&, e_vov)
13769 synthesis_node_type_define(const T0&, const T1 , e_voc)
13770 synthesis_node_type_define(const T0 , const T1&, e_cov)
13771 synthesis_node_type_define( T0&, T1&, e_none)
13772 synthesis_node_type_define(const T0 , const T1 , e_none)
13773 synthesis_node_type_define( T0&, const T1 , e_none)
13774 synthesis_node_type_define(const T0 , T1&, e_none)
13775 synthesis_node_type_define(const T0&, T1&, e_none)
13776 synthesis_node_type_define( T0&, const T1&, e_none)
13777 #undef synthesis_node_type_define
13778
13779 template <typename T, typename T0, typename T1, typename T2>
13780 struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
13781 template <typename T, typename T0, typename T1, typename T2>
13782 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
13783
13784 #define synthesis_node_type_define(T0_,T1_,T2_,v_) \
13785 template <typename T, typename T0, typename T1, typename T2> \
13786 struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
13787 template <typename T, typename T0, typename T1, typename T2> \
13788 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
13789
13790 synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
13791 synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
13792 synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
13793 synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
13794 synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
13795 synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
13796 synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
13797 synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
13798 synthesis_node_type_define( T0&, T1&, T2&, e_none )
13799 #undef synthesis_node_type_define
13800
13801 template <typename T, typename T0, typename T1, typename T2, typename T3>
13802 struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
13803 template <typename T, typename T0, typename T1, typename T2, typename T3>
13804 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
13805
13806 #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \
13807 template <typename T, typename T0, typename T1, typename T2, typename T3> \
13808 struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
13809 template <typename T, typename T0, typename T1, typename T2, typename T3> \
13810 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
13811
13812 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
13813 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
13814 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
13815 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
13816 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
13817 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
13818 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
13819 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
13820 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
13821 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
13822 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
13823 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
13824 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
13825 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
13826 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
13827 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
13828 #undef synthesis_node_type_define
13829
13830 template <typename T, typename T0, typename T1>
13831 class T0oT1 : public expression_node<T>
13832 {
13833 public:
13834
13835 typedef typename details::functor_t<T> functor_t;
13836 typedef typename functor_t::bfunc_t bfunc_t;
13837 typedef T value_type;
13838 typedef T0oT1<T,T0,T1> node_type;
13839
13840 T0oT1(T0 p0, T1 p1, const bfunc_t p2)
13841 : t0_(p0),
13842 t1_(p1),
13843 f_ (p2)
13844 {}
13845
13846 inline typename expression_node<T>::node_type type() const
13847 {
13848 static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
13849 return result;
13850 }
13851
13852 inline operator_type operation() const
13853 {
13854 return e_default;
13855 }
13856
13857 inline T value() const
13858 {
13859 return f_(t0_,t1_);
13860 }
13861
13862 inline T0 t0() const
13863 {
13864 return t0_;
13865 }
13866
13867 inline T1 t1() const
13868 {
13869 return t1_;
13870 }
13871
13872 inline bfunc_t f() const
13873 {
13874 return f_;
13875 }
13876
13877 template <typename Allocator>
13878 static inline expression_node<T>* allocate(Allocator& allocator,
13879 T0 p0, T1 p1,
13880 bfunc_t p2)
13881 {
13882 return allocator
13883 .template allocate_type<node_type, T0, T1, bfunc_t&>
13884 (p0, p1, p2);
13885 }
13886
13887 private:
13888
13889 T0oT1(T0oT1<T,T0,T1>&) {}
13890 T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
13891
13892 T0 t0_;
13893 T1 t1_;
13894 const bfunc_t f_;
13895 };
13896
13897 template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
13898 class T0oT1oT2 : public T0oT1oT2_base_node<T>
13899 {
13900 public:
13901
13902 typedef typename details::functor_t<T> functor_t;
13903 typedef typename functor_t::bfunc_t bfunc_t;
13904 typedef T value_type;
13905 typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
13906 typedef ProcessMode process_mode_t;
13907
13908 T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
13909 : t0_(p0),
13910 t1_(p1),
13911 t2_(p2),
13912 f0_(p3),
13913 f1_(p4)
13914 {}
13915
13916 inline typename expression_node<T>::node_type type() const
13917 {
13918 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
13919 return result;
13920 }
13921
13922 inline operator_type operation() const
13923 {
13924 return e_default;
13925 }
13926
13927 inline T value() const
13928 {
13929 return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
13930 }
13931
13932 inline T0 t0() const
13933 {
13934 return t0_;
13935 }
13936
13937 inline T1 t1() const
13938 {
13939 return t1_;
13940 }
13941
13942 inline T2 t2() const
13943 {
13944 return t2_;
13945 }
13946
13947 bfunc_t f0() const
13948 {
13949 return f0_;
13950 }
13951
13952 bfunc_t f1() const
13953 {
13954 return f1_;
13955 }
13956
13957 std::string type_id() const
13958 {
13959 return id();
13960 }
13961
13962 static inline std::string id()
13963 {
13964 return process_mode_t::template id<T0,T1,T2>();
13965 }
13966
13967 template <typename Allocator>
13968 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
13969 {
13970 return allocator
13971 .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
13972 (p0, p1, p2, p3, p4);
13973 }
13974
13975 private:
13976
13977 T0oT1oT2(node_type&) {}
13978 node_type& operator=(node_type&) { return (*this); }
13979
13980 T0 t0_;
13981 T1 t1_;
13982 T2 t2_;
13983 const bfunc_t f0_;
13984 const bfunc_t f1_;
13985 };
13986
13987 template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
13988 class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
13989 {
13990 public:
13991
13992 typedef typename details::functor_t<T> functor_t;
13993 typedef typename functor_t::bfunc_t bfunc_t;
13994 typedef T value_type;
13995 typedef T0_ T0;
13996 typedef T1_ T1;
13997 typedef T2_ T2;
13998 typedef T3_ T3;
13999 typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
14000 typedef ProcessMode process_mode_t;
14001
14002 T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
14003 : t0_(p0),
14004 t1_(p1),
14005 t2_(p2),
14006 t3_(p3),
14007 f0_(p4),
14008 f1_(p5),
14009 f2_(p6)
14010 {}
14011
14012 inline T value() const
14013 {
14014 return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
14015 }
14016
14017 inline T0 t0() const
14018 {
14019 return t0_;
14020 }
14021
14022 inline T1 t1() const
14023 {
14024 return t1_;
14025 }
14026
14027 inline T2 t2() const
14028 {
14029 return t2_;
14030 }
14031
14032 inline T3 t3() const
14033 {
14034 return t3_;
14035 }
14036
14037 inline bfunc_t f0() const
14038 {
14039 return f0_;
14040 }
14041
14042 inline bfunc_t f1() const
14043 {
14044 return f1_;
14045 }
14046
14047 inline bfunc_t f2() const
14048 {
14049 return f2_;
14050 }
14051
14052 inline std::string type_id() const
14053 {
14054 return id();
14055 }
14056
14057 static inline std::string id()
14058 {
14059 return process_mode_t::template id<T0, T1, T2, T3>();
14060 }
14061
14062 template <typename Allocator>
14063 static inline expression_node<T>* allocate(Allocator& allocator,
14064 T0 p0, T1 p1, T2 p2, T3 p3,
14065 bfunc_t p4, bfunc_t p5, bfunc_t p6)
14066 {
14067 return allocator
14068 .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14069 (p0, p1, p2, p3, p4, p5, p6);
14070 }
14071
14072 private:
14073
14074 T0oT1oT2oT3(node_type&) {}
14075 node_type& operator=(node_type&) { return (*this); }
14076
14077 T0 t0_;
14078 T1 t1_;
14079 T2 t2_;
14080 T3 t3_;
14081 const bfunc_t f0_;
14082 const bfunc_t f1_;
14083 const bfunc_t f2_;
14084 };
14085
14086 template <typename T, typename T0, typename T1, typename T2>
14087 class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
14088 {
14089 public:
14090
14091 typedef typename details::functor_t<T> functor_t;
14092 typedef typename functor_t::tfunc_t tfunc_t;
14093 typedef T value_type;
14094 typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
14095
14096 T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14097 : t0_(p0),
14098 t1_(p1),
14099 t2_(p2),
14100 f_ (p3)
14101 {}
14102
14103 inline typename expression_node<T>::node_type type() const
14104 {
14105 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14106 return result;
14107 }
14108
14109 inline operator_type operation() const
14110 {
14111 return e_default;
14112 }
14113
14114 inline T value() const
14115 {
14116 return f_(t0_, t1_, t2_);
14117 }
14118
14119 inline T0 t0() const
14120 {
14121 return t0_;
14122 }
14123
14124 inline T1 t1() const
14125 {
14126 return t1_;
14127 }
14128
14129 inline T2 t2() const
14130 {
14131 return t2_;
14132 }
14133
14134 tfunc_t f() const
14135 {
14136 return f_;
14137 }
14138
14139 std::string type_id() const
14140 {
14141 return id();
14142 }
14143
14144 static inline std::string id()
14145 {
14146 return "sf3";
14147 }
14148
14149 template <typename Allocator>
14150 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14151 {
14152 return allocator
14153 .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14154 (p0, p1, p2, p3);
14155 }
14156
14157 private:
14158
14159 T0oT1oT2_sf3(node_type&) {}
14160 node_type& operator=(node_type&) { return (*this); }
14161
14162 T0 t0_;
14163 T1 t1_;
14164 T2 t2_;
14165 const tfunc_t f_;
14166 };
14167
14168 template <typename T, typename T0, typename T1, typename T2>
14169 class sf3ext_type_node : public T0oT1oT2_base_node<T>
14170 {
14171 public:
14172
14173 virtual ~sf3ext_type_node()
14174 {}
14175
14176 virtual T0 t0() const = 0;
14177
14178 virtual T1 t1() const = 0;
14179
14180 virtual T2 t2() const = 0;
14181 };
14182
14183 template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14184 class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14185 {
14186 public:
14187
14188 typedef typename details::functor_t<T> functor_t;
14189 typedef typename functor_t::tfunc_t tfunc_t;
14190 typedef T value_type;
14191 typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
14192
14193 T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
14194 : t0_(p0),
14195 t1_(p1),
14196 t2_(p2)
14197 {}
14198
14199 inline typename expression_node<T>::node_type type() const
14200 {
14201 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14202 return result;
14203 }
14204
14205 inline operator_type operation() const
14206 {
14207 return e_default;
14208 }
14209
14210 inline T value() const
14211 {
14212 return SF3Operation::process(t0_, t1_, t2_);
14213 }
14214
14215 T0 t0() const
14216 {
14217 return t0_;
14218 }
14219
14220 T1 t1() const
14221 {
14222 return t1_;
14223 }
14224
14225 T2 t2() const
14226 {
14227 return t2_;
14228 }
14229
14230 std::string type_id() const
14231 {
14232 return id();
14233 }
14234
14235 static inline std::string id()
14236 {
14237 return SF3Operation::id();
14238 }
14239
14240 template <typename Allocator>
14241 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14242 {
14243 return allocator
14244 .template allocate_type<node_type, T0, T1, T2>
14245 (p0, p1, p2);
14246 }
14247
14248 private:
14249
14250 T0oT1oT2_sf3ext(node_type&) {}
14251 node_type& operator=(node_type&) { return (*this); }
14252
14253 T0 t0_;
14254 T1 t1_;
14255 T2 t2_;
14256 };
14257
14258 template <typename T>
14259 inline bool is_sf3ext_node(const expression_node<T>* n)
14260 {
14261 switch (n->type())
14262 {
14263 case expression_node<T>::e_vovov : return true;
14264 case expression_node<T>::e_vovoc : return true;
14265 case expression_node<T>::e_vocov : return true;
14266 case expression_node<T>::e_covov : return true;
14267 case expression_node<T>::e_covoc : return true;
14268 default : return false;
14269 }
14270 }
14271
14272 template <typename T, typename T0, typename T1, typename T2, typename T3>
14273 class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
14274 {
14275 public:
14276
14277 typedef typename details::functor_t<T> functor_t;
14278 typedef typename functor_t::qfunc_t qfunc_t;
14279 typedef T value_type;
14280 typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
14281
14282 T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14283 : t0_(p0),
14284 t1_(p1),
14285 t2_(p2),
14286 t3_(p3),
14287 f_ (p4)
14288 {}
14289
14290 inline typename expression_node<T>::node_type type() const
14291 {
14292 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14293 return result;
14294 }
14295
14296 inline operator_type operation() const
14297 {
14298 return e_default;
14299 }
14300
14301 inline T value() const
14302 {
14303 return f_(t0_, t1_, t2_, t3_);
14304 }
14305
14306 inline T0 t0() const
14307 {
14308 return t0_;
14309 }
14310
14311 inline T1 t1() const
14312 {
14313 return t1_;
14314 }
14315
14316 inline T2 t2() const
14317 {
14318 return t2_;
14319 }
14320
14321 inline T3 t3() const
14322 {
14323 return t3_;
14324 }
14325
14326 qfunc_t f() const
14327 {
14328 return f_;
14329 }
14330
14331 std::string type_id() const
14332 {
14333 return id();
14334 }
14335
14336 static inline std::string id()
14337 {
14338 return "sf4";
14339 }
14340
14341 template <typename Allocator>
14342 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14343 {
14344 return allocator
14345 .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14346 (p0, p1, p2, p3, p4);
14347 }
14348
14349 private:
14350
14351 T0oT1oT2oT3_sf4(node_type&) {}
14352 node_type& operator=(node_type&) { return (*this); }
14353
14354 T0 t0_;
14355 T1 t1_;
14356 T2 t2_;
14357 T3 t3_;
14358 const qfunc_t f_;
14359 };
14360
14361 template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14362 class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
14363 {
14364 public:
14365
14366 typedef typename details::functor_t<T> functor_t;
14367 typedef typename functor_t::tfunc_t tfunc_t;
14368 typedef T value_type;
14369 typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
14370
14371 T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14372 : t0_(p0),
14373 t1_(p1),
14374 t2_(p2),
14375 t3_(p3)
14376 {}
14377
14378 inline typename expression_node<T>::node_type type() const
14379 {
14380 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14381 return result;
14382 }
14383
14384 inline operator_type operation() const
14385 {
14386 return e_default;
14387 }
14388
14389 inline T value() const
14390 {
14391 return SF4Operation::process(t0_, t1_, t2_, t3_);
14392 }
14393
14394 inline T0 t0() const
14395 {
14396 return t0_;
14397 }
14398
14399 inline T1 t1() const
14400 {
14401 return t1_;
14402 }
14403
14404 inline T2 t2() const
14405 {
14406 return t2_;
14407 }
14408
14409 inline T3 t3() const
14410 {
14411 return t3_;
14412 }
14413
14414 std::string type_id() const
14415 {
14416 return id();
14417 }
14418
14419 static inline std::string id()
14420 {
14421 return SF4Operation::id();
14422 }
14423
14424 template <typename Allocator>
14425 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
14426 {
14427 return allocator
14428 .template allocate_type<node_type, T0, T1, T2, T3>
14429 (p0, p1, p2, p3);
14430 }
14431
14432 private:
14433
14434 T0oT1oT2oT3_sf4ext(node_type&) {}
14435 node_type& operator=(node_type&) { return (*this); }
14436
14437 T0 t0_;
14438 T1 t1_;
14439 T2 t2_;
14440 T3 t3_;
14441 };
14442
14443 template <typename T>
14444 inline bool is_sf4ext_node(const expression_node<T>* n)
14445 {
14446 switch (n->type())
14447 {
14448 case expression_node<T>::e_vovovov : return true;
14449 case expression_node<T>::e_vovovoc : return true;
14450 case expression_node<T>::e_vovocov : return true;
14451 case expression_node<T>::e_vocovov : return true;
14452 case expression_node<T>::e_covovov : return true;
14453 case expression_node<T>::e_covocov : return true;
14454 case expression_node<T>::e_vocovoc : return true;
14455 case expression_node<T>::e_covovoc : return true;
14456 case expression_node<T>::e_vococov : return true;
14457 default : return false;
14458 }
14459 }
14460
14461 template <typename T, typename T0, typename T1>
14462 struct T0oT1_define
14463 {
14464 typedef details::T0oT1<T, T0, T1> type0;
14465 };
14466
14467 template <typename T, typename T0, typename T1, typename T2>
14468 struct T0oT1oT2_define
14469 {
14470 typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
14471 typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
14472 typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
14473 typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
14474 };
14475
14476 template <typename T, typename T0, typename T1, typename T2, typename T3>
14477 struct T0oT1oT2oT3_define
14478 {
14479 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
14480 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
14481 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
14482 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
14483 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
14484 typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
14485 };
14486
14487 template <typename T, typename Operation>
14488 class vov_node : public vov_base_node<T>
14489 {
14490 public:
14491
14492 typedef expression_node<T>* expression_ptr;
14493 typedef Operation operation_t;
14494
14495 // variable op variable node
14496 explicit vov_node(const T& var0, const T& var1)
14497 : v0_(var0),
14498 v1_(var1)
14499 {}
14500
14501 inline T value() const
14502 {
14503 return Operation::process(v0_,v1_);
14504 }
14505
14506 inline typename expression_node<T>::node_type type() const
14507 {
14508 return Operation::type();
14509 }
14510
14511 inline operator_type operation() const
14512 {
14513 return Operation::operation();
14514 }
14515
14516 inline const T& v0() const
14517 {
14518 return v0_;
14519 }
14520
14521 inline const T& v1() const
14522 {
14523 return v1_;
14524 }
14525
14526 protected:
14527
14528 const T& v0_;
14529 const T& v1_;
14530
14531 private:
14532
14533 vov_node(vov_node<T,Operation>&);
14534 vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
14535 };
14536
14537 template <typename T, typename Operation>
14538 class cov_node : public cov_base_node<T>
14539 {
14540 public:
14541
14542 typedef expression_node<T>* expression_ptr;
14543 typedef Operation operation_t;
14544
14545 // constant op variable node
14546 explicit cov_node(const T& const_var, const T& var)
14547 : c_(const_var),
14548 v_(var)
14549 {}
14550
14551 inline T value() const
14552 {
14553 return Operation::process(c_,v_);
14554 }
14555
14556 inline typename expression_node<T>::node_type type() const
14557 {
14558 return Operation::type();
14559 }
14560
14561 inline operator_type operation() const
14562 {
14563 return Operation::operation();
14564 }
14565
14566 inline const T c() const
14567 {
14568 return c_;
14569 }
14570
14571 inline const T& v() const
14572 {
14573 return v_;
14574 }
14575
14576 protected:
14577
14578 const T c_;
14579 const T& v_;
14580
14581 private:
14582
14583 cov_node(const cov_node<T,Operation>&);
14584 cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
14585 };
14586
14587 template <typename T, typename Operation>
14588 class voc_node : public voc_base_node<T>
14589 {
14590 public:
14591
14592 typedef expression_node<T>* expression_ptr;
14593 typedef Operation operation_t;
14594
14595 // variable op constant node
14596 explicit voc_node(const T& var, const T& const_var)
14597 : v_(var),
14598 c_(const_var)
14599 {}
14600
14601 inline T value() const
14602 {
14603 return Operation::process(v_,c_);
14604 }
14605
14606 inline operator_type operation() const
14607 {
14608 return Operation::operation();
14609 }
14610
14611 inline const T c() const
14612 {
14613 return c_;
14614 }
14615
14616 inline const T& v() const
14617 {
14618 return v_;
14619 }
14620
14621 protected:
14622
14623 const T& v_;
14624 const T c_;
14625
14626 private:
14627
14628 voc_node(const voc_node<T,Operation>&);
14629 voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
14630 };
14631
14632 template <typename T, typename Operation>
14633 class vob_node : public vob_base_node<T>
14634 {
14635 public:
14636
14637 typedef expression_node<T>* expression_ptr;
14638 typedef std::pair<expression_ptr,bool> branch_t;
14639 typedef Operation operation_t;
14640
14641 // variable op constant node
14642 explicit vob_node(const T& var, const expression_ptr brnch)
14643 : v_(var)
14644 {
14645 init_branches<1>(branch_,brnch);
14646 }
14647
14648 ~vob_node()
14649 {
14650 cleanup_branches::execute<T,1>(branch_);
14651 }
14652
14653 inline T value() const
14654 {
14655 return Operation::process(v_,branch_[0].first->value());
14656 }
14657
14658 inline operator_type operation() const
14659 {
14660 return Operation::operation();
14661 }
14662
14663 inline const T& v() const
14664 {
14665 return v_;
14666 }
14667
14668 inline expression_node<T>* branch(const std::size_t&) const
14669 {
14670 return branch_[0].first;
14671 }
14672
14673 private:
14674
14675 vob_node(const vob_node<T,Operation>&);
14676 vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
14677
14678 const T& v_;
14679 branch_t branch_[1];
14680 };
14681
14682 template <typename T, typename Operation>
14683 class bov_node : public bov_base_node<T>
14684 {
14685 public:
14686
14687 typedef expression_node<T>* expression_ptr;
14688 typedef std::pair<expression_ptr,bool> branch_t;
14689 typedef Operation operation_t;
14690
14691 // variable op constant node
14692 explicit bov_node(const expression_ptr brnch, const T& var)
14693 : v_(var)
14694 {
14695 init_branches<1>(branch_,brnch);
14696 }
14697
14698 ~bov_node()
14699 {
14700 cleanup_branches::execute<T,1>(branch_);
14701 }
14702
14703 inline T value() const
14704 {
14705 return Operation::process(branch_[0].first->value(),v_);
14706 }
14707
14708 inline operator_type operation() const
14709 {
14710 return Operation::operation();
14711 }
14712
14713 inline const T& v() const
14714 {
14715 return v_;
14716 }
14717
14718 inline expression_node<T>* branch(const std::size_t&) const
14719 {
14720 return branch_[0].first;
14721 }
14722
14723 private:
14724
14725 bov_node(const bov_node<T,Operation>&);
14726 bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
14727
14728 const T& v_;
14729 branch_t branch_[1];
14730 };
14731
14732 template <typename T, typename Operation>
14733 class cob_node : public cob_base_node<T>
14734 {
14735 public:
14736
14737 typedef expression_node<T>* expression_ptr;
14738 typedef std::pair<expression_ptr,bool> branch_t;
14739 typedef Operation operation_t;
14740
14741 // variable op constant node
14742 explicit cob_node(const T const_var, const expression_ptr brnch)
14743 : c_(const_var)
14744 {
14745 init_branches<1>(branch_,brnch);
14746 }
14747
14748 ~cob_node()
14749 {
14750 cleanup_branches::execute<T,1>(branch_);
14751 }
14752
14753 inline T value() const
14754 {
14755 return Operation::process(c_,branch_[0].first->value());
14756 }
14757
14758 inline operator_type operation() const
14759 {
14760 return Operation::operation();
14761 }
14762
14763 inline const T c() const
14764 {
14765 return c_;
14766 }
14767
14768 inline void set_c(const T new_c)
14769 {
14770 (*const_cast<T*>(&c_)) = new_c;
14771 }
14772
14773 inline expression_node<T>* branch(const std::size_t&) const
14774 {
14775 return branch_[0].first;
14776 }
14777
14778 inline expression_node<T>* move_branch(const std::size_t&)
14779 {
14780 branch_[0].second = false;
14781 return branch_[0].first;
14782 }
14783
14784 private:
14785
14786 cob_node(const cob_node<T,Operation>&);
14787 cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
14788
14789 const T c_;
14790 branch_t branch_[1];
14791 };
14792
14793 template <typename T, typename Operation>
14794 class boc_node : public boc_base_node<T>
14795 {
14796 public:
14797
14798 typedef expression_node<T>* expression_ptr;
14799 typedef std::pair<expression_ptr,bool> branch_t;
14800 typedef Operation operation_t;
14801
14802 // variable op constant node
14803 explicit boc_node(const expression_ptr brnch, const T const_var)
14804 : c_(const_var)
14805 {
14806 init_branches<1>(branch_,brnch);
14807 }
14808
14809 ~boc_node()
14810 {
14811 cleanup_branches::execute<T,1>(branch_);
14812 }
14813
14814 inline T value() const
14815 {
14816 return Operation::process(branch_[0].first->value(),c_);
14817 }
14818
14819 inline operator_type operation() const
14820 {
14821 return Operation::operation();
14822 }
14823
14824 inline const T c() const
14825 {
14826 return c_;
14827 }
14828
14829 inline void set_c(const T new_c)
14830 {
14831 (*const_cast<T*>(&c_)) = new_c;
14832 }
14833
14834 inline expression_node<T>* branch(const std::size_t&) const
14835 {
14836 return branch_[0].first;
14837 }
14838
14839 inline expression_node<T>* move_branch(const std::size_t&)
14840 {
14841 branch_[0].second = false;
14842 return branch_[0].first;
14843 }
14844
14845 private:
14846
14847 boc_node(const boc_node<T,Operation>&);
14848 boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
14849
14850 const T c_;
14851 branch_t branch_[1];
14852 };
14853
14854 #ifndef exprtk_disable_string_capabilities
14855 template <typename T, typename SType0, typename SType1, typename Operation>
14856 class sos_node : public sos_base_node<T>
14857 {
14858 public:
14859
14860 typedef expression_node<T>* expression_ptr;
14861 typedef Operation operation_t;
14862
14863 // string op string node
14864 explicit sos_node(SType0 p0, SType1 p1)
14865 : s0_(p0),
14866 s1_(p1)
14867 {}
14868
14869 inline T value() const
14870 {
14871 return Operation::process(s0_,s1_);
14872 }
14873
14874 inline typename expression_node<T>::node_type type() const
14875 {
14876 return Operation::type();
14877 }
14878
14879 inline operator_type operation() const
14880 {
14881 return Operation::operation();
14882 }
14883
14884 inline std::string& s0()
14885 {
14886 return s0_;
14887 }
14888
14889 inline std::string& s1()
14890 {
14891 return s1_;
14892 }
14893
14894 protected:
14895
14896 SType0 s0_;
14897 SType1 s1_;
14898
14899 private:
14900
14901 sos_node(sos_node<T,SType0,SType1,Operation>&);
14902 sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
14903 };
14904
14905 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14906 class str_xrox_node : public sos_base_node<T>
14907 {
14908 public:
14909
14910 typedef expression_node<T>* expression_ptr;
14911 typedef Operation operation_t;
14912
14913 // string-range op string node
14914 explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
14915 : s0_ (p0 ),
14916 s1_ (p1 ),
14917 rp0_(rp0)
14918 {}
14919
14920 ~str_xrox_node()
14921 {
14922 rp0_.free();
14923 }
14924
14925 inline T value() const
14926 {
14927 std::size_t r0 = 0;
14928 std::size_t r1 = 0;
14929
14930 if (rp0_(r0, r1, s0_.size()))
14931 return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
14932 else
14933 return T(0);
14934 }
14935
14936 inline typename expression_node<T>::node_type type() const
14937 {
14938 return Operation::type();
14939 }
14940
14941 inline operator_type operation() const
14942 {
14943 return Operation::operation();
14944 }
14945
14946 inline std::string& s0()
14947 {
14948 return s0_;
14949 }
14950
14951 inline std::string& s1()
14952 {
14953 return s1_;
14954 }
14955
14956 protected:
14957
14958 SType0 s0_;
14959 SType1 s1_;
14960 RangePack rp0_;
14961
14962 private:
14963
14964 str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14965 str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14966 };
14967
14968 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14969 class str_xoxr_node : public sos_base_node<T>
14970 {
14971 public:
14972
14973 typedef expression_node<T>* expression_ptr;
14974 typedef Operation operation_t;
14975
14976 // string op string range node
14977 explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
14978 : s0_ (p0 ),
14979 s1_ (p1 ),
14980 rp1_(rp1)
14981 {}
14982
14983 ~str_xoxr_node()
14984 {
14985 rp1_.free();
14986 }
14987
14988 inline T value() const
14989 {
14990 std::size_t r0 = 0;
14991 std::size_t r1 = 0;
14992
14993 if (rp1_(r0, r1, s1_.size()))
14994 return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
14995 else
14996 return T(0);
14997 }
14998
14999 inline typename expression_node<T>::node_type type() const
15000 {
15001 return Operation::type();
15002 }
15003
15004 inline operator_type operation() const
15005 {
15006 return Operation::operation();
15007 }
15008
15009 inline std::string& s0()
15010 {
15011 return s0_;
15012 }
15013
15014 inline std::string& s1()
15015 {
15016 return s1_;
15017 }
15018
15019 protected:
15020
15021 SType0 s0_;
15022 SType1 s1_;
15023 RangePack rp1_;
15024
15025 private:
15026
15027 str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15028 str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15029 };
15030
15031 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15032 class str_xroxr_node : public sos_base_node<T>
15033 {
15034 public:
15035
15036 typedef expression_node<T>* expression_ptr;
15037 typedef Operation operation_t;
15038
15039 // string-range op string-range node
15040 explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15041 : s0_ (p0 ),
15042 s1_ (p1 ),
15043 rp0_(rp0),
15044 rp1_(rp1)
15045 {}
15046
15047 ~str_xroxr_node()
15048 {
15049 rp0_.free();
15050 rp1_.free();
15051 }
15052
15053 inline T value() const
15054 {
15055 std::size_t r0_0 = 0;
15056 std::size_t r0_1 = 0;
15057 std::size_t r1_0 = 0;
15058 std::size_t r1_1 = 0;
15059
15060 if (
15061 rp0_(r0_0, r1_0, s0_.size()) &&
15062 rp1_(r0_1, r1_1, s1_.size())
15063 )
15064 {
15065 return Operation::process(
15066 s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15067 s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15068 );
15069 }
15070 else
15071 return T(0);
15072 }
15073
15074 inline typename expression_node<T>::node_type type() const
15075 {
15076 return Operation::type();
15077 }
15078
15079 inline operator_type operation() const
15080 {
15081 return Operation::operation();
15082 }
15083
15084 inline std::string& s0()
15085 {
15086 return s0_;
15087 }
15088
15089 inline std::string& s1()
15090 {
15091 return s1_;
15092 }
15093
15094 protected:
15095
15096 SType0 s0_;
15097 SType1 s1_;
15098 RangePack rp0_;
15099 RangePack rp1_;
15100
15101 private:
15102
15103 str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15104 str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15105 };
15106
15107 template <typename T, typename Operation>
15108 class str_sogens_node : public binary_node<T>
15109 {
15110 public:
15111
15112 typedef expression_node <T>* expression_ptr;
15113 typedef string_base_node<T>* str_base_ptr;
15114 typedef range_pack <T> range_t;
15115 typedef range_t* range_ptr;
15116 typedef range_interface<T> irange_t;
15117 typedef irange_t* irange_ptr;
15118
15119 str_sogens_node(const operator_type& opr,
15120 expression_ptr branch0,
15121 expression_ptr branch1)
15122 : binary_node<T>(opr, branch0, branch1),
15123 str0_base_ptr_ (0),
15124 str1_base_ptr_ (0),
15125 str0_range_ptr_(0),
15126 str1_range_ptr_(0)
15127 {
15128 if (is_generally_string_node(binary_node<T>::branch_[0].first))
15129 {
15130 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15131
15132 if (0 == str0_base_ptr_)
15133 return;
15134
15135 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15136
15137 if (0 == range)
15138 return;
15139
15140 str0_range_ptr_ = &(range->range_ref());
15141 }
15142
15143 if (is_generally_string_node(binary_node<T>::branch_[1].first))
15144 {
15145 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15146
15147 if (0 == str1_base_ptr_)
15148 return;
15149
15150 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15151
15152 if (0 == range)
15153 return;
15154
15155 str1_range_ptr_ = &(range->range_ref());
15156 }
15157 }
15158
15159 inline T value() const
15160 {
15161 if (
15162 str0_base_ptr_ &&
15163 str1_base_ptr_ &&
15164 str0_range_ptr_ &&
15165 str1_range_ptr_
15166 )
15167 {
15168 binary_node<T>::branch_[0].first->value();
15169 binary_node<T>::branch_[1].first->value();
15170
15171 std::size_t str0_r0 = 0;
15172 std::size_t str0_r1 = 0;
15173
15174 std::size_t str1_r0 = 0;
15175 std::size_t str1_r1 = 0;
15176
15177 range_t& range0 = (*str0_range_ptr_);
15178 range_t& range1 = (*str1_range_ptr_);
15179
15180 if (
15181 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15182 range1(str1_r0, str1_r1, str1_base_ptr_->size())
15183 )
15184 {
15185 return Operation::process(
15186 str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15187 str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15188 );
15189 }
15190 }
15191
15192 return std::numeric_limits<T>::quiet_NaN();
15193 }
15194
15195 inline typename expression_node<T>::node_type type() const
15196 {
15197 return Operation::type();
15198 }
15199
15200 inline operator_type operation() const
15201 {
15202 return Operation::operation();
15203 }
15204
15205 private:
15206
15207 str_sogens_node(str_sogens_node<T,Operation>&);
15208 str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
15209
15210 str_base_ptr str0_base_ptr_;
15211 str_base_ptr str1_base_ptr_;
15212 range_ptr str0_range_ptr_;
15213 range_ptr str1_range_ptr_;
15214 };
15215
15216 template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15217 class sosos_node : public sosos_base_node<T>
15218 {
15219 public:
15220
15221 typedef expression_node<T>* expression_ptr;
15222 typedef Operation operation_t;
15223
15224 // variable op variable node
15225 explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15226 : s0_(p0),
15227 s1_(p1),
15228 s2_(p2)
15229 {}
15230
15231 inline T value() const
15232 {
15233 return Operation::process(s0_,s1_,s2_);
15234 }
15235
15236 inline typename expression_node<T>::node_type type() const
15237 {
15238 return Operation::type();
15239 }
15240
15241 inline operator_type operation() const
15242 {
15243 return Operation::operation();
15244 }
15245
15246 inline std::string& s0()
15247 {
15248 return s0_;
15249 }
15250
15251 inline std::string& s1()
15252 {
15253 return s1_;
15254 }
15255
15256 inline std::string& s2()
15257 {
15258 return s2_;
15259 }
15260
15261 protected:
15262
15263 SType0 s0_;
15264 SType1 s1_;
15265 SType2 s2_;
15266
15267 private:
15268
15269 sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
15270 sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
15271 };
15272 #endif
15273
15274 template <typename T, typename PowOp>
15275 class ipow_node : public expression_node<T>
15276 {
15277 public:
15278
15279 typedef expression_node<T>* expression_ptr;
15280 typedef PowOp operation_t;
15281
15282 explicit ipow_node(const T& v)
15283 : v_(v)
15284 {}
15285
15286 inline T value() const
15287 {
15288 return PowOp::result(v_);
15289 }
15290
15291 inline typename expression_node<T>::node_type type() const
15292 {
15293 return expression_node<T>::e_ipow;
15294 }
15295
15296 private:
15297
15298 ipow_node(const ipow_node<T,PowOp>&);
15299 ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
15300
15301 const T& v_;
15302 };
15303
15304 template <typename T, typename PowOp>
15305 class bipow_node : public expression_node<T>
15306 {
15307 public:
15308
15309 typedef expression_node<T>* expression_ptr;
15310 typedef std::pair<expression_ptr, bool> branch_t;
15311 typedef PowOp operation_t;
15312
15313 explicit bipow_node(expression_ptr brnch)
15314 {
15315 init_branches<1>(branch_, brnch);
15316 }
15317
15318 ~bipow_node()
15319 {
15320 cleanup_branches::execute<T,1>(branch_);
15321 }
15322
15323 inline T value() const
15324 {
15325 return PowOp::result(branch_[0].first->value());
15326 }
15327
15328 inline typename expression_node<T>::node_type type() const
15329 {
15330 return expression_node<T>::e_ipow;
15331 }
15332
15333 private:
15334
15335 bipow_node(const bipow_node<T,PowOp>&);
15336 bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
15337
15338 branch_t branch_[1];
15339 };
15340
15341 template <typename T, typename PowOp>
15342 class ipowinv_node : public expression_node<T>
15343 {
15344 public:
15345
15346 typedef expression_node<T>* expression_ptr;
15347 typedef PowOp operation_t;
15348
15349 explicit ipowinv_node(const T& v)
15350 : v_(v)
15351 {}
15352
15353 inline T value() const
15354 {
15355 return (T(1) / PowOp::result(v_));
15356 }
15357
15358 inline typename expression_node<T>::node_type type() const
15359 {
15360 return expression_node<T>::e_ipowinv;
15361 }
15362
15363 private:
15364
15365 ipowinv_node(const ipowinv_node<T,PowOp>&);
15366 ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
15367
15368 const T& v_;
15369 };
15370
15371 template <typename T, typename PowOp>
15372 class bipowninv_node : public expression_node<T>
15373 {
15374 public:
15375
15376 typedef expression_node<T>* expression_ptr;
15377 typedef std::pair<expression_ptr, bool> branch_t;
15378 typedef PowOp operation_t;
15379
15380 explicit bipowninv_node(expression_ptr brnch)
15381 {
15382 init_branches<1>(branch_, brnch);
15383 }
15384
15385 ~bipowninv_node()
15386 {
15387 cleanup_branches::execute<T,1>(branch_);
15388 }
15389
15390 inline T value() const
15391 {
15392 return (T(1) / PowOp::result(branch_[0].first->value()));
15393 }
15394
15395 inline typename expression_node<T>::node_type type() const
15396 {
15397 return expression_node<T>::e_ipowinv;
15398 }
15399
15400 private:
15401
15402 bipowninv_node(const bipowninv_node<T,PowOp>&);
15403 bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
15404
15405 branch_t branch_[1];
15406 };
15407
15408 template <typename T>
15409 inline bool is_vov_node(const expression_node<T>* node)
15410 {
15411 return (0 != dynamic_cast<const vov_base_node<T>*>(node));
15412 }
15413
15414 template <typename T>
15415 inline bool is_cov_node(const expression_node<T>* node)
15416 {
15417 return (0 != dynamic_cast<const cov_base_node<T>*>(node));
15418 }
15419
15420 template <typename T>
15421 inline bool is_voc_node(const expression_node<T>* node)
15422 {
15423 return (0 != dynamic_cast<const voc_base_node<T>*>(node));
15424 }
15425
15426 template <typename T>
15427 inline bool is_cob_node(const expression_node<T>* node)
15428 {
15429 return (0 != dynamic_cast<const cob_base_node<T>*>(node));
15430 }
15431
15432 template <typename T>
15433 inline bool is_boc_node(const expression_node<T>* node)
15434 {
15435 return (0 != dynamic_cast<const boc_base_node<T>*>(node));
15436 }
15437
15438 template <typename T>
15439 inline bool is_t0ot1ot2_node(const expression_node<T>* node)
15440 {
15441 return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
15442 }
15443
15444 template <typename T>
15445 inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
15446 {
15447 return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
15448 }
15449
15450 template <typename T>
15451 inline bool is_uv_node(const expression_node<T>* node)
15452 {
15453 return (0 != dynamic_cast<const uv_base_node<T>*>(node));
15454 }
15455
15456 template <typename T>
15457 inline bool is_string_node(const expression_node<T>* node)
15458 {
15459 return node && (expression_node<T>::e_stringvar == node->type());
15460 }
15461
15462 template <typename T>
15463 inline bool is_string_range_node(const expression_node<T>* node)
15464 {
15465 return node && (expression_node<T>::e_stringvarrng == node->type());
15466 }
15467
15468 template <typename T>
15469 inline bool is_const_string_node(const expression_node<T>* node)
15470 {
15471 return node && (expression_node<T>::e_stringconst == node->type());
15472 }
15473
15474 template <typename T>
15475 inline bool is_const_string_range_node(const expression_node<T>* node)
15476 {
15477 return node && (expression_node<T>::e_cstringvarrng == node->type());
15478 }
15479
15480 template <typename T>
15481 inline bool is_string_assignment_node(const expression_node<T>* node)
15482 {
15483 return node && (expression_node<T>::e_strass == node->type());
15484 }
15485
15486 template <typename T>
15487 inline bool is_string_concat_node(const expression_node<T>* node)
15488 {
15489 return node && (expression_node<T>::e_strconcat == node->type());
15490 }
15491
15492 template <typename T>
15493 inline bool is_string_function_node(const expression_node<T>* node)
15494 {
15495 return node && (expression_node<T>::e_strfunction == node->type());
15496 }
15497
15498 template <typename T>
15499 inline bool is_string_condition_node(const expression_node<T>* node)
15500 {
15501 return node && (expression_node<T>::e_strcondition == node->type());
15502 }
15503
15504 template <typename T>
15505 inline bool is_string_ccondition_node(const expression_node<T>* node)
15506 {
15507 return node && (expression_node<T>::e_strccondition == node->type());
15508 }
15509
15510 template <typename T>
15511 inline bool is_string_vararg_node(const expression_node<T>* node)
15512 {
15513 return node && (expression_node<T>::e_stringvararg == node->type());
15514 }
15515
15516 template <typename T>
15517 inline bool is_genricstring_range_node(const expression_node<T>* node)
15518 {
15519 return node && (expression_node<T>::e_strgenrange == node->type());
15520 }
15521
15522 template <typename T>
15523 inline bool is_generally_string_node(const expression_node<T>* node)
15524 {
15525 if (node)
15526 {
15527 switch (node->type())
15528 {
15529 case expression_node<T>::e_stringvar :
15530 case expression_node<T>::e_stringconst :
15531 case expression_node<T>::e_stringvarrng :
15532 case expression_node<T>::e_cstringvarrng :
15533 case expression_node<T>::e_strgenrange :
15534 case expression_node<T>::e_strass :
15535 case expression_node<T>::e_strconcat :
15536 case expression_node<T>::e_strfunction :
15537 case expression_node<T>::e_strcondition :
15538 case expression_node<T>::e_strccondition :
15539 case expression_node<T>::e_stringvararg : return true;
15540 default : return false;
15541 }
15542 }
15543
15544 return false;
15545 }
15546
15547 class node_allocator
15548 {
15549 public:
15550
15551 template <typename ResultNode, typename OpType, typename ExprNode>
15552 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
15553 {
15554 return allocate<ResultNode>(operation, branch[0]);
15555 }
15556
15557 template <typename ResultNode, typename OpType, typename ExprNode>
15558 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
15559 {
15560 return allocate<ResultNode>(operation, branch[0], branch[1]);
15561 }
15562
15563 template <typename ResultNode, typename OpType, typename ExprNode>
15564 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
15565 {
15566 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
15567 }
15568
15569 template <typename ResultNode, typename OpType, typename ExprNode>
15570 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
15571 {
15572 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
15573 }
15574
15575 template <typename ResultNode, typename OpType, typename ExprNode>
15576 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
15577 {
15578 return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
15579 }
15580
15581 template <typename ResultNode, typename OpType, typename ExprNode>
15582 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
15583 {
15584 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
15585 }
15586
15587 template <typename node_type>
15588 inline expression_node<typename node_type::value_type>* allocate() const
15589 {
15590 return (new node_type());
15591 }
15592
15593 template <typename node_type,
15594 typename Type,
15595 typename Allocator,
15596 template <typename, typename> class Sequence>
15597 inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
15598 {
15599 return (new node_type(seq));
15600 }
15601
15602 template <typename node_type, typename T1>
15603 inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
15604 {
15605 return (new node_type(t1));
15606 }
15607
15608 template <typename node_type, typename T1>
15609 inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
15610 {
15611 return (new node_type(t1));
15612 }
15613
15614 template <typename node_type,
15615 typename T1, typename T2>
15616 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
15617 {
15618 return (new node_type(t1, t2));
15619 }
15620
15621 template <typename node_type,
15622 typename T1, typename T2>
15623 inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
15624 {
15625 return (new node_type(t1, t2));
15626 }
15627
15628 template <typename node_type,
15629 typename T1, typename T2>
15630 inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
15631 {
15632 return (new node_type(t1, t2));
15633 }
15634
15635 template <typename node_type,
15636 typename T1, typename T2>
15637 inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
15638 {
15639 return (new node_type(t1, t2));
15640 }
15641
15642 template <typename node_type,
15643 typename T1, typename T2>
15644 inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
15645 {
15646 return (new node_type(t1, t2));
15647 }
15648
15649 template <typename node_type,
15650 typename T1, typename T2, typename T3>
15651 inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
15652 {
15653 return (new node_type(t1, t2, t3));
15654 }
15655
15656 template <typename node_type,
15657 typename T1, typename T2, typename T3, typename T4>
15658 inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
15659 {
15660 return (new node_type(t1, t2, t3, t4));
15661 }
15662
15663 template <typename node_type,
15664 typename T1, typename T2, typename T3>
15665 inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
15666 {
15667 return (new node_type(t1, t2, t3));
15668 }
15669
15670 template <typename node_type,
15671 typename T1, typename T2, typename T3, typename T4>
15672 inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
15673 {
15674 return (new node_type(t1, t2, t3, t4));
15675 }
15676
15677 template <typename node_type,
15678 typename T1, typename T2, typename T3, typename T4, typename T5>
15679 inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
15680 {
15681 return (new node_type(t1, t2, t3, t4, t5));
15682 }
15683
15684 template <typename node_type,
15685 typename T1, typename T2, typename T3>
15686 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15687 const T3& t3) const
15688 {
15689 return (new node_type(t1, t2, t3));
15690 }
15691
15692 template <typename node_type,
15693 typename T1, typename T2,
15694 typename T3, typename T4>
15695 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15696 const T3& t3, const T4& t4) const
15697 {
15698 return (new node_type(t1, t2, t3, t4));
15699 }
15700
15701 template <typename node_type,
15702 typename T1, typename T2,
15703 typename T3, typename T4, typename T5>
15704 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15705 const T3& t3, const T4& t4,
15706 const T5& t5) const
15707 {
15708 return (new node_type(t1, t2, t3, t4, t5));
15709 }
15710
15711 template <typename node_type,
15712 typename T1, typename T2,
15713 typename T3, typename T4, typename T5, typename T6>
15714 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15715 const T3& t3, const T4& t4,
15716 const T5& t5, const T6& t6) const
15717 {
15718 return (new node_type(t1, t2, t3, t4, t5, t6));
15719 }
15720
15721 template <typename node_type,
15722 typename T1, typename T2,
15723 typename T3, typename T4,
15724 typename T5, typename T6, typename T7>
15725 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15726 const T3& t3, const T4& t4,
15727 const T5& t5, const T6& t6,
15728 const T7& t7) const
15729 {
15730 return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15731 }
15732
15733 template <typename node_type,
15734 typename T1, typename T2,
15735 typename T3, typename T4,
15736 typename T5, typename T6,
15737 typename T7, typename T8>
15738 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15739 const T3& t3, const T4& t4,
15740 const T5& t5, const T6& t6,
15741 const T7& t7, const T8& t8) const
15742 {
15743 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
15744 }
15745
15746 template <typename node_type,
15747 typename T1, typename T2,
15748 typename T3, typename T4,
15749 typename T5, typename T6,
15750 typename T7, typename T8, typename T9>
15751 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15752 const T3& t3, const T4& t4,
15753 const T5& t5, const T6& t6,
15754 const T7& t7, const T8& t8,
15755 const T9& t9) const
15756 {
15757 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
15758 }
15759
15760 template <typename node_type,
15761 typename T1, typename T2,
15762 typename T3, typename T4,
15763 typename T5, typename T6,
15764 typename T7, typename T8,
15765 typename T9, typename T10>
15766 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15767 const T3& t3, const T4& t4,
15768 const T5& t5, const T6& t6,
15769 const T7& t7, const T8& t8,
15770 const T9& t9, const T10& t10) const
15771 {
15772 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
15773 }
15774
15775 template <typename node_type,
15776 typename T1, typename T2, typename T3>
15777 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
15778 {
15779 return (new node_type(t1, t2, t3));
15780 }
15781
15782 template <typename node_type,
15783 typename T1, typename T2,
15784 typename T3, typename T4>
15785 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15786 T3 t3, T4 t4) const
15787 {
15788 return (new node_type(t1, t2, t3, t4));
15789 }
15790
15791 template <typename node_type,
15792 typename T1, typename T2,
15793 typename T3, typename T4,
15794 typename T5>
15795 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15796 T3 t3, T4 t4,
15797 T5 t5) const
15798 {
15799 return (new node_type(t1, t2, t3, t4, t5));
15800 }
15801
15802 template <typename node_type,
15803 typename T1, typename T2,
15804 typename T3, typename T4,
15805 typename T5, typename T6>
15806 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15807 T3 t3, T4 t4,
15808 T5 t5, T6 t6) const
15809 {
15810 return (new node_type(t1, t2, t3, t4, t5, t6));
15811 }
15812
15813 template <typename node_type,
15814 typename T1, typename T2,
15815 typename T3, typename T4,
15816 typename T5, typename T6, typename T7>
15817 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15818 T3 t3, T4 t4,
15819 T5 t5, T6 t6,
15820 T7 t7) const
15821 {
15822 return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15823 }
15824
15825 template <typename T>
15826 void inline free(expression_node<T>*& e) const
15827 {
15828 delete e;
15829 e = 0;
15830 }
15831 };
15832
15833 inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
15834 {
15835 #define register_op(Symbol,Type,Args) \
15836 m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
15837
15838 register_op( "abs", e_abs , 1)
15839 register_op( "acos", e_acos , 1)
15840 register_op( "acosh", e_acosh , 1)
15841 register_op( "asin", e_asin , 1)
15842 register_op( "asinh", e_asinh , 1)
15843 register_op( "atan", e_atan , 1)
15844 register_op( "atanh", e_atanh , 1)
15845 register_op( "ceil", e_ceil , 1)
15846 register_op( "cos", e_cos , 1)
15847 register_op( "cosh", e_cosh , 1)
15848 register_op( "exp", e_exp , 1)
15849 register_op( "expm1", e_expm1 , 1)
15850 register_op( "floor", e_floor , 1)
15851 register_op( "log", e_log , 1)
15852 register_op( "log10", e_log10 , 1)
15853 register_op( "log2", e_log2 , 1)
15854 register_op( "log1p", e_log1p , 1)
15855 register_op( "round", e_round , 1)
15856 register_op( "sin", e_sin , 1)
15857 register_op( "sinc", e_sinc , 1)
15858 register_op( "sinh", e_sinh , 1)
15859 register_op( "sec", e_sec , 1)
15860 register_op( "csc", e_csc , 1)
15861 register_op( "sqrt", e_sqrt , 1)
15862 register_op( "tan", e_tan , 1)
15863 register_op( "tanh", e_tanh , 1)
15864 register_op( "cot", e_cot , 1)
15865 register_op( "rad2deg", e_r2d , 1)
15866 register_op( "deg2rad", e_d2r , 1)
15867 register_op( "deg2grad", e_d2g , 1)
15868 register_op( "grad2deg", e_g2d , 1)
15869 register_op( "sgn", e_sgn , 1)
15870 register_op( "not", e_notl , 1)
15871 register_op( "erf", e_erf , 1)
15872 register_op( "erfc", e_erfc , 1)
15873 register_op( "ncdf", e_ncdf , 1)
15874 register_op( "frac", e_frac , 1)
15875 register_op( "trunc", e_trunc , 1)
15876 register_op( "atan2", e_atan2 , 2)
15877 register_op( "mod", e_mod , 2)
15878 register_op( "logn", e_logn , 2)
15879 register_op( "pow", e_pow , 2)
15880 register_op( "root", e_root , 2)
15881 register_op( "roundn", e_roundn , 2)
15882 register_op( "equal", e_equal , 2)
15883 register_op("not_equal", e_nequal , 2)
15884 register_op( "hypot", e_hypot , 2)
15885 register_op( "shr", e_shr , 2)
15886 register_op( "shl", e_shl , 2)
15887 register_op( "clamp", e_clamp , 3)
15888 register_op( "iclamp", e_iclamp , 3)
15889 register_op( "inrange", e_inrange , 3)
15890 #undef register_op
15891 }
15892
15893 } // namespace details
15894
15895 class function_traits
15896 {
15897 public:
15898
15899 function_traits()
15900 : allow_zero_parameters_(false),
15901 has_side_effects_(true),
15902 min_num_args_(0),
15903 max_num_args_(std::numeric_limits<std::size_t>::max())
15904 {}
15905
15906 inline bool& allow_zero_parameters()
15907 {
15908 return allow_zero_parameters_;
15909 }
15910
15911 inline bool& has_side_effects()
15912 {
15913 return has_side_effects_;
15914 }
15915
15916 std::size_t& min_num_args()
15917 {
15918 return min_num_args_;
15919 }
15920
15921 std::size_t& max_num_args()
15922 {
15923 return max_num_args_;
15924 }
15925
15926 private:
15927
15928 bool allow_zero_parameters_;
15929 bool has_side_effects_;
15930 std::size_t min_num_args_;
15931 std::size_t max_num_args_;
15932 };
15933
15934 template <typename FunctionType>
15935 void enable_zero_parameters(FunctionType& func)
15936 {
15937 func.allow_zero_parameters() = true;
15938
15939 if (0 != func.min_num_args())
15940 {
15941 func.min_num_args() = 0;
15942 }
15943 }
15944
15945 template <typename FunctionType>
15946 void disable_zero_parameters(FunctionType& func)
15947 {
15948 func.allow_zero_parameters() = false;
15949 }
15950
15951 template <typename FunctionType>
15952 void enable_has_side_effects(FunctionType& func)
15953 {
15954 func.has_side_effects() = true;
15955 }
15956
15957 template <typename FunctionType>
15958 void disable_has_side_effects(FunctionType& func)
15959 {
15960 func.has_side_effects() = false;
15961 }
15962
15963 template <typename FunctionType>
15964 void set_min_num_args(FunctionType& func, const std::size_t& num_args)
15965 {
15966 func.min_num_args() = num_args;
15967
15968 if ((0 != func.min_num_args()) && func.allow_zero_parameters())
15969 func.allow_zero_parameters() = false;
15970 }
15971
15972 template <typename FunctionType>
15973 void set_max_num_args(FunctionType& func, const std::size_t& num_args)
15974 {
15975 func.max_num_args() = num_args;
15976 }
15977
15978 template <typename T>
15979 class ifunction : public function_traits
15980 {
15981 public:
15982
15983 explicit ifunction(const std::size_t& pc)
15984 : param_count(pc)
15985 {}
15986
15987 virtual ~ifunction()
15988 {}
15989
15990 #define empty_method_body \
15991 { \
15992 return std::numeric_limits<T>::quiet_NaN(); \
15993 } \
15994
15995 inline virtual T operator() ()
15996 empty_method_body
15997
15998 inline virtual T operator() (const T&)
15999 empty_method_body
16000
16001 inline virtual T operator() (const T&,const T&)
16002 empty_method_body
16003
16004 inline virtual T operator() (const T&, const T&, const T&)
16005 empty_method_body
16006
16007 inline virtual T operator() (const T&, const T&, const T&, const T&)
16008 empty_method_body
16009
16010 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16011 empty_method_body
16012
16013 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16014 empty_method_body
16015
16016 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16017 empty_method_body
16018
16019 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16020 empty_method_body
16021
16022 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16023 empty_method_body
16024
16025 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16026 empty_method_body
16027
16028 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16029 const T&)
16030 empty_method_body
16031
16032 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16033 const T&, const T&)
16034 empty_method_body
16035
16036 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16037 const T&, const T&, const T&)
16038 empty_method_body
16039
16040 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16041 const T&, const T&, const T&, const T&)
16042 empty_method_body
16043
16044 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16045 const T&, const T&, const T&, const T&, const T&)
16046 empty_method_body
16047
16048 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16049 const T&, const T&, const T&, const T&, const T&, const T&)
16050 empty_method_body
16051
16052 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16053 const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16054 empty_method_body
16055
16056 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16057 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16058 empty_method_body
16059
16060 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16061 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16062 empty_method_body
16063
16064 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16065 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16066 empty_method_body
16067
16068 #undef empty_method_body
16069
16070 std::size_t param_count;
16071 };
16072
16073 template <typename T>
16074 class ivararg_function : public function_traits
16075 {
16076 public:
16077
16078 virtual ~ivararg_function()
16079 {}
16080
16081 inline virtual T operator() (const std::vector<T>&)
16082 {
16083 exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
16084 return std::numeric_limits<T>::quiet_NaN();
16085 }
16086 };
16087
16088 template <typename T>
16089 class igeneric_function : public function_traits
16090 {
16091 public:
16092
16093 enum return_type
16094 {
16095 e_rtrn_scalar = 0,
16096 e_rtrn_string = 1,
16097 e_rtrn_overload = 2
16098 };
16099
16100 typedef T type;
16101 typedef type_store<T> generic_type;
16102 typedef typename generic_type::parameter_list parameter_list_t;
16103
16104 igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16105 : parameter_sequence(param_seq),
16106 rtrn_type(rtr_type)
16107 {}
16108
16109 virtual ~igeneric_function()
16110 {}
16111
16112 #define igeneric_function_empty_body(N) \
16113 { \
16114 exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
16115 return std::numeric_limits<T>::quiet_NaN(); \
16116 } \
16117
16118 // f(i_0,i_1,....,i_N) --> Scalar
16119 inline virtual T operator() (parameter_list_t)
16120 igeneric_function_empty_body(1)
16121
16122 // f(i_0,i_1,....,i_N) --> String
16123 inline virtual T operator() (std::string&, parameter_list_t)
16124 igeneric_function_empty_body(2)
16125
16126 // f(psi,i_0,i_1,....,i_N) --> Scalar
16127 inline virtual T operator() (const std::size_t&, parameter_list_t)
16128 igeneric_function_empty_body(3)
16129
16130 // f(psi,i_0,i_1,....,i_N) --> String
16131 inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16132 igeneric_function_empty_body(4)
16133
16134 std::string parameter_sequence;
16135 return_type rtrn_type;
16136 };
16137
16138 template <typename T> class parser;
16139 template <typename T> class expression_helper;
16140
16141 template <typename T>
16142 class symbol_table
16143 {
16144 public:
16145
16146 typedef T (*ff00_functor)();
16147 typedef T (*ff01_functor)(T);
16148 typedef T (*ff02_functor)(T, T);
16149 typedef T (*ff03_functor)(T, T, T);
16150 typedef T (*ff04_functor)(T, T, T, T);
16151 typedef T (*ff05_functor)(T, T, T, T, T);
16152 typedef T (*ff06_functor)(T, T, T, T, T, T);
16153 typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16154 typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16155 typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16156 typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16157 typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16158 typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16159 typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16160 typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16161 typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16162
16163 protected:
16164
16165 struct freefunc00 : public exprtk::ifunction<T>
16166 {
16167 using exprtk::ifunction<T>::operator();
16168
16169 explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
16170 inline T operator() ()
16171 { return f(); }
16172 ff00_functor f;
16173 };
16174
16175 struct freefunc01 : public exprtk::ifunction<T>
16176 {
16177 using exprtk::ifunction<T>::operator();
16178
16179 explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
16180 inline T operator() (const T& v0)
16181 { return f(v0); }
16182 ff01_functor f;
16183 };
16184
16185 struct freefunc02 : public exprtk::ifunction<T>
16186 {
16187 using exprtk::ifunction<T>::operator();
16188
16189 explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
16190 inline T operator() (const T& v0, const T& v1)
16191 { return f(v0, v1); }
16192 ff02_functor f;
16193 };
16194
16195 struct freefunc03 : public exprtk::ifunction<T>
16196 {
16197 using exprtk::ifunction<T>::operator();
16198
16199 explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
16200 inline T operator() (const T& v0, const T& v1, const T& v2)
16201 { return f(v0, v1, v2); }
16202 ff03_functor f;
16203 };
16204
16205 struct freefunc04 : public exprtk::ifunction<T>
16206 {
16207 using exprtk::ifunction<T>::operator();
16208
16209 explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
16210 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16211 { return f(v0, v1, v2, v3); }
16212 ff04_functor f;
16213 };
16214
16215 struct freefunc05 : public exprtk::ifunction<T>
16216 {
16217 using exprtk::ifunction<T>::operator();
16218
16219 explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
16220 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16221 { return f(v0, v1, v2, v3, v4); }
16222 ff05_functor f;
16223 };
16224
16225 struct freefunc06 : public exprtk::ifunction<T>
16226 {
16227 using exprtk::ifunction<T>::operator();
16228
16229 explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
16230 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16231 { return f(v0, v1, v2, v3, v4, v5); }
16232 ff06_functor f;
16233 };
16234
16235 struct freefunc07 : public exprtk::ifunction<T>
16236 {
16237 using exprtk::ifunction<T>::operator();
16238
16239 explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
16240 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16241 const T& v5, const T& v6)
16242 { return f(v0, v1, v2, v3, v4, v5, v6); }
16243 ff07_functor f;
16244 };
16245
16246 struct freefunc08 : public exprtk::ifunction<T>
16247 {
16248 using exprtk::ifunction<T>::operator();
16249
16250 explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
16251 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16252 const T& v5, const T& v6, const T& v7)
16253 { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
16254 ff08_functor f;
16255 };
16256
16257 struct freefunc09 : public exprtk::ifunction<T>
16258 {
16259 using exprtk::ifunction<T>::operator();
16260
16261 explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
16262 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16263 const T& v5, const T& v6, const T& v7, const T& v8)
16264 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
16265 ff09_functor f;
16266 };
16267
16268 struct freefunc10 : public exprtk::ifunction<T>
16269 {
16270 using exprtk::ifunction<T>::operator();
16271
16272 explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
16273 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16274 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
16275 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
16276 ff10_functor f;
16277 };
16278
16279 struct freefunc11 : public exprtk::ifunction<T>
16280 {
16281 using exprtk::ifunction<T>::operator();
16282
16283 explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
16284 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16285 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
16286 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
16287 ff11_functor f;
16288 };
16289
16290 struct freefunc12 : public exprtk::ifunction<T>
16291 {
16292 using exprtk::ifunction<T>::operator();
16293
16294 explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
16295 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16296 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16297 const T& v10, const T& v11)
16298 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
16299 ff12_functor f;
16300 };
16301
16302 struct freefunc13 : public exprtk::ifunction<T>
16303 {
16304 using exprtk::ifunction<T>::operator();
16305
16306 explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
16307 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16308 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16309 const T& v10, const T& v11, const T& v12)
16310 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
16311 ff13_functor f;
16312 };
16313
16314 struct freefunc14 : public exprtk::ifunction<T>
16315 {
16316 using exprtk::ifunction<T>::operator();
16317
16318 explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
16319 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16320 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16321 const T& v10, const T& v11, const T& v12, const T& v13)
16322 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
16323 ff14_functor f;
16324 };
16325
16326 struct freefunc15 : public exprtk::ifunction<T>
16327 {
16328 using exprtk::ifunction<T>::operator();
16329
16330 explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
16331 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16332 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16333 const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
16334 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
16335 ff15_functor f;
16336 };
16337
16338 template <typename Type, typename RawType>
16339 struct type_store
16340 {
16341 typedef details::expression_node<T>* expression_ptr;
16342 typedef typename details::variable_node<T> variable_node_t;
16343 typedef ifunction<T> ifunction_t;
16344 typedef ivararg_function<T> ivararg_function_t;
16345 typedef igeneric_function<T> igeneric_function_t;
16346 typedef details::vector_holder<T> vector_t;
16347 #ifndef exprtk_disable_string_capabilities
16348 typedef typename details::stringvar_node<T> stringvar_node_t;
16349 #endif
16350
16351 typedef Type type_t;
16352 typedef type_t* type_ptr;
16353 typedef std::pair<bool,type_ptr> type_pair_t;
16354 typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
16355 typedef typename type_map_t::iterator tm_itr_t;
16356 typedef typename type_map_t::const_iterator tm_const_itr_t;
16357
16358 enum { lut_size = 256 };
16359
16360 type_map_t map;
16361 std::size_t size;
16362
16363 type_store()
16364 : size(0)
16365 {}
16366
16367 inline bool symbol_exists(const std::string& symbol_name) const
16368 {
16369 if (symbol_name.empty())
16370 return false;
16371 else if (map.end() != map.find(symbol_name))
16372 return true;
16373 else
16374 return false;
16375 }
16376
16377 template <typename PtrType>
16378 inline std::string entity_name(const PtrType& ptr) const
16379 {
16380 if (map.empty())
16381 return std::string();
16382
16383 tm_const_itr_t itr = map.begin();
16384
16385 while (map.end() != itr)
16386 {
16387 if (itr->second.second == ptr)
16388 {
16389 return itr->first;
16390 }
16391 else
16392 ++itr;
16393 }
16394
16395 return std::string();
16396 }
16397
16398 inline bool is_constant(const std::string& symbol_name) const
16399 {
16400 if (symbol_name.empty())
16401 return false;
16402 else
16403 {
16404 const tm_const_itr_t itr = map.find(symbol_name);
16405
16406 if (map.end() == itr)
16407 return false;
16408 else
16409 return (*itr).second.first;
16410 }
16411 }
16412
16413 template <typename Tie, typename RType>
16414 inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
16415 {
16416 if (symbol_name.size() > 1)
16417 {
16418 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16419 {
16420 if (details::imatch(symbol_name, details::reserved_symbols[i]))
16421 {
16422 return false;
16423 }
16424 }
16425 }
16426
16427 const tm_itr_t itr = map.find(symbol_name);
16428
16429 if (map.end() == itr)
16430 {
16431 map[symbol_name] = Tie::make(t,is_const);
16432 ++size;
16433 }
16434
16435 return true;
16436 }
16437
16438 struct tie_array
16439 {
16440 static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
16441 {
16442 return std::make_pair(is_const, new vector_t(v.first, v.second));
16443 }
16444 };
16445
16446 struct tie_stdvec
16447 {
16448 template <typename Allocator>
16449 static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
16450 {
16451 return std::make_pair(is_const, new vector_t(v));
16452 }
16453 };
16454
16455 struct tie_vecview
16456 {
16457 static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
16458 {
16459 return std::make_pair(is_const, new vector_t(v));
16460 }
16461 };
16462
16463 struct tie_stddeq
16464 {
16465 template <typename Allocator>
16466 static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
16467 {
16468 return std::make_pair(is_const, new vector_t(v));
16469 }
16470 };
16471
16472 template <std::size_t v_size>
16473 inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
16474 {
16475 return add_impl<tie_array,std::pair<T*,std::size_t> >
16476 (symbol_name, std::make_pair(v,v_size), is_const);
16477 }
16478
16479 inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
16480 {
16481 return add_impl<tie_array,std::pair<T*,std::size_t> >
16482 (symbol_name, std::make_pair(v,v_size), is_const);
16483 }
16484
16485 template <typename Allocator>
16486 inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
16487 {
16488 return add_impl<tie_stdvec,std::vector<T,Allocator>&>
16489 (symbol_name, v, is_const);
16490 }
16491
16492 inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
16493 {
16494 return add_impl<tie_vecview,exprtk::vector_view<T>&>
16495 (symbol_name, v, is_const);
16496 }
16497
16498 template <typename Allocator>
16499 inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
16500 {
16501 return add_impl<tie_stddeq,std::deque<T,Allocator>&>
16502 (symbol_name, v, is_const);
16503 }
16504
16505 inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
16506 {
16507 struct tie
16508 {
16509 static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
16510 {
16511 return std::make_pair(is_const, new variable_node_t(t));
16512 }
16513
16514 #ifndef exprtk_disable_string_capabilities
16515 static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
16516 {
16517 return std::make_pair(is_const, new stringvar_node_t(t));
16518 }
16519 #endif
16520
16521 static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
16522 {
16523 return std::make_pair(is_constant,&t);
16524 }
16525
16526 static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
16527 {
16528 return std::make_pair(is_const,&t);
16529 }
16530
16531 static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
16532 {
16533 return std::make_pair(is_constant,&t);
16534 }
16535 };
16536
16537 const tm_itr_t itr = map.find(symbol_name);
16538
16539 if (map.end() == itr)
16540 {
16541 map[symbol_name] = tie::make(t,is_const);
16542 ++size;
16543 }
16544
16545 return true;
16546 }
16547
16548 inline type_ptr get(const std::string& symbol_name) const
16549 {
16550 const tm_const_itr_t itr = map.find(symbol_name);
16551
16552 if (map.end() == itr)
16553 return reinterpret_cast<type_ptr>(0);
16554 else
16555 return itr->second.second;
16556 }
16557
16558 template <typename TType, typename TRawType, typename PtrType>
16559 struct ptr_match
16560 {
16561 static inline bool test(const PtrType, const void*)
16562 {
16563 return false;
16564 }
16565 };
16566
16567 template <typename TType, typename TRawType>
16568 struct ptr_match<TType,TRawType,variable_node_t*>
16569 {
16570 static inline bool test(const variable_node_t* p, const void* ptr)
16571 {
16572 exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
16573 return (&(p->ref()) == ptr);
16574 }
16575 };
16576
16577 inline type_ptr get_from_varptr(const void* ptr) const
16578 {
16579 tm_const_itr_t itr = map.begin();
16580
16581 while (map.end() != itr)
16582 {
16583 type_ptr ret_ptr = itr->second.second;
16584
16585 if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
16586 {
16587 return ret_ptr;
16588 }
16589
16590 ++itr;
16591 }
16592
16593 return type_ptr(0);
16594 }
16595
16596 inline bool remove(const std::string& symbol_name, const bool delete_node = true)
16597 {
16598 const tm_itr_t itr = map.find(symbol_name);
16599
16600 if (map.end() != itr)
16601 {
16602 struct deleter
16603 {
16604 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16605 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16606 #ifndef exprtk_disable_string_capabilities
16607 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16608 #endif
16609 static inline void process(std::pair<bool,function_t*>&) { }
16610 };
16611
16612 if (delete_node)
16613 {
16614 deleter::process((*itr).second);
16615 }
16616
16617 map.erase(itr);
16618 --size;
16619
16620 return true;
16621 }
16622 else
16623 return false;
16624 }
16625
16626 inline RawType& type_ref(const std::string& symbol_name)
16627 {
16628 struct init_type
16629 {
16630 static inline double set(double) { return (0.0); }
16631 static inline double set(long double) { return (0.0); }
16632 static inline float set(float) { return (0.0f); }
16633 static inline std::string set(std::string) { return std::string(""); }
16634 };
16635
16636 static RawType null_type = init_type::set(RawType());
16637
16638 const tm_const_itr_t itr = map.find(symbol_name);
16639
16640 if (map.end() == itr)
16641 return null_type;
16642 else
16643 return itr->second.second->ref();
16644 }
16645
16646 inline void clear(const bool delete_node = true)
16647 {
16648 struct deleter
16649 {
16650 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16651 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16652 static inline void process(std::pair<bool,function_t*>&) { }
16653 #ifndef exprtk_disable_string_capabilities
16654 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16655 #endif
16656 };
16657
16658 if (!map.empty())
16659 {
16660 if (delete_node)
16661 {
16662 tm_itr_t itr = map.begin();
16663 tm_itr_t end = map.end ();
16664
16665 while (end != itr)
16666 {
16667 deleter::process((*itr).second);
16668 ++itr;
16669 }
16670 }
16671
16672 map.clear();
16673 }
16674
16675 size = 0;
16676 }
16677
16678 template <typename Allocator,
16679 template <typename, typename> class Sequence>
16680 inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
16681 {
16682 std::size_t count = 0;
16683
16684 if (!map.empty())
16685 {
16686 tm_const_itr_t itr = map.begin();
16687 tm_const_itr_t end = map.end ();
16688
16689 while (end != itr)
16690 {
16691 list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
16692 ++itr;
16693 ++count;
16694 }
16695 }
16696
16697 return count;
16698 }
16699
16700 template <typename Allocator,
16701 template <typename, typename> class Sequence>
16702 inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
16703 {
16704 std::size_t count = 0;
16705
16706 if (!map.empty())
16707 {
16708 tm_const_itr_t itr = map.begin();
16709 tm_const_itr_t end = map.end ();
16710
16711 while (end != itr)
16712 {
16713 vlist.push_back((*itr).first);
16714 ++itr;
16715 ++count;
16716 }
16717 }
16718
16719 return count;
16720 }
16721 };
16722
16723 typedef details::expression_node<T>* expression_ptr;
16724 typedef typename details::variable_node<T> variable_t;
16725 typedef typename details::vector_holder<T> vector_holder_t;
16726 typedef variable_t* variable_ptr;
16727 #ifndef exprtk_disable_string_capabilities
16728 typedef typename details::stringvar_node<T> stringvar_t;
16729 typedef stringvar_t* stringvar_ptr;
16730 #endif
16731 typedef ifunction <T> function_t;
16732 typedef ivararg_function <T> vararg_function_t;
16733 typedef igeneric_function<T> generic_function_t;
16734 typedef function_t* function_ptr;
16735 typedef vararg_function_t* vararg_function_ptr;
16736 typedef generic_function_t* generic_function_ptr;
16737
16738 static const std::size_t lut_size = 256;
16739
16740 // Symbol Table Holder
16741 struct control_block
16742 {
16743 struct st_data
16744 {
16745 type_store<typename details::variable_node<T>,T> variable_store;
16746 #ifndef exprtk_disable_string_capabilities
16747 type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
16748 #endif
16749 type_store<ifunction<T>,ifunction<T> > function_store;
16750 type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
16751 type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
16752 type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
16753 type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store;
16754 type_store<vector_holder_t,vector_holder_t> vector_store;
16755
16756 st_data()
16757 {
16758 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
16759 {
16760 reserved_symbol_table_.insert(details::reserved_words[i]);
16761 }
16762
16763 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16764 {
16765 reserved_symbol_table_.insert(details::reserved_symbols[i]);
16766 }
16767 }
16768
16769 ~st_data()
16770 {
16771 for (std::size_t i = 0; i < free_function_list_.size(); ++i)
16772 {
16773 delete free_function_list_[i];
16774 }
16775 }
16776
16777 inline bool is_reserved_symbol(const std::string& symbol) const
16778 {
16779 return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
16780 }
16781
16782 static inline st_data* create()
16783 {
16784 return (new st_data);
16785 }
16786
16787 static inline void destroy(st_data*& sd)
16788 {
16789 delete sd;
16790 sd = reinterpret_cast<st_data*>(0);
16791 }
16792
16793 std::list<T> local_symbol_list_;
16794 std::list<std::string> local_stringvar_list_;
16795 std::set<std::string> reserved_symbol_table_;
16796 std::vector<ifunction<T>*> free_function_list_;
16797 };
16798
16799 control_block()
16800 : ref_count(1),
16801 data_(st_data::create())
16802 {}
16803
16804 explicit control_block(st_data* data)
16805 : ref_count(1),
16806 data_(data)
16807 {}
16808
16809 ~control_block()
16810 {
16811 if (data_ && (0 == ref_count))
16812 {
16813 st_data::destroy(data_);
16814 }
16815 }
16816
16817 static inline control_block* create()
16818 {
16819 return (new control_block);
16820 }
16821
16822 template <typename SymTab>
16823 static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
16824 {
16825 if (cntrl_blck)
16826 {
16827 if (
16828 (0 != cntrl_blck->ref_count) &&
16829 (0 == --cntrl_blck->ref_count)
16830 )
16831 {
16832 if (sym_tab)
16833 sym_tab->clear();
16834
16835 delete cntrl_blck;
16836 }
16837
16838 cntrl_blck = 0;
16839 }
16840 }
16841
16842 std::size_t ref_count;
16843 st_data* data_;
16844 };
16845
16846 public:
16847
16848 symbol_table()
16849 : control_block_(control_block::create())
16850 {
16851 clear();
16852 }
16853
16854 ~symbol_table()
16855 {
16856 control_block::destroy(control_block_,this);
16857 }
16858
16859 symbol_table(const symbol_table<T>& st)
16860 {
16861 control_block_ = st.control_block_;
16862 control_block_->ref_count++;
16863 }
16864
16865 inline symbol_table<T>& operator=(const symbol_table<T>& st)
16866 {
16867 if (this != &st)
16868 {
16869 control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
16870
16871 control_block_ = st.control_block_;
16872 control_block_->ref_count++;
16873 }
16874
16875 return (*this);
16876 }
16877
16878 inline bool operator==(const symbol_table<T>& st) const
16879 {
16880 return (this == &st) || (control_block_ == st.control_block_);
16881 }
16882
16883 inline void clear_variables(const bool delete_node = true)
16884 {
16885 local_data().variable_store.clear(delete_node);
16886 }
16887
16888 inline void clear_functions()
16889 {
16890 local_data().function_store.clear();
16891 }
16892
16893 inline void clear_strings()
16894 {
16895 #ifndef exprtk_disable_string_capabilities
16896 local_data().stringvar_store.clear();
16897 #endif
16898 }
16899
16900 inline void clear_vectors()
16901 {
16902 local_data().vector_store.clear();
16903 }
16904
16905 inline void clear_local_constants()
16906 {
16907 local_data().local_symbol_list_.clear();
16908 }
16909
16910 inline void clear()
16911 {
16912 if (!valid()) return;
16913 clear_variables ();
16914 clear_functions ();
16915 clear_strings ();
16916 clear_vectors ();
16917 clear_local_constants();
16918 }
16919
16920 inline std::size_t variable_count() const
16921 {
16922 if (valid())
16923 return local_data().variable_store.size;
16924 else
16925 return 0;
16926 }
16927
16928 #ifndef exprtk_disable_string_capabilities
16929 inline std::size_t stringvar_count() const
16930 {
16931 if (valid())
16932 return local_data().stringvar_store.size;
16933 else
16934 return 0;
16935 }
16936 #endif
16937
16938 inline std::size_t function_count() const
16939 {
16940 if (valid())
16941 return local_data().function_store.size;
16942 else
16943 return 0;
16944 }
16945
16946 inline std::size_t vector_count() const
16947 {
16948 if (valid())
16949 return local_data().vector_store.size;
16950 else
16951 return 0;
16952 }
16953
16954 inline variable_ptr get_variable(const std::string& variable_name) const
16955 {
16956 if (!valid())
16957 return reinterpret_cast<variable_ptr>(0);
16958 else if (!valid_symbol(variable_name))
16959 return reinterpret_cast<variable_ptr>(0);
16960 else
16961 return local_data().variable_store.get(variable_name);
16962 }
16963
16964 inline variable_ptr get_variable(const T& var_ref) const
16965 {
16966 if (!valid())
16967 return reinterpret_cast<variable_ptr>(0);
16968 else
16969 return local_data().variable_store.get_from_varptr(
16970 reinterpret_cast<const void*>(&var_ref));
16971 }
16972
16973 #ifndef exprtk_disable_string_capabilities
16974 inline stringvar_ptr get_stringvar(const std::string& string_name) const
16975 {
16976 if (!valid())
16977 return reinterpret_cast<stringvar_ptr>(0);
16978 else if (!valid_symbol(string_name))
16979 return reinterpret_cast<stringvar_ptr>(0);
16980 else
16981 return local_data().stringvar_store.get(string_name);
16982 }
16983 #endif
16984
16985 inline function_ptr get_function(const std::string& function_name) const
16986 {
16987 if (!valid())
16988 return reinterpret_cast<function_ptr>(0);
16989 else if (!valid_symbol(function_name))
16990 return reinterpret_cast<function_ptr>(0);
16991 else
16992 return local_data().function_store.get(function_name);
16993 }
16994
16995 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
16996 {
16997 if (!valid())
16998 return reinterpret_cast<vararg_function_ptr>(0);
16999 else if (!valid_symbol(vararg_function_name))
17000 return reinterpret_cast<vararg_function_ptr>(0);
17001 else
17002 return local_data().vararg_function_store.get(vararg_function_name);
17003 }
17004
17005 inline generic_function_ptr get_generic_function(const std::string& function_name) const
17006 {
17007 if (!valid())
17008 return reinterpret_cast<generic_function_ptr>(0);
17009 else if (!valid_symbol(function_name))
17010 return reinterpret_cast<generic_function_ptr>(0);
17011 else
17012 return local_data().generic_function_store.get(function_name);
17013 }
17014
17015 inline generic_function_ptr get_string_function(const std::string& function_name) const
17016 {
17017 if (!valid())
17018 return reinterpret_cast<generic_function_ptr>(0);
17019 else if (!valid_symbol(function_name))
17020 return reinterpret_cast<generic_function_ptr>(0);
17021 else
17022 return local_data().string_function_store.get(function_name);
17023 }
17024
17025 inline generic_function_ptr get_overload_function(const std::string& function_name) const
17026 {
17027 if (!valid())
17028 return reinterpret_cast<generic_function_ptr>(0);
17029 else if (!valid_symbol(function_name))
17030 return reinterpret_cast<generic_function_ptr>(0);
17031 else
17032 return local_data().overload_function_store.get(function_name);
17033 }
17034
17035 typedef vector_holder_t* vector_holder_ptr;
17036
17037 inline vector_holder_ptr get_vector(const std::string& vector_name) const
17038 {
17039 if (!valid())
17040 return reinterpret_cast<vector_holder_ptr>(0);
17041 else if (!valid_symbol(vector_name))
17042 return reinterpret_cast<vector_holder_ptr>(0);
17043 else
17044 return local_data().vector_store.get(vector_name);
17045 }
17046
17047 inline T& variable_ref(const std::string& symbol_name)
17048 {
17049 static T null_var = T(0);
17050 if (!valid())
17051 return null_var;
17052 else if (!valid_symbol(symbol_name))
17053 return null_var;
17054 else
17055 return local_data().variable_store.type_ref(symbol_name);
17056 }
17057
17058 #ifndef exprtk_disable_string_capabilities
17059 inline std::string& stringvar_ref(const std::string& symbol_name)
17060 {
17061 static std::string null_stringvar;
17062 if (!valid())
17063 return null_stringvar;
17064 else if (!valid_symbol(symbol_name))
17065 return null_stringvar;
17066 else
17067 return local_data().stringvar_store.type_ref(symbol_name);
17068 }
17069 #endif
17070
17071 inline bool is_constant_node(const std::string& symbol_name) const
17072 {
17073 if (!valid())
17074 return false;
17075 else if (!valid_symbol(symbol_name))
17076 return false;
17077 else
17078 return local_data().variable_store.is_constant(symbol_name);
17079 }
17080
17081 #ifndef exprtk_disable_string_capabilities
17082 inline bool is_constant_string(const std::string& symbol_name) const
17083 {
17084 if (!valid())
17085 return false;
17086 else if (!valid_symbol(symbol_name))
17087 return false;
17088 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17089 return false;
17090 else
17091 return local_data().stringvar_store.is_constant(symbol_name);
17092 }
17093 #endif
17094
17095 inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17096 {
17097 if (!valid())
17098 return false;
17099 else if (!valid_symbol(variable_name))
17100 return false;
17101 else if (symbol_exists(variable_name))
17102 return false;
17103
17104 local_data().local_symbol_list_.push_back(value);
17105 T& t = local_data().local_symbol_list_.back();
17106
17107 return add_variable(variable_name,t);
17108 }
17109
17110 #ifndef exprtk_disable_string_capabilities
17111 inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17112 {
17113 if (!valid())
17114 return false;
17115 else if (!valid_symbol(stringvar_name))
17116 return false;
17117 else if (symbol_exists(stringvar_name))
17118 return false;
17119
17120 local_data().local_stringvar_list_.push_back(value);
17121 std::string& s = local_data().local_stringvar_list_.back();
17122
17123 return add_stringvar(stringvar_name,s);
17124 }
17125 #endif
17126
17127 inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17128 {
17129 if (!valid())
17130 return false;
17131 else if (!valid_symbol(variable_name))
17132 return false;
17133 else if (symbol_exists(variable_name))
17134 return false;
17135 else
17136 return local_data().variable_store.add(variable_name, t, is_constant);
17137 }
17138
17139 inline bool add_constant(const std::string& constant_name, const T& value)
17140 {
17141 if (!valid())
17142 return false;
17143 else if (!valid_symbol(constant_name))
17144 return false;
17145 else if (symbol_exists(constant_name))
17146 return false;
17147
17148 local_data().local_symbol_list_.push_back(value);
17149 T& t = local_data().local_symbol_list_.back();
17150
17151 return add_variable(constant_name, t, true);
17152 }
17153
17154 #ifndef exprtk_disable_string_capabilities
17155 inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17156 {
17157 if (!valid())
17158 return false;
17159 else if (!valid_symbol(stringvar_name))
17160 return false;
17161 else if (symbol_exists(stringvar_name))
17162 return false;
17163 else
17164 return local_data().stringvar_store.add(stringvar_name, s, is_constant);
17165 }
17166 #endif
17167
17168 inline bool add_function(const std::string& function_name, function_t& function)
17169 {
17170 if (!valid())
17171 return false;
17172 else if (!valid_symbol(function_name))
17173 return false;
17174 else if (symbol_exists(function_name))
17175 return false;
17176 else
17177 return local_data().function_store.add(function_name,function);
17178 }
17179
17180 inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17181 {
17182 if (!valid())
17183 return false;
17184 else if (!valid_symbol(vararg_function_name))
17185 return false;
17186 else if (symbol_exists(vararg_function_name))
17187 return false;
17188 else
17189 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17190 }
17191
17192 inline bool add_function(const std::string& function_name, generic_function_t& function)
17193 {
17194 if (!valid())
17195 return false;
17196 else if (!valid_symbol(function_name))
17197 return false;
17198 else if (symbol_exists(function_name))
17199 return false;
17200 else if (
17201 (
17202 (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17203 (generic_function_t::e_rtrn_string == function.rtrn_type)
17204 ) &&
17205 std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
17206 )
17207 return false;
17208 else if (
17209 (generic_function_t::e_rtrn_overload == function.rtrn_type) &&
17210 std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
17211 )
17212 return false;
17213
17214 switch (function.rtrn_type)
17215 {
17216 case generic_function_t::e_rtrn_scalar :
17217 return local_data().generic_function_store.add(function_name,function);
17218
17219 case generic_function_t::e_rtrn_string :
17220 return local_data().string_function_store.add(function_name,function);
17221
17222 case generic_function_t::e_rtrn_overload :
17223 return local_data().overload_function_store.add(function_name,function);
17224 }
17225
17226 return false;
17227 }
17228
17229 #define exprtk_define_freefunction(NN) \
17230 inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17231 { \
17232 if (!valid()) \
17233 { return false; } \
17234 if (!valid_symbol(function_name)) \
17235 { return false; } \
17236 if (symbol_exists(function_name)) \
17237 { return false; } \
17238 \
17239 exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
17240 \
17241 local_data().free_function_list_.push_back(ifunc); \
17242 \
17243 return add_function(function_name,(*local_data().free_function_list_.back())); \
17244 } \
17245
17246 exprtk_define_freefunction(00) exprtk_define_freefunction(01)
17247 exprtk_define_freefunction(02) exprtk_define_freefunction(03)
17248 exprtk_define_freefunction(04) exprtk_define_freefunction(05)
17249 exprtk_define_freefunction(06) exprtk_define_freefunction(07)
17250 exprtk_define_freefunction(08) exprtk_define_freefunction(09)
17251 exprtk_define_freefunction(10) exprtk_define_freefunction(11)
17252 exprtk_define_freefunction(12) exprtk_define_freefunction(13)
17253 exprtk_define_freefunction(14) exprtk_define_freefunction(15)
17254
17255 #undef exprtk_define_freefunction
17256
17257 inline bool add_reserved_function(const std::string& function_name, function_t& function)
17258 {
17259 if (!valid())
17260 return false;
17261 else if (!valid_symbol(function_name,false))
17262 return false;
17263 else if (symbol_exists(function_name,false))
17264 return false;
17265 else
17266 return local_data().function_store.add(function_name,function);
17267 }
17268
17269 inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17270 {
17271 if (!valid())
17272 return false;
17273 else if (!valid_symbol(vararg_function_name,false))
17274 return false;
17275 else if (symbol_exists(vararg_function_name,false))
17276 return false;
17277 else
17278 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17279 }
17280
17281 inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
17282 {
17283 if (!valid())
17284 return false;
17285 else if (!valid_symbol(function_name,false))
17286 return false;
17287 else if (symbol_exists(function_name,false))
17288 return false;
17289 else if (
17290 (
17291 (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17292 (generic_function_t::e_rtrn_string == function.rtrn_type)
17293 ) &&
17294 std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
17295 )
17296 return false;
17297 else if (
17298 generic_function_t::e_rtrn_overload &&
17299 std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
17300 )
17301 return false;
17302
17303 switch (function.rtrn_type)
17304 {
17305 case generic_function_t::e_rtrn_scalar :
17306 return local_data().generic_function_store.add(function_name,function);
17307
17308 case generic_function_t::e_rtrn_string :
17309 return local_data().string_function_store.add(function_name,function);
17310
17311 case generic_function_t::e_rtrn_overload :
17312 return local_data().overload_function_store.add(function_name,function);
17313 }
17314
17315 return false;
17316 }
17317
17318 template <std::size_t N>
17319 inline bool add_vector(const std::string& vector_name, T (&v)[N])
17320 {
17321 if (!valid())
17322 return false;
17323 else if (!valid_symbol(vector_name))
17324 return false;
17325 else if (symbol_exists(vector_name))
17326 return false;
17327 else
17328 return local_data().vector_store.add(vector_name,v);
17329 }
17330
17331 inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
17332 {
17333 if (!valid())
17334 return false;
17335 else if (!valid_symbol(vector_name))
17336 return false;
17337 else if (symbol_exists(vector_name))
17338 return false;
17339 else if (0 == v_size)
17340 return false;
17341 else
17342 return local_data().vector_store.add(vector_name, v, v_size);
17343 }
17344
17345 template <typename Allocator>
17346 inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
17347 {
17348 if (!valid())
17349 return false;
17350 else if (!valid_symbol(vector_name))
17351 return false;
17352 else if (symbol_exists(vector_name))
17353 return false;
17354 else if (0 == v.size())
17355 return false;
17356 else
17357 return local_data().vector_store.add(vector_name,v);
17358 }
17359
17360 inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
17361 {
17362 if (!valid())
17363 return false;
17364 else if (!valid_symbol(vector_name))
17365 return false;
17366 else if (symbol_exists(vector_name))
17367 return false;
17368 else if (0 == v.size())
17369 return false;
17370 else
17371 return local_data().vector_store.add(vector_name,v);
17372 }
17373
17374 inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
17375 {
17376 if (!valid())
17377 return false;
17378 else
17379 return local_data().variable_store.remove(variable_name, delete_node);
17380 }
17381
17382 #ifndef exprtk_disable_string_capabilities
17383 inline bool remove_stringvar(const std::string& string_name)
17384 {
17385 if (!valid())
17386 return false;
17387 else
17388 return local_data().stringvar_store.remove(string_name);
17389 }
17390 #endif
17391
17392 inline bool remove_function(const std::string& function_name)
17393 {
17394 if (!valid())
17395 return false;
17396 else
17397 return local_data().function_store.remove(function_name);
17398 }
17399
17400 inline bool remove_vararg_function(const std::string& vararg_function_name)
17401 {
17402 if (!valid())
17403 return false;
17404 else
17405 return local_data().vararg_function_store.remove(vararg_function_name);
17406 }
17407
17408 inline bool remove_vector(const std::string& vector_name)
17409 {
17410 if (!valid())
17411 return false;
17412 else
17413 return local_data().vector_store.remove(vector_name);
17414 }
17415
17416 inline bool add_constants()
17417 {
17418 return add_pi () &&
17419 add_epsilon () &&
17420 add_infinity() ;
17421 }
17422
17423 inline bool add_pi()
17424 {
17425 const typename details::numeric::details::number_type<T>::type num_type;
17426 static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
17427 return add_constant("pi",local_pi);
17428 }
17429
17430 inline bool add_epsilon()
17431 {
17432 static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
17433 return add_constant("epsilon",local_epsilon);
17434 }
17435
17436 inline bool add_infinity()
17437 {
17438 static const T local_infinity = std::numeric_limits<T>::infinity();
17439 return add_constant("inf",local_infinity);
17440 }
17441
17442 template <typename Package>
17443 inline bool add_package(Package& package)
17444 {
17445 return package.register_package(*this);
17446 }
17447
17448 template <typename Allocator,
17449 template <typename, typename> class Sequence>
17450 inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
17451 {
17452 if (!valid())
17453 return 0;
17454 else
17455 return local_data().variable_store.get_list(vlist);
17456 }
17457
17458 template <typename Allocator,
17459 template <typename, typename> class Sequence>
17460 inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
17461 {
17462 if (!valid())
17463 return 0;
17464 else
17465 return local_data().variable_store.get_list(vlist);
17466 }
17467
17468 #ifndef exprtk_disable_string_capabilities
17469 template <typename Allocator,
17470 template <typename, typename> class Sequence>
17471 inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
17472 {
17473 if (!valid())
17474 return 0;
17475 else
17476 return local_data().stringvar_store.get_list(svlist);
17477 }
17478
17479 template <typename Allocator,
17480 template <typename, typename> class Sequence>
17481 inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
17482 {
17483 if (!valid())
17484 return 0;
17485 else
17486 return local_data().stringvar_store.get_list(svlist);
17487 }
17488 #endif
17489
17490 template <typename Allocator,
17491 template <typename, typename> class Sequence>
17492 inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
17493 {
17494 if (!valid())
17495 return 0;
17496 else
17497 return local_data().vector_store.get_list(vlist);
17498 }
17499
17500 inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
17501 {
17502 /*
17503 Function will return true if symbol_name exists as either a
17504 reserved symbol, variable, stringvar, vector or function name
17505 in any of the type stores.
17506 */
17507 if (!valid())
17508 return false;
17509 else if (local_data().variable_store.symbol_exists(symbol_name))
17510 return true;
17511 #ifndef exprtk_disable_string_capabilities
17512 else if (local_data().stringvar_store.symbol_exists(symbol_name))
17513 return true;
17514 #endif
17515 else if (local_data().vector_store.symbol_exists(symbol_name))
17516 return true;
17517 else if (local_data().function_store.symbol_exists(symbol_name))
17518 return true;
17519 else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
17520 return true;
17521 else
17522 return false;
17523 }
17524
17525 inline bool is_variable(const std::string& variable_name) const
17526 {
17527 if (!valid())
17528 return false;
17529 else
17530 return local_data().variable_store.symbol_exists(variable_name);
17531 }
17532
17533 #ifndef exprtk_disable_string_capabilities
17534 inline bool is_stringvar(const std::string& stringvar_name) const
17535 {
17536 if (!valid())
17537 return false;
17538 else
17539 return local_data().stringvar_store.symbol_exists(stringvar_name);
17540 }
17541
17542 inline bool is_conststr_stringvar(const std::string& symbol_name) const
17543 {
17544 if (!valid())
17545 return false;
17546 else if (!valid_symbol(symbol_name))
17547 return false;
17548 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17549 return false;
17550
17551 return (
17552 local_data().stringvar_store.symbol_exists(symbol_name) ||
17553 local_data().stringvar_store.is_constant (symbol_name)
17554 );
17555 }
17556 #endif
17557
17558 inline bool is_function(const std::string& function_name) const
17559 {
17560 if (!valid())
17561 return false;
17562 else
17563 return local_data().function_store.symbol_exists(function_name);
17564 }
17565
17566 inline bool is_vararg_function(const std::string& vararg_function_name) const
17567 {
17568 if (!valid())
17569 return false;
17570 else
17571 return local_data().vararg_function_store.symbol_exists(vararg_function_name);
17572 }
17573
17574 inline bool is_vector(const std::string& vector_name) const
17575 {
17576 if (!valid())
17577 return false;
17578 else
17579 return local_data().vector_store.symbol_exists(vector_name);
17580 }
17581
17582 inline std::string get_variable_name(const expression_ptr& ptr) const
17583 {
17584 return local_data().variable_store.entity_name(ptr);
17585 }
17586
17587 inline std::string get_vector_name(const vector_holder_ptr& ptr) const
17588 {
17589 return local_data().vector_store.entity_name(ptr);
17590 }
17591
17592 #ifndef exprtk_disable_string_capabilities
17593 inline std::string get_stringvar_name(const expression_ptr& ptr) const
17594 {
17595 return local_data().stringvar_store.entity_name(ptr);
17596 }
17597
17598 inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
17599 {
17600 return local_data().stringvar_store.entity_name(ptr);
17601 }
17602 #endif
17603
17604 inline bool valid() const
17605 {
17606 // Symbol table sanity check.
17607 return control_block_ && control_block_->data_;
17608 }
17609
17610 inline void load_from(const symbol_table<T>& st)
17611 {
17612 {
17613 std::vector<std::string> name_list;
17614
17615 st.local_data().function_store.get_list(name_list);
17616
17617 if (!name_list.empty())
17618 {
17619 for (std::size_t i = 0; i < name_list.size(); ++i)
17620 {
17621 exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
17622 add_function(name_list[i],ifunc);
17623 }
17624 }
17625 }
17626
17627 {
17628 std::vector<std::string> name_list;
17629
17630 st.local_data().vararg_function_store.get_list(name_list);
17631
17632 if (!name_list.empty())
17633 {
17634 for (std::size_t i = 0; i < name_list.size(); ++i)
17635 {
17636 exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
17637 add_function(name_list[i],ivafunc);
17638 }
17639 }
17640 }
17641
17642 {
17643 std::vector<std::string> name_list;
17644
17645 st.local_data().generic_function_store.get_list(name_list);
17646
17647 if (!name_list.empty())
17648 {
17649 for (std::size_t i = 0; i < name_list.size(); ++i)
17650 {
17651 exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
17652 add_function(name_list[i],ifunc);
17653 }
17654 }
17655 }
17656
17657 {
17658 std::vector<std::string> name_list;
17659
17660 st.local_data().string_function_store.get_list(name_list);
17661
17662 if (!name_list.empty())
17663 {
17664 for (std::size_t i = 0; i < name_list.size(); ++i)
17665 {
17666 exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
17667 add_function(name_list[i],ifunc);
17668 }
17669 }
17670 }
17671
17672 {
17673 std::vector<std::string> name_list;
17674
17675 st.local_data().overload_function_store.get_list(name_list);
17676
17677 if (!name_list.empty())
17678 {
17679 for (std::size_t i = 0; i < name_list.size(); ++i)
17680 {
17681 exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
17682 add_function(name_list[i],ifunc);
17683 }
17684 }
17685 }
17686 }
17687
17688 private:
17689
17690 inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
17691 {
17692 if (symbol.empty())
17693 return false;
17694 else if (!details::is_letter(symbol[0]))
17695 return false;
17696 else if (symbol.size() > 1)
17697 {
17698 for (std::size_t i = 1; i < symbol.size(); ++i)
17699 {
17700 if (
17701 !details::is_letter_or_digit(symbol[i]) &&
17702 ('_' != symbol[i])
17703 )
17704 {
17705 if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17706 continue;
17707 else
17708 return false;
17709 }
17710 }
17711 }
17712
17713 return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
17714 }
17715
17716 inline bool valid_function(const std::string& symbol) const
17717 {
17718 if (symbol.empty())
17719 return false;
17720 else if (!details::is_letter(symbol[0]))
17721 return false;
17722 else if (symbol.size() > 1)
17723 {
17724 for (std::size_t i = 1; i < symbol.size(); ++i)
17725 {
17726 if (
17727 !details::is_letter_or_digit(symbol[i]) &&
17728 ('_' != symbol[i])
17729 )
17730 {
17731 if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17732 continue;
17733 else
17734 return false;
17735 }
17736 }
17737 }
17738
17739 return true;
17740 }
17741
17742 typedef typename control_block::st_data local_data_t;
17743
17744 inline local_data_t& local_data()
17745 {
17746 return *(control_block_->data_);
17747 }
17748
17749 inline const local_data_t& local_data() const
17750 {
17751 return *(control_block_->data_);
17752 }
17753
17754 control_block* control_block_;
17755
17756 friend class parser<T>;
17757 };
17758
17759 template <typename T>
17760 class function_compositor;
17761
17762 template <typename T>
17763 class expression
17764 {
17765 private:
17766
17767 typedef details::expression_node<T>* expression_ptr;
17768 typedef details::vector_holder<T>* vector_holder_ptr;
17769 typedef std::vector<symbol_table<T> > symtab_list_t;
17770
17771 struct control_block
17772 {
17773 enum data_type
17774 {
17775 e_unknown ,
17776 e_expr ,
17777 e_vecholder,
17778 e_data ,
17779 e_vecdata ,
17780 e_string
17781 };
17782
17783 struct data_pack
17784 {
17785 data_pack()
17786 : pointer(0),
17787 type(e_unknown),
17788 size(0)
17789 {}
17790
17791 data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
17792 : pointer(ptr),
17793 type(dt),
17794 size(sz)
17795 {}
17796
17797 void* pointer;
17798 data_type type;
17799 std::size_t size;
17800 };
17801
17802 typedef std::vector<data_pack> local_data_list_t;
17803 typedef results_context<T> results_context_t;
17804
17805 control_block()
17806 : ref_count(0),
17807 expr (0),
17808 results (0),
17809 retinv_null(false),
17810 return_invoked(&retinv_null)
17811 {}
17812
17813 explicit control_block(expression_ptr e)
17814 : ref_count(1),
17815 expr (e),
17816 results (0),
17817 retinv_null(false),
17818 return_invoked(&retinv_null)
17819 {}
17820
17821 ~control_block()
17822 {
17823 if (expr && details::branch_deletable(expr))
17824 {
17825 destroy_node(expr);
17826 }
17827
17828 if (!local_data_list.empty())
17829 {
17830 for (std::size_t i = 0; i < local_data_list.size(); ++i)
17831 {
17832 switch (local_data_list[i].type)
17833 {
17834 case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
17835 break;
17836
17837 case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
17838 break;
17839
17840 case e_data : delete (T*)(local_data_list[i].pointer);
17841 break;
17842
17843 case e_vecdata : delete [] (T*)(local_data_list[i].pointer);
17844 break;
17845
17846 case e_string : delete (std::string*)(local_data_list[i].pointer);
17847 break;
17848
17849 default : break;
17850 }
17851 }
17852 }
17853
17854 if (results)
17855 {
17856 delete results;
17857 }
17858 }
17859
17860 static inline control_block* create(expression_ptr e)
17861 {
17862 return new control_block(e);
17863 }
17864
17865 static inline void destroy(control_block*& cntrl_blck)
17866 {
17867 if (cntrl_blck)
17868 {
17869 if (
17870 (0 != cntrl_blck->ref_count) &&
17871 (0 == --cntrl_blck->ref_count)
17872 )
17873 {
17874 delete cntrl_blck;
17875 }
17876
17877 cntrl_blck = 0;
17878 }
17879 }
17880
17881 std::size_t ref_count;
17882 expression_ptr expr;
17883 local_data_list_t local_data_list;
17884 results_context_t* results;
17885 bool retinv_null;
17886 bool* return_invoked;
17887
17888 friend class function_compositor<T>;
17889 };
17890
17891 public:
17892
17893 expression()
17894 : control_block_(0)
17895 {
17896 set_expression(new details::null_node<T>());
17897 }
17898
17899 expression(const expression<T>& e)
17900 : control_block_ (e.control_block_ ),
17901 symbol_table_list_(e.symbol_table_list_)
17902 {
17903 control_block_->ref_count++;
17904 }
17905
17906 explicit expression(const symbol_table<T>& symbol_table)
17907 : control_block_(0)
17908 {
17909 set_expression(new details::null_node<T>());
17910 symbol_table_list_.push_back(symbol_table);
17911 }
17912
17913 inline expression<T>& operator=(const expression<T>& e)
17914 {
17915 if (this != &e)
17916 {
17917 if (control_block_)
17918 {
17919 if (
17920 (0 != control_block_->ref_count) &&
17921 (0 == --control_block_->ref_count)
17922 )
17923 {
17924 delete control_block_;
17925 }
17926
17927 control_block_ = 0;
17928 }
17929
17930 control_block_ = e.control_block_;
17931 control_block_->ref_count++;
17932 symbol_table_list_ = e.symbol_table_list_;
17933 }
17934
17935 return *this;
17936 }
17937
17938 inline bool operator==(const expression<T>& e) const
17939 {
17940 return (this == &e);
17941 }
17942
17943 inline bool operator!() const
17944 {
17945 return (
17946 (0 == control_block_ ) ||
17947 (0 == control_block_->expr)
17948 );
17949 }
17950
17951 inline expression<T>& release()
17952 {
17953 control_block::destroy(control_block_);
17954
17955 return (*this);
17956 }
17957
17958 ~expression()
17959 {
17960 control_block::destroy(control_block_);
17961 }
17962
17963 inline T value() const
17964 {
17965 return control_block_->expr->value();
17966 }
17967
17968 inline T operator() () const
17969 {
17970 return value();
17971 }
17972
17973 inline operator T() const
17974 {
17975 return value();
17976 }
17977
17978 inline operator bool() const
17979 {
17980 return details::is_true(value());
17981 }
17982
17983 inline void register_symbol_table(symbol_table<T>& st)
17984 {
17985 symbol_table_list_.push_back(st);
17986 }
17987
17988 inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
17989 {
17990 return symbol_table_list_[index];
17991 }
17992
17993 inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
17994 {
17995 return symbol_table_list_[index];
17996 }
17997
17998 typedef results_context<T> results_context_t;
17999
18000 inline const results_context_t& results() const
18001 {
18002 if (control_block_->results)
18003 return (*control_block_->results);
18004 else
18005 {
18006 static const results_context_t null_results;
18007 return null_results;
18008 }
18009 }
18010
18011 inline bool return_invoked() const
18012 {
18013 return (*control_block_->return_invoked);
18014 }
18015
18016 private:
18017
18018 inline symtab_list_t get_symbol_table_list() const
18019 {
18020 return symbol_table_list_;
18021 }
18022
18023 inline void set_expression(const expression_ptr expr)
18024 {
18025 if (expr)
18026 {
18027 if (control_block_)
18028 {
18029 if (0 == --control_block_->ref_count)
18030 {
18031 delete control_block_;
18032 }
18033 }
18034
18035 control_block_ = control_block::create(expr);
18036 }
18037 }
18038
18039 inline void register_local_var(expression_ptr expr)
18040 {
18041 if (expr)
18042 {
18043 if (control_block_)
18044 {
18045 control_block_->
18046 local_data_list.push_back(
18047 typename expression<T>::control_block::
18048 data_pack(reinterpret_cast<void*>(expr),
18049 control_block::e_expr));
18050 }
18051 }
18052 }
18053
18054 inline void register_local_var(vector_holder_ptr vec_holder)
18055 {
18056 if (vec_holder)
18057 {
18058 if (control_block_)
18059 {
18060 control_block_->
18061 local_data_list.push_back(
18062 typename expression<T>::control_block::
18063 data_pack(reinterpret_cast<void*>(vec_holder),
18064 control_block::e_vecholder));
18065 }
18066 }
18067 }
18068
18069 inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18070 {
18071 if (data)
18072 {
18073 if (control_block_)
18074 {
18075 typename control_block::data_type dt = control_block::e_data;
18076
18077 switch (data_mode)
18078 {
18079 case 0 : dt = control_block::e_data; break;
18080 case 1 : dt = control_block::e_vecdata; break;
18081 case 2 : dt = control_block::e_string; break;
18082 }
18083
18084 control_block_->
18085 local_data_list.push_back(
18086 typename expression<T>::control_block::
18087 data_pack(reinterpret_cast<void*>(data), dt, size));
18088 }
18089 }
18090 }
18091
18092 inline const typename control_block::local_data_list_t& local_data_list()
18093 {
18094 if (control_block_)
18095 {
18096 return control_block_->local_data_list;
18097 }
18098 else
18099 {
18100 static typename control_block::local_data_list_t null_local_data_list;
18101 return null_local_data_list;
18102 }
18103 }
18104
18105 inline void register_return_results(results_context_t* rc)
18106 {
18107 if (control_block_ && rc)
18108 {
18109 control_block_->results = rc;
18110 }
18111 }
18112
18113 inline void set_retinvk(bool* retinvk_ptr)
18114 {
18115 if (control_block_)
18116 {
18117 control_block_->return_invoked = retinvk_ptr;
18118 }
18119 }
18120
18121 control_block* control_block_;
18122 symtab_list_t symbol_table_list_;
18123
18124 friend class parser<T>;
18125 friend class expression_helper<T>;
18126 friend class function_compositor<T>;
18127 };
18128
18129 template <typename T>
18130 class expression_helper
18131 {
18132 public:
18133
18134 static inline bool is_constant(const expression<T>& expr)
18135 {
18136 return details::is_constant_node(expr.control_block_->expr);
18137 }
18138
18139 static inline bool is_variable(const expression<T>& expr)
18140 {
18141 return details::is_variable_node(expr.control_block_->expr);
18142 }
18143
18144 static inline bool is_unary(const expression<T>& expr)
18145 {
18146 return details::is_unary_node(expr.control_block_->expr);
18147 }
18148
18149 static inline bool is_binary(const expression<T>& expr)
18150 {
18151 return details::is_binary_node(expr.control_block_->expr);
18152 }
18153
18154 static inline bool is_function(const expression<T>& expr)
18155 {
18156 return details::is_function(expr.control_block_->expr);
18157 }
18158
18159 static inline bool is_null(const expression<T>& expr)
18160 {
18161 return details::is_null_node(expr.control_block_->expr);
18162 }
18163 };
18164
18165 template <typename T>
18166 inline bool is_valid(const expression<T>& expr)
18167 {
18168 return !expression_helper<T>::is_null(expr);
18169 }
18170
18171 namespace parser_error
18172 {
18173 enum error_mode
18174 {
18175 e_unknown = 0,
18176 e_syntax = 1,
18177 e_token = 2,
18178 e_numeric = 4,
18179 e_symtab = 5,
18180 e_lexer = 6,
18181 e_helper = 7
18182 };
18183
18184 struct type
18185 {
18186 type()
18187 : mode(parser_error::e_unknown),
18188 line_no (0),
18189 column_no(0)
18190 {}
18191
18192 lexer::token token;
18193 error_mode mode;
18194 std::string diagnostic;
18195 std::string src_location;
18196 std::string error_line;
18197 std::size_t line_no;
18198 std::size_t column_no;
18199 };
18200
18201 inline type make_error(const error_mode mode,
18202 const std::string& diagnostic = "",
18203 const std::string& src_location = "")
18204 {
18205 type t;
18206 t.mode = mode;
18207 t.token.type = lexer::token::e_error;
18208 t.diagnostic = diagnostic;
18209 t.src_location = src_location;
18210 exprtk_debug(("%s\n",diagnostic .c_str()));
18211 return t;
18212 }
18213
18214 inline type make_error(const error_mode mode,
18215 const lexer::token& tk,
18216 const std::string& diagnostic = "",
18217 const std::string& src_location = "")
18218 {
18219 type t;
18220 t.mode = mode;
18221 t.token = tk;
18222 t.diagnostic = diagnostic;
18223 t.src_location = src_location;
18224 exprtk_debug(("%s\n",diagnostic .c_str()));
18225 return t;
18226 }
18227
18228 inline std::string to_str(error_mode mode)
18229 {
18230 switch (mode)
18231 {
18232 case e_unknown : return std::string("Unknown Error");
18233 case e_syntax : return std::string("Syntax Error" );
18234 case e_token : return std::string("Token Error" );
18235 case e_numeric : return std::string("Numeric Error");
18236 case e_symtab : return std::string("Symbol Error" );
18237 case e_lexer : return std::string("Lexer Error" );
18238 case e_helper : return std::string("Helper Error" );
18239 default : return std::string("Unknown Error");
18240 }
18241 }
18242
18243 inline bool update_error(type& error, const std::string& expression)
18244 {
18245 if (
18246 expression.empty() ||
18247 (error.token.position > expression.size()) ||
18248 (std::numeric_limits<std::size_t>::max() == error.token.position)
18249 )
18250 {
18251 return false;
18252 }
18253
18254 std::size_t error_line_start = 0;
18255
18256 for (std::size_t i = error.token.position; i > 0; --i)
18257 {
18258 const details::char_t c = expression[i];
18259
18260 if (('\n' == c) || ('\r' == c))
18261 {
18262 error_line_start = i + 1;
18263 break;
18264 }
18265 }
18266
18267 std::size_t next_nl_position = std::min(expression.size(),
18268 expression.find_first_of('\n',error.token.position + 1));
18269
18270 error.column_no = error.token.position - error_line_start;
18271 error.error_line = expression.substr(error_line_start,
18272 next_nl_position - error_line_start);
18273
18274 error.line_no = 0;
18275
18276 for (std::size_t i = 0; i < next_nl_position; ++i)
18277 {
18278 if ('\n' == expression[i])
18279 ++error.line_no;
18280 }
18281
18282 return true;
18283 }
18284
18285 inline void dump_error(const type& error)
18286 {
18287 printf("Position: %02d Type: [%s] Msg: %s\n",
18288 static_cast<int>(error.token.position),
18289 exprtk::parser_error::to_str(error.mode).c_str(),
18290 error.diagnostic.c_str());
18291 }
18292 }
18293
18294 namespace details
18295 {
18296 template <typename Parser>
18297 inline void disable_type_checking(Parser& p)
18298 {
18299 p.state_.type_check_enabled = false;
18300 }
18301 }
18302
18303 template <typename T>
18304 class parser : public lexer::parser_helper
18305 {
18306 private:
18307
18308 enum precedence_level
18309 {
18310 e_level00,
18311 e_level01,
18312 e_level02,
18313 e_level03,
18314 e_level04,
18315 e_level05,
18316 e_level06,
18317 e_level07,
18318 e_level08,
18319 e_level09,
18320 e_level10,
18321 e_level11,
18322 e_level12,
18323 e_level13,
18324 e_level14
18325 };
18326
18327 typedef const T& cref_t;
18328 typedef const T const_t;
18329 typedef ifunction <T> F;
18330 typedef ivararg_function <T> VAF;
18331 typedef igeneric_function <T> GF;
18332 typedef ifunction <T> ifunction_t;
18333 typedef ivararg_function <T> ivararg_function_t;
18334 typedef igeneric_function <T> igeneric_function_t;
18335 typedef details::expression_node <T> expression_node_t;
18336 typedef details::literal_node <T> literal_node_t;
18337 typedef details::unary_node <T> unary_node_t;
18338 typedef details::binary_node <T> binary_node_t;
18339 typedef details::trinary_node <T> trinary_node_t;
18340 typedef details::quaternary_node <T> quaternary_node_t;
18341 typedef details::conditional_node<T> conditional_node_t;
18342 typedef details::cons_conditional_node<T> cons_conditional_node_t;
18343 typedef details::while_loop_node <T> while_loop_node_t;
18344 typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
18345 typedef details::for_loop_node <T> for_loop_node_t;
18346 #ifndef exprtk_disable_break_continue
18347 typedef details::while_loop_bc_node <T> while_loop_bc_node_t;
18348 typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
18349 typedef details::for_loop_bc_node<T> for_loop_bc_node_t;
18350 #endif
18351 typedef details::switch_node <T> switch_node_t;
18352 typedef details::variable_node <T> variable_node_t;
18353 typedef details::vector_elem_node<T> vector_elem_node_t;
18354 typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t;
18355 typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
18356 typedef details::vector_node <T> vector_node_t;
18357 typedef details::range_pack <T> range_t;
18358 #ifndef exprtk_disable_string_capabilities
18359 typedef details::stringvar_node <T> stringvar_node_t;
18360 typedef details::string_literal_node<T> string_literal_node_t;
18361 typedef details::string_range_node <T> string_range_node_t;
18362 typedef details::const_string_range_node<T> const_string_range_node_t;
18363 typedef details::generic_string_range_node<T> generic_string_range_node_t;
18364 typedef details::string_concat_node <T> string_concat_node_t;
18365 typedef details::assignment_string_node<T> assignment_string_node_t;
18366 typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
18367 typedef details::conditional_string_node<T> conditional_string_node_t;
18368 typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
18369 #endif
18370 typedef details::assignment_node<T> assignment_node_t;
18371 typedef details::assignment_vec_elem_node <T> assignment_vec_elem_node_t;
18372 typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
18373 typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
18374 typedef details::assignment_vec_node <T> assignment_vec_node_t;
18375 typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
18376 typedef details::scand_node<T> scand_node_t;
18377 typedef details::scor_node<T> scor_node_t;
18378 typedef lexer::token token_t;
18379 typedef expression_node_t* expression_node_ptr;
18380 typedef expression<T> expression_t;
18381 typedef symbol_table<T> symbol_table_t;
18382 typedef typename expression<T>::symtab_list_t symbol_table_list_t;
18383 typedef details::vector_holder<T>* vector_holder_ptr;
18384
18385 typedef typename details::functor_t<T> functor_t;
18386 typedef typename functor_t::qfunc_t quaternary_functor_t;
18387 typedef typename functor_t::tfunc_t trinary_functor_t;
18388 typedef typename functor_t::bfunc_t binary_functor_t;
18389 typedef typename functor_t::ufunc_t unary_functor_t;
18390
18391 typedef details::operator_type operator_t;
18392
18393 typedef std::map<operator_t, unary_functor_t> unary_op_map_t;
18394 typedef std::map<operator_t, binary_functor_t> binary_op_map_t;
18395 typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
18396
18397 typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
18398 typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
18399
18400 typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
18401 typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
18402 typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
18403
18404 typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
18405 typedef details::T0oT1_define<T, const_t, cref_t> cov_t;
18406 typedef details::T0oT1_define<T, cref_t, const_t> voc_t;
18407
18408 typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
18409 typedef details::T0oT1oT2_define<T, cref_t, cref_t, const_t> vovoc_t;
18410 typedef details::T0oT1oT2_define<T, cref_t, const_t, cref_t> vocov_t;
18411 typedef details::T0oT1oT2_define<T, const_t, cref_t, cref_t> covov_t;
18412 typedef details::T0oT1oT2_define<T, const_t, cref_t, const_t> covoc_t;
18413 typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t> cocov_t;
18414 typedef details::T0oT1oT2_define<T, cref_t, const_t, const_t> vococ_t;
18415
18416 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
18417 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, const_t> vovovoc_t;
18418 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, const_t, cref_t> vovocov_t;
18419 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, cref_t> vocovov_t;
18420 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, cref_t> covovov_t;
18421
18422 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, const_t, cref_t> covocov_t;
18423 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, const_t> vocovoc_t;
18424 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, const_t> covovoc_t;
18425 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, const_t, cref_t> vococov_t;
18426
18427 typedef results_context<T> results_context_t;
18428
18429 typedef parser_helper prsrhlpr_t;
18430
18431 struct scope_element
18432 {
18433 enum element_type
18434 {
18435 e_none ,
18436 e_variable,
18437 e_vector ,
18438 e_vecelem ,
18439 e_string
18440 };
18441
18442 typedef details::vector_holder<T> vector_holder_t;
18443 typedef variable_node_t* variable_node_ptr;
18444 typedef vector_holder_t* vector_holder_ptr;
18445 typedef expression_node_t* expression_node_ptr;
18446 #ifndef exprtk_disable_string_capabilities
18447 typedef stringvar_node_t* stringvar_node_ptr;
18448 #endif
18449
18450 scope_element()
18451 : name("???"),
18452 size (std::numeric_limits<std::size_t>::max()),
18453 index(std::numeric_limits<std::size_t>::max()),
18454 depth(std::numeric_limits<std::size_t>::max()),
18455 ref_count(0),
18456 ip_index (0),
18457 type (e_none),
18458 active(false),
18459 data (0),
18460 var_node(0),
18461 vec_node(0)
18462 #ifndef exprtk_disable_string_capabilities
18463 ,str_node(0)
18464 #endif
18465 {}
18466
18467 bool operator < (const scope_element& se) const
18468 {
18469 if (ip_index < se.ip_index)
18470 return true;
18471 else if (ip_index > se.ip_index)
18472 return false;
18473 else if (depth < se.depth)
18474 return true;
18475 else if (depth > se.depth)
18476 return false;
18477 else if (index < se.index)
18478 return true;
18479 else if (index > se.index)
18480 return false;
18481 else
18482 return (name < se.name);
18483 }
18484
18485 void clear()
18486 {
18487 name = "???";
18488 size = std::numeric_limits<std::size_t>::max();
18489 index = std::numeric_limits<std::size_t>::max();
18490 depth = std::numeric_limits<std::size_t>::max();
18491 type = e_none;
18492 active = false;
18493 ref_count = 0;
18494 ip_index = 0;
18495 data = 0;
18496 var_node = 0;
18497 vec_node = 0;
18498 #ifndef exprtk_disable_string_capabilities
18499 str_node = 0;
18500 #endif
18501 }
18502
18503 std::string name;
18504 std::size_t size;
18505 std::size_t index;
18506 std::size_t depth;
18507 std::size_t ref_count;
18508 std::size_t ip_index;
18509 element_type type;
18510 bool active;
18511 void* data;
18512 expression_node_ptr var_node;
18513 vector_holder_ptr vec_node;
18514 #ifndef exprtk_disable_string_capabilities
18515 stringvar_node_ptr str_node;
18516 #endif
18517 };
18518
18519 class scope_element_manager
18520 {
18521 public:
18522
18523 typedef expression_node_t* expression_node_ptr;
18524 typedef variable_node_t* variable_node_ptr;
18525 typedef parser<T> parser_t;
18526
18527 explicit scope_element_manager(parser<T>& p)
18528 : parser_(p),
18529 input_param_cnt_(0)
18530 {}
18531
18532 inline std::size_t size() const
18533 {
18534 return element_.size();
18535 }
18536
18537 inline bool empty() const
18538 {
18539 return element_.empty();
18540 }
18541
18542 inline scope_element& get_element(const std::size_t& index)
18543 {
18544 if (index < element_.size())
18545 return element_[index];
18546 else
18547 return null_element_;
18548 }
18549
18550 inline scope_element& get_element(const std::string& var_name,
18551 const std::size_t index = std::numeric_limits<std::size_t>::max())
18552 {
18553 const std::size_t current_depth = parser_.state_.scope_depth;
18554
18555 for (std::size_t i = 0; i < element_.size(); ++i)
18556 {
18557 scope_element& se = element_[i];
18558
18559 if (se.depth > current_depth)
18560 continue;
18561 else if (
18562 details::imatch(se.name, var_name) &&
18563 (se.index == index)
18564 )
18565 return se;
18566 }
18567
18568 return null_element_;
18569 }
18570
18571 inline scope_element& get_active_element(const std::string& var_name,
18572 const std::size_t index = std::numeric_limits<std::size_t>::max())
18573 {
18574 const std::size_t current_depth = parser_.state_.scope_depth;
18575
18576 for (std::size_t i = 0; i < element_.size(); ++i)
18577 {
18578 scope_element& se = element_[i];
18579
18580 if (se.depth > current_depth)
18581 continue;
18582 else if (
18583 details::imatch(se.name, var_name) &&
18584 (se.index == index) &&
18585 (se.active)
18586 )
18587 return se;
18588 }
18589
18590 return null_element_;
18591 }
18592
18593 inline bool add_element(const scope_element& se)
18594 {
18595 for (std::size_t i = 0; i < element_.size(); ++i)
18596 {
18597 scope_element& cse = element_[i];
18598
18599 if (
18600 details::imatch(cse.name, se.name) &&
18601 (cse.depth <= se.depth) &&
18602 (cse.index == se.index) &&
18603 (cse.size == se.size ) &&
18604 (cse.type == se.type ) &&
18605 (cse.active)
18606 )
18607 return false;
18608 }
18609
18610 element_.push_back(se);
18611 std::sort(element_.begin(),element_.end());
18612
18613 return true;
18614 }
18615
18616 inline void deactivate(const std::size_t& scope_depth)
18617 {
18618 exprtk_debug(("deactivate() - Scope depth: %d\n",
18619 static_cast<int>(parser_.state_.scope_depth)));
18620
18621 for (std::size_t i = 0; i < element_.size(); ++i)
18622 {
18623 scope_element& se = element_[i];
18624
18625 if (se.active && (se.depth >= scope_depth))
18626 {
18627 exprtk_debug(("deactivate() - element[%02d] '%s'\n",
18628 static_cast<int>(i),
18629 se.name.c_str()));
18630
18631 se.active = false;
18632 }
18633 }
18634 }
18635
18636 inline void free_element(scope_element& se)
18637 {
18638 #ifdef exprtk_enable_debugging
18639 exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
18640 #endif
18641
18642 switch (se.type)
18643 {
18644 case scope_element::e_variable : if (se.data ) delete (T*) se.data;
18645 if (se.var_node) delete se.var_node;
18646 break;
18647
18648 case scope_element::e_vector : if (se.data ) delete[] (T*) se.data;
18649 if (se.vec_node) delete se.vec_node;
18650 break;
18651
18652 case scope_element::e_vecelem : if (se.var_node) delete se.var_node;
18653 break;
18654
18655 #ifndef exprtk_disable_string_capabilities
18656 case scope_element::e_string : if (se.data ) delete (std::string*) se.data;
18657 if (se.str_node) delete se.str_node;
18658 break;
18659 #endif
18660
18661 default : return;
18662 }
18663
18664 se.clear();
18665 }
18666
18667 inline void cleanup()
18668 {
18669 for (std::size_t i = 0; i < element_.size(); ++i)
18670 {
18671 free_element(element_[i]);
18672 }
18673
18674 element_.clear();
18675
18676 input_param_cnt_ = 0;
18677 }
18678
18679 inline std::size_t next_ip_index()
18680 {
18681 return ++input_param_cnt_;
18682 }
18683
18684 inline expression_node_ptr get_variable(const T& v)
18685 {
18686 for (std::size_t i = 0; i < element_.size(); ++i)
18687 {
18688 scope_element& se = element_[i];
18689
18690 if (
18691 se.active &&
18692 se.var_node &&
18693 details::is_variable_node(se.var_node)
18694 )
18695 {
18696 variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
18697
18698 if (&(vn->ref()) == (&v))
18699 {
18700 return se.var_node;
18701 }
18702 }
18703 }
18704
18705 return expression_node_ptr(0);
18706 }
18707
18708 private:
18709
18710 scope_element_manager& operator=(const scope_element_manager&);
18711
18712 parser_t& parser_;
18713 std::vector<scope_element> element_;
18714 scope_element null_element_;
18715 std::size_t input_param_cnt_;
18716 };
18717
18718 class scope_handler
18719 {
18720 public:
18721
18722 typedef parser<T> parser_t;
18723
18724 explicit scope_handler(parser<T>& p)
18725 : parser_(p)
18726 {
18727 parser_.state_.scope_depth++;
18728 #ifdef exprtk_enable_debugging
18729 const std::string depth(2 * parser_.state_.scope_depth,'-');
18730 exprtk_debug(("%s> Scope Depth: %02d\n",
18731 depth.c_str(),
18732 static_cast<int>(parser_.state_.scope_depth)));
18733 #endif
18734 }
18735
18736 ~scope_handler()
18737 {
18738 parser_.sem_.deactivate(parser_.state_.scope_depth);
18739 parser_.state_.scope_depth--;
18740 #ifdef exprtk_enable_debugging
18741 const std::string depth(2 * parser_.state_.scope_depth,'-');
18742 exprtk_debug(("<%s Scope Depth: %02d\n",
18743 depth.c_str(),
18744 static_cast<int>(parser_.state_.scope_depth)));
18745 #endif
18746 }
18747
18748 private:
18749
18750 scope_handler& operator=(const scope_handler&);
18751
18752 parser_t& parser_;
18753 };
18754
18755 struct symtab_store
18756 {
18757 symbol_table_list_t symtab_list_;
18758
18759 typedef typename symbol_table_t::local_data_t local_data_t;
18760 typedef typename symbol_table_t::variable_ptr variable_ptr;
18761 typedef typename symbol_table_t::function_ptr function_ptr;
18762 #ifndef exprtk_disable_string_capabilities
18763 typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
18764 #endif
18765 typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr;
18766 typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr;
18767 typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
18768
18769 inline bool empty() const
18770 {
18771 return symtab_list_.empty();
18772 }
18773
18774 inline void clear()
18775 {
18776 symtab_list_.clear();
18777 }
18778
18779 inline bool valid() const
18780 {
18781 if (!empty())
18782 {
18783 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18784 {
18785 if (symtab_list_[i].valid())
18786 return true;
18787 }
18788 }
18789
18790 return false;
18791 }
18792
18793 inline bool valid_symbol(const std::string& symbol) const
18794 {
18795 if (!symtab_list_.empty())
18796 return symtab_list_[0].valid_symbol(symbol);
18797 else
18798 return false;
18799 }
18800
18801 inline bool valid_function_name(const std::string& symbol) const
18802 {
18803 if (!symtab_list_.empty())
18804 return symtab_list_[0].valid_function(symbol);
18805 else
18806 return false;
18807 }
18808
18809 inline variable_ptr get_variable(const std::string& variable_name) const
18810 {
18811 if (!valid_symbol(variable_name))
18812 return reinterpret_cast<variable_ptr>(0);
18813
18814 variable_ptr result = reinterpret_cast<variable_ptr>(0);
18815
18816 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18817 {
18818 if (!symtab_list_[i].valid())
18819 continue;
18820 else
18821 result = local_data(i)
18822 .variable_store.get(variable_name);
18823
18824 if (result) break;
18825 }
18826
18827 return result;
18828 }
18829
18830 inline variable_ptr get_variable(const T& var_ref) const
18831 {
18832 variable_ptr result = reinterpret_cast<variable_ptr>(0);
18833
18834 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18835 {
18836 if (!symtab_list_[i].valid())
18837 continue;
18838 else
18839 result = local_data(i).variable_store
18840 .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
18841
18842 if (result) break;
18843 }
18844
18845 return result;
18846 }
18847
18848 #ifndef exprtk_disable_string_capabilities
18849 inline stringvar_ptr get_stringvar(const std::string& string_name) const
18850 {
18851 if (!valid_symbol(string_name))
18852 return reinterpret_cast<stringvar_ptr>(0);
18853
18854 stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
18855
18856 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18857 {
18858 if (!symtab_list_[i].valid())
18859 continue;
18860 else
18861 result = local_data(i)
18862 .stringvar_store.get(string_name);
18863
18864 if (result) break;
18865 }
18866
18867 return result;
18868 }
18869 #endif
18870
18871 inline function_ptr get_function(const std::string& function_name) const
18872 {
18873 if (!valid_function_name(function_name))
18874 return reinterpret_cast<function_ptr>(0);
18875
18876 function_ptr result = reinterpret_cast<function_ptr>(0);
18877
18878 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18879 {
18880 if (!symtab_list_[i].valid())
18881 continue;
18882 else
18883 result = local_data(i)
18884 .function_store.get(function_name);
18885
18886 if (result) break;
18887 }
18888
18889 return result;
18890 }
18891
18892 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
18893 {
18894 if (!valid_function_name(vararg_function_name))
18895 return reinterpret_cast<vararg_function_ptr>(0);
18896
18897 vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
18898
18899 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18900 {
18901 if (!symtab_list_[i].valid())
18902 continue;
18903 else
18904 result = local_data(i)
18905 .vararg_function_store.get(vararg_function_name);
18906
18907 if (result) break;
18908 }
18909
18910 return result;
18911 }
18912
18913 inline generic_function_ptr get_generic_function(const std::string& function_name) const
18914 {
18915 if (!valid_function_name(function_name))
18916 return reinterpret_cast<generic_function_ptr>(0);
18917
18918 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18919
18920 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18921 {
18922 if (!symtab_list_[i].valid())
18923 continue;
18924 else
18925 result = local_data(i)
18926 .generic_function_store.get(function_name);
18927
18928 if (result) break;
18929 }
18930
18931 return result;
18932 }
18933
18934 inline generic_function_ptr get_string_function(const std::string& function_name) const
18935 {
18936 if (!valid_function_name(function_name))
18937 return reinterpret_cast<generic_function_ptr>(0);
18938
18939 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18940
18941 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18942 {
18943 if (!symtab_list_[i].valid())
18944 continue;
18945 else
18946 result =
18947 local_data(i).string_function_store.get(function_name);
18948
18949 if (result) break;
18950 }
18951
18952 return result;
18953 }
18954
18955 inline generic_function_ptr get_overload_function(const std::string& function_name) const
18956 {
18957 if (!valid_function_name(function_name))
18958 return reinterpret_cast<generic_function_ptr>(0);
18959
18960 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18961
18962 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18963 {
18964 if (!symtab_list_[i].valid())
18965 continue;
18966 else
18967 result =
18968 local_data(i).overload_function_store.get(function_name);
18969
18970 if (result) break;
18971 }
18972
18973 return result;
18974 }
18975
18976 inline vector_holder_ptr get_vector(const std::string& vector_name) const
18977 {
18978 if (!valid_symbol(vector_name))
18979 return reinterpret_cast<vector_holder_ptr>(0);
18980
18981 vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
18982
18983 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18984 {
18985 if (!symtab_list_[i].valid())
18986 continue;
18987 else
18988 result =
18989 local_data(i).vector_store.get(vector_name);
18990
18991 if (result) break;
18992 }
18993
18994 return result;
18995 }
18996
18997 inline bool is_constant_node(const std::string& symbol_name) const
18998 {
18999 if (!valid_symbol(symbol_name))
19000 return false;
19001
19002 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19003 {
19004 if (!symtab_list_[i].valid())
19005 continue;
19006 else if (local_data(i).variable_store.is_constant(symbol_name))
19007 return true;
19008 }
19009
19010 return false;
19011 }
19012
19013 #ifndef exprtk_disable_string_capabilities
19014 inline bool is_constant_string(const std::string& symbol_name) const
19015 {
19016 if (!valid_symbol(symbol_name))
19017 return false;
19018
19019 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19020 {
19021 if (!symtab_list_[i].valid())
19022 continue;
19023 else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19024 continue;
19025 else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19026 return true;
19027 }
19028
19029 return false;
19030 }
19031 #endif
19032
19033 inline bool symbol_exists(const std::string& symbol) const
19034 {
19035 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19036 {
19037 if (!symtab_list_[i].valid())
19038 continue;
19039 else if (symtab_list_[i].symbol_exists(symbol))
19040 return true;
19041 }
19042
19043 return false;
19044 }
19045
19046 inline bool is_variable(const std::string& variable_name) const
19047 {
19048 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19049 {
19050 if (!symtab_list_[i].valid())
19051 continue;
19052 else if (
19053 symtab_list_[i].local_data().variable_store
19054 .symbol_exists(variable_name)
19055 )
19056 return true;
19057 }
19058
19059 return false;
19060 }
19061
19062 #ifndef exprtk_disable_string_capabilities
19063 inline bool is_stringvar(const std::string& stringvar_name) const
19064 {
19065 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19066 {
19067 if (!symtab_list_[i].valid())
19068 continue;
19069 else if (
19070 symtab_list_[i].local_data().stringvar_store
19071 .symbol_exists(stringvar_name)
19072 )
19073 return true;
19074 }
19075
19076 return false;
19077 }
19078
19079 inline bool is_conststr_stringvar(const std::string& symbol_name) const
19080 {
19081 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19082 {
19083 if (!symtab_list_[i].valid())
19084 continue;
19085 else if (
19086 symtab_list_[i].local_data().stringvar_store
19087 .symbol_exists(symbol_name)
19088 )
19089 {
19090 return (
19091 local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19092 local_data(i).stringvar_store.is_constant (symbol_name)
19093 );
19094
19095 }
19096 }
19097
19098 return false;
19099 }
19100 #endif
19101
19102 inline bool is_function(const std::string& function_name) const
19103 {
19104 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19105 {
19106 if (!symtab_list_[i].valid())
19107 continue;
19108 else if (
19109 local_data(i).vararg_function_store
19110 .symbol_exists(function_name)
19111 )
19112 return true;
19113 }
19114
19115 return false;
19116 }
19117
19118 inline bool is_vararg_function(const std::string& vararg_function_name) const
19119 {
19120 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19121 {
19122 if (!symtab_list_[i].valid())
19123 continue;
19124 else if (
19125 local_data(i).vararg_function_store
19126 .symbol_exists(vararg_function_name)
19127 )
19128 return true;
19129 }
19130
19131 return false;
19132 }
19133
19134 inline bool is_vector(const std::string& vector_name) const
19135 {
19136 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19137 {
19138 if (!symtab_list_[i].valid())
19139 continue;
19140 else if (
19141 local_data(i).vector_store
19142 .symbol_exists(vector_name)
19143 )
19144 return true;
19145 }
19146
19147 return false;
19148 }
19149
19150 inline std::string get_variable_name(const expression_node_ptr& ptr) const
19151 {
19152 return local_data().variable_store.entity_name(ptr);
19153 }
19154
19155 inline std::string get_vector_name(const vector_holder_ptr& ptr) const
19156 {
19157 return local_data().vector_store.entity_name(ptr);
19158 }
19159
19160 #ifndef exprtk_disable_string_capabilities
19161 inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
19162 {
19163 return local_data().stringvar_store.entity_name(ptr);
19164 }
19165
19166 inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
19167 {
19168 return local_data().stringvar_store.entity_name(ptr);
19169 }
19170 #endif
19171
19172 inline local_data_t& local_data(const std::size_t& index = 0)
19173 {
19174 return symtab_list_[index].local_data();
19175 }
19176
19177 inline const local_data_t& local_data(const std::size_t& index = 0) const
19178 {
19179 return symtab_list_[index].local_data();
19180 }
19181
19182 inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19183 {
19184 return symtab_list_[index];
19185 }
19186 };
19187
19188 struct parser_state
19189 {
19190 parser_state()
19191 : type_check_enabled(true)
19192 {
19193 reset();
19194 }
19195
19196 void reset()
19197 {
19198 parsing_return_stmt = false;
19199 parsing_break_stmt = false;
19200 return_stmt_present = false;
19201 side_effect_present = false;
19202 scope_depth = 0;
19203 }
19204
19205 #ifndef exprtk_enable_debugging
19206 void activate_side_effect(const std::string&)
19207 #else
19208 void activate_side_effect(const std::string& source)
19209 #endif
19210 {
19211 if (!side_effect_present)
19212 {
19213 side_effect_present = true;
19214
19215 exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19216 }
19217 }
19218
19219 bool parsing_return_stmt;
19220 bool parsing_break_stmt;
19221 bool return_stmt_present;
19222 bool side_effect_present;
19223 bool type_check_enabled;
19224 std::size_t scope_depth;
19225 };
19226
19227 public:
19228
19229 struct unknown_symbol_resolver
19230 {
19231
19232 enum usr_symbol_type
19233 {
19234 e_usr_unknown_type = 0,
19235 e_usr_variable_type = 1,
19236 e_usr_constant_type = 2
19237 };
19238
19239 enum usr_mode
19240 {
19241 e_usrmode_default = 0,
19242 e_usrmode_extended = 1
19243 };
19244
19245 usr_mode mode;
19246
19247 unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
19248 : mode(m)
19249 {}
19250
19251 virtual ~unknown_symbol_resolver()
19252 {}
19253
19254 virtual bool process(const std::string& /*unknown_symbol*/,
19255 usr_symbol_type& st,
19256 T& default_value,
19257 std::string& error_message)
19258 {
19259 if (e_usrmode_default != mode)
19260 return false;
19261
19262 st = e_usr_variable_type;
19263 default_value = T(0);
19264 error_message.clear();
19265
19266 return true;
19267 }
19268
19269 virtual bool process(const std::string& /* unknown_symbol */,
19270 symbol_table_t& /* symbol_table */,
19271 std::string& /* error_message */)
19272 {
19273 return false;
19274 }
19275 };
19276
19277 enum collect_type
19278 {
19279 e_ct_none = 0,
19280 e_ct_variables = 1,
19281 e_ct_functions = 2,
19282 e_ct_assignments = 4
19283 };
19284
19285 enum symbol_type
19286 {
19287 e_st_unknown = 0,
19288 e_st_variable = 1,
19289 e_st_vector = 2,
19290 e_st_vecelem = 3,
19291 e_st_string = 4,
19292 e_st_function = 5,
19293 e_st_local_variable = 6,
19294 e_st_local_vector = 7,
19295 e_st_local_string = 8
19296 };
19297
19298 class dependent_entity_collector
19299 {
19300 public:
19301
19302 typedef std::pair<std::string,symbol_type> symbol_t;
19303 typedef std::vector<symbol_t> symbol_list_t;
19304
19305 dependent_entity_collector(const std::size_t options = e_ct_none)
19306 : options_(options),
19307 collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ),
19308 collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ),
19309 collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
19310 return_present_ (false),
19311 final_stmt_return_(false)
19312 {}
19313
19314 template <typename Allocator,
19315 template <typename, typename> class Sequence>
19316 inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
19317 {
19318 if (!collect_variables_ && !collect_functions_)
19319 return 0;
19320 else if (symbol_name_list_.empty())
19321 return 0;
19322
19323 for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
19324 {
19325 details::case_normalise(symbol_name_list_[i].first);
19326 }
19327
19328 std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
19329
19330 std::unique_copy(symbol_name_list_.begin(),
19331 symbol_name_list_.end (),
19332 std::back_inserter(symbols_list));
19333
19334 return symbols_list.size();
19335 }
19336
19337 template <typename Allocator,
19338 template <typename, typename> class Sequence>
19339 inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
19340 {
19341 if (!collect_assignments_)
19342 return 0;
19343 else if (assignment_name_list_.empty())
19344 return 0;
19345
19346 for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
19347 {
19348 details::case_normalise(assignment_name_list_[i].first);
19349 }
19350
19351 std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
19352
19353 std::unique_copy(assignment_name_list_.begin(),
19354 assignment_name_list_.end (),
19355 std::back_inserter(assignment_list));
19356
19357 return assignment_list.size();
19358 }
19359
19360 void clear()
19361 {
19362 symbol_name_list_ .clear();
19363 assignment_name_list_.clear();
19364 retparam_list_ .clear();
19365 return_present_ = false;
19366 final_stmt_return_ = false;
19367 }
19368
19369 bool& collect_variables()
19370 {
19371 return collect_variables_;
19372 }
19373
19374 bool& collect_functions()
19375 {
19376 return collect_functions_;
19377 }
19378
19379 bool& collect_assignments()
19380 {
19381 return collect_assignments_;
19382 }
19383
19384 bool return_present() const
19385 {
19386 return return_present_;
19387 }
19388
19389 bool final_stmt_return() const
19390 {
19391 return final_stmt_return_;
19392 }
19393
19394 typedef std::vector<std::string> retparam_list_t;
19395
19396 retparam_list_t return_param_type_list() const
19397 {
19398 return retparam_list_;
19399 }
19400
19401 private:
19402
19403 inline void add_symbol(const std::string& symbol, const symbol_type st)
19404 {
19405 switch (st)
19406 {
19407 case e_st_variable :
19408 case e_st_vector :
19409 case e_st_string :
19410 case e_st_local_variable :
19411 case e_st_local_vector :
19412 case e_st_local_string : if (collect_variables_)
19413 symbol_name_list_
19414 .push_back(std::make_pair(symbol, st));
19415 break;
19416
19417 case e_st_function : if (collect_functions_)
19418 symbol_name_list_
19419 .push_back(std::make_pair(symbol, st));
19420 break;
19421
19422 default : return;
19423 }
19424 }
19425
19426 inline void add_assignment(const std::string& symbol, const symbol_type st)
19427 {
19428 switch (st)
19429 {
19430 case e_st_variable :
19431 case e_st_vector :
19432 case e_st_string : if (collect_assignments_)
19433 assignment_name_list_
19434 .push_back(std::make_pair(symbol, st));
19435 break;
19436
19437 default : return;
19438 }
19439 }
19440
19441 std::size_t options_;
19442 bool collect_variables_;
19443 bool collect_functions_;
19444 bool collect_assignments_;
19445 bool return_present_;
19446 bool final_stmt_return_;
19447 symbol_list_t symbol_name_list_;
19448 symbol_list_t assignment_name_list_;
19449 retparam_list_t retparam_list_;
19450
19451 friend class parser<T>;
19452 };
19453
19454 class settings_store
19455 {
19456 private:
19457
19458 typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
19459 typedef disabled_entity_set_t::iterator des_itr_t;
19460
19461 public:
19462
19463 enum settings_compilation_options
19464 {
19465 e_unknown = 0,
19466 e_replacer = 1,
19467 e_joiner = 2,
19468 e_numeric_check = 4,
19469 e_bracket_check = 8,
19470 e_sequence_check = 16,
19471 e_commutative_check = 32,
19472 e_strength_reduction = 64,
19473 e_disable_vardef = 128,
19474 e_collect_vars = 256,
19475 e_collect_funcs = 512,
19476 e_collect_assings = 1024,
19477 e_disable_usr_on_rsrvd = 2048,
19478 e_disable_zero_return = 4096
19479 };
19480
19481 enum settings_base_funcs
19482 {
19483 e_bf_unknown = 0,
19484 e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
19485 e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
19486 e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
19487 e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
19488 e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
19489 e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
19490 e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
19491 e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
19492 e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
19493 e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
19494 e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
19495 e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
19496 e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
19497 e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad,
19498 e_bf_rad2deg , e_bf_grad2deg
19499 };
19500
19501 enum settings_control_structs
19502 {
19503 e_ctrl_unknown = 0,
19504 e_ctrl_ifelse,
19505 e_ctrl_switch,
19506 e_ctrl_for_loop,
19507 e_ctrl_while_loop,
19508 e_ctrl_repeat_loop,
19509 e_ctrl_return
19510 };
19511
19512 enum settings_logic_opr
19513 {
19514 e_logic_unknown = 0,
19515 e_logic_and, e_logic_nand, e_logic_nor,
19516 e_logic_not, e_logic_or, e_logic_xnor,
19517 e_logic_xor, e_logic_scand, e_logic_scor
19518 };
19519
19520 enum settings_arithmetic_opr
19521 {
19522 e_arith_unknown = 0,
19523 e_arith_add, e_arith_sub, e_arith_mul,
19524 e_arith_div, e_arith_mod, e_arith_pow
19525 };
19526
19527 enum settings_assignment_opr
19528 {
19529 e_assign_unknown = 0,
19530 e_assign_assign, e_assign_addass, e_assign_subass,
19531 e_assign_mulass, e_assign_divass, e_assign_modass
19532 };
19533
19534 enum settings_inequality_opr
19535 {
19536 e_ineq_unknown = 0,
19537 e_ineq_lt, e_ineq_lte, e_ineq_eq,
19538 e_ineq_equal, e_ineq_ne, e_ineq_nequal,
19539 e_ineq_gte, e_ineq_gt
19540 };
19541
19542 static const std::size_t compile_all_opts = e_replacer +
19543 e_joiner +
19544 e_numeric_check +
19545 e_bracket_check +
19546 e_sequence_check +
19547 e_commutative_check +
19548 e_strength_reduction;
19549
19550 settings_store(const std::size_t compile_options = compile_all_opts)
19551 {
19552 load_compile_options(compile_options);
19553 }
19554
19555 settings_store& enable_all_base_functions()
19556 {
19557 disabled_func_set_.clear();
19558 return (*this);
19559 }
19560
19561 settings_store& enable_all_control_structures()
19562 {
19563 disabled_ctrl_set_.clear();
19564 return (*this);
19565 }
19566
19567 settings_store& enable_all_logic_ops()
19568 {
19569 disabled_logic_set_.clear();
19570 return (*this);
19571 }
19572
19573 settings_store& enable_all_arithmetic_ops()
19574 {
19575 disabled_arithmetic_set_.clear();
19576 return (*this);
19577 }
19578
19579 settings_store& enable_all_assignment_ops()
19580 {
19581 disabled_assignment_set_.clear();
19582 return (*this);
19583 }
19584
19585 settings_store& enable_all_inequality_ops()
19586 {
19587 disabled_inequality_set_.clear();
19588 return (*this);
19589 }
19590
19591 settings_store& enable_local_vardef()
19592 {
19593 disable_vardef_ = false;
19594 return (*this);
19595 }
19596
19597 settings_store& disable_all_base_functions()
19598 {
19599 std::copy(details::base_function_list,
19600 details::base_function_list + details::base_function_list_size,
19601 std::insert_iterator<disabled_entity_set_t>
19602 (disabled_func_set_, disabled_func_set_.begin()));
19603 return (*this);
19604 }
19605
19606 settings_store& disable_all_control_structures()
19607 {
19608 std::copy(details::cntrl_struct_list,
19609 details::cntrl_struct_list + details::cntrl_struct_list_size,
19610 std::insert_iterator<disabled_entity_set_t>
19611 (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
19612 return (*this);
19613 }
19614
19615 settings_store& disable_all_logic_ops()
19616 {
19617 std::copy(details::logic_ops_list,
19618 details::logic_ops_list + details::logic_ops_list_size,
19619 std::insert_iterator<disabled_entity_set_t>
19620 (disabled_logic_set_, disabled_logic_set_.begin()));
19621 return (*this);
19622 }
19623
19624 settings_store& disable_all_arithmetic_ops()
19625 {
19626 std::copy(details::arithmetic_ops_list,
19627 details::arithmetic_ops_list + details::arithmetic_ops_list_size,
19628 std::insert_iterator<disabled_entity_set_t>
19629 (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
19630 return (*this);
19631 }
19632
19633 settings_store& disable_all_assignment_ops()
19634 {
19635 std::copy(details::assignment_ops_list,
19636 details::assignment_ops_list + details::assignment_ops_list_size,
19637 std::insert_iterator<disabled_entity_set_t>
19638 (disabled_assignment_set_, disabled_assignment_set_.begin()));
19639 return (*this);
19640 }
19641
19642 settings_store& disable_all_inequality_ops()
19643 {
19644 std::copy(details::inequality_ops_list,
19645 details::inequality_ops_list + details::inequality_ops_list_size,
19646 std::insert_iterator<disabled_entity_set_t>
19647 (disabled_inequality_set_, disabled_inequality_set_.begin()));
19648 return (*this);
19649 }
19650
19651 settings_store& disable_local_vardef()
19652 {
19653 disable_vardef_ = true;
19654 return (*this);
19655 }
19656
19657 bool replacer_enabled () const { return enable_replacer_; }
19658 bool commutative_check_enabled () const { return enable_commutative_check_; }
19659 bool joiner_enabled () const { return enable_joiner_; }
19660 bool numeric_check_enabled () const { return enable_numeric_check_; }
19661 bool bracket_check_enabled () const { return enable_bracket_check_; }
19662 bool sequence_check_enabled () const { return enable_sequence_check_; }
19663 bool strength_reduction_enabled () const { return enable_strength_reduction_; }
19664 bool collect_variables_enabled () const { return enable_collect_vars_; }
19665 bool collect_functions_enabled () const { return enable_collect_funcs_; }
19666 bool collect_assignments_enabled() const { return enable_collect_assings_; }
19667 bool vardef_disabled () const { return disable_vardef_; }
19668 bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
19669 bool zero_return_disabled () const { return disable_zero_return_; }
19670
19671 bool function_enabled(const std::string& function_name) const
19672 {
19673 if (disabled_func_set_.empty())
19674 return true;
19675 else
19676 return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
19677 }
19678
19679 bool control_struct_enabled(const std::string& control_struct) const
19680 {
19681 if (disabled_ctrl_set_.empty())
19682 return true;
19683 else
19684 return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
19685 }
19686
19687 bool logic_enabled(const std::string& logic_operation) const
19688 {
19689 if (disabled_logic_set_.empty())
19690 return true;
19691 else
19692 return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
19693 }
19694
19695 bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
19696 {
19697 if (disabled_logic_set_.empty())
19698 return true;
19699 else
19700 return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
19701 .find(arith_opr_to_string(arithmetic_operation));
19702 }
19703
19704 bool assignment_enabled(const details::operator_type& assignment) const
19705 {
19706 if (disabled_assignment_set_.empty())
19707 return true;
19708 else
19709 return disabled_assignment_set_.end() == disabled_assignment_set_
19710 .find(assign_opr_to_string(assignment));
19711 }
19712
19713 bool inequality_enabled(const details::operator_type& inequality) const
19714 {
19715 if (disabled_inequality_set_.empty())
19716 return true;
19717 else
19718 return disabled_inequality_set_.end() == disabled_inequality_set_
19719 .find(inequality_opr_to_string(inequality));
19720 }
19721
19722 bool function_disabled(const std::string& function_name) const
19723 {
19724 if (disabled_func_set_.empty())
19725 return false;
19726 else
19727 return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
19728 }
19729
19730 bool control_struct_disabled(const std::string& control_struct) const
19731 {
19732 if (disabled_ctrl_set_.empty())
19733 return false;
19734 else
19735 return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
19736 }
19737
19738 bool logic_disabled(const std::string& logic_operation) const
19739 {
19740 if (disabled_logic_set_.empty())
19741 return false;
19742 else
19743 return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
19744 }
19745
19746 bool assignment_disabled(const details::operator_type assignment_operation) const
19747 {
19748 if (disabled_assignment_set_.empty())
19749 return false;
19750 else
19751 return disabled_assignment_set_.end() != disabled_assignment_set_
19752 .find(assign_opr_to_string(assignment_operation));
19753 }
19754
19755 bool logic_disabled(const details::operator_type logic_operation) const
19756 {
19757 if (disabled_logic_set_.empty())
19758 return false;
19759 else
19760 return disabled_logic_set_.end() != disabled_logic_set_
19761 .find(logic_opr_to_string(logic_operation));
19762 }
19763
19764 bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
19765 {
19766 if (disabled_arithmetic_set_.empty())
19767 return false;
19768 else
19769 return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
19770 .find(arith_opr_to_string(arithmetic_operation));
19771 }
19772
19773 bool inequality_disabled(const details::operator_type& inequality) const
19774 {
19775 if (disabled_inequality_set_.empty())
19776 return false;
19777 else
19778 return disabled_inequality_set_.end() != disabled_inequality_set_
19779 .find(inequality_opr_to_string(inequality));
19780 }
19781
19782 settings_store& disable_base_function(settings_base_funcs bf)
19783 {
19784 if (
19785 (e_bf_unknown != bf) &&
19786 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19787 )
19788 {
19789 disabled_func_set_.insert(details::base_function_list[bf - 1]);
19790 }
19791
19792 return (*this);
19793 }
19794
19795 settings_store& disable_control_structure(settings_control_structs ctrl_struct)
19796 {
19797 if (
19798 (e_ctrl_unknown != ctrl_struct) &&
19799 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19800 )
19801 {
19802 disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
19803 }
19804
19805 return (*this);
19806 }
19807
19808 settings_store& disable_logic_operation(settings_logic_opr logic)
19809 {
19810 if (
19811 (e_logic_unknown != logic) &&
19812 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19813 )
19814 {
19815 disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
19816 }
19817
19818 return (*this);
19819 }
19820
19821 settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19822 {
19823 if (
19824 (e_arith_unknown != arithmetic) &&
19825 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19826 )
19827 {
19828 disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
19829 }
19830
19831 return (*this);
19832 }
19833
19834 settings_store& disable_assignment_operation(settings_assignment_opr assignment)
19835 {
19836 if (
19837 (e_assign_unknown != assignment) &&
19838 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19839 )
19840 {
19841 disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
19842 }
19843
19844 return (*this);
19845 }
19846
19847 settings_store& disable_inequality_operation(settings_inequality_opr inequality)
19848 {
19849 if (
19850 (e_ineq_unknown != inequality) &&
19851 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19852 )
19853 {
19854 disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
19855 }
19856
19857 return (*this);
19858 }
19859
19860 settings_store& enable_base_function(settings_base_funcs bf)
19861 {
19862 if (
19863 (e_bf_unknown != bf) &&
19864 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19865 )
19866 {
19867 const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
19868
19869 if (disabled_func_set_.end() != itr)
19870 {
19871 disabled_func_set_.erase(itr);
19872 }
19873 }
19874
19875 return (*this);
19876 }
19877
19878 settings_store& enable_control_structure(settings_control_structs ctrl_struct)
19879 {
19880 if (
19881 (e_ctrl_unknown != ctrl_struct) &&
19882 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19883 )
19884 {
19885 const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
19886
19887 if (disabled_ctrl_set_.end() != itr)
19888 {
19889 disabled_ctrl_set_.erase(itr);
19890 }
19891 }
19892
19893 return (*this);
19894 }
19895
19896 settings_store& enable_logic_operation(settings_logic_opr logic)
19897 {
19898 if (
19899 (e_logic_unknown != logic) &&
19900 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19901 )
19902 {
19903 const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
19904
19905 if (disabled_logic_set_.end() != itr)
19906 {
19907 disabled_logic_set_.erase(itr);
19908 }
19909 }
19910
19911 return (*this);
19912 }
19913
19914 settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19915 {
19916 if (
19917 (e_arith_unknown != arithmetic) &&
19918 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19919 )
19920 {
19921 const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
19922
19923 if (disabled_arithmetic_set_.end() != itr)
19924 {
19925 disabled_arithmetic_set_.erase(itr);
19926 }
19927 }
19928
19929 return (*this);
19930 }
19931
19932 settings_store& enable_assignment_operation(settings_assignment_opr assignment)
19933 {
19934 if (
19935 (e_assign_unknown != assignment) &&
19936 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19937 )
19938 {
19939 const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
19940
19941 if (disabled_assignment_set_.end() != itr)
19942 {
19943 disabled_assignment_set_.erase(itr);
19944 }
19945 }
19946
19947 return (*this);
19948 }
19949
19950 settings_store& enable_inequality_operation(settings_inequality_opr inequality)
19951 {
19952 if (
19953 (e_ineq_unknown != inequality) &&
19954 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19955 )
19956 {
19957 const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
19958
19959 if (disabled_inequality_set_.end() != itr)
19960 {
19961 disabled_inequality_set_.erase(itr);
19962 }
19963 }
19964
19965 return (*this);
19966 }
19967
19968 private:
19969
19970 void load_compile_options(const std::size_t compile_options)
19971 {
19972 enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
19973 enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
19974 enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
19975 enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
19976 enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
19977 enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
19978 enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
19979 enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
19980 enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
19981 enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
19982 disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
19983 disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
19984 disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
19985 }
19986
19987 std::string assign_opr_to_string(details::operator_type opr) const
19988 {
19989 switch (opr)
19990 {
19991 case details::e_assign : return ":=";
19992 case details::e_addass : return "+=";
19993 case details::e_subass : return "-=";
19994 case details::e_mulass : return "*=";
19995 case details::e_divass : return "/=";
19996 case details::e_modass : return "%=";
19997 default : return "";
19998 }
19999 }
20000
20001 std::string arith_opr_to_string(details::operator_type opr) const
20002 {
20003 switch (opr)
20004 {
20005 case details::e_add : return "+";
20006 case details::e_sub : return "-";
20007 case details::e_mul : return "*";
20008 case details::e_div : return "/";
20009 case details::e_mod : return "%";
20010 default : return "";
20011 }
20012 }
20013
20014 std::string inequality_opr_to_string(details::operator_type opr) const
20015 {
20016 switch (opr)
20017 {
20018 case details::e_lt : return "<";
20019 case details::e_lte : return "<=";
20020 case details::e_eq : return "==";
20021 case details::e_equal : return "=";
20022 case details::e_ne : return "!=";
20023 case details::e_nequal: return "<>";
20024 case details::e_gte : return ">=";
20025 case details::e_gt : return ">";
20026 default : return "";
20027 }
20028 }
20029
20030 std::string logic_opr_to_string(details::operator_type opr) const
20031 {
20032 switch (opr)
20033 {
20034 case details::e_and : return "and" ;
20035 case details::e_or : return "or" ;
20036 case details::e_xor : return "xor" ;
20037 case details::e_nand : return "nand";
20038 case details::e_nor : return "nor" ;
20039 case details::e_xnor : return "xnor";
20040 case details::e_notl : return "not" ;
20041 default : return "" ;
20042 }
20043 }
20044
20045 bool enable_replacer_;
20046 bool enable_joiner_;
20047 bool enable_numeric_check_;
20048 bool enable_bracket_check_;
20049 bool enable_sequence_check_;
20050 bool enable_commutative_check_;
20051 bool enable_strength_reduction_;
20052 bool enable_collect_vars_;
20053 bool enable_collect_funcs_;
20054 bool enable_collect_assings_;
20055 bool disable_vardef_;
20056 bool disable_rsrvd_sym_usr_;
20057 bool disable_zero_return_;
20058
20059 disabled_entity_set_t disabled_func_set_ ;
20060 disabled_entity_set_t disabled_ctrl_set_ ;
20061 disabled_entity_set_t disabled_logic_set_;
20062 disabled_entity_set_t disabled_arithmetic_set_;
20063 disabled_entity_set_t disabled_assignment_set_;
20064 disabled_entity_set_t disabled_inequality_set_;
20065
20066 friend class parser<T>;
20067 };
20068
20069 typedef settings_store settings_t;
20070
20071 parser(const settings_t& settings = settings_t())
20072 : settings_(settings),
20073 resolve_unknown_symbol_(false),
20074 results_context_(0),
20075 unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20076 #ifdef _MSC_VER
20077 #pragma warning(push)
20078 #pragma warning (disable:4355)
20079 #endif
20080 sem_(*this),
20081 #ifdef _MSC_VER
20082 #pragma warning(pop)
20083 #endif
20084 operator_joiner_2_(2),
20085 operator_joiner_3_(3)
20086 {
20087 init_precompilation();
20088
20089 load_operations_map (base_ops_map_ );
20090 load_unary_operations_map (unary_op_map_ );
20091 load_binary_operations_map (binary_op_map_ );
20092 load_inv_binary_operations_map(inv_binary_op_map_);
20093 load_sf3_map (sf3_map_ );
20094 load_sf4_map (sf4_map_ );
20095
20096 expression_generator_.init_synthesize_map();
20097 expression_generator_.set_parser(*this);
20098 expression_generator_.set_uom(unary_op_map_);
20099 expression_generator_.set_bom(binary_op_map_);
20100 expression_generator_.set_ibom(inv_binary_op_map_);
20101 expression_generator_.set_sf3m(sf3_map_);
20102 expression_generator_.set_sf4m(sf4_map_);
20103 expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20104 }
20105
20106 ~parser()
20107 {}
20108
20109 inline void init_precompilation()
20110 {
20111 if (settings_.collect_variables_enabled())
20112 dec_.collect_variables() = true;
20113
20114 if (settings_.collect_functions_enabled())
20115 dec_.collect_functions() = true;
20116
20117 if (settings_.collect_assignments_enabled())
20118 dec_.collect_assignments() = true;
20119
20120 if (settings_.replacer_enabled())
20121 {
20122 symbol_replacer_.clear();
20123 symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
20124 symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
20125 helper_assembly_.token_modifier_list.clear();
20126 helper_assembly_.register_modifier(&symbol_replacer_);
20127 }
20128
20129 if (settings_.commutative_check_enabled())
20130 {
20131 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20132 {
20133 commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20134 }
20135
20136 helper_assembly_.token_inserter_list.clear();
20137 helper_assembly_.register_inserter(&commutative_inserter_);
20138 }
20139
20140 if (settings_.joiner_enabled())
20141 {
20142 helper_assembly_.token_joiner_list.clear();
20143 helper_assembly_.register_joiner(&operator_joiner_2_);
20144 helper_assembly_.register_joiner(&operator_joiner_3_);
20145 }
20146
20147 if (
20148 settings_.numeric_check_enabled () ||
20149 settings_.bracket_check_enabled () ||
20150 settings_.sequence_check_enabled()
20151 )
20152 {
20153 helper_assembly_.token_scanner_list.clear();
20154
20155 if (settings_.numeric_check_enabled())
20156 {
20157 helper_assembly_.register_scanner(&numeric_checker_);
20158 }
20159
20160 if (settings_.bracket_check_enabled())
20161 {
20162 helper_assembly_.register_scanner(&bracket_checker_);
20163 }
20164
20165 if (settings_.sequence_check_enabled())
20166 {
20167 helper_assembly_.register_scanner(&sequence_validator_ );
20168 helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20169 }
20170 }
20171 }
20172
20173 inline bool compile(const std::string& expression_string, expression<T>& expr)
20174 {
20175 state_ .reset();
20176 error_list_ .clear();
20177 brkcnt_list_ .clear();
20178 synthesis_error_.clear();
20179 sem_ .cleanup();
20180
20181 return_cleanup();
20182
20183 expression_generator_.set_allocator(node_allocator_);
20184
20185 if (expression_string.empty())
20186 {
20187 set_error(
20188 make_error(parser_error::e_syntax,
20189 "ERR000 - Empty expression!",
20190 exprtk_error_location));
20191
20192 return false;
20193 }
20194
20195 if (!init(expression_string))
20196 {
20197 process_lexer_errors();
20198 return false;
20199 }
20200
20201 if (lexer().empty())
20202 {
20203 set_error(
20204 make_error(parser_error::e_syntax,
20205 "ERR001 - Empty expression!",
20206 exprtk_error_location));
20207
20208 return false;
20209 }
20210
20211 if (!run_assemblies())
20212 {
20213 return false;
20214 }
20215
20216 symtab_store_.symtab_list_ = expr.get_symbol_table_list();
20217 dec_.clear();
20218
20219 lexer().begin();
20220
20221 next_token();
20222
20223 expression_node_ptr e = parse_corpus();
20224
20225 if ((0 != e) && (token_t::e_eof == current_token().type))
20226 {
20227 bool* retinvk_ptr = 0;
20228
20229 if (state_.return_stmt_present)
20230 {
20231 dec_.return_present_ = true;
20232
20233 e = expression_generator_
20234 .return_envelope(e, results_context_, retinvk_ptr);
20235 }
20236
20237 expr.set_expression(e);
20238 expr.set_retinvk(retinvk_ptr);
20239
20240 register_local_vars(expr);
20241 register_return_results(expr);
20242
20243 return !(!expr);
20244 }
20245 else
20246 {
20247 if (error_list_.empty())
20248 {
20249 set_error(
20250 make_error(parser_error::e_syntax,
20251 current_token(),
20252 "ERR002 - Invalid expression encountered",
20253 exprtk_error_location));
20254 }
20255
20256 if ((0 != e) && branch_deletable(e))
20257 {
20258 destroy_node(e);
20259 }
20260
20261 dec_.clear ();
20262 sem_.cleanup ();
20263 return_cleanup();
20264
20265 return false;
20266 }
20267 }
20268
20269 inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
20270 {
20271 expression_t expr;
20272
20273 expr.register_symbol_table(symtab);
20274
20275 compile(expression_string,expr);
20276
20277 return expr;
20278 }
20279
20280 void process_lexer_errors()
20281 {
20282 for (std::size_t i = 0; i < lexer().size(); ++i)
20283 {
20284 if (lexer()[i].is_error())
20285 {
20286 std::string diagnostic = "ERR003 - ";
20287
20288 switch (lexer()[i].type)
20289 {
20290 case lexer::token::e_error : diagnostic += "General token error";
20291 break;
20292
20293 case lexer::token::e_err_symbol : diagnostic += "Symbol error";
20294 break;
20295
20296 case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
20297 break;
20298
20299 case lexer::token::e_err_string : diagnostic += "Invalid string token";
20300 break;
20301
20302 case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
20303 break;
20304
20305 default : diagnostic += "Unknown compiler error";
20306 }
20307
20308 set_error(
20309 make_error(parser_error::e_lexer,
20310 lexer()[i],
20311 diagnostic + ": " + lexer()[i].value,
20312 exprtk_error_location));
20313 }
20314 }
20315 }
20316
20317 inline bool run_assemblies()
20318 {
20319 if (settings_.commutative_check_enabled())
20320 {
20321 helper_assembly_.run_inserters(lexer());
20322 }
20323
20324 if (settings_.joiner_enabled())
20325 {
20326 helper_assembly_.run_joiners(lexer());
20327 }
20328
20329 if (settings_.replacer_enabled())
20330 {
20331 helper_assembly_.run_modifiers(lexer());
20332 }
20333
20334 if (
20335 settings_.numeric_check_enabled () ||
20336 settings_.bracket_check_enabled () ||
20337 settings_.sequence_check_enabled()
20338 )
20339 {
20340 if (!helper_assembly_.run_scanners(lexer()))
20341 {
20342 if (helper_assembly_.error_token_scanner)
20343 {
20344 lexer::helper::bracket_checker* bracket_checker_ptr = 0;
20345 lexer::helper::numeric_checker* numeric_checker_ptr = 0;
20346 lexer::helper::sequence_validator* sequence_validator_ptr = 0;
20347 lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
20348
20349 if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
20350 {
20351 set_error(
20352 make_error(parser_error::e_token,
20353 bracket_checker_ptr->error_token(),
20354 "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
20355 exprtk_error_location));
20356 }
20357 else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
20358 {
20359 for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
20360 {
20361 lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
20362
20363 set_error(
20364 make_error(parser_error::e_token,
20365 error_token,
20366 "ERR005 - Invalid numeric token: '" + error_token.value + "'",
20367 exprtk_error_location));
20368 }
20369
20370 if (numeric_checker_ptr->error_count())
20371 {
20372 numeric_checker_ptr->clear_errors();
20373 }
20374 }
20375 else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
20376 {
20377 for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
20378 {
20379 std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
20380
20381 set_error(
20382 make_error(parser_error::e_token,
20383 error_token.first,
20384 "ERR006 - Invalid token sequence: '" +
20385 error_token.first.value + "' and '" +
20386 error_token.second.value + "'",
20387 exprtk_error_location));
20388 }
20389
20390 if (sequence_validator_ptr->error_count())
20391 {
20392 sequence_validator_ptr->clear_errors();
20393 }
20394 }
20395 else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
20396 {
20397 for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
20398 {
20399 std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
20400
20401 set_error(
20402 make_error(parser_error::e_token,
20403 error_token.first,
20404 "ERR007 - Invalid token sequence: '" +
20405 error_token.first.value + "' and '" +
20406 error_token.second.value + "'",
20407 exprtk_error_location));
20408 }
20409
20410 if (sequence_validator3_ptr->error_count())
20411 {
20412 sequence_validator3_ptr->clear_errors();
20413 }
20414 }
20415 }
20416
20417 return false;
20418 }
20419 }
20420
20421 return true;
20422 }
20423
20424 inline settings_store& settings()
20425 {
20426 return settings_;
20427 }
20428
20429 inline parser_error::type get_error(const std::size_t& index) const
20430 {
20431 if (index < error_list_.size())
20432 return error_list_[index];
20433 else
20434 throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
20435 }
20436
20437 inline std::string error() const
20438 {
20439 if (!error_list_.empty())
20440 {
20441 return error_list_[0].diagnostic;
20442 }
20443 else
20444 return std::string("No Error");
20445 }
20446
20447 inline std::size_t error_count() const
20448 {
20449 return error_list_.size();
20450 }
20451
20452 inline dependent_entity_collector& dec()
20453 {
20454 return dec_;
20455 }
20456
20457 inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
20458 {
20459 if (!settings_.replacer_enabled())
20460 return false;
20461 else if (details::is_reserved_word(old_symbol))
20462 return false;
20463 else
20464 return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
20465 }
20466
20467 inline bool remove_replace_symbol(const std::string& symbol)
20468 {
20469 if (!settings_.replacer_enabled())
20470 return false;
20471 else if (details::is_reserved_word(symbol))
20472 return false;
20473 else
20474 return symbol_replacer_.remove(symbol);
20475 }
20476
20477 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
20478 {
20479 resolve_unknown_symbol_ = true;
20480
20481 if (usr)
20482 unknown_symbol_resolver_ = usr;
20483 else
20484 unknown_symbol_resolver_ = &default_usr_;
20485 }
20486
20487 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
20488 {
20489 enable_unknown_symbol_resolver(&usr);
20490 }
20491
20492 inline void disable_unknown_symbol_resolver()
20493 {
20494 resolve_unknown_symbol_ = false;
20495 unknown_symbol_resolver_ = &default_usr_;
20496 }
20497
20498 private:
20499
20500 inline bool valid_base_operation(const std::string& symbol) const
20501 {
20502 const std::size_t length = symbol.size();
20503
20504 if (
20505 (length < 3) || // Shortest base op symbol length
20506 (length > 9) // Longest base op symbol length
20507 )
20508 return false;
20509 else
20510 return settings_.function_enabled(symbol) &&
20511 (base_ops_map_.end() != base_ops_map_.find(symbol));
20512 }
20513
20514 inline bool valid_vararg_operation(const std::string& symbol) const
20515 {
20516 static const std::string s_sum = "sum" ;
20517 static const std::string s_mul = "mul" ;
20518 static const std::string s_avg = "avg" ;
20519 static const std::string s_min = "min" ;
20520 static const std::string s_max = "max" ;
20521 static const std::string s_mand = "mand";
20522 static const std::string s_mor = "mor" ;
20523 static const std::string s_multi = "~" ;
20524 static const std::string s_mswitch = "[*]" ;
20525
20526 return
20527 (
20528 details::imatch(symbol,s_sum ) ||
20529 details::imatch(symbol,s_mul ) ||
20530 details::imatch(symbol,s_avg ) ||
20531 details::imatch(symbol,s_min ) ||
20532 details::imatch(symbol,s_max ) ||
20533 details::imatch(symbol,s_mand ) ||
20534 details::imatch(symbol,s_mor ) ||
20535 details::imatch(symbol,s_multi ) ||
20536 details::imatch(symbol,s_mswitch)
20537 ) &&
20538 settings_.function_enabled(symbol);
20539 }
20540
20541 bool is_invalid_logic_operation(const details::operator_type operation) const
20542 {
20543 return settings_.logic_disabled(operation);
20544 }
20545
20546 bool is_invalid_arithmetic_operation(const details::operator_type operation) const
20547 {
20548 return settings_.arithmetic_disabled(operation);
20549 }
20550
20551 bool is_invalid_assignment_operation(const details::operator_type operation) const
20552 {
20553 return settings_.assignment_disabled(operation);
20554 }
20555
20556 bool is_invalid_inequality_operation(const details::operator_type operation) const
20557 {
20558 return settings_.inequality_disabled(operation);
20559 }
20560
20561 #ifdef exprtk_enable_debugging
20562 inline void next_token()
20563 {
20564 const std::string ct_str = current_token().value;
20565 parser_helper::next_token();
20566 const std::string depth(2 * state_.scope_depth,' ');
20567 exprtk_debug(("%s"
20568 "prev[%s] --> curr[%s]\n",
20569 depth.c_str(),
20570 ct_str.c_str(),
20571 current_token().value.c_str()));
20572 }
20573 #endif
20574
20575 inline expression_node_ptr parse_corpus()
20576 {
20577 std::vector<expression_node_ptr> arg_list;
20578 std::vector<bool> side_effect_list;
20579
20580 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
20581
20582 lexer::token begin_token;
20583 lexer::token end_token;
20584
20585 for ( ; ; )
20586 {
20587 state_.side_effect_present = false;
20588
20589 begin_token = current_token();
20590
20591 expression_node_ptr arg = parse_expression();
20592
20593 if (0 == arg)
20594 {
20595 if (error_list_.empty())
20596 {
20597 set_error(
20598 make_error(parser_error::e_syntax,
20599 current_token(),
20600 "ERR008 - Invalid expression encountered",
20601 exprtk_error_location));
20602 }
20603
20604 return error_node();
20605 }
20606 else
20607 {
20608 arg_list.push_back(arg);
20609
20610 side_effect_list.push_back(state_.side_effect_present);
20611
20612 end_token = current_token();
20613
20614 const std::string sub_expr = construct_subexpr(begin_token, end_token);
20615
20616 exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
20617 static_cast<int>(arg_list.size() - 1),
20618 sub_expr.c_str()));
20619
20620 exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
20621 static_cast<int>(arg_list.size() - 1),
20622 state_.side_effect_present ? "true" : "false"));
20623
20624 exprtk_debug(("-------------------------------------------------\n"));
20625 }
20626
20627 if (lexer().finished())
20628 break;
20629 else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
20630 {
20631 if (lexer().finished())
20632 break;
20633 else
20634 next_token();
20635 }
20636 }
20637
20638 if (
20639 !arg_list.empty() &&
20640 is_return_node(arg_list.back())
20641 )
20642 {
20643 dec_.final_stmt_return_ = true;
20644 }
20645
20646 const expression_node_ptr result = simplify(arg_list,side_effect_list);
20647
20648 sdd.delete_ptr = (0 == result);
20649
20650 return result;
20651 }
20652
20653 std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
20654 {
20655 std::string result = lexer().substr(begin_token.position,end_token.position);
20656
20657 for (std::size_t i = 0; i < result.size(); ++i)
20658 {
20659 if (details::is_whitespace(result[i])) result[i] = ' ';
20660 }
20661
20662 return result;
20663 }
20664
20665 static const precedence_level default_precedence = e_level00;
20666
20667 struct state_t
20668 {
20669 inline void set(const precedence_level& l,
20670 const precedence_level& r,
20671 const details::operator_type& o)
20672 {
20673 left = l;
20674 right = r;
20675 operation = o;
20676 }
20677
20678 inline void reset()
20679 {
20680 left = e_level00;
20681 right = e_level00;
20682 operation = details::e_default;
20683 }
20684
20685 precedence_level left;
20686 precedence_level right;
20687 details::operator_type operation;
20688 };
20689
20690 inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
20691 {
20692 expression_node_ptr expression = parse_branch(precedence);
20693
20694 if (0 == expression)
20695 {
20696 return error_node();
20697 }
20698
20699 bool break_loop = false;
20700
20701 state_t current_state;
20702
20703 for ( ; ; )
20704 {
20705 current_state.reset();
20706
20707 switch (current_token().type)
20708 {
20709 case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
20710 case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
20711 case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
20712 case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
20713 case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
20714 case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
20715 case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break;
20716 case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break;
20717 case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break;
20718 case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break;
20719 case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break;
20720 case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break;
20721 case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break;
20722 case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break;
20723 case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break;
20724 case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break;
20725 case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break;
20726 case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break;
20727 case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break;
20728 default : if (token_t::e_symbol == current_token().type)
20729 {
20730 static const std::string s_and = "and";
20731 static const std::string s_nand = "nand";
20732 static const std::string s_or = "or";
20733 static const std::string s_nor = "nor";
20734 static const std::string s_xor = "xor";
20735 static const std::string s_xnor = "xnor";
20736 static const std::string s_in = "in";
20737 static const std::string s_like = "like";
20738 static const std::string s_ilike = "ilike";
20739 static const std::string s_and1 = "&";
20740 static const std::string s_or1 = "|";
20741 static const std::string s_not = "not";
20742
20743 if (details::imatch(current_token().value,s_and))
20744 {
20745 current_state.set(e_level03, e_level04, details::e_and);
20746 break;
20747 }
20748 else if (details::imatch(current_token().value,s_and1))
20749 {
20750 #ifndef exprtk_disable_sc_andor
20751 current_state.set(e_level03, e_level04, details::e_scand);
20752 #else
20753 current_state.set(e_level03, e_level04, details::e_and);
20754 #endif
20755 break;
20756 }
20757 else if (details::imatch(current_token().value,s_nand))
20758 {
20759 current_state.set(e_level03, e_level04, details::e_nand);
20760 break;
20761 }
20762 else if (details::imatch(current_token().value,s_or))
20763 {
20764 current_state.set(e_level01, e_level02, details::e_or);
20765 break;
20766 }
20767 else if (details::imatch(current_token().value,s_or1))
20768 {
20769 #ifndef exprtk_disable_sc_andor
20770 current_state.set(e_level01, e_level02, details::e_scor);
20771 #else
20772 current_state.set(e_level01, e_level02, details::e_or);
20773 #endif
20774 break;
20775 }
20776 else if (details::imatch(current_token().value,s_nor))
20777 {
20778 current_state.set(e_level01, e_level02, details::e_nor);
20779 break;
20780 }
20781 else if (details::imatch(current_token().value,s_xor))
20782 {
20783 current_state.set(e_level01, e_level02, details::e_xor);
20784 break;
20785 }
20786 else if (details::imatch(current_token().value,s_xnor))
20787 {
20788 current_state.set(e_level01, e_level02, details::e_xnor);
20789 break;
20790 }
20791 else if (details::imatch(current_token().value,s_in))
20792 {
20793 current_state.set(e_level04, e_level04, details::e_in);
20794 break;
20795 }
20796 else if (details::imatch(current_token().value,s_like))
20797 {
20798 current_state.set(e_level04, e_level04, details::e_like);
20799 break;
20800 }
20801 else if (details::imatch(current_token().value,s_ilike))
20802 {
20803 current_state.set(e_level04, e_level04, details::e_ilike);
20804 break;
20805 }
20806 else if (details::imatch(current_token().value,s_not))
20807 {
20808 break;
20809 }
20810 }
20811
20812 break_loop = true;
20813 }
20814
20815 if (break_loop)
20816 {
20817 parse_pending_string_rangesize(expression);
20818 break;
20819 }
20820 else if (current_state.left < precedence)
20821 break;
20822
20823 const lexer::token prev_token = current_token();
20824
20825 next_token();
20826
20827 expression_node_ptr right_branch = error_node();
20828 expression_node_ptr new_expression = error_node();
20829
20830 if (is_invalid_logic_operation(current_state.operation))
20831 {
20832 free_node(node_allocator_,expression);
20833
20834 set_error(
20835 make_error(parser_error::e_syntax,
20836 prev_token,
20837 "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
20838 exprtk_error_location));
20839
20840 return error_node();
20841 }
20842 else if (is_invalid_arithmetic_operation(current_state.operation))
20843 {
20844 free_node(node_allocator_,expression);
20845
20846 set_error(
20847 make_error(parser_error::e_syntax,
20848 prev_token,
20849 "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
20850 exprtk_error_location));
20851
20852 return error_node();
20853 }
20854 else if (is_invalid_inequality_operation(current_state.operation))
20855 {
20856 free_node(node_allocator_,expression);
20857
20858 set_error(
20859 make_error(parser_error::e_syntax,
20860 prev_token,
20861 "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
20862 exprtk_error_location));
20863
20864 return error_node();
20865 }
20866 else if (is_invalid_assignment_operation(current_state.operation))
20867 {
20868 free_node(node_allocator_,expression);
20869
20870 set_error(
20871 make_error(parser_error::e_syntax,
20872 prev_token,
20873 "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
20874 exprtk_error_location));
20875
20876 return error_node();
20877 }
20878
20879 if (0 != (right_branch = parse_expression(current_state.right)))
20880 {
20881 if (
20882 details::is_return_node( expression) ||
20883 details::is_return_node(right_branch)
20884 )
20885 {
20886 free_node(node_allocator_, expression);
20887 free_node(node_allocator_, right_branch);
20888
20889 set_error(
20890 make_error(parser_error::e_syntax,
20891 prev_token,
20892 "ERR013 - Return statements cannot be part of sub-expressions",
20893 exprtk_error_location));
20894
20895 return error_node();
20896 }
20897
20898 new_expression = expression_generator_
20899 (
20900 current_state.operation,
20901 expression,
20902 right_branch
20903 );
20904 }
20905
20906 if (0 == new_expression)
20907 {
20908 if (error_list_.empty())
20909 {
20910 set_error(
20911 make_error(parser_error::e_syntax,
20912 prev_token,
20913 !synthesis_error_.empty() ?
20914 synthesis_error_ :
20915 "ERR014 - General parsing error at token: '" + prev_token.value + "'",
20916 exprtk_error_location));
20917 }
20918
20919 free_node(node_allocator_, expression);
20920 free_node(node_allocator_, right_branch);
20921
20922 return error_node();
20923 }
20924 else
20925 {
20926 if (
20927 token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
20928 (precedence == e_level00)
20929 )
20930 {
20931 expression = parse_ternary_conditional_statement(new_expression);
20932 }
20933 else
20934 expression = new_expression;
20935
20936 parse_pending_string_rangesize(expression);
20937 }
20938 }
20939
20940 return expression;
20941 }
20942
20943 bool simplify_unary_negation_branch(expression_node_ptr& node)
20944 {
20945 {
20946 typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
20947 ubn_t* n = dynamic_cast<ubn_t*>(node);
20948
20949 if (n)
20950 {
20951 expression_node_ptr un_r = n->branch(0);
20952 n->release();
20953 free_node(node_allocator_,node);
20954 node = un_r;
20955
20956 return true;
20957 }
20958 }
20959
20960 {
20961 typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
20962
20963 uvn_t* n = dynamic_cast<uvn_t*>(node);
20964
20965 if (n)
20966 {
20967 const T& v = n->v();
20968 expression_node_ptr return_node = error_node();
20969
20970 if (
20971 (0 != (return_node = symtab_store_.get_variable(v))) ||
20972 (0 != (return_node = sem_ .get_variable(v)))
20973 )
20974 {
20975 free_node(node_allocator_,node);
20976 node = return_node;
20977
20978 return true;
20979 }
20980 else
20981 {
20982 set_error(
20983 make_error(parser_error::e_syntax,
20984 current_token(),
20985 "ERR015 - Failed to find variable node in symbol table",
20986 exprtk_error_location));
20987
20988 free_node(node_allocator_,node);
20989
20990 return false;
20991 }
20992 }
20993 }
20994
20995 return false;
20996 }
20997
20998 static inline expression_node_ptr error_node()
20999 {
21000 return reinterpret_cast<expression_node_ptr>(0);
21001 }
21002
21003 template <typename Type, std::size_t N>
21004 struct scoped_delete
21005 {
21006 typedef Type* ptr_t;
21007
21008 scoped_delete(parser<T>& pr, ptr_t& p)
21009 : delete_ptr(true),
21010 parser_(pr),
21011 p_(&p)
21012 {}
21013
21014 scoped_delete(parser<T>& pr, ptr_t (&p)[N])
21015 : delete_ptr(true),
21016 parser_(pr),
21017 p_(&p[0])
21018 {}
21019
21020 ~scoped_delete()
21021 {
21022 if (delete_ptr)
21023 {
21024 for (std::size_t i = 0; i < N; ++i)
21025 {
21026 free_node(parser_.node_allocator_,p_[i]);
21027 }
21028 }
21029 }
21030
21031 bool delete_ptr;
21032 parser<T>& parser_;
21033 ptr_t* p_;
21034
21035 private:
21036
21037 scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
21038 };
21039
21040 template <typename Type>
21041 struct scoped_deq_delete
21042 {
21043 typedef Type* ptr_t;
21044
21045 scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
21046 : delete_ptr(true),
21047 parser_(pr),
21048 deq_(deq)
21049 {}
21050
21051 ~scoped_deq_delete()
21052 {
21053 if (delete_ptr && !deq_.empty())
21054 {
21055 for (std::size_t i = 0; i < deq_.size(); ++i)
21056 {
21057 free_node(parser_.node_allocator_,deq_[i]);
21058 }
21059
21060 deq_.clear();
21061 }
21062 }
21063
21064 bool delete_ptr;
21065 parser<T>& parser_;
21066 std::deque<ptr_t>& deq_;
21067
21068 private:
21069
21070 scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
21071 };
21072
21073 template <typename Type>
21074 struct scoped_vec_delete
21075 {
21076 typedef Type* ptr_t;
21077
21078 scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21079 : delete_ptr(true),
21080 parser_(pr),
21081 vec_(vec)
21082 {}
21083
21084 ~scoped_vec_delete()
21085 {
21086 if (delete_ptr && !vec_.empty())
21087 {
21088 for (std::size_t i = 0; i < vec_.size(); ++i)
21089 {
21090 free_node(parser_.node_allocator_,vec_[i]);
21091 }
21092
21093 vec_.clear();
21094 }
21095 }
21096
21097 bool delete_ptr;
21098 parser<T>& parser_;
21099 std::vector<ptr_t>& vec_;
21100
21101 private:
21102
21103 scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
21104 };
21105
21106 struct scoped_bool_negator
21107 {
21108 explicit scoped_bool_negator(bool& bb)
21109 : b(bb)
21110 { b = !b; }
21111
21112 ~scoped_bool_negator()
21113 { b = !b; }
21114
21115 bool& b;
21116 };
21117
21118 struct scoped_bool_or_restorer
21119 {
21120 explicit scoped_bool_or_restorer(bool& bb)
21121 : b(bb),
21122 original_value_(bb)
21123 {}
21124
21125 ~scoped_bool_or_restorer()
21126 {
21127 b = b || original_value_;
21128 }
21129
21130 bool& b;
21131 bool original_value_;
21132 };
21133
21134 inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
21135 {
21136 expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
21137
21138 switch (function->param_count)
21139 {
21140 case 0 : func_node = parse_function_call_0 (function,function_name); break;
21141 case 1 : func_node = parse_function_call< 1>(function,function_name); break;
21142 case 2 : func_node = parse_function_call< 2>(function,function_name); break;
21143 case 3 : func_node = parse_function_call< 3>(function,function_name); break;
21144 case 4 : func_node = parse_function_call< 4>(function,function_name); break;
21145 case 5 : func_node = parse_function_call< 5>(function,function_name); break;
21146 case 6 : func_node = parse_function_call< 6>(function,function_name); break;
21147 case 7 : func_node = parse_function_call< 7>(function,function_name); break;
21148 case 8 : func_node = parse_function_call< 8>(function,function_name); break;
21149 case 9 : func_node = parse_function_call< 9>(function,function_name); break;
21150 case 10 : func_node = parse_function_call<10>(function,function_name); break;
21151 case 11 : func_node = parse_function_call<11>(function,function_name); break;
21152 case 12 : func_node = parse_function_call<12>(function,function_name); break;
21153 case 13 : func_node = parse_function_call<13>(function,function_name); break;
21154 case 14 : func_node = parse_function_call<14>(function,function_name); break;
21155 case 15 : func_node = parse_function_call<15>(function,function_name); break;
21156 case 16 : func_node = parse_function_call<16>(function,function_name); break;
21157 case 17 : func_node = parse_function_call<17>(function,function_name); break;
21158 case 18 : func_node = parse_function_call<18>(function,function_name); break;
21159 case 19 : func_node = parse_function_call<19>(function,function_name); break;
21160 case 20 : func_node = parse_function_call<20>(function,function_name); break;
21161 default : {
21162 set_error(
21163 make_error(parser_error::e_syntax,
21164 current_token(),
21165 "ERR016 - Invalid number of parameters for function: '" + function_name + "'",
21166 exprtk_error_location));
21167
21168 return error_node();
21169 }
21170 }
21171
21172 if (func_node)
21173 return func_node;
21174 else
21175 {
21176 set_error(
21177 make_error(parser_error::e_syntax,
21178 current_token(),
21179 "ERR017 - Failed to generate call to function: '" + function_name + "'",
21180 exprtk_error_location));
21181
21182 return error_node();
21183 }
21184 }
21185
21186 template <std::size_t NumberofParameters>
21187 inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
21188 {
21189 #ifdef _MSC_VER
21190 #pragma warning(push)
21191 #pragma warning(disable: 4127)
21192 #endif
21193 if (0 == NumberofParameters)
21194 {
21195 set_error(
21196 make_error(parser_error::e_syntax,
21197 current_token(),
21198 "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
21199 exprtk_error_location));
21200
21201 return error_node();
21202 }
21203 #ifdef _MSC_VER
21204 #pragma warning(pop)
21205 #endif
21206
21207 expression_node_ptr branch[NumberofParameters];
21208 expression_node_ptr result = error_node();
21209
21210 std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21211
21212 scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
21213
21214 next_token();
21215
21216 if (!token_is(token_t::e_lbracket))
21217 {
21218 set_error(
21219 make_error(parser_error::e_syntax,
21220 current_token(),
21221 "ERR019 - Expecting argument list for function: '" + function_name + "'",
21222 exprtk_error_location));
21223
21224 return error_node();
21225 }
21226
21227 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
21228 {
21229 branch[i] = parse_expression();
21230
21231 if (0 == branch[i])
21232 {
21233 set_error(
21234 make_error(parser_error::e_syntax,
21235 current_token(),
21236 "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
21237 exprtk_error_location));
21238
21239 return error_node();
21240 }
21241 else if (i < static_cast<int>(NumberofParameters - 1))
21242 {
21243 if (!token_is(token_t::e_comma))
21244 {
21245 set_error(
21246 make_error(parser_error::e_syntax,
21247 current_token(),
21248 "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
21249 exprtk_error_location));
21250
21251 return error_node();
21252 }
21253 }
21254 }
21255
21256 if (!token_is(token_t::e_rbracket))
21257 {
21258 set_error(
21259 make_error(parser_error::e_syntax,
21260 current_token(),
21261 "ERR022 - Invalid number of arguments for function: '" + function_name + "'",
21262 exprtk_error_location));
21263
21264 return error_node();
21265 }
21266 else
21267 result = expression_generator_.function(function,branch);
21268
21269 sd.delete_ptr = false;
21270
21271 return result;
21272 }
21273
21274 inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
21275 {
21276 expression_node_ptr result = expression_generator_.function(function);
21277
21278 state_.side_effect_present = function->has_side_effects();
21279
21280 next_token();
21281
21282 if (
21283 token_is(token_t::e_lbracket) &&
21284 !token_is(token_t::e_rbracket)
21285 )
21286 {
21287 set_error(
21288 make_error(parser_error::e_syntax,
21289 current_token(),
21290 "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'",
21291 exprtk_error_location));
21292
21293 free_node(node_allocator_,result);
21294
21295 return error_node();
21296 }
21297 else
21298 return result;
21299 }
21300
21301 template <std::size_t MaxNumberofParameters>
21302 inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
21303 {
21304 std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21305
21306 scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
21307
21308 next_token();
21309
21310 if (!token_is(token_t::e_lbracket))
21311 {
21312 set_error(
21313 make_error(parser_error::e_syntax,
21314 current_token(),
21315 "ERR024 - Expected a '(' at start of function call to '" + function_name +
21316 "', instead got: '" + current_token().value + "'",
21317 exprtk_error_location));
21318
21319 return 0;
21320 }
21321
21322 if (token_is(token_t::e_rbracket, e_hold))
21323 {
21324 set_error(
21325 make_error(parser_error::e_syntax,
21326 current_token(),
21327 "ERR025 - Expected at least one input parameter for function call '" + function_name + "'",
21328 exprtk_error_location));
21329
21330 return 0;
21331 }
21332
21333 std::size_t param_index = 0;
21334
21335 for (; param_index < MaxNumberofParameters; ++param_index)
21336 {
21337 param_list[param_index] = parse_expression();
21338
21339 if (0 == param_list[param_index])
21340 return 0;
21341 else if (token_is(token_t::e_rbracket))
21342 {
21343 sd.delete_ptr = false;
21344 break;
21345 }
21346 else if (token_is(token_t::e_comma))
21347 continue;
21348 else
21349 {
21350 set_error(
21351 make_error(parser_error::e_syntax,
21352 current_token(),
21353 "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
21354 exprtk_error_location));
21355
21356 return 0;
21357 }
21358 }
21359
21360 if (sd.delete_ptr)
21361 {
21362 set_error(
21363 make_error(parser_error::e_syntax,
21364 current_token(),
21365 "ERR027 - Invalid number of input parameters passed to function '" + function_name + "'",
21366 exprtk_error_location));
21367
21368 return 0;
21369 }
21370
21371 return (param_index + 1);
21372 }
21373
21374 inline expression_node_ptr parse_base_operation()
21375 {
21376 typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
21377
21378 const std::string operation_name = current_token().value;
21379 const token_t diagnostic_token = current_token();
21380
21381 map_range_t itr_range = base_ops_map_.equal_range(operation_name);
21382
21383 if (0 == std::distance(itr_range.first,itr_range.second))
21384 {
21385 set_error(
21386 make_error(parser_error::e_syntax,
21387 diagnostic_token,
21388 "ERR028 - No entry found for base operation: " + operation_name,
21389 exprtk_error_location));
21390
21391 return error_node();
21392 }
21393
21394 static const std::size_t MaxNumberofParameters = 4;
21395 expression_node_ptr param_list[MaxNumberofParameters] = {0};
21396
21397 const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
21398
21399 if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
21400 {
21401 for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
21402 {
21403 const details::base_operation_t& operation = itr->second;
21404
21405 if (operation.num_params == parameter_count)
21406 {
21407 switch (parameter_count)
21408 {
21409 #define base_opr_case(N) \
21410 case N : { \
21411 expression_node_ptr pl##N[N] = {0}; \
21412 std::copy(param_list, param_list + N, pl##N); \
21413 lodge_symbol(operation_name, e_st_function); \
21414 return expression_generator_(operation.type, pl##N); \
21415 } \
21416
21417 base_opr_case(1)
21418 base_opr_case(2)
21419 base_opr_case(3)
21420 base_opr_case(4)
21421 #undef base_opr_case
21422 }
21423 }
21424 }
21425 }
21426
21427 for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
21428 {
21429 free_node(node_allocator_, param_list[i]);
21430 }
21431
21432 set_error(
21433 make_error(parser_error::e_syntax,
21434 diagnostic_token,
21435 "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'",
21436 exprtk_error_location));
21437
21438 return error_node();
21439 }
21440
21441 inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
21442 {
21443 // Parse: [if][(][condition][,][consequent][,][alternative][)]
21444
21445 expression_node_ptr consequent = error_node();
21446 expression_node_ptr alternative = error_node();
21447
21448 bool result = true;
21449
21450 if (!token_is(token_t::e_comma))
21451 {
21452 set_error(
21453 make_error(parser_error::e_syntax,
21454 current_token(),
21455 "ERR030 - Expected ',' between if-statement condition and consequent",
21456 exprtk_error_location));
21457 result = false;
21458 }
21459 else if (0 == (consequent = parse_expression()))
21460 {
21461 set_error(
21462 make_error(parser_error::e_syntax,
21463 current_token(),
21464 "ERR031 - Failed to parse consequent for if-statement",
21465 exprtk_error_location));
21466 result = false;
21467 }
21468 else if (!token_is(token_t::e_comma))
21469 {
21470 set_error(
21471 make_error(parser_error::e_syntax,
21472 current_token(),
21473 "ERR032 - Expected ',' between if-statement consequent and alternative",
21474 exprtk_error_location));
21475 result = false;
21476 }
21477 else if (0 == (alternative = parse_expression()))
21478 {
21479 set_error(
21480 make_error(parser_error::e_syntax,
21481 current_token(),
21482 "ERR033 - Failed to parse alternative for if-statement",
21483 exprtk_error_location));
21484 result = false;
21485 }
21486 else if (!token_is(token_t::e_rbracket))
21487 {
21488 set_error(
21489 make_error(parser_error::e_syntax,
21490 current_token(),
21491 "ERR034 - Expected ')' at the end of if-statement",
21492 exprtk_error_location));
21493 result = false;
21494 }
21495
21496 #ifndef exprtk_disable_string_capabilities
21497 if (result)
21498 {
21499 const bool consq_is_str = is_generally_string_node( consequent);
21500 const bool alter_is_str = is_generally_string_node(alternative);
21501
21502 if (consq_is_str || alter_is_str)
21503 {
21504 if (consq_is_str && alter_is_str)
21505 {
21506 return expression_generator_
21507 .conditional_string(condition, consequent, alternative);
21508 }
21509
21510 set_error(
21511 make_error(parser_error::e_syntax,
21512 current_token(),
21513 "ERR035 - Return types of ternary if-statement differ",
21514 exprtk_error_location));
21515
21516 result = false;
21517 }
21518 }
21519 #endif
21520
21521 if (!result)
21522 {
21523 free_node(node_allocator_, condition);
21524 free_node(node_allocator_, consequent);
21525 free_node(node_allocator_,alternative);
21526
21527 return error_node();
21528 }
21529 else
21530 return expression_generator_
21531 .conditional(condition, consequent, alternative);
21532 }
21533
21534 inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
21535 {
21536 expression_node_ptr consequent = error_node();
21537 expression_node_ptr alternative = error_node();
21538
21539 bool result = true;
21540
21541 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21542 {
21543 if (0 == (consequent = parse_multi_sequence("if-statement-01")))
21544 {
21545 set_error(
21546 make_error(parser_error::e_syntax,
21547 current_token(),
21548 "ERR036 - Failed to parse body of consequent for if-statement",
21549 exprtk_error_location));
21550
21551 result = false;
21552 }
21553 }
21554 else
21555 {
21556 if (
21557 settings_.commutative_check_enabled() &&
21558 token_is(token_t::e_mul,prsrhlpr_t::e_hold)
21559 )
21560 {
21561 next_token();
21562 }
21563
21564 if (0 != (consequent = parse_expression()))
21565 {
21566 if (!token_is(token_t::e_eof))
21567 {
21568 set_error(
21569 make_error(parser_error::e_syntax,
21570 current_token(),
21571 "ERR037 - Expected ';' at the end of the consequent for if-statement",
21572 exprtk_error_location));
21573
21574 result = false;
21575 }
21576 }
21577 else
21578 {
21579 set_error(
21580 make_error(parser_error::e_syntax,
21581 current_token(),
21582 "ERR038 - Failed to parse body of consequent for if-statement",
21583 exprtk_error_location));
21584
21585 result = false;
21586 }
21587 }
21588
21589 if (result)
21590 {
21591 if (details::imatch(current_token().value,"else"))
21592 {
21593 next_token();
21594
21595 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21596 {
21597 if (0 == (alternative = parse_multi_sequence("else-statement-01")))
21598 {
21599 set_error(
21600 make_error(parser_error::e_syntax,
21601 current_token(),
21602 "ERR039 - Failed to parse body of the 'else' for if-statement",
21603 exprtk_error_location));
21604
21605 result = false;
21606 }
21607 }
21608 else if (details::imatch(current_token().value,"if"))
21609 {
21610 if (0 == (alternative = parse_conditional_statement()))
21611 {
21612 set_error(
21613 make_error(parser_error::e_syntax,
21614 current_token(),
21615 "ERR040 - Failed to parse body of if-else statement",
21616 exprtk_error_location));
21617
21618 result = false;
21619 }
21620 }
21621 else if (0 != (alternative = parse_expression()))
21622 {
21623 if (!token_is(token_t::e_eof))
21624 {
21625 set_error(
21626 make_error(parser_error::e_syntax,
21627 current_token(),
21628 "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement",
21629 exprtk_error_location));
21630
21631 result = false;
21632 }
21633 }
21634 else
21635 {
21636 set_error(
21637 make_error(parser_error::e_syntax,
21638 current_token(),
21639 "ERR042 - Failed to parse body of the 'else' for if-statement",
21640 exprtk_error_location));
21641
21642 result = false;
21643 }
21644 }
21645 }
21646
21647 #ifndef exprtk_disable_string_capabilities
21648 if (result)
21649 {
21650 const bool consq_is_str = is_generally_string_node( consequent);
21651 const bool alter_is_str = is_generally_string_node(alternative);
21652
21653 if (consq_is_str || alter_is_str)
21654 {
21655 if (consq_is_str && alter_is_str)
21656 {
21657 return expression_generator_
21658 .conditional_string(condition, consequent, alternative);
21659 }
21660
21661 set_error(
21662 make_error(parser_error::e_syntax,
21663 current_token(),
21664 "ERR043 - Return types of ternary if-statement differ",
21665 exprtk_error_location));
21666
21667 result = false;
21668 }
21669 }
21670 #endif
21671
21672 if (!result)
21673 {
21674 free_node(node_allocator_, condition);
21675 free_node(node_allocator_, consequent);
21676 free_node(node_allocator_, alternative);
21677
21678 return error_node();
21679 }
21680 else
21681 return expression_generator_
21682 .conditional(condition, consequent, alternative);
21683 }
21684
21685 inline expression_node_ptr parse_conditional_statement()
21686 {
21687 expression_node_ptr condition = error_node();
21688
21689 next_token();
21690
21691 if (!token_is(token_t::e_lbracket))
21692 {
21693 set_error(
21694 make_error(parser_error::e_syntax,
21695 current_token(),
21696 "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
21697 exprtk_error_location));
21698
21699 return error_node();
21700 }
21701 else if (0 == (condition = parse_expression()))
21702 {
21703 set_error(
21704 make_error(parser_error::e_syntax,
21705 current_token(),
21706 "ERR045 - Failed to parse condition for if-statement",
21707 exprtk_error_location));
21708
21709 return error_node();
21710 }
21711 else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
21712 {
21713 // if (x,y,z)
21714 return parse_conditional_statement_01(condition);
21715 }
21716 else if (token_is(token_t::e_rbracket))
21717 {
21718 // 00. if (x) y;
21719 // 01. if (x) y; else z;
21720 // 02. if (x) y; else {z0; ... zn;}
21721 // 03. if (x) y; else if (z) w;
21722 // 04. if (x) y; else if (z) w; else u;
21723 // 05. if (x) y; else if (z) w; else {u0; ... un;}
21724 // 06. if (x) y; else if (z) {w0; ... wn;}
21725 // 07. if (x) {y0; ... yn;}
21726 // 08. if (x) {y0; ... yn;} else z;
21727 // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
21728 // 10. if (x) {y0; ... yn;} else if (z) w;
21729 // 11. if (x) {y0; ... yn;} else if (z) w; else u;
21730 // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
21731 // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
21732 return parse_conditional_statement_02(condition);
21733 }
21734
21735 set_error(
21736 make_error(parser_error::e_syntax,
21737 current_token(),
21738 "ERR046 - Invalid if-statement",
21739 exprtk_error_location));
21740
21741 free_node(node_allocator_,condition);
21742
21743 return error_node();
21744 }
21745
21746 inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
21747 {
21748 // Parse: [condition][?][consequent][:][alternative]
21749 expression_node_ptr consequent = error_node();
21750 expression_node_ptr alternative = error_node();
21751
21752 bool result = true;
21753
21754 if (0 == condition)
21755 {
21756 set_error(
21757 make_error(parser_error::e_syntax,
21758 current_token(),
21759 "ERR047 - Encountered invalid condition branch for ternary if-statement",
21760 exprtk_error_location));
21761
21762 return error_node();
21763 }
21764 else if (!token_is(token_t::e_ternary))
21765 {
21766 set_error(
21767 make_error(parser_error::e_syntax,
21768 current_token(),
21769 "ERR048 - Expected '?' after condition of ternary if-statement",
21770 exprtk_error_location));
21771
21772 result = false;
21773 }
21774 else if (0 == (consequent = parse_expression()))
21775 {
21776 set_error(
21777 make_error(parser_error::e_syntax,
21778 current_token(),
21779 "ERR049 - Failed to parse consequent for ternary if-statement",
21780 exprtk_error_location));
21781
21782 result = false;
21783 }
21784 else if (!token_is(token_t::e_colon))
21785 {
21786 set_error(
21787 make_error(parser_error::e_syntax,
21788 current_token(),
21789 "ERR050 - Expected ':' between ternary if-statement consequent and alternative",
21790 exprtk_error_location));
21791
21792 result = false;
21793 }
21794 else if (0 == (alternative = parse_expression()))
21795 {
21796 set_error(
21797 make_error(parser_error::e_syntax,
21798 current_token(),
21799 "ERR051 - Failed to parse alternative for ternary if-statement",
21800 exprtk_error_location));
21801
21802 result = false;
21803 }
21804
21805 #ifndef exprtk_disable_string_capabilities
21806 if (result)
21807 {
21808 const bool consq_is_str = is_generally_string_node( consequent);
21809 const bool alter_is_str = is_generally_string_node(alternative);
21810
21811 if (consq_is_str || alter_is_str)
21812 {
21813 if (consq_is_str && alter_is_str)
21814 {
21815 return expression_generator_
21816 .conditional_string(condition, consequent, alternative);
21817 }
21818
21819 set_error(
21820 make_error(parser_error::e_syntax,
21821 current_token(),
21822 "ERR052 - Return types of ternary if-statement differ",
21823 exprtk_error_location));
21824
21825 result = false;
21826 }
21827 }
21828 #endif
21829
21830 if (!result)
21831 {
21832 free_node(node_allocator_, condition);
21833 free_node(node_allocator_, consequent);
21834 free_node(node_allocator_, alternative);
21835
21836 return error_node();
21837 }
21838 else
21839 return expression_generator_
21840 .conditional(condition, consequent, alternative);
21841 }
21842
21843 inline expression_node_ptr parse_not_statement()
21844 {
21845 if (settings_.logic_disabled("not"))
21846 {
21847 set_error(
21848 make_error(parser_error::e_syntax,
21849 current_token(),
21850 "ERR053 - Invalid or disabled logic operation 'not'",
21851 exprtk_error_location));
21852
21853 return error_node();
21854 }
21855
21856 return parse_base_operation();
21857 }
21858
21859 inline expression_node_ptr parse_while_loop()
21860 {
21861 // Parse: [while][(][test expr][)][{][expression][}]
21862 expression_node_ptr condition = error_node();
21863 expression_node_ptr branch = error_node();
21864 expression_node_ptr result_node = error_node();
21865
21866 bool result = true;
21867
21868 next_token();
21869
21870 if (!token_is(token_t::e_lbracket))
21871 {
21872 set_error(
21873 make_error(parser_error::e_syntax,
21874 current_token(),
21875 "ERR054 - Expected '(' at start of while-loop condition statement",
21876 exprtk_error_location));
21877
21878 return error_node();
21879 }
21880 else if (0 == (condition = parse_expression()))
21881 {
21882 set_error(
21883 make_error(parser_error::e_syntax,
21884 current_token(),
21885 "ERR055 - Failed to parse condition for while-loop",
21886 exprtk_error_location));
21887
21888 return error_node();
21889 }
21890 else if (!token_is(token_t::e_rbracket))
21891 {
21892 set_error(
21893 make_error(parser_error::e_syntax,
21894 current_token(),
21895 "ERR056 - Expected ')' at end of while-loop condition statement",
21896 exprtk_error_location));
21897
21898 result = false;
21899 }
21900
21901 brkcnt_list_.push_front(false);
21902
21903 if (result)
21904 {
21905 if (0 == (branch = parse_multi_sequence("while-loop")))
21906 {
21907 set_error(
21908 make_error(parser_error::e_syntax,
21909 current_token(),
21910 "ERR057 - Failed to parse body of while-loop"));
21911 result = false;
21912 }
21913 else if (0 == (result_node = expression_generator_.while_loop(condition,
21914 branch,
21915 brkcnt_list_.front())))
21916 {
21917 set_error(
21918 make_error(parser_error::e_syntax,
21919 current_token(),
21920 "ERR058 - Failed to synthesize while-loop",
21921 exprtk_error_location));
21922
21923 result = false;
21924 }
21925 }
21926
21927 if (!result)
21928 {
21929 free_node(node_allocator_, branch);
21930 free_node(node_allocator_, condition);
21931 free_node(node_allocator_, result_node);
21932
21933 brkcnt_list_.pop_front();
21934
21935 return error_node();
21936 }
21937 else
21938 return result_node;
21939 }
21940
21941 inline expression_node_ptr parse_repeat_until_loop()
21942 {
21943 // Parse: [repeat][{][expression][}][until][(][test expr][)]
21944 expression_node_ptr condition = error_node();
21945 expression_node_ptr branch = error_node();
21946 next_token();
21947
21948 std::vector<expression_node_ptr> arg_list;
21949 std::vector<bool> side_effect_list;
21950
21951 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21952
21953 brkcnt_list_.push_front(false);
21954
21955 if (details::imatch(current_token().value,"until"))
21956 {
21957 next_token();
21958 branch = node_allocator_.allocate<details::null_node<T> >();
21959 }
21960 else
21961 {
21962 const token_t::token_type seperator = token_t::e_eof;
21963
21964 scope_handler sh(*this);
21965
21966 scoped_bool_or_restorer sbr(state_.side_effect_present);
21967
21968 for ( ; ; )
21969 {
21970 state_.side_effect_present = false;
21971
21972 expression_node_ptr arg = parse_expression();
21973
21974 if (0 == arg)
21975 return error_node();
21976 else
21977 {
21978 arg_list.push_back(arg);
21979 side_effect_list.push_back(state_.side_effect_present);
21980 }
21981
21982 if (details::imatch(current_token().value,"until"))
21983 {
21984 next_token();
21985 break;
21986 }
21987
21988 const bool is_next_until = peek_token_is(token_t::e_symbol) &&
21989 peek_token_is("until");
21990
21991 if (!token_is(seperator) && is_next_until)
21992 {
21993 set_error(
21994 make_error(parser_error::e_syntax,
21995 current_token(),
21996 "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
21997 exprtk_error_location));
21998
21999 return error_node();
22000 }
22001
22002 if (details::imatch(current_token().value,"until"))
22003 {
22004 next_token();
22005 break;
22006 }
22007 }
22008
22009 branch = simplify(arg_list,side_effect_list);
22010
22011 sdd.delete_ptr = (0 == branch);
22012
22013 if (sdd.delete_ptr)
22014 {
22015 brkcnt_list_.pop_front();
22016
22017 set_error(
22018 make_error(parser_error::e_syntax,
22019 current_token(),
22020 "ERR060 - Failed to parse body of repeat until loop",
22021 exprtk_error_location));
22022
22023 return error_node();
22024 }
22025 }
22026
22027 if (!token_is(token_t::e_lbracket))
22028 {
22029 brkcnt_list_.pop_front();
22030
22031 set_error(
22032 make_error(parser_error::e_syntax,
22033 current_token(),
22034 "ERR061 - Expected '(' before condition statement of repeat until loop",
22035 exprtk_error_location));
22036
22037 free_node(node_allocator_,branch);
22038
22039 return error_node();
22040 }
22041 else if (0 == (condition = parse_expression()))
22042 {
22043 brkcnt_list_.pop_front();
22044
22045 set_error(
22046 make_error(parser_error::e_syntax,
22047 current_token(),
22048 "ERR062 - Failed to parse condition for repeat until loop",
22049 exprtk_error_location));
22050
22051 free_node(node_allocator_,branch);
22052
22053 return error_node();
22054 }
22055 else if (!token_is(token_t::e_rbracket))
22056 {
22057 set_error(
22058 make_error(parser_error::e_syntax,
22059 current_token(),
22060 "ERR063 - Expected ')' after condition of repeat until loop",
22061 exprtk_error_location));
22062
22063 free_node(node_allocator_, branch);
22064 free_node(node_allocator_, condition);
22065
22066 brkcnt_list_.pop_front();
22067
22068 return error_node();
22069 }
22070
22071 expression_node_ptr result;
22072
22073 result = expression_generator_
22074 .repeat_until_loop(condition, branch, brkcnt_list_.front());
22075
22076 if (0 == result)
22077 {
22078 set_error(
22079 make_error(parser_error::e_syntax,
22080 current_token(),
22081 "ERR064 - Failed to synthesize repeat until loop",
22082 exprtk_error_location));
22083
22084 free_node(node_allocator_,condition);
22085
22086 brkcnt_list_.pop_front();
22087
22088 return error_node();
22089 }
22090 else
22091 {
22092 brkcnt_list_.pop_front();
22093 return result;
22094 }
22095 }
22096
22097 inline expression_node_ptr parse_for_loop()
22098 {
22099 expression_node_ptr initialiser = error_node();
22100 expression_node_ptr condition = error_node();
22101 expression_node_ptr incrementor = error_node();
22102 expression_node_ptr loop_body = error_node();
22103
22104 scope_element* se = 0;
22105 bool result = true;
22106
22107 next_token();
22108
22109 scope_handler sh(*this);
22110
22111 if (!token_is(token_t::e_lbracket))
22112 {
22113 set_error(
22114 make_error(parser_error::e_syntax,
22115 current_token(),
22116 "ERR065 - Expected '(' at start of for-loop",
22117 exprtk_error_location));
22118
22119 return error_node();
22120 }
22121
22122 if (!token_is(token_t::e_eof))
22123 {
22124 if (
22125 !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
22126 details::imatch(current_token().value,"var")
22127 )
22128 {
22129 next_token();
22130
22131 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
22132 {
22133 set_error(
22134 make_error(parser_error::e_syntax,
22135 current_token(),
22136 "ERR066 - Expected a variable at the start of initialiser section of for-loop",
22137 exprtk_error_location));
22138
22139 return error_node();
22140 }
22141 else if (!peek_token_is(token_t::e_assign))
22142 {
22143 set_error(
22144 make_error(parser_error::e_syntax,
22145 current_token(),
22146 "ERR067 - Expected variable assignment of initialiser section of for-loop",
22147 exprtk_error_location));
22148
22149 return error_node();
22150 }
22151
22152 const std::string loop_counter_symbol = current_token().value;
22153
22154 se = &sem_.get_element(loop_counter_symbol);
22155
22156 if ((se->name == loop_counter_symbol) && se->active)
22157 {
22158 set_error(
22159 make_error(parser_error::e_syntax,
22160 current_token(),
22161 "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
22162 exprtk_error_location));
22163
22164 return error_node();
22165 }
22166 else if (!symtab_store_.is_variable(loop_counter_symbol))
22167 {
22168 if (
22169 !se->active &&
22170 (se->name == loop_counter_symbol) &&
22171 (se->type == scope_element::e_variable)
22172 )
22173 {
22174 se->active = true;
22175 se->ref_count++;
22176 }
22177 else
22178 {
22179 scope_element nse;
22180 nse.name = loop_counter_symbol;
22181 nse.active = true;
22182 nse.ref_count = 1;
22183 nse.type = scope_element::e_variable;
22184 nse.depth = state_.scope_depth;
22185 nse.data = new T(T(0));
22186 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
22187
22188 if (!sem_.add_element(nse))
22189 {
22190 set_error(
22191 make_error(parser_error::e_syntax,
22192 current_token(),
22193 "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
22194 exprtk_error_location));
22195
22196 sem_.free_element(nse);
22197
22198 result = false;
22199 }
22200 else
22201 {
22202 exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
22203
22204 state_.activate_side_effect("parse_for_loop()");
22205 }
22206 }
22207 }
22208 }
22209
22210 if (0 == (initialiser = parse_expression()))
22211 {
22212 set_error(
22213 make_error(parser_error::e_syntax,
22214 current_token(),
22215 "ERR070 - Failed to parse initialiser of for-loop",
22216 exprtk_error_location));
22217
22218 result = false;
22219 }
22220 else if (!token_is(token_t::e_eof))
22221 {
22222 set_error(
22223 make_error(parser_error::e_syntax,
22224 current_token(),
22225 "ERR071 - Expected ';' after initialiser of for-loop",
22226 exprtk_error_location));
22227
22228 result = false;
22229 }
22230 }
22231
22232 if (!token_is(token_t::e_eof))
22233 {
22234 if (0 == (condition = parse_expression()))
22235 {
22236 set_error(
22237 make_error(parser_error::e_syntax,
22238 current_token(),
22239 "ERR072 - Failed to parse condition of for-loop",
22240 exprtk_error_location));
22241
22242 result = false;
22243 }
22244 else if (!token_is(token_t::e_eof))
22245 {
22246 set_error(
22247 make_error(parser_error::e_syntax,
22248 current_token(),
22249 "ERR073 - Expected ';' after condition section of for-loop",
22250 exprtk_error_location));
22251
22252 result = false;
22253 }
22254 }
22255
22256 if (!token_is(token_t::e_rbracket))
22257 {
22258 if (0 == (incrementor = parse_expression()))
22259 {
22260 set_error(
22261 make_error(parser_error::e_syntax,
22262 current_token(),
22263 "ERR074 - Failed to parse incrementor of for-loop",
22264 exprtk_error_location));
22265
22266 result = false;
22267 }
22268 else if (!token_is(token_t::e_rbracket))
22269 {
22270 set_error(
22271 make_error(parser_error::e_syntax,
22272 current_token(),
22273 "ERR075 - Expected ')' after incrementor section of for-loop",
22274 exprtk_error_location));
22275
22276 result = false;
22277 }
22278 }
22279
22280 if (result)
22281 {
22282 brkcnt_list_.push_front(false);
22283
22284 if (0 == (loop_body = parse_multi_sequence("for-loop")))
22285 {
22286 set_error(
22287 make_error(parser_error::e_syntax,
22288 current_token(),
22289 "ERR076 - Failed to parse body of for-loop",
22290 exprtk_error_location));
22291
22292 result = false;
22293 }
22294 }
22295
22296 if (!result)
22297 {
22298 if (se)
22299 {
22300 se->ref_count--;
22301 }
22302
22303 free_node(node_allocator_, initialiser);
22304 free_node(node_allocator_, condition);
22305 free_node(node_allocator_, incrementor);
22306 free_node(node_allocator_, loop_body);
22307
22308 if (!brkcnt_list_.empty())
22309 {
22310 brkcnt_list_.pop_front();
22311 }
22312
22313 return error_node();
22314 }
22315 else
22316 {
22317 expression_node_ptr result_node =
22318 expression_generator_.for_loop(initialiser,
22319 condition,
22320 incrementor,
22321 loop_body,
22322 brkcnt_list_.front());
22323 brkcnt_list_.pop_front();
22324
22325 return result_node;
22326 }
22327 }
22328
22329 inline expression_node_ptr parse_switch_statement()
22330 {
22331 std::vector<expression_node_ptr> arg_list;
22332 expression_node_ptr result = error_node();
22333
22334 if (!details::imatch(current_token().value,"switch"))
22335 {
22336 set_error(
22337 make_error(parser_error::e_syntax,
22338 current_token(),
22339 "ERR077 - Expected keyword 'switch'",
22340 exprtk_error_location));
22341
22342 return error_node();
22343 }
22344
22345 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22346
22347 next_token();
22348
22349 if (!token_is(token_t::e_lcrlbracket))
22350 {
22351 set_error(
22352 make_error(parser_error::e_syntax,
22353 current_token(),
22354 "ERR078 - Expected '{' for call to switch statement",
22355 exprtk_error_location));
22356
22357 return error_node();
22358 }
22359
22360 for ( ; ; )
22361 {
22362 if (!details::imatch("case",current_token().value))
22363 {
22364 set_error(
22365 make_error(parser_error::e_syntax,
22366 current_token(),
22367 "ERR079 - Expected either a 'case' or 'default' statement",
22368 exprtk_error_location));
22369
22370 return error_node();
22371 }
22372
22373 next_token();
22374
22375 expression_node_ptr condition = parse_expression();
22376
22377 if (0 == condition)
22378 return error_node();
22379 else if (!token_is(token_t::e_colon))
22380 {
22381 set_error(
22382 make_error(parser_error::e_syntax,
22383 current_token(),
22384 "ERR080 - Expected ':' for case of switch statement",
22385 exprtk_error_location));
22386
22387 return error_node();
22388 }
22389
22390 expression_node_ptr consequent = parse_expression();
22391
22392 if (0 == consequent)
22393 return error_node();
22394 else if (!token_is(token_t::e_eof))
22395 {
22396 set_error(
22397 make_error(parser_error::e_syntax,
22398 current_token(),
22399 "ERR081 - Expected ';' at end of case for switch statement",
22400 exprtk_error_location));
22401
22402 return error_node();
22403 }
22404
22405 // Can we optimise away the case statement?
22406 if (is_constant_node(condition) && is_false(condition))
22407 {
22408 free_node(node_allocator_, condition);
22409 free_node(node_allocator_, consequent);
22410 }
22411 else
22412 {
22413 arg_list.push_back( condition);
22414 arg_list.push_back(consequent);
22415 }
22416
22417 if (details::imatch("default",current_token().value))
22418 {
22419 next_token();
22420 if (!token_is(token_t::e_colon))
22421 {
22422 set_error(
22423 make_error(parser_error::e_syntax,
22424 current_token(),
22425 "ERR082 - Expected ':' for default of switch statement",
22426 exprtk_error_location));
22427
22428 return error_node();
22429 }
22430
22431 expression_node_ptr default_statement = error_node();
22432
22433 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22434 default_statement = parse_multi_sequence("switch-default");
22435 else
22436 default_statement = parse_expression();
22437
22438 if (0 == default_statement)
22439 return error_node();
22440 else if (!token_is(token_t::e_eof))
22441 {
22442 free_node(node_allocator_,default_statement);
22443
22444 set_error(
22445 make_error(parser_error::e_syntax,
22446 current_token(),
22447 "ERR083 - Expected ';' at end of default for switch statement",
22448 exprtk_error_location));
22449
22450 return error_node();
22451 }
22452
22453 arg_list.push_back(default_statement);
22454 break;
22455 }
22456 }
22457
22458 if (!token_is(token_t::e_rcrlbracket))
22459 {
22460 set_error(
22461 make_error(parser_error::e_syntax,
22462 current_token(),
22463 "ERR084 - Expected '}' at end of switch statement",
22464 exprtk_error_location));
22465
22466 return error_node();
22467 }
22468
22469 result = expression_generator_.switch_statement(arg_list);
22470
22471 svd.delete_ptr = (0 == result);
22472
22473 return result;
22474 }
22475
22476 inline expression_node_ptr parse_multi_switch_statement()
22477 {
22478 std::vector<expression_node_ptr> arg_list;
22479
22480 if (!details::imatch(current_token().value,"[*]"))
22481 {
22482 set_error(
22483 make_error(parser_error::e_syntax,
22484 current_token(),
22485 "ERR085 - Expected token '[*]'",
22486 exprtk_error_location));
22487
22488 return error_node();
22489 }
22490
22491 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22492
22493 next_token();
22494
22495 if (!token_is(token_t::e_lcrlbracket))
22496 {
22497 set_error(
22498 make_error(parser_error::e_syntax,
22499 current_token(),
22500 "ERR086 - Expected '{' for call to [*] statement",
22501 exprtk_error_location));
22502
22503 return error_node();
22504 }
22505
22506 for ( ; ; )
22507 {
22508 if (!details::imatch("case",current_token().value))
22509 {
22510 set_error(
22511 make_error(parser_error::e_syntax,
22512 current_token(),
22513 "ERR087 - Expected a 'case' statement for multi-switch",
22514 exprtk_error_location));
22515
22516 return error_node();
22517 }
22518
22519 next_token();
22520
22521 expression_node_ptr condition = parse_expression();
22522
22523 if (0 == condition)
22524 return error_node();
22525
22526 if (!token_is(token_t::e_colon))
22527 {
22528 set_error(
22529 make_error(parser_error::e_syntax,
22530 current_token(),
22531 "ERR088 - Expected ':' for case of [*] statement",
22532 exprtk_error_location));
22533
22534 return error_node();
22535 }
22536
22537 expression_node_ptr consequent = parse_expression();
22538
22539 if (0 == consequent)
22540 return error_node();
22541
22542 if (!token_is(token_t::e_eof))
22543 {
22544 set_error(
22545 make_error(parser_error::e_syntax,
22546 current_token(),
22547 "ERR089 - Expected ';' at end of case for [*] statement",
22548 exprtk_error_location));
22549
22550 return error_node();
22551 }
22552
22553 // Can we optimise away the case statement?
22554 if (is_constant_node(condition) && is_false(condition))
22555 {
22556 free_node(node_allocator_, condition);
22557 free_node(node_allocator_, consequent);
22558 }
22559 else
22560 {
22561 arg_list.push_back( condition);
22562 arg_list.push_back(consequent);
22563 }
22564
22565 if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
22566 {
22567 break;
22568 }
22569 }
22570
22571 if (!token_is(token_t::e_rcrlbracket))
22572 {
22573 set_error(
22574 make_error(parser_error::e_syntax,
22575 current_token(),
22576 "ERR090 - Expected '}' at end of [*] statement",
22577 exprtk_error_location));
22578
22579 return error_node();
22580 }
22581
22582 const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
22583
22584 svd.delete_ptr = (0 == result);
22585
22586 return result;
22587 }
22588
22589 inline expression_node_ptr parse_vararg_function()
22590 {
22591 std::vector<expression_node_ptr> arg_list;
22592
22593 details::operator_type opt_type = details::e_default;
22594 const std::string symbol = current_token().value;
22595
22596 if (details::imatch(symbol,"~"))
22597 {
22598 next_token();
22599 return parse_multi_sequence();
22600 }
22601 else if (details::imatch(symbol,"[*]"))
22602 {
22603 return parse_multi_switch_statement();
22604 }
22605 else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
22606 else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
22607 else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
22608 else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
22609 else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
22610 else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
22611 else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
22612 else
22613 {
22614 set_error(
22615 make_error(parser_error::e_syntax,
22616 current_token(),
22617 "ERR091 - Unsupported vararg function: " + symbol,
22618 exprtk_error_location));
22619
22620 return error_node();
22621 }
22622
22623 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22624
22625 lodge_symbol(symbol, e_st_function);
22626
22627 next_token();
22628
22629 if (!token_is(token_t::e_lbracket))
22630 {
22631 set_error(
22632 make_error(parser_error::e_syntax,
22633 current_token(),
22634 "ERR092 - Expected '(' for call to vararg function: " + symbol,
22635 exprtk_error_location));
22636
22637 return error_node();
22638 }
22639
22640 for ( ; ; )
22641 {
22642 expression_node_ptr arg = parse_expression();
22643
22644 if (0 == arg)
22645 return error_node();
22646 else
22647 arg_list.push_back(arg);
22648
22649 if (token_is(token_t::e_rbracket))
22650 break;
22651 else if (!token_is(token_t::e_comma))
22652 {
22653 set_error(
22654 make_error(parser_error::e_syntax,
22655 current_token(),
22656 "ERR093 - Expected ',' for call to vararg function: " + symbol,
22657 exprtk_error_location));
22658
22659 return error_node();
22660 }
22661 }
22662
22663 const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
22664
22665 sdd.delete_ptr = (0 == result);
22666 return result;
22667 }
22668
22669 #ifndef exprtk_disable_string_capabilities
22670 inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
22671 {
22672 if (!token_is(token_t::e_lsqrbracket))
22673 {
22674 set_error(
22675 make_error(parser_error::e_syntax,
22676 current_token(),
22677 "ERR094 - Expected '[' as start of string range definition",
22678 exprtk_error_location));
22679
22680 free_node(node_allocator_,expression);
22681
22682 return error_node();
22683 }
22684 else if (token_is(token_t::e_rsqrbracket))
22685 {
22686 return node_allocator_.allocate<details::string_size_node<T> >(expression);
22687 }
22688
22689 range_t rp;
22690
22691 if (!parse_range(rp,true))
22692 {
22693 free_node(node_allocator_,expression);
22694
22695 return error_node();
22696 }
22697
22698 expression_node_ptr result = expression_generator_(expression,rp);
22699
22700 if (0 == result)
22701 {
22702 set_error(
22703 make_error(parser_error::e_syntax,
22704 current_token(),
22705 "ERR095 - Failed to generate string range node",
22706 exprtk_error_location));
22707
22708 free_node(node_allocator_,expression);
22709 }
22710
22711 rp.clear();
22712
22713 return result;
22714 }
22715 #else
22716 inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
22717 {
22718 return error_node();
22719 }
22720 #endif
22721
22722 inline void parse_pending_string_rangesize(expression_node_ptr& expression)
22723 {
22724 // Allow no more than 100 range calls, eg: s[][][]...[][]
22725 const std::size_t max_rangesize_parses = 100;
22726
22727 std::size_t i = 0;
22728
22729 while
22730 (
22731 (0 != expression) &&
22732 (i++ < max_rangesize_parses) &&
22733 error_list_.empty() &&
22734 is_generally_string_node(expression) &&
22735 token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
22736 )
22737 {
22738 expression = parse_string_range_statement(expression);
22739 }
22740 }
22741
22742 template <typename Allocator1,
22743 typename Allocator2,
22744 template <typename, typename> class Sequence>
22745 inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
22746 Sequence<bool,Allocator2>& side_effect_list,
22747 const bool specialise_on_final_type = false)
22748 {
22749 if (expression_list.empty())
22750 return error_node();
22751 else if (1 == expression_list.size())
22752 return expression_list[0];
22753
22754 Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
22755
22756 bool return_node_present = false;
22757
22758 for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
22759 {
22760 if (is_variable_node(expression_list[i]))
22761 continue;
22762 else if (
22763 is_return_node (expression_list[i]) ||
22764 is_break_node (expression_list[i]) ||
22765 is_continue_node(expression_list[i])
22766 )
22767 {
22768 tmp_expression_list.push_back(expression_list[i]);
22769
22770 // Remove all subexpressions after first short-circuit
22771 // node has been encountered.
22772
22773 for (std::size_t j = i + 1; j < expression_list.size(); ++j)
22774 {
22775 free_node(node_allocator_,expression_list[j]);
22776 }
22777
22778 return_node_present = true;
22779
22780 break;
22781 }
22782 else if (
22783 is_constant_node(expression_list[i]) ||
22784 is_null_node (expression_list[i]) ||
22785 !side_effect_list[i]
22786 )
22787 {
22788 free_node(node_allocator_,expression_list[i]);
22789 continue;
22790 }
22791 else
22792 tmp_expression_list.push_back(expression_list[i]);
22793 }
22794
22795 if (!return_node_present)
22796 {
22797 tmp_expression_list.push_back(expression_list.back());
22798 }
22799
22800 expression_list.swap(tmp_expression_list);
22801
22802 if (tmp_expression_list.size() > expression_list.size())
22803 {
22804 exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
22805 static_cast<int>(tmp_expression_list.size()),
22806 static_cast<int>(expression_list .size())));
22807 }
22808
22809 if (
22810 return_node_present ||
22811 side_effect_list.back() ||
22812 (expression_list.size() > 1)
22813 )
22814 state_.activate_side_effect("simplify()");
22815
22816 if (1 == expression_list.size())
22817 return expression_list[0];
22818 else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
22819 return expression_generator_.vararg_function(details::e_smulti,expression_list);
22820 else
22821 return expression_generator_.vararg_function(details::e_multi,expression_list);
22822 }
22823
22824 inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
22825 {
22826 token_t::token_type close_bracket = token_t::e_rcrlbracket;
22827 token_t::token_type seperator = token_t::e_eof;
22828
22829 if (!token_is(token_t::e_lcrlbracket))
22830 {
22831 if (token_is(token_t::e_lbracket))
22832 {
22833 close_bracket = token_t::e_rbracket;
22834 seperator = token_t::e_comma;
22835 }
22836 else
22837 {
22838 set_error(
22839 make_error(parser_error::e_syntax,
22840 current_token(),
22841 "ERR096 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
22842 ((!source.empty()) ? std::string(" section of " + source): ""),
22843 exprtk_error_location));
22844
22845 return error_node();
22846 }
22847 }
22848 else if (token_is(token_t::e_rcrlbracket))
22849 {
22850 return node_allocator_.allocate<details::null_node<T> >();
22851 }
22852
22853 std::vector<expression_node_ptr> arg_list;
22854 std::vector<bool> side_effect_list;
22855
22856 expression_node_ptr result = error_node();
22857
22858 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22859
22860 scope_handler sh(*this);
22861
22862 scoped_bool_or_restorer sbr(state_.side_effect_present);
22863
22864 for ( ; ; )
22865 {
22866 state_.side_effect_present = false;
22867
22868 expression_node_ptr arg = parse_expression();
22869
22870 if (0 == arg)
22871 return error_node();
22872 else
22873 {
22874 arg_list.push_back(arg);
22875 side_effect_list.push_back(state_.side_effect_present);
22876 }
22877
22878 if (token_is(close_bracket))
22879 break;
22880
22881 const bool is_next_close = peek_token_is(close_bracket);
22882
22883 if (!token_is(seperator) && is_next_close)
22884 {
22885 set_error(
22886 make_error(parser_error::e_syntax,
22887 current_token(),
22888 "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
22889 exprtk_error_location));
22890
22891 return error_node();
22892 }
22893
22894 if (token_is(close_bracket))
22895 break;
22896 }
22897
22898 result = simplify(arg_list,side_effect_list,source.empty());
22899
22900 sdd.delete_ptr = (0 == result);
22901 return result;
22902 }
22903
22904 inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
22905 {
22906 // Examples of valid ranges:
22907 // 1. [1:5] -> 1..5
22908 // 2. [ :5] -> 0..5
22909 // 3. [1: ] -> 1..end
22910 // 4. [x:y] -> x..y where x <= y
22911 // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
22912 // 6. [ :y] -> 0..y where 0 <= y
22913 // 7. [x: ] -> x..end where x <= end
22914
22915 rp.clear();
22916
22917 if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
22918 {
22919 set_error(
22920 make_error(parser_error::e_syntax,
22921 current_token(),
22922 "ERR098 - Expected '[' for start of range",
22923 exprtk_error_location));
22924
22925 return false;
22926 }
22927
22928 if (token_is(token_t::e_colon))
22929 {
22930 rp.n0_c.first = true;
22931 rp.n0_c.second = 0;
22932 rp.cache.first = 0;
22933 }
22934 else
22935 {
22936 expression_node_ptr r0 = parse_expression();
22937
22938 if (0 == r0)
22939 {
22940 set_error(
22941 make_error(parser_error::e_syntax,
22942 current_token(),
22943 "ERR099 - Failed parse begin section of range",
22944 exprtk_error_location));
22945
22946 return false;
22947 }
22948 else if (is_constant_node(r0))
22949 {
22950 const T r0_value = r0->value();
22951
22952 if (r0_value >= T(0))
22953 {
22954 rp.n0_c.first = true;
22955 rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
22956 rp.cache.first = rp.n0_c.second;
22957 }
22958
22959 free_node(node_allocator_,r0);
22960
22961 if (r0_value < T(0))
22962 {
22963 set_error(
22964 make_error(parser_error::e_syntax,
22965 current_token(),
22966 "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0",
22967 exprtk_error_location));
22968
22969 return false;
22970 }
22971 }
22972 else
22973 {
22974 rp.n0_e.first = true;
22975 rp.n0_e.second = r0;
22976 }
22977
22978 if (!token_is(token_t::e_colon))
22979 {
22980 set_error(
22981 make_error(parser_error::e_syntax,
22982 current_token(),
22983 "ERR101 - Expected ':' for break in range",
22984 exprtk_error_location));
22985
22986 rp.free();
22987
22988 return false;
22989 }
22990 }
22991
22992 if (token_is(token_t::e_rsqrbracket))
22993 {
22994 rp.n1_c.first = true;
22995 rp.n1_c.second = std::numeric_limits<std::size_t>::max();
22996 }
22997 else
22998 {
22999 expression_node_ptr r1 = parse_expression();
23000
23001 if (0 == r1)
23002 {
23003 set_error(
23004 make_error(parser_error::e_syntax,
23005 current_token(),
23006 "ERR102 - Failed parse end section of range",
23007 exprtk_error_location));
23008
23009 rp.free();
23010
23011 return false;
23012 }
23013 else if (is_constant_node(r1))
23014 {
23015 const T r1_value = r1->value();
23016
23017 if (r1_value >= T(0))
23018 {
23019 rp.n1_c.first = true;
23020 rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
23021 rp.cache.second = rp.n1_c.second;
23022 }
23023
23024 free_node(node_allocator_,r1);
23025
23026 if (r1_value < T(0))
23027 {
23028 set_error(
23029 make_error(parser_error::e_syntax,
23030 current_token(),
23031 "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0",
23032 exprtk_error_location));
23033
23034 return false;
23035 }
23036 }
23037 else
23038 {
23039 rp.n1_e.first = true;
23040 rp.n1_e.second = r1;
23041 }
23042
23043 if (!token_is(token_t::e_rsqrbracket))
23044 {
23045 set_error(
23046 make_error(parser_error::e_syntax,
23047 current_token(),
23048 "ERR104 - Expected ']' for start of range",
23049 exprtk_error_location));
23050
23051 rp.free();
23052
23053 return false;
23054 }
23055 }
23056
23057 if (rp.const_range())
23058 {
23059 std::size_t r0 = 0;
23060 std::size_t r1 = 0;
23061
23062 const bool rp_result = rp(r0,r1);
23063
23064 if (!rp_result || (r0 > r1))
23065 {
23066 set_error(
23067 make_error(parser_error::e_syntax,
23068 current_token(),
23069 "ERR105 - Invalid range, Constraint: r0 <= r1",
23070 exprtk_error_location));
23071
23072 return false;
23073 }
23074 }
23075
23076 return true;
23077 }
23078
23079 inline void lodge_symbol(const std::string& symbol,
23080 const symbol_type st)
23081 {
23082 dec_.add_symbol(symbol,st);
23083 }
23084
23085 #ifndef exprtk_disable_string_capabilities
23086 inline expression_node_ptr parse_string()
23087 {
23088 const std::string symbol = current_token().value;
23089
23090 typedef details::stringvar_node<T>* strvar_node_t;
23091
23092 expression_node_ptr result = error_node();
23093 strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23094
23095 scope_element& se = sem_.get_active_element(symbol);
23096
23097 if (scope_element::e_string == se.type)
23098 {
23099 se.active = true;
23100 result = se.str_node;
23101 lodge_symbol(symbol, e_st_local_string);
23102 }
23103 else
23104 {
23105 if (!symtab_store_.is_conststr_stringvar(symbol))
23106 {
23107 set_error(
23108 make_error(parser_error::e_syntax,
23109 current_token(),
23110 "ERR106 - Unknown string symbol",
23111 exprtk_error_location));
23112
23113 return error_node();
23114 }
23115
23116 result = symtab_store_.get_stringvar(symbol);
23117
23118 if (symtab_store_.is_constant_string(symbol))
23119 {
23120 const_str_node = static_cast<strvar_node_t>(result);
23121 result = expression_generator_(const_str_node->str());
23122 }
23123
23124 lodge_symbol(symbol, e_st_string);
23125 }
23126
23127 if (peek_token_is(token_t::e_lsqrbracket))
23128 {
23129 next_token();
23130
23131 if (peek_token_is(token_t::e_rsqrbracket))
23132 {
23133 next_token();
23134 next_token();
23135
23136 if (const_str_node)
23137 {
23138 free_node(node_allocator_,result);
23139
23140 return expression_generator_(T(const_str_node->size()));
23141 }
23142 else
23143 return node_allocator_.allocate<details::stringvar_size_node<T> >
23144 (static_cast<details::stringvar_node<T>*>(result)->ref());
23145 }
23146
23147 range_t rp;
23148
23149 if (!parse_range(rp))
23150 {
23151 free_node(node_allocator_,result);
23152
23153 return error_node();
23154 }
23155 else if (const_str_node)
23156 {
23157 free_node(node_allocator_,result);
23158 result = expression_generator_(const_str_node->ref(),rp);
23159 }
23160 else
23161 result = expression_generator_(static_cast<details::stringvar_node<T>*>
23162 (result)->ref(), rp);
23163
23164 if (result)
23165 rp.clear();
23166 }
23167 else
23168 next_token();
23169
23170 return result;
23171 }
23172 #else
23173 inline expression_node_ptr parse_string()
23174 {
23175 return error_node();
23176 }
23177 #endif
23178
23179 #ifndef exprtk_disable_string_capabilities
23180 inline expression_node_ptr parse_const_string()
23181 {
23182 const std::string const_str = current_token().value;
23183 expression_node_ptr result = expression_generator_(const_str);
23184
23185 if (peek_token_is(token_t::e_lsqrbracket))
23186 {
23187 next_token();
23188
23189 if (peek_token_is(token_t::e_rsqrbracket))
23190 {
23191 next_token();
23192 next_token();
23193
23194 free_node(node_allocator_,result);
23195
23196 return expression_generator_(T(const_str.size()));
23197 }
23198
23199 range_t rp;
23200
23201 if (!parse_range(rp))
23202 {
23203 free_node(node_allocator_,result);
23204
23205 return error_node();
23206 }
23207
23208 free_node(node_allocator_,result);
23209
23210 if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
23211 {
23212 rp.n1_c.second = const_str.size() - 1;
23213 rp.cache.second = rp.n1_c.second;
23214 }
23215
23216 if (
23217 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
23218 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
23219 )
23220 {
23221 set_error(
23222 make_error(parser_error::e_syntax,
23223 current_token(),
23224 "ERR107 - Overflow in range for string: '" + const_str + "'[" +
23225 (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
23226 (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
23227 exprtk_error_location));
23228
23229 return error_node();
23230 }
23231
23232 result = expression_generator_(const_str,rp);
23233
23234 if (result)
23235 rp.clear();
23236 }
23237 else
23238 next_token();
23239
23240 return result;
23241 }
23242 #else
23243 inline expression_node_ptr parse_const_string()
23244 {
23245 return error_node();
23246 }
23247 #endif
23248
23249 inline expression_node_ptr parse_vector()
23250 {
23251 const std::string symbol = current_token().value;
23252
23253 vector_holder_ptr vec = vector_holder_ptr(0);
23254
23255 const scope_element& se = sem_.get_active_element(symbol);
23256
23257 if (
23258 !details::imatch(se.name, symbol) ||
23259 (se.depth > state_.scope_depth) ||
23260 (scope_element::e_vector != se.type)
23261 )
23262 {
23263 if (0 == (vec = symtab_store_.get_vector(symbol)))
23264 {
23265 set_error(
23266 make_error(parser_error::e_syntax,
23267 current_token(),
23268 "ERR108 - Symbol '" + symbol+ " not a vector",
23269 exprtk_error_location));
23270
23271 return error_node();
23272 }
23273 }
23274 else
23275 vec = se.vec_node;
23276
23277 expression_node_ptr index_expr = error_node();
23278
23279 next_token();
23280
23281 if (!token_is(token_t::e_lsqrbracket))
23282 {
23283 return node_allocator_.allocate<vector_node_t>(vec);
23284 }
23285 else if (token_is(token_t::e_rsqrbracket))
23286 {
23287 return expression_generator_(T(vec->size()));
23288 }
23289 else if (0 == (index_expr = parse_expression()))
23290 {
23291 set_error(
23292 make_error(parser_error::e_syntax,
23293 current_token(),
23294 "ERR109 - Failed to parse index for vector: '" + symbol + "'",
23295 exprtk_error_location));
23296
23297 return error_node();
23298 }
23299 else if (!token_is(token_t::e_rsqrbracket))
23300 {
23301 set_error(
23302 make_error(parser_error::e_syntax,
23303 current_token(),
23304 "ERR110 - Expected ']' for index of vector: '" + symbol + "'",
23305 exprtk_error_location));
23306
23307 free_node(node_allocator_,index_expr);
23308
23309 return error_node();
23310 }
23311
23312 // Perform compile-time range check
23313 if (details::is_constant_node(index_expr))
23314 {
23315 const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
23316 const std::size_t vec_size = vec->size();
23317
23318 if (index >= vec_size)
23319 {
23320 set_error(
23321 make_error(parser_error::e_syntax,
23322 current_token(),
23323 "ERR111 - Index of " + details::to_str(index) + " out of range for "
23324 "vector '" + symbol + "' of size " + details::to_str(vec_size),
23325 exprtk_error_location));
23326
23327 free_node(node_allocator_,index_expr);
23328
23329 return error_node();
23330 }
23331 }
23332
23333 return expression_generator_.vector_element(symbol, vec, index_expr);
23334 }
23335
23336 inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
23337 {
23338 std::vector<expression_node_ptr> arg_list;
23339
23340 expression_node_ptr result = error_node();
23341
23342 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23343
23344 next_token();
23345
23346 if (token_is(token_t::e_lbracket))
23347 {
23348 if (token_is(token_t::e_rbracket))
23349 {
23350 if (!vararg_function->allow_zero_parameters())
23351 {
23352 set_error(
23353 make_error(parser_error::e_syntax,
23354 current_token(),
23355 "ERR112 - Zero parameter call to vararg function: "
23356 + vararg_function_name + " not allowed",
23357 exprtk_error_location));
23358
23359 return error_node();
23360 }
23361 }
23362 else
23363 {
23364 for ( ; ; )
23365 {
23366 expression_node_ptr arg = parse_expression();
23367
23368 if (0 == arg)
23369 return error_node();
23370 else
23371 arg_list.push_back(arg);
23372
23373 if (token_is(token_t::e_rbracket))
23374 break;
23375 else if (!token_is(token_t::e_comma))
23376 {
23377 set_error(
23378 make_error(parser_error::e_syntax,
23379 current_token(),
23380 "ERR113 - Expected ',' for call to vararg function: "
23381 + vararg_function_name,
23382 exprtk_error_location));
23383
23384 return error_node();
23385 }
23386 }
23387 }
23388 }
23389 else if (!vararg_function->allow_zero_parameters())
23390 {
23391 set_error(
23392 make_error(parser_error::e_syntax,
23393 current_token(),
23394 "ERR114 - Zero parameter call to vararg function: "
23395 + vararg_function_name + " not allowed",
23396 exprtk_error_location));
23397
23398 return error_node();
23399 }
23400
23401 if (arg_list.size() < vararg_function->min_num_args())
23402 {
23403 set_error(
23404 make_error(parser_error::e_syntax,
23405 current_token(),
23406 "ERR115 - Invalid number of parameters to call to vararg function: "
23407 + vararg_function_name + ", require at least "
23408 + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
23409 exprtk_error_location));
23410
23411 return error_node();
23412 }
23413 else if (arg_list.size() > vararg_function->max_num_args())
23414 {
23415 set_error(
23416 make_error(parser_error::e_syntax,
23417 current_token(),
23418 "ERR116 - Invalid number of parameters to call to vararg function: "
23419 + vararg_function_name + ", require no more than "
23420 + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
23421 exprtk_error_location));
23422
23423 return error_node();
23424 }
23425
23426 result = expression_generator_.vararg_function_call(vararg_function,arg_list);
23427
23428 sdd.delete_ptr = (0 == result);
23429
23430 return result;
23431 }
23432
23433 class type_checker
23434 {
23435 public:
23436
23437 enum return_type_t
23438 {
23439 e_overload = ' ',
23440 e_numeric = 'T',
23441 e_string = 'S'
23442 };
23443
23444 struct function_prototype_t
23445 {
23446 return_type_t return_type;
23447 std::string param_seq;
23448 };
23449
23450 typedef parser<T> parser_t;
23451 typedef std::vector<function_prototype_t> function_definition_list_t;
23452
23453 type_checker(parser_t& p,
23454 const std::string& func_name,
23455 const std::string& func_prototypes,
23456 const return_type_t default_return_type)
23457 : invalid_state_(true),
23458 parser_(p),
23459 function_name_(func_name),
23460 default_return_type_(default_return_type)
23461 {
23462 parse_function_prototypes(func_prototypes);
23463 }
23464
23465 void set_default_return_type(const std::string& return_type)
23466 {
23467 default_return_type_ = return_type;
23468 }
23469
23470 bool verify(const std::string& param_seq, std::size_t& pseq_index)
23471 {
23472 if (function_definition_list_.empty())
23473 return true;
23474
23475 std::vector<std::pair<std::size_t,char> > error_list;
23476
23477 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23478 {
23479 details::char_t diff_value = 0;
23480 std::size_t diff_index = 0;
23481
23482 const bool result = details::sequence_match(function_definition_list_[i].param_seq,
23483 param_seq,
23484 diff_index, diff_value);
23485
23486 if (result)
23487 {
23488 pseq_index = i;
23489 return true;
23490 }
23491 else
23492 error_list.push_back(std::make_pair(diff_index, diff_value));
23493 }
23494
23495 if (1 == error_list.size())
23496 {
23497 parser_.
23498 set_error(
23499 make_error(parser_error::e_syntax,
23500 parser_.current_token(),
23501 "ERR117 - Failed parameter type check for function '" + function_name_ + "', "
23502 "Expected '" + function_definition_list_[0].param_seq +
23503 "' call set: '" + param_seq + "'",
23504 exprtk_error_location));
23505 }
23506 else
23507 {
23508 // find first with largest diff_index;
23509 std::size_t max_diff_index = 0;
23510
23511 for (std::size_t i = 1; i < error_list.size(); ++i)
23512 {
23513 if (error_list[i].first > error_list[max_diff_index].first)
23514 {
23515 max_diff_index = i;
23516 }
23517 }
23518
23519 parser_.
23520 set_error(
23521 make_error(parser_error::e_syntax,
23522 parser_.current_token(),
23523 "ERR118 - Failed parameter type check for function '" + function_name_ + "', "
23524 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
23525 "' call set: '" + param_seq + "'",
23526 exprtk_error_location));
23527 }
23528
23529 return false;
23530 }
23531
23532 std::size_t paramseq_count() const
23533 {
23534 return function_definition_list_.size();
23535 }
23536
23537 std::string paramseq(const std::size_t& index) const
23538 {
23539 return function_definition_list_[index].param_seq;
23540 }
23541
23542 return_type_t return_type(const std::size_t& index) const
23543 {
23544 return function_definition_list_[index].return_type;
23545 }
23546
23547 bool invalid() const
23548 {
23549 return !invalid_state_;
23550 }
23551
23552 bool allow_zero_parameters() const
23553 {
23554
23555 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23556 {
23557 if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
23558 {
23559 return true;
23560 }
23561 }
23562
23563 return false;
23564 }
23565
23566 private:
23567
23568 std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
23569 {
23570 std::string::const_iterator current_begin = param_seq.begin();
23571 std::string::const_iterator iter = param_seq.begin();
23572
23573 std::vector<std::string> result;
23574
23575 while (iter != param_seq.end())
23576 {
23577 if (*iter == delimiter)
23578 {
23579 result.push_back(std::string(current_begin, iter));
23580 current_begin = ++iter;
23581 }
23582 else
23583 ++iter;
23584 }
23585
23586 if (current_begin != iter)
23587 {
23588 result.push_back(std::string(current_begin, iter));
23589 }
23590
23591 return result;
23592 }
23593
23594 inline bool is_valid_token(std::string param_seq,
23595 function_prototype_t& funcproto) const
23596 {
23597 // Determine return type
23598 funcproto.return_type = default_return_type_;
23599
23600 if (param_seq.size() > 2)
23601 {
23602 if (':' == param_seq[1])
23603 {
23604 // Note: Only overloaded igeneric functions can have return
23605 // type definitions.
23606 if (type_checker::e_overload != default_return_type_)
23607 return false;
23608
23609 switch (param_seq[0])
23610 {
23611 case 'T' : funcproto.return_type = type_checker::e_numeric;
23612 break;
23613
23614 case 'S' : funcproto.return_type = type_checker::e_string;
23615 break;
23616
23617 default : return false;
23618 }
23619
23620 param_seq.erase(0,2);
23621 }
23622 }
23623
23624 if (
23625 (std::string::npos != param_seq.find("?*")) ||
23626 (std::string::npos != param_seq.find("**"))
23627 )
23628 {
23629 return false;
23630 }
23631 else if (
23632 (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
23633 ("Z" == param_seq)
23634 )
23635 {
23636 funcproto.param_seq = param_seq;
23637 return true;
23638 }
23639
23640 return false;
23641 }
23642
23643 void parse_function_prototypes(const std::string& func_prototypes)
23644 {
23645 if (func_prototypes.empty())
23646 return;
23647
23648 std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
23649
23650 typedef std::map<std::string,std::size_t> param_seq_map_t;
23651 param_seq_map_t param_seq_map;
23652
23653 for (std::size_t i = 0; i < param_seq_list.size(); ++i)
23654 {
23655 function_prototype_t func_proto;
23656
23657 if (!is_valid_token(param_seq_list[i], func_proto))
23658 {
23659 invalid_state_ = false;
23660
23661 parser_.
23662 set_error(
23663 make_error(parser_error::e_syntax,
23664 parser_.current_token(),
23665 "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] +
23666 "' for function: " + function_name_,
23667 exprtk_error_location));
23668 return;
23669 }
23670
23671 param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
23672
23673 if (param_seq_map.end() != seq_itr)
23674 {
23675 invalid_state_ = false;
23676
23677 parser_.
23678 set_error(
23679 make_error(parser_error::e_syntax,
23680 parser_.current_token(),
23681 "ERR120 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
23682 "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
23683 "pseq_idx[" + details::to_str(i) + "] " +
23684 "param seq: " + param_seq_list[i],
23685 exprtk_error_location));
23686 return;
23687 }
23688
23689 function_definition_list_.push_back(func_proto);
23690 }
23691 }
23692
23693 type_checker(const type_checker&);
23694 type_checker& operator=(const type_checker&);
23695
23696 bool invalid_state_;
23697 parser_t& parser_;
23698 std::string function_name_;
23699 const return_type_t default_return_type_;
23700 function_definition_list_t function_definition_list_;
23701 };
23702
23703 inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
23704 {
23705 std::vector<expression_node_ptr> arg_list;
23706
23707 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23708
23709 next_token();
23710
23711 std::string param_type_list;
23712
23713 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23714
23715 if (tc.invalid())
23716 {
23717 set_error(
23718 make_error(parser_error::e_syntax,
23719 current_token(),
23720 "ERR121 - Type checker instantiation failure for generic function: " + function_name,
23721 exprtk_error_location));
23722
23723 return error_node();
23724 }
23725
23726 if (token_is(token_t::e_lbracket))
23727 {
23728 if (token_is(token_t::e_rbracket))
23729 {
23730 if (
23731 !function->allow_zero_parameters() &&
23732 !tc .allow_zero_parameters()
23733 )
23734 {
23735 set_error(
23736 make_error(parser_error::e_syntax,
23737 current_token(),
23738 "ERR122 - Zero parameter call to generic function: "
23739 + function_name + " not allowed",
23740 exprtk_error_location));
23741
23742 return error_node();
23743 }
23744 }
23745 else
23746 {
23747 for ( ; ; )
23748 {
23749 expression_node_ptr arg = parse_expression();
23750
23751 if (0 == arg)
23752 return error_node();
23753
23754 if (is_ivector_node(arg))
23755 param_type_list += 'V';
23756 else if (is_generally_string_node(arg))
23757 param_type_list += 'S';
23758 else // Everything else is assumed to be a scalar returning expression
23759 param_type_list += 'T';
23760
23761 arg_list.push_back(arg);
23762
23763 if (token_is(token_t::e_rbracket))
23764 break;
23765 else if (!token_is(token_t::e_comma))
23766 {
23767 set_error(
23768 make_error(parser_error::e_syntax,
23769 current_token(),
23770 "ERR123 - Expected ',' for call to generic function: " + function_name,
23771 exprtk_error_location));
23772
23773 return error_node();
23774 }
23775 }
23776 }
23777 }
23778 else if (
23779 !function->parameter_sequence.empty() &&
23780 function->allow_zero_parameters () &&
23781 !tc .allow_zero_parameters ()
23782 )
23783 {
23784 set_error(
23785 make_error(parser_error::e_syntax,
23786 current_token(),
23787 "ERR124 - Zero parameter call to generic function: "
23788 + function_name + " not allowed",
23789 exprtk_error_location));
23790
23791 return error_node();
23792 }
23793
23794 std::size_t param_seq_index = 0;
23795
23796 if (
23797 state_.type_check_enabled &&
23798 !tc.verify(param_type_list, param_seq_index)
23799 )
23800 {
23801 set_error(
23802 make_error(parser_error::e_syntax,
23803 current_token(),
23804 "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name,
23805 exprtk_error_location));
23806
23807 return error_node();
23808 }
23809
23810 expression_node_ptr result = error_node();
23811
23812 if (tc.paramseq_count() <= 1)
23813 result = expression_generator_
23814 .generic_function_call(function, arg_list);
23815 else
23816 result = expression_generator_
23817 .generic_function_call(function, arg_list, param_seq_index);
23818
23819 sdd.delete_ptr = (0 == result);
23820
23821 return result;
23822 }
23823
23824 inline bool parse_igeneric_function_params(std::string& param_type_list,
23825 std::vector<expression_node_ptr>& arg_list,
23826 const std::string& function_name,
23827 igeneric_function<T>* function,
23828 const type_checker& tc)
23829 {
23830 if (token_is(token_t::e_lbracket))
23831 {
23832 if (token_is(token_t::e_rbracket))
23833 {
23834 if (
23835 !function->allow_zero_parameters() &&
23836 !tc .allow_zero_parameters()
23837 )
23838 {
23839 set_error(
23840 make_error(parser_error::e_syntax,
23841 current_token(),
23842 "ERR126 - Zero parameter call to generic function: "
23843 + function_name + " not allowed",
23844 exprtk_error_location));
23845
23846 return false;
23847 }
23848 }
23849 else
23850 {
23851 for ( ; ; )
23852 {
23853 expression_node_ptr arg = parse_expression();
23854
23855 if (0 == arg)
23856 return false;
23857
23858 if (is_ivector_node(arg))
23859 param_type_list += 'V';
23860 else if (is_generally_string_node(arg))
23861 param_type_list += 'S';
23862 else // Everything else is a scalar returning expression
23863 param_type_list += 'T';
23864
23865 arg_list.push_back(arg);
23866
23867 if (token_is(token_t::e_rbracket))
23868 break;
23869 else if (!token_is(token_t::e_comma))
23870 {
23871 set_error(
23872 make_error(parser_error::e_syntax,
23873 current_token(),
23874 "ERR127 - Expected ',' for call to string function: " + function_name,
23875 exprtk_error_location));
23876
23877 return false;
23878 }
23879 }
23880 }
23881
23882 return true;
23883 }
23884 else
23885 return false;
23886 }
23887
23888 #ifndef exprtk_disable_string_capabilities
23889 inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
23890 {
23891 // Move pass the function name
23892 next_token();
23893
23894 std::string param_type_list;
23895
23896 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23897
23898 if (
23899 (!function->parameter_sequence.empty()) &&
23900 (0 == tc.paramseq_count())
23901 )
23902 {
23903 return error_node();
23904 }
23905
23906 std::vector<expression_node_ptr> arg_list;
23907 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23908
23909 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23910 {
23911 return error_node();
23912 }
23913
23914 std::size_t param_seq_index = 0;
23915
23916 if (!tc.verify(param_type_list, param_seq_index))
23917 {
23918 set_error(
23919 make_error(parser_error::e_syntax,
23920 current_token(),
23921 "ERR128 - Invalid input parameter sequence for call to string function: " + function_name,
23922 exprtk_error_location));
23923
23924 return error_node();
23925 }
23926
23927 expression_node_ptr result = error_node();
23928
23929 if (tc.paramseq_count() <= 1)
23930 result = expression_generator_
23931 .string_function_call(function, arg_list);
23932 else
23933 result = expression_generator_
23934 .string_function_call(function, arg_list, param_seq_index);
23935
23936 sdd.delete_ptr = (0 == result);
23937
23938 return result;
23939 }
23940
23941 inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
23942 {
23943 // Move pass the function name
23944 next_token();
23945
23946 std::string param_type_list;
23947
23948 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
23949
23950 if (
23951 (!function->parameter_sequence.empty()) &&
23952 (0 == tc.paramseq_count())
23953 )
23954 {
23955 return error_node();
23956 }
23957
23958 std::vector<expression_node_ptr> arg_list;
23959 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23960
23961 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23962 {
23963 return error_node();
23964 }
23965
23966 std::size_t param_seq_index = 0;
23967
23968 if (!tc.verify(param_type_list, param_seq_index))
23969 {
23970 set_error(
23971 make_error(parser_error::e_syntax,
23972 current_token(),
23973 "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name,
23974 exprtk_error_location));
23975
23976 return error_node();
23977 }
23978
23979 expression_node_ptr result = error_node();
23980
23981 if (type_checker::e_numeric == tc.return_type(param_seq_index))
23982 {
23983 if (tc.paramseq_count() <= 1)
23984 result = expression_generator_
23985 .generic_function_call(function, arg_list);
23986 else
23987 result = expression_generator_
23988 .generic_function_call(function, arg_list, param_seq_index);
23989 }
23990 else if (type_checker::e_string == tc.return_type(param_seq_index))
23991 {
23992 if (tc.paramseq_count() <= 1)
23993 result = expression_generator_
23994 .string_function_call(function, arg_list);
23995 else
23996 result = expression_generator_
23997 .string_function_call(function, arg_list, param_seq_index);
23998 }
23999 else
24000 {
24001 set_error(
24002 make_error(parser_error::e_syntax,
24003 current_token(),
24004 "ERR130 - Invalid return type for call to overloaded function: " + function_name,
24005 exprtk_error_location));
24006 }
24007
24008 sdd.delete_ptr = (0 == result);
24009 return result;
24010 }
24011 #endif
24012
24013 template <typename Type, std::size_t NumberOfParameters>
24014 struct parse_special_function_impl
24015 {
24016 static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
24017 {
24018 expression_node_ptr branch[NumberOfParameters];
24019 expression_node_ptr result = error_node();
24020
24021 std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
24022
24023 scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
24024
24025 p.next_token();
24026
24027 if (!p.token_is(token_t::e_lbracket))
24028 {
24029 p.set_error(
24030 make_error(parser_error::e_syntax,
24031 p.current_token(),
24032 "ERR131 - Expected '(' for special function '" + sf_name + "'",
24033 exprtk_error_location));
24034
24035 return error_node();
24036 }
24037
24038 for (std::size_t i = 0; i < NumberOfParameters; ++i)
24039 {
24040 branch[i] = p.parse_expression();
24041
24042 if (0 == branch[i])
24043 {
24044 return p.error_node();
24045 }
24046 else if (i < (NumberOfParameters - 1))
24047 {
24048 if (!p.token_is(token_t::e_comma))
24049 {
24050 p.set_error(
24051 make_error(parser_error::e_syntax,
24052 p.current_token(),
24053 "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'",
24054 exprtk_error_location));
24055
24056 return p.error_node();
24057 }
24058 }
24059 }
24060
24061 if (!p.token_is(token_t::e_rbracket))
24062 {
24063 p.set_error(
24064 make_error(parser_error::e_syntax,
24065 p.current_token(),
24066 "ERR133 - Invalid number of parameters for special function '" + sf_name + "'",
24067 exprtk_error_location));
24068
24069 return p.error_node();
24070 }
24071 else
24072 result = p.expression_generator_.special_function(opt_type,branch);
24073
24074 sd.delete_ptr = (0 == result);
24075
24076 return result;
24077 }
24078 };
24079
24080 inline expression_node_ptr parse_special_function()
24081 {
24082 const std::string sf_name = current_token().value;
24083
24084 // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24085 if (
24086 !details::is_digit(sf_name[2]) ||
24087 !details::is_digit(sf_name[3])
24088 )
24089 {
24090 set_error(
24091 make_error(parser_error::e_token,
24092 current_token(),
24093 "ERR134 - Invalid special function[1]: " + sf_name,
24094 exprtk_error_location));
24095
24096 return error_node();
24097 }
24098
24099 const int id = (sf_name[2] - '0') * 10 +
24100 (sf_name[3] - '0');
24101
24102 if (id >= details::e_sffinal)
24103 {
24104 set_error(
24105 make_error(parser_error::e_token,
24106 current_token(),
24107 "ERR135 - Invalid special function[2]: " + sf_name,
24108 exprtk_error_location));
24109
24110 return error_node();
24111 }
24112
24113 const int sf_3_to_4 = details::e_sf48;
24114 const details::operator_type opt_type = details::operator_type(id + 1000);
24115 const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
24116
24117 switch (NumberOfParameters)
24118 {
24119 case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
24120 case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
24121 default : return error_node();
24122 }
24123 }
24124
24125 inline expression_node_ptr parse_null_statement()
24126 {
24127 next_token();
24128 return node_allocator_.allocate<details::null_node<T> >();
24129 }
24130
24131 #ifndef exprtk_disable_break_continue
24132 inline expression_node_ptr parse_break_statement()
24133 {
24134 if (state_.parsing_break_stmt)
24135 {
24136 set_error(
24137 make_error(parser_error::e_syntax,
24138 current_token(),
24139 "ERR136 - Break call within a break call is not allowed",
24140 exprtk_error_location));
24141
24142 return error_node();
24143 }
24144
24145 scoped_bool_negator sbn(state_.parsing_break_stmt);
24146
24147 if (!brkcnt_list_.empty())
24148 {
24149 next_token();
24150
24151 brkcnt_list_.front() = true;
24152
24153 expression_node_ptr return_expr = error_node();
24154
24155 if (token_is(token_t::e_lsqrbracket))
24156 {
24157 if (0 == (return_expr = parse_expression()))
24158 {
24159 set_error(
24160 make_error(parser_error::e_syntax,
24161 current_token(),
24162 "ERR137 - Failed to parse return expression for 'break' statement",
24163 exprtk_error_location));
24164
24165 return error_node();
24166 }
24167 else if (!token_is(token_t::e_rsqrbracket))
24168 {
24169 set_error(
24170 make_error(parser_error::e_syntax,
24171 current_token(),
24172 "ERR138 - Expected ']' at the completion of break's return expression",
24173 exprtk_error_location));
24174
24175 free_node(node_allocator_,return_expr);
24176
24177 return error_node();
24178 }
24179 }
24180
24181 state_.activate_side_effect("parse_break_statement()");
24182
24183 return node_allocator_.allocate<details::break_node<T> >(return_expr);
24184 }
24185 else
24186 {
24187 set_error(
24188 make_error(parser_error::e_syntax,
24189 current_token(),
24190 "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
24191 exprtk_error_location));
24192 }
24193
24194 return error_node();
24195 }
24196
24197 inline expression_node_ptr parse_continue_statement()
24198 {
24199 if (!brkcnt_list_.empty())
24200 {
24201 next_token();
24202
24203 brkcnt_list_.front() = true;
24204 state_.activate_side_effect("parse_continue_statement()");
24205
24206 return node_allocator_.allocate<details::continue_node<T> >();
24207 }
24208 else
24209 {
24210 set_error(
24211 make_error(parser_error::e_syntax,
24212 current_token(),
24213 "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop",
24214 exprtk_error_location));
24215
24216 return error_node();
24217 }
24218 }
24219 #endif
24220
24221 inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
24222 {
24223 expression_node_ptr size_expr = error_node();
24224
24225 if (!token_is(token_t::e_lsqrbracket))
24226 {
24227 set_error(
24228 make_error(parser_error::e_syntax,
24229 current_token(),
24230 "ERR141 - Expected '[' as part of vector size definition",
24231 exprtk_error_location));
24232
24233 return error_node();
24234 }
24235 else if (0 == (size_expr = parse_expression()))
24236 {
24237 set_error(
24238 make_error(parser_error::e_syntax,
24239 current_token(),
24240 "ERR142 - Failed to determine size of vector '" + vec_name + "'",
24241 exprtk_error_location));
24242
24243 return error_node();
24244 }
24245 else if (!is_constant_node(size_expr))
24246 {
24247 free_node(node_allocator_,size_expr);
24248
24249 set_error(
24250 make_error(parser_error::e_syntax,
24251 current_token(),
24252 "ERR143 - Expected a literal number as size of vector '" + vec_name + "'",
24253 exprtk_error_location));
24254
24255 return error_node();
24256 }
24257
24258 const T vector_size = size_expr->value();
24259
24260 free_node(node_allocator_,size_expr);
24261
24262 const T max_vector_size = T(2000000000.0);
24263
24264 if (
24265 (vector_size <= T(0)) ||
24266 std::not_equal_to<T>()
24267 (T(0),vector_size - details::numeric::trunc(vector_size)) ||
24268 (vector_size > max_vector_size)
24269 )
24270 {
24271 set_error(
24272 make_error(parser_error::e_syntax,
24273 current_token(),
24274 "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
24275 details::to_str(details::numeric::to_int32(vector_size)),
24276 exprtk_error_location));
24277
24278 return error_node();
24279 }
24280
24281 std::vector<expression_node_ptr> vec_initilizer_list;
24282
24283 scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
24284
24285 bool single_value_initialiser = false;
24286 bool vec_to_vec_initialiser = false;
24287 bool null_initialisation = false;
24288
24289 if (!token_is(token_t::e_rsqrbracket))
24290 {
24291 set_error(
24292 make_error(parser_error::e_syntax,
24293 current_token(),
24294 "ERR145 - Expected ']' as part of vector size definition",
24295 exprtk_error_location));
24296
24297 return error_node();
24298 }
24299 else if (!token_is(token_t::e_eof))
24300 {
24301 if (!token_is(token_t::e_assign))
24302 {
24303 set_error(
24304 make_error(parser_error::e_syntax,
24305 current_token(),
24306 "ERR146 - Expected ':=' as part of vector definition",
24307 exprtk_error_location));
24308
24309 return error_node();
24310 }
24311 else if (token_is(token_t::e_lsqrbracket))
24312 {
24313 expression_node_ptr initialiser = parse_expression();
24314
24315 if (0 == initialiser)
24316 {
24317 set_error(
24318 make_error(parser_error::e_syntax,
24319 current_token(),
24320 "ERR147 - Failed to parse single vector initialiser",
24321 exprtk_error_location));
24322
24323 return error_node();
24324 }
24325
24326 vec_initilizer_list.push_back(initialiser);
24327
24328 if (!token_is(token_t::e_rsqrbracket))
24329 {
24330 set_error(
24331 make_error(parser_error::e_syntax,
24332 current_token(),
24333 "ERR148 - Expected ']' to close single value vector initialiser",
24334 exprtk_error_location));
24335
24336 return error_node();
24337 }
24338
24339 single_value_initialiser = true;
24340 }
24341 else if (!token_is(token_t::e_lcrlbracket))
24342 {
24343 expression_node_ptr initialiser = error_node();
24344
24345 // Is this a vector to vector assignment and initialisation?
24346 if (token_t::e_symbol == current_token().type)
24347 {
24348 // Is it a locally defined vector?
24349 scope_element& se = sem_.get_active_element(current_token().value);
24350
24351 if (scope_element::e_vector == se.type)
24352 {
24353 if (0 != (initialiser = parse_expression()))
24354 vec_initilizer_list.push_back(initialiser);
24355 else
24356 return error_node();
24357 }
24358 // Are we dealing with a user defined vector?
24359 else if (symtab_store_.is_vector(current_token().value))
24360 {
24361 lodge_symbol(current_token().value, e_st_vector);
24362
24363 if (0 != (initialiser = parse_expression()))
24364 vec_initilizer_list.push_back(initialiser);
24365 else
24366 return error_node();
24367 }
24368 // Are we dealing with a null initialisation vector definition?
24369 else if (token_is(token_t::e_symbol,"null"))
24370 null_initialisation = true;
24371 }
24372
24373 if (!null_initialisation)
24374 {
24375 if (0 == initialiser)
24376 {
24377 set_error(
24378 make_error(parser_error::e_syntax,
24379 current_token(),
24380 "ERR149 - Expected '{' as part of vector initialiser list",
24381 exprtk_error_location));
24382
24383 return error_node();
24384 }
24385 else
24386 vec_to_vec_initialiser = true;
24387 }
24388 }
24389 else if (!token_is(token_t::e_rcrlbracket))
24390 {
24391 for ( ; ; )
24392 {
24393 expression_node_ptr initialiser = parse_expression();
24394
24395 if (0 == initialiser)
24396 {
24397 set_error(
24398 make_error(parser_error::e_syntax,
24399 current_token(),
24400 "ERR150 - Expected '{' as part of vector initialiser list",
24401 exprtk_error_location));
24402
24403 return error_node();
24404 }
24405 else
24406 vec_initilizer_list.push_back(initialiser);
24407
24408 if (token_is(token_t::e_rcrlbracket))
24409 break;
24410
24411 const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
24412
24413 if (!token_is(token_t::e_comma) && is_next_close)
24414 {
24415 set_error(
24416 make_error(parser_error::e_syntax,
24417 current_token(),
24418 "ERR151 - Expected ',' between vector initialisers",
24419 exprtk_error_location));
24420
24421 return error_node();
24422 }
24423
24424 if (token_is(token_t::e_rcrlbracket))
24425 break;
24426 }
24427 }
24428
24429 if (
24430 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24431 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24432 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24433 )
24434 {
24435 if (!token_is(token_t::e_eof))
24436 {
24437 set_error(
24438 make_error(parser_error::e_syntax,
24439 current_token(),
24440 "ERR152 - Expected ';' at end of vector definition",
24441 exprtk_error_location));
24442
24443 return error_node();
24444 }
24445 }
24446
24447 if (vec_initilizer_list.size() > vector_size)
24448 {
24449 set_error(
24450 make_error(parser_error::e_syntax,
24451 current_token(),
24452 "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
24453 exprtk_error_location));
24454
24455 return error_node();
24456 }
24457 }
24458
24459 typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
24460
24461 const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
24462
24463 scope_element& se = sem_.get_element(vec_name);
24464
24465 if (se.name == vec_name)
24466 {
24467 if (se.active)
24468 {
24469 set_error(
24470 make_error(parser_error::e_syntax,
24471 current_token(),
24472 "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'",
24473 exprtk_error_location));
24474
24475 return error_node();
24476 }
24477 else if (
24478 (se.size == vec_size) &&
24479 (scope_element::e_vector == se.type)
24480 )
24481 {
24482 vec_holder = se.vec_node;
24483 se.active = true;
24484 se.depth = state_.scope_depth;
24485 se.ref_count++;
24486 }
24487 }
24488
24489 if (0 == vec_holder)
24490 {
24491 scope_element nse;
24492 nse.name = vec_name;
24493 nse.active = true;
24494 nse.ref_count = 1;
24495 nse.type = scope_element::e_vector;
24496 nse.depth = state_.scope_depth;
24497 nse.size = vec_size;
24498 nse.data = new T[vec_size];
24499 nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
24500
24501 if (!sem_.add_element(nse))
24502 {
24503 set_error(
24504 make_error(parser_error::e_syntax,
24505 current_token(),
24506 "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM",
24507 exprtk_error_location));
24508
24509 sem_.free_element(nse);
24510
24511 return error_node();
24512 }
24513
24514 vec_holder = nse.vec_node;
24515
24516 exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
24517 nse.name.c_str(),
24518 static_cast<int>(nse.size)));
24519 }
24520
24521 state_.activate_side_effect("parse_define_vector_statement()");
24522
24523 lodge_symbol(vec_name, e_st_local_vector);
24524
24525 expression_node_ptr result = error_node();
24526
24527 if (null_initialisation)
24528 result = expression_generator_(T(0.0));
24529 else if (vec_to_vec_initialiser)
24530 {
24531 expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
24532
24533 result = expression_generator_(
24534 details::e_assign,
24535 vec_node,
24536 vec_initilizer_list[0]);
24537 }
24538 else
24539 result = node_allocator_
24540 .allocate<details::vector_assignment_node<T> >(
24541 (*vec_holder)[0],
24542 vec_size,
24543 vec_initilizer_list,
24544 single_value_initialiser);
24545
24546 svd.delete_ptr = (0 == result);
24547
24548 return result;
24549 }
24550
24551 #ifndef exprtk_disable_string_capabilities
24552 inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
24553 {
24554 stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
24555
24556 scope_element& se = sem_.get_element(str_name);
24557
24558 if (se.name == str_name)
24559 {
24560 if (se.active)
24561 {
24562 set_error(
24563 make_error(parser_error::e_syntax,
24564 current_token(),
24565 "ERR156 - Illegal redefinition of local variable: '" + str_name + "'",
24566 exprtk_error_location));
24567
24568 free_node(node_allocator_,initialisation_expression);
24569
24570 return error_node();
24571 }
24572 else if (scope_element::e_string == se.type)
24573 {
24574 str_node = se.str_node;
24575 se.active = true;
24576 se.depth = state_.scope_depth;
24577 se.ref_count++;
24578 }
24579 }
24580
24581 if (0 == str_node)
24582 {
24583 scope_element nse;
24584 nse.name = str_name;
24585 nse.active = true;
24586 nse.ref_count = 1;
24587 nse.type = scope_element::e_string;
24588 nse.depth = state_.scope_depth;
24589 nse.data = new std::string;
24590 nse.str_node = new stringvar_node_t(*(std::string*)(nse.data));
24591
24592 if (!sem_.add_element(nse))
24593 {
24594 set_error(
24595 make_error(parser_error::e_syntax,
24596 current_token(),
24597 "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM",
24598 exprtk_error_location));
24599
24600 free_node(node_allocator_,initialisation_expression);
24601
24602 sem_.free_element(nse);
24603
24604 return error_node();
24605 }
24606
24607 str_node = nse.str_node;
24608
24609 exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
24610 }
24611
24612 lodge_symbol(str_name, e_st_local_string);
24613
24614 state_.activate_side_effect("parse_define_string_statement()");
24615
24616 expression_node_ptr branch[2] = {0};
24617
24618 branch[0] = str_node;
24619 branch[1] = initialisation_expression;
24620
24621 return expression_generator_(details::e_assign,branch);
24622 }
24623 #else
24624 inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
24625 {
24626 return error_node();
24627 }
24628 #endif
24629
24630 inline bool local_variable_is_shadowed(const std::string& symbol)
24631 {
24632 const scope_element& se = sem_.get_element(symbol);
24633 return (se.name == symbol) && se.active;
24634 }
24635
24636 inline expression_node_ptr parse_define_var_statement()
24637 {
24638 if (settings_.vardef_disabled())
24639 {
24640 set_error(
24641 make_error(parser_error::e_syntax,
24642 current_token(),
24643 "ERR158 - Illegal variable definition",
24644 exprtk_error_location));
24645
24646 return error_node();
24647 }
24648 else if (!details::imatch(current_token().value,"var"))
24649 {
24650 return error_node();
24651 }
24652 else
24653 next_token();
24654
24655 const std::string var_name = current_token().value;
24656
24657 expression_node_ptr initialisation_expression = error_node();
24658
24659 if (!token_is(token_t::e_symbol))
24660 {
24661 set_error(
24662 make_error(parser_error::e_syntax,
24663 current_token(),
24664 "ERR159 - Expected a symbol for variable definition",
24665 exprtk_error_location));
24666
24667 return error_node();
24668 }
24669 else if (details::is_reserved_symbol(var_name))
24670 {
24671 set_error(
24672 make_error(parser_error::e_syntax,
24673 current_token(),
24674 "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'",
24675 exprtk_error_location));
24676
24677 return error_node();
24678 }
24679 else if (symtab_store_.symbol_exists(var_name))
24680 {
24681 set_error(
24682 make_error(parser_error::e_syntax,
24683 current_token(),
24684 "ERR161 - Illegal redefinition of variable '" + var_name + "'",
24685 exprtk_error_location));
24686
24687 return error_node();
24688 }
24689 else if (local_variable_is_shadowed(var_name))
24690 {
24691 set_error(
24692 make_error(parser_error::e_syntax,
24693 current_token(),
24694 "ERR162 - Illegal redefinition of local variable: '" + var_name + "'",
24695 exprtk_error_location));
24696
24697 return error_node();
24698 }
24699 else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
24700 {
24701 return parse_define_vector_statement(var_name);
24702 }
24703 else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
24704 {
24705 return parse_uninitialised_var_statement(var_name);
24706 }
24707 else if (token_is(token_t::e_assign))
24708 {
24709 if (0 == (initialisation_expression = parse_expression()))
24710 {
24711 set_error(
24712 make_error(parser_error::e_syntax,
24713 current_token(),
24714 "ERR163 - Failed to parse initialisation expression",
24715 exprtk_error_location));
24716
24717 return error_node();
24718 }
24719 }
24720
24721 if (
24722 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24723 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24724 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24725 )
24726 {
24727 if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24728 {
24729 set_error(
24730 make_error(parser_error::e_syntax,
24731 current_token(),
24732 "ERR164 - Expected ';' after variable definition",
24733 exprtk_error_location));
24734
24735 free_node(node_allocator_,initialisation_expression);
24736
24737 return error_node();
24738 }
24739 }
24740
24741 if (
24742 (0 != initialisation_expression) &&
24743 details::is_generally_string_node(initialisation_expression)
24744 )
24745 {
24746 return parse_define_string_statement(var_name,initialisation_expression);
24747 }
24748
24749 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24750
24751 scope_element& se = sem_.get_element(var_name);
24752
24753 if (se.name == var_name)
24754 {
24755 if (se.active)
24756 {
24757 set_error(
24758 make_error(parser_error::e_syntax,
24759 current_token(),
24760 "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
24761 exprtk_error_location));
24762
24763 free_node(node_allocator_, initialisation_expression);
24764
24765 return error_node();
24766 }
24767 else if (scope_element::e_variable == se.type)
24768 {
24769 var_node = se.var_node;
24770 se.active = true;
24771 se.depth = state_.scope_depth;
24772 se.ref_count++;
24773 }
24774 }
24775
24776 if (0 == var_node)
24777 {
24778 scope_element nse;
24779 nse.name = var_name;
24780 nse.active = true;
24781 nse.ref_count = 1;
24782 nse.type = scope_element::e_variable;
24783 nse.depth = state_.scope_depth;
24784 nse.data = new T(T(0));
24785 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24786
24787 if (!sem_.add_element(nse))
24788 {
24789 set_error(
24790 make_error(parser_error::e_syntax,
24791 current_token(),
24792 "ERR166 - Failed to add new local variable '" + var_name + "' to SEM",
24793 exprtk_error_location));
24794
24795 free_node(node_allocator_, initialisation_expression);
24796
24797 sem_.free_element(nse);
24798
24799 return error_node();
24800 }
24801
24802 var_node = nse.var_node;
24803
24804 exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
24805 }
24806
24807 state_.activate_side_effect("parse_define_var_statement()");
24808
24809 lodge_symbol(var_name, e_st_local_variable);
24810
24811 expression_node_ptr branch[2] = {0};
24812
24813 branch[0] = var_node;
24814 branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
24815
24816 return expression_generator_(details::e_assign,branch);
24817 }
24818
24819 inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
24820 {
24821 if (
24822 !token_is(token_t::e_lcrlbracket) ||
24823 !token_is(token_t::e_rcrlbracket)
24824 )
24825 {
24826 set_error(
24827 make_error(parser_error::e_syntax,
24828 current_token(),
24829 "ERR167 - Expected a '{}' for uninitialised var definition",
24830 exprtk_error_location));
24831
24832 return error_node();
24833 }
24834 else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24835 {
24836 set_error(
24837 make_error(parser_error::e_syntax,
24838 current_token(),
24839 "ERR168 - Expected ';' after uninitialised variable definition",
24840 exprtk_error_location));
24841
24842 return error_node();
24843 }
24844
24845 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24846
24847 scope_element& se = sem_.get_element(var_name);
24848
24849 if (se.name == var_name)
24850 {
24851 if (se.active)
24852 {
24853 set_error(
24854 make_error(parser_error::e_syntax,
24855 current_token(),
24856 "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
24857 exprtk_error_location));
24858
24859 return error_node();
24860 }
24861 else if (scope_element::e_variable == se.type)
24862 {
24863 var_node = se.var_node;
24864 se.active = true;
24865 se.ref_count++;
24866 }
24867 }
24868
24869 if (0 == var_node)
24870 {
24871 scope_element nse;
24872 nse.name = var_name;
24873 nse.active = true;
24874 nse.ref_count = 1;
24875 nse.type = scope_element::e_variable;
24876 nse.depth = state_.scope_depth;
24877 nse.ip_index = sem_.next_ip_index();
24878 nse.data = new T(T(0));
24879 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24880
24881 if (!sem_.add_element(nse))
24882 {
24883 set_error(
24884 make_error(parser_error::e_syntax,
24885 current_token(),
24886 "ERR170 - Failed to add new local variable '" + var_name + "' to SEM",
24887 exprtk_error_location));
24888
24889 sem_.free_element(nse);
24890
24891 return error_node();
24892 }
24893
24894 exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
24895 nse.name.c_str()));
24896 }
24897
24898 lodge_symbol(var_name, e_st_local_variable);
24899
24900 state_.activate_side_effect("parse_uninitialised_var_statement()");
24901
24902 return expression_generator_(T(0));
24903 }
24904
24905 inline expression_node_ptr parse_swap_statement()
24906 {
24907 if (!details::imatch(current_token().value,"swap"))
24908 {
24909 return error_node();
24910 }
24911 else
24912 next_token();
24913
24914 if (!token_is(token_t::e_lbracket))
24915 {
24916 set_error(
24917 make_error(parser_error::e_syntax,
24918 current_token(),
24919 "ERR171 - Expected '(' at start of swap statement",
24920 exprtk_error_location));
24921
24922 return error_node();
24923 }
24924
24925 expression_node_ptr variable0 = error_node();
24926 expression_node_ptr variable1 = error_node();
24927
24928 bool variable0_generated = false;
24929 bool variable1_generated = false;
24930
24931 const std::string var0_name = current_token().value;
24932
24933 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
24934 {
24935 set_error(
24936 make_error(parser_error::e_syntax,
24937 current_token(),
24938 "ERR172 - Expected a symbol for variable or vector element definition",
24939 exprtk_error_location));
24940
24941 return error_node();
24942 }
24943 else if (peek_token_is(token_t::e_lsqrbracket))
24944 {
24945 if (0 == (variable0 = parse_vector()))
24946 {
24947 set_error(
24948 make_error(parser_error::e_syntax,
24949 current_token(),
24950 "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
24951 exprtk_error_location));
24952
24953 return error_node();
24954 }
24955
24956 variable0_generated = true;
24957 }
24958 else
24959 {
24960 if (symtab_store_.is_variable(var0_name))
24961 {
24962 variable0 = symtab_store_.get_variable(var0_name);
24963 }
24964
24965 scope_element& se = sem_.get_element(var0_name);
24966
24967 if (
24968 (se.active) &&
24969 (se.name == var0_name) &&
24970 (scope_element::e_variable == se.type)
24971 )
24972 {
24973 variable0 = se.var_node;
24974 }
24975
24976 lodge_symbol(var0_name, e_st_variable);
24977
24978 if (0 == variable0)
24979 {
24980 set_error(
24981 make_error(parser_error::e_syntax,
24982 current_token(),
24983 "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'",
24984 exprtk_error_location));
24985
24986 return error_node();
24987 }
24988 else
24989 next_token();
24990 }
24991
24992 if (!token_is(token_t::e_comma))
24993 {
24994 set_error(
24995 make_error(parser_error::e_syntax,
24996 current_token(),
24997 "ERR175 - Expected ',' between parameters to swap",
24998 exprtk_error_location));
24999
25000 if (variable0_generated)
25001 {
25002 free_node(node_allocator_,variable0);
25003 }
25004
25005 return error_node();
25006 }
25007
25008 const std::string var1_name = current_token().value;
25009
25010 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25011 {
25012 set_error(
25013 make_error(parser_error::e_syntax,
25014 current_token(),
25015 "ERR176 - Expected a symbol for variable or vector element definition",
25016 exprtk_error_location));
25017
25018 if (variable0_generated)
25019 {
25020 free_node(node_allocator_,variable0);
25021 }
25022
25023 return error_node();
25024 }
25025 else if (peek_token_is(token_t::e_lsqrbracket))
25026 {
25027 if (0 == (variable1 = parse_vector()))
25028 {
25029 set_error(
25030 make_error(parser_error::e_syntax,
25031 current_token(),
25032 "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
25033 exprtk_error_location));
25034
25035 if (variable0_generated)
25036 {
25037 free_node(node_allocator_,variable0);
25038 }
25039
25040 return error_node();
25041 }
25042
25043 variable1_generated = true;
25044 }
25045 else
25046 {
25047 if (symtab_store_.is_variable(var1_name))
25048 {
25049 variable1 = symtab_store_.get_variable(var1_name);
25050 }
25051
25052 scope_element& se = sem_.get_element(var1_name);
25053
25054 if (
25055 (se.active) &&
25056 (se.name == var1_name) &&
25057 (scope_element::e_variable == se.type)
25058 )
25059 {
25060 variable1 = se.var_node;
25061 }
25062
25063 lodge_symbol(var1_name, e_st_variable);
25064
25065 if (0 == variable1)
25066 {
25067 set_error(
25068 make_error(parser_error::e_syntax,
25069 current_token(),
25070 "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25071 exprtk_error_location));
25072
25073 if (variable0_generated)
25074 {
25075 free_node(node_allocator_,variable0);
25076 }
25077
25078 return error_node();
25079 }
25080 else
25081 next_token();
25082 }
25083
25084 if (!token_is(token_t::e_rbracket))
25085 {
25086 set_error(
25087 make_error(parser_error::e_syntax,
25088 current_token(),
25089 "ERR179 - Expected ')' at end of swap statement",
25090 exprtk_error_location));
25091
25092 if (variable0_generated)
25093 {
25094 free_node(node_allocator_,variable0);
25095 }
25096
25097 if (variable1_generated)
25098 {
25099 free_node(node_allocator_,variable1);
25100 }
25101
25102 return error_node();
25103 }
25104
25105 typedef details::variable_node<T>* variable_node_ptr;
25106
25107 variable_node_ptr v0 = variable_node_ptr(0);
25108 variable_node_ptr v1 = variable_node_ptr(0);
25109
25110 expression_node_ptr result = error_node();
25111
25112 if (
25113 (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
25114 (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
25115 )
25116 {
25117 result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
25118
25119 if (variable0_generated)
25120 {
25121 free_node(node_allocator_,variable0);
25122 }
25123
25124 if (variable1_generated)
25125 {
25126 free_node(node_allocator_,variable1);
25127 }
25128 }
25129 else
25130 result = node_allocator_.allocate<details::swap_generic_node<T> >
25131 (variable0, variable1);
25132
25133 state_.activate_side_effect("parse_swap_statement()");
25134
25135 return result;
25136 }
25137
25138 #ifndef exprtk_disable_return_statement
25139 inline expression_node_ptr parse_return_statement()
25140 {
25141 if (state_.parsing_return_stmt)
25142 {
25143 set_error(
25144 make_error(parser_error::e_syntax,
25145 current_token(),
25146 "ERR180 - Return call within a return call is not allowed",
25147 exprtk_error_location));
25148
25149 return error_node();
25150 }
25151
25152 scoped_bool_negator sbn(state_.parsing_return_stmt);
25153
25154 std::vector<expression_node_ptr> arg_list;
25155
25156 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
25157
25158 if (!details::imatch(current_token().value,"return"))
25159 {
25160 return error_node();
25161 }
25162 else
25163 next_token();
25164
25165 if (!token_is(token_t::e_lsqrbracket))
25166 {
25167 set_error(
25168 make_error(parser_error::e_syntax,
25169 current_token(),
25170 "ERR181 - Expected '[' at start of return statement",
25171 exprtk_error_location));
25172
25173 return error_node();
25174 }
25175 else if (!token_is(token_t::e_rsqrbracket))
25176 {
25177 for ( ; ; )
25178 {
25179 expression_node_ptr arg = parse_expression();
25180
25181 if (0 == arg)
25182 return error_node();
25183
25184 arg_list.push_back(arg);
25185
25186 if (token_is(token_t::e_rsqrbracket))
25187 break;
25188 else if (!token_is(token_t::e_comma))
25189 {
25190 set_error(
25191 make_error(parser_error::e_syntax,
25192 current_token(),
25193 "ERR182 - Expected ',' between values during call to return",
25194 exprtk_error_location));
25195
25196 return error_node();
25197 }
25198 }
25199 }
25200 else if (settings_.zero_return_disabled())
25201 {
25202 set_error(
25203 make_error(parser_error::e_syntax,
25204 current_token(),
25205 "ERR183 - Zero parameter return statement not allowed",
25206 exprtk_error_location));
25207
25208 return error_node();
25209 }
25210
25211 const lexer::token prev_token = current_token();
25212
25213 if (token_is(token_t::e_rsqrbracket))
25214 {
25215 if (!arg_list.empty())
25216 {
25217 set_error(
25218 make_error(parser_error::e_syntax,
25219 prev_token,
25220 "ERR184 - Invalid ']' found during return call",
25221 exprtk_error_location));
25222
25223 return error_node();
25224 }
25225 }
25226
25227 std::string ret_param_type_list;
25228
25229 for (std::size_t i = 0; i < arg_list.size(); ++i)
25230 {
25231 if (0 == arg_list[i])
25232 return error_node();
25233 else if (is_ivector_node(arg_list[i]))
25234 ret_param_type_list += 'V';
25235 else if (is_generally_string_node(arg_list[i]))
25236 ret_param_type_list += 'S';
25237 else
25238 ret_param_type_list += 'T';
25239 }
25240
25241 dec_.retparam_list_.push_back(ret_param_type_list);
25242
25243 expression_node_ptr result = expression_generator_.return_call(arg_list);
25244
25245 sdd.delete_ptr = (0 == result);
25246
25247 state_.return_stmt_present = true;
25248
25249 state_.activate_side_effect("parse_return_statement()");
25250
25251 return result;
25252 }
25253 #else
25254 inline expression_node_ptr parse_return_statement()
25255 {
25256 return error_node();
25257 }
25258 #endif
25259
25260 inline bool post_variable_process(const std::string& symbol)
25261 {
25262 if (
25263 peek_token_is(token_t::e_lbracket ) ||
25264 peek_token_is(token_t::e_lcrlbracket) ||
25265 peek_token_is(token_t::e_lsqrbracket)
25266 )
25267 {
25268 if (!settings_.commutative_check_enabled())
25269 {
25270 set_error(
25271 make_error(parser_error::e_syntax,
25272 current_token(),
25273 "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket",
25274 exprtk_error_location));
25275
25276 return false;
25277 }
25278
25279 lexer().insert_front(token_t::e_mul);
25280 }
25281
25282 return true;
25283 }
25284
25285 inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
25286 {
25287 bool implied_mul = false;
25288
25289 if (is_generally_string_node(branch))
25290 return true;
25291
25292 const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
25293
25294 switch (token)
25295 {
25296 case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25297 token_is(token_t::e_lcrlbracket,hold) ||
25298 token_is(token_t::e_lsqrbracket,hold) ;
25299 break;
25300
25301 case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25302 token_is(token_t::e_lcrlbracket,hold) ||
25303 token_is(token_t::e_lsqrbracket,hold) ;
25304 break;
25305
25306 case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25307 token_is(token_t::e_lcrlbracket,hold) ||
25308 token_is(token_t::e_lsqrbracket,hold) ;
25309 break;
25310
25311 default : return true;
25312 }
25313
25314 if (implied_mul)
25315 {
25316 if (!settings_.commutative_check_enabled())
25317 {
25318 set_error(
25319 make_error(parser_error::e_syntax,
25320 current_token(),
25321 "ERR186 - Invalid sequence of brackets",
25322 exprtk_error_location));
25323
25324 return false;
25325 }
25326 else if (token_t::e_eof != current_token().type)
25327 {
25328 lexer().insert_front(current_token().type);
25329 lexer().insert_front(token_t::e_mul);
25330 next_token();
25331 }
25332 }
25333
25334 return true;
25335 }
25336
25337 inline expression_node_ptr parse_symtab_symbol()
25338 {
25339 const std::string symbol = current_token().value;
25340
25341 // Are we dealing with a variable or a special constant?
25342 expression_node_ptr variable = symtab_store_.get_variable(symbol);
25343
25344 if (variable)
25345 {
25346 if (symtab_store_.is_constant_node(symbol))
25347 {
25348 variable = expression_generator_(variable->value());
25349 }
25350
25351 if (!post_variable_process(symbol))
25352 return error_node();
25353
25354 lodge_symbol(symbol, e_st_variable);
25355 next_token();
25356
25357 return variable;
25358 }
25359
25360 // Are we dealing with a locally defined variable, vector or string?
25361 if (!sem_.empty())
25362 {
25363 scope_element& se = sem_.get_active_element(symbol);
25364
25365 if (se.active && details::imatch(se.name, symbol))
25366 {
25367 if (scope_element::e_variable == se.type)
25368 {
25369 se.active = true;
25370 lodge_symbol(symbol, e_st_local_variable);
25371
25372 if (!post_variable_process(symbol))
25373 return error_node();
25374
25375 next_token();
25376
25377 return se.var_node;
25378 }
25379 else if (scope_element::e_vector == se.type)
25380 {
25381 return parse_vector();
25382 }
25383 #ifndef exprtk_disable_string_capabilities
25384 else if (scope_element::e_string == se.type)
25385 {
25386 return parse_string();
25387 }
25388 #endif
25389 }
25390 }
25391
25392 #ifndef exprtk_disable_string_capabilities
25393 // Are we dealing with a string variable?
25394 if (symtab_store_.is_stringvar(symbol))
25395 {
25396 return parse_string();
25397 }
25398 #endif
25399
25400 {
25401 // Are we dealing with a function?
25402 ifunction<T>* function = symtab_store_.get_function(symbol);
25403
25404 if (function)
25405 {
25406 lodge_symbol(symbol, e_st_function);
25407
25408 expression_node_ptr func_node =
25409 parse_function_invocation(function,symbol);
25410
25411 if (func_node)
25412 return func_node;
25413 else
25414 {
25415 set_error(
25416 make_error(parser_error::e_syntax,
25417 current_token(),
25418 "ERR187 - Failed to generate node for function: '" + symbol + "'",
25419 exprtk_error_location));
25420
25421 return error_node();
25422 }
25423 }
25424 }
25425
25426 {
25427 // Are we dealing with a vararg function?
25428 ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
25429
25430 if (vararg_function)
25431 {
25432 lodge_symbol(symbol, e_st_function);
25433
25434 expression_node_ptr vararg_func_node =
25435 parse_vararg_function_call(vararg_function, symbol);
25436
25437 if (vararg_func_node)
25438 return vararg_func_node;
25439 else
25440 {
25441 set_error(
25442 make_error(parser_error::e_syntax,
25443 current_token(),
25444 "ERR188 - Failed to generate node for vararg function: '" + symbol + "'",
25445 exprtk_error_location));
25446
25447 return error_node();
25448 }
25449 }
25450 }
25451
25452 {
25453 // Are we dealing with a vararg generic function?
25454 igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
25455
25456 if (generic_function)
25457 {
25458 lodge_symbol(symbol, e_st_function);
25459
25460 expression_node_ptr genericfunc_node =
25461 parse_generic_function_call(generic_function, symbol);
25462
25463 if (genericfunc_node)
25464 return genericfunc_node;
25465 else
25466 {
25467 set_error(
25468 make_error(parser_error::e_syntax,
25469 current_token(),
25470 "ERR189 - Failed to generate node for generic function: '" + symbol + "'",
25471 exprtk_error_location));
25472
25473 return error_node();
25474 }
25475 }
25476 }
25477
25478 #ifndef exprtk_disable_string_capabilities
25479 {
25480 // Are we dealing with a vararg string returning function?
25481 igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
25482
25483 if (string_function)
25484 {
25485 lodge_symbol(symbol, e_st_function);
25486
25487 expression_node_ptr stringfunc_node =
25488 parse_string_function_call(string_function, symbol);
25489
25490 if (stringfunc_node)
25491 return stringfunc_node;
25492 else
25493 {
25494 set_error(
25495 make_error(parser_error::e_syntax,
25496 current_token(),
25497 "ERR190 - Failed to generate node for string function: '" + symbol + "'",
25498 exprtk_error_location));
25499
25500 return error_node();
25501 }
25502 }
25503 }
25504
25505 {
25506 // Are we dealing with a vararg overloaded scalar/string returning function?
25507 igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
25508
25509 if (overload_function)
25510 {
25511 lodge_symbol(symbol, e_st_function);
25512
25513 expression_node_ptr overloadfunc_node =
25514 parse_overload_function_call(overload_function, symbol);
25515
25516 if (overloadfunc_node)
25517 return overloadfunc_node;
25518 else
25519 {
25520 set_error(
25521 make_error(parser_error::e_syntax,
25522 current_token(),
25523 "ERR191 - Failed to generate node for overload function: '" + symbol + "'",
25524 exprtk_error_location));
25525
25526 return error_node();
25527 }
25528 }
25529 }
25530 #endif
25531
25532 // Are we dealing with a vector?
25533 if (symtab_store_.is_vector(symbol))
25534 {
25535 lodge_symbol(symbol, e_st_vector);
25536 return parse_vector();
25537 }
25538
25539 if (details::is_reserved_symbol(symbol))
25540 {
25541 if (
25542 settings_.function_enabled(symbol) ||
25543 !details::is_base_function(symbol)
25544 )
25545 {
25546 set_error(
25547 make_error(parser_error::e_syntax,
25548 current_token(),
25549 "ERR192 - Invalid use of reserved symbol '" + symbol + "'",
25550 exprtk_error_location));
25551
25552 return error_node();
25553 }
25554 }
25555
25556 // Should we handle unknown symbols?
25557 if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
25558 {
25559 if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
25560 {
25561 symbol_table_t& symtab = symtab_store_.get_symbol_table();
25562
25563 std::string error_message;
25564
25565 if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
25566 {
25567 T default_value = T(0);
25568
25569 typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
25570
25571 if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
25572 {
25573 bool create_result = false;
25574
25575 switch (usr_symbol_type)
25576 {
25577 case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
25578 break;
25579
25580 case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
25581 break;
25582
25583 default : create_result = false;
25584 }
25585
25586 if (create_result)
25587 {
25588 expression_node_ptr var = symtab_store_.get_variable(symbol);
25589
25590 if (var)
25591 {
25592 if (symtab_store_.is_constant_node(symbol))
25593 {
25594 var = expression_generator_(var->value());
25595 }
25596
25597 lodge_symbol(symbol, e_st_variable);
25598
25599 if (!post_variable_process(symbol))
25600 return error_node();
25601
25602 next_token();
25603
25604 return var;
25605 }
25606 }
25607 }
25608
25609 set_error(
25610 make_error(parser_error::e_symtab,
25611 current_token(),
25612 "ERR193 - Failed to create variable: '" + symbol + "'" +
25613 (error_message.empty() ? "" : " - " + error_message),
25614 exprtk_error_location));
25615
25616 }
25617 else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
25618 {
25619 if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
25620 {
25621 expression_node_ptr result = parse_symtab_symbol();
25622
25623 if (result)
25624 {
25625 return result;
25626 }
25627 }
25628
25629 set_error(
25630 make_error(parser_error::e_symtab,
25631 current_token(),
25632 "ERR194 - Failed to resolve symbol: '" + symbol + "'" +
25633 (error_message.empty() ? "" : " - " + error_message),
25634 exprtk_error_location));
25635 }
25636
25637 return error_node();
25638 }
25639 }
25640
25641 set_error(
25642 make_error(parser_error::e_syntax,
25643 current_token(),
25644 "ERR195 - Undefined symbol: '" + symbol + "'",
25645 exprtk_error_location));
25646
25647 return error_node();
25648 }
25649
25650 inline expression_node_ptr parse_symbol()
25651 {
25652 static const std::string symbol_if = "if" ;
25653 static const std::string symbol_while = "while" ;
25654 static const std::string symbol_repeat = "repeat" ;
25655 static const std::string symbol_for = "for" ;
25656 static const std::string symbol_switch = "switch" ;
25657 static const std::string symbol_null = "null" ;
25658 static const std::string symbol_break = "break" ;
25659 static const std::string symbol_continue = "continue";
25660 static const std::string symbol_var = "var" ;
25661 static const std::string symbol_swap = "swap" ;
25662 static const std::string symbol_return = "return" ;
25663 static const std::string symbol_not = "not" ;
25664
25665 if (valid_vararg_operation(current_token().value))
25666 {
25667 return parse_vararg_function();
25668 }
25669 else if (details::imatch(current_token().value, symbol_not))
25670 {
25671 return parse_not_statement();
25672 }
25673 else if (valid_base_operation(current_token().value))
25674 {
25675 return parse_base_operation();
25676 }
25677 else if (
25678 details::imatch(current_token().value, symbol_if) &&
25679 settings_.control_struct_enabled(current_token().value)
25680 )
25681 {
25682 return parse_conditional_statement();
25683 }
25684 else if (
25685 details::imatch(current_token().value, symbol_while) &&
25686 settings_.control_struct_enabled(current_token().value)
25687 )
25688 {
25689 return parse_while_loop();
25690 }
25691 else if (
25692 details::imatch(current_token().value, symbol_repeat) &&
25693 settings_.control_struct_enabled(current_token().value)
25694 )
25695 {
25696 return parse_repeat_until_loop();
25697 }
25698 else if (
25699 details::imatch(current_token().value, symbol_for) &&
25700 settings_.control_struct_enabled(current_token().value)
25701 )
25702 {
25703 return parse_for_loop();
25704 }
25705 else if (
25706 details::imatch(current_token().value, symbol_switch) &&
25707 settings_.control_struct_enabled(current_token().value)
25708 )
25709 {
25710 return parse_switch_statement();
25711 }
25712 else if (details::is_valid_sf_symbol(current_token().value))
25713 {
25714 return parse_special_function();
25715 }
25716 else if (details::imatch(current_token().value, symbol_null))
25717 {
25718 return parse_null_statement();
25719 }
25720 #ifndef exprtk_disable_break_continue
25721 else if (details::imatch(current_token().value, symbol_break))
25722 {
25723 return parse_break_statement();
25724 }
25725 else if (details::imatch(current_token().value, symbol_continue))
25726 {
25727 return parse_continue_statement();
25728 }
25729 #endif
25730 else if (details::imatch(current_token().value, symbol_var))
25731 {
25732 return parse_define_var_statement();
25733 }
25734 else if (details::imatch(current_token().value, symbol_swap))
25735 {
25736 return parse_swap_statement();
25737 }
25738 #ifndef exprtk_disable_return_statement
25739 else if (
25740 details::imatch(current_token().value, symbol_return) &&
25741 settings_.control_struct_enabled(current_token().value)
25742 )
25743 {
25744 return parse_return_statement();
25745 }
25746 #endif
25747 else if (symtab_store_.valid() || !sem_.empty())
25748 {
25749 return parse_symtab_symbol();
25750 }
25751 else
25752 {
25753 set_error(
25754 make_error(parser_error::e_symtab,
25755 current_token(),
25756 "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
25757 exprtk_error_location));
25758
25759 return error_node();
25760 }
25761 }
25762
25763 inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
25764 {
25765 expression_node_ptr branch = error_node();
25766
25767 if (token_t::e_number == current_token().type)
25768 {
25769 T numeric_value = T(0);
25770
25771 if (details::string_to_real(current_token().value, numeric_value))
25772 {
25773 expression_node_ptr literal_exp = expression_generator_(numeric_value);
25774
25775 if (0 == literal_exp)
25776 {
25777 set_error(
25778 make_error(parser_error::e_numeric,
25779 current_token(),
25780 "ERR197 - Failed generate node for scalar: '" + current_token().value + "'",
25781 exprtk_error_location));
25782
25783 return error_node();
25784 }
25785
25786 next_token();
25787 branch = literal_exp;
25788 }
25789 else
25790 {
25791 set_error(
25792 make_error(parser_error::e_numeric,
25793 current_token(),
25794 "ERR198 - Failed to convert '" + current_token().value + "' to a number",
25795 exprtk_error_location));
25796
25797 return error_node();
25798 }
25799 }
25800 else if (token_t::e_symbol == current_token().type)
25801 {
25802 branch = parse_symbol();
25803 }
25804 #ifndef exprtk_disable_string_capabilities
25805 else if (token_t::e_string == current_token().type)
25806 {
25807 branch = parse_const_string();
25808 }
25809 #endif
25810 else if (token_t::e_lbracket == current_token().type)
25811 {
25812 next_token();
25813
25814 if (0 == (branch = parse_expression()))
25815 return error_node();
25816 else if (!token_is(token_t::e_rbracket))
25817 {
25818 set_error(
25819 make_error(parser_error::e_syntax,
25820 current_token(),
25821 "ERR199 - Expected ')' instead of: '" + current_token().value + "'",
25822 exprtk_error_location));
25823
25824 free_node(node_allocator_,branch);
25825
25826 return error_node();
25827 }
25828 else if (!post_bracket_process(token_t::e_lbracket,branch))
25829 {
25830 free_node(node_allocator_,branch);
25831
25832 return error_node();
25833 }
25834 }
25835 else if (token_t::e_lsqrbracket == current_token().type)
25836 {
25837 next_token();
25838
25839 if (0 == (branch = parse_expression()))
25840 return error_node();
25841 else if (!token_is(token_t::e_rsqrbracket))
25842 {
25843 set_error(
25844 make_error(parser_error::e_syntax,
25845 current_token(),
25846 "ERR200 - Expected ']' instead of: '" + current_token().value + "'",
25847 exprtk_error_location));
25848
25849 free_node(node_allocator_,branch);
25850
25851 return error_node();
25852 }
25853 else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
25854 {
25855 free_node(node_allocator_,branch);
25856
25857 return error_node();
25858 }
25859 }
25860 else if (token_t::e_lcrlbracket == current_token().type)
25861 {
25862 next_token();
25863
25864 if (0 == (branch = parse_expression()))
25865 return error_node();
25866 else if (!token_is(token_t::e_rcrlbracket))
25867 {
25868 set_error(
25869 make_error(parser_error::e_syntax,
25870 current_token(),
25871 "ERR201 - Expected '}' instead of: '" + current_token().value + "'",
25872 exprtk_error_location));
25873
25874 free_node(node_allocator_,branch);
25875
25876 return error_node();
25877 }
25878 else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
25879 {
25880 free_node(node_allocator_,branch);
25881
25882 return error_node();
25883 }
25884 }
25885 else if (token_t::e_sub == current_token().type)
25886 {
25887 next_token();
25888 branch = parse_expression(e_level11);
25889
25890 if (
25891 branch &&
25892 !(
25893 details::is_neg_unary_node (branch) &&
25894 simplify_unary_negation_branch(branch)
25895 )
25896 )
25897 {
25898 branch = expression_generator_(details::e_neg,branch);
25899 }
25900 }
25901 else if (token_t::e_add == current_token().type)
25902 {
25903 next_token();
25904 branch = parse_expression(e_level13);
25905 }
25906 else if (token_t::e_eof == current_token().type)
25907 {
25908 set_error(
25909 make_error(parser_error::e_syntax,
25910 current_token(),
25911 "ERR202 - Premature end of expression[1]",
25912 exprtk_error_location));
25913
25914 return error_node();
25915 }
25916 else
25917 {
25918 set_error(
25919 make_error(parser_error::e_syntax,
25920 current_token(),
25921 "ERR203 - Premature end of expression[2]",
25922 exprtk_error_location));
25923
25924 return error_node();
25925 }
25926
25927 if (
25928 branch &&
25929 (e_level00 == precedence) &&
25930 token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
25931 )
25932 {
25933 branch = parse_ternary_conditional_statement(branch);
25934 }
25935
25936 parse_pending_string_rangesize(branch);
25937
25938 return branch;
25939 }
25940
25941 template <typename Type>
25942 class expression_generator
25943 {
25944 public:
25945
25946 typedef details::expression_node<Type>* expression_node_ptr;
25947 typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
25948 typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
25949 typedef typename exprtk::parser<Type> parser_t;
25950 typedef const Type& vtype;
25951 typedef const Type ctype;
25952
25953 inline void init_synthesize_map()
25954 {
25955 #ifndef exprtk_disable_enhanced_features
25956 synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
25957 synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
25958 synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
25959
25960 #define register_synthezier(S) \
25961 synthesize_map_[S ::node_type::id()] = S ::process; \
25962
25963 register_synthezier(synthesize_vovov_expression0)
25964 register_synthezier(synthesize_vovov_expression1)
25965 register_synthezier(synthesize_vovoc_expression0)
25966 register_synthezier(synthesize_vovoc_expression1)
25967 register_synthezier(synthesize_vocov_expression0)
25968 register_synthezier(synthesize_vocov_expression1)
25969 register_synthezier(synthesize_covov_expression0)
25970 register_synthezier(synthesize_covov_expression1)
25971 register_synthezier(synthesize_covoc_expression0)
25972 register_synthezier(synthesize_covoc_expression1)
25973 register_synthezier(synthesize_cocov_expression1)
25974 register_synthezier(synthesize_vococ_expression0)
25975
25976 register_synthezier(synthesize_vovovov_expression0)
25977 register_synthezier(synthesize_vovovoc_expression0)
25978 register_synthezier(synthesize_vovocov_expression0)
25979 register_synthezier(synthesize_vocovov_expression0)
25980 register_synthezier(synthesize_covovov_expression0)
25981 register_synthezier(synthesize_covocov_expression0)
25982 register_synthezier(synthesize_vocovoc_expression0)
25983 register_synthezier(synthesize_covovoc_expression0)
25984 register_synthezier(synthesize_vococov_expression0)
25985
25986 register_synthezier(synthesize_vovovov_expression1)
25987 register_synthezier(synthesize_vovovoc_expression1)
25988 register_synthezier(synthesize_vovocov_expression1)
25989 register_synthezier(synthesize_vocovov_expression1)
25990 register_synthezier(synthesize_covovov_expression1)
25991 register_synthezier(synthesize_covocov_expression1)
25992 register_synthezier(synthesize_vocovoc_expression1)
25993 register_synthezier(synthesize_covovoc_expression1)
25994 register_synthezier(synthesize_vococov_expression1)
25995
25996 register_synthezier(synthesize_vovovov_expression2)
25997 register_synthezier(synthesize_vovovoc_expression2)
25998 register_synthezier(synthesize_vovocov_expression2)
25999 register_synthezier(synthesize_vocovov_expression2)
26000 register_synthezier(synthesize_covovov_expression2)
26001 register_synthezier(synthesize_covocov_expression2)
26002 register_synthezier(synthesize_vocovoc_expression2)
26003 register_synthezier(synthesize_covovoc_expression2)
26004
26005 register_synthezier(synthesize_vovovov_expression3)
26006 register_synthezier(synthesize_vovovoc_expression3)
26007 register_synthezier(synthesize_vovocov_expression3)
26008 register_synthezier(synthesize_vocovov_expression3)
26009 register_synthezier(synthesize_covovov_expression3)
26010 register_synthezier(synthesize_covocov_expression3)
26011 register_synthezier(synthesize_vocovoc_expression3)
26012 register_synthezier(synthesize_covovoc_expression3)
26013 register_synthezier(synthesize_vococov_expression3)
26014
26015 register_synthezier(synthesize_vovovov_expression4)
26016 register_synthezier(synthesize_vovovoc_expression4)
26017 register_synthezier(synthesize_vovocov_expression4)
26018 register_synthezier(synthesize_vocovov_expression4)
26019 register_synthezier(synthesize_covovov_expression4)
26020 register_synthezier(synthesize_covocov_expression4)
26021 register_synthezier(synthesize_vocovoc_expression4)
26022 register_synthezier(synthesize_covovoc_expression4)
26023 #endif
26024 }
26025
26026 inline void set_parser(parser_t& p)
26027 {
26028 parser_ = &p;
26029 }
26030
26031 inline void set_uom(unary_op_map_t& unary_op_map)
26032 {
26033 unary_op_map_ = &unary_op_map;
26034 }
26035
26036 inline void set_bom(binary_op_map_t& binary_op_map)
26037 {
26038 binary_op_map_ = &binary_op_map;
26039 }
26040
26041 inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
26042 {
26043 inv_binary_op_map_ = &inv_binary_op_map;
26044 }
26045
26046 inline void set_sf3m(sf3_map_t& sf3_map)
26047 {
26048 sf3_map_ = &sf3_map;
26049 }
26050
26051 inline void set_sf4m(sf4_map_t& sf4_map)
26052 {
26053 sf4_map_ = &sf4_map;
26054 }
26055
26056 inline void set_allocator(details::node_allocator& na)
26057 {
26058 node_allocator_ = &na;
26059 }
26060
26061 inline void set_strength_reduction_state(const bool enabled)
26062 {
26063 strength_reduction_enabled_ = enabled;
26064 }
26065
26066 inline bool strength_reduction_enabled() const
26067 {
26068 return strength_reduction_enabled_;
26069 }
26070
26071 inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
26072 {
26073 typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
26074
26075 if ((*binary_op_map_).end() == bop_itr)
26076 return false;
26077
26078 bop = bop_itr->second;
26079
26080 return true;
26081 }
26082
26083 inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
26084 {
26085 typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
26086
26087 if ((*unary_op_map_).end() == uop_itr)
26088 return false;
26089
26090 uop = uop_itr->second;
26091
26092 return true;
26093 }
26094
26095 inline details::operator_type get_operator(const binary_functor_t& bop) const
26096 {
26097 return (*inv_binary_op_map_).find(bop)->second;
26098 }
26099
26100 inline expression_node_ptr operator() (const Type& v) const
26101 {
26102 return node_allocator_->allocate<literal_node_t>(v);
26103 }
26104
26105 #ifndef exprtk_disable_string_capabilities
26106 inline expression_node_ptr operator() (const std::string& s) const
26107 {
26108 return node_allocator_->allocate<string_literal_node_t>(s);
26109 }
26110
26111 inline expression_node_ptr operator() (std::string& s, range_t& rp) const
26112 {
26113 return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
26114 }
26115
26116 inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
26117 {
26118 return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
26119 }
26120
26121 inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
26122 {
26123 if (is_generally_string_node(branch))
26124 return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
26125 else
26126 return error_node();
26127 }
26128 #endif
26129
26130 inline bool unary_optimisable(const details::operator_type& operation) const
26131 {
26132 return (details::e_abs == operation) || (details::e_acos == operation) ||
26133 (details::e_acosh == operation) || (details::e_asin == operation) ||
26134 (details::e_asinh == operation) || (details::e_atan == operation) ||
26135 (details::e_atanh == operation) || (details::e_ceil == operation) ||
26136 (details::e_cos == operation) || (details::e_cosh == operation) ||
26137 (details::e_exp == operation) || (details::e_expm1 == operation) ||
26138 (details::e_floor == operation) || (details::e_log == operation) ||
26139 (details::e_log10 == operation) || (details::e_log2 == operation) ||
26140 (details::e_log1p == operation) || (details::e_neg == operation) ||
26141 (details::e_pos == operation) || (details::e_round == operation) ||
26142 (details::e_sin == operation) || (details::e_sinc == operation) ||
26143 (details::e_sinh == operation) || (details::e_sqrt == operation) ||
26144 (details::e_tan == operation) || (details::e_tanh == operation) ||
26145 (details::e_cot == operation) || (details::e_sec == operation) ||
26146 (details::e_csc == operation) || (details::e_r2d == operation) ||
26147 (details::e_d2r == operation) || (details::e_d2g == operation) ||
26148 (details::e_g2d == operation) || (details::e_notl == operation) ||
26149 (details::e_sgn == operation) || (details::e_erf == operation) ||
26150 (details::e_erfc == operation) || (details::e_ncdf == operation) ||
26151 (details::e_frac == operation) || (details::e_trunc == operation) ;
26152 }
26153
26154 inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
26155 {
26156 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26157
26158 if (sf3_map_->end() == itr)
26159 return false;
26160 else
26161 tfunc = itr->second.first;
26162
26163 return true;
26164 }
26165
26166 inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
26167 {
26168 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26169
26170 if (sf4_map_->end() == itr)
26171 return false;
26172 else
26173 qfunc = itr->second.first;
26174
26175 return true;
26176 }
26177
26178 inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
26179 {
26180 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26181
26182 if (sf3_map_->end() == itr)
26183 return false;
26184 else
26185 operation = itr->second.second;
26186
26187 return true;
26188 }
26189
26190 inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
26191 {
26192 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26193
26194 if (sf4_map_->end() == itr)
26195 return false;
26196 else
26197 operation = itr->second.second;
26198
26199 return true;
26200 }
26201
26202 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
26203 {
26204 if (0 == branch[0])
26205 {
26206 return error_node();
26207 }
26208 else if (details::is_null_node(branch[0]))
26209 {
26210 return branch[0];
26211 }
26212 else if (details::is_break_node(branch[0]))
26213 {
26214 return error_node();
26215 }
26216 else if (details::is_continue_node(branch[0]))
26217 {
26218 return error_node();
26219 }
26220 else if (details::is_constant_node(branch[0]))
26221 {
26222 return synthesize_expression<unary_node_t,1>(operation,branch);
26223 }
26224 else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
26225 {
26226 return synthesize_uv_expression(operation,branch);
26227 }
26228 else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
26229 {
26230 return synthesize_uvec_expression(operation,branch);
26231 }
26232 else
26233 return synthesize_unary_expression(operation,branch);
26234 }
26235
26236 inline bool is_assignment_operation(const details::operator_type& operation) const
26237 {
26238 return (
26239 (details::e_addass == operation) ||
26240 (details::e_subass == operation) ||
26241 (details::e_mulass == operation) ||
26242 (details::e_divass == operation) ||
26243 (details::e_modass == operation)
26244 ) &&
26245 parser_->settings_.assignment_enabled(operation);
26246 }
26247
26248 #ifndef exprtk_disable_string_capabilities
26249 inline bool valid_string_operation(const details::operator_type& operation) const
26250 {
26251 return (details::e_add == operation) ||
26252 (details::e_lt == operation) ||
26253 (details::e_lte == operation) ||
26254 (details::e_gt == operation) ||
26255 (details::e_gte == operation) ||
26256 (details::e_eq == operation) ||
26257 (details::e_ne == operation) ||
26258 (details::e_in == operation) ||
26259 (details::e_like == operation) ||
26260 (details::e_ilike == operation) ||
26261 (details::e_assign == operation) ||
26262 (details::e_addass == operation) ||
26263 (details::e_swap == operation) ;
26264 }
26265 #else
26266 inline bool valid_string_operation(const details::operator_type&) const
26267 {
26268 return false;
26269 }
26270 #endif
26271
26272 inline std::string to_str(const details::operator_type& operation) const
26273 {
26274 switch (operation)
26275 {
26276 case details::e_add : return "+" ;
26277 case details::e_sub : return "-" ;
26278 case details::e_mul : return "*" ;
26279 case details::e_div : return "/" ;
26280 case details::e_mod : return "%" ;
26281 case details::e_pow : return "^" ;
26282 case details::e_lt : return "<" ;
26283 case details::e_lte : return "<=" ;
26284 case details::e_gt : return ">" ;
26285 case details::e_gte : return ">=" ;
26286 case details::e_eq : return "==" ;
26287 case details::e_ne : return "!=" ;
26288 case details::e_and : return "and" ;
26289 case details::e_nand : return "nand" ;
26290 case details::e_or : return "or" ;
26291 case details::e_nor : return "nor" ;
26292 case details::e_xor : return "xor" ;
26293 case details::e_xnor : return "xnor" ;
26294 default : return "UNKNOWN";
26295 }
26296 }
26297
26298 inline bool operation_optimisable(const details::operator_type& operation) const
26299 {
26300 return (details::e_add == operation) ||
26301 (details::e_sub == operation) ||
26302 (details::e_mul == operation) ||
26303 (details::e_div == operation) ||
26304 (details::e_mod == operation) ||
26305 (details::e_pow == operation) ||
26306 (details::e_lt == operation) ||
26307 (details::e_lte == operation) ||
26308 (details::e_gt == operation) ||
26309 (details::e_gte == operation) ||
26310 (details::e_eq == operation) ||
26311 (details::e_ne == operation) ||
26312 (details::e_and == operation) ||
26313 (details::e_nand == operation) ||
26314 (details::e_or == operation) ||
26315 (details::e_nor == operation) ||
26316 (details::e_xor == operation) ||
26317 (details::e_xnor == operation) ;
26318 }
26319
26320 inline std::string branch_to_id(expression_node_ptr branch) const
26321 {
26322 static const std::string null_str ("(null)" );
26323 static const std::string const_str ("(c)" );
26324 static const std::string var_str ("(v)" );
26325 static const std::string vov_str ("(vov)" );
26326 static const std::string cov_str ("(cov)" );
26327 static const std::string voc_str ("(voc)" );
26328 static const std::string str_str ("(s)" );
26329 static const std::string strrng_str ("(rngs)" );
26330 static const std::string cs_str ("(cs)" );
26331 static const std::string cstrrng_str("(crngs)");
26332
26333 if (details::is_null_node(branch))
26334 return null_str;
26335 else if (details::is_constant_node(branch))
26336 return const_str;
26337 else if (details::is_variable_node(branch))
26338 return var_str;
26339 else if (details::is_vov_node(branch))
26340 return vov_str;
26341 else if (details::is_cov_node(branch))
26342 return cov_str;
26343 else if (details::is_voc_node(branch))
26344 return voc_str;
26345 else if (details::is_string_node(branch))
26346 return str_str;
26347 else if (details::is_const_string_node(branch))
26348 return cs_str;
26349 else if (details::is_string_range_node(branch))
26350 return strrng_str;
26351 else if (details::is_const_string_range_node(branch))
26352 return cstrrng_str;
26353 else if (details::is_t0ot1ot2_node(branch))
26354 return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
26355 else if (details::is_t0ot1ot2ot3_node(branch))
26356 return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
26357 else
26358 return "ERROR";
26359 }
26360
26361 inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
26362 {
26363 return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
26364 }
26365
26366 inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26367 {
26368 if (!operation_optimisable(operation))
26369 return false;
26370 else
26371 return details::is_constant_node(branch[0]) &&
26372 details::is_variable_node(branch[1]) ;
26373 }
26374
26375 inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26376 {
26377 if (!operation_optimisable(operation))
26378 return false;
26379 else
26380 return details::is_variable_node(branch[0]) &&
26381 details::is_constant_node(branch[1]) ;
26382 }
26383
26384 inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26385 {
26386 if (!operation_optimisable(operation))
26387 return false;
26388 else
26389 return details::is_variable_node(branch[0]) &&
26390 details::is_variable_node(branch[1]) ;
26391 }
26392
26393 inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26394 {
26395 if (!operation_optimisable(operation))
26396 return false;
26397 else
26398 return details::is_constant_node(branch[0]) &&
26399 !details::is_constant_node(branch[1]) ;
26400 }
26401
26402 inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26403 {
26404 if (!operation_optimisable(operation))
26405 return false;
26406 else
26407 return !details::is_constant_node(branch[0]) &&
26408 details::is_constant_node(branch[1]) ;
26409 }
26410
26411 inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26412 {
26413 if (
26414 (details::e_add == operation) ||
26415 (details::e_sub == operation) ||
26416 (details::e_mul == operation) ||
26417 (details::e_div == operation)
26418 )
26419 {
26420 return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
26421 (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
26422 }
26423 else
26424 return false;
26425 }
26426
26427 inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26428 {
26429 if (
26430 (details::e_add == operation) ||
26431 (details::e_sub == operation) ||
26432 (details::e_mul == operation) ||
26433 (details::e_div == operation)
26434 )
26435 {
26436 return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
26437 (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
26438 }
26439 else
26440 return false;
26441 }
26442
26443 inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26444 {
26445 if (!operation_optimisable(operation))
26446 return false;
26447 else
26448 return details::is_uv_node(branch[0]) &&
26449 details::is_uv_node(branch[1]) ;
26450 }
26451
26452 inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26453 {
26454 if (!operation_optimisable(operation))
26455 return false;
26456 else
26457 return details::is_variable_node(branch[0]) &&
26458 !details::is_variable_node(branch[1]) ;
26459 }
26460
26461 inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26462 {
26463 if (!operation_optimisable(operation))
26464 return false;
26465 else
26466 return !details::is_variable_node(branch[0]) &&
26467 details::is_variable_node(branch[1]) ;
26468 }
26469
26470 inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26471 {
26472 if (!operation_optimisable(operation))
26473 return false;
26474 else
26475 return !details::is_constant_node(branch[0]) ||
26476 !details::is_constant_node(branch[1]) ;
26477 }
26478
26479 inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26480 {
26481 if (is_assignment_operation(operation))
26482 {
26483 const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
26484
26485 if (details::is_string_node(branch[0]))
26486 return !b1_is_genstring;
26487 else
26488 return (
26489 !details::is_variable_node (branch[0]) &&
26490 !details::is_vector_elem_node (branch[0]) &&
26491 !details::is_rebasevector_elem_node (branch[0]) &&
26492 !details::is_rebasevector_celem_node(branch[0]) &&
26493 !details::is_vector_node (branch[0])
26494 )
26495 || b1_is_genstring;
26496 }
26497 else
26498 return false;
26499 }
26500
26501 inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
26502 {
26503 if (
26504 !details::is_constant_node(branch[1]) ||
26505 details::is_constant_node(branch[0]) ||
26506 details::is_variable_node(branch[0]) ||
26507 details::is_vector_node (branch[0]) ||
26508 details::is_generally_string_node(branch[0])
26509 )
26510 return false;
26511
26512 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
26513
26514 return cardinal_pow_optimisable(operation, c);
26515 }
26516
26517 inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
26518 {
26519 return (
26520 details::is_break_node (branch[0]) ||
26521 details::is_break_node (branch[1]) ||
26522 details::is_continue_node(branch[0]) ||
26523 details::is_continue_node(branch[1])
26524 );
26525 }
26526
26527 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26528 {
26529 const bool b0_string = is_generally_string_node(branch[0]);
26530 const bool b1_string = is_generally_string_node(branch[1]);
26531
26532 bool result = false;
26533
26534 if (b0_string != b1_string)
26535 result = true;
26536 else if (!valid_string_operation(operation) && b0_string && b1_string)
26537 result = true;
26538
26539 if (result)
26540 {
26541 parser_->set_synthesis_error("Invalid string operation");
26542 }
26543
26544 return result;
26545 }
26546
26547 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26548 {
26549 const bool b0_string = is_generally_string_node(branch[0]);
26550 const bool b1_string = is_generally_string_node(branch[1]);
26551 const bool b2_string = is_generally_string_node(branch[2]);
26552
26553 bool result = false;
26554
26555 if ((b0_string != b1_string) || (b1_string != b2_string))
26556 result = true;
26557 else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
26558 result = true;
26559
26560 if (result)
26561 {
26562 parser_->set_synthesis_error("Invalid string operation");
26563 }
26564
26565 return result;
26566 }
26567
26568 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26569 {
26570 const bool b0_string = is_generally_string_node(branch[0]);
26571 const bool b1_string = is_generally_string_node(branch[1]);
26572
26573 return (b0_string && b1_string && valid_string_operation(operation));
26574 }
26575
26576 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26577 {
26578 const bool b0_string = is_generally_string_node(branch[0]);
26579 const bool b1_string = is_generally_string_node(branch[1]);
26580 const bool b2_string = is_generally_string_node(branch[2]);
26581
26582 return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
26583 }
26584
26585 #ifndef exprtk_disable_sc_andor
26586 inline bool is_shortcircuit_expression(const details::operator_type& operation) const
26587 {
26588 return (
26589 (details::e_scand == operation) ||
26590 (details::e_scor == operation)
26591 );
26592 }
26593 #else
26594 inline bool is_shortcircuit_expression(const details::operator_type&) const
26595 {
26596 return false;
26597 }
26598 #endif
26599
26600 inline bool is_null_present(expression_node_ptr (&branch)[2]) const
26601 {
26602 return (
26603 details::is_null_node(branch[0]) ||
26604 details::is_null_node(branch[1])
26605 );
26606 }
26607
26608 inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26609 {
26610 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26611 return false;
26612 else
26613 return (
26614 (details::e_lt == operation) ||
26615 (details::e_lte == operation) ||
26616 (details::e_gt == operation) ||
26617 (details::e_gte == operation) ||
26618 (details::e_eq == operation) ||
26619 (details::e_ne == operation) ||
26620 (details::e_equal == operation) ||
26621 (details::e_and == operation) ||
26622 (details::e_nand == operation) ||
26623 (details:: e_or == operation) ||
26624 (details:: e_nor == operation) ||
26625 (details:: e_xor == operation) ||
26626 (details::e_xnor == operation)
26627 );
26628 }
26629
26630 inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26631 {
26632 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26633 return false;
26634 else
26635 return (
26636 (details::e_add == operation) ||
26637 (details::e_sub == operation) ||
26638 (details::e_mul == operation) ||
26639 (details::e_div == operation) ||
26640 (details::e_pow == operation)
26641 );
26642 }
26643
26644 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
26645 {
26646 if ((0 == branch[0]) || (0 == branch[1]))
26647 {
26648 return error_node();
26649 }
26650 else if (is_invalid_string_op(operation,branch))
26651 {
26652 return error_node();
26653 }
26654 else if (is_invalid_assignment_op(operation,branch))
26655 {
26656 return error_node();
26657 }
26658 else if (is_invalid_break_continue_op(branch))
26659 {
26660 return error_node();
26661 }
26662 else if (details::e_assign == operation)
26663 {
26664 return synthesize_assignment_expression(operation, branch);
26665 }
26666 else if (details::e_swap == operation)
26667 {
26668 return synthesize_swap_expression(branch);
26669 }
26670 else if (is_assignment_operation(operation))
26671 {
26672 return synthesize_assignment_operation_expression(operation, branch);
26673 }
26674 else if (is_vector_eqineq_logic_operation(operation, branch))
26675 {
26676 return synthesize_veceqineqlogic_operation_expression(operation, branch);
26677 }
26678 else if (is_vector_arithmetic_operation(operation, branch))
26679 {
26680 return synthesize_vecarithmetic_operation_expression(operation, branch);
26681 }
26682 else if (is_shortcircuit_expression(operation))
26683 {
26684 return synthesize_shortcircuit_expression(operation, branch);
26685 }
26686 else if (is_string_operation(operation, branch))
26687 {
26688 return synthesize_string_expression(operation, branch);
26689 }
26690 else if (is_null_present(branch))
26691 {
26692 return synthesize_null_expression(operation, branch);
26693 }
26694 #ifndef exprtk_disable_cardinal_pow_optimisation
26695 else if (is_constpow_operation(operation, branch))
26696 {
26697 return cardinal_pow_optimisation(branch);
26698 }
26699 #endif
26700
26701 expression_node_ptr result = error_node();
26702
26703 #ifndef exprtk_disable_enhanced_features
26704 if (synthesize_expression(operation, branch, result))
26705 {
26706 return result;
26707 }
26708 else
26709 #endif
26710
26711 {
26712 /*
26713 Possible reductions:
26714 1. c o cob -> cob
26715 2. cob o c -> cob
26716 3. c o boc -> boc
26717 4. boc o c -> boc
26718 */
26719 result = error_node();
26720
26721 if (cocob_optimisable(operation, branch))
26722 {
26723 result = synthesize_cocob_expression::process((*this), operation, branch);
26724 }
26725 else if (coboc_optimisable(operation, branch) && (0 == result))
26726 {
26727 result = synthesize_coboc_expression::process((*this), operation, branch);
26728 }
26729
26730 if (result)
26731 return result;
26732 }
26733
26734 if (uvouv_optimisable(operation, branch))
26735 {
26736 return synthesize_uvouv_expression(operation, branch);
26737 }
26738 else if (vob_optimisable(operation, branch))
26739 {
26740 return synthesize_vob_expression::process((*this), operation, branch);
26741 }
26742 else if (bov_optimisable(operation, branch))
26743 {
26744 return synthesize_bov_expression::process((*this), operation, branch);
26745 }
26746 else if (cob_optimisable(operation, branch))
26747 {
26748 return synthesize_cob_expression::process((*this), operation, branch);
26749 }
26750 else if (boc_optimisable(operation, branch))
26751 {
26752 return synthesize_boc_expression::process((*this), operation, branch);
26753 }
26754 #ifndef exprtk_disable_enhanced_features
26755 else if (cov_optimisable(operation, branch))
26756 {
26757 return synthesize_cov_expression::process((*this), operation, branch);
26758 }
26759 #endif
26760 else if (binext_optimisable(operation, branch))
26761 {
26762 return synthesize_binary_ext_expression::process((*this), operation, branch);
26763 }
26764 else
26765 return synthesize_expression<binary_node_t,2>(operation, branch);
26766 }
26767
26768 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
26769 {
26770 if (
26771 (0 == branch[0]) ||
26772 (0 == branch[1]) ||
26773 (0 == branch[2])
26774 )
26775 {
26776 details::free_all_nodes(*node_allocator_,branch);
26777
26778 return error_node();
26779 }
26780 else if (is_invalid_string_op(operation, branch))
26781 {
26782 return error_node();
26783 }
26784 else if (is_string_operation(operation, branch))
26785 {
26786 return synthesize_string_expression(operation, branch);
26787 }
26788 else
26789 return synthesize_expression<trinary_node_t,3>(operation, branch);
26790 }
26791
26792 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
26793 {
26794 return synthesize_expression<quaternary_node_t,4>(operation,branch);
26795 }
26796
26797 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
26798 {
26799 expression_node_ptr branch[1] = { b0 };
26800 return (*this)(operation,branch);
26801 }
26802
26803 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
26804 {
26805 expression_node_ptr result = error_node();
26806
26807 if ((0 != b0) && (0 != b1))
26808 {
26809 expression_node_ptr branch[2] = { b0, b1 };
26810 result = expression_generator<Type>::operator()(operation, branch);
26811 b0 = branch[0];
26812 b1 = branch[1];
26813 }
26814
26815 return result;
26816 }
26817
26818 inline expression_node_ptr conditional(expression_node_ptr condition,
26819 expression_node_ptr consequent,
26820 expression_node_ptr alternative) const
26821 {
26822 if ((0 == condition) || (0 == consequent))
26823 {
26824 free_node(*node_allocator_, condition);
26825 free_node(*node_allocator_, consequent);
26826 free_node(*node_allocator_, alternative);
26827
26828 return error_node();
26829 }
26830 // Can the condition be immediately evaluated? if so optimise.
26831 else if (details::is_constant_node(condition))
26832 {
26833 // True branch
26834 if (details::is_true(condition))
26835 {
26836 free_node(*node_allocator_, condition);
26837 free_node(*node_allocator_, alternative);
26838
26839 return consequent;
26840 }
26841 // False branch
26842 else
26843 {
26844 free_node(*node_allocator_, condition);
26845 free_node(*node_allocator_, consequent);
26846
26847 if (alternative)
26848 return alternative;
26849 else
26850 return node_allocator_->allocate<details::null_node<T> >();
26851 }
26852 }
26853 else if ((0 != consequent) && (0 != alternative))
26854 {
26855 return node_allocator_->
26856 allocate<conditional_node_t>(condition, consequent, alternative);
26857 }
26858 else
26859 return node_allocator_->
26860 allocate<cons_conditional_node_t>(condition, consequent);
26861 }
26862
26863 #ifndef exprtk_disable_string_capabilities
26864 inline expression_node_ptr conditional_string(expression_node_ptr condition,
26865 expression_node_ptr consequent,
26866 expression_node_ptr alternative) const
26867 {
26868 if ((0 == condition) || (0 == consequent))
26869 {
26870 free_node(*node_allocator_, condition);
26871 free_node(*node_allocator_, consequent);
26872 free_node(*node_allocator_, alternative);
26873
26874 return error_node();
26875 }
26876 // Can the condition be immediately evaluated? if so optimise.
26877 else if (details::is_constant_node(condition))
26878 {
26879 // True branch
26880 if (details::is_true(condition))
26881 {
26882 free_node(*node_allocator_, condition);
26883 free_node(*node_allocator_, alternative);
26884
26885 return consequent;
26886 }
26887 // False branch
26888 else
26889 {
26890 free_node(*node_allocator_, condition);
26891 free_node(*node_allocator_, consequent);
26892
26893 if (alternative)
26894 return alternative;
26895 else
26896 return node_allocator_->
26897 allocate_c<details::string_literal_node<Type> >("");
26898 }
26899 }
26900 else if ((0 != consequent) && (0 != alternative))
26901 return node_allocator_->
26902 allocate<conditional_string_node_t>(condition, consequent, alternative);
26903 else
26904 return error_node();
26905 }
26906 #else
26907 inline expression_node_ptr conditional_string(expression_node_ptr,
26908 expression_node_ptr,
26909 expression_node_ptr) const
26910 {
26911 return error_node();
26912 }
26913 #endif
26914
26915 inline expression_node_ptr while_loop(expression_node_ptr& condition,
26916 expression_node_ptr& branch,
26917 const bool brkcont = false) const
26918 {
26919 if (!brkcont && details::is_constant_node(condition))
26920 {
26921 expression_node_ptr result = error_node();
26922 if (details::is_true(condition))
26923 // Infinite loops are not allowed.
26924 result = error_node();
26925 else
26926 result = node_allocator_->allocate<details::null_node<Type> >();
26927
26928 free_node(*node_allocator_, condition);
26929 free_node(*node_allocator_, branch);
26930
26931 return result;
26932 }
26933 else if (details::is_null_node(condition))
26934 {
26935 free_node(*node_allocator_,condition);
26936
26937 return branch;
26938 }
26939 else if (!brkcont)
26940 return node_allocator_->allocate<while_loop_node_t>(condition,branch);
26941 #ifndef exprtk_disable_break_continue
26942 else
26943 return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
26944 #else
26945 return error_node();
26946 #endif
26947 }
26948
26949 inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
26950 expression_node_ptr& branch,
26951 const bool brkcont = false) const
26952 {
26953 if (!brkcont && details::is_constant_node(condition))
26954 {
26955 if (
26956 details::is_true(condition) &&
26957 details::is_constant_node(branch)
26958 )
26959 {
26960 free_node(*node_allocator_,condition);
26961
26962 return branch;
26963 }
26964
26965 free_node(*node_allocator_, condition);
26966 free_node(*node_allocator_, branch);
26967
26968 return error_node();
26969 }
26970 else if (details::is_null_node(condition))
26971 {
26972 free_node(*node_allocator_,condition);
26973
26974 return branch;
26975 }
26976 else if (!brkcont)
26977 return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
26978 #ifndef exprtk_disable_break_continue
26979 else
26980 return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
26981 #else
26982 return error_node();
26983 #endif
26984 }
26985
26986 inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
26987 expression_node_ptr& condition,
26988 expression_node_ptr& incrementor,
26989 expression_node_ptr& loop_body,
26990 bool brkcont = false) const
26991 {
26992 if (!brkcont && details::is_constant_node(condition))
26993 {
26994 expression_node_ptr result = error_node();
26995
26996 if (details::is_true(condition))
26997 // Infinite loops are not allowed.
26998 result = error_node();
26999 else
27000 result = node_allocator_->allocate<details::null_node<Type> >();
27001
27002 free_node(*node_allocator_, initialiser);
27003 free_node(*node_allocator_, condition);
27004 free_node(*node_allocator_, incrementor);
27005 free_node(*node_allocator_, loop_body);
27006
27007 return result;
27008 }
27009 else if (details::is_null_node(condition) || (0 == condition))
27010 {
27011 free_node(*node_allocator_, initialiser);
27012 free_node(*node_allocator_, condition);
27013 free_node(*node_allocator_, incrementor);
27014
27015 return loop_body;
27016 }
27017 else if (!brkcont)
27018 return node_allocator_->allocate<for_loop_node_t>
27019 (
27020 initialiser,
27021 condition,
27022 incrementor,
27023 loop_body
27024 );
27025
27026 #ifndef exprtk_disable_break_continue
27027 else
27028 return node_allocator_->allocate<for_loop_bc_node_t>
27029 (
27030 initialiser,
27031 condition,
27032 incrementor,
27033 loop_body
27034 );
27035 #else
27036 return error_node();
27037 #endif
27038 }
27039
27040 template <typename Allocator,
27041 template <typename, typename> class Sequence>
27042 inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
27043 {
27044 expression_node_ptr result = error_node();
27045
27046 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27047 {
27048 expression_node_ptr condition = arg_list[(2 * i) ];
27049 expression_node_ptr consequent = arg_list[(2 * i) + 1];
27050
27051 if ((0 == result) && details::is_true(condition))
27052 {
27053 result = consequent;
27054 break;
27055 }
27056 }
27057
27058 if (0 == result)
27059 {
27060 result = arg_list.back();
27061 }
27062
27063 for (std::size_t i = 0; i < arg_list.size(); ++i)
27064 {
27065 expression_node_ptr current_expr = arg_list[i];
27066
27067 if (current_expr && (current_expr != result))
27068 {
27069 free_node(*node_allocator_,current_expr);
27070 }
27071 }
27072
27073 return result;
27074 }
27075
27076 template <typename Allocator,
27077 template <typename, typename> class Sequence>
27078 inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
27079 {
27080 expression_node_ptr result = error_node();
27081
27082 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27083 {
27084 expression_node_ptr condition = arg_list[(2 * i) ];
27085 expression_node_ptr consequent = arg_list[(2 * i) + 1];
27086
27087 if (details::is_true(condition))
27088 {
27089 result = consequent;
27090 }
27091 }
27092
27093 if (0 == result)
27094 {
27095 T zero = T(0);
27096 result = node_allocator_->allocate<literal_node_t>(zero);
27097 }
27098
27099 for (std::size_t i = 0; i < arg_list.size(); ++i)
27100 {
27101 expression_node_ptr& current_expr = arg_list[i];
27102
27103 if (current_expr && (current_expr != result))
27104 {
27105 free_node(*node_allocator_,current_expr);
27106 }
27107 }
27108
27109 return result;
27110 }
27111
27112 struct switch_nodes
27113 {
27114 typedef std::vector<expression_node_ptr> arg_list_t;
27115
27116 #define case_stmt(N) \
27117 if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
27118
27119 struct switch_1
27120 {
27121 static inline T process(const arg_list_t& arg)
27122 {
27123 case_stmt(0)
27124
27125 return arg.back()->value();
27126 }
27127 };
27128
27129 struct switch_2
27130 {
27131 static inline T process(const arg_list_t& arg)
27132 {
27133 case_stmt(0) case_stmt(1)
27134
27135 return arg.back()->value();
27136 }
27137 };
27138
27139 struct switch_3
27140 {
27141 static inline T process(const arg_list_t& arg)
27142 {
27143 case_stmt(0) case_stmt(1)
27144 case_stmt(2)
27145
27146 return arg.back()->value();
27147 }
27148 };
27149
27150 struct switch_4
27151 {
27152 static inline T process(const arg_list_t& arg)
27153 {
27154 case_stmt(0) case_stmt(1)
27155 case_stmt(2) case_stmt(3)
27156
27157 return arg.back()->value();
27158 }
27159 };
27160
27161 struct switch_5
27162 {
27163 static inline T process(const arg_list_t& arg)
27164 {
27165 case_stmt(0) case_stmt(1)
27166 case_stmt(2) case_stmt(3)
27167 case_stmt(4)
27168
27169 return arg.back()->value();
27170 }
27171 };
27172
27173 struct switch_6
27174 {
27175 static inline T process(const arg_list_t& arg)
27176 {
27177 case_stmt(0) case_stmt(1)
27178 case_stmt(2) case_stmt(3)
27179 case_stmt(4) case_stmt(5)
27180
27181 return arg.back()->value();
27182 }
27183 };
27184
27185 struct switch_7
27186 {
27187 static inline T process(const arg_list_t& arg)
27188 {
27189 case_stmt(0) case_stmt(1)
27190 case_stmt(2) case_stmt(3)
27191 case_stmt(4) case_stmt(5)
27192 case_stmt(6)
27193
27194 return arg.back()->value();
27195 }
27196 };
27197
27198 #undef case_stmt
27199 };
27200
27201 template <typename Allocator,
27202 template <typename, typename> class Sequence>
27203 inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27204 {
27205 if (arg_list.empty())
27206 return error_node();
27207 else if (
27208 !all_nodes_valid(arg_list) ||
27209 (arg_list.size() < 3) ||
27210 ((arg_list.size() % 2) != 1)
27211 )
27212 {
27213 details::free_all_nodes(*node_allocator_,arg_list);
27214
27215 return error_node();
27216 }
27217 else if (is_constant_foldable(arg_list))
27218 return const_optimise_switch(arg_list);
27219
27220 switch ((arg_list.size() - 1) / 2)
27221 {
27222 #define case_stmt(N) \
27223 case N : \
27224 return node_allocator_-> \
27225 allocate<details::switch_n_node \
27226 <Type,typename switch_nodes::switch_##N> >(arg_list); \
27227
27228 case_stmt(1)
27229 case_stmt(2)
27230 case_stmt(3)
27231 case_stmt(4)
27232 case_stmt(5)
27233 case_stmt(6)
27234 case_stmt(7)
27235 #undef case_stmt
27236
27237 default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
27238 }
27239 }
27240
27241 template <typename Allocator,
27242 template <typename, typename> class Sequence>
27243 inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27244 {
27245 if (!all_nodes_valid(arg_list))
27246 {
27247 details::free_all_nodes(*node_allocator_,arg_list);
27248
27249 return error_node();
27250 }
27251 else if (is_constant_foldable(arg_list))
27252 return const_optimise_mswitch(arg_list);
27253 else
27254 return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
27255 }
27256
27257 #define unary_opr_switch_statements \
27258 case_stmt(details:: e_abs, details:: abs_op) \
27259 case_stmt(details:: e_acos, details:: acos_op) \
27260 case_stmt(details::e_acosh, details::acosh_op) \
27261 case_stmt(details:: e_asin, details:: asin_op) \
27262 case_stmt(details::e_asinh, details::asinh_op) \
27263 case_stmt(details:: e_atan, details:: atan_op) \
27264 case_stmt(details::e_atanh, details::atanh_op) \
27265 case_stmt(details:: e_ceil, details:: ceil_op) \
27266 case_stmt(details:: e_cos, details:: cos_op) \
27267 case_stmt(details:: e_cosh, details:: cosh_op) \
27268 case_stmt(details:: e_exp, details:: exp_op) \
27269 case_stmt(details::e_expm1, details::expm1_op) \
27270 case_stmt(details::e_floor, details::floor_op) \
27271 case_stmt(details:: e_log, details:: log_op) \
27272 case_stmt(details::e_log10, details::log10_op) \
27273 case_stmt(details:: e_log2, details:: log2_op) \
27274 case_stmt(details::e_log1p, details::log1p_op) \
27275 case_stmt(details:: e_neg, details:: neg_op) \
27276 case_stmt(details:: e_pos, details:: pos_op) \
27277 case_stmt(details::e_round, details::round_op) \
27278 case_stmt(details:: e_sin, details:: sin_op) \
27279 case_stmt(details:: e_sinc, details:: sinc_op) \
27280 case_stmt(details:: e_sinh, details:: sinh_op) \
27281 case_stmt(details:: e_sqrt, details:: sqrt_op) \
27282 case_stmt(details:: e_tan, details:: tan_op) \
27283 case_stmt(details:: e_tanh, details:: tanh_op) \
27284 case_stmt(details:: e_cot, details:: cot_op) \
27285 case_stmt(details:: e_sec, details:: sec_op) \
27286 case_stmt(details:: e_csc, details:: csc_op) \
27287 case_stmt(details:: e_r2d, details:: r2d_op) \
27288 case_stmt(details:: e_d2r, details:: d2r_op) \
27289 case_stmt(details:: e_d2g, details:: d2g_op) \
27290 case_stmt(details:: e_g2d, details:: g2d_op) \
27291 case_stmt(details:: e_notl, details:: notl_op) \
27292 case_stmt(details:: e_sgn, details:: sgn_op) \
27293 case_stmt(details:: e_erf, details:: erf_op) \
27294 case_stmt(details:: e_erfc, details:: erfc_op) \
27295 case_stmt(details:: e_ncdf, details:: ncdf_op) \
27296 case_stmt(details:: e_frac, details:: frac_op) \
27297 case_stmt(details::e_trunc, details::trunc_op) \
27298
27299 inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
27300 expression_node_ptr (&branch)[1])
27301 {
27302 T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
27303
27304 switch (operation)
27305 {
27306 #define case_stmt(op0,op1) \
27307 case op0 : return node_allocator_-> \
27308 allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
27309
27310 unary_opr_switch_statements
27311 #undef case_stmt
27312 default : return error_node();
27313 }
27314 }
27315
27316 inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
27317 expression_node_ptr (&branch)[1])
27318 {
27319 switch (operation)
27320 {
27321 #define case_stmt(op0,op1) \
27322 case op0 : return node_allocator_-> \
27323 allocate<typename details::unary_vector_node<Type,op1<Type> > > \
27324 (operation, branch[0]); \
27325
27326 unary_opr_switch_statements
27327 #undef case_stmt
27328 default : return error_node();
27329 }
27330 }
27331
27332 inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
27333 expression_node_ptr (&branch)[1])
27334 {
27335 switch (operation)
27336 {
27337 #define case_stmt(op0,op1) \
27338 case op0 : return node_allocator_-> \
27339 allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
27340
27341 unary_opr_switch_statements
27342 #undef case_stmt
27343 default : return error_node();
27344 }
27345 }
27346
27347 inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
27348 expression_node_ptr (&branch)[3])
27349 {
27350 expression_node_ptr temp_node = error_node();
27351
27352 switch (operation)
27353 {
27354 #define case_stmt(op) \
27355 case details::e_sf##op : temp_node = node_allocator_-> \
27356 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27357 (operation, branch); \
27358 break; \
27359
27360 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27361 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27362 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27363 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27364 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27365 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27366 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27367 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27368 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27369 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27370 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27371 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27372 #undef case_stmt
27373 default : return error_node();
27374 }
27375
27376 const T v = temp_node->value();
27377
27378 details::free_node(*node_allocator_,temp_node);
27379
27380 return node_allocator_->allocate<literal_node_t>(v);
27381 }
27382
27383 inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27384 {
27385 typedef details::variable_node<Type>* variable_ptr;
27386
27387 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27388 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27389 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27390
27391 switch (operation)
27392 {
27393 #define case_stmt(op) \
27394 case details::e_sf##op : return node_allocator_-> \
27395 allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
27396 (v0, v1, v2); \
27397
27398 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27399 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27400 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27401 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27402 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27403 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27404 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27405 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27406 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27407 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27408 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27409 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27410 #undef case_stmt
27411 default : return error_node();
27412 }
27413 }
27414
27415 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27416 {
27417 if (!all_nodes_valid(branch))
27418 return error_node();
27419 else if (is_constant_foldable(branch))
27420 return const_optimise_sf3(operation,branch);
27421 else if (all_nodes_variables(branch))
27422 return varnode_optimise_sf3(operation,branch);
27423 else
27424 {
27425 switch (operation)
27426 {
27427 #define case_stmt(op) \
27428 case details::e_sf##op : return node_allocator_-> \
27429 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27430 (operation, branch); \
27431
27432 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27433 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27434 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27435 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27436 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27437 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27438 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27439 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27440 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27441 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27442 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27443 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27444 #undef case_stmt
27445 default : return error_node();
27446 }
27447 }
27448 }
27449
27450 inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27451 {
27452 expression_node_ptr temp_node = error_node();
27453
27454 switch (operation)
27455 {
27456 #define case_stmt(op) \
27457 case details::e_sf##op : temp_node = node_allocator_-> \
27458 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27459 (operation, branch); \
27460 break; \
27461
27462 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27463 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27464 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27465 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27466 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27467 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27468 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27469 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27470 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27471 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27472 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27473 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27474 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27475 #undef case_stmt
27476 default : return error_node();
27477 }
27478
27479 const T v = temp_node->value();
27480
27481 details::free_node(*node_allocator_,temp_node);
27482
27483 return node_allocator_->allocate<literal_node_t>(v);
27484 }
27485
27486 inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27487 {
27488 typedef details::variable_node<Type>* variable_ptr;
27489
27490 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27491 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27492 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27493 const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
27494
27495 switch (operation)
27496 {
27497 #define case_stmt(op) \
27498 case details::e_sf##op : return node_allocator_-> \
27499 allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
27500 (v0, v1, v2, v3); \
27501
27502 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27503 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27504 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27505 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27506 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27507 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27508 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27509 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27510 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27511 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27512 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27513 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27514 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27515 #undef case_stmt
27516 default : return error_node();
27517 }
27518 }
27519
27520 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27521 {
27522 if (!all_nodes_valid(branch))
27523 return error_node();
27524 else if (is_constant_foldable(branch))
27525 return const_optimise_sf4(operation,branch);
27526 else if (all_nodes_variables(branch))
27527 return varnode_optimise_sf4(operation,branch);
27528 switch (operation)
27529 {
27530 #define case_stmt(op) \
27531 case details::e_sf##op : return node_allocator_-> \
27532 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27533 (operation, branch); \
27534
27535 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27536 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27537 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27538 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27539 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27540 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27541 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27542 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27543 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27544 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27545 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27546 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27547 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27548 #undef case_stmt
27549 default : return error_node();
27550 }
27551 }
27552
27553 template <typename Allocator,
27554 template <typename, typename> class Sequence>
27555 inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27556 {
27557 expression_node_ptr temp_node = error_node();
27558
27559 switch (operation)
27560 {
27561 #define case_stmt(op0,op1) \
27562 case op0 : temp_node = node_allocator_-> \
27563 allocate<details::vararg_node<Type,op1<Type> > > \
27564 (arg_list); \
27565 break; \
27566
27567 case_stmt(details::e_sum , details::vararg_add_op )
27568 case_stmt(details::e_prod , details::vararg_mul_op )
27569 case_stmt(details::e_avg , details::vararg_avg_op )
27570 case_stmt(details::e_min , details::vararg_min_op )
27571 case_stmt(details::e_max , details::vararg_max_op )
27572 case_stmt(details::e_mand , details::vararg_mand_op )
27573 case_stmt(details::e_mor , details::vararg_mor_op )
27574 case_stmt(details::e_multi , details::vararg_multi_op)
27575 #undef case_stmt
27576 default : return error_node();
27577 }
27578
27579 const T v = temp_node->value();
27580
27581 details::free_node(*node_allocator_,temp_node);
27582
27583 return node_allocator_->allocate<literal_node_t>(v);
27584 }
27585
27586 inline bool special_one_parameter_vararg(const details::operator_type& operation) const
27587 {
27588 return (
27589 (details::e_sum == operation) ||
27590 (details::e_prod == operation) ||
27591 (details::e_avg == operation) ||
27592 (details::e_min == operation) ||
27593 (details::e_max == operation)
27594 );
27595 }
27596
27597 template <typename Allocator,
27598 template <typename, typename> class Sequence>
27599 inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27600 {
27601 switch (operation)
27602 {
27603 #define case_stmt(op0,op1) \
27604 case op0 : return node_allocator_-> \
27605 allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
27606
27607 case_stmt(details::e_sum , details::vararg_add_op )
27608 case_stmt(details::e_prod , details::vararg_mul_op )
27609 case_stmt(details::e_avg , details::vararg_avg_op )
27610 case_stmt(details::e_min , details::vararg_min_op )
27611 case_stmt(details::e_max , details::vararg_max_op )
27612 case_stmt(details::e_mand , details::vararg_mand_op )
27613 case_stmt(details::e_mor , details::vararg_mor_op )
27614 case_stmt(details::e_multi , details::vararg_multi_op)
27615 #undef case_stmt
27616 default : return error_node();
27617 }
27618 }
27619
27620 template <typename Allocator,
27621 template <typename, typename> class Sequence>
27622 inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27623 {
27624 if (1 == arg_list.size())
27625 {
27626 switch (operation)
27627 {
27628 #define case_stmt(op0,op1) \
27629 case op0 : return node_allocator_-> \
27630 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
27631
27632 case_stmt(details::e_sum , details::vec_add_op)
27633 case_stmt(details::e_prod , details::vec_mul_op)
27634 case_stmt(details::e_avg , details::vec_avg_op)
27635 case_stmt(details::e_min , details::vec_min_op)
27636 case_stmt(details::e_max , details::vec_max_op)
27637 #undef case_stmt
27638 default : return error_node();
27639 }
27640 }
27641 else
27642 return error_node();
27643 }
27644
27645 template <typename Allocator,
27646 template <typename, typename> class Sequence>
27647 inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27648 {
27649 if (!all_nodes_valid(arg_list))
27650 {
27651 details::free_all_nodes(*node_allocator_,arg_list);
27652
27653 return error_node();
27654 }
27655 else if (is_constant_foldable(arg_list))
27656 return const_optimise_varargfunc(operation,arg_list);
27657 else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
27658 return vectorize_func(operation,arg_list);
27659 else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
27660 return arg_list[0];
27661 else if (all_nodes_variables(arg_list))
27662 return varnode_optimise_varargfunc(operation,arg_list);
27663
27664 #ifndef exprtk_disable_string_capabilities
27665 if (details::e_smulti == operation)
27666 {
27667 return node_allocator_->
27668 allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
27669 }
27670 else
27671 #endif
27672 {
27673 switch (operation)
27674 {
27675 #define case_stmt(op0,op1) \
27676 case op0 : return node_allocator_-> \
27677 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
27678
27679 case_stmt(details::e_sum , details::vararg_add_op )
27680 case_stmt(details::e_prod , details::vararg_mul_op )
27681 case_stmt(details::e_avg , details::vararg_avg_op )
27682 case_stmt(details::e_min , details::vararg_min_op )
27683 case_stmt(details::e_max , details::vararg_max_op )
27684 case_stmt(details::e_mand , details::vararg_mand_op )
27685 case_stmt(details::e_mor , details::vararg_mor_op )
27686 case_stmt(details::e_multi , details::vararg_multi_op)
27687 #undef case_stmt
27688 default : return error_node();
27689 }
27690 }
27691 }
27692
27693 template <std::size_t N>
27694 inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
27695 {
27696 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
27697 expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
27698
27699 if (0 == result)
27700 return error_node();
27701 else
27702 {
27703 // Can the function call be completely optimised?
27704 if (details::is_constant_node(result))
27705 return result;
27706 else if (!all_nodes_valid(b))
27707 return error_node();
27708 else if (N != f->param_count)
27709 {
27710 details::free_all_nodes(*node_allocator_,b);
27711
27712 return error_node();
27713 }
27714
27715 function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
27716
27717 if (func_node_ptr->init_branches(b))
27718 return result;
27719 else
27720 {
27721 details::free_all_nodes(*node_allocator_,b);
27722
27723 return error_node();
27724 }
27725 }
27726 }
27727
27728 inline expression_node_ptr function(ifunction_t* f)
27729 {
27730 typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
27731 return node_allocator_->allocate<function_N_node_t>(f);
27732 }
27733
27734 inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
27735 std::vector<expression_node_ptr>& arg_list)
27736 {
27737 if (!all_nodes_valid(arg_list))
27738 {
27739 details::free_all_nodes(*node_allocator_,arg_list);
27740
27741 return error_node();
27742 }
27743
27744 typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
27745
27746 expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
27747
27748 if (
27749 !arg_list.empty() &&
27750 !vaf->has_side_effects() &&
27751 is_constant_foldable(arg_list)
27752 )
27753 {
27754 const Type v = result->value();
27755 details::free_node(*node_allocator_,result);
27756 result = node_allocator_->allocate<literal_node_t>(v);
27757 }
27758
27759 parser_->state_.activate_side_effect("vararg_function_call()");
27760
27761 return result;
27762 }
27763
27764 inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
27765 std::vector<expression_node_ptr>& arg_list,
27766 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27767 {
27768 if (!all_nodes_valid(arg_list))
27769 {
27770 details::free_all_nodes(*node_allocator_,arg_list);
27771 return error_node();
27772 }
27773
27774 typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1;
27775 typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
27776
27777 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27778
27779 expression_node_ptr result = error_node();
27780
27781 if (no_psi == param_seq_index)
27782 result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
27783 else
27784 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27785
27786 alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
27787
27788 if (
27789 !arg_list.empty() &&
27790 !gf->has_side_effects() &&
27791 parser_->state_.type_check_enabled &&
27792 is_constant_foldable(arg_list)
27793 )
27794 {
27795 genfunc_node_ptr->init_branches();
27796
27797 const Type v = result->value();
27798
27799 details::free_node(*node_allocator_,result);
27800
27801 return node_allocator_->allocate<literal_node_t>(v);
27802 }
27803 else if (genfunc_node_ptr->init_branches())
27804 {
27805 parser_->state_.activate_side_effect("generic_function_call()");
27806
27807 return result;
27808 }
27809 else
27810 {
27811 details::free_node(*node_allocator_, result);
27812 details::free_all_nodes(*node_allocator_, arg_list);
27813
27814 return error_node();
27815 }
27816 }
27817
27818 #ifndef exprtk_disable_string_capabilities
27819 inline expression_node_ptr string_function_call(igeneric_function_t* gf,
27820 std::vector<expression_node_ptr>& arg_list,
27821 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27822 {
27823 if (!all_nodes_valid(arg_list))
27824 {
27825 details::free_all_nodes(*node_allocator_,arg_list);
27826 return error_node();
27827 }
27828
27829 typedef details::string_function_node <Type,igeneric_function_t> alloc_type1;
27830 typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
27831
27832 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27833
27834 expression_node_ptr result = error_node();
27835
27836 if (no_psi == param_seq_index)
27837 result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
27838 else
27839 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27840
27841 alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
27842
27843 if (
27844 !arg_list.empty() &&
27845 !gf->has_side_effects() &&
27846 is_constant_foldable(arg_list)
27847 )
27848 {
27849 strfunc_node_ptr->init_branches();
27850
27851 const Type v = result->value();
27852
27853 details::free_node(*node_allocator_,result);
27854
27855 return node_allocator_->allocate<literal_node_t>(v);
27856 }
27857 else if (strfunc_node_ptr->init_branches())
27858 {
27859 parser_->state_.activate_side_effect("string_function_call()");
27860
27861 return result;
27862 }
27863 else
27864 {
27865 details::free_node (*node_allocator_,result );
27866 details::free_all_nodes(*node_allocator_,arg_list);
27867
27868 return error_node();
27869 }
27870 }
27871 #endif
27872
27873 #ifndef exprtk_disable_return_statement
27874 inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
27875 {
27876 if (!all_nodes_valid(arg_list))
27877 {
27878 details::free_all_nodes(*node_allocator_,arg_list);
27879 return error_node();
27880 }
27881
27882 typedef details::return_node<Type> alloc_type;
27883
27884 expression_node_ptr result = node_allocator_->
27885 allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
27886
27887 alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
27888
27889 if (return_node_ptr->init_branches())
27890 {
27891 parser_->state_.activate_side_effect("return_call()");
27892
27893 return result;
27894 }
27895 else
27896 {
27897 details::free_node (*node_allocator_,result );
27898 details::free_all_nodes(*node_allocator_,arg_list);
27899
27900 return error_node();
27901 }
27902 }
27903
27904 inline expression_node_ptr return_envelope(expression_node_ptr body,
27905 results_context_t* rc,
27906 bool*& return_invoked)
27907 {
27908 typedef details::return_envelope_node<Type> alloc_type;
27909
27910 expression_node_ptr result = node_allocator_->
27911 allocate_cr<alloc_type>(body,(*rc));
27912
27913 return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
27914
27915 return result;
27916 }
27917 #else
27918 inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
27919 {
27920 return error_node();
27921 }
27922
27923 inline expression_node_ptr return_envelope(expression_node_ptr,
27924 results_context_t*,
27925 bool*&)
27926 {
27927 return error_node();
27928 }
27929 #endif
27930
27931 inline expression_node_ptr vector_element(const std::string& symbol,
27932 vector_holder_ptr vector_base,
27933 expression_node_ptr index)
27934 {
27935 expression_node_ptr result = error_node();
27936
27937 if (details::is_constant_node(index))
27938 {
27939 std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
27940
27941 details::free_node(*node_allocator_,index);
27942
27943 if (vector_base->rebaseable())
27944 {
27945 return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
27946 }
27947
27948 scope_element& se = parser_->sem_.get_element(symbol,i);
27949
27950 if (se.index == i)
27951 {
27952 result = se.var_node;
27953 }
27954 else
27955 {
27956 scope_element nse;
27957 nse.name = symbol;
27958 nse.active = true;
27959 nse.ref_count = 1;
27960 nse.type = scope_element::e_vecelem;
27961 nse.index = i;
27962 nse.depth = parser_->state_.scope_depth;
27963 nse.data = 0;
27964 nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
27965
27966 if (!parser_->sem_.add_element(nse))
27967 {
27968 parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
27969
27970 parser_->sem_.free_element(nse);
27971
27972 result = error_node();
27973 }
27974
27975 exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
27976
27977 parser_->state_.activate_side_effect("vector_element()");
27978
27979 result = nse.var_node;
27980 }
27981 }
27982 else if (vector_base->rebaseable())
27983 result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
27984 else
27985 result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
27986
27987 return result;
27988 }
27989
27990 private:
27991
27992 template <std::size_t N, typename NodePtr>
27993 inline bool is_constant_foldable(NodePtr (&b)[N]) const
27994 {
27995 for (std::size_t i = 0; i < N; ++i)
27996 {
27997 if (0 == b[i])
27998 return false;
27999 else if (!details::is_constant_node(b[i]))
28000 return false;
28001 }
28002
28003 return true;
28004 }
28005
28006 template <typename NodePtr,
28007 typename Allocator,
28008 template <typename, typename> class Sequence>
28009 inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
28010 {
28011 for (std::size_t i = 0; i < b.size(); ++i)
28012 {
28013 if (0 == b[i])
28014 return false;
28015 else if (!details::is_constant_node(b[i]))
28016 return false;
28017 }
28018
28019 return true;
28020 }
28021
28022 void lodge_assignment(symbol_type cst, expression_node_ptr node)
28023 {
28024 parser_->state_.activate_side_effect("lodge_assignment()");
28025
28026 if (!parser_->dec_.collect_assignments())
28027 return;
28028
28029 std::string symbol_name;
28030
28031 switch (cst)
28032 {
28033 case e_st_variable : symbol_name = parser_->symtab_store_
28034 .get_variable_name(node);
28035 break;
28036
28037 #ifndef exprtk_disable_string_capabilities
28038 case e_st_string : symbol_name = parser_->symtab_store_
28039 .get_stringvar_name(node);
28040 break;
28041 #endif
28042
28043 case e_st_vector : {
28044 typedef details::vector_holder<T> vector_holder_t;
28045
28046 vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
28047
28048 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28049 }
28050 break;
28051
28052 case e_st_vecelem : {
28053 typedef details::vector_holder<T> vector_holder_t;
28054
28055 vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
28056
28057 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28058
28059 cst = e_st_vector;
28060 }
28061 break;
28062
28063 default : return;
28064 }
28065
28066 if (!symbol_name.empty())
28067 {
28068 parser_->dec_.add_assignment(symbol_name,cst);
28069 }
28070 }
28071
28072 inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28073 {
28074 if (details::is_variable_node(branch[0]))
28075 {
28076 lodge_assignment(e_st_variable,branch[0]);
28077
28078 return synthesize_expression<assignment_node_t,2>(operation,branch);
28079 }
28080 else if (details::is_vector_elem_node(branch[0]))
28081 {
28082 lodge_assignment(e_st_vecelem,branch[0]);
28083
28084 return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
28085 }
28086 else if (details::is_rebasevector_elem_node(branch[0]))
28087 {
28088 lodge_assignment(e_st_vecelem,branch[0]);
28089
28090 return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
28091 }
28092 else if (details::is_rebasevector_celem_node(branch[0]))
28093 {
28094 lodge_assignment(e_st_vecelem,branch[0]);
28095
28096 return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
28097 }
28098 #ifndef exprtk_disable_string_capabilities
28099 else if (details::is_string_node(branch[0]))
28100 {
28101 lodge_assignment(e_st_string,branch[0]);
28102
28103 return synthesize_expression<assignment_string_node_t,2>(operation, branch);
28104 }
28105 else if (details::is_string_range_node(branch[0]))
28106 {
28107 lodge_assignment(e_st_string,branch[0]);
28108
28109 return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
28110 }
28111 #endif
28112 else if (details::is_vector_node(branch[0]))
28113 {
28114 lodge_assignment(e_st_vector,branch[0]);
28115
28116 if (details::is_ivector_node(branch[1]))
28117 return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
28118 else
28119 return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
28120 }
28121 else
28122 {
28123 parser_->set_synthesis_error("Invalid assignment operation.[1]");
28124
28125 return error_node();
28126 }
28127 }
28128
28129 inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
28130 expression_node_ptr (&branch)[2])
28131 {
28132 if (details::is_variable_node(branch[0]))
28133 {
28134 lodge_assignment(e_st_variable,branch[0]);
28135
28136 switch (operation)
28137 {
28138 #define case_stmt(op0,op1) \
28139 case op0 : return node_allocator_-> \
28140 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
28141 (operation, branch[0], branch[1]); \
28142
28143 case_stmt(details::e_addass,details::add_op)
28144 case_stmt(details::e_subass,details::sub_op)
28145 case_stmt(details::e_mulass,details::mul_op)
28146 case_stmt(details::e_divass,details::div_op)
28147 case_stmt(details::e_modass,details::mod_op)
28148 #undef case_stmt
28149 default : return error_node();
28150 }
28151 }
28152 else if (details::is_vector_elem_node(branch[0]))
28153 {
28154 lodge_assignment(e_st_vecelem,branch[0]);
28155
28156 switch (operation)
28157 {
28158 #define case_stmt(op0,op1) \
28159 case op0 : return node_allocator_-> \
28160 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
28161 (operation, branch[0], branch[1]); \
28162
28163 case_stmt(details::e_addass,details::add_op)
28164 case_stmt(details::e_subass,details::sub_op)
28165 case_stmt(details::e_mulass,details::mul_op)
28166 case_stmt(details::e_divass,details::div_op)
28167 case_stmt(details::e_modass,details::mod_op)
28168 #undef case_stmt
28169 default : return error_node();
28170 }
28171 }
28172 else if (details::is_rebasevector_elem_node(branch[0]))
28173 {
28174 lodge_assignment(e_st_vecelem,branch[0]);
28175
28176 switch (operation)
28177 {
28178 #define case_stmt(op0,op1) \
28179 case op0 : return node_allocator_-> \
28180 template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
28181 (operation, branch[0], branch[1]); \
28182
28183 case_stmt(details::e_addass,details::add_op)
28184 case_stmt(details::e_subass,details::sub_op)
28185 case_stmt(details::e_mulass,details::mul_op)
28186 case_stmt(details::e_divass,details::div_op)
28187 case_stmt(details::e_modass,details::mod_op)
28188 #undef case_stmt
28189 default : return error_node();
28190 }
28191 }
28192 else if (details::is_rebasevector_celem_node(branch[0]))
28193 {
28194 lodge_assignment(e_st_vecelem,branch[0]);
28195
28196 switch (operation)
28197 {
28198 #define case_stmt(op0,op1) \
28199 case op0 : return node_allocator_-> \
28200 template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
28201 (operation, branch[0], branch[1]); \
28202
28203 case_stmt(details::e_addass,details::add_op)
28204 case_stmt(details::e_subass,details::sub_op)
28205 case_stmt(details::e_mulass,details::mul_op)
28206 case_stmt(details::e_divass,details::div_op)
28207 case_stmt(details::e_modass,details::mod_op)
28208 #undef case_stmt
28209 default : return error_node();
28210 }
28211 }
28212 else if (details::is_vector_node(branch[0]))
28213 {
28214 lodge_assignment(e_st_vector,branch[0]);
28215
28216 if (details::is_ivector_node(branch[1]))
28217 {
28218 switch (operation)
28219 {
28220 #define case_stmt(op0,op1) \
28221 case op0 : return node_allocator_-> \
28222 template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
28223 (operation, branch[0], branch[1]); \
28224
28225 case_stmt(details::e_addass,details::add_op)
28226 case_stmt(details::e_subass,details::sub_op)
28227 case_stmt(details::e_mulass,details::mul_op)
28228 case_stmt(details::e_divass,details::div_op)
28229 case_stmt(details::e_modass,details::mod_op)
28230 #undef case_stmt
28231 default : return error_node();
28232 }
28233 }
28234 else
28235 {
28236 switch (operation)
28237 {
28238 #define case_stmt(op0,op1) \
28239 case op0 : return node_allocator_-> \
28240 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
28241 (operation, branch[0], branch[1]); \
28242
28243 case_stmt(details::e_addass,details::add_op)
28244 case_stmt(details::e_subass,details::sub_op)
28245 case_stmt(details::e_mulass,details::mul_op)
28246 case_stmt(details::e_divass,details::div_op)
28247 case_stmt(details::e_modass,details::mod_op)
28248 #undef case_stmt
28249 default : return error_node();
28250 }
28251 }
28252 }
28253 #ifndef exprtk_disable_string_capabilities
28254 else if (
28255 (details::e_addass == operation) &&
28256 details::is_string_node(branch[0])
28257 )
28258 {
28259 typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
28260
28261 lodge_assignment(e_st_string,branch[0]);
28262
28263 return synthesize_expression<addass_t,2>(operation,branch);
28264 }
28265 #endif
28266 else
28267 {
28268 parser_->set_synthesis_error("Invalid assignment operation[2]");
28269
28270 return error_node();
28271 }
28272 }
28273
28274 inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
28275 expression_node_ptr (&branch)[2])
28276 {
28277 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28278 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28279
28280 #define batch_eqineq_logic_case \
28281 case_stmt(details:: e_lt, details:: lt_op) \
28282 case_stmt(details:: e_lte, details:: lte_op) \
28283 case_stmt(details:: e_gt, details:: gt_op) \
28284 case_stmt(details:: e_gte, details:: gte_op) \
28285 case_stmt(details:: e_eq, details:: eq_op) \
28286 case_stmt(details:: e_ne, details:: ne_op) \
28287 case_stmt(details::e_equal, details::equal_op) \
28288 case_stmt(details:: e_and, details:: and_op) \
28289 case_stmt(details:: e_nand, details:: nand_op) \
28290 case_stmt(details:: e_or, details:: or_op) \
28291 case_stmt(details:: e_nor, details:: nor_op) \
28292 case_stmt(details:: e_xor, details:: xor_op) \
28293 case_stmt(details:: e_xnor, details:: xnor_op) \
28294
28295 if (is_b0_ivec && is_b1_ivec)
28296 {
28297 switch (operation)
28298 {
28299 #define case_stmt(op0,op1) \
28300 case op0 : return node_allocator_-> \
28301 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28302 (operation, branch[0], branch[1]); \
28303
28304 batch_eqineq_logic_case
28305 #undef case_stmt
28306 default : return error_node();
28307 }
28308 }
28309 else if (is_b0_ivec && !is_b1_ivec)
28310 {
28311 switch (operation)
28312 {
28313 #define case_stmt(op0,op1) \
28314 case op0 : return node_allocator_-> \
28315 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28316 (operation, branch[0], branch[1]); \
28317
28318 batch_eqineq_logic_case
28319 #undef case_stmt
28320 default : return error_node();
28321 }
28322 }
28323 else if (!is_b0_ivec && is_b1_ivec)
28324 {
28325 switch (operation)
28326 {
28327 #define case_stmt(op0,op1) \
28328 case op0 : return node_allocator_-> \
28329 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28330 (operation, branch[0], branch[1]); \
28331
28332 batch_eqineq_logic_case
28333 #undef case_stmt
28334 default : return error_node();
28335 }
28336 }
28337 else
28338 return error_node();
28339
28340 #undef batch_eqineq_logic_case
28341 }
28342
28343 inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
28344 expression_node_ptr (&branch)[2])
28345 {
28346 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28347 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28348
28349 #define vector_ops \
28350 case_stmt(details::e_add,details::add_op) \
28351 case_stmt(details::e_sub,details::sub_op) \
28352 case_stmt(details::e_mul,details::mul_op) \
28353 case_stmt(details::e_div,details::div_op) \
28354 case_stmt(details::e_mod,details::mod_op) \
28355
28356 if (is_b0_ivec && is_b1_ivec)
28357 {
28358 switch (operation)
28359 {
28360 #define case_stmt(op0,op1) \
28361 case op0 : return node_allocator_-> \
28362 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28363 (operation, branch[0], branch[1]); \
28364
28365 vector_ops
28366 case_stmt(details::e_pow,details:: pow_op)
28367 #undef case_stmt
28368 default : return error_node();
28369 }
28370 }
28371 else if (is_b0_ivec && !is_b1_ivec)
28372 {
28373 switch (operation)
28374 {
28375 #define case_stmt(op0,op1) \
28376 case op0 : return node_allocator_-> \
28377 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28378 (operation, branch[0], branch[1]); \
28379
28380 vector_ops
28381 case_stmt(details::e_pow,details:: pow_op)
28382 #undef case_stmt
28383 default : return error_node();
28384 }
28385 }
28386 else if (!is_b0_ivec && is_b1_ivec)
28387 {
28388 switch (operation)
28389 {
28390 #define case_stmt(op0,op1) \
28391 case op0 : return node_allocator_-> \
28392 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28393 (operation, branch[0], branch[1]); \
28394
28395 vector_ops
28396 #undef case_stmt
28397 default : return error_node();
28398 }
28399 }
28400 else
28401 return error_node();
28402
28403 #undef vector_ops
28404 }
28405
28406 inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
28407 {
28408 const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
28409 const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
28410
28411 const bool v0_is_ivec = details::is_ivector_node (branch[0]);
28412 const bool v1_is_ivec = details::is_ivector_node (branch[1]);
28413
28414 #ifndef exprtk_disable_string_capabilities
28415 const bool v0_is_str = details::is_generally_string_node(branch[0]);
28416 const bool v1_is_str = details::is_generally_string_node(branch[1]);
28417 #endif
28418
28419 expression_node_ptr result = error_node();
28420
28421 if (v0_is_ivar && v1_is_ivar)
28422 {
28423 typedef details::variable_node<T>* variable_node_ptr;
28424
28425 variable_node_ptr v0 = variable_node_ptr(0);
28426 variable_node_ptr v1 = variable_node_ptr(0);
28427
28428 if (
28429 (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
28430 (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
28431 )
28432 {
28433 result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
28434 }
28435 else
28436 result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
28437 }
28438 else if (v0_is_ivec && v1_is_ivec)
28439 {
28440 result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
28441 }
28442 #ifndef exprtk_disable_string_capabilities
28443 else if (v0_is_str && v1_is_str)
28444 {
28445 if (is_string_node(branch[0]) && is_string_node(branch[1]))
28446 result = node_allocator_->allocate<details::swap_string_node<T> >
28447 (branch[0], branch[1]);
28448 else
28449 result = node_allocator_->allocate<details::swap_genstrings_node<T> >
28450 (branch[0], branch[1]);
28451 }
28452 #endif
28453 else
28454 {
28455 parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
28456
28457 return error_node();
28458 }
28459
28460 parser_->state_.activate_side_effect("synthesize_swap_expression()");
28461
28462 return result;
28463 }
28464
28465 #ifndef exprtk_disable_sc_andor
28466 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28467 {
28468 expression_node_ptr result = error_node();
28469
28470 if (details::is_constant_node(branch[0]))
28471 {
28472 if (
28473 (details::e_scand == operation) &&
28474 std::equal_to<T>()(T(0),branch[0]->value())
28475 )
28476 result = node_allocator_->allocate_c<literal_node_t>(T(0));
28477 else if (
28478 (details::e_scor == operation) &&
28479 std::not_equal_to<T>()(T(0),branch[0]->value())
28480 )
28481 result = node_allocator_->allocate_c<literal_node_t>(T(1));
28482 }
28483
28484 if (details::is_constant_node(branch[1]) && (0 == result))
28485 {
28486 if (
28487 (details::e_scand == operation) &&
28488 std::equal_to<T>()(T(0),branch[1]->value())
28489 )
28490 result = node_allocator_->allocate_c<literal_node_t>(T(0));
28491 else if (
28492 (details::e_scor == operation) &&
28493 std::not_equal_to<T>()(T(0),branch[1]->value())
28494 )
28495 result = node_allocator_->allocate_c<literal_node_t>(T(1));
28496 }
28497
28498 if (result)
28499 {
28500 free_node(*node_allocator_, branch[0]);
28501 free_node(*node_allocator_, branch[1]);
28502
28503 return result;
28504 }
28505 else if (details::e_scand == operation)
28506 {
28507 return synthesize_expression<scand_node_t,2>(operation, branch);
28508 }
28509 else if (details::e_scor == operation)
28510 {
28511 return synthesize_expression<scor_node_t,2>(operation, branch);
28512 }
28513 else
28514 return error_node();
28515 }
28516 #else
28517 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
28518 {
28519 return error_node();
28520 }
28521 #endif
28522
28523 #define basic_opr_switch_statements \
28524 case_stmt(details::e_add, details::add_op) \
28525 case_stmt(details::e_sub, details::sub_op) \
28526 case_stmt(details::e_mul, details::mul_op) \
28527 case_stmt(details::e_div, details::div_op) \
28528 case_stmt(details::e_mod, details::mod_op) \
28529 case_stmt(details::e_pow, details::pow_op) \
28530
28531 #define extended_opr_switch_statements \
28532 case_stmt(details:: e_lt, details:: lt_op) \
28533 case_stmt(details:: e_lte, details:: lte_op) \
28534 case_stmt(details:: e_gt, details:: gt_op) \
28535 case_stmt(details:: e_gte, details:: gte_op) \
28536 case_stmt(details:: e_eq, details:: eq_op) \
28537 case_stmt(details:: e_ne, details:: ne_op) \
28538 case_stmt(details:: e_and, details:: and_op) \
28539 case_stmt(details::e_nand, details::nand_op) \
28540 case_stmt(details:: e_or, details:: or_op) \
28541 case_stmt(details:: e_nor, details:: nor_op) \
28542 case_stmt(details:: e_xor, details:: xor_op) \
28543 case_stmt(details::e_xnor, details::xnor_op) \
28544
28545 #ifndef exprtk_disable_cardinal_pow_optimisation
28546 template <typename TType, template <typename, typename> class IPowNode>
28547 inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
28548 {
28549 switch (p)
28550 {
28551 #define case_stmt(cp) \
28552 case cp : return node_allocator_-> \
28553 allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
28554
28555 case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
28556 case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
28557 case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
28558 case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
28559 case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
28560 case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
28561 case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
28562 case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
28563 case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
28564 case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
28565 case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
28566 case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
28567 case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
28568 case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
28569 case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
28570 #undef case_stmt
28571 default : return error_node();
28572 }
28573 }
28574
28575 inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
28576 {
28577 const bool not_recipricol = (c >= T(0));
28578 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28579
28580 if (0 == p)
28581 return node_allocator_->allocate_c<literal_node_t>(T(1));
28582 else if (std::equal_to<T>()(T(2),c))
28583 {
28584 return node_allocator_->
28585 template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
28586 }
28587 else
28588 {
28589 if (not_recipricol)
28590 return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
28591 else
28592 return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
28593 }
28594 }
28595
28596 inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
28597 {
28598 return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
28599 }
28600
28601 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
28602 {
28603 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
28604 const bool not_recipricol = (c >= T(0));
28605 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28606
28607 node_allocator_->free(branch[1]);
28608
28609 if (0 == p)
28610 {
28611 details::free_all_nodes(*node_allocator_, branch);
28612
28613 return node_allocator_->allocate_c<literal_node_t>(T(1));
28614 }
28615 else if (not_recipricol)
28616 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
28617 else
28618 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
28619 }
28620 #else
28621 inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
28622 {
28623 return error_node();
28624 }
28625
28626 inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
28627 {
28628 return false;
28629 }
28630
28631 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
28632 {
28633 return error_node();
28634 }
28635 #endif
28636
28637 struct synthesize_binary_ext_expression
28638 {
28639 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28640 const details::operator_type& operation,
28641 expression_node_ptr (&branch)[2])
28642 {
28643 const bool left_neg = is_neg_unary_node(branch[0]);
28644 const bool right_neg = is_neg_unary_node(branch[1]);
28645
28646 if (left_neg && right_neg)
28647 {
28648 if (
28649 (details::e_add == operation) ||
28650 (details::e_sub == operation) ||
28651 (details::e_mul == operation) ||
28652 (details::e_div == operation)
28653 )
28654 {
28655 if (
28656 !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
28657 !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
28658 )
28659 {
28660 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28661
28662 return error_node();
28663 }
28664 }
28665
28666 switch (operation)
28667 {
28668 // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
28669 case details::e_add : return expr_gen(details::e_neg,
28670 expr_gen.node_allocator_->
28671 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28672 (branch[0],branch[1]));
28673
28674 // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
28675 case details::e_sub : return expr_gen.node_allocator_->
28676 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28677 (branch[1],branch[0]);
28678
28679 default : break;
28680 }
28681 }
28682 else if (left_neg && !right_neg)
28683 {
28684 if (
28685 (details::e_add == operation) ||
28686 (details::e_sub == operation) ||
28687 (details::e_mul == operation) ||
28688 (details::e_div == operation)
28689 )
28690 {
28691 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
28692 {
28693 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28694
28695 return error_node();
28696 }
28697
28698 switch (operation)
28699 {
28700 // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
28701 case details::e_add : return expr_gen.node_allocator_->
28702 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28703 (branch[1], branch[0]);
28704
28705 // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
28706 case details::e_sub : return expr_gen(details::e_neg,
28707 expr_gen.node_allocator_->
28708 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28709 (branch[0], branch[1]));
28710
28711 // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
28712 case details::e_mul : return expr_gen(details::e_neg,
28713 expr_gen.node_allocator_->
28714 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28715 (branch[0], branch[1]));
28716
28717 // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
28718 case details::e_div : return expr_gen(details::e_neg,
28719 expr_gen.node_allocator_->
28720 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28721 (branch[0], branch[1]));
28722
28723 default : return error_node();
28724 }
28725 }
28726 }
28727 else if (!left_neg && right_neg)
28728 {
28729 if (
28730 (details::e_add == operation) ||
28731 (details::e_sub == operation) ||
28732 (details::e_mul == operation) ||
28733 (details::e_div == operation)
28734 )
28735 {
28736 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
28737 {
28738 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28739
28740 return error_node();
28741 }
28742
28743 switch (operation)
28744 {
28745 // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
28746 case details::e_add : return expr_gen.node_allocator_->
28747 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28748 (branch[0], branch[1]);
28749
28750 // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
28751 case details::e_sub : return expr_gen.node_allocator_->
28752 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28753 (branch[0], branch[1]);
28754
28755 // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
28756 case details::e_mul : return expr_gen(details::e_neg,
28757 expr_gen.node_allocator_->
28758 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28759 (branch[0], branch[1]));
28760
28761 // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
28762 case details::e_div : return expr_gen(details::e_neg,
28763 expr_gen.node_allocator_->
28764 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28765 (branch[0], branch[1]));
28766
28767 default : return error_node();
28768 }
28769 }
28770 }
28771
28772 switch (operation)
28773 {
28774 #define case_stmt(op0,op1) \
28775 case op0 : return expr_gen.node_allocator_-> \
28776 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
28777 (branch[0], branch[1]); \
28778
28779 basic_opr_switch_statements
28780 extended_opr_switch_statements
28781 #undef case_stmt
28782 default : return error_node();
28783 }
28784 }
28785 };
28786
28787 struct synthesize_vob_expression
28788 {
28789 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28790 const details::operator_type& operation,
28791 expression_node_ptr (&branch)[2])
28792 {
28793 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
28794
28795 #ifndef exprtk_disable_enhanced_features
28796 if (details::is_sf3ext_node(branch[1]))
28797 {
28798 expression_node_ptr result = error_node();
28799
28800 const bool synthesis_result =
28801 synthesize_sf4ext_expression::template compile_right<vtype>
28802 (expr_gen, v, operation, branch[1], result);
28803
28804 if (synthesis_result)
28805 {
28806 free_node(*expr_gen.node_allocator_,branch[1]);
28807 return result;
28808 }
28809 }
28810 #endif
28811
28812 if (
28813 (details::e_mul == operation) ||
28814 (details::e_div == operation)
28815 )
28816 {
28817 if (details::is_uv_node(branch[1]))
28818 {
28819 typedef details::uv_base_node<Type>* uvbn_ptr_t;
28820
28821 details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
28822
28823 if (details::e_neg == o)
28824 {
28825 const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
28826
28827 free_node(*expr_gen.node_allocator_,branch[1]);
28828
28829 switch (operation)
28830 {
28831 case details::e_mul : return expr_gen(details::e_neg,
28832 expr_gen.node_allocator_->
28833 template allocate_rr<typename details::
28834 vov_node<Type,details::mul_op<Type> > >(v,v1));
28835
28836 case details::e_div : return expr_gen(details::e_neg,
28837 expr_gen.node_allocator_->
28838 template allocate_rr<typename details::
28839 vov_node<Type,details::div_op<Type> > >(v,v1));
28840
28841 default : break;
28842 }
28843 }
28844 }
28845 }
28846
28847 switch (operation)
28848 {
28849 #define case_stmt(op0,op1) \
28850 case op0 : return expr_gen.node_allocator_-> \
28851 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
28852 (v, branch[1]); \
28853
28854 basic_opr_switch_statements
28855 extended_opr_switch_statements
28856 #undef case_stmt
28857 default : return error_node();
28858 }
28859 }
28860 };
28861
28862 struct synthesize_bov_expression
28863 {
28864 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28865 const details::operator_type& operation,
28866 expression_node_ptr (&branch)[2])
28867 {
28868 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
28869
28870 #ifndef exprtk_disable_enhanced_features
28871 if (details::is_sf3ext_node(branch[0]))
28872 {
28873 expression_node_ptr result = error_node();
28874
28875 const bool synthesis_result =
28876 synthesize_sf4ext_expression::template compile_left<vtype>
28877 (expr_gen, v, operation, branch[0], result);
28878
28879 if (synthesis_result)
28880 {
28881 free_node(*expr_gen.node_allocator_, branch[0]);
28882
28883 return result;
28884 }
28885 }
28886 #endif
28887
28888 if (
28889 (details::e_add == operation) ||
28890 (details::e_sub == operation) ||
28891 (details::e_mul == operation) ||
28892 (details::e_div == operation)
28893 )
28894 {
28895 if (details::is_uv_node(branch[0]))
28896 {
28897 typedef details::uv_base_node<Type>* uvbn_ptr_t;
28898
28899 details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
28900
28901 if (details::e_neg == o)
28902 {
28903 const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
28904
28905 free_node(*expr_gen.node_allocator_,branch[0]);
28906
28907 switch (operation)
28908 {
28909 case details::e_add : return expr_gen.node_allocator_->
28910 template allocate_rr<typename details::
28911 vov_node<Type,details::sub_op<Type> > >(v,v0);
28912
28913 case details::e_sub : return expr_gen(details::e_neg,
28914 expr_gen.node_allocator_->
28915 template allocate_rr<typename details::
28916 vov_node<Type,details::add_op<Type> > >(v0,v));
28917
28918 case details::e_mul : return expr_gen(details::e_neg,
28919 expr_gen.node_allocator_->
28920 template allocate_rr<typename details::
28921 vov_node<Type,details::mul_op<Type> > >(v0,v));
28922
28923 case details::e_div : return expr_gen(details::e_neg,
28924 expr_gen.node_allocator_->
28925 template allocate_rr<typename details::
28926 vov_node<Type,details::div_op<Type> > >(v0,v));
28927 default : break;
28928 }
28929 }
28930 }
28931 }
28932
28933 switch (operation)
28934 {
28935 #define case_stmt(op0,op1) \
28936 case op0 : return expr_gen.node_allocator_-> \
28937 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
28938 (branch[0], v); \
28939
28940 basic_opr_switch_statements
28941 extended_opr_switch_statements
28942 #undef case_stmt
28943 default : return error_node();
28944 }
28945 }
28946 };
28947
28948 struct synthesize_cob_expression
28949 {
28950 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28951 const details::operator_type& operation,
28952 expression_node_ptr (&branch)[2])
28953 {
28954 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
28955
28956 free_node(*expr_gen.node_allocator_,branch[0]);
28957
28958 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
28959 {
28960 free_node(*expr_gen.node_allocator_,branch[1]);
28961
28962 return expr_gen(T(0));
28963 }
28964 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
28965 {
28966 free_node(*expr_gen.node_allocator_, branch[1]);
28967
28968 return expr_gen(T(0));
28969 }
28970 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
28971 return branch[1];
28972 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
28973 return branch[1];
28974
28975 if (details::is_cob_node(branch[1]))
28976 {
28977 // Simplify expressions of the form:
28978 // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
28979 // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
28980 if (
28981 (operation == details::e_mul) ||
28982 (operation == details::e_add)
28983 )
28984 {
28985 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28986
28987 if (operation == cobnode->operation())
28988 {
28989 switch (operation)
28990 {
28991 case details::e_add : cobnode->set_c(c + cobnode->c()); break;
28992 case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
28993 default : return error_node();
28994 }
28995
28996 return cobnode;
28997 }
28998 }
28999
29000 if (operation == details::e_mul)
29001 {
29002 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29003 details::operator_type cob_opr = cobnode->operation();
29004
29005 if (
29006 (details::e_div == cob_opr) ||
29007 (details::e_mul == cob_opr)
29008 )
29009 {
29010 switch (cob_opr)
29011 {
29012 case details::e_div : cobnode->set_c(c * cobnode->c()); break;
29013 case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
29014 default : return error_node();
29015 }
29016
29017 return cobnode;
29018 }
29019 }
29020 else if (operation == details::e_div)
29021 {
29022 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29023 details::operator_type cob_opr = cobnode->operation();
29024
29025 if (
29026 (details::e_div == cob_opr) ||
29027 (details::e_mul == cob_opr)
29028 )
29029 {
29030 details::expression_node<Type>* new_cobnode = error_node();
29031
29032 switch (cob_opr)
29033 {
29034 case details::e_div : new_cobnode = expr_gen.node_allocator_->
29035 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29036 (c / cobnode->c(), cobnode->move_branch(0));
29037 break;
29038
29039 case details::e_mul : new_cobnode = expr_gen.node_allocator_->
29040 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29041 (c / cobnode->c(), cobnode->move_branch(0));
29042 break;
29043
29044 default : return error_node();
29045 }
29046
29047 free_node(*expr_gen.node_allocator_,branch[1]);
29048
29049 return new_cobnode;
29050 }
29051 }
29052 }
29053 #ifndef exprtk_disable_enhanced_features
29054 else if (details::is_sf3ext_node(branch[1]))
29055 {
29056 expression_node_ptr result = error_node();
29057
29058 const bool synthesis_result =
29059 synthesize_sf4ext_expression::template compile_right<ctype>
29060 (expr_gen, c, operation, branch[1], result);
29061
29062 if (synthesis_result)
29063 {
29064 free_node(*expr_gen.node_allocator_,branch[1]);
29065
29066 return result;
29067 }
29068 }
29069 #endif
29070
29071 switch (operation)
29072 {
29073 #define case_stmt(op0,op1) \
29074 case op0 : return expr_gen.node_allocator_-> \
29075 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
29076 (c, branch[1]); \
29077
29078 basic_opr_switch_statements
29079 extended_opr_switch_statements
29080 #undef case_stmt
29081 default : return error_node();
29082 }
29083 }
29084 };
29085
29086 struct synthesize_boc_expression
29087 {
29088 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29089 const details::operator_type& operation,
29090 expression_node_ptr (&branch)[2])
29091 {
29092 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29093
29094 details::free_node(*(expr_gen.node_allocator_), branch[1]);
29095
29096 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29097 {
29098 free_node(*expr_gen.node_allocator_, branch[0]);
29099
29100 return expr_gen(T(0));
29101 }
29102 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29103 {
29104 free_node(*expr_gen.node_allocator_, branch[0]);
29105
29106 return expr_gen(std::numeric_limits<T>::quiet_NaN());
29107 }
29108 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29109 return branch[0];
29110 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29111 return branch[0];
29112
29113 if (details::is_boc_node(branch[0]))
29114 {
29115 // Simplify expressions of the form:
29116 // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
29117 // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
29118 if (
29119 (operation == details::e_mul) ||
29120 (operation == details::e_add)
29121 )
29122 {
29123 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29124
29125 if (operation == bocnode->operation())
29126 {
29127 switch (operation)
29128 {
29129 case details::e_add : bocnode->set_c(c + bocnode->c()); break;
29130 case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
29131 default : return error_node();
29132 }
29133
29134 return bocnode;
29135 }
29136 }
29137 else if (operation == details::e_div)
29138 {
29139 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29140 details::operator_type boc_opr = bocnode->operation();
29141
29142 if (
29143 (details::e_div == boc_opr) ||
29144 (details::e_mul == boc_opr)
29145 )
29146 {
29147 switch (boc_opr)
29148 {
29149 case details::e_div : bocnode->set_c(c * bocnode->c()); break;
29150 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29151 default : return error_node();
29152 }
29153
29154 return bocnode;
29155 }
29156 }
29157 else if (operation == details::e_pow)
29158 {
29159 // (v ^ c0) ^ c1 --> v ^(c0 * c1)
29160 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29161 details::operator_type boc_opr = bocnode->operation();
29162
29163 if (details::e_pow == boc_opr)
29164 {
29165 bocnode->set_c(bocnode->c() * c);
29166
29167 return bocnode;
29168 }
29169 }
29170 }
29171
29172 #ifndef exprtk_disable_enhanced_features
29173 if (details::is_sf3ext_node(branch[0]))
29174 {
29175 expression_node_ptr result = error_node();
29176
29177 const bool synthesis_result =
29178 synthesize_sf4ext_expression::template compile_left<ctype>
29179 (expr_gen, c, operation, branch[0], result);
29180
29181 if (synthesis_result)
29182 {
29183 free_node(*expr_gen.node_allocator_, branch[0]);
29184
29185 return result;
29186 }
29187 }
29188 #endif
29189
29190 switch (operation)
29191 {
29192 #define case_stmt(op0,op1) \
29193 case op0 : return expr_gen.node_allocator_-> \
29194 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
29195 (branch[0], c); \
29196
29197 basic_opr_switch_statements
29198 extended_opr_switch_statements
29199 #undef case_stmt
29200 default : return error_node();
29201 }
29202 }
29203 };
29204
29205 struct synthesize_cocob_expression
29206 {
29207 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29208 const details::operator_type& operation,
29209 expression_node_ptr (&branch)[2])
29210 {
29211 expression_node_ptr result = error_node();
29212
29213 // (cob) o c --> cob
29214 if (details::is_cob_node(branch[0]))
29215 {
29216 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
29217
29218 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29219
29220 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29221 {
29222 free_node(*expr_gen.node_allocator_, branch[0]);
29223 free_node(*expr_gen.node_allocator_, branch[1]);
29224
29225 return expr_gen(T(0));
29226 }
29227 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29228 {
29229 free_node(*expr_gen.node_allocator_, branch[0]);
29230 free_node(*expr_gen.node_allocator_, branch[1]);
29231
29232 return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
29233 }
29234 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29235 {
29236 free_node(*expr_gen.node_allocator_, branch[1]);
29237
29238 return branch[0];
29239 }
29240 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29241 {
29242 free_node(*expr_gen.node_allocator_, branch[1]);
29243
29244 return branch[0];
29245 }
29246 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29247 {
29248 free_node(*expr_gen.node_allocator_, branch[1]);
29249
29250 return branch[0];
29251 }
29252
29253 const bool op_addsub = (details::e_add == cobnode->operation()) ||
29254 (details::e_sub == cobnode->operation()) ;
29255
29256 if (op_addsub)
29257 {
29258 switch (operation)
29259 {
29260 case details::e_add : cobnode->set_c(cobnode->c() + c); break;
29261 case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
29262 default : return error_node();
29263 }
29264
29265 result = cobnode;
29266 }
29267 else if (details::e_mul == cobnode->operation())
29268 {
29269 switch (operation)
29270 {
29271 case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
29272 case details::e_div : cobnode->set_c(cobnode->c() / c); break;
29273 default : return error_node();
29274 }
29275
29276 result = cobnode;
29277 }
29278 else if (details::e_div == cobnode->operation())
29279 {
29280 if (details::e_mul == operation)
29281 {
29282 cobnode->set_c(cobnode->c() * c);
29283 result = cobnode;
29284 }
29285 else if (details::e_div == operation)
29286 {
29287 result = expr_gen.node_allocator_->
29288 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29289 (cobnode->c() / c, cobnode->move_branch(0));
29290
29291 free_node(*expr_gen.node_allocator_, branch[0]);
29292 }
29293 }
29294
29295 if (result)
29296 {
29297 free_node(*expr_gen.node_allocator_,branch[1]);
29298 }
29299 }
29300
29301 // c o (cob) --> cob
29302 else if (details::is_cob_node(branch[1]))
29303 {
29304 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29305
29306 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29307
29308 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29309 {
29310 free_node(*expr_gen.node_allocator_, branch[0]);
29311 free_node(*expr_gen.node_allocator_, branch[1]);
29312
29313 return expr_gen(T(0));
29314 }
29315 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29316 {
29317 free_node(*expr_gen.node_allocator_, branch[0]);
29318 free_node(*expr_gen.node_allocator_, branch[1]);
29319
29320 return expr_gen(T(0));
29321 }
29322 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29323 {
29324 free_node(*expr_gen.node_allocator_, branch[0]);
29325
29326 return branch[1];
29327 }
29328 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29329 {
29330 free_node(*expr_gen.node_allocator_, branch[0]);
29331
29332 return branch[1];
29333 }
29334
29335 if (details::e_add == cobnode->operation())
29336 {
29337 if (details::e_add == operation)
29338 {
29339 cobnode->set_c(c + cobnode->c());
29340 result = cobnode;
29341 }
29342 else if (details::e_sub == operation)
29343 {
29344 result = expr_gen.node_allocator_->
29345 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29346 (c - cobnode->c(), cobnode->move_branch(0));
29347
29348 free_node(*expr_gen.node_allocator_,branch[1]);
29349 }
29350 }
29351 else if (details::e_sub == cobnode->operation())
29352 {
29353 if (details::e_add == operation)
29354 {
29355 cobnode->set_c(c + cobnode->c());
29356 result = cobnode;
29357 }
29358 else if (details::e_sub == operation)
29359 {
29360 result = expr_gen.node_allocator_->
29361 template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
29362 (c - cobnode->c(), cobnode->move_branch(0));
29363
29364 free_node(*expr_gen.node_allocator_,branch[1]);
29365 }
29366 }
29367 else if (details::e_mul == cobnode->operation())
29368 {
29369 if (details::e_mul == operation)
29370 {
29371 cobnode->set_c(c * cobnode->c());
29372 result = cobnode;
29373 }
29374 else if (details::e_div == operation)
29375 {
29376 result = expr_gen.node_allocator_->
29377 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29378 (c / cobnode->c(), cobnode->move_branch(0));
29379
29380 free_node(*expr_gen.node_allocator_,branch[1]);
29381 }
29382 }
29383 else if (details::e_div == cobnode->operation())
29384 {
29385 if (details::e_mul == operation)
29386 {
29387 cobnode->set_c(c * cobnode->c());
29388 result = cobnode;
29389 }
29390 else if (details::e_div == operation)
29391 {
29392 result = expr_gen.node_allocator_->
29393 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29394 (c / cobnode->c(), cobnode->move_branch(0));
29395
29396 free_node(*expr_gen.node_allocator_,branch[1]);
29397 }
29398 }
29399
29400 if (result)
29401 {
29402 free_node(*expr_gen.node_allocator_,branch[0]);
29403 }
29404 }
29405
29406 return result;
29407 }
29408 };
29409
29410 struct synthesize_coboc_expression
29411 {
29412 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29413 const details::operator_type& operation,
29414 expression_node_ptr (&branch)[2])
29415 {
29416 expression_node_ptr result = error_node();
29417
29418 // (boc) o c --> boc
29419 if (details::is_boc_node(branch[0]))
29420 {
29421 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29422
29423 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29424
29425 if (details::e_add == bocnode->operation())
29426 {
29427 switch (operation)
29428 {
29429 case details::e_add : bocnode->set_c(bocnode->c() + c); break;
29430 case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
29431 default : return error_node();
29432 }
29433
29434 result = bocnode;
29435 }
29436 else if (details::e_mul == bocnode->operation())
29437 {
29438 switch (operation)
29439 {
29440 case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
29441 case details::e_div : bocnode->set_c(bocnode->c() / c); break;
29442 default : return error_node();
29443 }
29444
29445 result = bocnode;
29446 }
29447 else if (details::e_sub == bocnode->operation())
29448 {
29449 if (details::e_add == operation)
29450 {
29451 result = expr_gen.node_allocator_->
29452 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29453 (bocnode->move_branch(0), c - bocnode->c());
29454
29455 free_node(*expr_gen.node_allocator_,branch[0]);
29456 }
29457 else if (details::e_sub == operation)
29458 {
29459 bocnode->set_c(bocnode->c() + c);
29460 result = bocnode;
29461 }
29462 }
29463 else if (details::e_div == bocnode->operation())
29464 {
29465 switch (operation)
29466 {
29467 case details::e_div : bocnode->set_c(bocnode->c() * c); break;
29468 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29469 default : return error_node();
29470 }
29471
29472 result = bocnode;
29473 }
29474
29475 if (result)
29476 {
29477 free_node(*expr_gen.node_allocator_, branch[1]);
29478 }
29479 }
29480
29481 // c o (boc) --> boc
29482 else if (details::is_boc_node(branch[1]))
29483 {
29484 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
29485
29486 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29487
29488 if (details::e_add == bocnode->operation())
29489 {
29490 if (details::e_add == operation)
29491 {
29492 bocnode->set_c(c + bocnode->c());
29493 result = bocnode;
29494 }
29495 else if (details::e_sub == operation)
29496 {
29497 result = expr_gen.node_allocator_->
29498 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29499 (c - bocnode->c(), bocnode->move_branch(0));
29500
29501 free_node(*expr_gen.node_allocator_,branch[1]);
29502 }
29503 }
29504 else if (details::e_sub == bocnode->operation())
29505 {
29506 if (details::e_add == operation)
29507 {
29508 result = expr_gen.node_allocator_->
29509 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29510 (bocnode->move_branch(0), c - bocnode->c());
29511
29512 free_node(*expr_gen.node_allocator_,branch[1]);
29513 }
29514 else if (details::e_sub == operation)
29515 {
29516 result = expr_gen.node_allocator_->
29517 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29518 (c + bocnode->c(), bocnode->move_branch(0));
29519
29520 free_node(*expr_gen.node_allocator_,branch[1]);
29521 }
29522 }
29523 else if (details::e_mul == bocnode->operation())
29524 {
29525 if (details::e_mul == operation)
29526 {
29527 bocnode->set_c(c * bocnode->c());
29528 result = bocnode;
29529 }
29530 else if (details::e_div == operation)
29531 {
29532 result = expr_gen.node_allocator_->
29533 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29534 (c / bocnode->c(), bocnode->move_branch(0));
29535
29536 free_node(*expr_gen.node_allocator_,branch[1]);
29537 }
29538 }
29539 else if (details::e_div == bocnode->operation())
29540 {
29541 if (details::e_mul == operation)
29542 {
29543 bocnode->set_c(bocnode->c() / c);
29544 result = bocnode;
29545 }
29546 else if (details::e_div == operation)
29547 {
29548 result = expr_gen.node_allocator_->
29549 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29550 (c * bocnode->c(), bocnode->move_branch(0));
29551
29552 free_node(*expr_gen.node_allocator_,branch[1]);
29553 }
29554 }
29555
29556 if (result)
29557 {
29558 free_node(*expr_gen.node_allocator_,branch[0]);
29559 }
29560 }
29561
29562 return result;
29563 }
29564 };
29565
29566 #ifndef exprtk_disable_enhanced_features
29567 inline bool synthesize_expression(const details::operator_type& operation,
29568 expression_node_ptr (&branch)[2],
29569 expression_node_ptr& result)
29570 {
29571 result = error_node();
29572
29573 if (!operation_optimisable(operation))
29574 return false;
29575
29576 const std::string node_id = branch_to_id(branch);
29577
29578 const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
29579
29580 if (synthesize_map_.end() != itr)
29581 {
29582 result = itr->second((*this), operation, branch);
29583
29584 return true;
29585 }
29586 else
29587 return false;
29588 }
29589
29590 struct synthesize_vov_expression
29591 {
29592 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29593 const details::operator_type& operation,
29594 expression_node_ptr (&branch)[2])
29595 {
29596 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29597 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29598
29599 switch (operation)
29600 {
29601 #define case_stmt(op0,op1) \
29602 case op0 : return expr_gen.node_allocator_-> \
29603 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
29604 (v1, v2); \
29605
29606 basic_opr_switch_statements
29607 extended_opr_switch_statements
29608 #undef case_stmt
29609 default : return error_node();
29610 }
29611 }
29612 };
29613
29614 struct synthesize_cov_expression
29615 {
29616 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29617 const details::operator_type& operation,
29618 expression_node_ptr (&branch)[2])
29619 {
29620 const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
29621 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
29622
29623 details::free_node(*(expr_gen.node_allocator_),branch[0]);
29624
29625 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29626 return expr_gen(T(0));
29627 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29628 return expr_gen(T(0));
29629 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29630 return static_cast<details::variable_node<Type>*>(branch[1]);
29631 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29632 return static_cast<details::variable_node<Type>*>(branch[1]);
29633
29634 switch (operation)
29635 {
29636 #define case_stmt(op0,op1) \
29637 case op0 : return expr_gen.node_allocator_-> \
29638 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
29639 (c, v); \
29640
29641 basic_opr_switch_statements
29642 extended_opr_switch_statements
29643 #undef case_stmt
29644 default : return error_node();
29645 }
29646 }
29647 };
29648
29649 struct synthesize_voc_expression
29650 {
29651 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29652 const details::operator_type& operation,
29653 expression_node_ptr (&branch)[2])
29654 {
29655 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
29656 const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
29657
29658 details::free_node(*(expr_gen.node_allocator_), branch[1]);
29659
29660 if (expr_gen.cardinal_pow_optimisable(operation,c))
29661 {
29662 if (std::equal_to<T>()(T(1),c))
29663 return branch[0];
29664 else
29665 return expr_gen.cardinal_pow_optimisation(v,c);
29666 }
29667 else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29668 return expr_gen(T(0));
29669 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29670 return expr_gen(std::numeric_limits<T>::quiet_NaN());
29671 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29672 return static_cast<details::variable_node<Type>*>(branch[0]);
29673 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29674 return static_cast<details::variable_node<Type>*>(branch[0]);
29675 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29676 return static_cast<details::variable_node<Type>*>(branch[0]);
29677
29678 switch (operation)
29679 {
29680 #define case_stmt(op0,op1) \
29681 case op0 : return expr_gen.node_allocator_-> \
29682 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
29683 (v, c); \
29684
29685 basic_opr_switch_statements
29686 extended_opr_switch_statements
29687 #undef case_stmt
29688 default : return error_node();
29689 }
29690 }
29691 };
29692
29693 struct synthesize_sf3ext_expression
29694 {
29695 template <typename T0, typename T1, typename T2>
29696 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29697 const details::operator_type& sf3opr,
29698 T0 t0, T1 t1, T2 t2)
29699 {
29700 switch (sf3opr)
29701 {
29702 #define case_stmt(op) \
29703 case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
29704 allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
29705
29706 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
29707 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
29708 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
29709 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
29710 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
29711 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
29712 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
29713 case_stmt(28) case_stmt(29) case_stmt(30)
29714 #undef case_stmt
29715 default : return error_node();
29716 }
29717 }
29718
29719 template <typename T0, typename T1, typename T2>
29720 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29721 T0 t0, T1 t1, T2 t2,
29722 expression_node_ptr& result)
29723 {
29724 details::operator_type sf3opr;
29725
29726 if (!expr_gen.sf3_optimisable(id,sf3opr))
29727 return false;
29728 else
29729 result = synthesize_sf3ext_expression::template process<T0, T1, T2>
29730 (expr_gen, sf3opr, t0, t1, t2);
29731
29732 return true;
29733 }
29734 };
29735
29736 struct synthesize_sf4ext_expression
29737 {
29738 template <typename T0, typename T1, typename T2, typename T3>
29739 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29740 const details::operator_type& sf4opr,
29741 T0 t0, T1 t1, T2 t2, T3 t3)
29742 {
29743 switch (sf4opr)
29744 {
29745 #define case_stmt0(op) \
29746 case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
29747 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29748
29749
29750 #define case_stmt1(op) \
29751 case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
29752 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29753
29754 case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
29755 case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
29756 case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
29757 case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
29758 case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
29759 case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
29760 case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
29761 case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
29762 case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
29763
29764 case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
29765 case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
29766 case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
29767 case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
29768 case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
29769 case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
29770 case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
29771 case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
29772 case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
29773 case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
29774 case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
29775 case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
29776 case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
29777 case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
29778 case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
29779 case_stmt1(60) case_stmt1(61)
29780
29781 #undef case_stmt0
29782 #undef case_stmt1
29783 default : return error_node();
29784 }
29785 }
29786
29787 template <typename T0, typename T1, typename T2, typename T3>
29788 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29789 T0 t0, T1 t1, T2 t2, T3 t3,
29790 expression_node_ptr& result)
29791 {
29792 details::operator_type sf4opr;
29793
29794 if (!expr_gen.sf4_optimisable(id,sf4opr))
29795 return false;
29796 else
29797 result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
29798 (expr_gen, sf4opr, t0, t1, t2, t3);
29799
29800 return true;
29801 }
29802
29803 // T o (sf3ext)
29804 template <typename ExternalType>
29805 static inline bool compile_right(expression_generator<Type>& expr_gen,
29806 ExternalType t,
29807 const details::operator_type& operation,
29808 expression_node_ptr& sf3node,
29809 expression_node_ptr& result)
29810 {
29811 if (!details::is_sf3ext_node(sf3node))
29812 return false;
29813
29814 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29815
29816 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29817 const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
29818
29819 switch (n->type())
29820 {
29821 case details::expression_node<Type>::e_covoc : return compile_right_impl
29822 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29823 (expr_gen, id, t, sf3node, result);
29824
29825 case details::expression_node<Type>::e_covov : return compile_right_impl
29826 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29827 (expr_gen, id, t, sf3node, result);
29828
29829 case details::expression_node<Type>::e_vocov : return compile_right_impl
29830 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29831 (expr_gen, id, t, sf3node, result);
29832
29833 case details::expression_node<Type>::e_vovoc : return compile_right_impl
29834 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29835 (expr_gen, id, t, sf3node, result);
29836
29837 case details::expression_node<Type>::e_vovov : return compile_right_impl
29838 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29839 (expr_gen, id, t, sf3node, result);
29840
29841 default : return false;
29842 }
29843 }
29844
29845 // (sf3ext) o T
29846 template <typename ExternalType>
29847 static inline bool compile_left(expression_generator<Type>& expr_gen,
29848 ExternalType t,
29849 const details::operator_type& operation,
29850 expression_node_ptr& sf3node,
29851 expression_node_ptr& result)
29852 {
29853 if (!details::is_sf3ext_node(sf3node))
29854 return false;
29855
29856 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29857
29858 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29859
29860 const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
29861
29862 switch (n->type())
29863 {
29864 case details::expression_node<Type>::e_covoc : return compile_left_impl
29865 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29866 (expr_gen, id, t, sf3node, result);
29867
29868 case details::expression_node<Type>::e_covov : return compile_left_impl
29869 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29870 (expr_gen, id, t, sf3node, result);
29871
29872 case details::expression_node<Type>::e_vocov : return compile_left_impl
29873 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29874 (expr_gen, id, t, sf3node, result);
29875
29876 case details::expression_node<Type>::e_vovoc : return compile_left_impl
29877 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29878 (expr_gen, id, t, sf3node, result);
29879
29880 case details::expression_node<Type>::e_vovov : return compile_left_impl
29881 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29882 (expr_gen, id, t, sf3node, result);
29883
29884 default : return false;
29885 }
29886 }
29887
29888 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29889 static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
29890 const std::string& id,
29891 ExternalType t,
29892 expression_node_ptr& node,
29893 expression_node_ptr& result)
29894 {
29895 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29896
29897 if (n)
29898 {
29899 T0 t0 = n->t0();
29900 T1 t1 = n->t1();
29901 T2 t2 = n->t2();
29902
29903 return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
29904 (expr_gen, id, t, t0, t1, t2, result);
29905 }
29906 else
29907 return false;
29908 }
29909
29910 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29911 static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
29912 const std::string& id,
29913 ExternalType t,
29914 expression_node_ptr& node,
29915 expression_node_ptr& result)
29916 {
29917 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29918
29919 if (n)
29920 {
29921 T0 t0 = n->t0();
29922 T1 t1 = n->t1();
29923 T2 t2 = n->t2();
29924
29925 return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
29926 (expr_gen, id, t0, t1, t2, t, result);
29927 }
29928 else
29929 return false;
29930 }
29931 };
29932
29933 struct synthesize_vovov_expression0
29934 {
29935 typedef typename vovov_t::type0 node_type;
29936 typedef typename vovov_t::sf3_type sf3_type;
29937
29938 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29939 const details::operator_type& operation,
29940 expression_node_ptr (&branch)[2])
29941 {
29942 // (v0 o0 v1) o1 (v2)
29943 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
29944 const Type& v0 = vov->v0();
29945 const Type& v1 = vov->v1();
29946 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29947 const details::operator_type o0 = vov->operation();
29948 const details::operator_type o1 = operation;
29949
29950 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29951 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29952
29953 details::free_node(*(expr_gen.node_allocator_),branch[0]);
29954
29955 expression_node_ptr result = error_node();
29956
29957 if (expr_gen.parser_->settings_.strength_reduction_enabled())
29958 {
29959 // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
29960 if ((details::e_div == o0) && (details::e_div == o1))
29961 {
29962 const bool synthesis_result =
29963 synthesize_sf3ext_expression::
29964 template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
29965
29966 exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
29967
29968 return (synthesis_result) ? result : error_node();
29969 }
29970 }
29971
29972 const bool synthesis_result =
29973 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
29974 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
29975
29976 if (synthesis_result)
29977 return result;
29978 else if (!expr_gen.valid_operator(o0,f0))
29979 return error_node();
29980 else if (!expr_gen.valid_operator(o1,f1))
29981 return error_node();
29982 else
29983 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
29984 }
29985
29986 static inline std::string id(expression_generator<Type>& expr_gen,
29987 const details::operator_type o0, const details::operator_type o1)
29988 {
29989 return details::build_string()
29990 << "(t" << expr_gen.to_str(o0)
29991 << "t)" << expr_gen.to_str(o1)
29992 << "t";
29993 }
29994 };
29995
29996 struct synthesize_vovov_expression1
29997 {
29998 typedef typename vovov_t::type1 node_type;
29999 typedef typename vovov_t::sf3_type sf3_type;
30000
30001 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30002 const details::operator_type& operation,
30003 expression_node_ptr (&branch)[2])
30004 {
30005 // (v0) o0 (v1 o1 v2)
30006 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30007 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30008 const Type& v1 = vov->v0();
30009 const Type& v2 = vov->v1();
30010 const details::operator_type o0 = operation;
30011 const details::operator_type o1 = vov->operation();
30012
30013 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30014 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30015
30016 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30017
30018 expression_node_ptr result = error_node();
30019
30020 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30021 {
30022 // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
30023 if ((details::e_div == o0) && (details::e_div == o1))
30024 {
30025 const bool synthesis_result =
30026 synthesize_sf3ext_expression::
30027 template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
30028
30029 exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
30030
30031 return (synthesis_result) ? result : error_node();
30032 }
30033 }
30034
30035 const bool synthesis_result =
30036 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
30037 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
30038
30039 if (synthesis_result)
30040 return result;
30041 else if (!expr_gen.valid_operator(o0,f0))
30042 return error_node();
30043 else if (!expr_gen.valid_operator(o1,f1))
30044 return error_node();
30045 else
30046 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
30047 }
30048
30049 static inline std::string id(expression_generator<Type>& expr_gen,
30050 const details::operator_type o0, const details::operator_type o1)
30051 {
30052 return details::build_string()
30053 << "t" << expr_gen.to_str(o0)
30054 << "(t" << expr_gen.to_str(o1)
30055 << "t)";
30056 }
30057 };
30058
30059 struct synthesize_vovoc_expression0
30060 {
30061 typedef typename vovoc_t::type0 node_type;
30062 typedef typename vovoc_t::sf3_type sf3_type;
30063
30064 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30065 const details::operator_type& operation,
30066 expression_node_ptr (&branch)[2])
30067 {
30068 // (v0 o0 v1) o1 (c)
30069 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30070 const Type& v0 = vov->v0();
30071 const Type& v1 = vov->v1();
30072 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30073 const details::operator_type o0 = vov->operation();
30074 const details::operator_type o1 = operation;
30075
30076 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30077 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30078
30079 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30080 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30081
30082 expression_node_ptr result = error_node();
30083
30084 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30085 {
30086 // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
30087 if ((details::e_div == o0) && (details::e_div == o1))
30088 {
30089 const bool synthesis_result =
30090 synthesize_sf3ext_expression::
30091 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30092
30093 exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
30094
30095 return (synthesis_result) ? result : error_node();
30096 }
30097 }
30098
30099 const bool synthesis_result =
30100 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30101 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30102
30103 if (synthesis_result)
30104 return result;
30105 else if (!expr_gen.valid_operator(o0,f0))
30106 return error_node();
30107 else if (!expr_gen.valid_operator(o1,f1))
30108 return error_node();
30109 else
30110 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30111 }
30112
30113 static inline std::string id(expression_generator<Type>& expr_gen,
30114 const details::operator_type o0, const details::operator_type o1)
30115 {
30116 return details::build_string()
30117 << "(t" << expr_gen.to_str(o0)
30118 << "t)" << expr_gen.to_str(o1)
30119 << "t";
30120 }
30121 };
30122
30123 struct synthesize_vovoc_expression1
30124 {
30125 typedef typename vovoc_t::type1 node_type;
30126 typedef typename vovoc_t::sf3_type sf3_type;
30127
30128 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30129 const details::operator_type& operation,
30130 expression_node_ptr (&branch)[2])
30131 {
30132 // (v0) o0 (v1 o1 c)
30133 const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
30134 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30135 const Type& v1 = voc->v();
30136 const Type c = voc->c();
30137 const details::operator_type o0 = operation;
30138 const details::operator_type o1 = voc->operation();
30139
30140 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30141 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30142
30143 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30144
30145 expression_node_ptr result = error_node();
30146
30147 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30148 {
30149 // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
30150 if ((details::e_div == o0) && (details::e_div == o1))
30151 {
30152 const bool synthesis_result =
30153 synthesize_sf3ext_expression::
30154 template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
30155
30156 exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
30157
30158 return (synthesis_result) ? result : error_node();
30159 }
30160 }
30161
30162 const bool synthesis_result =
30163 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30164 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30165
30166 if (synthesis_result)
30167 return result;
30168 else if (!expr_gen.valid_operator(o0,f0))
30169 return error_node();
30170 else if (!expr_gen.valid_operator(o1,f1))
30171 return error_node();
30172 else
30173 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30174 }
30175
30176 static inline std::string id(expression_generator<Type>& expr_gen,
30177 const details::operator_type o0, const details::operator_type o1)
30178 {
30179 return details::build_string()
30180 << "t" << expr_gen.to_str(o0)
30181 << "(t" << expr_gen.to_str(o1)
30182 << "t)";
30183 }
30184 };
30185
30186 struct synthesize_vocov_expression0
30187 {
30188 typedef typename vocov_t::type0 node_type;
30189 typedef typename vocov_t::sf3_type sf3_type;
30190
30191 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30192 const details::operator_type& operation,
30193 expression_node_ptr (&branch)[2])
30194 {
30195 // (v0 o0 c) o1 (v1)
30196 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30197 const Type& v0 = voc->v();
30198 const Type c = voc->c();
30199 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30200 const details::operator_type o0 = voc->operation();
30201 const details::operator_type o1 = operation;
30202
30203 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30204 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30205
30206 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30207
30208 expression_node_ptr result = error_node();
30209
30210 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30211 {
30212 // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
30213 if ((details::e_div == o0) && (details::e_div == o1))
30214 {
30215 const bool synthesis_result =
30216 synthesize_sf3ext_expression::
30217 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30218
30219 exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
30220
30221 return (synthesis_result) ? result : error_node();
30222 }
30223 }
30224
30225 const bool synthesis_result =
30226 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30227 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30228
30229 if (synthesis_result)
30230 return result;
30231 else if (!expr_gen.valid_operator(o0,f0))
30232 return error_node();
30233 else if (!expr_gen.valid_operator(o1,f1))
30234 return error_node();
30235 else
30236 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30237 }
30238
30239 static inline std::string id(expression_generator<Type>& expr_gen,
30240 const details::operator_type o0, const details::operator_type o1)
30241 {
30242 return details::build_string()
30243 << "(t" << expr_gen.to_str(o0)
30244 << "t)" << expr_gen.to_str(o1)
30245 << "t";
30246 }
30247 };
30248
30249 struct synthesize_vocov_expression1
30250 {
30251 typedef typename vocov_t::type1 node_type;
30252 typedef typename vocov_t::sf3_type sf3_type;
30253
30254 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30255 const details::operator_type& operation,
30256 expression_node_ptr (&branch)[2])
30257 {
30258 // (v0) o0 (c o1 v1)
30259 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30260 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30261 const Type c = cov->c();
30262 const Type& v1 = cov->v();
30263 const details::operator_type o0 = operation;
30264 const details::operator_type o1 = cov->operation();
30265
30266 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30267 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30268
30269 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30270
30271 expression_node_ptr result = error_node();
30272
30273 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30274 {
30275 // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
30276 if ((details::e_div == o0) && (details::e_div == o1))
30277 {
30278 const bool synthesis_result =
30279 synthesize_sf3ext_expression::
30280 template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
30281
30282 exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
30283
30284 return (synthesis_result) ? result : error_node();
30285 }
30286 }
30287
30288 const bool synthesis_result =
30289 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30290 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30291
30292 if (synthesis_result)
30293 return result;
30294 else if (!expr_gen.valid_operator(o0,f0))
30295 return error_node();
30296 else if (!expr_gen.valid_operator(o1,f1))
30297 return error_node();
30298 else
30299 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30300 }
30301
30302 static inline std::string id(expression_generator<Type>& expr_gen,
30303 const details::operator_type o0, const details::operator_type o1)
30304 {
30305 return details::build_string()
30306 << "t" << expr_gen.to_str(o0)
30307 << "(t" << expr_gen.to_str(o1)
30308 << "t)";
30309 }
30310 };
30311
30312 struct synthesize_covov_expression0
30313 {
30314 typedef typename covov_t::type0 node_type;
30315 typedef typename covov_t::sf3_type sf3_type;
30316
30317 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30318 const details::operator_type& operation,
30319 expression_node_ptr (&branch)[2])
30320 {
30321 // (c o0 v0) o1 (v1)
30322 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30323 const Type c = cov->c();
30324 const Type& v0 = cov->v();
30325 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30326 const details::operator_type o0 = cov->operation();
30327 const details::operator_type o1 = operation;
30328
30329 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30330 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30331
30332 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30333
30334 expression_node_ptr result = error_node();
30335
30336 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30337 {
30338 // (c / v0) / v1 --> (covov) c / (v0 * v1)
30339 if ((details::e_div == o0) && (details::e_div == o1))
30340 {
30341 const bool synthesis_result =
30342 synthesize_sf3ext_expression::
30343 template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
30344
30345 exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
30346
30347 return (synthesis_result) ? result : error_node();
30348 }
30349 }
30350
30351 const bool synthesis_result =
30352 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30353 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30354
30355 if (synthesis_result)
30356 return result;
30357 else if (!expr_gen.valid_operator(o0,f0))
30358 return error_node();
30359 else if (!expr_gen.valid_operator(o1,f1))
30360 return error_node();
30361 else
30362 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30363 }
30364
30365 static inline std::string id(expression_generator<Type>& expr_gen,
30366 const details::operator_type o0, const details::operator_type o1)
30367 {
30368 return details::build_string()
30369 << "(t" << expr_gen.to_str(o0)
30370 << "t)" << expr_gen.to_str(o1)
30371 << "t";
30372 }
30373 };
30374
30375 struct synthesize_covov_expression1
30376 {
30377 typedef typename covov_t::type1 node_type;
30378 typedef typename covov_t::sf3_type sf3_type;
30379
30380 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30381 const details::operator_type& operation,
30382 expression_node_ptr (&branch)[2])
30383 {
30384 // (c) o0 (v0 o1 v1)
30385 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30386 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30387 const Type& v0 = vov->v0();
30388 const Type& v1 = vov->v1();
30389 const details::operator_type o0 = operation;
30390 const details::operator_type o1 = vov->operation();
30391
30392 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30393 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30394
30395 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30396 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30397
30398 expression_node_ptr result = error_node();
30399
30400 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30401 {
30402 // c / (v0 / v1) --> (covov) (c * v1) / v0
30403 if ((details::e_div == o0) && (details::e_div == o1))
30404 {
30405 const bool synthesis_result =
30406 synthesize_sf3ext_expression::
30407 template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
30408
30409 exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
30410
30411 return (synthesis_result) ? result : error_node();
30412 }
30413 }
30414
30415 const bool synthesis_result =
30416 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30417 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30418
30419 if (synthesis_result)
30420 return result;
30421 else if (!expr_gen.valid_operator(o0,f0))
30422 return error_node();
30423 else if (!expr_gen.valid_operator(o1,f1))
30424 return error_node();
30425 else
30426 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30427 }
30428
30429 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30430 {
30431 return details::build_string()
30432 << "t" << expr_gen.to_str(o0)
30433 << "(t" << expr_gen.to_str(o1)
30434 << "t)";
30435 }
30436 };
30437
30438 struct synthesize_covoc_expression0
30439 {
30440 typedef typename covoc_t::type0 node_type;
30441 typedef typename covoc_t::sf3_type sf3_type;
30442
30443 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30444 const details::operator_type& operation,
30445 expression_node_ptr (&branch)[2])
30446 {
30447 // (c0 o0 v) o1 (c1)
30448 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30449 const Type c0 = cov->c();
30450 const Type& v = cov->v();
30451 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30452 const details::operator_type o0 = cov->operation();
30453 const details::operator_type o1 = operation;
30454
30455 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30456 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30457
30458 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30459 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30460
30461 expression_node_ptr result = error_node();
30462
30463 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30464 {
30465 // (c0 + v) + c1 --> (cov) (c0 + c1) + v
30466 if ((details::e_add == o0) && (details::e_add == o1))
30467 {
30468 exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
30469
30470 return expr_gen.node_allocator_->
30471 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30472 }
30473 // (c0 + v) - c1 --> (cov) (c0 - c1) + v
30474 else if ((details::e_add == o0) && (details::e_sub == o1))
30475 {
30476 exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
30477
30478 return expr_gen.node_allocator_->
30479 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30480 }
30481 // (c0 - v) + c1 --> (cov) (c0 + c1) - v
30482 else if ((details::e_sub == o0) && (details::e_add == o1))
30483 {
30484 exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
30485
30486 return expr_gen.node_allocator_->
30487 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30488 }
30489 // (c0 - v) - c1 --> (cov) (c0 - c1) - v
30490 else if ((details::e_sub == o0) && (details::e_sub == o1))
30491 {
30492 exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
30493
30494 return expr_gen.node_allocator_->
30495 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30496 }
30497 // (c0 * v) * c1 --> (cov) (c0 * c1) * v
30498 else if ((details::e_mul == o0) && (details::e_mul == o1))
30499 {
30500 exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
30501
30502 return expr_gen.node_allocator_->
30503 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30504 }
30505 // (c0 * v) / c1 --> (cov) (c0 / c1) * v
30506 else if ((details::e_mul == o0) && (details::e_div == o1))
30507 {
30508 exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
30509
30510 return expr_gen.node_allocator_->
30511 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30512 }
30513 // (c0 / v) * c1 --> (cov) (c0 * c1) / v
30514 else if ((details::e_div == o0) && (details::e_mul == o1))
30515 {
30516 exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
30517
30518 return expr_gen.node_allocator_->
30519 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30520 }
30521 // (c0 / v) / c1 --> (cov) (c0 / c1) / v
30522 else if ((details::e_div == o0) && (details::e_div == o1))
30523 {
30524 exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
30525
30526 return expr_gen.node_allocator_->
30527 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30528 }
30529 }
30530
30531 const bool synthesis_result =
30532 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30533 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30534
30535 if (synthesis_result)
30536 return result;
30537 else if (!expr_gen.valid_operator(o0,f0))
30538 return error_node();
30539 else if (!expr_gen.valid_operator(o1,f1))
30540 return error_node();
30541 else
30542 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30543 }
30544
30545 static inline std::string id(expression_generator<Type>& expr_gen,
30546 const details::operator_type o0, const details::operator_type o1)
30547 {
30548 return details::build_string()
30549 << "(t" << expr_gen.to_str(o0)
30550 << "t)" << expr_gen.to_str(o1)
30551 << "t";
30552 }
30553 };
30554
30555 struct synthesize_covoc_expression1
30556 {
30557 typedef typename covoc_t::type1 node_type;
30558 typedef typename covoc_t::sf3_type sf3_type;
30559
30560 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30561 const details::operator_type& operation,
30562 expression_node_ptr (&branch)[2])
30563 {
30564 // (c0) o0 (v o1 c1)
30565 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
30566 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30567 const Type& v = voc->v();
30568 const Type c1 = voc->c();
30569 const details::operator_type o0 = operation;
30570 const details::operator_type o1 = voc->operation();
30571
30572 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30573 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30574
30575 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30576 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30577
30578 expression_node_ptr result = error_node();
30579
30580 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30581 {
30582 // (c0) + (v + c1) --> (cov) (c0 + c1) + v
30583 if ((details::e_add == o0) && (details::e_add == o1))
30584 {
30585 exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
30586
30587 return expr_gen.node_allocator_->
30588 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30589 }
30590 // (c0) + (v - c1) --> (cov) (c0 - c1) + v
30591 else if ((details::e_add == o0) && (details::e_sub == o1))
30592 {
30593 exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
30594
30595 return expr_gen.node_allocator_->
30596 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30597 }
30598 // (c0) - (v + c1) --> (cov) (c0 - c1) - v
30599 else if ((details::e_sub == o0) && (details::e_add == o1))
30600 {
30601 exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
30602
30603 return expr_gen.node_allocator_->
30604 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30605 }
30606 // (c0) - (v - c1) --> (cov) (c0 + c1) - v
30607 else if ((details::e_sub == o0) && (details::e_sub == o1))
30608 {
30609 exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
30610
30611 return expr_gen.node_allocator_->
30612 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30613 }
30614 // (c0) * (v * c1) --> (voc) v * (c0 * c1)
30615 else if ((details::e_mul == o0) && (details::e_mul == o1))
30616 {
30617 exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
30618
30619 return expr_gen.node_allocator_->
30620 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30621 }
30622 // (c0) * (v / c1) --> (cov) (c0 / c1) * v
30623 else if ((details::e_mul == o0) && (details::e_div == o1))
30624 {
30625 exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
30626
30627 return expr_gen.node_allocator_->
30628 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30629 }
30630 // (c0) / (v * c1) --> (cov) (c0 / c1) / v
30631 else if ((details::e_div == o0) && (details::e_mul == o1))
30632 {
30633 exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
30634
30635 return expr_gen.node_allocator_->
30636 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30637 }
30638 // (c0) / (v / c1) --> (cov) (c0 * c1) / v
30639 else if ((details::e_div == o0) && (details::e_div == o1))
30640 {
30641 exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
30642
30643 return expr_gen.node_allocator_->
30644 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30645 }
30646 }
30647
30648 const bool synthesis_result =
30649 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30650 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30651
30652 if (synthesis_result)
30653 return result;
30654 else if (!expr_gen.valid_operator(o0,f0))
30655 return error_node();
30656 else if (!expr_gen.valid_operator(o1,f1))
30657 return error_node();
30658 else
30659 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30660 }
30661
30662 static inline std::string id(expression_generator<Type>& expr_gen,
30663 const details::operator_type o0, const details::operator_type o1)
30664 {
30665 return details::build_string()
30666 << "t" << expr_gen.to_str(o0)
30667 << "(t" << expr_gen.to_str(o1)
30668 << "t)";
30669 }
30670 };
30671
30672 struct synthesize_cocov_expression0
30673 {
30674 typedef typename cocov_t::type0 node_type;
30675 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30676 {
30677 // (c0 o0 c1) o1 (v) - Not possible.
30678 return error_node();
30679 }
30680 };
30681
30682 struct synthesize_cocov_expression1
30683 {
30684 typedef typename cocov_t::type1 node_type;
30685 typedef typename cocov_t::sf3_type sf3_type;
30686
30687 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30688 const details::operator_type& operation,
30689 expression_node_ptr (&branch)[2])
30690 {
30691 // (c0) o0 (c1 o1 v)
30692 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30693 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30694 const Type c1 = cov->c();
30695 const Type& v = cov->v();
30696 const details::operator_type o0 = operation;
30697 const details::operator_type o1 = cov->operation();
30698
30699 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30700 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30701
30702 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30703 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30704
30705 expression_node_ptr result = error_node();
30706
30707 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30708 {
30709 // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
30710 if ((details::e_add == o0) && (details::e_add == o1))
30711 {
30712 exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
30713
30714 return expr_gen.node_allocator_->
30715 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30716 }
30717 // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
30718 else if ((details::e_add == o0) && (details::e_sub == o1))
30719 {
30720 exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
30721
30722 return expr_gen.node_allocator_->
30723 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30724 }
30725 // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
30726 else if ((details::e_sub == o0) && (details::e_add == o1))
30727 {
30728 exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
30729
30730 return expr_gen.node_allocator_->
30731 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30732 }
30733 // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
30734 else if ((details::e_sub == o0) && (details::e_sub == o1))
30735 {
30736 exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
30737
30738 return expr_gen.node_allocator_->
30739 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30740 }
30741 // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
30742 else if ((details::e_mul == o0) && (details::e_mul == o1))
30743 {
30744 exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
30745
30746 return expr_gen.node_allocator_->
30747 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30748 }
30749 // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
30750 else if ((details::e_mul == o0) && (details::e_div == o1))
30751 {
30752 exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
30753
30754 return expr_gen.node_allocator_->
30755 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30756 }
30757 // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
30758 else if ((details::e_div == o0) && (details::e_mul == o1))
30759 {
30760 exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
30761
30762 return expr_gen.node_allocator_->
30763 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30764 }
30765 // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
30766 else if ((details::e_div == o0) && (details::e_div == o1))
30767 {
30768 exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
30769
30770 return expr_gen.node_allocator_->
30771 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30772 }
30773 }
30774
30775 const bool synthesis_result =
30776 synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
30777 (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
30778
30779 if (synthesis_result)
30780 return result;
30781 else if (!expr_gen.valid_operator(o0,f0))
30782 return error_node();
30783 else if (!expr_gen.valid_operator(o1,f1))
30784 return error_node();
30785 else
30786 return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
30787 }
30788
30789 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30790 {
30791 return details::build_string()
30792 << "t" << expr_gen.to_str(o0)
30793 << "(t" << expr_gen.to_str(o1)
30794 << "t)";
30795 }
30796 };
30797
30798 struct synthesize_vococ_expression0
30799 {
30800 typedef typename vococ_t::type0 node_type;
30801 typedef typename vococ_t::sf3_type sf3_type;
30802
30803 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30804 const details::operator_type& operation,
30805 expression_node_ptr (&branch)[2])
30806 {
30807 // (v o0 c0) o1 (c1)
30808 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30809 const Type& v = voc->v();
30810 const Type& c0 = voc->c();
30811 const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30812 const details::operator_type o0 = voc->operation();
30813 const details::operator_type o1 = operation;
30814
30815 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30816 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30817
30818 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30819 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30820
30821 expression_node_ptr result = error_node();
30822
30823 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30824 {
30825 // (v + c0) + c1 --> (voc) v + (c0 + c1)
30826 if ((details::e_add == o0) && (details::e_add == o1))
30827 {
30828 exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
30829
30830 return expr_gen.node_allocator_->
30831 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
30832 }
30833 // (v + c0) - c1 --> (voc) v + (c0 - c1)
30834 else if ((details::e_add == o0) && (details::e_sub == o1))
30835 {
30836 exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
30837
30838 return expr_gen.node_allocator_->
30839 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
30840 }
30841 // (v - c0) + c1 --> (voc) v - (c0 + c1)
30842 else if ((details::e_sub == o0) && (details::e_add == o1))
30843 {
30844 exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
30845
30846 return expr_gen.node_allocator_->
30847 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
30848 }
30849 // (v - c0) - c1 --> (voc) v - (c0 + c1)
30850 else if ((details::e_sub == o0) && (details::e_sub == o1))
30851 {
30852 exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
30853
30854 return expr_gen.node_allocator_->
30855 template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
30856 }
30857 // (v * c0) * c1 --> (voc) v * (c0 * c1)
30858 else if ((details::e_mul == o0) && (details::e_mul == o1))
30859 {
30860 exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
30861
30862 return expr_gen.node_allocator_->
30863 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
30864 }
30865 // (v * c0) / c1 --> (voc) v * (c0 / c1)
30866 else if ((details::e_mul == o0) && (details::e_div == o1))
30867 {
30868 exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
30869
30870 return expr_gen.node_allocator_->
30871 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
30872 }
30873 // (v / c0) * c1 --> (voc) v * (c1 / c0)
30874 else if ((details::e_div == o0) && (details::e_mul == o1))
30875 {
30876 exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
30877
30878 return expr_gen.node_allocator_->
30879 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
30880 }
30881 // (v / c0) / c1 --> (voc) v / (c0 * c1)
30882 else if ((details::e_div == o0) && (details::e_div == o1))
30883 {
30884 exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
30885
30886 return expr_gen.node_allocator_->
30887 template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
30888 }
30889 // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
30890 else if ((details::e_pow == o0) && (details::e_pow == o1))
30891 {
30892 exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
30893
30894 return expr_gen.node_allocator_->
30895 template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
30896 }
30897 }
30898
30899 const bool synthesis_result =
30900 synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
30901 (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
30902
30903 if (synthesis_result)
30904 return result;
30905 else if (!expr_gen.valid_operator(o0,f0))
30906 return error_node();
30907 else if (!expr_gen.valid_operator(o1,f1))
30908 return error_node();
30909 else
30910 return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
30911 }
30912
30913 static inline std::string id(expression_generator<Type>& expr_gen,
30914 const details::operator_type o0, const details::operator_type o1)
30915 {
30916 return details::build_string()
30917 << "(t" << expr_gen.to_str(o0)
30918 << "t)" << expr_gen.to_str(o1)
30919 << "t";
30920 }
30921 };
30922
30923 struct synthesize_vococ_expression1
30924 {
30925 typedef typename vococ_t::type0 node_type;
30926
30927 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30928 {
30929 // (v) o0 (c0 o1 c1) - Not possible.
30930 exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
30931 return error_node();
30932 }
30933 };
30934
30935 struct synthesize_vovovov_expression0
30936 {
30937 typedef typename vovovov_t::type0 node_type;
30938 typedef typename vovovov_t::sf4_type sf4_type;
30939 typedef typename node_type::T0 T0;
30940 typedef typename node_type::T1 T1;
30941 typedef typename node_type::T2 T2;
30942 typedef typename node_type::T3 T3;
30943
30944 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30945 const details::operator_type& operation,
30946 expression_node_ptr (&branch)[2])
30947 {
30948 // (v0 o0 v1) o1 (v2 o2 v3)
30949 const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
30950 const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
30951 const Type& v0 = vov0->v0();
30952 const Type& v1 = vov0->v1();
30953 const Type& v2 = vov1->v0();
30954 const Type& v3 = vov1->v1();
30955 const details::operator_type o0 = vov0->operation();
30956 const details::operator_type o1 = operation;
30957 const details::operator_type o2 = vov1->operation();
30958
30959 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30960 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30961 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
30962
30963 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30964 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30965
30966 expression_node_ptr result = error_node();
30967
30968 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30969 {
30970 // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
30971 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
30972 {
30973 const bool synthesis_result =
30974 synthesize_sf4ext_expression::
30975 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
30976
30977 exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
30978
30979 return (synthesis_result) ? result : error_node();
30980 }
30981 // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
30982 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
30983 {
30984 const bool synthesis_result =
30985 synthesize_sf4ext_expression::
30986 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
30987
30988 exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
30989
30990 return (synthesis_result) ? result : error_node();
30991 }
30992 // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
30993 else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
30994 {
30995 const bool synthesis_result =
30996 synthesize_sf4ext_expression::
30997 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
30998
30999 exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
31000
31001 return (synthesis_result) ? result : error_node();
31002 }
31003 // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31004 else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
31005 {
31006 const bool synthesis_result =
31007 synthesize_sf4ext_expression::
31008 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
31009
31010 exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
31011
31012 return (synthesis_result) ? result : error_node();
31013 }
31014 // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
31015 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31016 {
31017 const bool synthesis_result =
31018 synthesize_sf4ext_expression::
31019 template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
31020
31021 exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
31022
31023 return (synthesis_result) ? result : error_node();
31024 }
31025 }
31026
31027 const bool synthesis_result =
31028 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31029 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
31030
31031 if (synthesis_result)
31032 return result;
31033 else if (!expr_gen.valid_operator(o0,f0))
31034 return error_node();
31035 else if (!expr_gen.valid_operator(o1,f1))
31036 return error_node();
31037 else if (!expr_gen.valid_operator(o2,f2))
31038 return error_node();
31039 else
31040 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
31041 }
31042
31043 static inline std::string id(expression_generator<Type>& expr_gen,
31044 const details::operator_type o0,
31045 const details::operator_type o1,
31046 const details::operator_type o2)
31047 {
31048 return details::build_string()
31049 << "(t" << expr_gen.to_str(o0)
31050 << "t)" << expr_gen.to_str(o1)
31051 << "(t" << expr_gen.to_str(o2)
31052 << "t)";
31053 }
31054 };
31055
31056 struct synthesize_vovovoc_expression0
31057 {
31058 typedef typename vovovoc_t::type0 node_type;
31059 typedef typename vovovoc_t::sf4_type sf4_type;
31060 typedef typename node_type::T0 T0;
31061 typedef typename node_type::T1 T1;
31062 typedef typename node_type::T2 T2;
31063 typedef typename node_type::T3 T3;
31064
31065 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31066 const details::operator_type& operation,
31067 expression_node_ptr (&branch)[2])
31068 {
31069 // (v0 o0 v1) o1 (v2 o2 c)
31070 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31071 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31072 const Type& v0 = vov->v0();
31073 const Type& v1 = vov->v1();
31074 const Type& v2 = voc->v ();
31075 const Type c = voc->c ();
31076 const details::operator_type o0 = vov->operation();
31077 const details::operator_type o1 = operation;
31078 const details::operator_type o2 = voc->operation();
31079
31080 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31081 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31082 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31083
31084 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31085 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31086
31087 expression_node_ptr result = error_node();
31088
31089 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31090 {
31091 // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
31092 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31093 {
31094 const bool synthesis_result =
31095 synthesize_sf4ext_expression::
31096 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31097
31098 exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31099
31100 return (synthesis_result) ? result : error_node();
31101 }
31102 // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
31103 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31104 {
31105 const bool synthesis_result =
31106 synthesize_sf4ext_expression::
31107 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31108
31109 exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31110
31111 return (synthesis_result) ? result : error_node();
31112 }
31113 }
31114
31115 const bool synthesis_result =
31116 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31117 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
31118
31119 if (synthesis_result)
31120 return result;
31121 else if (!expr_gen.valid_operator(o0,f0))
31122 return error_node();
31123 else if (!expr_gen.valid_operator(o1,f1))
31124 return error_node();
31125 else if (!expr_gen.valid_operator(o2,f2))
31126 return error_node();
31127 else
31128 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
31129 }
31130
31131 static inline std::string id(expression_generator<Type>& expr_gen,
31132 const details::operator_type o0,
31133 const details::operator_type o1,
31134 const details::operator_type o2)
31135 {
31136 return details::build_string()
31137 << "(t" << expr_gen.to_str(o0)
31138 << "t)" << expr_gen.to_str(o1)
31139 << "(t" << expr_gen.to_str(o2)
31140 << "t)";
31141 }
31142 };
31143
31144 struct synthesize_vovocov_expression0
31145 {
31146 typedef typename vovocov_t::type0 node_type;
31147 typedef typename vovocov_t::sf4_type sf4_type;
31148 typedef typename node_type::T0 T0;
31149 typedef typename node_type::T1 T1;
31150 typedef typename node_type::T2 T2;
31151 typedef typename node_type::T3 T3;
31152
31153 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31154 const details::operator_type& operation,
31155 expression_node_ptr (&branch)[2])
31156 {
31157 // (v0 o0 v1) o1 (c o2 v2)
31158 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31159 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31160 const Type& v0 = vov->v0();
31161 const Type& v1 = vov->v1();
31162 const Type& v2 = cov->v ();
31163 const Type c = cov->c ();
31164 const details::operator_type o0 = vov->operation();
31165 const details::operator_type o1 = operation;
31166 const details::operator_type o2 = cov->operation();
31167
31168 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31169 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31170 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31171
31172 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31173 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31174
31175 expression_node_ptr result = error_node();
31176
31177 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31178 {
31179 // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
31180 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31181 {
31182 const bool synthesis_result =
31183 synthesize_sf4ext_expression::
31184 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31185
31186 exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31187
31188 return (synthesis_result) ? result : error_node();
31189 }
31190 // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
31191 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31192 {
31193 const bool synthesis_result =
31194 synthesize_sf4ext_expression::
31195 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31196
31197 exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31198
31199 return (synthesis_result) ? result : error_node();
31200 }
31201 }
31202
31203 const bool synthesis_result =
31204 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31205 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
31206
31207 if (synthesis_result)
31208 return result;
31209 else if (!expr_gen.valid_operator(o0,f0))
31210 return error_node();
31211 else if (!expr_gen.valid_operator(o1,f1))
31212 return error_node();
31213 else if (!expr_gen.valid_operator(o2,f2))
31214 return error_node();
31215 else
31216 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
31217 }
31218
31219 static inline std::string id(expression_generator<Type>& expr_gen,
31220 const details::operator_type o0,
31221 const details::operator_type o1,
31222 const details::operator_type o2)
31223 {
31224 return details::build_string()
31225 << "(t" << expr_gen.to_str(o0)
31226 << "t)" << expr_gen.to_str(o1)
31227 << "(t" << expr_gen.to_str(o2)
31228 << "t)";
31229 }
31230 };
31231
31232 struct synthesize_vocovov_expression0
31233 {
31234 typedef typename vocovov_t::type0 node_type;
31235 typedef typename vocovov_t::sf4_type sf4_type;
31236 typedef typename node_type::T0 T0;
31237 typedef typename node_type::T1 T1;
31238 typedef typename node_type::T2 T2;
31239 typedef typename node_type::T3 T3;
31240
31241 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31242 const details::operator_type& operation,
31243 expression_node_ptr (&branch)[2])
31244 {
31245 // (v0 o0 c) o1 (v1 o2 v2)
31246 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31247 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31248 const Type c = voc->c ();
31249 const Type& v0 = voc->v ();
31250 const Type& v1 = vov->v0();
31251 const Type& v2 = vov->v1();
31252 const details::operator_type o0 = voc->operation();
31253 const details::operator_type o1 = operation;
31254 const details::operator_type o2 = vov->operation();
31255
31256 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31257 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31258 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31259
31260 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31261 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31262
31263 expression_node_ptr result = error_node();
31264
31265 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31266 {
31267 // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
31268 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31269 {
31270 const bool synthesis_result =
31271 synthesize_sf4ext_expression::
31272 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
31273
31274 exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
31275
31276 return (synthesis_result) ? result : error_node();
31277 }
31278 // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
31279 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31280 {
31281 const bool synthesis_result =
31282 synthesize_sf4ext_expression::
31283 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
31284
31285 exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
31286
31287 return (synthesis_result) ? result : error_node();
31288 }
31289 }
31290
31291 const bool synthesis_result =
31292 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31293 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
31294
31295 if (synthesis_result)
31296 return result;
31297 else if (!expr_gen.valid_operator(o0,f0))
31298 return error_node();
31299 else if (!expr_gen.valid_operator(o1,f1))
31300 return error_node();
31301 else if (!expr_gen.valid_operator(o2,f2))
31302 return error_node();
31303 else
31304 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
31305 }
31306
31307 static inline std::string id(expression_generator<Type>& expr_gen,
31308 const details::operator_type o0,
31309 const details::operator_type o1,
31310 const details::operator_type o2)
31311 {
31312 return details::build_string()
31313 << "(t" << expr_gen.to_str(o0)
31314 << "t)" << expr_gen.to_str(o1)
31315 << "(t" << expr_gen.to_str(o2)
31316 << "t)";
31317 }
31318 };
31319
31320 struct synthesize_covovov_expression0
31321 {
31322 typedef typename covovov_t::type0 node_type;
31323 typedef typename covovov_t::sf4_type sf4_type;
31324 typedef typename node_type::T0 T0;
31325 typedef typename node_type::T1 T1;
31326 typedef typename node_type::T2 T2;
31327 typedef typename node_type::T3 T3;
31328
31329 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31330 const details::operator_type& operation,
31331 expression_node_ptr (&branch)[2])
31332 {
31333 // (c o0 v0) o1 (v1 o2 v2)
31334 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31335 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31336 const Type c = cov->c ();
31337 const Type& v0 = cov->v ();
31338 const Type& v1 = vov->v0();
31339 const Type& v2 = vov->v1();
31340 const details::operator_type o0 = cov->operation();
31341 const details::operator_type o1 = operation;
31342 const details::operator_type o2 = vov->operation();
31343
31344 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31345 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31346 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31347
31348 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31349 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31350
31351 expression_node_ptr result = error_node();
31352
31353 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31354 {
31355 // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
31356 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31357 {
31358 const bool synthesis_result =
31359 synthesize_sf4ext_expression::
31360 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
31361
31362 exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
31363
31364 return (synthesis_result) ? result : error_node();
31365 }
31366 // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
31367 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31368 {
31369 const bool synthesis_result =
31370 synthesize_sf4ext_expression::
31371 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
31372
31373 exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
31374
31375 return (synthesis_result) ? result : error_node();
31376 }
31377 }
31378
31379 const bool synthesis_result =
31380 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31381 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
31382
31383 if (synthesis_result)
31384 return result;
31385 else if (!expr_gen.valid_operator(o0,f0))
31386 return error_node();
31387 else if (!expr_gen.valid_operator(o1,f1))
31388 return error_node();
31389 else if (!expr_gen.valid_operator(o2,f2))
31390 return error_node();
31391 else
31392 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
31393 }
31394
31395 static inline std::string id(expression_generator<Type>& expr_gen,
31396 const details::operator_type o0,
31397 const details::operator_type o1,
31398 const details::operator_type o2)
31399 {
31400 return details::build_string()
31401 << "(t" << expr_gen.to_str(o0)
31402 << "t)" << expr_gen.to_str(o1)
31403 << "(t" << expr_gen.to_str(o2)
31404 << "t)";
31405 }
31406 };
31407
31408 struct synthesize_covocov_expression0
31409 {
31410 typedef typename covocov_t::type0 node_type;
31411 typedef typename covocov_t::sf4_type sf4_type;
31412 typedef typename node_type::T0 T0;
31413 typedef typename node_type::T1 T1;
31414 typedef typename node_type::T2 T2;
31415 typedef typename node_type::T3 T3;
31416
31417 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31418 const details::operator_type& operation,
31419 expression_node_ptr (&branch)[2])
31420 {
31421 // (c0 o0 v0) o1 (c1 o2 v1)
31422 const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
31423 const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
31424 const Type c0 = cov0->c();
31425 const Type& v0 = cov0->v();
31426 const Type c1 = cov1->c();
31427 const Type& v1 = cov1->v();
31428 const details::operator_type o0 = cov0->operation();
31429 const details::operator_type o1 = operation;
31430 const details::operator_type o2 = cov1->operation();
31431
31432 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31433 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31434 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31435
31436 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31437 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31438
31439 expression_node_ptr result = error_node();
31440
31441 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31442 {
31443 // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
31444 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31445 {
31446 const bool synthesis_result =
31447 synthesize_sf3ext_expression::
31448 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31449
31450 exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
31451
31452 return (synthesis_result) ? result : error_node();
31453 }
31454 // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
31455 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31456 {
31457 const bool synthesis_result =
31458 synthesize_sf3ext_expression::
31459 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31460
31461 exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
31462
31463 return (synthesis_result) ? result : error_node();
31464 }
31465 // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
31466 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31467 {
31468 const bool synthesis_result =
31469 synthesize_sf3ext_expression::
31470 template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
31471
31472 exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
31473
31474 return (synthesis_result) ? result : error_node();
31475 }
31476 // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
31477 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31478 {
31479 const bool synthesis_result =
31480 synthesize_sf3ext_expression::
31481 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31482
31483 exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
31484
31485 return (synthesis_result) ? result : error_node();
31486 }
31487 // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
31488 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31489 {
31490 const bool synthesis_result =
31491 synthesize_sf3ext_expression::
31492 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31493
31494 exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31495
31496 return (synthesis_result) ? result : error_node();
31497 }
31498 // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
31499 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31500 {
31501 const bool synthesis_result =
31502 synthesize_sf3ext_expression::
31503 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31504
31505 exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31506
31507 return (synthesis_result) ? result : error_node();
31508 }
31509 // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
31510 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31511 {
31512 const bool synthesis_result =
31513 synthesize_sf3ext_expression::
31514 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
31515
31516 exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
31517
31518 return (synthesis_result) ? result : error_node();
31519 }
31520 // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
31521 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31522 {
31523 const bool synthesis_result =
31524 synthesize_sf3ext_expression::
31525 template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
31526
31527 exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
31528
31529 return (synthesis_result) ? result : error_node();
31530 }
31531 // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
31532 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31533 {
31534 const bool synthesis_result =
31535 synthesize_sf3ext_expression::
31536 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31537
31538 exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31539
31540 return (synthesis_result) ? result : error_node();
31541 }
31542 // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
31543 else if (
31544 (std::equal_to<T>()(c0,c1)) &&
31545 (details::e_mul == o0) &&
31546 (details::e_mul == o2) &&
31547 (
31548 (details::e_add == o1) ||
31549 (details::e_sub == o1)
31550 )
31551 )
31552 {
31553 std::string specfunc;
31554
31555 switch (o1)
31556 {
31557 case details::e_add : specfunc = "t*(t+t)"; break;
31558 case details::e_sub : specfunc = "t*(t-t)"; break;
31559 default : return error_node();
31560 }
31561
31562 const bool synthesis_result =
31563 synthesize_sf3ext_expression::
31564 template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
31565
31566 exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
31567
31568 return (synthesis_result) ? result : error_node();
31569 }
31570 }
31571
31572 const bool synthesis_result =
31573 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31574 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
31575
31576 if (synthesis_result)
31577 return result;
31578 else if (!expr_gen.valid_operator(o0,f0))
31579 return error_node();
31580 else if (!expr_gen.valid_operator(o1,f1))
31581 return error_node();
31582 else if (!expr_gen.valid_operator(o2,f2))
31583 return error_node();
31584 else
31585 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
31586 }
31587
31588 static inline std::string id(expression_generator<Type>& expr_gen,
31589 const details::operator_type o0,
31590 const details::operator_type o1,
31591 const details::operator_type o2)
31592 {
31593 return details::build_string()
31594 << "(t" << expr_gen.to_str(o0)
31595 << "t)" << expr_gen.to_str(o1)
31596 << "(t" << expr_gen.to_str(o2)
31597 << "t)";
31598 }
31599 };
31600
31601 struct synthesize_vocovoc_expression0
31602 {
31603 typedef typename vocovoc_t::type0 node_type;
31604 typedef typename vocovoc_t::sf4_type sf4_type;
31605 typedef typename node_type::T0 T0;
31606 typedef typename node_type::T1 T1;
31607 typedef typename node_type::T2 T2;
31608 typedef typename node_type::T3 T3;
31609
31610 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31611 const details::operator_type& operation,
31612 expression_node_ptr (&branch)[2])
31613 {
31614 // (v0 o0 c0) o1 (v1 o2 c1)
31615 const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
31616 const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
31617 const Type c0 = voc0->c();
31618 const Type& v0 = voc0->v();
31619 const Type c1 = voc1->c();
31620 const Type& v1 = voc1->v();
31621 const details::operator_type o0 = voc0->operation();
31622 const details::operator_type o1 = operation;
31623 const details::operator_type o2 = voc1->operation();
31624
31625 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31626 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31627 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31628
31629 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31630 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31631
31632 expression_node_ptr result = error_node();
31633
31634 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31635 {
31636 // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31637 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31638 {
31639 const bool synthesis_result =
31640 synthesize_sf3ext_expression::
31641 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31642
31643 exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31644
31645 return (synthesis_result) ? result : error_node();
31646 }
31647 // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31648 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31649 {
31650 const bool synthesis_result =
31651 synthesize_sf3ext_expression::
31652 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31653
31654 exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31655
31656 return (synthesis_result) ? result : error_node();
31657 }
31658 // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
31659 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31660 {
31661 const bool synthesis_result =
31662 synthesize_sf3ext_expression::
31663 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
31664
31665 exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
31666
31667 return (synthesis_result) ? result : error_node();
31668 }
31669 // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31670 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31671 {
31672 const bool synthesis_result =
31673 synthesize_sf3ext_expression::
31674 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31675
31676 exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31677
31678 return (synthesis_result) ? result : error_node();
31679 }
31680 // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31681 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31682 {
31683 const bool synthesis_result =
31684 synthesize_sf3ext_expression::
31685 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31686
31687 exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31688
31689 return (synthesis_result) ? result : error_node();
31690 }
31691 // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
31692 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31693 {
31694 const bool synthesis_result =
31695 synthesize_sf3ext_expression::
31696 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
31697
31698 exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
31699
31700 return (synthesis_result) ? result : error_node();
31701 }
31702 // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
31703 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31704 {
31705 const bool synthesis_result =
31706 synthesize_sf3ext_expression::
31707 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
31708
31709 exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
31710
31711 return (synthesis_result) ? result : error_node();
31712 }
31713 // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31714 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31715 {
31716 const bool synthesis_result =
31717 synthesize_sf3ext_expression::
31718 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
31719
31720 exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31721
31722 return (synthesis_result) ? result : error_node();
31723 }
31724 // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
31725 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31726 {
31727 const bool synthesis_result =
31728 synthesize_sf3ext_expression::
31729 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
31730
31731 exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
31732
31733 return (synthesis_result) ? result : error_node();
31734 }
31735 // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
31736 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
31737 {
31738 const bool synthesis_result =
31739 synthesize_sf4ext_expression::
31740 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
31741
31742 exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
31743
31744 return (synthesis_result) ? result : error_node();
31745 }
31746 // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
31747 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
31748 {
31749 const bool synthesis_result =
31750 synthesize_sf4ext_expression::
31751 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
31752
31753 exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
31754
31755 return (synthesis_result) ? result : error_node();
31756 }
31757 // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31758 else if (
31759 (std::equal_to<T>()(c0,c1)) &&
31760 (details::e_mul == o0) &&
31761 (details::e_mul == o2) &&
31762 (
31763 (details::e_add == o1) ||
31764 (details::e_sub == o1)
31765 )
31766 )
31767 {
31768 std::string specfunc;
31769
31770 switch (o1)
31771 {
31772 case details::e_add : specfunc = "t*(t+t)"; break;
31773 case details::e_sub : specfunc = "t*(t-t)"; break;
31774 default : return error_node();
31775 }
31776
31777 const bool synthesis_result =
31778 synthesize_sf3ext_expression::
31779 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
31780
31781 exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
31782
31783 return (synthesis_result) ? result : error_node();
31784 }
31785 // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
31786 else if (
31787 (std::equal_to<T>()(c0,c1)) &&
31788 (details::e_div == o0) &&
31789 (details::e_div == o2) &&
31790 (
31791 (details::e_add == o1) ||
31792 (details::e_sub == o1)
31793 )
31794 )
31795 {
31796 std::string specfunc;
31797
31798 switch (o1)
31799 {
31800 case details::e_add : specfunc = "(t+t)/t"; break;
31801 case details::e_sub : specfunc = "(t-t)/t"; break;
31802 default : return error_node();
31803 }
31804
31805 const bool synthesis_result =
31806 synthesize_sf3ext_expression::
31807 template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
31808
31809 exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
31810
31811 return (synthesis_result) ? result : error_node();
31812 }
31813 }
31814
31815 const bool synthesis_result =
31816 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31817 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
31818
31819 if (synthesis_result)
31820 return result;
31821 else if (!expr_gen.valid_operator(o0,f0))
31822 return error_node();
31823 else if (!expr_gen.valid_operator(o1,f1))
31824 return error_node();
31825 else if (!expr_gen.valid_operator(o2,f2))
31826 return error_node();
31827 else
31828 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
31829 }
31830
31831 static inline std::string id(expression_generator<Type>& expr_gen,
31832 const details::operator_type o0,
31833 const details::operator_type o1,
31834 const details::operator_type o2)
31835 {
31836 return details::build_string()
31837 << "(t" << expr_gen.to_str(o0)
31838 << "t)" << expr_gen.to_str(o1)
31839 << "(t" << expr_gen.to_str(o2)
31840 << "t)";
31841 }
31842 };
31843
31844 struct synthesize_covovoc_expression0
31845 {
31846 typedef typename covovoc_t::type0 node_type;
31847 typedef typename covovoc_t::sf4_type sf4_type;
31848 typedef typename node_type::T0 T0;
31849 typedef typename node_type::T1 T1;
31850 typedef typename node_type::T2 T2;
31851 typedef typename node_type::T3 T3;
31852
31853 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31854 const details::operator_type& operation,
31855 expression_node_ptr (&branch)[2])
31856 {
31857 // (c0 o0 v0) o1 (v1 o2 c1)
31858 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31859 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31860 const Type c0 = cov->c();
31861 const Type& v0 = cov->v();
31862 const Type c1 = voc->c();
31863 const Type& v1 = voc->v();
31864 const details::operator_type o0 = cov->operation();
31865 const details::operator_type o1 = operation;
31866 const details::operator_type o2 = voc->operation();
31867
31868 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31869 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31870 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31871
31872 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31873 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31874
31875 expression_node_ptr result = error_node();
31876
31877 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31878 {
31879 // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31880 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31881 {
31882 const bool synthesis_result =
31883 synthesize_sf3ext_expression::
31884 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31885
31886 exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31887
31888 return (synthesis_result) ? result : error_node();
31889 }
31890 // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31891 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31892 {
31893 const bool synthesis_result =
31894 synthesize_sf3ext_expression::
31895 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31896
31897 exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31898
31899 return (synthesis_result) ? result : error_node();
31900 }
31901 // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
31902 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31903 {
31904 const bool synthesis_result =
31905 synthesize_sf3ext_expression::
31906 template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
31907
31908 exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
31909
31910 return (synthesis_result) ? result : error_node();
31911 }
31912 // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31913 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31914 {
31915 const bool synthesis_result =
31916 synthesize_sf3ext_expression::
31917 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31918
31919 exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31920
31921 return (synthesis_result) ? result : error_node();
31922 }
31923 // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31924 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31925 {
31926 const bool synthesis_result =
31927 synthesize_sf3ext_expression::
31928 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31929
31930 exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31931
31932 return (synthesis_result) ? result : error_node();
31933 }
31934 // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
31935 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31936 {
31937 const bool synthesis_result =
31938 synthesize_sf3ext_expression::
31939 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
31940
31941 exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
31942
31943 return (synthesis_result) ? result : error_node();
31944 }
31945 // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
31946 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31947 {
31948 const bool synthesis_result =
31949 synthesize_sf3ext_expression::
31950 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31951
31952 exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31953
31954 return (synthesis_result) ? result : error_node();
31955 }
31956 // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31957 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31958 {
31959 const bool synthesis_result =
31960 synthesize_sf3ext_expression::
31961 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
31962
31963 exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31964
31965 return (synthesis_result) ? result : error_node();
31966 }
31967 // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
31968 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31969 {
31970 const bool synthesis_result =
31971 synthesize_sf3ext_expression::
31972 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31973
31974 exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31975
31976 return (synthesis_result) ? result : error_node();
31977 }
31978 // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31979 else if (
31980 (std::equal_to<T>()(c0,c1)) &&
31981 (details::e_mul == o0) &&
31982 (details::e_mul == o2) &&
31983 (
31984 (details::e_add == o1) ||
31985 (details::e_sub == o1)
31986 )
31987 )
31988 {
31989 std::string specfunc;
31990
31991 switch (o1)
31992 {
31993 case details::e_add : specfunc = "t*(t+t)"; break;
31994 case details::e_sub : specfunc = "t*(t-t)"; break;
31995 default : return error_node();
31996 }
31997
31998 const bool synthesis_result =
31999 synthesize_sf3ext_expression::
32000 template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
32001
32002 exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32003
32004 return (synthesis_result) ? result : error_node();
32005 }
32006 }
32007
32008 const bool synthesis_result =
32009 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32010 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32011
32012 if (synthesis_result)
32013 return result;
32014 else if (!expr_gen.valid_operator(o0,f0))
32015 return error_node();
32016 else if (!expr_gen.valid_operator(o1,f1))
32017 return error_node();
32018 else if (!expr_gen.valid_operator(o2,f2))
32019 return error_node();
32020 else
32021 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32022 }
32023
32024 static inline std::string id(expression_generator<Type>& expr_gen,
32025 const details::operator_type o0,
32026 const details::operator_type o1,
32027 const details::operator_type o2)
32028 {
32029 return details::build_string()
32030 << "(t" << expr_gen.to_str(o0)
32031 << "t)" << expr_gen.to_str(o1)
32032 << "(t" << expr_gen.to_str(o2)
32033 << "t)";
32034 }
32035 };
32036
32037 struct synthesize_vococov_expression0
32038 {
32039 typedef typename vococov_t::type0 node_type;
32040 typedef typename vococov_t::sf4_type sf4_type;
32041 typedef typename node_type::T0 T0;
32042 typedef typename node_type::T1 T1;
32043 typedef typename node_type::T2 T2;
32044 typedef typename node_type::T3 T3;
32045
32046 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32047 const details::operator_type& operation,
32048 expression_node_ptr (&branch)[2])
32049 {
32050 // (v0 o0 c0) o1 (c1 o2 v1)
32051 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
32052 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
32053 const Type c0 = voc->c();
32054 const Type& v0 = voc->v();
32055 const Type c1 = cov->c();
32056 const Type& v1 = cov->v();
32057 const details::operator_type o0 = voc->operation();
32058 const details::operator_type o1 = operation;
32059 const details::operator_type o2 = cov->operation();
32060
32061 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32062 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32063 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32064
32065 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32066 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32067
32068 expression_node_ptr result = error_node();
32069
32070 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32071 {
32072 // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
32073 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32074 {
32075 const bool synthesis_result =
32076 synthesize_sf3ext_expression::
32077 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32078
32079 exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
32080
32081 return (synthesis_result) ? result : error_node();
32082 }
32083 // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32084 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32085 {
32086 const bool synthesis_result =
32087 synthesize_sf3ext_expression::
32088 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32089
32090 exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32091
32092 return (synthesis_result) ? result : error_node();
32093 }
32094 // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
32095 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32096 {
32097 const bool synthesis_result =
32098 synthesize_sf3ext_expression::
32099 template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
32100
32101 exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
32102
32103 return (synthesis_result) ? result : error_node();
32104 }
32105 // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32106 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32107 {
32108 const bool synthesis_result =
32109 synthesize_sf3ext_expression::
32110 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32111
32112 exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32113
32114 return (synthesis_result) ? result : error_node();
32115 }
32116 // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
32117 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32118 {
32119 const bool synthesis_result =
32120 synthesize_sf3ext_expression::
32121 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32122
32123 exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32124
32125 return (synthesis_result) ? result : error_node();
32126 }
32127 // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
32128 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32129 {
32130 const bool synthesis_result =
32131 synthesize_sf3ext_expression::
32132 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32133
32134 exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
32135
32136 return (synthesis_result) ? result : error_node();
32137 }
32138 // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32139 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32140 {
32141 const bool synthesis_result =
32142 synthesize_sf3ext_expression::
32143 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
32144
32145 exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32146
32147 return (synthesis_result) ? result : error_node();
32148 }
32149 // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
32150 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32151 {
32152 const bool synthesis_result =
32153 synthesize_sf3ext_expression::
32154 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
32155
32156 exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
32157
32158 return (synthesis_result) ? result : error_node();
32159 }
32160 // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
32161 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32162 {
32163 const bool synthesis_result =
32164 synthesize_sf3ext_expression::
32165 template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
32166
32167 exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
32168
32169 return (synthesis_result) ? result : error_node();
32170 }
32171 // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32172 else if (
32173 (std::equal_to<T>()(c0,c1)) &&
32174 (details::e_mul == o0) &&
32175 (details::e_mul == o2) &&
32176 (
32177 (details::e_add == o1) || (details::e_sub == o1)
32178 )
32179 )
32180 {
32181 std::string specfunc;
32182
32183 switch (o1)
32184 {
32185 case details::e_add : specfunc = "t*(t+t)"; break;
32186 case details::e_sub : specfunc = "t*(t-t)"; break;
32187 default : return error_node();
32188 }
32189
32190 const bool synthesis_result =
32191 synthesize_sf3ext_expression::
32192 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32193
32194 exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32195
32196 return (synthesis_result) ? result : error_node();
32197 }
32198 }
32199
32200 const bool synthesis_result =
32201 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32202 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32203
32204 if (synthesis_result)
32205 return result;
32206 else if (!expr_gen.valid_operator(o0,f0))
32207 return error_node();
32208 else if (!expr_gen.valid_operator(o1,f1))
32209 return error_node();
32210 else if (!expr_gen.valid_operator(o2,f2))
32211 return error_node();
32212 else
32213 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32214 }
32215
32216 static inline std::string id(expression_generator<Type>& expr_gen,
32217 const details::operator_type o0,
32218 const details::operator_type o1,
32219 const details::operator_type o2)
32220 {
32221 return details::build_string()
32222 << "(t" << expr_gen.to_str(o0)
32223 << "t)" << expr_gen.to_str(o1)
32224 << "(t" << expr_gen.to_str(o2)
32225 << "t)";
32226 }
32227 };
32228
32229 struct synthesize_vovovov_expression1
32230 {
32231 typedef typename vovovov_t::type1 node_type;
32232 typedef typename vovovov_t::sf4_type sf4_type;
32233 typedef typename node_type::T0 T0;
32234 typedef typename node_type::T1 T1;
32235 typedef typename node_type::T2 T2;
32236 typedef typename node_type::T3 T3;
32237
32238 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32239 const details::operator_type& operation,
32240 expression_node_ptr (&branch)[2])
32241 {
32242 // v0 o0 (v1 o1 (v2 o2 v3))
32243 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32244
32245 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32246 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32247 const Type& v1 = vovov->t0();
32248 const Type& v2 = vovov->t1();
32249 const Type& v3 = vovov->t2();
32250 const details::operator_type o0 = operation;
32251 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32252 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32253
32254 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32255 binary_functor_t f1 = vovov->f0();
32256 binary_functor_t f2 = vovov->f1();
32257
32258 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32259
32260 expression_node_ptr result = error_node();
32261
32262 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
32263 return result;
32264 else if (!expr_gen.valid_operator(o0,f0))
32265 return error_node();
32266
32267 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
32268
32269 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
32270 }
32271
32272 static inline std::string id(expression_generator<Type>& expr_gen,
32273 const details::operator_type o0,
32274 const details::operator_type o1,
32275 const details::operator_type o2)
32276 {
32277 return details::build_string()
32278 << "t" << expr_gen.to_str(o0)
32279 << "(t" << expr_gen.to_str(o1)
32280 << "(t" << expr_gen.to_str(o2)
32281 << "t))";
32282 }
32283 };
32284
32285 struct synthesize_vovovoc_expression1
32286 {
32287 typedef typename vovovoc_t::type1 node_type;
32288 typedef typename vovovoc_t::sf4_type sf4_type;
32289 typedef typename node_type::T0 T0;
32290 typedef typename node_type::T1 T1;
32291 typedef typename node_type::T2 T2;
32292 typedef typename node_type::T3 T3;
32293
32294 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32295 const details::operator_type& operation,
32296 expression_node_ptr (&branch)[2])
32297 {
32298 // v0 o0 (v1 o1 (v2 o2 c))
32299 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32300
32301 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32302 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32303 const Type& v1 = vovoc->t0();
32304 const Type& v2 = vovoc->t1();
32305 const Type c = vovoc->t2();
32306 const details::operator_type o0 = operation;
32307 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32308 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32309
32310 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32311 binary_functor_t f1 = vovoc->f0();
32312 binary_functor_t f2 = vovoc->f1();
32313
32314 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32315
32316 expression_node_ptr result = error_node();
32317
32318 const bool synthesis_result =
32319 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32320 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32321
32322 if (synthesis_result)
32323 return result;
32324 else if (!expr_gen.valid_operator(o0,f0))
32325 return error_node();
32326
32327 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
32328
32329 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32330 }
32331
32332 static inline std::string id(expression_generator<Type>& expr_gen,
32333 const details::operator_type o0,
32334 const details::operator_type o1,
32335 const details::operator_type o2)
32336 {
32337 return details::build_string()
32338 << "t" << expr_gen.to_str(o0)
32339 << "(t" << expr_gen.to_str(o1)
32340 << "(t" << expr_gen.to_str(o2)
32341 << "t))";
32342 }
32343 };
32344
32345 struct synthesize_vovocov_expression1
32346 {
32347 typedef typename vovocov_t::type1 node_type;
32348 typedef typename vovocov_t::sf4_type sf4_type;
32349 typedef typename node_type::T0 T0;
32350 typedef typename node_type::T1 T1;
32351 typedef typename node_type::T2 T2;
32352 typedef typename node_type::T3 T3;
32353
32354 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32355 const details::operator_type& operation,
32356 expression_node_ptr (&branch)[2])
32357 {
32358 // v0 o0 (v1 o1 (c o2 v2))
32359 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32360
32361 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32362 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32363 const Type& v1 = vocov->t0();
32364 const Type c = vocov->t1();
32365 const Type& v2 = vocov->t2();
32366 const details::operator_type o0 = operation;
32367 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32368 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32369
32370 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32371 binary_functor_t f1 = vocov->f0();
32372 binary_functor_t f2 = vocov->f1();
32373
32374 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32375
32376 expression_node_ptr result = error_node();
32377
32378 const bool synthesis_result =
32379 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32380 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32381
32382 if (synthesis_result)
32383 return result;
32384 if (!expr_gen.valid_operator(o0,f0))
32385 return error_node();
32386
32387 exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
32388
32389 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32390 }
32391
32392 static inline std::string id(expression_generator<Type>& expr_gen,
32393 const details::operator_type o0,
32394 const details::operator_type o1,
32395 const details::operator_type o2)
32396 {
32397 return details::build_string()
32398 << "t" << expr_gen.to_str(o0)
32399 << "(t" << expr_gen.to_str(o1)
32400 << "(t" << expr_gen.to_str(o2)
32401 << "t))";
32402 }
32403 };
32404
32405 struct synthesize_vocovov_expression1
32406 {
32407 typedef typename vocovov_t::type1 node_type;
32408 typedef typename vocovov_t::sf4_type sf4_type;
32409 typedef typename node_type::T0 T0;
32410 typedef typename node_type::T1 T1;
32411 typedef typename node_type::T2 T2;
32412 typedef typename node_type::T3 T3;
32413
32414 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32415 const details::operator_type& operation,
32416 expression_node_ptr (&branch)[2])
32417 {
32418 // v0 o0 (c o1 (v1 o2 v2))
32419 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
32420
32421 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32422 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32423 const Type c = covov->t0();
32424 const Type& v1 = covov->t1();
32425 const Type& v2 = covov->t2();
32426 const details::operator_type o0 = operation;
32427 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32428 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32429
32430 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32431 binary_functor_t f1 = covov->f0();
32432 binary_functor_t f2 = covov->f1();
32433
32434 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32435
32436 expression_node_ptr result = error_node();
32437
32438 const bool synthesis_result =
32439 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32440 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32441
32442 if (synthesis_result)
32443 return result;
32444 else if (!expr_gen.valid_operator(o0,f0))
32445 return error_node();
32446
32447 exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
32448
32449 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32450 }
32451
32452 static inline std::string id(expression_generator<Type>& expr_gen,
32453 const details::operator_type o0,
32454 const details::operator_type o1,
32455 const details::operator_type o2)
32456 {
32457 return details::build_string()
32458 << "t" << expr_gen.to_str(o0)
32459 << "(t" << expr_gen.to_str(o1)
32460 << "(t" << expr_gen.to_str(o2)
32461 << "t))";
32462 }
32463 };
32464
32465 struct synthesize_covovov_expression1
32466 {
32467 typedef typename covovov_t::type1 node_type;
32468 typedef typename covovov_t::sf4_type sf4_type;
32469 typedef typename node_type::T0 T0;
32470 typedef typename node_type::T1 T1;
32471 typedef typename node_type::T2 T2;
32472 typedef typename node_type::T3 T3;
32473
32474 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32475 const details::operator_type& operation,
32476 expression_node_ptr (&branch)[2])
32477 {
32478 // c o0 (v0 o1 (v1 o2 v2))
32479 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32480
32481 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32482 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
32483 const Type& v0 = vovov->t0();
32484 const Type& v1 = vovov->t1();
32485 const Type& v2 = vovov->t2();
32486 const details::operator_type o0 = operation;
32487 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32488 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32489
32490 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32491 binary_functor_t f1 = vovov->f0();
32492 binary_functor_t f2 = vovov->f1();
32493
32494 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32495 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32496
32497 expression_node_ptr result = error_node();
32498
32499 const bool synthesis_result =
32500 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32501 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32502
32503 if (synthesis_result)
32504 return result;
32505 if (!expr_gen.valid_operator(o0,f0))
32506 return error_node();
32507
32508 exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
32509
32510 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32511 }
32512
32513 static inline std::string id(expression_generator<Type>& expr_gen,
32514 const details::operator_type o0,
32515 const details::operator_type o1,
32516 const details::operator_type o2)
32517 {
32518 return details::build_string()
32519 << "t" << expr_gen.to_str(o0)
32520 << "(t" << expr_gen.to_str(o1)
32521 << "(t" << expr_gen.to_str(o2)
32522 << "t))";
32523 }
32524 };
32525
32526 struct synthesize_covocov_expression1
32527 {
32528 typedef typename covocov_t::type1 node_type;
32529 typedef typename covocov_t::sf4_type sf4_type;
32530 typedef typename node_type::T0 T0;
32531 typedef typename node_type::T1 T1;
32532 typedef typename node_type::T2 T2;
32533 typedef typename node_type::T3 T3;
32534
32535 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32536 const details::operator_type& operation,
32537 expression_node_ptr (&branch)[2])
32538 {
32539 // c0 o0 (v0 o1 (c1 o2 v1))
32540 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32541
32542 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32543 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32544 const Type& v0 = vocov->t0();
32545 const Type c1 = vocov->t1();
32546 const Type& v1 = vocov->t2();
32547 const details::operator_type o0 = operation;
32548 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32549 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32550
32551 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32552 binary_functor_t f1 = vocov->f0();
32553 binary_functor_t f2 = vocov->f1();
32554
32555 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32556 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32557
32558 expression_node_ptr result = error_node();
32559
32560 const bool synthesis_result =
32561 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32562 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32563
32564 if (synthesis_result)
32565 return result;
32566 else if (!expr_gen.valid_operator(o0,f0))
32567 return error_node();
32568
32569 exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
32570
32571 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32572 }
32573
32574 static inline std::string id(expression_generator<Type>& expr_gen,
32575 const details::operator_type o0,
32576 const details::operator_type o1,
32577 const details::operator_type o2)
32578 {
32579 return details::build_string()
32580 << "t" << expr_gen.to_str(o0)
32581 << "(t" << expr_gen.to_str(o1)
32582 << "(t" << expr_gen.to_str(o2)
32583 << "t))";
32584 }
32585 };
32586
32587 struct synthesize_vocovoc_expression1
32588 {
32589 typedef typename vocovoc_t::type1 node_type;
32590 typedef typename vocovoc_t::sf4_type sf4_type;
32591 typedef typename node_type::T0 T0;
32592 typedef typename node_type::T1 T1;
32593 typedef typename node_type::T2 T2;
32594 typedef typename node_type::T3 T3;
32595
32596 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32597 const details::operator_type& operation,
32598 expression_node_ptr (&branch)[2])
32599 {
32600 // v0 o0 (c0 o1 (v1 o2 c2))
32601 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
32602
32603 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
32604 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32605 const Type c0 = covoc->t0();
32606 const Type& v1 = covoc->t1();
32607 const Type c1 = covoc->t2();
32608 const details::operator_type o0 = operation;
32609 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
32610 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
32611
32612 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32613 binary_functor_t f1 = covoc->f0();
32614 binary_functor_t f2 = covoc->f1();
32615
32616 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32617
32618 expression_node_ptr result = error_node();
32619
32620 const bool synthesis_result =
32621 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32622 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32623
32624 if (synthesis_result)
32625 return result;
32626 else if (!expr_gen.valid_operator(o0,f0))
32627 return error_node();
32628
32629 exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
32630
32631 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32632 }
32633
32634 static inline std::string id(expression_generator<Type>& expr_gen,
32635 const details::operator_type o0,
32636 const details::operator_type o1,
32637 const details::operator_type o2)
32638 {
32639 return details::build_string()
32640 << "t" << expr_gen.to_str(o0)
32641 << "(t" << expr_gen.to_str(o1)
32642 << "(t" << expr_gen.to_str(o2)
32643 << "t))";
32644 }
32645 };
32646
32647 struct synthesize_covovoc_expression1
32648 {
32649 typedef typename covovoc_t::type1 node_type;
32650 typedef typename covovoc_t::sf4_type sf4_type;
32651 typedef typename node_type::T0 T0;
32652 typedef typename node_type::T1 T1;
32653 typedef typename node_type::T2 T2;
32654 typedef typename node_type::T3 T3;
32655 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32656 const details::operator_type& operation,
32657 expression_node_ptr (&branch)[2])
32658 {
32659 // c0 o0 (v0 o1 (v1 o2 c1))
32660 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32661
32662 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32663 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32664 const Type& v0 = vovoc->t0();
32665 const Type& v1 = vovoc->t1();
32666 const Type c1 = vovoc->t2();
32667 const details::operator_type o0 = operation;
32668 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32669 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32670
32671 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32672 binary_functor_t f1 = vovoc->f0();
32673 binary_functor_t f2 = vovoc->f1();
32674
32675 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32676 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32677
32678 expression_node_ptr result = error_node();
32679
32680 const bool synthesis_result =
32681 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32682 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32683
32684 if (synthesis_result)
32685 return result;
32686 else if (!expr_gen.valid_operator(o0,f0))
32687 return error_node();
32688
32689 exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
32690
32691 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32692 }
32693
32694 static inline std::string id(expression_generator<Type>& expr_gen,
32695 const details::operator_type o0,
32696 const details::operator_type o1,
32697 const details::operator_type o2)
32698 {
32699 return details::build_string()
32700 << "t" << expr_gen.to_str(o0)
32701 << "(t" << expr_gen.to_str(o1)
32702 << "(t" << expr_gen.to_str(o2)
32703 << "t))";
32704 }
32705 };
32706
32707 struct synthesize_vococov_expression1
32708 {
32709 typedef typename vococov_t::type1 node_type;
32710 typedef typename vococov_t::sf4_type sf4_type;
32711 typedef typename node_type::T0 T0;
32712 typedef typename node_type::T1 T1;
32713 typedef typename node_type::T2 T2;
32714 typedef typename node_type::T3 T3;
32715
32716 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32717 const details::operator_type& operation,
32718 expression_node_ptr (&branch)[2])
32719 {
32720 // v0 o0 (c0 o1 (c1 o2 v1))
32721 typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
32722
32723 const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
32724 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32725 const Type c0 = cocov->t0();
32726 const Type c1 = cocov->t1();
32727 const Type& v1 = cocov->t2();
32728 const details::operator_type o0 = operation;
32729 const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
32730 const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
32731
32732 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32733 binary_functor_t f1 = cocov->f0();
32734 binary_functor_t f2 = cocov->f1();
32735
32736 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32737
32738 expression_node_ptr result = error_node();
32739
32740 const bool synthesis_result =
32741 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32742 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32743
32744 if (synthesis_result)
32745 return result;
32746 else if (!expr_gen.valid_operator(o0,f0))
32747 return error_node();
32748
32749 exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
32750
32751 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32752 }
32753
32754 static inline std::string id(expression_generator<Type>& expr_gen,
32755 const details::operator_type o0,
32756 const details::operator_type o1,
32757 const details::operator_type o2)
32758 {
32759 return details::build_string()
32760 << "t" << expr_gen.to_str(o0)
32761 << "(t" << expr_gen.to_str(o1)
32762 << "(t" << expr_gen.to_str(o2)
32763 << "t))";
32764 }
32765 };
32766
32767 struct synthesize_vovovov_expression2
32768 {
32769 typedef typename vovovov_t::type2 node_type;
32770 typedef typename vovovov_t::sf4_type sf4_type;
32771 typedef typename node_type::T0 T0;
32772 typedef typename node_type::T1 T1;
32773 typedef typename node_type::T2 T2;
32774 typedef typename node_type::T3 T3;
32775
32776 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32777 const details::operator_type& operation,
32778 expression_node_ptr (&branch)[2])
32779 {
32780 // v0 o0 ((v1 o1 v2) o2 v3)
32781 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
32782
32783 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32784 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32785 const Type& v1 = vovov->t0();
32786 const Type& v2 = vovov->t1();
32787 const Type& v3 = vovov->t2();
32788 const details::operator_type o0 = operation;
32789 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32790 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32791
32792 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32793 binary_functor_t f1 = vovov->f0();
32794 binary_functor_t f2 = vovov->f1();
32795
32796 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32797
32798 expression_node_ptr result = error_node();
32799
32800 const bool synthesis_result =
32801 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32802 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32803
32804 if (synthesis_result)
32805 return result;
32806 else if (!expr_gen.valid_operator(o0,f0))
32807 return error_node();
32808
32809 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
32810
32811 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32812 }
32813
32814 static inline std::string id(expression_generator<Type>& expr_gen,
32815 const details::operator_type o0,
32816 const details::operator_type o1,
32817 const details::operator_type o2)
32818 {
32819 return details::build_string()
32820 << "t" << expr_gen.to_str(o0)
32821 << "((t" << expr_gen.to_str(o1)
32822 << "t)" << expr_gen.to_str(o2)
32823 << "t)";
32824 }
32825 };
32826
32827 struct synthesize_vovovoc_expression2
32828 {
32829 typedef typename vovovoc_t::type2 node_type;
32830 typedef typename vovovoc_t::sf4_type sf4_type;
32831 typedef typename node_type::T0 T0;
32832 typedef typename node_type::T1 T1;
32833 typedef typename node_type::T2 T2;
32834 typedef typename node_type::T3 T3;
32835
32836 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32837 const details::operator_type& operation,
32838 expression_node_ptr (&branch)[2])
32839 {
32840 // v0 o0 ((v1 o1 v2) o2 c)
32841 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
32842
32843 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32844 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32845 const Type& v1 = vovoc->t0();
32846 const Type& v2 = vovoc->t1();
32847 const Type c = vovoc->t2();
32848 const details::operator_type o0 = operation;
32849 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32850 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32851
32852 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32853 binary_functor_t f1 = vovoc->f0();
32854 binary_functor_t f2 = vovoc->f1();
32855
32856 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32857
32858 expression_node_ptr result = error_node();
32859
32860 const bool synthesis_result =
32861 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32862 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32863
32864 if (synthesis_result)
32865 return result;
32866 else if (!expr_gen.valid_operator(o0,f0))
32867 return error_node();
32868
32869 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
32870
32871 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32872 }
32873
32874 static inline std::string id(expression_generator<Type>& expr_gen,
32875 const details::operator_type o0,
32876 const details::operator_type o1,
32877 const details::operator_type o2)
32878 {
32879 return details::build_string()
32880 << "t" << expr_gen.to_str(o0)
32881 << "((t" << expr_gen.to_str(o1)
32882 << "t)" << expr_gen.to_str(o2)
32883 << "t)";
32884 }
32885 };
32886
32887 struct synthesize_vovocov_expression2
32888 {
32889 typedef typename vovocov_t::type2 node_type;
32890 typedef typename vovocov_t::sf4_type sf4_type;
32891 typedef typename node_type::T0 T0;
32892 typedef typename node_type::T1 T1;
32893 typedef typename node_type::T2 T2;
32894 typedef typename node_type::T3 T3;
32895
32896 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32897 const details::operator_type& operation,
32898 expression_node_ptr (&branch)[2])
32899 {
32900 // v0 o0 ((v1 o1 c) o2 v2)
32901 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
32902
32903 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32904 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32905 const Type& v1 = vocov->t0();
32906 const Type c = vocov->t1();
32907 const Type& v2 = vocov->t2();
32908 const details::operator_type o0 = operation;
32909 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32910 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32911
32912 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32913 binary_functor_t f1 = vocov->f0();
32914 binary_functor_t f2 = vocov->f1();
32915
32916 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32917
32918 expression_node_ptr result = error_node();
32919
32920 const bool synthesis_result =
32921 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32922 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32923
32924 if (synthesis_result)
32925 return result;
32926 else if (!expr_gen.valid_operator(o0,f0))
32927 return error_node();
32928
32929 exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
32930
32931 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32932 }
32933
32934 static inline std::string id(expression_generator<Type>& expr_gen,
32935 const details::operator_type o0,
32936 const details::operator_type o1,
32937 const details::operator_type o2)
32938 {
32939 return details::build_string()
32940 << "t" << expr_gen.to_str(o0)
32941 << "((t" << expr_gen.to_str(o1)
32942 << "t)" << expr_gen.to_str(o2)
32943 << "t)";
32944 }
32945 };
32946
32947 struct synthesize_vocovov_expression2
32948 {
32949 typedef typename vocovov_t::type2 node_type;
32950 typedef typename vocovov_t::sf4_type sf4_type;
32951 typedef typename node_type::T0 T0;
32952 typedef typename node_type::T1 T1;
32953 typedef typename node_type::T2 T2;
32954 typedef typename node_type::T3 T3;
32955
32956 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32957 const details::operator_type& operation,
32958 expression_node_ptr (&branch)[2])
32959 {
32960 // v0 o0 ((c o1 v1) o2 v2)
32961 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
32962
32963 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32964 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32965 const Type c = covov->t0();
32966 const Type& v1 = covov->t1();
32967 const Type& v2 = covov->t2();
32968 const details::operator_type o0 = operation;
32969 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32970 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32971
32972 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32973 binary_functor_t f1 = covov->f0();
32974 binary_functor_t f2 = covov->f1();
32975
32976 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32977
32978 expression_node_ptr result = error_node();
32979
32980 const bool synthesis_result =
32981 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32982 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32983
32984 if (synthesis_result)
32985 return result;
32986 else if (!expr_gen.valid_operator(o0,f0))
32987 return error_node();
32988
32989 exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
32990
32991 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32992 }
32993
32994 static inline std::string id(expression_generator<Type>& expr_gen,
32995 const details::operator_type o0,
32996 const details::operator_type o1,
32997 const details::operator_type o2)
32998 {
32999 return details::build_string()
33000 << "t" << expr_gen.to_str(o0)
33001 << "((t" << expr_gen.to_str(o1)
33002 << "t)" << expr_gen.to_str(o2)
33003 << "t)";
33004 }
33005 };
33006
33007 struct synthesize_covovov_expression2
33008 {
33009 typedef typename covovov_t::type2 node_type;
33010 typedef typename covovov_t::sf4_type sf4_type;
33011 typedef typename node_type::T0 T0;
33012 typedef typename node_type::T1 T1;
33013 typedef typename node_type::T2 T2;
33014 typedef typename node_type::T3 T3;
33015
33016 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33017 const details::operator_type& operation,
33018 expression_node_ptr (&branch)[2])
33019 {
33020 // c o0 ((v1 o1 v2) o2 v3)
33021 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33022
33023 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33024 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33025 const Type& v0 = vovov->t0();
33026 const Type& v1 = vovov->t1();
33027 const Type& v2 = vovov->t2();
33028 const details::operator_type o0 = operation;
33029 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33030 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33031
33032 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33033 binary_functor_t f1 = vovov->f0();
33034 binary_functor_t f2 = vovov->f1();
33035
33036 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33037 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33038
33039 expression_node_ptr result = error_node();
33040
33041 const bool synthesis_result =
33042 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33043 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33044
33045 if (synthesis_result)
33046 return result;
33047 else if (!expr_gen.valid_operator(o0,f0))
33048 return error_node();
33049
33050 exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
33051
33052 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33053 }
33054
33055 static inline std::string id(expression_generator<Type>& expr_gen,
33056 const details::operator_type o0,
33057 const details::operator_type o1,
33058 const details::operator_type o2)
33059 {
33060 return details::build_string()
33061 << "t" << expr_gen.to_str(o0)
33062 << "((t" << expr_gen.to_str(o1)
33063 << "t)" << expr_gen.to_str(o2)
33064 << "t)";
33065 }
33066 };
33067
33068 struct synthesize_covocov_expression2
33069 {
33070 typedef typename covocov_t::type2 node_type;
33071 typedef typename covocov_t::sf4_type sf4_type;
33072 typedef typename node_type::T0 T0;
33073 typedef typename node_type::T1 T1;
33074 typedef typename node_type::T2 T2;
33075 typedef typename node_type::T3 T3;
33076
33077 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33078 const details::operator_type& operation,
33079 expression_node_ptr (&branch)[2])
33080 {
33081 // c0 o0 ((v0 o1 c1) o2 v1)
33082 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33083
33084 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33085 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33086 const Type& v0 = vocov->t0();
33087 const Type c1 = vocov->t1();
33088 const Type& v1 = vocov->t2();
33089 const details::operator_type o0 = operation;
33090 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33091 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33092
33093 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33094 binary_functor_t f1 = vocov->f0();
33095 binary_functor_t f2 = vocov->f1();
33096
33097 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33098 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33099
33100 expression_node_ptr result = error_node();
33101
33102 const bool synthesis_result =
33103 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33104 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33105
33106 if (synthesis_result)
33107 return result;
33108 else if (!expr_gen.valid_operator(o0,f0))
33109 return error_node();
33110
33111 exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
33112
33113 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33114 }
33115
33116 static inline std::string id(expression_generator<Type>& expr_gen,
33117 const details::operator_type o0,
33118 const details::operator_type o1,
33119 const details::operator_type o2)
33120 {
33121 return details::build_string()
33122 << "t" << expr_gen.to_str(o0)
33123 << "((t" << expr_gen.to_str(o1)
33124 << "t)" << expr_gen.to_str(o2)
33125 << "t)";
33126 }
33127 };
33128
33129 struct synthesize_vocovoc_expression2
33130 {
33131 typedef typename vocovoc_t::type2 node_type;
33132 typedef typename vocovoc_t::sf4_type sf4_type;
33133 typedef typename node_type::T0 T0;
33134 typedef typename node_type::T1 T1;
33135 typedef typename node_type::T2 T2;
33136 typedef typename node_type::T3 T3;
33137
33138 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33139 const details::operator_type& operation,
33140 expression_node_ptr (&branch)[2])
33141 {
33142 // v0 o0 ((c0 o1 v1) o2 c1)
33143 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33144
33145 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33146 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33147 const Type c0 = covoc->t0();
33148 const Type& v1 = covoc->t1();
33149 const Type c1 = covoc->t2();
33150 const details::operator_type o0 = operation;
33151 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33152 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33153
33154 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33155 binary_functor_t f1 = covoc->f0();
33156 binary_functor_t f2 = covoc->f1();
33157
33158 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33159
33160 expression_node_ptr result = error_node();
33161
33162 const bool synthesis_result =
33163 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33164 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33165
33166 if (synthesis_result)
33167 return result;
33168 else if (!expr_gen.valid_operator(o0,f0))
33169 return error_node();
33170
33171 exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
33172
33173 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33174 }
33175
33176 static inline std::string id(expression_generator<Type>& expr_gen,
33177 const details::operator_type o0,
33178 const details::operator_type o1,
33179 const details::operator_type o2)
33180 {
33181 return details::build_string()
33182 << "t" << expr_gen.to_str(o0)
33183 << "((t" << expr_gen.to_str(o1)
33184 << "t)" << expr_gen.to_str(o2)
33185 << "t)";
33186 }
33187 };
33188
33189 struct synthesize_covovoc_expression2
33190 {
33191 typedef typename covovoc_t::type2 node_type;
33192 typedef typename covovoc_t::sf4_type sf4_type;
33193 typedef typename node_type::T0 T0;
33194 typedef typename node_type::T1 T1;
33195 typedef typename node_type::T2 T2;
33196 typedef typename node_type::T3 T3;
33197
33198 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33199 const details::operator_type& operation,
33200 expression_node_ptr (&branch)[2])
33201 {
33202 // c0 o0 ((v0 o1 v1) o2 c1)
33203 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33204
33205 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33206 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33207 const Type& v0 = vovoc->t0();
33208 const Type& v1 = vovoc->t1();
33209 const Type c1 = vovoc->t2();
33210 const details::operator_type o0 = operation;
33211 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33212 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33213
33214 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33215 binary_functor_t f1 = vovoc->f0();
33216 binary_functor_t f2 = vovoc->f1();
33217
33218 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33219 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33220
33221 expression_node_ptr result = error_node();
33222
33223 const bool synthesis_result =
33224 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33225 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33226
33227 if (synthesis_result)
33228 return result;
33229 else if (!expr_gen.valid_operator(o0,f0))
33230 return error_node();
33231
33232 exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
33233
33234 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33235 }
33236
33237 static inline std::string id(expression_generator<Type>& expr_gen,
33238 const details::operator_type o0,
33239 const details::operator_type o1,
33240 const details::operator_type o2)
33241 {
33242 return details::build_string()
33243 << "t" << expr_gen.to_str(o0)
33244 << "((t" << expr_gen.to_str(o1)
33245 << "t)" << expr_gen.to_str(o2)
33246 << "t)";
33247 }
33248 };
33249
33250 struct synthesize_vococov_expression2
33251 {
33252 typedef typename vococov_t::type2 node_type;
33253 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
33254 {
33255 // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
33256 exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
33257 return error_node();
33258 }
33259
33260 static inline std::string id(expression_generator<Type>&,
33261 const details::operator_type, const details::operator_type, const details::operator_type)
33262 {
33263 return "INVALID";
33264 }
33265 };
33266
33267 struct synthesize_vovovov_expression3
33268 {
33269 typedef typename vovovov_t::type3 node_type;
33270 typedef typename vovovov_t::sf4_type sf4_type;
33271 typedef typename node_type::T0 T0;
33272 typedef typename node_type::T1 T1;
33273 typedef typename node_type::T2 T2;
33274 typedef typename node_type::T3 T3;
33275
33276 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33277 const details::operator_type& operation,
33278 expression_node_ptr (&branch)[2])
33279 {
33280 // ((v0 o0 v1) o1 v2) o2 v3
33281 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33282
33283 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33284 const Type& v0 = vovov->t0();
33285 const Type& v1 = vovov->t1();
33286 const Type& v2 = vovov->t2();
33287 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33288 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33289 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33290 const details::operator_type o2 = operation;
33291
33292 binary_functor_t f0 = vovov->f0();
33293 binary_functor_t f1 = vovov->f1();
33294 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33295
33296 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33297
33298 expression_node_ptr result = error_node();
33299
33300 const bool synthesis_result =
33301 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33302 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33303
33304 if (synthesis_result)
33305 return result;
33306 else if (!expr_gen.valid_operator(o2,f2))
33307 return error_node();
33308
33309 exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
33310
33311 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33312 }
33313
33314 static inline std::string id(expression_generator<Type>& expr_gen,
33315 const details::operator_type o0,
33316 const details::operator_type o1,
33317 const details::operator_type o2)
33318 {
33319 return details::build_string()
33320 << "((t" << expr_gen.to_str(o0)
33321 << "t)" << expr_gen.to_str(o1)
33322 << "t)" << expr_gen.to_str(o2)
33323 << "t";
33324 }
33325 };
33326
33327 struct synthesize_vovovoc_expression3
33328 {
33329 typedef typename vovovoc_t::type3 node_type;
33330 typedef typename vovovoc_t::sf4_type sf4_type;
33331 typedef typename node_type::T0 T0;
33332 typedef typename node_type::T1 T1;
33333 typedef typename node_type::T2 T2;
33334 typedef typename node_type::T3 T3;
33335
33336 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33337 const details::operator_type& operation,
33338 expression_node_ptr (&branch)[2])
33339 {
33340 // ((v0 o0 v1) o1 v2) o2 c
33341 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33342
33343 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33344 const Type& v0 = vovov->t0();
33345 const Type& v1 = vovov->t1();
33346 const Type& v2 = vovov->t2();
33347 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33348 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33349 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33350 const details::operator_type o2 = operation;
33351
33352 binary_functor_t f0 = vovov->f0();
33353 binary_functor_t f1 = vovov->f1();
33354 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33355
33356 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33357 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33358
33359 expression_node_ptr result = error_node();
33360
33361 const bool synthesis_result =
33362 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33363 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33364
33365 if (synthesis_result)
33366 return result;
33367 else if (!expr_gen.valid_operator(o2,f2))
33368 return error_node();
33369
33370 exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
33371
33372 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33373 }
33374
33375 static inline std::string id(expression_generator<Type>& expr_gen,
33376 const details::operator_type o0,
33377 const details::operator_type o1,
33378 const details::operator_type o2)
33379 {
33380 return details::build_string()
33381 << "((t" << expr_gen.to_str(o0)
33382 << "t)" << expr_gen.to_str(o1)
33383 << "t)" << expr_gen.to_str(o2)
33384 << "t";
33385 }
33386 };
33387
33388 struct synthesize_vovocov_expression3
33389 {
33390 typedef typename vovocov_t::type3 node_type;
33391 typedef typename vovocov_t::sf4_type sf4_type;
33392 typedef typename node_type::T0 T0;
33393 typedef typename node_type::T1 T1;
33394 typedef typename node_type::T2 T2;
33395 typedef typename node_type::T3 T3;
33396
33397 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33398 const details::operator_type& operation,
33399 expression_node_ptr (&branch)[2])
33400 {
33401 // ((v0 o0 v1) o1 c) o2 v2
33402 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33403
33404 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33405 const Type& v0 = vovoc->t0();
33406 const Type& v1 = vovoc->t1();
33407 const Type c = vovoc->t2();
33408 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33409 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33410 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33411 const details::operator_type o2 = operation;
33412
33413 binary_functor_t f0 = vovoc->f0();
33414 binary_functor_t f1 = vovoc->f1();
33415 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33416
33417 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33418
33419 expression_node_ptr result = error_node();
33420
33421 const bool synthesis_result =
33422 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33423 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33424
33425 if (synthesis_result)
33426 return result;
33427 else if (!expr_gen.valid_operator(o2,f2))
33428 return error_node();
33429
33430 exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
33431
33432 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33433 }
33434
33435 static inline std::string id(expression_generator<Type>& expr_gen,
33436 const details::operator_type o0,
33437 const details::operator_type o1,
33438 const details::operator_type o2)
33439 {
33440 return details::build_string()
33441 << "((t" << expr_gen.to_str(o0)
33442 << "t)" << expr_gen.to_str(o1)
33443 << "t)" << expr_gen.to_str(o2)
33444 << "t";
33445 }
33446 };
33447
33448 struct synthesize_vocovov_expression3
33449 {
33450 typedef typename vocovov_t::type3 node_type;
33451 typedef typename vocovov_t::sf4_type sf4_type;
33452 typedef typename node_type::T0 T0;
33453 typedef typename node_type::T1 T1;
33454 typedef typename node_type::T2 T2;
33455 typedef typename node_type::T3 T3;
33456
33457 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33458 const details::operator_type& operation,
33459 expression_node_ptr (&branch)[2])
33460 {
33461 // ((v0 o0 c) o1 v1) o2 v2
33462 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33463
33464 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33465 const Type& v0 = vocov->t0();
33466 const Type c = vocov->t1();
33467 const Type& v1 = vocov->t2();
33468 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33469 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33470 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33471 const details::operator_type o2 = operation;
33472
33473 binary_functor_t f0 = vocov->f0();
33474 binary_functor_t f1 = vocov->f1();
33475 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33476
33477 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33478
33479 expression_node_ptr result = error_node();
33480
33481 const bool synthesis_result =
33482 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33483 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33484
33485 if (synthesis_result)
33486 return result;
33487 else if (!expr_gen.valid_operator(o2,f2))
33488 return error_node();
33489
33490 exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
33491
33492 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33493 }
33494
33495 static inline std::string id(expression_generator<Type>& expr_gen,
33496 const details::operator_type o0,
33497 const details::operator_type o1,
33498 const details::operator_type o2)
33499 {
33500 return details::build_string()
33501 << "((t" << expr_gen.to_str(o0)
33502 << "t)" << expr_gen.to_str(o1)
33503 << "t)" << expr_gen.to_str(o2)
33504 << "t";
33505 }
33506 };
33507
33508 struct synthesize_covovov_expression3
33509 {
33510 typedef typename covovov_t::type3 node_type;
33511 typedef typename covovov_t::sf4_type sf4_type;
33512 typedef typename node_type::T0 T0;
33513 typedef typename node_type::T1 T1;
33514 typedef typename node_type::T2 T2;
33515 typedef typename node_type::T3 T3;
33516
33517 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33518 const details::operator_type& operation,
33519 expression_node_ptr (&branch)[2])
33520 {
33521 // ((c o0 v0) o1 v1) o2 v2
33522 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33523
33524 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33525 const Type c = covov->t0();
33526 const Type& v0 = covov->t1();
33527 const Type& v1 = covov->t2();
33528 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33529 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33530 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33531 const details::operator_type o2 = operation;
33532
33533 binary_functor_t f0 = covov->f0();
33534 binary_functor_t f1 = covov->f1();
33535 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33536
33537 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33538
33539 expression_node_ptr result = error_node();
33540
33541 const bool synthesis_result =
33542 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33543 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33544
33545 if (synthesis_result)
33546 return result;
33547 else if (!expr_gen.valid_operator(o2,f2))
33548 return error_node();
33549
33550 exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
33551
33552 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33553 }
33554
33555 static inline std::string id(expression_generator<Type>& expr_gen,
33556 const details::operator_type o0,
33557 const details::operator_type o1,
33558 const details::operator_type o2)
33559 {
33560 return details::build_string()
33561 << "((t" << expr_gen.to_str(o0)
33562 << "t)" << expr_gen.to_str(o1)
33563 << "t)" << expr_gen.to_str(o2)
33564 << "t";
33565 }
33566 };
33567
33568 struct synthesize_covocov_expression3
33569 {
33570 typedef typename covocov_t::type3 node_type;
33571 typedef typename covocov_t::sf4_type sf4_type;
33572 typedef typename node_type::T0 T0;
33573 typedef typename node_type::T1 T1;
33574 typedef typename node_type::T2 T2;
33575 typedef typename node_type::T3 T3;
33576
33577 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33578 const details::operator_type& operation,
33579 expression_node_ptr (&branch)[2])
33580 {
33581 // ((c0 o0 v0) o1 c1) o2 v1
33582 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33583
33584 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
33585 const Type c0 = covoc->t0();
33586 const Type& v0 = covoc->t1();
33587 const Type c1 = covoc->t2();
33588 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33589 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
33590 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
33591 const details::operator_type o2 = operation;
33592
33593 binary_functor_t f0 = covoc->f0();
33594 binary_functor_t f1 = covoc->f1();
33595 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33596
33597 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33598
33599 expression_node_ptr result = error_node();
33600
33601 const bool synthesis_result =
33602 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33603 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33604
33605 if (synthesis_result)
33606 return result;
33607 else if (!expr_gen.valid_operator(o2,f2))
33608 return error_node();
33609
33610 exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
33611
33612 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33613 }
33614
33615 static inline std::string id(expression_generator<Type>& expr_gen,
33616 const details::operator_type o0,
33617 const details::operator_type o1,
33618 const details::operator_type o2)
33619 {
33620 return details::build_string()
33621 << "((t" << expr_gen.to_str(o0)
33622 << "t)" << expr_gen.to_str(o1)
33623 << "t)" << expr_gen.to_str(o2)
33624 << "t";
33625 }
33626 };
33627
33628 struct synthesize_vocovoc_expression3
33629 {
33630 typedef typename vocovoc_t::type3 node_type;
33631 typedef typename vocovoc_t::sf4_type sf4_type;
33632 typedef typename node_type::T0 T0;
33633 typedef typename node_type::T1 T1;
33634 typedef typename node_type::T2 T2;
33635 typedef typename node_type::T3 T3;
33636
33637 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33638 const details::operator_type& operation,
33639 expression_node_ptr (&branch)[2])
33640 {
33641 // ((v0 o0 c0) o1 v1) o2 c1
33642 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33643
33644 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33645 const Type& v0 = vocov->t0();
33646 const Type c0 = vocov->t1();
33647 const Type& v1 = vocov->t2();
33648 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33649 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33650 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33651 const details::operator_type o2 = operation;
33652
33653 binary_functor_t f0 = vocov->f0();
33654 binary_functor_t f1 = vocov->f1();
33655 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33656
33657 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33658 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33659
33660 expression_node_ptr result = error_node();
33661
33662 const bool synthesis_result =
33663 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33664 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33665
33666 if (synthesis_result)
33667 return result;
33668 else if (!expr_gen.valid_operator(o2,f2))
33669 return error_node();
33670
33671 exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
33672
33673 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33674 }
33675
33676 static inline std::string id(expression_generator<Type>& expr_gen,
33677 const details::operator_type o0,
33678 const details::operator_type o1,
33679 const details::operator_type o2)
33680 {
33681 return details::build_string()
33682 << "((t" << expr_gen.to_str(o0)
33683 << "t)" << expr_gen.to_str(o1)
33684 << "t)" << expr_gen.to_str(o2)
33685 << "t";
33686 }
33687 };
33688
33689 struct synthesize_covovoc_expression3
33690 {
33691 typedef typename covovoc_t::type3 node_type;
33692 typedef typename covovoc_t::sf4_type sf4_type;
33693 typedef typename node_type::T0 T0;
33694 typedef typename node_type::T1 T1;
33695 typedef typename node_type::T2 T2;
33696 typedef typename node_type::T3 T3;
33697
33698 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33699 const details::operator_type& operation,
33700 expression_node_ptr (&branch)[2])
33701 {
33702 // ((c0 o0 v0) o1 v1) o2 c1
33703 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33704
33705 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33706 const Type c0 = covov->t0();
33707 const Type& v0 = covov->t1();
33708 const Type& v1 = covov->t2();
33709 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33710 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33711 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33712 const details::operator_type o2 = operation;
33713
33714 binary_functor_t f0 = covov->f0();
33715 binary_functor_t f1 = covov->f1();
33716 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33717
33718 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33719 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33720
33721 expression_node_ptr result = error_node();
33722
33723 const bool synthesis_result =
33724 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33725 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33726
33727 if (synthesis_result)
33728 return result;
33729 else if (!expr_gen.valid_operator(o2,f2))
33730 return error_node();
33731
33732 exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
33733
33734 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33735 }
33736
33737 static inline std::string id(expression_generator<Type>& expr_gen,
33738 const details::operator_type o0,
33739 const details::operator_type o1,
33740 const details::operator_type o2)
33741 {
33742 return details::build_string()
33743 << "((t" << expr_gen.to_str(o0)
33744 << "t)" << expr_gen.to_str(o1)
33745 << "t)" << expr_gen.to_str(o2)
33746 << "t";
33747 }
33748 };
33749
33750 struct synthesize_vococov_expression3
33751 {
33752 typedef typename vococov_t::type3 node_type;
33753 typedef typename vococov_t::sf4_type sf4_type;
33754 typedef typename node_type::T0 T0;
33755 typedef typename node_type::T1 T1;
33756 typedef typename node_type::T2 T2;
33757 typedef typename node_type::T3 T3;
33758
33759 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33760 const details::operator_type& operation,
33761 expression_node_ptr (&branch)[2])
33762 {
33763 // ((v0 o0 c0) o1 c1) o2 v1
33764 typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
33765
33766 const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
33767 const Type& v0 = vococ->t0();
33768 const Type c0 = vococ->t1();
33769 const Type c1 = vococ->t2();
33770 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33771 const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
33772 const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
33773 const details::operator_type o2 = operation;
33774
33775 binary_functor_t f0 = vococ->f0();
33776 binary_functor_t f1 = vococ->f1();
33777 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33778
33779 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33780
33781 expression_node_ptr result = error_node();
33782
33783 const bool synthesis_result =
33784 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33785 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33786
33787 if (synthesis_result)
33788 return result;
33789 else if (!expr_gen.valid_operator(o2,f2))
33790 return error_node();
33791
33792 exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
33793
33794 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33795 }
33796
33797 static inline std::string id(expression_generator<Type>& expr_gen,
33798 const details::operator_type o0,
33799 const details::operator_type o1,
33800 const details::operator_type o2)
33801 {
33802 return details::build_string()
33803 << "((t" << expr_gen.to_str(o0)
33804 << "t)" << expr_gen.to_str(o1)
33805 << "t)" << expr_gen.to_str(o2)
33806 << "t";
33807 }
33808 };
33809
33810 struct synthesize_vovovov_expression4
33811 {
33812 typedef typename vovovov_t::type4 node_type;
33813 typedef typename vovovov_t::sf4_type sf4_type;
33814 typedef typename node_type::T0 T0;
33815 typedef typename node_type::T1 T1;
33816 typedef typename node_type::T2 T2;
33817 typedef typename node_type::T3 T3;
33818
33819 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33820 const details::operator_type& operation,
33821 expression_node_ptr (&branch)[2])
33822 {
33823 // (v0 o0 (v1 o1 v2)) o2 v3
33824 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33825
33826 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33827 const Type& v0 = vovov->t0();
33828 const Type& v1 = vovov->t1();
33829 const Type& v2 = vovov->t2();
33830 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33831 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33832 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33833 const details::operator_type o2 = operation;
33834
33835 binary_functor_t f0 = vovov->f0();
33836 binary_functor_t f1 = vovov->f1();
33837 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33838
33839 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33840
33841 expression_node_ptr result = error_node();
33842
33843 const bool synthesis_result =
33844 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33845 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33846
33847 if (synthesis_result)
33848 return result;
33849 else if (!expr_gen.valid_operator(o2,f2))
33850 return error_node();
33851
33852 exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
33853
33854 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33855 }
33856
33857 static inline std::string id(expression_generator<Type>& expr_gen,
33858 const details::operator_type o0,
33859 const details::operator_type o1,
33860 const details::operator_type o2)
33861 {
33862 return details::build_string()
33863 << "(t" << expr_gen.to_str(o0)
33864 << "(t" << expr_gen.to_str(o1)
33865 << "t)" << expr_gen.to_str(o2)
33866 << "t";
33867 }
33868 };
33869
33870 struct synthesize_vovovoc_expression4
33871 {
33872 typedef typename vovovoc_t::type4 node_type;
33873 typedef typename vovovoc_t::sf4_type sf4_type;
33874 typedef typename node_type::T0 T0;
33875 typedef typename node_type::T1 T1;
33876 typedef typename node_type::T2 T2;
33877 typedef typename node_type::T3 T3;
33878
33879 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33880 const details::operator_type& operation,
33881 expression_node_ptr (&branch)[2])
33882 {
33883 // ((v0 o0 (v1 o1 v2)) o2 c)
33884 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33885
33886 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33887 const Type& v0 = vovov->t0();
33888 const Type& v1 = vovov->t1();
33889 const Type& v2 = vovov->t2();
33890 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33891 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33892 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33893 const details::operator_type o2 = operation;
33894
33895 binary_functor_t f0 = vovov->f0();
33896 binary_functor_t f1 = vovov->f1();
33897 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33898
33899 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33900 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33901
33902 expression_node_ptr result = error_node();
33903
33904 const bool synthesis_result =
33905 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33906 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33907
33908 if (synthesis_result)
33909 return result;
33910 else if (!expr_gen.valid_operator(o2,f2))
33911 return error_node();
33912
33913 exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
33914
33915 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33916 }
33917
33918 static inline std::string id(expression_generator<Type>& expr_gen,
33919 const details::operator_type o0,
33920 const details::operator_type o1,
33921 const details::operator_type o2)
33922 {
33923 return details::build_string()
33924 << "(t" << expr_gen.to_str(o0)
33925 << "(t" << expr_gen.to_str(o1)
33926 << "t)" << expr_gen.to_str(o2)
33927 << "t";
33928 }
33929 };
33930
33931 struct synthesize_vovocov_expression4
33932 {
33933 typedef typename vovocov_t::type4 node_type;
33934 typedef typename vovocov_t::sf4_type sf4_type;
33935 typedef typename node_type::T0 T0;
33936 typedef typename node_type::T1 T1;
33937 typedef typename node_type::T2 T2;
33938 typedef typename node_type::T3 T3;
33939
33940 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33941 const details::operator_type& operation,
33942 expression_node_ptr (&branch)[2])
33943 {
33944 // ((v0 o0 (v1 o1 c)) o2 v1)
33945 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33946
33947 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33948 const Type& v0 = vovoc->t0();
33949 const Type& v1 = vovoc->t1();
33950 const Type c = vovoc->t2();
33951 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33952 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33953 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33954 const details::operator_type o2 = operation;
33955
33956 binary_functor_t f0 = vovoc->f0();
33957 binary_functor_t f1 = vovoc->f1();
33958 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33959
33960 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33961
33962 expression_node_ptr result = error_node();
33963
33964 const bool synthesis_result =
33965 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33966 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33967
33968 if (synthesis_result)
33969 return result;
33970 else if (!expr_gen.valid_operator(o2,f2))
33971 return error_node();
33972
33973 exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
33974
33975 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33976 }
33977
33978 static inline std::string id(expression_generator<Type>& expr_gen,
33979 const details::operator_type o0,
33980 const details::operator_type o1,
33981 const details::operator_type o2)
33982 {
33983 return details::build_string()
33984 << "(t" << expr_gen.to_str(o0)
33985 << "(t" << expr_gen.to_str(o1)
33986 << "t)" << expr_gen.to_str(o2)
33987 << "t";
33988 }
33989 };
33990
33991 struct synthesize_vocovov_expression4
33992 {
33993 typedef typename vocovov_t::type4 node_type;
33994 typedef typename vocovov_t::sf4_type sf4_type;
33995 typedef typename node_type::T0 T0;
33996 typedef typename node_type::T1 T1;
33997 typedef typename node_type::T2 T2;
33998 typedef typename node_type::T3 T3;
33999
34000 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34001 const details::operator_type& operation,
34002 expression_node_ptr (&branch)[2])
34003 {
34004 // ((v0 o0 (c o1 v1)) o2 v2)
34005 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34006
34007 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34008 const Type& v0 = vocov->t0();
34009 const Type c = vocov->t1();
34010 const Type& v1 = vocov->t2();
34011 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34012 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34013 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34014 const details::operator_type o2 = operation;
34015
34016 binary_functor_t f0 = vocov->f0();
34017 binary_functor_t f1 = vocov->f1();
34018 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34019
34020 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34021 expression_node_ptr result = error_node();
34022
34023 const bool synthesis_result =
34024 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34025 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34026
34027 if (synthesis_result)
34028 return result;
34029 else if (!expr_gen.valid_operator(o2,f2))
34030 return error_node();
34031
34032 exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
34033
34034 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
34035 }
34036
34037 static inline std::string id(expression_generator<Type>& expr_gen,
34038 const details::operator_type o0,
34039 const details::operator_type o1,
34040 const details::operator_type o2)
34041 {
34042 return details::build_string()
34043 << "(t" << expr_gen.to_str(o0)
34044 << "(t" << expr_gen.to_str(o1)
34045 << "t)" << expr_gen.to_str(o2)
34046 << "t";
34047 }
34048 };
34049
34050 struct synthesize_covovov_expression4
34051 {
34052 typedef typename covovov_t::type4 node_type;
34053 typedef typename covovov_t::sf4_type sf4_type;
34054 typedef typename node_type::T0 T0;
34055 typedef typename node_type::T1 T1;
34056 typedef typename node_type::T2 T2;
34057 typedef typename node_type::T3 T3;
34058
34059 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34060 const details::operator_type& operation,
34061 expression_node_ptr (&branch)[2])
34062 {
34063 // ((c o0 (v0 o1 v1)) o2 v2)
34064 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34065
34066 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34067 const Type c = covov->t0();
34068 const Type& v0 = covov->t1();
34069 const Type& v1 = covov->t2();
34070 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34071 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34072 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34073 const details::operator_type o2 = operation;
34074
34075 binary_functor_t f0 = covov->f0();
34076 binary_functor_t f1 = covov->f1();
34077 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34078
34079 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34080
34081 expression_node_ptr result = error_node();
34082
34083 const bool synthesis_result =
34084 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34085 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34086
34087 if (synthesis_result)
34088 return result;
34089 else if (!expr_gen.valid_operator(o2,f2))
34090 return error_node();
34091
34092 exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
34093
34094 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34095 }
34096
34097 static inline std::string id(expression_generator<Type>& expr_gen,
34098 const details::operator_type o0,
34099 const details::operator_type o1,
34100 const details::operator_type o2)
34101 {
34102 return details::build_string()
34103 << "(t" << expr_gen.to_str(o0)
34104 << "(t" << expr_gen.to_str(o1)
34105 << "t)" << expr_gen.to_str(o2)
34106 << "t";
34107 }
34108 };
34109
34110 struct synthesize_covocov_expression4
34111 {
34112 typedef typename covocov_t::type4 node_type;
34113 typedef typename covocov_t::sf4_type sf4_type;
34114 typedef typename node_type::T0 T0;
34115 typedef typename node_type::T1 T1;
34116 typedef typename node_type::T2 T2;
34117 typedef typename node_type::T3 T3;
34118
34119 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34120 const details::operator_type& operation,
34121 expression_node_ptr (&branch)[2])
34122 {
34123 // ((c0 o0 (v0 o1 c1)) o2 v1)
34124 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
34125
34126 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34127 const Type c0 = covoc->t0();
34128 const Type& v0 = covoc->t1();
34129 const Type c1 = covoc->t2();
34130 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34131 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34132 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34133 const details::operator_type o2 = operation;
34134
34135 binary_functor_t f0 = covoc->f0();
34136 binary_functor_t f1 = covoc->f1();
34137 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34138
34139 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34140
34141 expression_node_ptr result = error_node();
34142
34143 const bool synthesis_result =
34144 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34145 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34146
34147 if (synthesis_result)
34148 return result;
34149 else if (!expr_gen.valid_operator(o2,f2))
34150 return error_node();
34151
34152 exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
34153
34154 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34155 }
34156
34157 static inline std::string id(expression_generator<Type>& expr_gen,
34158 const details::operator_type o0,
34159 const details::operator_type o1,
34160 const details::operator_type o2)
34161 {
34162 return details::build_string()
34163 << "(t" << expr_gen.to_str(o0)
34164 << "(t" << expr_gen.to_str(o1)
34165 << "t)" << expr_gen.to_str(o2)
34166 << "t";
34167 }
34168 };
34169
34170 struct synthesize_vocovoc_expression4
34171 {
34172 typedef typename vocovoc_t::type4 node_type;
34173 typedef typename vocovoc_t::sf4_type sf4_type;
34174 typedef typename node_type::T0 T0;
34175 typedef typename node_type::T1 T1;
34176 typedef typename node_type::T2 T2;
34177 typedef typename node_type::T3 T3;
34178
34179 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34180 const details::operator_type& operation,
34181 expression_node_ptr (&branch)[2])
34182 {
34183 // ((v0 o0 (c0 o1 v1)) o2 c1)
34184 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34185
34186 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34187 const Type& v0 = vocov->t0();
34188 const Type c0 = vocov->t1();
34189 const Type& v1 = vocov->t2();
34190 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34191 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34192 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34193 const details::operator_type o2 = operation;
34194
34195 binary_functor_t f0 = vocov->f0();
34196 binary_functor_t f1 = vocov->f1();
34197 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34198
34199 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34200 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34201
34202 expression_node_ptr result = error_node();
34203
34204 const bool synthesis_result =
34205 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34206 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34207
34208 if (synthesis_result)
34209 return result;
34210 else if (!expr_gen.valid_operator(o2,f2))
34211 return error_node();
34212
34213 exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
34214
34215 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34216 }
34217
34218 static inline std::string id(expression_generator<Type>& expr_gen,
34219 const details::operator_type o0,
34220 const details::operator_type o1,
34221 const details::operator_type o2)
34222 {
34223 return details::build_string()
34224 << "(t" << expr_gen.to_str(o0)
34225 << "(t" << expr_gen.to_str(o1)
34226 << "t)" << expr_gen.to_str(o2)
34227 << "t";
34228 }
34229 };
34230
34231 struct synthesize_covovoc_expression4
34232 {
34233 typedef typename covovoc_t::type4 node_type;
34234 typedef typename covovoc_t::sf4_type sf4_type;
34235 typedef typename node_type::T0 T0;
34236 typedef typename node_type::T1 T1;
34237 typedef typename node_type::T2 T2;
34238 typedef typename node_type::T3 T3;
34239
34240 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34241 const details::operator_type& operation,
34242 expression_node_ptr (&branch)[2])
34243 {
34244 // ((c0 o0 (v0 o1 v1)) o2 c1)
34245 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34246
34247 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34248 const Type c0 = covov->t0();
34249 const Type& v0 = covov->t1();
34250 const Type& v1 = covov->t2();
34251 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34252 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34253 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34254 const details::operator_type o2 = operation;
34255
34256 binary_functor_t f0 = covov->f0();
34257 binary_functor_t f1 = covov->f1();
34258 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34259
34260 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34261 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34262
34263 expression_node_ptr result = error_node();
34264
34265 const bool synthesis_result =
34266 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34267 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34268
34269 if (synthesis_result)
34270 return result;
34271 else if (!expr_gen.valid_operator(o2,f2))
34272 return error_node();
34273
34274 exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
34275
34276 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34277 }
34278
34279 static inline std::string id(expression_generator<Type>& expr_gen,
34280 const details::operator_type o0,
34281 const details::operator_type o1,
34282 const details::operator_type o2)
34283 {
34284 return details::build_string()
34285 << "(t" << expr_gen.to_str(o0)
34286 << "(t" << expr_gen.to_str(o1)
34287 << "t)" << expr_gen.to_str(o2)
34288 << "t";
34289 }
34290 };
34291
34292 struct synthesize_vococov_expression4
34293 {
34294 typedef typename vococov_t::type4 node_type;
34295 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
34296 {
34297 // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
34298 exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
34299 return error_node();
34300 }
34301
34302 static inline std::string id(expression_generator<Type>&,
34303 const details::operator_type, const details::operator_type, const details::operator_type)
34304 {
34305 return "INVALID";
34306 }
34307 };
34308 #endif
34309
34310 inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34311 {
34312 // Definition: uv o uv
34313 details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
34314 details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
34315 const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
34316 const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
34317 unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
34318 unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
34319 binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
34320
34321 if (!valid_operator(o0,u0))
34322 return error_node();
34323 else if (!valid_operator(o1,u1))
34324 return error_node();
34325 else if (!valid_operator(operation,f))
34326 return error_node();
34327
34328 expression_node_ptr result = error_node();
34329
34330 if (
34331 (details::e_neg == o0) &&
34332 (details::e_neg == o1)
34333 )
34334 {
34335 switch (operation)
34336 {
34337 // (-v0 + -v1) --> -(v0 + v1)
34338 case details::e_add : result = (*this)(details::e_neg,
34339 node_allocator_->
34340 allocate_rr<typename details::
34341 vov_node<Type,details::add_op<Type> > >(v0, v1));
34342 exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
34343 break;
34344
34345 // (-v0 - -v1) --> (v1 - v0)
34346 case details::e_sub : result = node_allocator_->
34347 allocate_rr<typename details::
34348 vov_node<Type,details::sub_op<Type> > >(v1, v0);
34349 exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
34350 break;
34351
34352 // (-v0 * -v1) --> (v0 * v1)
34353 case details::e_mul : result = node_allocator_->
34354 allocate_rr<typename details::
34355 vov_node<Type,details::mul_op<Type> > >(v0, v1);
34356 exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
34357 break;
34358
34359 // (-v0 / -v1) --> (v0 / v1)
34360 case details::e_div : result = node_allocator_->
34361 allocate_rr<typename details::
34362 vov_node<Type,details::div_op<Type> > >(v0, v1);
34363 exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
34364 break;
34365
34366 default : break;
34367 }
34368 }
34369
34370 if (0 == result)
34371 {
34372 result = node_allocator_->
34373 allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
34374 }
34375
34376 details::free_all_nodes(*node_allocator_,branch);
34377 return result;
34378 }
34379
34380 #undef basic_opr_switch_statements
34381 #undef extended_opr_switch_statements
34382 #undef unary_opr_switch_statements
34383
34384 #ifndef exprtk_disable_string_capabilities
34385
34386 #define string_opr_switch_statements \
34387 case_stmt(details:: e_lt ,details:: lt_op) \
34388 case_stmt(details:: e_lte ,details:: lte_op) \
34389 case_stmt(details:: e_gt ,details:: gt_op) \
34390 case_stmt(details:: e_gte ,details:: gte_op) \
34391 case_stmt(details:: e_eq ,details:: eq_op) \
34392 case_stmt(details:: e_ne ,details:: ne_op) \
34393 case_stmt(details::e_in ,details:: in_op) \
34394 case_stmt(details::e_like ,details:: like_op) \
34395 case_stmt(details::e_ilike,details::ilike_op) \
34396
34397 template <typename T0, typename T1>
34398 inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
34399 T0 s0, T1 s1,
34400 range_t rp0)
34401 {
34402 switch (opr)
34403 {
34404 #define case_stmt(op0,op1) \
34405 case op0 : return node_allocator_-> \
34406 allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34407 (s0, s1, rp0); \
34408
34409 string_opr_switch_statements
34410 #undef case_stmt
34411 default : return error_node();
34412 }
34413 }
34414
34415 template <typename T0, typename T1>
34416 inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
34417 T0 s0, T1 s1,
34418 range_t rp1)
34419 {
34420 switch (opr)
34421 {
34422 #define case_stmt(op0,op1) \
34423 case op0 : return node_allocator_-> \
34424 allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34425 (s0, s1, rp1); \
34426
34427 string_opr_switch_statements
34428 #undef case_stmt
34429 default : return error_node();
34430 }
34431 }
34432
34433 template <typename T0, typename T1>
34434 inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
34435 T0 s0, T1 s1,
34436 range_t rp0, range_t rp1)
34437 {
34438 switch (opr)
34439 {
34440 #define case_stmt(op0,op1) \
34441 case op0 : return node_allocator_-> \
34442 allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34443 (s0, s1, rp0, rp1); \
34444
34445 string_opr_switch_statements
34446 #undef case_stmt
34447 default : return error_node();
34448 }
34449 }
34450
34451 template <typename T0, typename T1>
34452 inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
34453 {
34454 switch (opr)
34455 {
34456 #define case_stmt(op0,op1) \
34457 case op0 : return node_allocator_-> \
34458 allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
34459
34460 string_opr_switch_statements
34461 #undef case_stmt
34462 default : return error_node();
34463 }
34464 }
34465
34466 inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34467 {
34468 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34469 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34470
34471 return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
34472 }
34473
34474 inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34475 {
34476 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34477 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34478 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34479
34480 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34481
34482 free_node(*node_allocator_,branch[0]);
34483
34484 return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
34485 }
34486
34487 inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34488 {
34489 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34490 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34491 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34492
34493 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34494
34495 free_node(*node_allocator_,branch[1]);
34496
34497 return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
34498 }
34499
34500 inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34501 {
34502 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34503 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34504 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34505
34506 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34507
34508 free_node(*node_allocator_,branch[1]);
34509
34510 return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
34511 }
34512
34513 inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34514 {
34515 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34516 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34517 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34518 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34519
34520 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34521 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34522
34523 details::free_node(*node_allocator_,branch[0]);
34524 details::free_node(*node_allocator_,branch[1]);
34525
34526 return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
34527 }
34528
34529 inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34530 {
34531 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34532 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34533
34534 details::free_node(*node_allocator_,branch[1]);
34535
34536 return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
34537 }
34538
34539 inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34540 {
34541 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34542 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34543
34544 details::free_node(*node_allocator_,branch[0]);
34545
34546 return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
34547 }
34548
34549 inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34550 {
34551 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
34552 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34553 range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34554
34555 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34556
34557 details::free_node(*node_allocator_,branch[0]);
34558 details::free_node(*node_allocator_,branch[1]);
34559
34560 return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
34561 }
34562
34563 inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34564 {
34565 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34566 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
34567 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34568
34569 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34570
34571 details::free_node(*node_allocator_,branch[0]);
34572 details::free_node(*node_allocator_,branch[1]);
34573
34574 return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
34575 }
34576
34577 inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34578 {
34579 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34580 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34581 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34582 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34583
34584 static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
34585 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34586
34587 details::free_node(*node_allocator_,branch[0]);
34588 details::free_node(*node_allocator_,branch[1]);
34589
34590 return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
34591 }
34592
34593 inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34594 {
34595 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34596 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34597
34598 expression_node_ptr result = error_node();
34599
34600 if (details::e_add == opr)
34601 result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
34602 else if (details::e_in == opr)
34603 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
34604 else if (details::e_like == opr)
34605 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
34606 else if (details::e_ilike == opr)
34607 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
34608 else
34609 {
34610 expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
34611
34612 const Type v = temp->value();
34613
34614 details::free_node(*node_allocator_,temp);
34615
34616 result = node_allocator_->allocate<literal_node_t>(v);
34617 }
34618
34619 details::free_all_nodes(*node_allocator_,branch);
34620
34621 return result;
34622 }
34623
34624 inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34625 {
34626 const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str ();
34627 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34628 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34629
34630 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34631
34632 free_node(*node_allocator_,branch[0]);
34633 free_node(*node_allocator_,branch[1]);
34634
34635 return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
34636 }
34637
34638 inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34639 {
34640 std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34641 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34642 range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34643
34644 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34645
34646 free_node(*node_allocator_,branch[0]);
34647
34648 return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
34649 }
34650
34651 inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34652 {
34653 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34654 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34655 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34656 const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34657
34658 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34659 static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
34660
34661 free_node(*node_allocator_,branch[0]);
34662 free_node(*node_allocator_,branch[1]);
34663
34664 return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
34665 }
34666
34667 inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34668 {
34669 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34670 const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str ();
34671 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34672
34673 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34674
34675 details::free_all_nodes(*node_allocator_,branch);
34676
34677 return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
34678 }
34679
34680 inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34681 {
34682 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34683 const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34684 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34685 const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34686
34687 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34688 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34689
34690 details::free_all_nodes(*node_allocator_,branch);
34691
34692 return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
34693 }
34694
34695 inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34696 {
34697 switch (opr)
34698 {
34699 #define case_stmt(op0,op1) \
34700 case op0 : return node_allocator_-> \
34701 allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
34702 (opr, branch[0], branch[1]); \
34703
34704 string_opr_switch_statements
34705 #undef case_stmt
34706 default : return error_node();
34707 }
34708 }
34709 #endif
34710
34711 #ifndef exprtk_disable_string_capabilities
34712 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34713 {
34714 if ((0 == branch[0]) || (0 == branch[1]))
34715 {
34716 details::free_all_nodes(*node_allocator_,branch);
34717
34718 return error_node();
34719 }
34720
34721 const bool b0_is_s = details::is_string_node (branch[0]);
34722 const bool b0_is_cs = details::is_const_string_node (branch[0]);
34723 const bool b0_is_sr = details::is_string_range_node (branch[0]);
34724 const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
34725
34726 const bool b1_is_s = details::is_string_node (branch[1]);
34727 const bool b1_is_cs = details::is_const_string_node (branch[1]);
34728 const bool b1_is_sr = details::is_string_range_node (branch[1]);
34729 const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
34730
34731 const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
34732 details::is_genricstring_range_node(branch[0]) ||
34733 details::is_string_concat_node (branch[0]) ||
34734 details::is_string_function_node (branch[0]) ||
34735 details::is_string_condition_node (branch[0]) ||
34736 details::is_string_ccondition_node (branch[0]) ||
34737 details::is_string_vararg_node (branch[0]) ;
34738
34739 const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
34740 details::is_genricstring_range_node(branch[1]) ||
34741 details::is_string_concat_node (branch[1]) ||
34742 details::is_string_function_node (branch[1]) ||
34743 details::is_string_condition_node (branch[1]) ||
34744 details::is_string_ccondition_node (branch[1]) ||
34745 details::is_string_vararg_node (branch[1]) ;
34746
34747 if (details::e_add == opr)
34748 {
34749 if (!b0_is_cs || !b1_is_cs)
34750 {
34751 return synthesize_expression<string_concat_node_t,2>(opr,branch);
34752 }
34753 }
34754
34755 if (b0_is_gen || b1_is_gen)
34756 {
34757 return synthesize_strogen_expression(opr,branch);
34758 }
34759 else if (b0_is_s)
34760 {
34761 if (b1_is_s ) return synthesize_sos_expression (opr,branch);
34762 else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
34763 else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
34764 else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
34765 }
34766 else if (b0_is_cs)
34767 {
34768 if (b1_is_s ) return synthesize_csos_expression (opr,branch);
34769 else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
34770 else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
34771 else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
34772 }
34773 else if (b0_is_sr)
34774 {
34775 if (b1_is_s ) return synthesize_sros_expression (opr,branch);
34776 else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
34777 else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
34778 else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
34779 }
34780 else if (b0_is_csr)
34781 {
34782 if (b1_is_s ) return synthesize_csros_expression (opr,branch);
34783 else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
34784 else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
34785 else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
34786 }
34787
34788 return error_node();
34789 }
34790 #else
34791 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
34792 {
34793 details::free_all_nodes(*node_allocator_,branch);
34794 return error_node();
34795 }
34796 #endif
34797
34798 #ifndef exprtk_disable_string_capabilities
34799 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
34800 {
34801 if (details::e_inrange != opr)
34802 return error_node();
34803 else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
34804 {
34805 details::free_all_nodes(*node_allocator_,branch);
34806
34807 return error_node();
34808 }
34809 else if (
34810 details::is_const_string_node(branch[0]) &&
34811 details::is_const_string_node(branch[1]) &&
34812 details::is_const_string_node(branch[2])
34813 )
34814 {
34815 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34816 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34817 const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34818
34819 const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
34820
34821 details::free_all_nodes(*node_allocator_,branch);
34822
34823 return node_allocator_->allocate_c<details::literal_node<Type> >(v);
34824 }
34825 else if (
34826 details::is_string_node(branch[0]) &&
34827 details::is_string_node(branch[1]) &&
34828 details::is_string_node(branch[2])
34829 )
34830 {
34831 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34832 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34833 std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
34834
34835 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34836
34837 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
34838 }
34839 else if (
34840 details::is_const_string_node(branch[0]) &&
34841 details::is_string_node(branch[1]) &&
34842 details::is_const_string_node(branch[2])
34843 )
34844 {
34845 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34846 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34847 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34848
34849 typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34850
34851 details::free_node(*node_allocator_,branch[0]);
34852 details::free_node(*node_allocator_,branch[2]);
34853
34854 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
34855 }
34856 else if (
34857 details::is_string_node(branch[0]) &&
34858 details::is_const_string_node(branch[1]) &&
34859 details::is_string_node(branch[2])
34860 )
34861 {
34862 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34863 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34864 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34865
34866 typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
34867
34868 details::free_node(*node_allocator_,branch[1]);
34869
34870 return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
34871 }
34872 else if (
34873 details::is_string_node(branch[0]) &&
34874 details::is_string_node(branch[1]) &&
34875 details::is_const_string_node(branch[2])
34876 )
34877 {
34878 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34879 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34880 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34881
34882 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34883
34884 details::free_node(*node_allocator_,branch[2]);
34885
34886 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
34887 }
34888 else if (
34889 details::is_const_string_node(branch[0]) &&
34890 details:: is_string_node(branch[1]) &&
34891 details:: is_string_node(branch[2])
34892 )
34893 {
34894 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34895 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34896 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34897
34898 typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34899
34900 details::free_node(*node_allocator_,branch[0]);
34901
34902 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
34903 }
34904 else
34905 return error_node();
34906 }
34907 #else
34908 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
34909 {
34910 details::free_all_nodes(*node_allocator_,branch);
34911 return error_node();
34912 }
34913 #endif
34914
34915 inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34916 {
34917 /*
34918 Note: The following are the type promotion rules
34919 that relate to operations that include 'null':
34920 0. null ==/!= null --> true false
34921 1. null operation null --> null
34922 2. x ==/!= null --> true/false
34923 3. null ==/!= x --> true/false
34924 4. x operation null --> x
34925 5. null operation x --> x
34926 */
34927
34928 typedef typename details::null_eq_node<T> nulleq_node_t;
34929
34930 const bool b0_null = details::is_null_node(branch[0]);
34931 const bool b1_null = details::is_null_node(branch[1]);
34932
34933 if (b0_null && b1_null)
34934 {
34935 expression_node_ptr result = error_node();
34936
34937 if (details::e_eq == operation)
34938 result = node_allocator_->allocate_c<literal_node_t>(T(1));
34939 else if (details::e_ne == operation)
34940 result = node_allocator_->allocate_c<literal_node_t>(T(0));
34941
34942 if (result)
34943 {
34944 details::free_node(*node_allocator_,branch[0]);
34945 details::free_node(*node_allocator_,branch[1]);
34946
34947 return result;
34948 }
34949
34950 details::free_node(*node_allocator_,branch[1]);
34951
34952 return branch[0];
34953 }
34954 else if (details::e_eq == operation)
34955 {
34956 expression_node_ptr result = node_allocator_->
34957 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
34958
34959 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34960
34961 return result;
34962 }
34963 else if (details::e_ne == operation)
34964 {
34965 expression_node_ptr result = node_allocator_->
34966 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
34967
34968 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34969
34970 return result;
34971 }
34972 else if (b0_null)
34973 {
34974 details::free_node(*node_allocator_,branch[0]);
34975 branch[0] = branch[1];
34976 branch[1] = error_node();
34977 }
34978 else if (b1_null)
34979 {
34980 details::free_node(*node_allocator_,branch[1]);
34981 branch[1] = error_node();
34982 }
34983
34984 if (
34985 (details::e_add == operation) || (details::e_sub == operation) ||
34986 (details::e_mul == operation) || (details::e_div == operation) ||
34987 (details::e_mod == operation) || (details::e_pow == operation)
34988 )
34989 {
34990 return branch[0];
34991 }
34992 else if (
34993 (details::e_lt == operation) || (details::e_lte == operation) ||
34994 (details::e_gt == operation) || (details::e_gte == operation) ||
34995 (details::e_and == operation) || (details::e_nand == operation) ||
34996 (details::e_or == operation) || (details::e_nor == operation) ||
34997 (details::e_xor == operation) || (details::e_xnor == operation) ||
34998 (details::e_in == operation) || (details::e_like == operation) ||
34999 (details::e_ilike == operation)
35000 )
35001 {
35002 return node_allocator_->allocate_c<literal_node_t>(T(0));
35003 }
35004
35005 details::free_node(*node_allocator_,branch[0]);
35006
35007 return node_allocator_->allocate<details::null_node<Type> >();
35008 }
35009
35010 template <typename NodeType, std::size_t N>
35011 inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
35012 {
35013 if (
35014 (details::e_in == operation) ||
35015 (details::e_like == operation) ||
35016 (details::e_ilike == operation)
35017 )
35018 {
35019 free_all_nodes(*node_allocator_,branch);
35020
35021 return error_node();
35022 }
35023 else if (!details::all_nodes_valid<N>(branch))
35024 {
35025 free_all_nodes(*node_allocator_,branch);
35026
35027 return error_node();
35028 }
35029 else if ((details::e_default != operation))
35030 {
35031 // Attempt simple constant folding optimisation.
35032 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
35033
35034 if (is_constant_foldable<N>(branch))
35035 {
35036 const Type v = expression_point->value();
35037 details::free_node(*node_allocator_,expression_point);
35038
35039 return node_allocator_->allocate<literal_node_t>(v);
35040 }
35041 else
35042 return expression_point;
35043 }
35044 else
35045 return error_node();
35046 }
35047
35048 template <typename NodeType, std::size_t N>
35049 inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
35050 {
35051 if (!details::all_nodes_valid<N>(branch))
35052 {
35053 free_all_nodes(*node_allocator_,branch);
35054
35055 return error_node();
35056 }
35057
35058 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
35059
35060 // Attempt simple constant folding optimisation.
35061
35062 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
35063 function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
35064
35065 if (0 == func_node_ptr)
35066 {
35067 free_all_nodes(*node_allocator_,branch);
35068
35069 return error_node();
35070 }
35071 else
35072 func_node_ptr->init_branches(branch);
35073
35074 if (is_constant_foldable<N>(branch) && !f->has_side_effects())
35075 {
35076 Type v = expression_point->value();
35077 details::free_node(*node_allocator_,expression_point);
35078
35079 return node_allocator_->allocate<literal_node_t>(v);
35080 }
35081
35082 parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
35083
35084 return expression_point;
35085 }
35086
35087 bool strength_reduction_enabled_;
35088 details::node_allocator* node_allocator_;
35089 synthesize_map_t synthesize_map_;
35090 unary_op_map_t* unary_op_map_;
35091 binary_op_map_t* binary_op_map_;
35092 inv_binary_op_map_t* inv_binary_op_map_;
35093 sf3_map_t* sf3_map_;
35094 sf4_map_t* sf4_map_;
35095 parser_t* parser_;
35096 };
35097
35098 inline void set_error(const parser_error::type& error_type)
35099 {
35100 error_list_.push_back(error_type);
35101 }
35102
35103 inline void remove_last_error()
35104 {
35105 if (!error_list_.empty())
35106 {
35107 error_list_.pop_back();
35108 }
35109 }
35110
35111 inline void set_synthesis_error(const std::string& synthesis_error_message)
35112 {
35113 if (synthesis_error_.empty())
35114 {
35115 synthesis_error_ = synthesis_error_message;
35116 }
35117 }
35118
35119 inline void register_local_vars(expression<T>& e)
35120 {
35121 for (std::size_t i = 0; i < sem_.size(); ++i)
35122 {
35123 scope_element& se = sem_.get_element(i);
35124
35125 if (
35126 (scope_element::e_variable == se.type) ||
35127 (scope_element::e_vecelem == se.type)
35128 )
35129 {
35130 if (se.var_node)
35131 {
35132 e.register_local_var(se.var_node);
35133 }
35134
35135 if (se.data)
35136 {
35137 e.register_local_data(se.data, 1, 0);
35138 }
35139 }
35140 else if (scope_element::e_vector == se.type)
35141 {
35142 if (se.vec_node)
35143 {
35144 e.register_local_var(se.vec_node);
35145 }
35146
35147 if (se.data)
35148 {
35149 e.register_local_data(se.data, se.size, 1);
35150 }
35151 }
35152 #ifndef exprtk_disable_string_capabilities
35153 else if (scope_element::e_string == se.type)
35154 {
35155 if (se.str_node)
35156 {
35157 e.register_local_var(se.str_node);
35158 }
35159
35160 if (se.data)
35161 {
35162 e.register_local_data(se.data, se.size, 2);
35163 }
35164 }
35165 #endif
35166
35167 se.var_node = 0;
35168 se.vec_node = 0;
35169 #ifndef exprtk_disable_string_capabilities
35170 se.str_node = 0;
35171 #endif
35172 se.data = 0;
35173 se.ref_count = 0;
35174 se.active = false;
35175 }
35176 }
35177
35178 inline void register_return_results(expression<T>& e)
35179 {
35180 e.register_return_results(results_context_);
35181 results_context_ = 0;
35182 }
35183
35184 inline void load_unary_operations_map(unary_op_map_t& m)
35185 {
35186 #define register_unary_op(Op,UnaryFunctor) \
35187 m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
35188
35189 register_unary_op(details:: e_abs, details:: abs_op)
35190 register_unary_op(details:: e_acos, details:: acos_op)
35191 register_unary_op(details::e_acosh, details::acosh_op)
35192 register_unary_op(details:: e_asin, details:: asin_op)
35193 register_unary_op(details::e_asinh, details::asinh_op)
35194 register_unary_op(details::e_atanh, details::atanh_op)
35195 register_unary_op(details:: e_ceil, details:: ceil_op)
35196 register_unary_op(details:: e_cos, details:: cos_op)
35197 register_unary_op(details:: e_cosh, details:: cosh_op)
35198 register_unary_op(details:: e_exp, details:: exp_op)
35199 register_unary_op(details::e_expm1, details::expm1_op)
35200 register_unary_op(details::e_floor, details::floor_op)
35201 register_unary_op(details:: e_log, details:: log_op)
35202 register_unary_op(details::e_log10, details::log10_op)
35203 register_unary_op(details:: e_log2, details:: log2_op)
35204 register_unary_op(details::e_log1p, details::log1p_op)
35205 register_unary_op(details:: e_neg, details:: neg_op)
35206 register_unary_op(details:: e_pos, details:: pos_op)
35207 register_unary_op(details::e_round, details::round_op)
35208 register_unary_op(details:: e_sin, details:: sin_op)
35209 register_unary_op(details:: e_sinc, details:: sinc_op)
35210 register_unary_op(details:: e_sinh, details:: sinh_op)
35211 register_unary_op(details:: e_sqrt, details:: sqrt_op)
35212 register_unary_op(details:: e_tan, details:: tan_op)
35213 register_unary_op(details:: e_tanh, details:: tanh_op)
35214 register_unary_op(details:: e_cot, details:: cot_op)
35215 register_unary_op(details:: e_sec, details:: sec_op)
35216 register_unary_op(details:: e_csc, details:: csc_op)
35217 register_unary_op(details:: e_r2d, details:: r2d_op)
35218 register_unary_op(details:: e_d2r, details:: d2r_op)
35219 register_unary_op(details:: e_d2g, details:: d2g_op)
35220 register_unary_op(details:: e_g2d, details:: g2d_op)
35221 register_unary_op(details:: e_notl, details:: notl_op)
35222 register_unary_op(details:: e_sgn, details:: sgn_op)
35223 register_unary_op(details:: e_erf, details:: erf_op)
35224 register_unary_op(details:: e_erfc, details:: erfc_op)
35225 register_unary_op(details:: e_ncdf, details:: ncdf_op)
35226 register_unary_op(details:: e_frac, details:: frac_op)
35227 register_unary_op(details::e_trunc, details::trunc_op)
35228 #undef register_unary_op
35229 }
35230
35231 inline void load_binary_operations_map(binary_op_map_t& m)
35232 {
35233 typedef typename binary_op_map_t::value_type value_type;
35234
35235 #define register_binary_op(Op,BinaryFunctor) \
35236 m.insert(value_type(Op,BinaryFunctor<T>::process)); \
35237
35238 register_binary_op(details:: e_add, details:: add_op)
35239 register_binary_op(details:: e_sub, details:: sub_op)
35240 register_binary_op(details:: e_mul, details:: mul_op)
35241 register_binary_op(details:: e_div, details:: div_op)
35242 register_binary_op(details:: e_mod, details:: mod_op)
35243 register_binary_op(details:: e_pow, details:: pow_op)
35244 register_binary_op(details:: e_lt, details:: lt_op)
35245 register_binary_op(details:: e_lte, details:: lte_op)
35246 register_binary_op(details:: e_gt, details:: gt_op)
35247 register_binary_op(details:: e_gte, details:: gte_op)
35248 register_binary_op(details:: e_eq, details:: eq_op)
35249 register_binary_op(details:: e_ne, details:: ne_op)
35250 register_binary_op(details:: e_and, details:: and_op)
35251 register_binary_op(details::e_nand, details::nand_op)
35252 register_binary_op(details:: e_or, details:: or_op)
35253 register_binary_op(details:: e_nor, details:: nor_op)
35254 register_binary_op(details:: e_xor, details:: xor_op)
35255 register_binary_op(details::e_xnor, details::xnor_op)
35256 #undef register_binary_op
35257 }
35258
35259 inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
35260 {
35261 typedef typename inv_binary_op_map_t::value_type value_type;
35262
35263 #define register_binary_op(Op,BinaryFunctor) \
35264 m.insert(value_type(BinaryFunctor<T>::process,Op)); \
35265
35266 register_binary_op(details:: e_add, details:: add_op)
35267 register_binary_op(details:: e_sub, details:: sub_op)
35268 register_binary_op(details:: e_mul, details:: mul_op)
35269 register_binary_op(details:: e_div, details:: div_op)
35270 register_binary_op(details:: e_mod, details:: mod_op)
35271 register_binary_op(details:: e_pow, details:: pow_op)
35272 register_binary_op(details:: e_lt, details:: lt_op)
35273 register_binary_op(details:: e_lte, details:: lte_op)
35274 register_binary_op(details:: e_gt, details:: gt_op)
35275 register_binary_op(details:: e_gte, details:: gte_op)
35276 register_binary_op(details:: e_eq, details:: eq_op)
35277 register_binary_op(details:: e_ne, details:: ne_op)
35278 register_binary_op(details:: e_and, details:: and_op)
35279 register_binary_op(details::e_nand, details::nand_op)
35280 register_binary_op(details:: e_or, details:: or_op)
35281 register_binary_op(details:: e_nor, details:: nor_op)
35282 register_binary_op(details:: e_xor, details:: xor_op)
35283 register_binary_op(details::e_xnor, details::xnor_op)
35284 #undef register_binary_op
35285 }
35286
35287 inline void load_sf3_map(sf3_map_t& sf3_map)
35288 {
35289 typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
35290
35291 #define register_sf3(Op) \
35292 sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35293
35294 register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
35295 register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
35296 register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
35297 register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
35298 register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
35299 register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
35300 register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
35301 register_sf3(28) register_sf3(29) register_sf3(30)
35302 #undef register_sf3
35303
35304 #define register_sf3_extid(Id, Op) \
35305 sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35306
35307 register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
35308 #undef register_sf3_extid
35309 }
35310
35311 inline void load_sf4_map(sf4_map_t& sf4_map)
35312 {
35313 typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
35314
35315 #define register_sf4(Op) \
35316 sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35317
35318 register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
35319 register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
35320 register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
35321 register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
35322 register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
35323 register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
35324 register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
35325 register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
35326 register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
35327 #undef register_sf4
35328
35329 #define register_sf4ext(Op) \
35330 sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
35331
35332 register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
35333 register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
35334 register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
35335 register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
35336 register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
35337 register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
35338 register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
35339 register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
35340 register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
35341 register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
35342 register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
35343 register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
35344 register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
35345 register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
35346 register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
35347 register_sf4ext(60) register_sf4ext(61)
35348 #undef register_sf4ext
35349 }
35350
35351 inline results_context_t& results_ctx()
35352 {
35353 if (0 == results_context_)
35354 {
35355 results_context_ = new results_context_t();
35356 }
35357
35358 return (*results_context_);
35359 }
35360
35361 inline void return_cleanup()
35362 {
35363 #ifndef exprtk_disable_return_statement
35364 if (results_context_)
35365 {
35366 delete results_context_;
35367 results_context_ = 0;
35368 }
35369
35370 state_.return_stmt_present = false;
35371 #endif
35372 }
35373
35374 private:
35375
35376 parser(const parser<T>&);
35377 parser<T>& operator=(const parser<T>&);
35378
35379 settings_store settings_;
35380 expression_generator<T> expression_generator_;
35381 details::node_allocator node_allocator_;
35382 symtab_store symtab_store_;
35383 dependent_entity_collector dec_;
35384 std::deque<parser_error::type> error_list_;
35385 std::deque<bool> brkcnt_list_;
35386 parser_state state_;
35387 bool resolve_unknown_symbol_;
35388 results_context_t* results_context_;
35389 unknown_symbol_resolver* unknown_symbol_resolver_;
35390 unknown_symbol_resolver default_usr_;
35391 base_ops_map_t base_ops_map_;
35392 unary_op_map_t unary_op_map_;
35393 binary_op_map_t binary_op_map_;
35394 inv_binary_op_map_t inv_binary_op_map_;
35395 sf3_map_t sf3_map_;
35396 sf4_map_t sf4_map_;
35397 std::string synthesis_error_;
35398 scope_element_manager sem_;
35399
35400 lexer::helper::helper_assembly helper_assembly_;
35401
35402 lexer::helper::commutative_inserter commutative_inserter_;
35403 lexer::helper::operator_joiner operator_joiner_2_;
35404 lexer::helper::operator_joiner operator_joiner_3_;
35405 lexer::helper::symbol_replacer symbol_replacer_;
35406 lexer::helper::bracket_checker bracket_checker_;
35407 lexer::helper::numeric_checker numeric_checker_;
35408 lexer::helper::sequence_validator sequence_validator_;
35409 lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
35410
35411 template <typename ParserType>
35412 friend void details::disable_type_checking(ParserType& p);
35413 };
35414
35415 namespace details
35416 {
35417 template <typename T>
35418 struct collector_helper
35419 {
35420 typedef exprtk::symbol_table<T> symbol_table_t;
35421 typedef exprtk::expression<T> expression_t;
35422 typedef exprtk::parser<T> parser_t;
35423 typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35424 typedef typename parser_t::unknown_symbol_resolver usr_t;
35425
35426 struct resolve_as_vector : public parser_t::unknown_symbol_resolver
35427 {
35428 typedef exprtk::parser<T> parser_t;
35429
35430 resolve_as_vector()
35431 : usr_t(usr_t::e_usrmode_extended)
35432 {}
35433
35434 virtual bool process(const std::string& unknown_symbol,
35435 symbol_table_t& symbol_table,
35436 std::string&)
35437 {
35438 static T v[1];
35439 symbol_table.add_vector(unknown_symbol,v);
35440 return true;
35441 }
35442 };
35443
35444 static inline bool collection_pass(const std::string& expression_string,
35445 std::set<std::string>& symbol_set,
35446 const bool collect_variables,
35447 const bool collect_functions,
35448 const bool vector_pass,
35449 symbol_table_t& ext_symbol_table)
35450 {
35451 symbol_table_t symbol_table;
35452 expression_t expression;
35453 parser_t parser;
35454
35455 resolve_as_vector vect_resolver;
35456
35457 expression.register_symbol_table(symbol_table );
35458 expression.register_symbol_table(ext_symbol_table);
35459
35460 if (vector_pass)
35461 parser.enable_unknown_symbol_resolver(&vect_resolver);
35462 else
35463 parser.enable_unknown_symbol_resolver();
35464
35465 if (collect_variables)
35466 parser.dec().collect_variables() = true;
35467
35468 if (collect_functions)
35469 parser.dec().collect_functions() = true;
35470
35471 bool pass_result = false;
35472
35473 details::disable_type_checking(parser);
35474
35475 if (parser.compile(expression_string, expression))
35476 {
35477 pass_result = true;
35478
35479 std::deque<symbol_t> symb_list;
35480 parser.dec().symbols(symb_list);
35481
35482 for (std::size_t i = 0; i < symb_list.size(); ++i)
35483 {
35484 symbol_set.insert(symb_list[i].first);
35485 }
35486 }
35487
35488 return pass_result;
35489 }
35490 };
35491 }
35492
35493 template <typename Allocator,
35494 template <typename, typename> class Sequence>
35495 inline bool collect_variables(const std::string& expression,
35496 Sequence<std::string, Allocator>& symbol_list)
35497 {
35498 typedef double T;
35499 typedef details::collector_helper<T> collect_t;
35500
35501 collect_t::symbol_table_t null_symbol_table;
35502
35503 std::set<std::string> symbol_set;
35504
35505 const bool variable_pass = collect_t::collection_pass
35506 (expression, symbol_set, true, false, false, null_symbol_table);
35507 const bool vector_pass = collect_t::collection_pass
35508 (expression, symbol_set, true, false, true, null_symbol_table);
35509
35510 if (!variable_pass && !vector_pass)
35511 return false;
35512
35513 std::set<std::string>::iterator itr = symbol_set.begin();
35514
35515 while (symbol_set.end() != itr)
35516 {
35517 symbol_list.push_back(*itr);
35518 ++itr;
35519 }
35520
35521 return true;
35522 }
35523
35524 template <typename T,
35525 typename Allocator,
35526 template <typename, typename> class Sequence>
35527 inline bool collect_variables(const std::string& expression,
35528 exprtk::symbol_table<T>& extrnl_symbol_table,
35529 Sequence<std::string, Allocator>& symbol_list)
35530 {
35531 typedef details::collector_helper<T> collect_t;
35532
35533 std::set<std::string> symbol_set;
35534
35535 const bool variable_pass = collect_t::collection_pass
35536 (expression, symbol_set, true, false, false, extrnl_symbol_table);
35537 const bool vector_pass = collect_t::collection_pass
35538 (expression, symbol_set, true, false, true, extrnl_symbol_table);
35539
35540 if (!variable_pass && !vector_pass)
35541 return false;
35542
35543 std::set<std::string>::iterator itr = symbol_set.begin();
35544
35545 while (symbol_set.end() != itr)
35546 {
35547 symbol_list.push_back(*itr);
35548 ++itr;
35549 }
35550
35551 return true;
35552 }
35553
35554 template <typename Allocator,
35555 template <typename, typename> class Sequence>
35556 inline bool collect_functions(const std::string& expression,
35557 Sequence<std::string, Allocator>& symbol_list)
35558 {
35559 typedef double T;
35560 typedef details::collector_helper<T> collect_t;
35561
35562 collect_t::symbol_table_t null_symbol_table;
35563
35564 std::set<std::string> symbol_set;
35565
35566 const bool variable_pass = collect_t::collection_pass
35567 (expression, symbol_set, false, true, false, null_symbol_table);
35568 const bool vector_pass = collect_t::collection_pass
35569 (expression, symbol_set, false, true, true, null_symbol_table);
35570
35571 if (!variable_pass && !vector_pass)
35572 return false;
35573
35574 std::set<std::string>::iterator itr = symbol_set.begin();
35575
35576 while (symbol_set.end() != itr)
35577 {
35578 symbol_list.push_back(*itr);
35579 ++itr;
35580 }
35581
35582 return true;
35583 }
35584
35585 template <typename T,
35586 typename Allocator,
35587 template <typename, typename> class Sequence>
35588 inline bool collect_functions(const std::string& expression,
35589 exprtk::symbol_table<T>& extrnl_symbol_table,
35590 Sequence<std::string, Allocator>& symbol_list)
35591 {
35592 typedef details::collector_helper<T> collect_t;
35593
35594 std::set<std::string> symbol_set;
35595
35596 const bool variable_pass = collect_t::collection_pass
35597 (expression, symbol_set, false, true, false, extrnl_symbol_table);
35598 const bool vector_pass = collect_t::collection_pass
35599 (expression, symbol_set, false, true, true, extrnl_symbol_table);
35600
35601 if (!variable_pass && !vector_pass)
35602 return false;
35603
35604 std::set<std::string>::iterator itr = symbol_set.begin();
35605
35606 while (symbol_set.end() != itr)
35607 {
35608 symbol_list.push_back(*itr);
35609 ++itr;
35610 }
35611
35612 return true;
35613 }
35614
35615 template <typename T>
35616 inline T integrate(const expression<T>& e,
35617 T& x,
35618 const T& r0, const T& r1,
35619 const std::size_t number_of_intervals = 1000000)
35620 {
35621 if (r0 > r1)
35622 return T(0);
35623
35624 const T h = (r1 - r0) / (T(2) * number_of_intervals);
35625 T total_area = T(0);
35626
35627 for (std::size_t i = 0; i < number_of_intervals; ++i)
35628 {
35629 x = r0 + T(2) * i * h;
35630 const T y0 = e.value(); x += h;
35631 const T y1 = e.value(); x += h;
35632 const T y2 = e.value(); x += h;
35633 total_area += h * (y0 + T(4) * y1 + y2) / T(3);
35634 }
35635
35636 return total_area;
35637 }
35638
35639 template <typename T>
35640 inline T integrate(const expression<T>& e,
35641 const std::string& variable_name,
35642 const T& r0, const T& r1,
35643 const std::size_t number_of_intervals = 1000000)
35644 {
35645 const symbol_table<T>& sym_table = e.get_symbol_table();
35646
35647 if (!sym_table.valid())
35648 return std::numeric_limits<T>::quiet_NaN();
35649
35650 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35651
35652 if (var)
35653 {
35654 T& x = var->ref();
35655 T x_original = x;
35656 T result = integrate(e, x, r0, r1, number_of_intervals);
35657 x = x_original;
35658
35659 return result;
35660 }
35661 else
35662 return std::numeric_limits<T>::quiet_NaN();
35663 }
35664
35665 template <typename T>
35666 inline T derivative(const expression<T>& e,
35667 T& x,
35668 const T& h = T(0.00000001))
35669 {
35670 const T x_init = x;
35671 const T _2h = T(2) * h;
35672
35673 x = x_init + _2h;
35674 const T y0 = e.value();
35675 x = x_init + h;
35676 const T y1 = e.value();
35677 x = x_init - h;
35678 const T y2 = e.value();
35679 x = x_init - _2h;
35680 const T y3 = e.value();
35681 x = x_init;
35682
35683 return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
35684 }
35685
35686 template <typename T>
35687 inline T second_derivative(const expression<T>& e,
35688 T& x,
35689 const T& h = T(0.00001))
35690 {
35691 const T x_init = x;
35692 const T _2h = T(2) * h;
35693
35694 const T y = e.value();
35695 x = x_init + _2h;
35696 const T y0 = e.value();
35697 x = x_init + h;
35698 const T y1 = e.value();
35699 x = x_init - h;
35700 const T y2 = e.value();
35701 x = x_init - _2h;
35702 const T y3 = e.value();
35703 x = x_init;
35704
35705 return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
35706 }
35707
35708 template <typename T>
35709 inline T third_derivative(const expression<T>& e,
35710 T& x,
35711 const T& h = T(0.0001))
35712 {
35713 const T x_init = x;
35714 const T _2h = T(2) * h;
35715
35716 x = x_init + _2h;
35717 const T y0 = e.value();
35718 x = x_init + h;
35719 const T y1 = e.value();
35720 x = x_init - h;
35721 const T y2 = e.value();
35722 x = x_init - _2h;
35723 const T y3 = e.value();
35724 x = x_init;
35725
35726 return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
35727 }
35728
35729 template <typename T>
35730 inline T derivative(const expression<T>& e,
35731 const std::string& variable_name,
35732 const T& h = T(0.00000001))
35733 {
35734 const symbol_table<T>& sym_table = e.get_symbol_table();
35735
35736 if (!sym_table.valid())
35737 {
35738 return std::numeric_limits<T>::quiet_NaN();
35739 }
35740
35741 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35742
35743 if (var)
35744 {
35745 T& x = var->ref();
35746 T x_original = x;
35747 T result = derivative(e, x, h);
35748 x = x_original;
35749
35750 return result;
35751 }
35752 else
35753 return std::numeric_limits<T>::quiet_NaN();
35754 }
35755
35756 template <typename T>
35757 inline T second_derivative(const expression<T>& e,
35758 const std::string& variable_name,
35759 const T& h = T(0.00001))
35760 {
35761 const symbol_table<T>& sym_table = e.get_symbol_table();
35762
35763 if (!sym_table.valid())
35764 {
35765 return std::numeric_limits<T>::quiet_NaN();
35766 }
35767
35768 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35769
35770 if (var)
35771 {
35772 T& x = var->ref();
35773 const T x_original = x;
35774 const T result = second_derivative(e, x, h);
35775 x = x_original;
35776
35777 return result;
35778 }
35779 else
35780 return std::numeric_limits<T>::quiet_NaN();
35781 }
35782
35783 template <typename T>
35784 inline T third_derivative(const expression<T>& e,
35785 const std::string& variable_name,
35786 const T& h = T(0.0001))
35787 {
35788 const symbol_table<T>& sym_table = e.get_symbol_table();
35789
35790 if (!sym_table.valid())
35791 {
35792 return std::numeric_limits<T>::quiet_NaN();
35793 }
35794
35795 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35796
35797 if (var)
35798 {
35799 T& x = var->ref();
35800 const T x_original = x;
35801 const T result = third_derivative(e, x, h);
35802 x = x_original;
35803
35804 return result;
35805 }
35806 else
35807 return std::numeric_limits<T>::quiet_NaN();
35808 }
35809
35810 /*
35811 Note: The following 'compute' routines are simple helpers,
35812 for quickly setting up the required pieces of code in order
35813 to evaluate an expression. By virtue of how they operate
35814 there will be an overhead with regards to their setup and
35815 teardown and hence should not be used in time critical
35816 sections of code.
35817 Furthermore they only assume a small sub set of variables,
35818 no string variables or user defined functions.
35819 */
35820 template <typename T>
35821 inline bool compute(const std::string& expression_string, T& result)
35822 {
35823 // No variables
35824 symbol_table<T> symbol_table;
35825 symbol_table.add_constants();
35826
35827 expression<T> expression;
35828 expression.register_symbol_table(symbol_table);
35829
35830 parser<T> parser;
35831
35832 if (parser.compile(expression_string,expression))
35833 {
35834 result = expression.value();
35835
35836 return true;
35837 }
35838 else
35839 return false;
35840 }
35841
35842 template <typename T>
35843 inline bool compute(const std::string& expression_string,
35844 const T& x,
35845 T& result)
35846 {
35847 // Only 'x'
35848 static const std::string x_var("x");
35849
35850 symbol_table<T> symbol_table;
35851 symbol_table.add_constants();
35852 symbol_table.add_constant(x_var,x);
35853
35854 expression<T> expression;
35855 expression.register_symbol_table(symbol_table);
35856
35857 parser<T> parser;
35858
35859 if (parser.compile(expression_string,expression))
35860 {
35861 result = expression.value();
35862
35863 return true;
35864 }
35865 else
35866 return false;
35867 }
35868
35869 template <typename T>
35870 inline bool compute(const std::string& expression_string,
35871 const T&x, const T& y,
35872 T& result)
35873 {
35874 // Only 'x' and 'y'
35875 static const std::string x_var("x");
35876 static const std::string y_var("y");
35877
35878 symbol_table<T> symbol_table;
35879 symbol_table.add_constants();
35880 symbol_table.add_constant(x_var,x);
35881 symbol_table.add_constant(y_var,y);
35882
35883 expression<T> expression;
35884 expression.register_symbol_table(symbol_table);
35885
35886 parser<T> parser;
35887
35888 if (parser.compile(expression_string,expression))
35889 {
35890 result = expression.value();
35891
35892 return true;
35893 }
35894 else
35895 return false;
35896 }
35897
35898 template <typename T>
35899 inline bool compute(const std::string& expression_string,
35900 const T& x, const T& y, const T& z,
35901 T& result)
35902 {
35903 // Only 'x', 'y' or 'z'
35904 static const std::string x_var("x");
35905 static const std::string y_var("y");
35906 static const std::string z_var("z");
35907
35908 symbol_table<T> symbol_table;
35909 symbol_table.add_constants();
35910 symbol_table.add_constant(x_var,x);
35911 symbol_table.add_constant(y_var,y);
35912 symbol_table.add_constant(z_var,z);
35913
35914 expression<T> expression;
35915 expression.register_symbol_table(symbol_table);
35916
35917 parser<T> parser;
35918
35919 if (parser.compile(expression_string,expression))
35920 {
35921 result = expression.value();
35922
35923 return true;
35924 }
35925 else
35926 return false;
35927 }
35928
35929 template <typename T, std::size_t N>
35930 class polynomial : public ifunction<T>
35931 {
35932 private:
35933
35934 template <typename Type, std::size_t NumberOfCoefficients>
35935 struct poly_impl { };
35936
35937 template <typename Type>
35938 struct poly_impl <Type,12>
35939 {
35940 static inline T evaluate(const Type x,
35941 const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
35942 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
35943 const Type c2, const Type c1, const Type c0)
35944 {
35945 // 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
35946 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);
35947 }
35948 };
35949
35950 template <typename Type>
35951 struct poly_impl <Type,11>
35952 {
35953 static inline T evaluate(const Type x,
35954 const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
35955 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
35956 const Type c1, const Type c0)
35957 {
35958 // 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
35959 return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35960 }
35961 };
35962
35963 template <typename Type>
35964 struct poly_impl <Type,10>
35965 {
35966 static inline T evaluate(const Type x,
35967 const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
35968 const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
35969 const Type c0)
35970 {
35971 // 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
35972 return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35973 }
35974 };
35975
35976 template <typename Type>
35977 struct poly_impl <Type,9>
35978 {
35979 static inline T evaluate(const Type x,
35980 const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
35981 const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
35982 {
35983 // 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
35984 return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35985 }
35986 };
35987
35988 template <typename Type>
35989 struct poly_impl <Type,8>
35990 {
35991 static inline T evaluate(const Type x,
35992 const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
35993 const Type c3, const Type c2, const Type c1, const Type c0)
35994 {
35995 // 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
35996 return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35997 }
35998 };
35999
36000 template <typename Type>
36001 struct poly_impl <Type,7>
36002 {
36003 static inline T evaluate(const Type x,
36004 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36005 const Type c2, const Type c1, const Type c0)
36006 {
36007 // 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
36008 return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36009 }
36010 };
36011
36012 template <typename Type>
36013 struct poly_impl <Type,6>
36014 {
36015 static inline T evaluate(const Type x,
36016 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36017 const Type c1, const Type c0)
36018 {
36019 // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36020 return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36021 }
36022 };
36023
36024 template <typename Type>
36025 struct poly_impl <Type,5>
36026 {
36027 static inline T evaluate(const Type x,
36028 const Type c5, const Type c4, const Type c3, const Type c2,
36029 const Type c1, const Type c0)
36030 {
36031 // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36032 return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36033 }
36034 };
36035
36036 template <typename Type>
36037 struct poly_impl <Type,4>
36038 {
36039 static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
36040 {
36041 // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36042 return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
36043 }
36044 };
36045
36046 template <typename Type>
36047 struct poly_impl <Type,3>
36048 {
36049 static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
36050 {
36051 // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36052 return (((c3 * x + c2) * x + c1) * x + c0);
36053 }
36054 };
36055
36056 template <typename Type>
36057 struct poly_impl <Type,2>
36058 {
36059 static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
36060 {
36061 // p(x) = c_2x^2 + c_1x^1 + c_0x^0
36062 return ((c2 * x + c1) * x + c0);
36063 }
36064 };
36065
36066 template <typename Type>
36067 struct poly_impl <Type,1>
36068 {
36069 static inline T evaluate(const Type x, const Type c1, const Type c0)
36070 {
36071 // p(x) = c_1x^1 + c_0x^0
36072 return (c1 * x + c0);
36073 }
36074 };
36075
36076 public:
36077
36078 using ifunction<T>::operator();
36079
36080 polynomial()
36081 : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
36082 {
36083 disable_has_side_effects(*this);
36084 }
36085
36086 virtual ~polynomial()
36087 {}
36088
36089 #define poly_rtrn(NN) \
36090 return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
36091
36092 inline virtual T operator() (const T& x, const T& c1, const T& c0)
36093 {
36094 poly_rtrn(1) poly_impl<T,1>::evaluate(x, c1, c0);
36095 }
36096
36097 inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
36098 {
36099 poly_rtrn(2) poly_impl<T,2>::evaluate(x, c2, c1, c0);
36100 }
36101
36102 inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
36103 {
36104 poly_rtrn(3) poly_impl<T,3>::evaluate(x, c3, c2, c1, c0);
36105 }
36106
36107 inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36108 {
36109 poly_rtrn(4) poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0);
36110 }
36111
36112 inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36113 {
36114 poly_rtrn(5) poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0);
36115 }
36116
36117 inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36118 {
36119 poly_rtrn(6) poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0);
36120 }
36121
36122 inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36123 {
36124 poly_rtrn(7) poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0);
36125 }
36126
36127 inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36128 {
36129 poly_rtrn(8) poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36130 }
36131
36132 inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36133 {
36134 poly_rtrn(9) poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36135 }
36136
36137 inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36138 {
36139 poly_rtrn(10) poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36140 }
36141
36142 inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36143 {
36144 poly_rtrn(11) poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36145 }
36146
36147 inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36148 {
36149 poly_rtrn(12) poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36150 }
36151
36152 #undef poly_rtrn
36153
36154 inline virtual T operator() ()
36155 {
36156 return std::numeric_limits<T>::quiet_NaN();
36157 }
36158
36159 inline virtual T operator() (const T&)
36160 {
36161 return std::numeric_limits<T>::quiet_NaN();
36162 }
36163
36164 inline virtual T operator() (const T&, const T&)
36165 {
36166 return std::numeric_limits<T>::quiet_NaN();
36167 }
36168 };
36169
36170 template <typename T>
36171 class function_compositor
36172 {
36173 public:
36174
36175 typedef exprtk::expression<T> expression_t;
36176 typedef exprtk::symbol_table<T> symbol_table_t;
36177 typedef exprtk::parser<T> parser_t;
36178 typedef typename parser_t::settings_store settings_t;
36179
36180 struct function
36181 {
36182 function()
36183 {}
36184
36185 function(const std::string& n)
36186 : name_(n)
36187 {}
36188
36189 function(const std::string& name,
36190 const std::string& expression)
36191 : name_(name),
36192 expression_(expression)
36193 {}
36194
36195 function(const std::string& name,
36196 const std::string& expression,
36197 const std::string& v0)
36198 : name_(name),
36199 expression_(expression)
36200 {
36201 v_.push_back(v0);
36202 }
36203
36204 function(const std::string& name,
36205 const std::string& expression,
36206 const std::string& v0, const std::string& v1)
36207 : name_(name),
36208 expression_(expression)
36209 {
36210 v_.push_back(v0); v_.push_back(v1);
36211 }
36212
36213 function(const std::string& name,
36214 const std::string& expression,
36215 const std::string& v0, const std::string& v1,
36216 const std::string& v2)
36217 : name_(name),
36218 expression_(expression)
36219 {
36220 v_.push_back(v0); v_.push_back(v1);
36221 v_.push_back(v2);
36222 }
36223
36224 function(const std::string& name,
36225 const std::string& expression,
36226 const std::string& v0, const std::string& v1,
36227 const std::string& v2, const std::string& v3)
36228 : name_(name),
36229 expression_(expression)
36230 {
36231 v_.push_back(v0); v_.push_back(v1);
36232 v_.push_back(v2); v_.push_back(v3);
36233 }
36234
36235 function(const std::string& name,
36236 const std::string& expression,
36237 const std::string& v0, const std::string& v1,
36238 const std::string& v2, const std::string& v3,
36239 const std::string& v4)
36240 : name_(name),
36241 expression_(expression)
36242 {
36243 v_.push_back(v0); v_.push_back(v1);
36244 v_.push_back(v2); v_.push_back(v3);
36245 v_.push_back(v4);
36246 }
36247
36248 inline function& name(const std::string& n)
36249 {
36250 name_ = n;
36251 return (*this);
36252 }
36253
36254 inline function& expression(const std::string& e)
36255 {
36256 expression_ = e;
36257 return (*this);
36258 }
36259
36260 inline function& var(const std::string& v)
36261 {
36262 v_.push_back(v);
36263 return (*this);
36264 }
36265
36266 std::string name_;
36267 std::string expression_;
36268 std::deque<std::string> v_;
36269 };
36270
36271 private:
36272
36273 struct base_func : public exprtk::ifunction<T>
36274 {
36275 typedef const T& type;
36276 typedef exprtk::ifunction<T> function_t;
36277 typedef std::vector<T*> varref_t;
36278 typedef std::vector<T> var_t;
36279 typedef std::pair<T*,std::size_t> lvarref_t;
36280 typedef std::vector<lvarref_t> lvr_vec_t;
36281
36282 using exprtk::ifunction<T>::operator();
36283
36284 base_func(const std::size_t& pc = 0)
36285 : exprtk::ifunction<T>(pc),
36286 local_var_stack_size(0),
36287 stack_depth(0)
36288 {
36289 v.resize(pc);
36290 }
36291
36292 virtual ~base_func()
36293 {}
36294
36295 inline void update(const T& v0)
36296 {
36297 (*v[0]) = v0;
36298 }
36299
36300 inline void update(const T& v0, const T& v1)
36301 {
36302 (*v[0]) = v0; (*v[1]) = v1;
36303 }
36304
36305 inline void update(const T& v0, const T& v1, const T& v2)
36306 {
36307 (*v[0]) = v0; (*v[1]) = v1;
36308 (*v[2]) = v2;
36309 }
36310
36311 inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
36312 {
36313 (*v[0]) = v0; (*v[1]) = v1;
36314 (*v[2]) = v2; (*v[3]) = v3;
36315 }
36316
36317 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
36318 {
36319 (*v[0]) = v0; (*v[1]) = v1;
36320 (*v[2]) = v2; (*v[3]) = v3;
36321 (*v[4]) = v4;
36322 }
36323
36324 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
36325 {
36326 (*v[0]) = v0; (*v[1]) = v1;
36327 (*v[2]) = v2; (*v[3]) = v3;
36328 (*v[4]) = v4; (*v[5]) = v5;
36329 }
36330
36331 inline function_t& setup(expression_t& expr)
36332 {
36333 expression = expr;
36334
36335 typedef typename expression_t::control_block::local_data_list_t ldl_t;
36336
36337 ldl_t ldl = expr.local_data_list();
36338
36339 std::vector<std::size_t> index_list;
36340
36341 for (std::size_t i = 0; i < ldl.size(); ++i)
36342 {
36343 if (ldl[i].size)
36344 {
36345 index_list.push_back(i);
36346 }
36347 }
36348
36349 std::size_t input_param_count = 0;
36350
36351 for (std::size_t i = 0; i < index_list.size(); ++i)
36352 {
36353 const std::size_t index = index_list[i];
36354
36355 if (i < (index_list.size() - v.size()))
36356 {
36357 lv.push_back(
36358 std::make_pair(
36359 reinterpret_cast<T*>(ldl[index].pointer),
36360 ldl[index].size));
36361
36362 local_var_stack_size += ldl[index].size;
36363 }
36364 else
36365 v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
36366 }
36367
36368 clear_stack();
36369
36370 return (*this);
36371 }
36372
36373 inline void pre()
36374 {
36375 if (stack_depth++)
36376 {
36377 if (!v.empty())
36378 {
36379 var_t var_stack(v.size(),T(0));
36380 copy(v,var_stack);
36381 param_stack.push_back(var_stack);
36382 }
36383
36384 if (!lv.empty())
36385 {
36386 var_t local_var_stack(local_var_stack_size,T(0));
36387 copy(lv,local_var_stack);
36388 local_stack.push_back(local_var_stack);
36389 }
36390 }
36391 }
36392
36393 inline void post()
36394 {
36395 if (--stack_depth)
36396 {
36397 if (!v.empty())
36398 {
36399 copy(param_stack.back(),v);
36400 param_stack.pop_back();
36401 }
36402
36403 if (!lv.empty())
36404 {
36405 copy(local_stack.back(),lv);
36406 local_stack.pop_back();
36407 }
36408 }
36409 }
36410
36411 void copy(const varref_t& src_v, var_t& dest_v)
36412 {
36413 for (std::size_t i = 0; i < src_v.size(); ++i)
36414 {
36415 dest_v[i] = (*src_v[i]);
36416 }
36417 }
36418
36419 void copy(const var_t& src_v, varref_t& dest_v)
36420 {
36421 for (std::size_t i = 0; i < src_v.size(); ++i)
36422 {
36423 (*dest_v[i]) = src_v[i];
36424 }
36425 }
36426
36427 void copy(const lvr_vec_t& src_v, var_t& dest_v)
36428 {
36429 typename var_t::iterator itr = dest_v.begin();
36430 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36431
36432 for (std::size_t i = 0; i < src_v.size(); ++i)
36433 {
36434 lvarref_t vr = src_v[i];
36435
36436 if (1 == vr.second)
36437 *itr++ = (*vr.first);
36438 else
36439 {
36440 std::copy(vr.first, vr.first + vr.second, itr);
36441 itr += static_cast<diff_t>(vr.second);
36442 }
36443 }
36444 }
36445
36446 void copy(const var_t& src_v, lvr_vec_t& dest_v)
36447 {
36448 typename var_t::const_iterator itr = src_v.begin();
36449 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36450
36451 for (std::size_t i = 0; i < src_v.size(); ++i)
36452 {
36453 lvarref_t vr = dest_v[i];
36454
36455 if (1 == vr.second)
36456 (*vr.first) = *itr++;
36457 else
36458 {
36459 std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
36460 itr += static_cast<diff_t>(vr.second);
36461 }
36462 }
36463 }
36464
36465 inline void clear_stack()
36466 {
36467 for (std::size_t i = 0; i < v.size(); ++i)
36468 {
36469 (*v[i]) = 0;
36470 }
36471 }
36472
36473 inline virtual T value(expression_t& e)
36474 {
36475 return e.value();
36476 }
36477
36478 expression_t expression;
36479 varref_t v;
36480 lvr_vec_t lv;
36481 std::size_t local_var_stack_size;
36482 std::size_t stack_depth;
36483 std::deque<var_t> param_stack;
36484 std::deque<var_t> local_stack;
36485 };
36486
36487 typedef std::map<std::string,base_func*> funcparam_t;
36488
36489 struct func_0param : public base_func
36490 {
36491 using exprtk::ifunction<T>::operator();
36492
36493 func_0param() : base_func(0) {}
36494
36495 inline T operator() ()
36496 {
36497 return this->value(base_func::expression);
36498 }
36499 };
36500
36501 typedef const T& type;
36502
36503 template <typename BaseFuncType>
36504 struct scoped_bft
36505 {
36506 scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
36507 ~scoped_bft() { bft_.post(); }
36508
36509 BaseFuncType& bft_;
36510
36511 private:
36512
36513 scoped_bft(scoped_bft&);
36514 scoped_bft& operator=(scoped_bft&);
36515 };
36516
36517 struct func_1param : public base_func
36518 {
36519 using exprtk::ifunction<T>::operator();
36520
36521 func_1param() : base_func(1) {}
36522
36523 inline T operator() (type v0)
36524 {
36525 scoped_bft<func_1param> sb(*this);
36526 base_func::update(v0);
36527 return this->value(base_func::expression);
36528 }
36529 };
36530
36531 struct func_2param : public base_func
36532 {
36533 using exprtk::ifunction<T>::operator();
36534
36535 func_2param() : base_func(2) {}
36536
36537 inline T operator() (type v0, type v1)
36538 {
36539 scoped_bft<func_2param> sb(*this);
36540 base_func::update(v0, v1);
36541 return this->value(base_func::expression);
36542 }
36543 };
36544
36545 struct func_3param : public base_func
36546 {
36547 using exprtk::ifunction<T>::operator();
36548
36549 func_3param() : base_func(3) {}
36550
36551 inline T operator() (type v0, type v1, type v2)
36552 {
36553 scoped_bft<func_3param> sb(*this);
36554 base_func::update(v0, v1, v2);
36555 return this->value(base_func::expression);
36556 }
36557 };
36558
36559 struct func_4param : public base_func
36560 {
36561 using exprtk::ifunction<T>::operator();
36562
36563 func_4param() : base_func(4) {}
36564
36565 inline T operator() (type v0, type v1, type v2, type v3)
36566 {
36567 scoped_bft<func_4param> sb(*this);
36568 base_func::update(v0, v1, v2, v3);
36569 return this->value(base_func::expression);
36570 }
36571 };
36572
36573 struct func_5param : public base_func
36574 {
36575 using exprtk::ifunction<T>::operator();
36576
36577 func_5param() : base_func(5) {}
36578
36579 inline T operator() (type v0, type v1, type v2, type v3, type v4)
36580 {
36581 scoped_bft<func_5param> sb(*this);
36582 base_func::update(v0, v1, v2, v3, v4);
36583 return this->value(base_func::expression);
36584 }
36585 };
36586
36587 struct func_6param : public base_func
36588 {
36589 using exprtk::ifunction<T>::operator();
36590
36591 func_6param() : base_func(6) {}
36592
36593 inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
36594 {
36595 scoped_bft<func_6param> sb(*this);
36596 base_func::update(v0, v1, v2, v3, v4, v5);
36597 return this->value(base_func::expression);
36598 }
36599 };
36600
36601 static T return_value(expression_t& e)
36602 {
36603 typedef exprtk::results_context<T> results_context_t;
36604 typedef typename results_context_t::type_store_t type_t;
36605 typedef typename type_t::scalar_view scalar_t;
36606
36607 T result = e.value();
36608
36609 if (e.return_invoked())
36610 {
36611 // Due to the post compilation checks, it can be safely
36612 // assumed that there will be at least one parameter
36613 // and that the first parameter will always be scalar.
36614 return scalar_t(e.results()[0])();
36615 }
36616
36617 return result;
36618 }
36619
36620 #define def_fp_retval(N) \
36621 struct func_##N##param_retval : public func_##N##param \
36622 { \
36623 inline T value(expression_t& e) \
36624 { \
36625 return return_value(e); \
36626 } \
36627 }; \
36628
36629 def_fp_retval(0)
36630 def_fp_retval(1)
36631 def_fp_retval(2)
36632 def_fp_retval(3)
36633 def_fp_retval(4)
36634 def_fp_retval(5)
36635 def_fp_retval(6)
36636
36637 template <typename Allocator,
36638 template <typename, typename> class Sequence>
36639 inline bool add(const std::string& name,
36640 const std::string& expression,
36641 const Sequence<std::string,Allocator>& var_list,
36642 const bool override = false)
36643 {
36644 const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
36645
36646 if (expr_map_.end() != itr)
36647 {
36648 if (!override)
36649 {
36650 exprtk_debug(("Compositor error(add): function '%s' already defined\n",
36651 name.c_str()));
36652
36653 return false;
36654 }
36655
36656 remove(name, var_list.size());
36657 }
36658
36659 if (compile_expression(name,expression,var_list))
36660 {
36661 const std::size_t n = var_list.size();
36662
36663 fp_map_[n][name]->setup(expr_map_[name]);
36664
36665 return true;
36666 }
36667 else
36668 {
36669 exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
36670 name.c_str()));
36671
36672 return false;
36673 }
36674 }
36675
36676 public:
36677
36678 function_compositor()
36679 : parser_(settings_t::compile_all_opts +
36680 settings_t::e_disable_zero_return),
36681 fp_map_(7)
36682 {}
36683
36684 function_compositor(const symbol_table_t& st)
36685 : symbol_table_(st),
36686 parser_(settings_t::compile_all_opts +
36687 settings_t::e_disable_zero_return),
36688 fp_map_(7)
36689 {}
36690
36691 ~function_compositor()
36692 {
36693 clear();
36694 }
36695
36696 inline symbol_table_t& symbol_table()
36697 {
36698 return symbol_table_;
36699 }
36700
36701 inline void add_auxiliary_symtab(symbol_table_t& symtab)
36702 {
36703 auxiliary_symtab_list_.push_back(&symtab);
36704 }
36705
36706 void clear()
36707 {
36708 symbol_table_.clear();
36709 expr_map_ .clear();
36710
36711 for (std::size_t i = 0; i < fp_map_.size(); ++i)
36712 {
36713 typename funcparam_t::iterator itr = fp_map_[i].begin();
36714 typename funcparam_t::iterator end = fp_map_[i].end ();
36715
36716 while (itr != end)
36717 {
36718 delete itr->second;
36719 ++itr;
36720 }
36721
36722 fp_map_[i].clear();
36723 }
36724 }
36725
36726 inline bool add(const function& f, const bool override = false)
36727 {
36728 return add(f.name_, f.expression_, f.v_,override);
36729 }
36730
36731 private:
36732
36733 template <typename Allocator,
36734 template <typename, typename> class Sequence>
36735 bool compile_expression(const std::string& name,
36736 const std::string& expression,
36737 const Sequence<std::string,Allocator>& input_var_list,
36738 bool return_present = false)
36739 {
36740 expression_t compiled_expression;
36741 symbol_table_t local_symbol_table;
36742
36743 local_symbol_table.load_from(symbol_table_);
36744 local_symbol_table.add_constants();
36745
36746 if (!valid(name,input_var_list.size()))
36747 return false;
36748
36749 if (!forward(name,
36750 input_var_list.size(),
36751 local_symbol_table,
36752 return_present))
36753 return false;
36754
36755 compiled_expression.register_symbol_table(local_symbol_table);
36756
36757 for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
36758 {
36759 compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
36760 }
36761
36762 std::string mod_expression;
36763
36764 for (std::size_t i = 0; i < input_var_list.size(); ++i)
36765 {
36766 mod_expression += " var " + input_var_list[i] + "{};\n";
36767 }
36768
36769 if (
36770 ('{' == details::front(expression)) &&
36771 ('}' == details::back (expression))
36772 )
36773 mod_expression += "~" + expression + ";";
36774 else
36775 mod_expression += "~{" + expression + "};";
36776
36777 if (!parser_.compile(mod_expression,compiled_expression))
36778 {
36779 exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
36780 exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
36781
36782 remove(name,input_var_list.size());
36783
36784 return false;
36785 }
36786
36787 if (!return_present && parser_.dec().return_present())
36788 {
36789 remove(name,input_var_list.size());
36790
36791 return compile_expression(name, expression, input_var_list, true);
36792 }
36793
36794 // Make sure every return point has a scalar as its first parameter
36795 if (parser_.dec().return_present())
36796 {
36797 typedef std::vector<std::string> str_list_t;
36798
36799 str_list_t ret_param_list = parser_.dec().return_param_type_list();
36800
36801 for (std::size_t i = 0; i < ret_param_list.size(); ++i)
36802 {
36803 const std::string& params = ret_param_list[i];
36804
36805 if (params.empty() || ('T' != params[0]))
36806 {
36807 exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
36808 name.c_str()));
36809
36810 remove(name,input_var_list.size());
36811
36812 return false;
36813 }
36814 }
36815 }
36816
36817 expr_map_[name] = compiled_expression;
36818
36819 exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
36820
36821 if (symbol_table_.add_function(name,ifunc))
36822 return true;
36823 else
36824 {
36825 exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
36826 name.c_str()));
36827 return false;
36828 }
36829 }
36830
36831 inline bool symbol_used(const std::string& symbol) const
36832 {
36833 return (
36834 symbol_table_.is_variable (symbol) ||
36835 symbol_table_.is_stringvar (symbol) ||
36836 symbol_table_.is_function (symbol) ||
36837 symbol_table_.is_vector (symbol) ||
36838 symbol_table_.is_vararg_function(symbol)
36839 );
36840 }
36841
36842 inline bool valid(const std::string& name,
36843 const std::size_t& arg_count) const
36844 {
36845 if (arg_count > 6)
36846 return false;
36847 else if (symbol_used(name))
36848 return false;
36849 else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
36850 return false;
36851 else
36852 return true;
36853 }
36854
36855 inline bool forward(const std::string& name,
36856 const std::size_t& arg_count,
36857 symbol_table_t& sym_table,
36858 const bool ret_present = false)
36859 {
36860 switch (arg_count)
36861 {
36862 #define case_stmt(N) \
36863 case N : (fp_map_[arg_count])[name] = \
36864 (!ret_present) ? static_cast<base_func*> \
36865 (new func_##N##param) : \
36866 static_cast<base_func*> \
36867 (new func_##N##param_retval) ; \
36868 break; \
36869
36870 case_stmt(0) case_stmt(1) case_stmt(2)
36871 case_stmt(3) case_stmt(4) case_stmt(5)
36872 case_stmt(6)
36873 #undef case_stmt
36874 }
36875
36876 exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
36877
36878 return sym_table.add_function(name,ifunc);
36879 }
36880
36881 inline void remove(const std::string& name, const std::size_t& arg_count)
36882 {
36883 if (arg_count > 6)
36884 return;
36885
36886 const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
36887
36888 if (expr_map_.end() != em_itr)
36889 {
36890 expr_map_.erase(em_itr);
36891 }
36892
36893 const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
36894
36895 if (fp_map_[arg_count].end() != fp_itr)
36896 {
36897 delete fp_itr->second;
36898 fp_map_[arg_count].erase(fp_itr);
36899 }
36900
36901 symbol_table_.remove_function(name);
36902 }
36903
36904 private:
36905
36906 symbol_table_t symbol_table_;
36907 parser_t parser_;
36908 std::map<std::string,expression_t> expr_map_;
36909 std::vector<funcparam_t> fp_map_;
36910 std::vector<symbol_table_t*> auxiliary_symtab_list_;
36911 };
36912
36913 template <typename T>
36914 inline bool pgo_primer()
36915 {
36916 static const std::string expression_list[] =
36917 {
36918 "(y + x)",
36919 "2 * (y + x)",
36920 "(2 * y + 2 * x)",
36921 "(y + x / y) * (x - y / x)",
36922 "x / ((x + y) * (x - y)) / y",
36923 "1 - ((x * y) + (y / x)) - 3",
36924 "sin(2 * x) + cos(pi / y)",
36925 "1 - sin(2 * x) + cos(pi / y)",
36926 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
36927 "(x^2 / sin(2 * pi / y)) -x / 2",
36928 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
36929 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36930 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36931 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
36932 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
36933 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
36934 "(yy + xx)",
36935 "2 * (yy + xx)",
36936 "(2 * yy + 2 * xx)",
36937 "(yy + xx / yy) * (xx - yy / xx)",
36938 "xx / ((xx + yy) * (xx - yy)) / yy",
36939 "1 - ((xx * yy) + (yy / xx)) - 3",
36940 "sin(2 * xx) + cos(pi / yy)",
36941 "1 - sin(2 * xx) + cos(pi / yy)",
36942 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
36943 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
36944 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
36945 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
36946 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
36947 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
36948 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
36949 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
36950 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
36951 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
36952 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
36953 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
36954 "(x + 2) * 3", "x + (2 * 3)",
36955 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
36956 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
36957 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
36958 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
36959 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
36960 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
36961 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
36962 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
36963 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
36964 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
36965 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
36966 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
36967 "((x + (2 * 3)) / y)",
36968 "(xx + yy) * zz", "xx + (yy * zz)",
36969 "(xx + yy) * 7", "xx + (yy * 7)",
36970 "(xx + 7) * yy", "xx + (7 * yy)",
36971 "(7 + xx) * yy", "7 + (xx * yy)",
36972 "(2 + x) * 3", "2 + (x * 3)",
36973 "(2 + 3) * x", "2 + (3 * x)",
36974 "(x + 2) * 3", "x + (2 * 3)",
36975 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
36976 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
36977 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
36978 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
36979 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
36980 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
36981 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
36982 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
36983 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
36984 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
36985 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
36986 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
36987 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
36988 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
36989 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
36990 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
36991 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
36992 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
36993 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
36994 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
36995 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
36996 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
36997 "((xx + (2 * 3)) / yy)"
36998 };
36999
37000 static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
37001
37002 T x = T(0);
37003 T y = T(0);
37004 T z = T(0);
37005 T w = T(0);
37006 T xx = T(0);
37007 T yy = T(0);
37008 T zz = T(0);
37009 T ww = T(0);
37010
37011 exprtk::symbol_table<T> symbol_table;
37012 symbol_table.add_constants();
37013 symbol_table.add_variable( "x", x);
37014 symbol_table.add_variable( "y", y);
37015 symbol_table.add_variable( "z", z);
37016 symbol_table.add_variable( "w", w);
37017 symbol_table.add_variable("xx",xx);
37018 symbol_table.add_variable("yy",yy);
37019 symbol_table.add_variable("zz",zz);
37020 symbol_table.add_variable("ww",ww);
37021
37022 typedef typename std::deque<exprtk::expression<T> > expr_list_t;
37023 expr_list_t expr_list;
37024
37025 const std::size_t rounds = 50;
37026
37027 {
37028 for (std::size_t r = 0; r < rounds; ++r)
37029 {
37030 expr_list.clear();
37031 exprtk::parser<T> parser;
37032
37033 for (std::size_t i = 0; i < expression_list_size; ++i)
37034 {
37035 exprtk::expression<T> expression;
37036 expression.register_symbol_table(symbol_table);
37037
37038 if (!parser.compile(expression_list[i],expression))
37039 {
37040 return false;
37041 }
37042
37043 expr_list.push_back(expression);
37044 }
37045 }
37046 }
37047
37048 struct execute
37049 {
37050 static inline T process(T& x, T& y, expression<T>& expression)
37051 {
37052 static const T lower_bound = T(-20);
37053 static const T upper_bound = T(+20);
37054 static const T delta = T(0.1);
37055
37056 T total = T(0);
37057
37058 for (x = lower_bound; x <= upper_bound; x += delta)
37059 {
37060 for (y = lower_bound; y <= upper_bound; y += delta)
37061 {
37062 total += expression.value();
37063 }
37064 }
37065
37066 return total;
37067 }
37068 };
37069
37070 for (std::size_t i = 0; i < expr_list.size(); ++i)
37071 {
37072 execute::process( x, y, expr_list[i]);
37073 execute::process(xx, yy, expr_list[i]);
37074 }
37075
37076 {
37077 for (std::size_t i = 0; i < 10000; ++i)
37078 {
37079 const T v = T(123.456 + i);
37080
37081 if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
37082 return false;
37083
37084 #define else_stmt(N) \
37085 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
37086 return false; \
37087
37088 else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
37089 else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
37090 else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
37091 else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
37092 else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
37093 else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
37094 else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
37095 else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
37096 else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
37097 else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
37098 else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
37099 else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
37100 else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
37101 else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
37102 else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
37103 }
37104 }
37105
37106 return true;
37107 }
37108}
37109
37110#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37111# ifndef NOMINMAX
37112# define NOMINMAX
37113# endif
37114# ifndef WIN32_LEAN_AND_MEAN
37115# define WIN32_LEAN_AND_MEAN
37116# endif
4788af1e
UH
37117# define NOGDI
37118# define NORESOURCE
4640a84e
SA
37119# include <windows.h>
37120# include <ctime>
37121#else
37122# include <ctime>
37123# include <sys/time.h>
37124# include <sys/types.h>
37125#endif
37126
37127namespace exprtk
37128{
37129 class timer
37130 {
37131 public:
37132
37133 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37134 timer()
37135 : in_use_(false)
37136 {
37137 QueryPerformanceFrequency(&clock_frequency_);
37138 }
37139
37140 inline void start()
37141 {
37142 in_use_ = true;
37143 QueryPerformanceCounter(&start_time_);
37144 }
37145
37146 inline void stop()
37147 {
37148 QueryPerformanceCounter(&stop_time_);
37149 in_use_ = false;
37150 }
37151
37152 inline double time() const
37153 {
37154 return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
37155 }
37156
37157 #else
37158
37159 timer()
37160 : in_use_(false)
37161 {
37162 start_time_.tv_sec = 0;
37163 start_time_.tv_usec = 0;
37164 stop_time_.tv_sec = 0;
37165 stop_time_.tv_usec = 0;
37166 }
37167
37168 inline void start()
37169 {
37170 in_use_ = true;
37171 gettimeofday(&start_time_,0);
37172 }
37173
37174 inline void stop()
37175 {
37176 gettimeofday(&stop_time_, 0);
37177 in_use_ = false;
37178 }
37179
37180 inline unsigned long long int usec_time() const
37181 {
37182 if (!in_use_)
37183 {
37184 if (stop_time_.tv_sec >= start_time_.tv_sec)
37185 {
37186 return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) +
37187 static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
37188 }
37189 else
37190 return std::numeric_limits<details::_uint64_t>::max();
37191 }
37192 else
37193 return std::numeric_limits<details::_uint64_t>::max();
37194 }
37195
37196 inline double time() const
37197 {
37198 return usec_time() * 0.000001;
37199 }
37200
37201 #endif
37202
37203 inline bool in_use() const
37204 {
37205 return in_use_;
37206 }
37207
37208 private:
37209
37210 bool in_use_;
37211
37212 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37213 LARGE_INTEGER start_time_;
37214 LARGE_INTEGER stop_time_;
37215 LARGE_INTEGER clock_frequency_;
37216 #else
37217 struct timeval start_time_;
37218 struct timeval stop_time_;
37219 #endif
37220 };
37221
37222} // namespace exprtk
37223
37224#ifndef exprtk_disable_rtl_io
37225namespace exprtk
37226{
37227 namespace rtl { namespace io { namespace details
37228 {
37229 template <typename T>
37230 inline void print_type(const std::string& fmt,
37231 const T v,
37232 exprtk::details::numeric::details::real_type_tag)
37233 {
37234 printf(fmt.c_str(),v);
37235 }
37236
37237 template <typename T>
37238 struct print_impl
37239 {
37240 typedef typename igeneric_function<T>::generic_type generic_type;
37241 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37242 typedef typename generic_type::scalar_view scalar_t;
37243 typedef typename generic_type::vector_view vector_t;
37244 typedef typename generic_type::string_view string_t;
37245 typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
37246
37247 static void process(const std::string& scalar_format, parameter_list_t parameters)
37248 {
37249 for (std::size_t i = 0; i < parameters.size(); ++i)
37250 {
37251 generic_type& gt = parameters[i];
37252
37253 switch (gt.type)
37254 {
37255 case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
37256 break;
37257
37258 case generic_type::e_vector : print(scalar_format,vector_t(gt));
37259 break;
37260
37261 case generic_type::e_string : print(string_t(gt));
37262 break;
37263
37264 default : continue;
37265 }
37266 }
37267 }
37268
37269 static inline void print(const std::string& scalar_format, const scalar_t& s)
37270 {
37271 print_type(scalar_format,s(),num_type());
37272 }
37273
37274 static inline void print(const std::string& scalar_format, const vector_t& v)
37275 {
37276 for (std::size_t i = 0; i < v.size(); ++i)
37277 {
37278 print_type(scalar_format,v[i],num_type());
37279
37280 if ((i + 1) < v.size())
37281 printf(" ");
37282 }
37283 }
37284
37285 static inline void print(const string_t& s)
37286 {
37287 printf("%s",to_str(s).c_str());
37288 }
37289 };
37290
37291 } // namespace exprtk::rtl::io::details
37292
37293 template <typename T>
37294 struct print : public exprtk::igeneric_function<T>
37295 {
37296 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37297
37298 using exprtk::igeneric_function<T>::operator();
37299
37300 print(const std::string& scalar_format = "%10.5f")
37301 : scalar_format_(scalar_format)
37302 {
37303 exprtk::enable_zero_parameters(*this);
37304 }
37305
37306 inline T operator() (parameter_list_t parameters)
37307 {
37308 details::print_impl<T>::process(scalar_format_,parameters);
37309 return T(0);
37310 }
37311
37312 std::string scalar_format_;
37313 };
37314
37315 template <typename T>
37316 struct println : public exprtk::igeneric_function<T>
37317 {
37318 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37319
37320 using exprtk::igeneric_function<T>::operator();
37321
37322 println(const std::string& scalar_format = "%10.5f")
37323 : scalar_format_(scalar_format)
37324 {
37325 exprtk::enable_zero_parameters(*this);
37326 }
37327
37328 inline T operator() (parameter_list_t parameters)
37329 {
37330 details::print_impl<T>::process(scalar_format_,parameters);
37331 printf("\n");
37332 return T(0);
37333 }
37334
37335 std::string scalar_format_;
37336 };
37337
37338 template <typename T>
37339 struct package
37340 {
37341 print <T> p;
37342 println<T> pl;
37343
37344 bool register_package(exprtk::symbol_table<T>& symtab)
37345 {
37346 #define exprtk_register_function(FunctionName,FunctionType) \
37347 if (!symtab.add_function(FunctionName,FunctionType)) \
37348 { \
37349 exprtk_debug(( \
37350 "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
37351 FunctionName)); \
37352 return false; \
37353 } \
37354
37355 exprtk_register_function("print" , p)
37356 exprtk_register_function("println", pl)
37357 #undef exprtk_register_function
37358
37359 return true;
37360 }
37361 };
37362
37363 } // namespace exprtk::rtl::io
37364 } // namespace exprtk::rtl
37365} // namespace exprtk
37366#endif
37367
37368#ifndef exprtk_disable_rtl_io_file
37369#include <fstream>
37370namespace exprtk
37371{
37372 namespace rtl { namespace io { namespace file { namespace details
37373 {
37374 enum file_mode
37375 {
37376 e_error = 0,
37377 e_read = 1,
37378 e_write = 2,
37379 e_rdwrt = 4
37380 };
37381
37382 struct file_descriptor
37383 {
37384 file_descriptor(const std::string& fname, const std::string& access)
37385 : stream_ptr(0),
37386 mode(get_file_mode(access)),
37387 file_name(fname)
37388 {}
37389
37390 void* stream_ptr;
37391 file_mode mode;
37392 std::string file_name;
37393
37394 bool open()
37395 {
37396 if (e_read == mode)
37397 {
37398 std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
37399
37400 if (!(*stream))
37401 {
37402 file_name.clear();
37403 delete stream;
37404
37405 return false;
37406 }
37407 else
37408 stream_ptr = stream;
37409
37410 return true;
37411 }
37412 else if (e_write == mode)
37413 {
37414 std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
37415
37416 if (!(*stream))
37417 {
37418 file_name.clear();
37419 delete stream;
37420
37421 return false;
37422 }
37423 else
37424 stream_ptr = stream;
37425
37426 return true;
37427 }
37428 else if (e_rdwrt == mode)
37429 {
37430 std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
37431
37432 if (!(*stream))
37433 {
37434 file_name.clear();
37435 delete stream;
37436
37437 return false;
37438 }
37439 else
37440 stream_ptr = stream;
37441
37442 return true;
37443 }
37444 else
37445 return false;
37446 }
37447
37448 template <typename Stream, typename Ptr>
37449 void close(Ptr& p)
37450 {
37451 Stream* stream = reinterpret_cast<Stream*>(p);
37452 stream->close();
37453 delete stream;
37454 p = reinterpret_cast<Ptr>(0);
37455 }
37456
37457 bool close()
37458 {
37459 switch (mode)
37460 {
37461 case e_read : close<std::ifstream>(stream_ptr);
37462 break;
37463
37464 case e_write : close<std::ofstream>(stream_ptr);
37465 break;
37466
37467 case e_rdwrt : close<std::fstream> (stream_ptr);
37468 break;
37469
37470 default : return false;
37471 }
37472
37473 return true;
37474 }
37475
37476 template <typename View>
37477 bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
37478 {
37479 switch (mode)
37480 {
37481 case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
37482 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37483 break;
37484
37485 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37486 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37487 break;
37488
37489 default : return false;
37490 }
37491
37492 return true;
37493 }
37494
37495 template <typename View>
37496 bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
37497 {
37498 switch (mode)
37499 {
37500 case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
37501 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37502 break;
37503
37504 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37505 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37506 break;
37507
37508 default : return false;
37509 }
37510
37511 return true;
37512 }
37513
37514 bool getline(std::string& s)
37515 {
37516 switch (mode)
37517 {
37518 case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
37519 case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
37520 default : return false;
37521 }
37522 }
37523
37524 bool eof() const
37525 {
37526 switch (mode)
37527 {
37528 case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
37529 case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
37530 case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
37531 default : return true;
37532 }
37533 }
37534
37535 file_mode get_file_mode(const std::string& access) const
37536 {
37537 if (access.empty() || access.size() > 2)
37538 return e_error;
37539
37540 std::size_t w_cnt = 0;
37541 std::size_t r_cnt = 0;
37542
37543 for (std::size_t i = 0; i < access.size(); ++i)
37544 {
37545 switch (std::tolower(access[i]))
37546 {
37547 case 'r' : r_cnt++; break;
37548 case 'w' : w_cnt++; break;
37549 default : return e_error;
37550 }
37551 }
37552
37553 if ((0 == r_cnt) && (0 == w_cnt))
37554 return e_error;
37555 else if ((r_cnt > 1) || (w_cnt > 1))
37556 return e_error;
37557 else if ((1 == r_cnt) && (1 == w_cnt))
37558 return e_rdwrt;
37559 else if (1 == r_cnt)
37560 return e_read;
37561 else
37562 return e_write;
37563 }
37564 };
37565
37566 template <typename T>
37567 file_descriptor* make_handle(T v)
37568 {
37569 file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
37570
37571 std::memcpy(reinterpret_cast<char*>(&fd),
37572 reinterpret_cast<const char*>(&v),
37573 sizeof(fd));
37574 return fd;
37575 }
37576
37577 template <typename T>
37578 void perform_check()
37579 {
37580 #ifdef _MSC_VER
37581 #pragma warning(push)
37582 #pragma warning(disable: 4127)
37583 #endif
37584 if (sizeof(T) < sizeof(void*))
37585 {
37586 throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
37587 }
37588 #ifdef _MSC_VER
37589 #pragma warning(pop)
37590 #endif
37591 }
37592
37593 } // namespace exprtk::rtl::io::file::details
37594
37595 template <typename T>
37596 class open : public exprtk::igeneric_function<T>
37597 {
37598 public:
37599
37600 typedef typename exprtk::igeneric_function<T> igfun_t;
37601 typedef typename igfun_t::parameter_list_t parameter_list_t;
37602 typedef typename igfun_t::generic_type generic_type;
37603 typedef typename generic_type::string_view string_t;
37604
37605 using exprtk::igeneric_function<T>::operator();
37606
37607 open()
37608 : exprtk::igeneric_function<T>("S|SS")
37609 { details::perform_check<T>(); }
37610
37611 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37612 {
37613 std::string file_name = to_str(string_t(parameters[0]));
37614 std::string access;
37615
37616 if (file_name.empty())
37617 return T(0);
37618
37619 if (0 == ps_index)
37620 access = "r";
37621 else if (0 == string_t(parameters[1]).size())
37622 return T(0);
37623 else
37624 access = to_str(string_t(parameters[1]));
37625
37626 details::file_descriptor* fd = new details::file_descriptor(file_name,access);
37627
37628 if (fd->open())
37629 {
37630 T t = T(0);
37631
37632 std::memcpy(reinterpret_cast<char*>(&t ),
37633 reinterpret_cast<char*>(&fd),
37634 sizeof(fd));
37635 return t;
37636 }
37637 else
37638 {
37639 delete fd;
37640 return T(0);
37641 }
37642 }
37643 };
37644
37645 template <typename T>
37646 struct close : public exprtk::ifunction<T>
37647 {
37648 using exprtk::ifunction<T>::operator();
37649
37650 close()
37651 : exprtk::ifunction<T>(1)
37652 { details::perform_check<T>(); }
37653
37654 inline T operator() (const T& v)
37655 {
37656 details::file_descriptor* fd = details::make_handle(v);
37657
37658 if (!fd->close())
37659 return T(0);
37660
37661 delete fd;
37662
37663 return T(1);
37664 }
37665 };
37666
37667 template <typename T>
37668 class write : public exprtk::igeneric_function<T>
37669 {
37670 public:
37671
37672 typedef typename exprtk::igeneric_function<T> igfun_t;
37673 typedef typename igfun_t::parameter_list_t parameter_list_t;
37674 typedef typename igfun_t::generic_type generic_type;
37675 typedef typename generic_type::string_view string_t;
37676 typedef typename generic_type::scalar_view scalar_t;
37677 typedef typename generic_type::vector_view vector_t;
37678
37679 using exprtk::igeneric_function<T>::operator();
37680
37681 write()
37682 : igfun_t("TS|TST|TV|TVT")
37683 { details::perform_check<T>(); }
37684
37685 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37686 {
37687 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37688
37689 std::size_t amount = 0;
37690
37691 switch (ps_index)
37692 {
37693 case 0 : {
37694 const string_t buffer(parameters[1]);
37695 amount = buffer.size();
37696 return T(fd->write(buffer, amount) ? 1 : 0);
37697 }
37698
37699 case 1 : {
37700 const string_t buffer(parameters[1]);
37701 amount = std::min(buffer.size(),
37702 static_cast<std::size_t>(scalar_t(parameters[2])()));
37703 return T(fd->write(buffer, amount) ? 1 : 0);
37704 }
37705
37706 case 2 : {
37707 const vector_t vec(parameters[1]);
37708 amount = vec.size();
37709 return T(fd->write(vec, amount) ? 1 : 0);
37710 }
37711
37712 case 3 : {
37713 const vector_t vec(parameters[1]);
37714 amount = std::min(vec.size(),
37715 static_cast<std::size_t>(scalar_t(parameters[2])()));
37716 return T(fd->write(vec, amount) ? 1 : 0);
37717 }
37718 }
37719
37720 return T(0);
37721 }
37722 };
37723
37724 template <typename T>
37725 class read : public exprtk::igeneric_function<T>
37726 {
37727 public:
37728
37729 typedef typename exprtk::igeneric_function<T> igfun_t;
37730 typedef typename igfun_t::parameter_list_t parameter_list_t;
37731 typedef typename igfun_t::generic_type generic_type;
37732 typedef typename generic_type::string_view string_t;
37733 typedef typename generic_type::scalar_view scalar_t;
37734 typedef typename generic_type::vector_view vector_t;
37735
37736 using exprtk::igeneric_function<T>::operator();
37737
37738 read()
37739 : igfun_t("TS|TST|TV|TVT")
37740 { details::perform_check<T>(); }
37741
37742 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37743 {
37744 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37745
37746 std::size_t amount = 0;
37747
37748 switch (ps_index)
37749 {
37750 case 0 : {
37751 string_t buffer(parameters[1]);
37752 amount = buffer.size();
37753 return T(fd->read(buffer,amount) ? 1 : 0);
37754 }
37755
37756 case 1 : {
37757 string_t buffer(parameters[1]);
37758 amount = std::min(buffer.size(),
37759 static_cast<std::size_t>(scalar_t(parameters[2])()));
37760 return T(fd->read(buffer,amount) ? 1 : 0);
37761 }
37762
37763 case 2 : {
37764 vector_t vec(parameters[1]);
37765 amount = vec.size();
37766 return T(fd->read(vec,amount) ? 1 : 0);
37767 }
37768
37769 case 3 : {
37770 vector_t vec(parameters[1]);
37771 amount = std::min(vec.size(),
37772 static_cast<std::size_t>(scalar_t(parameters[2])()));
37773 return T(fd->read(vec,amount) ? 1 : 0);
37774 }
37775 }
37776
37777 return T(0);
37778 }
37779 };
37780
37781 template <typename T>
37782 class getline : public exprtk::igeneric_function<T>
37783 {
37784 public:
37785
37786 typedef typename exprtk::igeneric_function<T> igfun_t;
37787 typedef typename igfun_t::parameter_list_t parameter_list_t;
37788 typedef typename igfun_t::generic_type generic_type;
37789 typedef typename generic_type::string_view string_t;
37790 typedef typename generic_type::scalar_view scalar_t;
37791
37792 using exprtk::igeneric_function<T>::operator();
37793
37794 getline()
37795 : igfun_t("T",igfun_t::e_rtrn_string)
37796 { details::perform_check<T>(); }
37797
37798 inline T operator() (std::string& result,
37799 parameter_list_t parameters)
37800 {
37801 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37802 return T(fd->getline(result) ? 1 : 0);
37803 }
37804 };
37805
37806 template <typename T>
37807 struct eof : public exprtk::ifunction<T>
37808 {
37809 using exprtk::ifunction<T>::operator();
37810
37811 eof()
37812 : exprtk::ifunction<T>(1)
37813 { details::perform_check<T>(); }
37814
37815 inline T operator() (const T& v)
37816 {
37817 details::file_descriptor* fd = details::make_handle(v);
37818
37819 return (fd->eof() ? T(1) : T(0));
37820 }
37821 };
37822
37823 template <typename T>
37824 struct package
37825 {
37826 open <T> o;
37827 close <T> c;
37828 write <T> w;
37829 read <T> r;
37830 getline<T> g;
37831 eof <T> e;
37832
37833 bool register_package(exprtk::symbol_table<T>& symtab)
37834 {
37835 #define exprtk_register_function(FunctionName,FunctionType) \
37836 if (!symtab.add_function(FunctionName,FunctionType)) \
37837 { \
37838 exprtk_debug(( \
37839 "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
37840 FunctionName)); \
37841 return false; \
37842 } \
37843
37844 exprtk_register_function("open" ,o)
37845 exprtk_register_function("close" ,c)
37846 exprtk_register_function("write" ,w)
37847 exprtk_register_function("read" ,r)
37848 exprtk_register_function("getline",g)
37849 exprtk_register_function("eof" ,e)
37850 #undef exprtk_register_function
37851
37852 return true;
37853 }
37854 };
37855
37856 } // namespace exprtk::rtl::io::file
37857 } // namespace exprtk::rtl::io
37858 } // namespace exprtk::rtl
37859} // namespace exprtk
37860#endif
37861
37862#ifndef exprtk_disable_rtl_vecops
37863namespace exprtk
37864{
37865 namespace rtl { namespace vecops {
37866
37867 namespace helper
37868 {
37869 template <typename Vector>
37870 inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
37871 {
37872 if (r0 > (v.size() - 1))
37873 return true;
37874 else if (r1 > (v.size() - 1))
37875 return true;
37876 else if (r1 < r0)
37877 return true;
37878 else
37879 return false;
37880 }
37881
37882 template <typename T>
37883 struct load_vector_range
37884 {
37885 typedef typename exprtk::igeneric_function<T> igfun_t;
37886 typedef typename igfun_t::parameter_list_t parameter_list_t;
37887 typedef typename igfun_t::generic_type generic_type;
37888 typedef typename generic_type::scalar_view scalar_t;
37889 typedef typename generic_type::vector_view vector_t;
37890
37891 static inline bool process(parameter_list_t& parameters,
37892 std::size_t& r0, std::size_t& r1,
37893 const std::size_t& r0_prmidx,
37894 const std::size_t& r1_prmidx,
37895 const std::size_t vec_idx = 0)
37896 {
37897 if (r0_prmidx >= parameters.size())
37898 return false;
37899
37900 if (r1_prmidx >= parameters.size())
37901 return false;
37902
37903 if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
37904 return false;
37905
37906 if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
37907 return false;
37908
37909 return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
37910 }
37911 };
37912 }
37913
37914 namespace details
37915 {
37916 template <typename T>
37917 inline void kahan_sum(T& sum, T& error, const T v)
37918 {
37919 const T x = v - error;
37920 const T y = sum + x;
37921 error = (y - sum) - x;
37922 sum = y;
37923 }
37924
37925 } // namespace exprtk::rtl::details
37926
37927 template <typename T>
37928 class all_true : public exprtk::igeneric_function<T>
37929 {
37930 public:
37931
37932 typedef typename exprtk::igeneric_function<T> igfun_t;
37933 typedef typename igfun_t::parameter_list_t parameter_list_t;
37934 typedef typename igfun_t::generic_type generic_type;
37935 typedef typename generic_type::vector_view vector_t;
37936
37937 using exprtk::igeneric_function<T>::operator();
37938
37939 all_true()
37940 : exprtk::igeneric_function<T>("V|VTT")
37941 /*
37942 Overloads:
37943 0. V - vector
37944 1. VTT - vector, r0, r1
37945 */
37946 {}
37947
37948 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37949 {
37950 const vector_t vec(parameters[0]);
37951
37952 std::size_t r0 = 0;
37953 std::size_t r1 = vec.size() - 1;
37954
37955 if (
37956 (1 == ps_index) &&
37957 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37958 )
37959 return std::numeric_limits<T>::quiet_NaN();
37960
37961 for (std::size_t i = r0; i <= r1; ++i)
37962 {
37963 if (vec[i] == T(0))
37964 {
37965 return T(0);
37966 }
37967 }
37968
37969 return T(1);
37970 }
37971 };
37972
37973 template <typename T>
37974 class all_false : public exprtk::igeneric_function<T>
37975 {
37976 public:
37977
37978 typedef typename exprtk::igeneric_function<T> igfun_t;
37979 typedef typename igfun_t::parameter_list_t parameter_list_t;
37980 typedef typename igfun_t::generic_type generic_type;
37981 typedef typename generic_type::vector_view vector_t;
37982
37983 using exprtk::igeneric_function<T>::operator();
37984
37985 all_false()
37986 : exprtk::igeneric_function<T>("V|VTT")
37987 /*
37988 Overloads:
37989 0. V - vector
37990 1. VTT - vector, r0, r1
37991 */
37992 {}
37993
37994 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37995 {
37996 const vector_t vec(parameters[0]);
37997
37998 std::size_t r0 = 0;
37999 std::size_t r1 = vec.size() - 1;
38000
38001 if (
38002 (1 == ps_index) &&
38003 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38004 )
38005 return std::numeric_limits<T>::quiet_NaN();
38006
38007 for (std::size_t i = r0; i <= r1; ++i)
38008 {
38009 if (vec[i] != T(0))
38010 {
38011 return T(0);
38012 }
38013 }
38014
38015 return T(1);
38016 }
38017 };
38018
38019 template <typename T>
38020 class any_true : public exprtk::igeneric_function<T>
38021 {
38022 public:
38023
38024 typedef typename exprtk::igeneric_function<T> igfun_t;
38025 typedef typename igfun_t::parameter_list_t parameter_list_t;
38026 typedef typename igfun_t::generic_type generic_type;
38027 typedef typename generic_type::vector_view vector_t;
38028
38029 using exprtk::igeneric_function<T>::operator();
38030
38031 any_true()
38032 : exprtk::igeneric_function<T>("V|VTT")
38033 /*
38034 Overloads:
38035 0. V - vector
38036 1. VTT - vector, r0, r1
38037 */
38038 {}
38039
38040 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38041 {
38042 const vector_t vec(parameters[0]);
38043
38044 std::size_t r0 = 0;
38045 std::size_t r1 = vec.size() - 1;
38046
38047 if (
38048 (1 == ps_index) &&
38049 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38050 )
38051 return std::numeric_limits<T>::quiet_NaN();
38052
38053 for (std::size_t i = r0; i <= r1; ++i)
38054 {
38055 if (vec[i] != T(0))
38056 {
38057 return T(1);
38058 }
38059 }
38060
38061 return T(0);
38062 }
38063 };
38064
38065 template <typename T>
38066 class any_false : public exprtk::igeneric_function<T>
38067 {
38068 public:
38069
38070 typedef typename exprtk::igeneric_function<T> igfun_t;
38071 typedef typename igfun_t::parameter_list_t parameter_list_t;
38072 typedef typename igfun_t::generic_type generic_type;
38073 typedef typename generic_type::vector_view vector_t;
38074
38075 using exprtk::igeneric_function<T>::operator();
38076
38077 any_false()
38078 : exprtk::igeneric_function<T>("V|VTT")
38079 /*
38080 Overloads:
38081 0. V - vector
38082 1. VTT - vector, r0, r1
38083 */
38084 {}
38085
38086 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38087 {
38088 const vector_t vec(parameters[0]);
38089
38090 std::size_t r0 = 0;
38091 std::size_t r1 = vec.size() - 1;
38092
38093 if (
38094 (1 == ps_index) &&
38095 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38096 )
38097 return std::numeric_limits<T>::quiet_NaN();
38098
38099 for (std::size_t i = r0; i <= r1; ++i)
38100 {
38101 if (vec[i] == T(0))
38102 {
38103 return T(1);
38104 }
38105 }
38106
38107 return T(0);
38108 }
38109 };
38110
38111 template <typename T>
38112 class count : public exprtk::igeneric_function<T>
38113 {
38114 public:
38115
38116 typedef typename exprtk::igeneric_function<T> igfun_t;
38117 typedef typename igfun_t::parameter_list_t parameter_list_t;
38118 typedef typename igfun_t::generic_type generic_type;
38119 typedef typename generic_type::vector_view vector_t;
38120
38121 using exprtk::igeneric_function<T>::operator();
38122
38123 count()
38124 : exprtk::igeneric_function<T>("V|VTT")
38125 /*
38126 Overloads:
38127 0. V - vector
38128 1. VTT - vector, r0, r1
38129 */
38130 {}
38131
38132 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38133 {
38134 const vector_t vec(parameters[0]);
38135
38136 std::size_t r0 = 0;
38137 std::size_t r1 = vec.size() - 1;
38138
38139 if (
38140 (1 == ps_index) &&
38141 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38142 )
38143 return std::numeric_limits<T>::quiet_NaN();
38144
38145 std::size_t cnt = 0;
38146
38147 for (std::size_t i = r0; i <= r1; ++i)
38148 {
38149 if (vec[i] != T(0)) ++cnt;
38150 }
38151
38152 return T(cnt);
38153 }
38154 };
38155
38156 template <typename T>
38157 class copy : public exprtk::igeneric_function<T>
38158 {
38159 public:
38160
38161 typedef typename exprtk::igeneric_function<T> igfun_t;
38162 typedef typename igfun_t::parameter_list_t parameter_list_t;
38163 typedef typename igfun_t::generic_type generic_type;
38164 typedef typename generic_type::scalar_view scalar_t;
38165 typedef typename generic_type::vector_view vector_t;
38166
38167 using exprtk::igeneric_function<T>::operator();
38168
38169 copy()
38170 : exprtk::igeneric_function<T>("VV|VTTVTT")
38171 /*
38172 Overloads:
38173 0. VV - x(vector), y(vector)
38174 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
38175 */
38176 {}
38177
38178 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38179 {
38180 const vector_t x(parameters[0]);
38181 vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
38182
38183 std::size_t xr0 = 0;
38184 std::size_t xr1 = x.size() - 1;
38185
38186 std::size_t yr0 = 0;
38187 std::size_t yr1 = y.size() - 1;
38188
38189 if (1 == ps_index)
38190 {
38191 if (
38192 !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
38193 !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
38194 )
38195 return T(0);
38196 }
38197
38198 const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
38199
38200 std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
38201
38202 return T(n);
38203 }
38204 };
38205
38206 template <typename T>
38207 class rol : public exprtk::igeneric_function<T>
38208 {
38209 public:
38210
38211 typedef typename exprtk::igeneric_function<T> igfun_t;
38212 typedef typename igfun_t::parameter_list_t parameter_list_t;
38213 typedef typename igfun_t::generic_type generic_type;
38214 typedef typename generic_type::scalar_view scalar_t;
38215 typedef typename generic_type::vector_view vector_t;
38216
38217 using exprtk::igeneric_function<T>::operator();
38218
38219 rol()
38220 : exprtk::igeneric_function<T>("VT|VTTT")
38221 /*
38222 Overloads:
38223 0. VT - vector, N
38224 1. VTTT - vector, N, r0, r1
38225 */
38226 {}
38227
38228 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38229 {
38230 vector_t vec(parameters[0]);
38231
38232 std::size_t n = 0;
38233 std::size_t r0 = 0;
38234 std::size_t r1 = vec.size() - 1;
38235
38236 if (!scalar_t(parameters[1]).to_uint(n))
38237 return T(0);
38238
38239 if (
38240 (1 == ps_index) &&
38241 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38242 )
38243 return T(0);
38244
38245 std::size_t dist = r1 - r0 + 1;
38246 std::size_t shift = n % dist;
38247
38248 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38249
38250 return T(1);
38251 }
38252 };
38253
38254 template <typename T>
38255 class ror : public exprtk::igeneric_function<T>
38256 {
38257 public:
38258
38259 typedef typename exprtk::igeneric_function<T> igfun_t;
38260 typedef typename igfun_t::parameter_list_t parameter_list_t;
38261 typedef typename igfun_t::generic_type generic_type;
38262 typedef typename generic_type::scalar_view scalar_t;
38263 typedef typename generic_type::vector_view vector_t;
38264
38265 using exprtk::igeneric_function<T>::operator();
38266
38267 ror()
38268 : exprtk::igeneric_function<T>("VT|VTTT")
38269 /*
38270 Overloads:
38271 0. VT - vector, N
38272 1. VTTT - vector, N, r0, r1
38273 */
38274 {}
38275
38276 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38277 {
38278 vector_t vec(parameters[0]);
38279
38280 std::size_t n = 0;
38281 std::size_t r0 = 0;
38282 std::size_t r1 = vec.size() - 1;
38283
38284 if (!scalar_t(parameters[1]).to_uint(n))
38285 return T(0);
38286
38287 if (
38288 (1 == ps_index) &&
38289 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38290 )
38291 return T(0);
38292
38293 std::size_t dist = r1 - r0 + 1;
38294 std::size_t shift = (dist - (n % dist)) % dist;
38295
38296 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38297
38298 return T(1);
38299 }
38300 };
38301
38302 template <typename T>
38303 class shift_left : public exprtk::igeneric_function<T>
38304 {
38305 public:
38306
38307 typedef typename exprtk::igeneric_function<T> igfun_t;
38308 typedef typename igfun_t::parameter_list_t parameter_list_t;
38309 typedef typename igfun_t::generic_type generic_type;
38310 typedef typename generic_type::scalar_view scalar_t;
38311 typedef typename generic_type::vector_view vector_t;
38312
38313 using exprtk::igeneric_function<T>::operator();
38314
38315 shift_left()
38316 : exprtk::igeneric_function<T>("VT|VTTT")
38317 /*
38318 Overloads:
38319 0. VT - vector, N
38320 1. VTTT - vector, N, r0, r1
38321 */
38322 {}
38323
38324 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38325 {
38326 vector_t vec(parameters[0]);
38327
38328 std::size_t n = 0;
38329 std::size_t r0 = 0;
38330 std::size_t r1 = vec.size() - 1;
38331
38332 if (!scalar_t(parameters[1]).to_uint(n))
38333 return T(0);
38334
38335 if (
38336 (1 == ps_index) &&
38337 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38338 )
38339 return T(0);
38340
38341 std::size_t dist = r1 - r0 + 1;
38342
38343 if (n > dist)
38344 return T(0);
38345
38346 std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
38347
38348 for (std::size_t i = r1 - n + 1; i <= r1; ++i)
38349 {
38350 vec[i] = T(0);
38351 }
38352
38353 return T(1);
38354 }
38355 };
38356
38357 template <typename T>
38358 class shift_right : public exprtk::igeneric_function<T>
38359 {
38360 public:
38361
38362 typedef typename exprtk::igeneric_function<T> igfun_t;
38363 typedef typename igfun_t::parameter_list_t parameter_list_t;
38364 typedef typename igfun_t::generic_type generic_type;
38365 typedef typename generic_type::scalar_view scalar_t;
38366 typedef typename generic_type::vector_view vector_t;
38367
38368 using exprtk::igeneric_function<T>::operator();
38369
38370 shift_right()
38371 : exprtk::igeneric_function<T>("VT|VTTT")
38372 /*
38373 Overloads:
38374 0. VT - vector, N
38375 1. VTTT - vector, N, r0, r1
38376 */
38377 {}
38378
38379 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38380 {
38381 vector_t vec(parameters[0]);
38382
38383 std::size_t n = 0;
38384 std::size_t r0 = 0;
38385 std::size_t r1 = vec.size() - 1;
38386
38387 if (!scalar_t(parameters[1]).to_uint(n))
38388 return T(0);
38389
38390 if (
38391 (1 == ps_index) &&
38392 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38393 )
38394 return T(0);
38395
38396 std::size_t dist = r1 - r0 + 1;
38397
38398 if (n > dist)
38399 return T(0);
38400
38401 std::size_t shift = (dist - (n % dist)) % dist;
38402
38403 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38404
38405 for (std::size_t i = r0; i < r0 + n; ++i)
38406 {
38407 vec[i] = T(0);
38408 }
38409
38410 return T(1);
38411 }
38412 };
38413
38414 template <typename T>
38415 class sort : public exprtk::igeneric_function<T>
38416 {
38417 public:
38418
38419 typedef typename exprtk::igeneric_function<T> igfun_t;
38420 typedef typename igfun_t::parameter_list_t parameter_list_t;
38421 typedef typename igfun_t::generic_type generic_type;
38422 typedef typename generic_type::string_view string_t;
38423 typedef typename generic_type::vector_view vector_t;
38424
38425 using exprtk::igeneric_function<T>::operator();
38426
38427 sort()
38428 : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
38429 /*
38430 Overloads:
38431 0. V - vector
38432 1. VTT - vector, r0, r1
38433 2. VS - vector, string
38434 3. VSTT - vector, string, r0, r1
38435 */
38436 {}
38437
38438 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38439 {
38440 vector_t vec(parameters[0]);
38441
38442 std::size_t r0 = 0;
38443 std::size_t r1 = vec.size() - 1;
38444
38445 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38446 return T(0);
38447 if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38448 return T(0);
38449
38450 bool ascending = true;
38451
38452 if ((2 == ps_index) || (3 == ps_index))
38453 {
38454 if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
38455 ascending = true;
38456 else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
38457 ascending = false;
38458 else
38459 return T(0);
38460 }
38461
38462 if (ascending)
38463 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ());
38464 else
38465 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
38466
38467 return T(1);
38468 }
38469 };
38470
38471 template <typename T>
38472 class nthelement : public exprtk::igeneric_function<T>
38473 {
38474 public:
38475
38476 typedef typename exprtk::igeneric_function<T> igfun_t;
38477 typedef typename igfun_t::parameter_list_t parameter_list_t;
38478 typedef typename igfun_t::generic_type generic_type;
38479 typedef typename generic_type::scalar_view scalar_t;
38480 typedef typename generic_type::vector_view vector_t;
38481
38482 using exprtk::igeneric_function<T>::operator();
38483
38484 nthelement()
38485 : exprtk::igeneric_function<T>("VT|VTTT")
38486 /*
38487 Overloads:
38488 0. VT - vector, nth-element
38489 1. VTTT - vector, nth-element, r0, r1
38490 */
38491 {}
38492
38493 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38494 {
38495 vector_t vec(parameters[0]);
38496
38497 std::size_t n = 0;
38498 std::size_t r0 = 0;
38499 std::size_t r1 = vec.size() - 1;
38500
38501 if (!scalar_t(parameters[1]).to_uint(n))
38502 return T(0);
38503
38504 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38505 return std::numeric_limits<T>::quiet_NaN();
38506
38507 std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
38508
38509 return T(1);
38510 }
38511 };
38512
38513 template <typename T>
38514 class iota : public exprtk::igeneric_function<T>
38515 {
38516 public:
38517
38518 typedef typename exprtk::igeneric_function<T> igfun_t;
38519 typedef typename igfun_t::parameter_list_t parameter_list_t;
38520 typedef typename igfun_t::generic_type generic_type;
38521 typedef typename generic_type::scalar_view scalar_t;
38522 typedef typename generic_type::vector_view vector_t;
38523
38524 using exprtk::igeneric_function<T>::operator();
38525
38526 iota()
38527 : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
38528 /*
38529 Overloads:
38530 0. VT - vector, increment
38531 1. VTT - vector, increment, base
38532 2. VTTTT - vector, increment, r0, r1
38533 3. VTTTT - vector, increment, base, r0, r1
38534 */
38535 {}
38536
38537 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38538 {
38539 vector_t vec(parameters[0]);
38540
38541 T increment = scalar_t(parameters[1])();
38542 T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
38543
38544 std::size_t r0 = 0;
38545 std::size_t r1 = vec.size() - 1;
38546
38547 if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38548 return std::numeric_limits<T>::quiet_NaN();
38549 else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
38550 return std::numeric_limits<T>::quiet_NaN();
38551 else
38552 {
38553 long long j = 0;
38554
38555 for (std::size_t i = r0; i <= r1; ++i, ++j)
38556 {
38557 vec[i] = base + (increment * j);
38558 }
38559 }
38560
38561 return T(1);
38562 }
38563 };
38564
38565 template <typename T>
38566 class sumk : public exprtk::igeneric_function<T>
38567 {
38568 public:
38569
38570 typedef typename exprtk::igeneric_function<T> igfun_t;
38571 typedef typename igfun_t::parameter_list_t parameter_list_t;
38572 typedef typename igfun_t::generic_type generic_type;
38573 typedef typename generic_type::vector_view vector_t;
38574
38575 using exprtk::igeneric_function<T>::operator();
38576
38577 sumk()
38578 : exprtk::igeneric_function<T>("V|VTT")
38579 /*
38580 Overloads:
38581 0. V - vector
38582 1. VTT - vector, r0, r1
38583 */
38584 {}
38585
38586 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38587 {
38588 const vector_t vec(parameters[0]);
38589
38590 std::size_t r0 = 0;
38591 std::size_t r1 = vec.size() - 1;
38592
38593 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38594 return std::numeric_limits<T>::quiet_NaN();
38595
38596 T result = T(0);
38597 T error = T(0);
38598
38599 for (std::size_t i = r0; i <= r1; ++i)
38600 {
38601 details::kahan_sum(result, error, vec[i]);
38602 }
38603
38604 return result;
38605 }
38606 };
38607
38608 template <typename T>
38609 class axpy : public exprtk::igeneric_function<T>
38610 {
38611 public:
38612
38613 typedef typename exprtk::igeneric_function<T> igfun_t;
38614 typedef typename igfun_t::parameter_list_t parameter_list_t;
38615 typedef typename igfun_t::generic_type generic_type;
38616 typedef typename generic_type::scalar_view scalar_t;
38617 typedef typename generic_type::vector_view vector_t;
38618
38619 using exprtk::igeneric_function<T>::operator();
38620
38621 axpy()
38622 : exprtk::igeneric_function<T>("TVV|TVVTT")
38623 /*
38624 y <- ax + y
38625 Overloads:
38626 0. TVV - a, x(vector), y(vector)
38627 1. TVVTT - a, x(vector), y(vector), r0, r1
38628 */
38629 {}
38630
38631 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38632 {
38633 const vector_t x(parameters[1]);
38634 vector_t y(parameters[2]);
38635
38636 std::size_t r0 = 0;
38637 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38638
38639 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38640 return std::numeric_limits<T>::quiet_NaN();
38641 else if (helper::invalid_range(y, r0, r1))
38642 return std::numeric_limits<T>::quiet_NaN();
38643
38644 const T a = scalar_t(parameters[0])();
38645
38646 for (std::size_t i = r0; i <= r1; ++i)
38647 {
38648 y[i] = (a * x[i]) + y[i];
38649 }
38650
38651 return T(1);
38652 }
38653 };
38654
38655 template <typename T>
38656 class axpby : public exprtk::igeneric_function<T>
38657 {
38658 public:
38659
38660 typedef typename exprtk::igeneric_function<T> igfun_t;
38661 typedef typename igfun_t::parameter_list_t parameter_list_t;
38662 typedef typename igfun_t::generic_type generic_type;
38663 typedef typename generic_type::scalar_view scalar_t;
38664 typedef typename generic_type::vector_view vector_t;
38665
38666 using exprtk::igeneric_function<T>::operator();
38667
38668 axpby()
38669 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38670 /*
38671 y <- ax + by
38672 Overloads:
38673 0. TVTV - a, x(vector), b, y(vector)
38674 1. TVTVTT - a, x(vector), b, y(vector), r0, r1
38675 */
38676 {}
38677
38678 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38679 {
38680 const vector_t x(parameters[1]);
38681 vector_t y(parameters[3]);
38682
38683 std::size_t r0 = 0;
38684 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38685
38686 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38687 return std::numeric_limits<T>::quiet_NaN();
38688 else if (helper::invalid_range(y, r0, r1))
38689 return std::numeric_limits<T>::quiet_NaN();
38690
38691 const T a = scalar_t(parameters[0])();
38692 const T b = scalar_t(parameters[2])();
38693
38694 for (std::size_t i = r0; i <= r1; ++i)
38695 {
38696 y[i] = (a * x[i]) + (b * y[i]);
38697 }
38698
38699 return T(1);
38700 }
38701 };
38702
38703 template <typename T>
38704 class axpyz : public exprtk::igeneric_function<T>
38705 {
38706 public:
38707
38708 typedef typename exprtk::igeneric_function<T> igfun_t;
38709 typedef typename igfun_t::parameter_list_t parameter_list_t;
38710 typedef typename igfun_t::generic_type generic_type;
38711 typedef typename generic_type::scalar_view scalar_t;
38712 typedef typename generic_type::vector_view vector_t;
38713
38714 using exprtk::igeneric_function<T>::operator();
38715
38716 axpyz()
38717 : exprtk::igeneric_function<T>("TVVV|TVVVTT")
38718 /*
38719 z <- ax + y
38720 Overloads:
38721 0. TVVV - a, x(vector), y(vector), z(vector)
38722 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
38723 */
38724 {}
38725
38726 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38727 {
38728 const vector_t x(parameters[1]);
38729 const vector_t y(parameters[2]);
38730 vector_t z(parameters[3]);
38731
38732 std::size_t r0 = 0;
38733 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38734
38735 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38736 return std::numeric_limits<T>::quiet_NaN();
38737 else if (helper::invalid_range(y, r0, r1))
38738 return std::numeric_limits<T>::quiet_NaN();
38739 else if (helper::invalid_range(z, r0, r1))
38740 return std::numeric_limits<T>::quiet_NaN();
38741
38742 const T a = scalar_t(parameters[0])();
38743
38744 for (std::size_t i = r0; i <= r1; ++i)
38745 {
38746 z[i] = (a * x[i]) + y[i];
38747 }
38748
38749 return T(1);
38750 }
38751 };
38752
38753 template <typename T>
38754 class axpbyz : public exprtk::igeneric_function<T>
38755 {
38756 public:
38757
38758 typedef typename exprtk::igeneric_function<T> igfun_t;
38759 typedef typename igfun_t::parameter_list_t parameter_list_t;
38760 typedef typename igfun_t::generic_type generic_type;
38761 typedef typename generic_type::scalar_view scalar_t;
38762 typedef typename generic_type::vector_view vector_t;
38763
38764 using exprtk::igeneric_function<T>::operator();
38765
38766 axpbyz()
38767 : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
38768 /*
38769 z <- ax + by
38770 Overloads:
38771 0. TVTVV - a, x(vector), b, y(vector), z(vector)
38772 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
38773 */
38774 {}
38775
38776 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38777 {
38778 const vector_t x(parameters[1]);
38779 const vector_t y(parameters[3]);
38780 vector_t z(parameters[4]);
38781
38782 std::size_t r0 = 0;
38783 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38784
38785 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38786 return std::numeric_limits<T>::quiet_NaN();
38787 else if (helper::invalid_range(y, r0, r1))
38788 return std::numeric_limits<T>::quiet_NaN();
38789 else if (helper::invalid_range(z, r0, r1))
38790 return std::numeric_limits<T>::quiet_NaN();
38791
38792 const T a = scalar_t(parameters[0])();
38793 const T b = scalar_t(parameters[2])();
38794
38795 for (std::size_t i = r0; i <= r1; ++i)
38796 {
38797 z[i] = (a * x[i]) + (b * y[i]);
38798 }
38799
38800 return T(1);
38801 }
38802 };
38803
38804 template <typename T>
38805 class axpbz : public exprtk::igeneric_function<T>
38806 {
38807 public:
38808
38809 typedef typename exprtk::igeneric_function<T> igfun_t;
38810 typedef typename igfun_t::parameter_list_t parameter_list_t;
38811 typedef typename igfun_t::generic_type generic_type;
38812 typedef typename generic_type::scalar_view scalar_t;
38813 typedef typename generic_type::vector_view vector_t;
38814
38815 using exprtk::igeneric_function<T>::operator();
38816
38817 axpbz()
38818 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38819 /*
38820 z <- ax + b
38821 Overloads:
38822 0. TVTV - a, x(vector), b, z(vector)
38823 1. TVTVTT - a, x(vector), b, z(vector), r0, r1
38824 */
38825 {}
38826
38827 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38828 {
38829 const vector_t x(parameters[1]);
38830 vector_t z(parameters[3]);
38831
38832 std::size_t r0 = 0;
38833 std::size_t r1 = x.size() - 1;
38834
38835 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38836 return std::numeric_limits<T>::quiet_NaN();
38837 else if (helper::invalid_range(z, r0, r1))
38838 return std::numeric_limits<T>::quiet_NaN();
38839
38840 const T a = scalar_t(parameters[0])();
38841 const T b = scalar_t(parameters[2])();
38842
38843 for (std::size_t i = r0; i <= r1; ++i)
38844 {
38845 z[i] = (a * x[i]) + b;
38846 }
38847
38848 return T(1);
38849 }
38850 };
38851
38852 template <typename T>
38853 class dot : public exprtk::igeneric_function<T>
38854 {
38855 public:
38856
38857 typedef typename exprtk::igeneric_function<T> igfun_t;
38858 typedef typename igfun_t::parameter_list_t parameter_list_t;
38859 typedef typename igfun_t::generic_type generic_type;
38860 typedef typename generic_type::scalar_view scalar_t;
38861 typedef typename generic_type::vector_view vector_t;
38862
38863 using exprtk::igeneric_function<T>::operator();
38864
38865 dot()
38866 : exprtk::igeneric_function<T>("VV|VVTT")
38867 /*
38868 Overloads:
38869 0. VV - x(vector), y(vector)
38870 1. VVTT - x(vector), y(vector), r0, r1
38871 */
38872 {}
38873
38874 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38875 {
38876 const vector_t x(parameters[0]);
38877 const vector_t y(parameters[1]);
38878
38879 std::size_t r0 = 0;
38880 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38881
38882 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38883 return std::numeric_limits<T>::quiet_NaN();
38884 else if (helper::invalid_range(y, r0, r1))
38885 return std::numeric_limits<T>::quiet_NaN();
38886
38887 T result = T(0);
38888
38889 for (std::size_t i = r0; i <= r1; ++i)
38890 {
38891 result += (x[i] * y[i]);
38892 }
38893
38894 return result;
38895 }
38896 };
38897
38898 template <typename T>
38899 class dotk : public exprtk::igeneric_function<T>
38900 {
38901 public:
38902
38903 typedef typename exprtk::igeneric_function<T> igfun_t;
38904 typedef typename igfun_t::parameter_list_t parameter_list_t;
38905 typedef typename igfun_t::generic_type generic_type;
38906 typedef typename generic_type::scalar_view scalar_t;
38907 typedef typename generic_type::vector_view vector_t;
38908
38909 using exprtk::igeneric_function<T>::operator();
38910
38911 dotk()
38912 : exprtk::igeneric_function<T>("VV|VVTT")
38913 /*
38914 Overloads:
38915 0. VV - x(vector), y(vector)
38916 1. VVTT - x(vector), y(vector), r0, r1
38917 */
38918 {}
38919
38920 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38921 {
38922 const vector_t x(parameters[0]);
38923 const vector_t y(parameters[1]);
38924
38925 std::size_t r0 = 0;
38926 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38927
38928 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38929 return std::numeric_limits<T>::quiet_NaN();
38930 else if (helper::invalid_range(y, r0, r1))
38931 return std::numeric_limits<T>::quiet_NaN();
38932
38933 T result = T(0);
38934 T error = T(0);
38935
38936 for (std::size_t i = r0; i <= r1; ++i)
38937 {
38938 details::kahan_sum(result, error, (x[i] * y[i]));
38939 }
38940
38941 return result;
38942 }
38943 };
38944
38945 template <typename T>
38946 struct package
38947 {
38948 all_true <T> at;
38949 all_false <T> af;
38950 any_true <T> nt;
38951 any_false <T> nf;
38952 count <T> c;
38953 copy <T> cp;
38954 rol <T> rl;
38955 ror <T> rr;
38956 shift_left <T> sl;
38957 shift_right<T> sr;
38958 sort <T> st;
38959 nthelement <T> ne;
38960 iota <T> ia;
38961 sumk <T> sk;
38962 axpy <T> b1_axpy;
38963 axpby <T> b1_axpby;
38964 axpyz <T> b1_axpyz;
38965 axpbyz <T> b1_axpbyz;
38966 axpbz <T> b1_axpbz;
38967 dot <T> dt;
38968 dotk <T> dtk;
38969
38970 bool register_package(exprtk::symbol_table<T>& symtab)
38971 {
38972 #define exprtk_register_function(FunctionName,FunctionType) \
38973 if (!symtab.add_function(FunctionName,FunctionType)) \
38974 { \
38975 exprtk_debug(( \
38976 "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
38977 FunctionName)); \
38978 return false; \
38979 } \
38980
38981 exprtk_register_function("all_true" ,at)
38982 exprtk_register_function("all_false" ,af)
38983 exprtk_register_function("any_true" ,nt)
38984 exprtk_register_function("any_false" ,nf)
38985 exprtk_register_function("count" , c)
38986 exprtk_register_function("copy" ,cp)
38987 exprtk_register_function("rotate_left" ,rl)
38988 exprtk_register_function("rol" ,rl)
38989 exprtk_register_function("rotate_right" ,rr)
38990 exprtk_register_function("ror" ,rr)
38991 exprtk_register_function("shftl" ,sl)
38992 exprtk_register_function("shftr" ,sr)
38993 exprtk_register_function("sort" ,st)
38994 exprtk_register_function("nth_element" ,ne)
38995 exprtk_register_function("iota" ,ia)
38996 exprtk_register_function("sumk" ,sk)
38997 exprtk_register_function("axpy" ,b1_axpy)
38998 exprtk_register_function("axpby" ,b1_axpby)
38999 exprtk_register_function("axpyz" ,b1_axpyz)
39000 exprtk_register_function("axpbyz",b1_axpbyz)
39001 exprtk_register_function("axpbz" ,b1_axpbz)
39002 exprtk_register_function("dot" ,dt)
39003 exprtk_register_function("dotk" ,dtk)
39004 #undef exprtk_register_function
39005
39006 return true;
39007 }
39008 };
39009
39010 } // namespace exprtk::rtl::vecops
39011 } // namespace exprtk::rtl
39012} // namespace exprtk
39013#endif
39014
39015namespace exprtk
39016{
39017 namespace information
39018 {
39019 static const char* library = "Mathematical Expression Toolkit";
39020 static const char* version = "2.7182818284590452353602874713526624977572470936999595749"
39021 "669676277240766303535475945713821785251664274274663919320";
39022 static const char* date = "20200101";
39023
39024 static inline std::string data()
39025 {
39026 static const std::string info_str = std::string(library) +
39027 std::string(" v") + std::string(version) +
39028 std::string(" (") + date + std::string(")");
39029 return info_str;
39030 }
39031
39032 } // namespace information
39033
39034 #ifdef exprtk_debug
39035 #undef exprtk_debug
39036 #endif
39037
39038 #ifdef exprtk_error_location
39039 #undef exprtk_error_location
39040 #endif
39041
39042 #ifdef exprtk_disable_fallthrough_begin
39043 #undef exprtk_disable_fallthrough_begin
39044 #endif
39045
39046 #ifdef exprtk_disable_fallthrough_end
39047 #undef exprtk_disable_fallthrough_end
39048 #endif
39049
39050} // namespace exprtk
39051
39052#endif