PulseView  unreleased development snapshot
A Qt-based sigrok GUI
exprtk.hpp
Go to the documentation of this file.
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 
59 namespace exprtk
60 {
61  #ifdef exprtk_enable_debugging
62  #define exprtk_debug(params) printf params
63  #else
64  #define exprtk_debug(params) (void)0
65  #endif
66 
67  #define exprtk_error_location \
68  "exprtk.hpp:" + details::to_str(__LINE__) \
69 
70  #if 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 
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 
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  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  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  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  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  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  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  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  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  {
766  struct real_type_tag { real_type_tag () {} };
768  struct int_type_tag { int_type_tag () {} };
769 
770  template <typename T>
771  struct number_type
772  {
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 
790  exprtk_register_real_type_tag(long double)
792 
796 
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()) /
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 
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  {
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  }
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  {
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 
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 = "";
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 
2194  std::string value;
2195  std::size_t position;
2196  };
2197 
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;
2206 
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 
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 
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_;
2857 
2858  friend class token_scanner;
2859  friend class token_modifier;
2860  friend class token_inserter;
2861  friend class token_joiner;
2862  };
2863 
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 
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 
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 
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&)
3067 
3068  inline virtual int insert(const token&, const token&, token&)
3070 
3071  inline virtual int insert(const token&, const token&, const token&, token&)
3073 
3074  inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3076 
3077  inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3079 
3080  #undef token_inserter_empty_body
3081 
3082  private:
3083 
3084  const std::size_t stride_;
3085  };
3086 
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 
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 
3191  {
3192  public:
3193 
3195 
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 
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  */
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 (
3410  (t1.type == lexer::token::e_mul ) &&
3412  )
3413  {
3415  t.value = "[*]";
3416  t.position = t0.position;
3417 
3418  return true;
3419  }
3420  else
3421  return false;
3422  }
3423  };
3424 
3426  {
3427  public:
3428 
3429  using lexer::token_scanner::operator();
3430 
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 
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 
3466  {
3467  if (
3468  !t.value.empty() &&
3469  (lexer::token::e_string != t.type) &&
3470  (lexer::token::e_symbol != t.type) &&
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));
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_;
3508  };
3509 
3511  {
3512  public:
3513 
3514  using lexer::token_scanner::operator();
3515 
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 
3533  {
3534  if (token::e_number == t.type)
3535  {
3536  double v;
3537 
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
3560  }
3561 
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 
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,
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 
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 
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 
3652  : lexer::token_scanner(2)
3653  {
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 
3719  {
3720  error_list_.clear();
3721  }
3722 
3723  private:
3724 
3726  {
3727  invalid_comb_.insert(std::make_pair(base,t));
3728  }
3729 
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 
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 
3809  std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3810  };
3811 
3813  {
3814  private:
3815 
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 
3825  : lexer::token_scanner(3)
3826  {
3830 
3837 
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 
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 
3894  std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3895  };
3896 
3898  {
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 
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 
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 
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 
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 
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 
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 
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 
4052  };
4053  }
4054 
4056  {
4057  public:
4058 
4059  typedef token token_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 
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_;
4166  };
4167  }
4168 
4169  template <typename T>
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 
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>
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  {
4253  {
4257  e_string
4258  };
4259 
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;
4274 
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  {
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 
4380 
4382  {
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  {
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;
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 
4452 
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;
4484 
4485  inline void assign(const parameter_list_t& pl)
4486  {
4487  parameter_list_ = pl.parameter_list_;
4488  results_available_ = true;
4489  }
4490 
4492  ts_list_t parameter_list_;
4493 
4494  #ifndef exprtk_disable_return_statement
4495  friend class details::return_node<T>;
4497  #endif
4498  };
4499 
4500  namespace details
4501  {
4503  {
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 
4609  {
4610  base_operation_t(const operator_type t, const unsigned int& np)
4611  : type(t),
4612  num_params(np)
4613  {}
4614 
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;
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>
4660  {
4661  public:
4662 
4664  typedef T* data_t;
4665 
4666  private:
4667 
4669  {
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 
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 
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 
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 
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  {
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>
5011  {
5012  public:
5013 
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 ,
5029  e_in , e_like , e_ilike , e_inranges ,
5030  e_ipow , e_ipowinv , e_abs , e_acos ,
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 ,
5053  };
5054 
5055  typedef T value_type;
5057 
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  (
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>
5157  {
5158  return node && (details::expression_node<T>::e_rbvecelem == node->type());
5159  }
5160 
5161  template <typename T>
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  {
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>
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>
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>
5361  {
5362  private:
5363 
5364  typedef Type value_type;
5365  typedef value_type* value_ptr;
5366  typedef const value_ptr const_value_ptr;
5367 
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 
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>
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 
5466  {
5467  public:
5468 
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 
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 
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  {
5569  }
5570  };
5571 
5572  template <typename T>
5573  class null_eq_node : public expression_node<T>
5574  {
5575  public:
5576 
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 
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  {
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_;
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  {
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 
5654 
5655  const T value_;
5656  };
5657 
5658  template <typename T>
5659  struct range_pack;
5660 
5661  template <typename T>
5663 
5664  template <typename T>
5666  {
5667  public:
5668 
5670 
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>
5682  {
5683  public:
5684 
5686 
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>
5699  public string_base_node<T>,
5700  public range_interface <T>
5701  {
5702  public:
5703 
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  {
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 
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 
5771 
5773  expression_ptr brnch)
5774  : operation_(opr),
5775  branch_(brnch),
5776  branch_deletable_(branch_deletable(branch_))
5777  {}
5778 
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  {
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 
5817  expression_ptr branch_;
5819  };
5820 
5821  template <typename T, std::size_t D, bool B>
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 
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 
5902  typedef std::pair<expression_ptr,bool> branch_t;
5903 
5905  expression_ptr branch0,
5906  expression_ptr branch1)
5907  : operation_(opr)
5908  {
5909  init_branches<2>(branch_, branch0, branch1);
5910  }
5911 
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  {
5928  }
5929 
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 
5948  branch_t branch_[2];
5949  };
5950 
5951  template <typename T, typename Operation>
5953  {
5954  public:
5955 
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 
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  {
5980  }
5981 
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 
6008  typedef std::pair<expression_ptr,bool> branch_t;
6009 
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 
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  {
6049  }
6050 
6051  protected:
6052 
6054  branch_t branch_[3];
6055  };
6056 
6057  template <typename T>
6059  {
6060  public:
6061 
6063  typedef std::pair<expression_ptr,bool> branch_t;
6064 
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 
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  {
6088  }
6089 
6090  protected:
6091 
6093  branch_t branch_[4];
6094  };
6095 
6096  template <typename T>
6098  {
6099  public:
6100 
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 
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  {
6143  }
6144 
6145  private:
6146 
6147  expression_ptr test_;
6148  expression_ptr consequent_;
6149  expression_ptr alternative_;
6150  const bool test_deletable_;
6153  };
6154 
6155  template <typename T>
6157  {
6158  public:
6159 
6160  // Consequent only conditional statement node
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 
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  {
6195  }
6196 
6197  private:
6198 
6199  expression_ptr test_;
6200  expression_ptr consequent_;
6201  const bool test_deletable_;
6203  };
6204 
6205  #ifndef exprtk_disable_break_continue
6206  template <typename T>
6208  {
6209  public:
6210 
6211  break_exception(const T& v)
6212  : value(v)
6213  {}
6214 
6216  };
6217 
6219  {};
6220 
6221  template <typename T>
6222  class break_node : public expression_node<T>
6223  {
6224  public:
6225 
6227 
6228  break_node(expression_ptr ret = expression_ptr(0))
6229  : return_(ret),
6230  return_deletable_(branch_deletable(return_))
6231  {}
6232 
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  {
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  {
6276  }
6277  };
6278  #endif
6279 
6280  template <typename T>
6282  {
6283  public:
6284 
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 
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  {
6322  }
6323 
6324  private:
6325 
6326  expression_ptr condition_;
6327  expression_ptr loop_body_;
6330  };
6331 
6332  template <typename T>
6334  {
6335  public:
6336 
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 
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  {
6375  }
6376 
6377  private:
6378 
6379  expression_ptr condition_;
6380  expression_ptr loop_body_;
6383  };
6384 
6385  template <typename T>
6386  class for_loop_node : public expression_node<T>
6387  {
6388  public:
6389 
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 
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  {
6458  }
6459 
6460  private:
6461 
6462  expression_ptr initialiser_ ;
6463  expression_ptr condition_ ;
6464  expression_ptr incrementor_ ;
6465  expression_ptr loop_body_ ;
6470  };
6471 
6472  #ifndef exprtk_disable_break_continue
6473  template <typename T>
6475  {
6476  public:
6477 
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 
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  {
6524  }
6525 
6526  private:
6527 
6528  expression_ptr condition_;
6529  expression_ptr loop_body_;
6532  };
6533 
6534  template <typename T>
6536  {
6537  public:
6538 
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 
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  {
6586  }
6587 
6588  private:
6589 
6590  expression_ptr condition_;
6591  expression_ptr loop_body_;
6594  };
6595 
6596  template <typename T>
6598  {
6599  public:
6600 
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 
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  {
6688  }
6689 
6690  private:
6691 
6692  expression_ptr initialiser_;
6693  expression_ptr condition_ ;
6694  expression_ptr incrementor_;
6695  expression_ptr loop_body_ ;
6700  };
6701  #endif
6702 
6703  template <typename T>
6704  class switch_node : public expression_node<T>
6705  {
6706  public:
6707 
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 
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  {
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 
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  {
6797  }
6798  };
6799 
6800  template <typename T>
6802  {
6803  public:
6804 
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 
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  {
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>
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  {
6931  }
6932 
6933  private:
6934 
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  {
6945  typedef std::pair<std::size_t,std::size_t> cached_range_t;
6946 
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 
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 (
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  {
7075 
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>
7095  {
7096  public:
7097 
7100 
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 
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  {
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>
7188  public ivariable <T>
7189  {
7190  public:
7191 
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 
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  {
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_;
7241  const bool index_deletable_;
7242  };
7243 
7244  template <typename T>
7246  public ivariable <T>
7247  {
7248  public:
7249 
7252  typedef vector_holder_t* vector_holder_ptr;
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 
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  {
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>
7307  public ivariable <T>
7308  {
7309  public:
7310 
7313  typedef vector_holder_t* vector_holder_ptr;
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  {
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>
7358  {
7359  public:
7360 
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 
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  {
7417  }
7418 
7419  private:
7420 
7422 
7423  mutable T* vector_base_;
7424  std::vector<expression_ptr> initialiser_list_;
7425  const std::size_t size_;
7427  };
7428 
7429  template <typename T>
7430  class swap_node : public expression_node<T>
7431  {
7432  public:
7433 
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  {
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 
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  {
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 
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  {
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 
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  {
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 
7593  std::size_t vec_size_;
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 
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  {
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>
7687  public string_base_node<T>,
7688  public range_interface <T>
7689  {
7690  public:
7691 
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 
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  {
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>
7772  public string_base_node<T>,
7773  public range_interface <T>
7774  {
7775  public:
7776 
7778 
7779  explicit const_string_range_node(const std::string& v, const range_t& rp)
7780  : value_(v),
7781  rp_(rp)
7782  {}
7783 
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  {
7827  }
7828 
7829  private:
7830 
7832 
7833  const std::string value_;
7834  range_t rp_;
7835  };
7836 
7837  template <typename T>
7839  public string_base_node<T>,
7840  public range_interface <T>
7841  {
7842  public:
7843 
7848  typedef range_t* range_ptr;
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 
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  {
7952  }
7953 
7954  private:
7955 
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 
7976  typedef range_t* range_ptr;
7978  typedef irange_t* irange_ptr;
7979 
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 
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 
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  {
8091  }
8092 
8093  private:
8094 
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 
8115  typedef range_t* range_ptr;
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  {
8126  {
8127  str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8128  }
8129 
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  {
8179  }
8180 
8181  private:
8182 
8184  strvar_node_ptr str0_node_ptr_;
8185  strvar_node_ptr str1_node_ptr_;
8186  };
8187 
8188  template <typename T>
8190  {
8191  public:
8192 
8196  typedef range_t* range_ptr;
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  {
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 
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 
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  }
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  {
8328  }
8329 
8330  private:
8331 
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_;
8340  };
8341 
8342  template <typename T>
8344  {
8345  public:
8346 
8347  static std::string null_value;
8348 
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  {
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>
8377  {
8378  public:
8379 
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 
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  {
8421  }
8422 
8423  private:
8424 
8425  expression_ptr branch_;
8426  const bool branch_deletable_;
8427  str_base_ptr str_base_ptr_;
8428  };
8429 
8431  {
8432  static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8433  { s.assign(data,size); }
8434  };
8435 
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>
8444  public string_base_node<T>,
8445  public range_interface <T>
8446  {
8447  public:
8448 
8453  typedef range_t* range_ptr;
8455  typedef irange_t* irange_ptr;
8456 
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  {
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 
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  {
8547  }
8548 
8549  private:
8550 
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>
8560  public string_base_node<T>,
8561  public range_interface <T>
8562  {
8563  public:
8564 
8569  typedef range_t* range_ptr;
8571  typedef irange_t* irange_ptr;
8572 
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  {
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 
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  {
8680  }
8681 
8682  private:
8683 
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>
8694  public string_base_node<T>,
8695  public range_interface <T>
8696  {
8697  public:
8698 
8702  typedef range_t* range_ptr;
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 
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 
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  {
8834  }
8835 
8836  private:
8837 
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>
8853  public string_base_node<T>,
8854  public range_interface <T>
8855  {
8856  public:
8857 
8861  typedef range_t* range_ptr;
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 
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  {
8954  }
8955 
8956  private:
8957 
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 
8978  typedef range_t* range_ptr;
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 
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  {
9088  }
9089 
9090  private:
9091 
9092  expression_ptr final_node_;
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
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
9114  }
9115 
9116  template <typename T>
9117  struct sf_base
9118  {
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 
9353 
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 
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  {
9394  }
9395 
9396  private:
9397 
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 
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  {
9428  }
9429 
9430  private:
9431 
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 
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 
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  {
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>
9500  {
9501  public:
9502 
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  {
9537  }
9538 
9539  private:
9540 
9541  std::vector<const T*> arg_list_;
9542  };
9543 
9544  template <typename T, typename VecFunction>
9546  {
9547  public:
9548 
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 
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  {
9586  }
9587 
9588  private:
9589 
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 
9601 
9603  expression_ptr branch0,
9604  expression_ptr branch1)
9605  : binary_node<T>(opr, branch0, branch1),
9606  var_node_ptr_(0)
9607  {
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 
9631  };
9632 
9633  template <typename T>
9635  {
9636  public:
9637 
9639 
9641  expression_ptr branch0,
9642  expression_ptr branch1)
9643  : binary_node<T>(opr, branch0, branch1),
9644  vec_node_ptr_(0)
9645  {
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 
9669  };
9670 
9671  template <typename T>
9673  {
9674  public:
9675 
9677 
9679  expression_ptr branch0,
9680  expression_ptr branch1)
9681  : binary_node<T>(opr, branch0, branch1),
9682  rbvec_node_ptr_(0)
9683  {
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 
9707  };
9708 
9709  template <typename T>
9711  {
9712  public:
9713 
9715 
9717  expression_ptr branch0,
9718  expression_ptr branch1)
9719  : binary_node<T>(opr, branch0, branch1),
9720  rbvec_node_ptr_(0)
9721  {
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 
9745  };
9746 
9747  template <typename T>
9748  class assignment_vec_node : public binary_node <T>,
9749  public vector_interface<T>
9750  {
9751  public:
9752 
9756 
9758  expression_ptr branch0,
9759  expression_ptr branch1)
9760  : binary_node<T>(opr, branch0, branch1),
9761  vec_node_ptr_(0)
9762  {
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 
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  }
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  {
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 
9861  vds_t vds_;
9862  };
9863 
9864  template <typename T>
9866  public vector_interface<T>
9867  {
9868  public:
9869 
9873 
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  {
9884  {
9885  vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9886  vds() = vec0_node_ptr_->vds();
9887  }
9888 
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 
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  }
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  {
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 
10014  vds_t vds_;
10015  };
10016 
10017  template <typename T, typename Operation>
10019  {
10020  public:
10021 
10023 
10025  expression_ptr branch0,
10026  expression_ptr branch1)
10027  : binary_node<T>(opr, branch0, branch1),
10028  var_node_ptr_(0)
10029  {
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();
10042 
10043  return v;
10044  }
10045  else
10046  return std::numeric_limits<T>::quiet_NaN();
10047  }
10048 
10049  private:
10050 
10052  };
10053 
10054  template <typename T, typename Operation>
10056  {
10057  public:
10058 
10060 
10062  expression_ptr branch0,
10063  expression_ptr branch1)
10064  : binary_node<T>(opr, branch0, branch1),
10065  vec_node_ptr_(0)
10066  {
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();
10079 
10080  return v;
10081  }
10082  else
10083  return std::numeric_limits<T>::quiet_NaN();
10084  }
10085 
10086  private:
10087 
10089  };
10090 
10091  template <typename T, typename Operation>
10093  {
10094  public:
10095 
10097 
10099  expression_ptr branch0,
10100  expression_ptr branch1)
10101  : binary_node<T>(opr, branch0, branch1),
10102  rbvec_node_ptr_(0)
10103  {
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();
10116 
10117  return v;
10118  }
10119  else
10120  return std::numeric_limits<T>::quiet_NaN();
10121  }
10122 
10123  private:
10124 
10126  };
10127 
10128  template <typename T, typename Operation>
10130  {
10131  public:
10132 
10134 
10136  expression_ptr branch0,
10137  expression_ptr branch1)
10138  : binary_node<T>(opr, branch0, branch1),
10139  rbvec_node_ptr_(0)
10140  {
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();
10153 
10154  return v;
10155  }
10156  else
10157  return std::numeric_limits<T>::quiet_NaN();
10158  }
10159 
10160  private:
10161 
10163  };
10164 
10165  template <typename T, typename Operation>
10167  public vector_interface<T>
10168  {
10169  public:
10170 
10174 
10176  expression_ptr branch0,
10177  expression_ptr branch1)
10178  : binary_node<T>(opr, branch0, branch1),
10179  vec_node_ptr_(0)
10180  {
10182  {
10183  vec_node_ptr_ = static_cast<vector_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 
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  }
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  {
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 
10285  vds_t vds_;
10286  };
10287 
10288  template <typename T, typename Operation>
10290  public vector_interface<T>
10291  {
10292  public:
10293 
10297 
10299  expression_ptr branch0,
10300  expression_ptr branch1)
10301  : binary_node<T>(opr, branch0, branch1),
10302  vec0_node_ptr_(0),
10303  vec1_node_ptr_(0),
10304  initialised_(false)
10305  {
10307  {
10308  vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10309  vds() = vec0_node_ptr_->vds();
10310  }
10311 
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 
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  }
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  {
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 
10436  vds_t vds_;
10437  };
10438 
10439  template <typename T, typename Operation>
10441  public vector_interface<T>
10442  {
10443  public:
10444 
10449 
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 
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 
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 
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 
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  }
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  {
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_;
10620  vds_t vds_;
10621  };
10622 
10623  template <typename T, typename Operation>
10625  public vector_interface<T>
10626  {
10627  public:
10628 
10633 
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 
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 
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 
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  }
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  {
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>
10780  public vector_interface<T>
10781  {
10782  public:
10783 
10788 
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 
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 
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 
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  }
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  {
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 
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 
10953  {
10954  vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
10955  }
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 
10980  {
10981  delete temp_;
10982  delete temp_vec_node_;
10983  }
10984 
10985  inline T value() const
10986  {
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 
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  }
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  {
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 
11091 
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 
11115 
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>
11135  {
11136  public:
11137 
11138  // Function of N paramters.
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 
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];
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>
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  {
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 
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  {
11454  }
11455 
11456  private:
11457 
11458  ifunction* function_;
11459  };
11460 
11461  template <typename T, typename VarArgFunction>
11463  {
11464  public:
11465 
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 
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  {
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>
11525  {
11526  public:
11527 
11532  typedef variable_node_t* variable_node_ptr_t;
11533  typedef vector_node_t* vector_node_ptr_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 
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  {
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 
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  {
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 
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  {
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 
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  {
11890  }
11891 
11892  private:
11893 
11894  const std::size_t param_seq_index_;
11895  };
11896  #endif
11897 
11899  {};
11900 
11901  template <typename T>
11903  {
11904  public:
11905 
11906  virtual ~null_igenfunc()
11907  {}
11908 
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 
11925  typedef igeneric_function_t* igeneric_function_ptr;
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  {
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 
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 
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  {
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 
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 )
12053  exprtk_define_unary_op(cosh )
12059  exprtk_define_unary_op(erfc )
12061  exprtk_define_unary_op(expm1)
12062  exprtk_define_unary_op(floor)
12063  exprtk_define_unary_op(frac )
12066  exprtk_define_unary_op(log10)
12068  exprtk_define_unary_op(log1p)
12069  exprtk_define_unary_op(ncdf )
12071  exprtk_define_unary_op(notl )
12074  exprtk_define_unary_op(round)
12078  exprtk_define_unary_op(sinc )
12079  exprtk_define_unary_op(sinh )
12080  exprtk_define_unary_op(sqrt )
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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)); }
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)); }
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  }
12355  };
12356 
12357  template <typename T>
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  {
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 
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  }
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 
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  }
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  {
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 
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  }
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 
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  }
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  {
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  {
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  {
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>
13382  {
13383  public:
13384 
13386  {}
13387 
13388  inline virtual operator_type operation() const
13389  {
13390  return details::e_default;
13391  }
13392  };
13393 
13394  template <typename T>
13396  {
13397  public:
13398 
13400  {}
13401 
13402  virtual std::string type_id() const = 0;
13403  };
13404 
13405  template <typename T>
13407  {
13408  public:
13409 
13411  {}
13412 
13413  virtual std::string type_id() const = 0;
13414  };
13415 
13416  template <typename T, typename Operation>
13418  {
13419  public:
13420 
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 
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 
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  {
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 
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>
13531  {
13532  public:
13533 
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 
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 
13579 
13580  expression_ptr branch_;
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>
13603  {
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>
13646  {
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>
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>
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>
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 
13836  typedef typename functor_t::bfunc_t bfunc_t;
13837  typedef T value_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 
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 
13903  typedef typename functor_t::bfunc_t bfunc_t;
13904  typedef T value_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>
13989  {
13990  public:
13991 
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;
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>
14088  {
14089  public:
14090 
14092  typedef typename functor_t::tfunc_t tfunc_t;
14093  typedef T value_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>
14170  {
14171  public:
14172 
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 
14189  typedef typename functor_t::tfunc_t tfunc_t;
14190  typedef T value_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>
14274  {
14275  public:
14276 
14278  typedef typename functor_t::qfunc_t qfunc_t;
14279  typedef T value_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>
14363  {
14364  public:
14365 
14367  typedef typename functor_t::tfunc_t tfunc_t;
14368  typedef T value_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>
14463  {
14465  };
14466 
14467  template <typename T, typename T0, typename T1, typename T2>
14469  {
14474  };
14475 
14476  template <typename T, typename T0, typename T1, typename T2, typename T3>
14478  {
14485  };
14486 
14487  template <typename T, typename Operation>
14488  class vov_node : public vov_base_node<T>
14489  {
14490  public:
14491 
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 
14535  };
14536 
14537  template <typename T, typename Operation>
14538  class cov_node : public cov_base_node<T>
14539  {
14540  public:
14541 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
15105  };
15106 
15107  template <typename T, typename Operation>
15108  class str_sogens_node : public binary_node<T>
15109  {
15110  public:
15111 
15115  typedef range_t* range_ptr;
15117  typedef irange_t* irange_ptr;
15118 
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  {
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 
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 
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 
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 
15271  };
15272  #endif
15273 
15274  template <typename T, typename PowOp>
15275  class ipow_node : public expression_node<T>
15276  {
15277  public:
15278 
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  {
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 
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 
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  {
15331  }
15332 
15333  private:
15334 
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 
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  {
15361  }
15362 
15363  private:
15364 
15366  ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
15367 
15368  const T& v_;
15369  };
15370 
15371  template <typename T, typename PowOp>
15373  {
15374  public:
15375 
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 
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  {
15398  }
15399 
15400  private:
15401 
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>
15476  {
15477  return node && (expression_node<T>::e_cstringvarrng == node->type());
15478  }
15479 
15480  template <typename T>
15482  {
15483  return node && (expression_node<T>::e_strass == node->type());
15484  }
15485 
15486  template <typename T>
15488  {
15489  return node && (expression_node<T>::e_strconcat == node->type());
15490  }
15491 
15492  template <typename T>
15494  {
15495  return node && (expression_node<T>::e_strfunction == node->type());
15496  }
15497 
15498  template <typename T>
15500  {
15501  return node && (expression_node<T>::e_strcondition == node->type());
15502  }
15503 
15504  template <typename T>
15506  {
15507  return node && (expression_node<T>::e_strccondition == node->type());
15508  }
15509 
15510  template <typename T>
15512  {
15513  return node && (expression_node<T>::e_stringvararg == node->type());
15514  }
15515 
15516  template <typename T>
15518  {
15519  return node && (expression_node<T>::e_strgenrange == node->type());
15520  }
15521 
15522  template <typename T>
15524  {
15525  if (node)
15526  {
15527  switch (node->type())
15528  {
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>
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>
15604  {
15605  return (new node_type(t1));
15606  }
15607 
15608  template <typename node_type, typename T1>
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>
15624  {
15625  return (new node_type(t1, t2));
15626  }
15627 
15628  template <typename node_type,
15629  typename T1, typename T2>
15631  {
15632  return (new node_type(t1, t2));
15633  }
15634 
15635  template <typename node_type,
15636  typename T1, typename T2>
15638  {
15639  return (new node_type(t1, t2));
15640  }
15641 
15642  template <typename node_type,
15643  typename T1, typename T2>
15645  {
15646  return (new node_type(t1, t2));
15647  }
15648 
15649  template <typename node_type,
15650  typename T1, typename T2, typename T3>
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>
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>
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>
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>
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>
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>
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 
15896  {
15897  public:
15898 
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 
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() ()
15997 
15998  inline virtual T operator() (const T&)
16000 
16001  inline virtual T operator() (const T&,const T&)
16003 
16004  inline virtual T operator() (const T&, const T&, const T&)
16006 
16007  inline virtual T operator() (const T&, const T&, const T&, const T&)
16009 
16010  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16012 
16013  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16015 
16016  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16018 
16019  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16021 
16022  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
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&)
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&)
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&)
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&)
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&)
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&)
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&)
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&)
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&)
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&)
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&)
16067 
16068  #undef empty_method_body
16069 
16070  std::size_t param_count;
16071  };
16072 
16073  template <typename T>
16075  {
16076  public:
16077 
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>
16090  {
16091  public:
16092 
16094  {
16095  e_rtrn_scalar = 0,
16096  e_rtrn_string = 1,
16097  e_rtrn_overload = 2
16098  };
16099 
16100  typedef T type;
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 
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)
16121 
16122  // f(i_0,i_1,....,i_N) --> String
16123  inline virtual T operator() (std::string&, parameter_list_t)
16125 
16126  // f(psi,i_0,i_1,....,i_N) --> Scalar
16127  inline virtual T operator() (const std::size_t&, parameter_list_t)
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)
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>
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
16347  #ifndef exprtk_disable_string_capabilities
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 
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 
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 
16726  typedef variable_t* variable_ptr;
16727  #ifndef exprtk_disable_string_capabilities
16729  typedef stringvar_t* stringvar_ptr;
16730  #endif
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
16742  {
16743  struct st_data
16744  {
16746  #ifndef exprtk_disable_string_capabilities
16748  #endif
16755 
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 
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 
16800  : ref_count(1),
16801  data_(st_data::create())
16802  {}
16803 
16805  : ref_count(1),
16806  data_(data)
16807  {}
16808 
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;
16844  };
16845 
16846  public:
16847 
16849  : control_block_(control_block::create())
16850  {
16851  clear();
16852  }
16853 
16855  {
16856  control_block::destroy(control_block_,this);
16857  }
16858 
16860  {
16861  control_block_ = st.control_block_;
16862  control_block_->ref_count++;
16863  }
16864 
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 
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 
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>
17761 
17762  template <typename T>
17764  {
17765  private:
17766 
17769  typedef std::vector<symbol_table<T> > symtab_list_t;
17770 
17772  {
17774  {
17780  e_string
17781  };
17782 
17783  struct data_pack
17784  {
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;
17799  std::size_t size;
17800  };
17801 
17802  typedef std::vector<data_pack> local_data_list_t;
17804 
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 
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;
17887 
17888  friend class function_compositor<T>;
17889  };
17890 
17891  public:
17892 
17894  : control_block_(0)
17895  {
17896  set_expression(new details::null_node<T>());
17897  }
17898 
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 
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 
17952  {
17953  control_block::destroy(control_block_);
17954 
17955  return (*this);
17956  }
17957 
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 
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 
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  {
18174  {
18177  e_token = 2,
18180  e_lexer = 6,
18182  };
18183 
18184  struct type
18185  {
18187  : mode(parser_error::e_unknown),
18188  line_no (0),
18189  column_no(0)
18190  {}
18191 
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;
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()) ||
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 
18309  {
18324  e_level14
18325  };
18326 
18327  typedef const T& cref_t;
18328  typedef const T const_t;
18329  typedef ifunction <T> F;
18346  #ifndef exprtk_disable_break_continue
18350  #endif
18358  #ifndef exprtk_disable_string_capabilities
18369  #endif
18379  typedef expression_node_t* expression_node_ptr;
18384 
18390 
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 
18407 
18415 
18421 
18426 
18428 
18429  typedef parser_helper prsrhlpr_t;
18430 
18432  {
18434  {
18439  e_string
18440  };
18441 
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 
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 = "???";
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;
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 
18520  {
18521  public:
18522 
18523  typedef expression_node_t* expression_node_ptr;
18524  typedef variable_node_t* variable_node_ptr;
18526 
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 &&
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_;
18715  std::size_t input_param_cnt_;
18716  };
18717 
18719  {
18720  public:
18721 
18723 
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 
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 
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 
19189  {
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 
19224  std::size_t scope_depth;
19225  };
19226 
19227  public:
19228 
19230  {
19231 
19233  {
19234  e_usr_unknown_type = 0,
19235  e_usr_variable_type = 1,
19236  e_usr_constant_type = 2
19237  };
19238 
19240  {
19241  e_usrmode_default = 0,
19242  e_usrmode_extended = 1
19243  };
19244 
19246 
19247  unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
19248  : mode(m)
19249  {}
19250 
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 
19278  {
19279  e_ct_none = 0,
19280  e_ct_variables = 1,
19281  e_ct_functions = 2,
19282  e_ct_assignments = 4
19283  };
19284 
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 
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 
19370  {
19371  return collect_variables_;
19372  }
19373 
19375  {
19376  return collect_functions_;
19377  }
19378 
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_;
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 
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 
19464  {
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 
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 
19502  {
19503  e_ctrl_unknown = 0,
19509  e_ctrl_return
19510  };
19511 
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 
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 
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 
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 
19556  {
19557  disabled_func_set_.clear();
19558  return (*this);
19559  }
19560 
19562  {
19563  disabled_ctrl_set_.clear();
19564  return (*this);
19565  }
19566 
19568  {
19569  disabled_logic_set_.clear();
19570  return (*this);
19571  }
19572 
19574  {
19575  disabled_arithmetic_set_.clear();
19576  return (*this);
19577  }
19578 
19580  {
19581  disabled_assignment_set_.clear();
19582  return (*this);
19583  }
19584 
19586  {
19587  disabled_inequality_set_.clear();
19588  return (*this);
19589  }
19590 
19592  {
19593  disable_vardef_ = false;
19594  return (*this);
19595  }
19596 
19598  {
19599  std::copy(details::base_function_list,
19601  std::insert_iterator<disabled_entity_set_t>
19602  (disabled_func_set_, disabled_func_set_.begin()));
19603  return (*this);
19604  }
19605 
19607  {
19608  std::copy(details::cntrl_struct_list,
19610  std::insert_iterator<disabled_entity_set_t>
19611  (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
19612  return (*this);
19613  }
19614 
19616  {
19617  std::copy(details::logic_ops_list,
19619  std::insert_iterator<disabled_entity_set_t>
19620  (disabled_logic_set_, disabled_logic_set_.begin()));
19621  return (*this);
19622  }
19623 
19625  {
19626  std::copy(details::arithmetic_ops_list,
19628  std::insert_iterator<disabled_entity_set_t>
19629  (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
19630  return (*this);
19631  }
19632 
19634  {
19635  std::copy(details::assignment_ops_list,
19637  std::insert_iterator<disabled_entity_set_t>
19638  (disabled_assignment_set_, disabled_assignment_set_.begin()));
19639  return (*this);
19640  }
19641 
19643  {
19644  std::copy(details::inequality_ops_list,
19646  std::insert_iterator<disabled_entity_set_t>
19647  (disabled_inequality_set_, disabled_inequality_set_.begin()));
19648  return (*this);
19649  }
19650 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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(
20189  "ERR000 - Empty expression!",
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(
20205  "ERR001 - Empty expression!",
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(
20251  current_token(),
20252  "ERR002 - Invalid expression encountered",
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 
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(
20310  lexer()[i],
20311  diagnostic + ": " + lexer()[i].value,
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(
20353  bracket_checker_ptr->error_token(),
20354  "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
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(
20365  error_token,
20366  "ERR005 - Invalid numeric token: '" + error_token.value + "'",
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(
20383  error_token.first,
20384  "ERR006 - Invalid token sequence: '" +
20385  error_token.first.value + "' and '" +
20386  error_token.second.value + "'",
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(
20403  error_token.first,
20404  "ERR007 - Invalid token sequence: '" +
20405  error_token.first.value + "' and '" +
20406  error_token.second.value + "'",
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 
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 
20542  {
20543  return settings_.logic_disabled(operation);
20544  }
20545 
20547  {
20548  return settings_.arithmetic_disabled(operation);
20549  }
20550 
20552  {
20553  return settings_.assignment_disabled(operation);
20554  }
20555 
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(
20599  current_token(),
20600  "ERR008 - Invalid expression encountered",
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 
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(
20836  prev_token,
20837  "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
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(
20848  prev_token,
20849  "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
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(
20860  prev_token,
20861  "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
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(
20872  prev_token,
20873  "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
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(
20891  prev_token,
20892  "ERR013 - Return statements cannot be part of sub-expressions",
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(
20912  prev_token,
20913  !synthesis_error_.empty() ?
20914  synthesis_error_ :
20915  "ERR014 - General parsing error at token: '" + prev_token.value + "'",
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  {
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  {
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(
20984  current_token(),
20985  "ERR015 - Failed to find variable node in symbol table",
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>
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 
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 
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>
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 
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 
21066  std::deque<ptr_t>& deq_;
21067 
21068  private:
21069 
21071  };
21072 
21073  template <typename Type>
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 
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 
21099  std::vector<ptr_t>& vec_;
21100 
21101  private:
21102 
21104  };
21105 
21107  {
21108  explicit scoped_bool_negator(bool& bb)
21109  : b(bb)
21110  { b = !b; }
21111 
21113  { b = !b; }
21114 
21115  bool& b;
21116  };
21117 
21119  {
21120  explicit scoped_bool_or_restorer(bool& bb)
21121  : b(bb),
21122  original_value_(bb)
21123  {}
21124 
21126  {
21127  b = b || original_value_;
21128  }
21129 
21130  bool& b;
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(
21164  current_token(),
21165  "ERR016 - Invalid number of parameters for function: '" + function_name + "'",
21167 
21168  return error_node();
21169  }
21170  }
21171 
21172  if (func_node)
21173  return func_node;
21174  else
21175  {
21176  set_error(
21178  current_token(),
21179  "ERR017 - Failed to generate call to function: '" + function_name + "'",
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(
21197  current_token(),
21198  "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
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(
21220  current_token(),
21221  "ERR019 - Expecting argument list for function: '" + function_name + "'",
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(
21235  current_token(),
21236  "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
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(
21247  current_token(),
21248  "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
21250 
21251  return error_node();
21252  }
21253  }
21254  }
21255 
21256  if (!token_is(token_t::e_rbracket))
21257  {
21258  set_error(
21260  current_token(),
21261  "ERR022 - Invalid number of arguments for function: '" + function_name + "'",
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(
21289  current_token(),
21290  "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'",
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(
21314  current_token(),
21315  "ERR024 - Expected a '(' at start of function call to '" + function_name +
21316  "', instead got: '" + current_token().value + "'",
21318 
21319  return 0;
21320  }
21321 
21322  if (token_is(token_t::e_rbracket, e_hold))
21323  {
21324  set_error(
21326  current_token(),
21327  "ERR025 - Expected at least one input parameter for function call '" + function_name + "'",
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(
21352  current_token(),
21353  "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
21355 
21356  return 0;
21357  }
21358  }
21359 
21360  if (sd.delete_ptr)
21361  {
21362  set_error(
21364  current_token(),
21365  "ERR027 - Invalid number of input parameters passed to function '" + function_name + "'",
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(
21387  diagnostic_token,
21388  "ERR028 - No entry found for base operation: " + operation_name,
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(
21434  diagnostic_token,
21435  "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'",
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(
21454  current_token(),
21455  "ERR030 - Expected ',' between if-statement condition and consequent",
21457  result = false;
21458  }
21459  else if (0 == (consequent = parse_expression()))
21460  {
21461  set_error(
21463  current_token(),
21464  "ERR031 - Failed to parse consequent for if-statement",
21466  result = false;
21467  }
21468  else if (!token_is(token_t::e_comma))
21469  {
21470  set_error(
21472  current_token(),
21473  "ERR032 - Expected ',' between if-statement consequent and alternative",
21475  result = false;
21476  }
21477  else if (0 == (alternative = parse_expression()))
21478  {
21479  set_error(
21481  current_token(),
21482  "ERR033 - Failed to parse alternative for if-statement",
21484  result = false;
21485  }
21486  else if (!token_is(token_t::e_rbracket))
21487  {
21488  set_error(
21490  current_token(),
21491  "ERR034 - Expected ')' at the end of if-statement",
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(
21512  current_token(),
21513  "ERR035 - Return types of ternary if-statement differ",
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(
21547  current_token(),
21548  "ERR036 - Failed to parse body of consequent for if-statement",
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(
21570  current_token(),
21571  "ERR037 - Expected ';' at the end of the consequent for if-statement",
21573 
21574  result = false;
21575  }
21576  }
21577  else
21578  {
21579  set_error(
21581  current_token(),
21582  "ERR038 - Failed to parse body of consequent for if-statement",
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(
21601  current_token(),
21602  "ERR039 - Failed to parse body of the 'else' for if-statement",
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(
21614  current_token(),
21615  "ERR040 - Failed to parse body of if-else statement",
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(
21627  current_token(),
21628  "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement",
21630 
21631  result = false;
21632  }
21633  }
21634  else
21635  {
21636  set_error(
21638  current_token(),
21639  "ERR042 - Failed to parse body of the 'else' for if-statement",
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(
21663  current_token(),
21664  "ERR043 - Return types of ternary if-statement differ",
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(
21695  current_token(),
21696  "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
21698 
21699  return error_node();
21700  }
21701  else if (0 == (condition = parse_expression()))
21702  {
21703  set_error(
21705  current_token(),
21706  "ERR045 - Failed to parse condition for if-statement",
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(
21737  current_token(),
21738  "ERR046 - Invalid if-statement",
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(
21758  current_token(),
21759  "ERR047 - Encountered invalid condition branch for ternary if-statement",
21761 
21762  return error_node();
21763  }
21764  else if (!token_is(token_t::e_ternary))
21765  {
21766  set_error(
21768  current_token(),
21769  "ERR048 - Expected '?' after condition of ternary if-statement",
21771 
21772  result = false;
21773  }
21774  else if (0 == (consequent = parse_expression()))
21775  {
21776  set_error(
21778  current_token(),
21779  "ERR049 - Failed to parse consequent for ternary if-statement",
21781 
21782  result = false;
21783  }
21784  else if (!token_is(token_t::e_colon))
21785  {
21786  set_error(
21788  current_token(),
21789  "ERR050 - Expected ':' between ternary if-statement consequent and alternative",
21791 
21792  result = false;
21793  }
21794  else if (0 == (alternative = parse_expression()))
21795  {
21796  set_error(
21798  current_token(),
21799  "ERR051 - Failed to parse alternative for ternary if-statement",
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(
21821  current_token(),
21822  "ERR052 - Return types of ternary if-statement differ",
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(
21849  current_token(),
21850  "ERR053 - Invalid or disabled logic operation 'not'",
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(
21874  current_token(),
21875  "ERR054 - Expected '(' at start of while-loop condition statement",
21877 
21878  return error_node();
21879  }
21880  else if (0 == (condition = parse_expression()))
21881  {
21882  set_error(
21884  current_token(),
21885  "ERR055 - Failed to parse condition for while-loop",
21887 
21888  return error_node();
21889  }
21890  else if (!token_is(token_t::e_rbracket))
21891  {
21892  set_error(
21894  current_token(),
21895  "ERR056 - Expected ')' at end of while-loop condition statement",
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(
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(
21919  current_token(),
21920  "ERR058 - Failed to synthesize while-loop",
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(
21995  current_token(),
21996  "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
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(
22019  current_token(),
22020  "ERR060 - Failed to parse body of repeat until loop",
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(
22033  current_token(),
22034  "ERR061 - Expected '(' before condition statement of repeat until loop",
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(
22047  current_token(),
22048  "ERR062 - Failed to parse condition for repeat until loop",
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(
22059  current_token(),
22060  "ERR063 - Expected ')' after condition of repeat until loop",
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(
22080  current_token(),
22081  "ERR064 - Failed to synthesize repeat until loop",
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(
22115  current_token(),
22116  "ERR065 - Expected '(' at start of for-loop",
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(
22135  current_token(),
22136  "ERR066 - Expected a variable at the start of initialiser section of for-loop",
22138 
22139  return error_node();
22140  }
22141  else if (!peek_token_is(token_t::e_assign))
22142  {
22143  set_error(
22145  current_token(),
22146  "ERR067 - Expected variable assignment of initialiser section of for-loop",
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(
22160  current_token(),
22161  "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
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(
22192  current_token(),
22193  "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
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(
22214  current_token(),
22215  "ERR070 - Failed to parse initialiser of for-loop",
22217 
22218  result = false;
22219  }
22220  else if (!token_is(token_t::e_eof))
22221  {
22222  set_error(
22224  current_token(),
22225  "ERR071 - Expected ';' after initialiser of for-loop",
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(
22238  current_token(),
22239  "ERR072 - Failed to parse condition of for-loop",
22241 
22242  result = false;
22243  }
22244  else if (!token_is(token_t::e_eof))
22245  {
22246  set_error(
22248  current_token(),
22249  "ERR073 - Expected ';' after condition section of for-loop",
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(
22262  current_token(),
22263  "ERR074 - Failed to parse incrementor of for-loop",
22265 
22266  result = false;
22267  }
22268  else if (!token_is(token_t::e_rbracket))
22269  {
22270  set_error(
22272  current_token(),
22273  "ERR075 - Expected ')' after incrementor section of for-loop",
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(
22288  current_token(),
22289  "ERR076 - Failed to parse body of for-loop",
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(
22338  current_token(),
22339  "ERR077 - Expected keyword 'switch'",
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(
22353  current_token(),
22354  "ERR078 - Expected '{' for call to switch statement",
22356 
22357  return error_node();
22358  }
22359 
22360  for ( ; ; )
22361  {
22362  if (!details::imatch("case",current_token().value))
22363  {
22364  set_error(
22366  current_token(),
22367  "ERR079 - Expected either a 'case' or 'default' statement",
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(
22383  current_token(),
22384  "ERR080 - Expected ':' for case of switch statement",
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(
22398  current_token(),
22399  "ERR081 - Expected ';' at end of case for switch statement",
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(
22424  current_token(),
22425  "ERR082 - Expected ':' for default of switch statement",
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(
22446  current_token(),
22447  "ERR083 - Expected ';' at end of default for switch statement",
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(
22462  current_token(),
22463  "ERR084 - Expected '}' at end of switch statement",
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(
22484  current_token(),
22485  "ERR085 - Expected token '[*]'",
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(
22499  current_token(),
22500  "ERR086 - Expected '{' for call to [*] statement",
22502 
22503  return error_node();
22504  }
22505 
22506  for ( ; ; )
22507  {
22508  if (!details::imatch("case",current_token().value))
22509  {
22510  set_error(
22512  current_token(),
22513  "ERR087 - Expected a 'case' statement for multi-switch",
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(
22530  current_token(),
22531  "ERR088 - Expected ':' for case of [*] statement",
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(
22546  current_token(),
22547  "ERR089 - Expected ';' at end of case for [*] statement",
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(
22575  current_token(),
22576  "ERR090 - Expected '}' at end of [*] statement",
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 
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(
22616  current_token(),
22617  "ERR091 - Unsupported vararg function: " + symbol,
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(
22633  current_token(),
22634  "ERR092 - Expected '(' for call to vararg function: " + symbol,
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(
22655  current_token(),
22656  "ERR093 - Expected ',' for call to vararg function: " + symbol,
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(
22676  current_token(),
22677  "ERR094 - Expected '[' as start of string range definition",
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(
22704  current_token(),
22705  "ERR095 - Failed to generate string range node",
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(
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): ""),
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(
22887  current_token(),
22888  "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
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(
22921  current_token(),
22922  "ERR098 - Expected '[' for start of range",
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(
22942  current_token(),
22943  "ERR099 - Failed parse begin section of range",
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(
22965  current_token(),
22966  "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0",
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(
22982  current_token(),
22983  "ERR101 - Expected ':' for break in range",
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;
22996  }
22997  else
22998  {
22999  expression_node_ptr r1 = parse_expression();
23000 
23001  if (0 == r1)
23002  {
23003  set_error(
23005  current_token(),
23006  "ERR102 - Failed parse end section of range",
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(
23030  current_token(),
23031  "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0",
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(
23047  current_token(),
23048  "ERR104 - Expected ']' for start of range",
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(
23068  current_token(),
23069  "ERR105 - Invalid range, Constraint: r0 <= r1",
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(
23109  current_token(),
23110  "ERR106 - Unknown string symbol",
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(
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)) : "?") + "]",
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(
23267  current_token(),
23268  "ERR108 - Symbol '" + symbol+ " not a vector",
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(
23293  current_token(),
23294  "ERR109 - Failed to parse index for vector: '" + symbol + "'",
23296 
23297  return error_node();
23298  }
23299  else if (!token_is(token_t::e_rsqrbracket))
23300  {
23301  set_error(
23303  current_token(),
23304  "ERR110 - Expected ']' for index of vector: '" + symbol + "'",
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(
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),
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(
23354  current_token(),
23355  "ERR112 - Zero parameter call to vararg function: "
23356  + vararg_function_name + " not allowed",
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(
23379  current_token(),
23380  "ERR113 - Expected ',' for call to vararg function: "
23381  + vararg_function_name,
23383 
23384  return error_node();
23385  }
23386  }
23387  }
23388  }
23389  else if (!vararg_function->allow_zero_parameters())
23390  {
23391  set_error(
23393  current_token(),
23394  "ERR114 - Zero parameter call to vararg function: "
23395  + vararg_function_name + " not allowed",
23397 
23398  return error_node();
23399  }
23400 
23401  if (arg_list.size() < vararg_function->min_num_args())
23402  {
23403  set_error(
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",
23410 
23411  return error_node();
23412  }
23413  else if (arg_list.size() > vararg_function->max_num_args())
23414  {
23415  set_error(
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",
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 
23434  {
23435  public:
23436 
23438  {
23439  e_overload = ' ',
23440  e_numeric = 'T',
23441  e_string = 'S'
23442  };
23443 
23445  {
23447  std::string param_seq;
23448  };
23449 
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(
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 + "'",
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(
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 + "'",
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 
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(
23664  parser_.current_token(),
23665  "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] +
23666  "' for function: " + function_name_,
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(
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],
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 
23697  parser_t& parser_;
23698  std::string function_name_;
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(
23719  current_token(),
23720  "ERR121 - Type checker instantiation failure for generic function: " + function_name,
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(
23737  current_token(),
23738  "ERR122 - Zero parameter call to generic function: "
23739  + function_name + " not allowed",
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(
23769  current_token(),
23770  "ERR123 - Expected ',' for call to generic function: " + function_name,
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(
23786  current_token(),
23787  "ERR124 - Zero parameter call to generic function: "
23788  + function_name + " not allowed",
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(
23803  current_token(),
23804  "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name,
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(
23841  current_token(),
23842  "ERR126 - Zero parameter call to generic function: "
23843  + function_name + " not allowed",
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(
23873  current_token(),
23874  "ERR127 - Expected ',' for call to string function: " + function_name,
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(
23920  current_token(),
23921  "ERR128 - Invalid input parameter sequence for call to string function: " + function_name,
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(
23972  current_token(),
23973  "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name,
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(
24003  current_token(),
24004  "ERR130 - Invalid return type for call to overloaded function: " + function_name,
24006  }
24007 
24008  sdd.delete_ptr = (0 == result);
24009  return result;
24010  }
24011  #endif
24012 
24013  template <typename Type, std::size_t NumberOfParameters>
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 
24024 
24025  p.next_token();
24026 
24027  if (!p.token_is(token_t::e_lbracket))
24028  {
24029  p.set_error(
24031  p.current_token(),
24032  "ERR131 - Expected '(' for special function '" + sf_name + "'",
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(
24052  p.current_token(),
24053  "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'",
24055 
24056  return p.error_node();
24057  }
24058  }
24059  }
24060 
24061  if (!p.token_is(token_t::e_rbracket))
24062  {
24063  p.set_error(
24065  p.current_token(),
24066  "ERR133 - Invalid number of parameters for special function '" + sf_name + "'",
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(
24092  current_token(),
24093  "ERR134 - Invalid special function[1]: " + sf_name,
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(
24106  current_token(),
24107  "ERR135 - Invalid special function[2]: " + sf_name,
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(
24138  current_token(),
24139  "ERR136 - Break call within a break call is not allowed",
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(
24161  current_token(),
24162  "ERR137 - Failed to parse return expression for 'break' statement",
24164 
24165  return error_node();
24166  }
24167  else if (!token_is(token_t::e_rsqrbracket))
24168  {
24169  set_error(
24171  current_token(),
24172  "ERR138 - Expected ']' at the completion of break's return expression",
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(
24189  current_token(),
24190  "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
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(
24212  current_token(),
24213  "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop",
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(
24229  current_token(),
24230  "ERR141 - Expected '[' as part of vector size definition",
24232 
24233  return error_node();
24234  }
24235  else if (0 == (size_expr = parse_expression()))
24236  {
24237  set_error(
24239  current_token(),
24240  "ERR142 - Failed to determine size of vector '" + vec_name + "'",
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(
24251  current_token(),
24252  "ERR143 - Expected a literal number as size of vector '" + vec_name + "'",
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(
24273  current_token(),
24274  "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
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(
24293  current_token(),
24294  "ERR145 - Expected ']' as part of vector size definition",
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(
24305  current_token(),
24306  "ERR146 - Expected ':=' as part of vector definition",
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(
24319  current_token(),
24320  "ERR147 - Failed to parse single vector initialiser",
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(
24332  current_token(),
24333  "ERR148 - Expected ']' to close single value vector initialiser",
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(
24379  current_token(),
24380  "ERR149 - Expected '{' as part of vector initialiser list",
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(
24399  current_token(),
24400  "ERR150 - Expected '{' as part of vector initialiser list",
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(
24417  current_token(),
24418  "ERR151 - Expected ',' between vector initialisers",
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(
24439  current_token(),
24440  "ERR152 - Expected ';' at end of vector definition",
24442 
24443  return error_node();
24444  }
24445  }
24446 
24447  if (vec_initilizer_list.size() > vector_size)
24448  {
24449  set_error(
24451  current_token(),
24452  "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
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(
24471  current_token(),
24472  "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'",
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(
24505  current_token(),
24506  "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM",
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_(
24535  vec_node,
24536  vec_initilizer_list[0]);
24537  }
24538  else
24539  result = node_allocator_
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(
24564  current_token(),
24565  "ERR156 - Illegal redefinition of local variable: '" + str_name + "'",
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(
24596  current_token(),
24597  "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM",
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(
24642  current_token(),
24643  "ERR158 - Illegal variable definition",
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(
24663  current_token(),
24664  "ERR159 - Expected a symbol for variable definition",
24666 
24667  return error_node();
24668  }
24669  else if (details::is_reserved_symbol(var_name))
24670  {
24671  set_error(
24673  current_token(),
24674  "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'",
24676 
24677  return error_node();
24678  }
24679  else if (symtab_store_.symbol_exists(var_name))
24680  {
24681  set_error(
24683  current_token(),
24684  "ERR161 - Illegal redefinition of variable '" + var_name + "'",
24686 
24687  return error_node();
24688  }
24689  else if (local_variable_is_shadowed(var_name))
24690  {
24691  set_error(
24693  current_token(),
24694  "ERR162 - Illegal redefinition of local variable: '" + var_name + "'",
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(
24713  current_token(),
24714  "ERR163 - Failed to parse initialisation expression",
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(
24731  current_token(),
24732  "ERR164 - Expected ';' after variable definition",
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(
24759  current_token(),
24760  "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
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(
24791  current_token(),
24792  "ERR166 - Failed to add new local variable '" + var_name + "' to SEM",
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(
24828  current_token(),
24829  "ERR167 - Expected a '{}' for uninitialised var definition",
24831 
24832  return error_node();
24833  }
24834  else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24835  {
24836  set_error(
24838  current_token(),
24839  "ERR168 - Expected ';' after uninitialised variable definition",
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(
24855  current_token(),
24856  "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
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(
24885  current_token(),
24886  "ERR170 - Failed to add new local variable '" + var_name + "' to SEM",
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(
24918  current_token(),
24919  "ERR171 - Expected '(' at start of swap statement",
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(
24937  current_token(),
24938  "ERR172 - Expected a symbol for variable or vector element definition",
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(
24949  current_token(),
24950  "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
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(
24982  current_token(),
24983  "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'",
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(
24996  current_token(),
24997  "ERR175 - Expected ',' between parameters to swap",
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(
25014  current_token(),
25015  "ERR176 - Expected a symbol for variable or vector element definition",
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(
25031  current_token(),
25032  "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
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(
25069  current_token(),
25070  "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
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(
25088  current_token(),
25089  "ERR179 - Expected ')' at end of swap statement",
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(
25145  current_token(),
25146  "ERR180 - Return call within a return call is not allowed",
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(
25169  current_token(),
25170  "ERR181 - Expected '[' at start of return statement",
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(
25192  current_token(),
25193  "ERR182 - Expected ',' between values during call to return",
25195 
25196  return error_node();
25197  }
25198  }
25199  }
25200  else if (settings_.zero_return_disabled())
25201  {
25202  set_error(
25204  current_token(),
25205  "ERR183 - Zero parameter return statement not allowed",
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(
25219  prev_token,
25220  "ERR184 - Invalid ']' found during return call",
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(
25272  current_token(),
25273  "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket",
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(
25320  current_token(),
25321  "ERR186 - Invalid sequence of brackets",
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(
25417  current_token(),
25418  "ERR187 - Failed to generate node for function: '" + symbol + "'",
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(
25443  current_token(),
25444  "ERR188 - Failed to generate node for vararg function: '" + symbol + "'",
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(
25469  current_token(),
25470  "ERR189 - Failed to generate node for generic function: '" + symbol + "'",
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(
25496  current_token(),
25497  "ERR190 - Failed to generate node for string function: '" + symbol + "'",
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(
25522  current_token(),
25523  "ERR191 - Failed to generate node for overload function: '" + symbol + "'",
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(
25548  current_token(),
25549  "ERR192 - Invalid use of reserved symbol '" + symbol + "'",
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(
25611  current_token(),
25612  "ERR193 - Failed to create variable: '" + symbol + "'" +
25613  (error_message.empty() ? "" : " - " + error_message),
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(
25631  current_token(),
25632  "ERR194 - Failed to resolve symbol: '" + symbol + "'" +
25633  (error_message.empty() ? "" : " - " + error_message),
25635  }
25636 
25637  return error_node();
25638  }
25639  }
25640 
25641  set_error(
25643  current_token(),
25644  "ERR195 - Undefined symbol: '" + symbol + "'",
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(
25755  current_token(),
25756  "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
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(
25779  current_token(),
25780  "ERR197 - Failed generate node for scalar: '" + current_token().value + "'",
25782 
25783  return error_node();
25784  }
25785 
25786  next_token();
25787  branch = literal_exp;
25788  }
25789  else
25790  {
25791  set_error(
25793  current_token(),
25794  "ERR198 - Failed to convert '" + current_token().value + "' to a number",
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(
25820  current_token(),
25821  "ERR199 - Expected ')' instead of: '" + current_token().value + "'",
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(
25845  current_token(),
25846  "ERR200 - Expected ']' instead of: '" + current_token().value + "'",
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(
25870  current_token(),
25871  "ERR201 - Expected '}' instead of: '" + current_token().value + "'",
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(
25910  current_token(),
25911  "ERR202 - Premature end of expression[1]",
25913 
25914  return error_node();
25915  }
25916  else
25917  {
25918  set_error(
25920  current_token(),
25921  "ERR203 - Premature end of expression[2]",
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>
25943  {
25944  public:
25945 
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 
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]) &&
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]) ||
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) &&
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  {
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 
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 
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 
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
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
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 
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 
28781  #undef case_stmt
28782  default : return error_node();
28783  }
28784  }
28785  };
28786 
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 
28856  #undef case_stmt
28857  default : return error_node();
28858  }
28859  }
28860  };
28861 
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::
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 
28942  #undef case_stmt
28943  default : return error_node();
28944  }
28945  }
28946  };
28947 
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 
29080  #undef case_stmt
29081  default : return error_node();
29082  }
29083  }
29084  };
29085 
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 
29199  #undef case_stmt
29200  default : return error_node();
29201  }
29202  }
29203  };
29204 
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 
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 
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 
29608  #undef case_stmt
29609  default : return error_node();
29610  }
29611  }
29612  };
29613 
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 
29643  #undef case_stmt
29644  default : return error_node();
29645  }
29646  }
29647  };
29648 
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 
29687  #undef case_stmt
29688  default : return error_node();
29689  }
29690  }
29691  };
29692 
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 
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 
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 
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,
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 
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 
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,
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 
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 
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,
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 
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 
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,
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 
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 
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,
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 
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 
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,
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 
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 
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,
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 
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 
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 
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 
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,
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 
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 
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,
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 
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 
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 
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 
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 
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,
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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>&,
33262  {
33263  return "INVALID";
33264  }
33265  };
33266 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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>&,
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::
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::
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::
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::
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 
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 
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 
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 
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 
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]) ||
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]) ||
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]) &&
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 
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]) &&
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 
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 
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]) &&
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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_;
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_;
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 
35401 
35410 
35411  template <typename ParserType>
35412  friend void details::disable_type_checking(ParserType& p);
35413  };
35414 
35415  namespace details
35416  {
35417  template <typename T>
35419  {
35423  typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35425 
35427  {
35429 
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
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 
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>
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>
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 
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 
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 
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 
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 
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 
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;
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 
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;
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  {
36492 
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 
36514  scoped_bft& operator=(scoped_bft&);
36515  };
36516 
36517  struct func_1param : public base_func
36518  {
36520 
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  {
36534 
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  {
36548 
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  {
36562 
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  {
36576 
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  {
36590 
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 
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 
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 
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
37117 # define NOGDI
37118 # define NORESOURCE
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 
37127 namespace 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 
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
37191  }
37192  else
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
37225 namespace 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,
37233  {
37234  printf(fmt.c_str(),v);
37235  }
37236 
37237  template <typename T>
37238  struct print_impl
37239  {
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>
37295  {
37297 
37299 
37300  print(const std::string& scalar_format = "%10.5f")
37301  : scalar_format_(scalar_format)
37302  {
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>
37317  {
37319 
37321 
37322  println(const std::string& scalar_format = "%10.5f")
37323  : scalar_format_(scalar_format)
37324  {
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  {
37343 
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>
37370 namespace exprtk
37371 {
37372  namespace rtl { namespace io { namespace file { namespace details
37373  {
37375  {
37376  e_error = 0,
37377  e_read = 1,
37378  e_write = 2,
37380  };
37381 
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;
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>
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>
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>
37597  {
37598  public:
37599 
37604 
37606 
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  {
37649 
37651  : exprtk::ifunction<T>(1)
37652  { details::perform_check<T>(); }
37653 
37654  inline T operator() (const T& v)
37655  {
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>
37669  {
37670  public:
37671 
37678 
37680 
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>
37726  {
37727  public:
37728 
37735 
37737 
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>
37783  {
37784  public:
37785 
37791 
37793 
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  {
37810 
37812  : exprtk::ifunction<T>(1)
37813  { details::perform_check<T>(); }
37814 
37815  inline T operator() (const T& v)
37816  {
37818 
37819  return (fd->eof() ? T(1) : T(0));
37820  }
37821  };
37822 
37823  template <typename T>
37824  struct package
37825  {
37832 
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
37863 namespace 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>
37884  {
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>
37929  {
37930  public:
37931 
37936 
37938 
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>
37975  {
37976  public:
37977 
37982 
37984 
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>
38021  {
38022  public:
38023 
38028 
38030 
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>
38067  {
38068  public:
38069 
38074 
38076 
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>
38113  {
38114  public:
38115 
38120 
38122 
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>
38158  {
38159  public:
38160 
38166 
38168 
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 
38216 
38218 
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 
38264 
38266 
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>
38304  {
38305  public:
38306 
38312 
38314 
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>
38359  {
38360  public:
38361 
38367 
38369 
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>
38416  {
38417  public:
38418 
38424 
38426 
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>
38473  {
38474  public:
38475 
38481 
38483 
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>
38515  {
38516  public:
38517 
38523 
38525 
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>
38567  {
38568  public:
38569 
38574 
38576 
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>
38610  {
38611  public:
38612 
38618 
38620 
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>
38657  {
38658  public:
38659 
38665 
38667 
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>
38705  {
38706  public:
38707 
38713 
38715 
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>
38755  {
38756  public:
38757 
38763 
38765 
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>
38806  {
38807  public:
38808 
38814 
38816 
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 
38862 
38864 
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>
38900  {
38901  public:
38902 
38908 
38910 
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  {
38969 
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 
39015 namespace 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
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30191
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12130
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32694
expression_node_ptr synthesize_sosr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34487
virtual char_cptr base() const =0
generic_type::vector_view vector_t
Definition: exprtk.hpp:38712
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29651
generic_type::vector_view vector_t
Definition: exprtk.hpp:38907
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31329
generic_type::string_view string_t
Definition: exprtk.hpp:37789
static std::pair< bool, vector_t * > make(std::deque< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:16466
bool is_stringvar(const std::string &stringvar_name) const
Definition: exprtk.hpp:19063
static std::string id()
Definition: exprtk.hpp:14336
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6455
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12819
manual pdf if(NOT EXISTS"${CMAKE_CURRENT_BINARY_DIR}/images") message(STATUS"creating symlink for manual's images/ subdirectory") execute_process(COMMAND $
Definition: CMakeLists.txt:42
settings_store & disable_inequality_operation(settings_inequality_opr inequality)
Definition: exprtk.hpp:19847
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5566
bool token_is(const token_t::token_type &ttype, const token_advance_mode mode=e_advance)
Definition: exprtk.hpp:4122
opr_base< T >::Type Type
Definition: exprtk.hpp:12210
expression_node_ptr synthesize_null_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34915
details::node_allocator node_allocator_
Definition: exprtk.hpp:35381
scoped_deq_delete(parser< T > &pr, std::deque< ptr_t > &deq)
Definition: exprtk.hpp:21045
static T_ execute(ifunction &f, T_(&v)[9])
Definition: exprtk.hpp:11354
bool compute(const std::string &expression_string, T &result)
Definition: exprtk.hpp:35821
bool update_error(type &error, const std::string &expression)
Definition: exprtk.hpp:18243
operator_type operation() const
Definition: exprtk.hpp:14879
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12286
const vds_t & vds() const
Definition: exprtk.hpp:11072
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8176
std::string type_id() const
Definition: exprtk.hpp:14230
void kahan_sum(T &sum, T &error, const T v)
Definition: exprtk.hpp:37917
void register_symbol_table(symbol_table< T > &st)
Definition: exprtk.hpp:17983
node_type & operator=(node_type &)
Definition: exprtk.hpp:14251
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:13673
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33314
bool is_operator_char(const char_t c)
Definition: exprtk.hpp:103
T compute_pow10(T d, const int exponent)
Definition: exprtk.hpp:1631
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4) const
Definition: exprtk.hpp:15785
function_definition_list_t function_definition_list_
Definition: exprtk.hpp:23700
void dump_error(const type &error)
Definition: exprtk.hpp:18285
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38365
expression(const symbol_table< T > &symbol_table)
Definition: exprtk.hpp:17906
T neg_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1336
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13213
bool is_unary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5114
ivararg_function< T > ivararg_function_t
Definition: exprtk.hpp:18333
static std::size_t min_size(control_block *cb0, control_block *cb1)
Definition: exprtk.hpp:4848
virtual bool join(const token &, const token &, const token &, token &)
Definition: exprtk.hpp:3109
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30128
details::T0oT1oT2oT3_define< T, const_t, cref_t, const_t, cref_t > covocov_t
Definition: exprtk.hpp:18422
expression_node_ptr const_optimise_sf4(const details::operator_type &operation, expression_node_ptr(&branch)[4])
Definition: exprtk.hpp:27450
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12339
std::pair< lexer::token, lexer::token > error(const std::size_t index)
Definition: exprtk.hpp:3868
T expm1_impl(const T v, int_type_tag)
Definition: exprtk.hpp:915
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31241
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5977
expression_node_ptr conditional_string(expression_node_ptr condition, expression_node_ptr consequent, expression_node_ptr alternative) const
Definition: exprtk.hpp:26864
static bool compile_right(expression_generator< Type > &expr_gen, ExternalType t, const details::operator_type &operation, expression_node_ptr &sf3node, expression_node_ptr &result)
Definition: exprtk.hpp:29805
type_store< T > generic_type
Definition: exprtk.hpp:16101
std::stack< std::pair< char, std::size_t > > stack_
Definition: exprtk.hpp:3506
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14860
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:37790
static T_ execute(ifunction &f, T_(&v)[12])
Definition: exprtk.hpp:11333
bool is_continue_node(const expression_node< T > *node)
Definition: exprtk.hpp:5216
control_block(expression_ptr e)
Definition: exprtk.hpp:17813
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:12974
std::string substr(const std::size_t &begin, const std::size_t &end)
Definition: exprtk.hpp:2326
sf3_var_node(const T &v0, const T &v1, const T &v2)
Definition: exprtk.hpp:9380
opr_base< T >::Type Type
Definition: exprtk.hpp:12101
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29412
bool is_end(details::char_cptr itr)
Definition: exprtk.hpp:2346
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32414
static std::string id()
Definition: exprtk.hpp:13962
expression_node_ptr synthesize_csrocsr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34680
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38072
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12276
const range_t & range_ref() const
Definition: exprtk.hpp:9080
std::vector< unsigned char > delete_branch_
Definition: exprtk.hpp:9495
bool wc_imatch(const std::string &wild_card, const std::string &str)
Definition: exprtk.hpp:656
expression_node_t * expression_node_ptr
Definition: exprtk.hpp:18523
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12812
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12132
std::set< std::string, details::ilesscompare > ignore_set_
Definition: exprtk.hpp:3249
vec_data_store(const std::size_t &size)
Definition: exprtk.hpp:4755
expression_node_ptr parse_define_string_statement(const std::string &str_name, expression_node_ptr initialisation_expression)
Definition: exprtk.hpp:24552
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14103
expression_node_ptr synthesize_csrosr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34651
#define register_unary_op(Op, UnaryFunctor)
details::assignment_rebasevec_elem_node< T > assignment_rebasevec_elem_node_t
Definition: exprtk.hpp:18372
settings_store & disable_logic_operation(settings_logic_opr logic)
Definition: exprtk.hpp:19808
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9753
symbol_table_t::function_ptr function_ptr
Definition: exprtk.hpp:18761
void parse_hex(Iterator &itr, Iterator end, std::string::value_type &result)
Definition: exprtk.hpp:313
bool rsrvd_sym_usr_disabled() const
Definition: exprtk.hpp:19668
T equal_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:899
double time() const
Definition: exprtk.hpp:37196
const range_t & range_ref() const
Definition: exprtk.hpp:8171
const std::size_t stride_
Definition: exprtk.hpp:3171
opr_base< T >::Type Type
Definition: exprtk.hpp:12506
expression_node_ptr parse_define_vector_statement(const std::string &vec_name)
Definition: exprtk.hpp:24221
std::pair< lexer::token::token_type, lexer::token::token_type > token_pair_t
Definition: exprtk.hpp:3644
results_context_t * results_context_
Definition: exprtk.hpp:35388
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38614
bool numeric_check_enabled() const
Definition: exprtk.hpp:19660
operator_type operation() const
Definition: exprtk.hpp:14941
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31131
range_data_type< T > range_data_type_t
Definition: exprtk.hpp:11535
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13176
static expression_node_ptr process(expression_generator< Type > &, const details::operator_type &, expression_node_ptr(&)[2])
Definition: exprtk.hpp:34295
generic_type::vector_view vector_t
Definition: exprtk.hpp:38423
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31831
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15395
settings_store settings_t
Definition: exprtk.hpp:20069
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12180
function & name(const std::string &n)
Definition: exprtk.hpp:36248
expression_node_ptr synthesize_expression(F *f, expression_node_ptr(&branch)[N])
Definition: exprtk.hpp:35049
bool is_string_function_node(const expression_node< T > *node)
Definition: exprtk.hpp:15493
value_ptr value_at(const std::size_t &index) const
Definition: exprtk.hpp:5413
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38615
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11836
T0oT1(T0oT1< T, T0, T1 > &)
Definition: exprtk.hpp:13889
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14936
bool inequality_enabled(const details::operator_type &inequality) const
Definition: exprtk.hpp:19713
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12621
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32535
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15376
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9352
type_store_t & operator[](const std::size_t &index)
Definition: exprtk.hpp:4465
const std::string assignment_ops_list[]
Definition: exprtk.hpp:485
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12118
expression_node_ptr parse_return_statement()
Definition: exprtk.hpp:25139
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9583
return_envelope_node(expression_ptr body, results_context_t &rc)
Definition: exprtk.hpp:11971
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12414
virtual const std::string & ref() const
Definition: exprtk.hpp:7741
T ceil_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1338
void add_auxiliary_symtab(symbol_table_t &symtab)
Definition: exprtk.hpp:36701
expression_node_ptr parse_corpus()
Definition: exprtk.hpp:20575
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12133
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38519
libsigrok allows users to import and export data from files in various formats some of them as generic as others very specific For a list and details
lexer::helper::numeric_checker numeric_checker_
Definition: exprtk.hpp:35407
token_list_itr_t store_token_itr_
Definition: exprtk.hpp:2852
expression_node_ptr synthesize_unary_expression(const details::operator_type &operation, expression_node_ptr(&branch)[1])
Definition: exprtk.hpp:27332
exprtk::vector_view< Type > vector_view_t
Definition: exprtk.hpp:5469
bool is_invalid_inequality_operation(const details::operator_type operation) const
Definition: exprtk.hpp:20556
expression_node_ptr synthesize_srocs_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34563
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38262
details::string_concat_node< T > string_concat_node_t
Definition: exprtk.hpp:18364
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7231
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6007
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13191
functor_t::qfunc_t qfunc_t
Definition: exprtk.hpp:14278
range_interface< T > irange_t
Definition: exprtk.hpp:8116
generic_type::vector_view vector_t
Definition: exprtk.hpp:38215
bool is_sign(const char_t c)
Definition: exprtk.hpp:149
expression_node< typename node_type::value_type > * allocate_rrrr(T1 &t1, T2 &t2, T3 &t3, T4 &t4) const
Definition: exprtk.hpp:15672
bool remove_vararg_function(const std::string &vararg_function_name)
Definition: exprtk.hpp:17400
#define case_stmt0(op)
expression_node_ptr varnode_optimise_varargfunc(const details::operator_type &operation, Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27599
opr_base< T >::Type Type
Definition: exprtk.hpp:12283
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12119
bool is_string_condition_node(const expression_node< T > *node)
Definition: exprtk.hpp:15499
details::sf3ext_type_node< T, T0, T1, T2 > sf3_type_node
Definition: exprtk.hpp:14473
T d2g_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1322
void set_default_return_type(const std::string &return_type)
Definition: exprtk.hpp:23465
settings_store & disable_all_logic_ops()
Definition: exprtk.hpp:19615
swap_vecvec_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:7500
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38571
expression_node< typename node_type::value_type > * allocate_cr(const T1 &t1, T2 &t2) const
Definition: exprtk.hpp:15623
ProcessMode process_mode_t
Definition: exprtk.hpp:13906
void set_synthesis_error(const std::string &synthesis_error_message)
Definition: exprtk.hpp:35111
bool is_ivector_node(const expression_node< T > *node)
Definition: exprtk.hpp:5174
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38521
dependent_entity_collector(const std::size_t options=e_ct_none)
Definition: exprtk.hpp:19305
settings_store(const std::size_t compile_options=compile_all_opts)
Definition: exprtk.hpp:19550
T0oT1(T0 p0, T1 p1, const bfunc_t p2)
Definition: exprtk.hpp:13840
vararg_function_node(VarArgFunction *func, const std::vector< expression_ptr > &arg_list)
Definition: exprtk.hpp:11468
bool is_invalid_break_continue_op(expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26517
std::map< operator_t, trinary_functor_t > trinary_op_map_t
Definition: exprtk.hpp:18395
void set_max_num_args(FunctionType &func, const std::size_t &num_args)
Definition: exprtk.hpp:15973
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28789
virtual const T & v1() const =0
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9487
bool is_invalid_assignment_operation(const details::operator_type operation) const
Definition: exprtk.hpp:20551
const range_t & range_ref() const
Definition: exprtk.hpp:7819
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33857
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31043
stringvar_node_t * stringvar_node_ptr
Definition: exprtk.hpp:18447
operator_type operation() const
Definition: exprtk.hpp:14296
std::string get_vector_name(const vector_holder_ptr &ptr) const
Definition: exprtk.hpp:19155
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2) const
Definition: exprtk.hpp:15616
bool is_binary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5126
expression_node< typename node_type::value_type > * allocate() const
Definition: exprtk.hpp:15588
expression_node_ptr for_loop(expression_node_ptr &initialiser, expression_node_ptr &condition, expression_node_ptr &incrementor, expression_node_ptr &loop_body, bool brkcont=false) const
Definition: exprtk.hpp:26986
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12607
std::string type_id() const
Definition: exprtk.hpp:14139
void load_from(const symbol_table< T > &st)
Definition: exprtk.hpp:17610
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7434
T min_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:874
expression_node_ptr parse_symtab_symbol()
Definition: exprtk.hpp:25337
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14874
void process_lexer_errors()
Definition: exprtk.hpp:20280
expression_node< typename node_type::value_type > * allocate_rrrrr(T1 &t1, T2 &t2, T3 &t3, T4 &t4, T5 &t5) const
Definition: exprtk.hpp:15679
opr_base< T >::Type Type
Definition: exprtk.hpp:12188
control_block(const std::size_t &dsize, data_t dptr, bool dstrct=false)
Definition: exprtk.hpp:4684
static T process(const T &, const T &)
Definition: exprtk.hpp:12326
details::T0oT1oT2_sf3< T, T0, T1, T2 > sf3_type
Definition: exprtk.hpp:14472
expression_node_ptr parse_multi_sequence(const std::string &source="")
Definition: exprtk.hpp:22824
T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
Definition: exprtk.hpp:14193
details::T0oT1oT2_define< T, const_t, cref_t, cref_t > covov_t
Definition: exprtk.hpp:18411
bool is_generally_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:15523
T exp_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1332
std::pair< bool, type_ptr > type_pair_t
Definition: exprtk.hpp:16353
T trunc_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1344
T modulus_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:948
static std::string result()
Definition: exprtk.hpp:13596
opr_base< T >::Type Type
Definition: exprtk.hpp:12242
results_context< T > results_context_t
Definition: exprtk.hpp:11969
void clear_variables(const bool delete_node=true)
Definition: exprtk.hpp:16883
parser_t::dependent_entity_collector::symbol_t symbol_t
Definition: exprtk.hpp:35423
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38812
expression_node_ptr parse_break_statement()
Definition: exprtk.hpp:24132
lexer::helper::operator_joiner operator_joiner_3_
Definition: exprtk.hpp:35404
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12789
sos_node(SType0 p0, SType1 p1)
Definition: exprtk.hpp:14864
const value_t & operator[](const std::size_t &i) const
Definition: exprtk.hpp:4356
bool is_control_struct(const std::string &cntrl_strct)
Definition: exprtk.hpp:541
static T evaluate(const Type x, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36015
void register_return_results(expression< T > &e)
Definition: exprtk.hpp:35178
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6478
details::assignment_vec_node< T > assignment_vec_node_t
Definition: exprtk.hpp:18374
operator_type operation() const
Definition: exprtk.hpp:14708
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7123
const std::size_t size_
Definition: exprtk.hpp:4228
generic_function_ptr get_string_function(const std::string &function_name) const
Definition: exprtk.hpp:18934
expression_node_ptr synthesize_socsr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34500
range_interface< T > irange_t
Definition: exprtk.hpp:8979
lexer::helper::helper_assembly helper_assembly_
Definition: exprtk.hpp:35400
type & operator=(const type &vds)
Definition: exprtk.hpp:4774
opr_base< T >::Type Type
Definition: exprtk.hpp:12864
results_context_t & results_ctx()
Definition: exprtk.hpp:35351
T csc_impl(const T, int_type_tag)
Definition: exprtk.hpp:1359
settings_store & enable_local_vardef()
Definition: exprtk.hpp:19591
static details::operator_type operation()
Definition: exprtk.hpp:12257
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6869
vararg_function_ptr get_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:16995
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33457
bool valid_operator(const details::operator_type &operation, unary_functor_t &uop)
Definition: exprtk.hpp:26083
symbol_table_t symbol_table_
Definition: exprtk.hpp:36906
vector_view(const vector_view< T > &vv)
Definition: exprtk.hpp:4182
stringvar_ptr get_stringvar(const std::string &string_name) const
Definition: exprtk.hpp:16974
opr_base< T >::Type Type
Definition: exprtk.hpp:12313
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31853
node_type & operator=(node_type &)
Definition: exprtk.hpp:13978
bipow_node(expression_ptr brnch)
Definition: exprtk.hpp:15313
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6372
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5901
bool is_vector_node(const expression_node< T > *node)
Definition: exprtk.hpp:5168
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12317
std::vector< token_t >::iterator token_list_itr_t
Definition: exprtk.hpp:2204
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8451
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:15113
expression_node_ptr synthesize_swap_expression(expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28406
generic_type::vector_view vector_t
Definition: exprtk.hpp:38366
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t+t)") define_sfop3(16
bool is_sf4ext_node(const expression_node< T > *n)
Definition: exprtk.hpp:14444
vector_node_ptr vec() const
Definition: exprtk.hpp:11047
bool is_genricstring_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:15517
vec_data_store< T > vds_t
Definition: exprtk.hpp:7498
swap_genstrings_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8200
expression_node< typename node_type::value_type > * allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
Definition: exprtk.hpp:15658
static details::operator_type operation()
Definition: exprtk.hpp:12236
std::size_t process_stride_3(generator &g)
Definition: exprtk.hpp:3142
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37934
settings_store & disable_all_inequality_ops()
Definition: exprtk.hpp:19642
static T process_7(const Sequence &arg_list)
Definition: exprtk.hpp:12946
void assign(const parameter_list_t &pl)
Definition: exprtk.hpp:4485
details::assignment_node< T > assignment_node_t
Definition: exprtk.hpp:18370
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:10940
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32392
symtab_store symtab_store_
Definition: exprtk.hpp:35382
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:11140
bool add(const std::string &symbol_name, exprtk::vector_view< T > &v, const bool is_const=false)
Definition: exprtk.hpp:16492
std::size_t size() const
Definition: exprtk.hpp:2250
static details::operator_type operation()
Definition: exprtk.hpp:12121
static bool is_unary(const expression< T > &expr)
Definition: exprtk.hpp:18144
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30113
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:11519
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:11537
bool sf4_optimisable(const std::string &sf4id, details::operator_type &operation) const
Definition: exprtk.hpp:26190
bool is_rebasevector_celem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5162
details::vector_elem_node< T > vector_elem_node_t
Definition: exprtk.hpp:18353
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12166
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6770
const range_t & range_ref() const
Definition: exprtk.hpp:8826
void register_local_vars(expression< T > &e)
Definition: exprtk.hpp:35119
details::T0oT1oT2oT3_define< T, cref_t, cref_t, cref_t, const_t > vovovoc_t
Definition: exprtk.hpp:18417
expression_node_t * expression_node_ptr
Definition: exprtk.hpp:18379
bool cocob_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26411
bool run_modifiers(lexer::generator &g)
Definition: exprtk.hpp:3955
bool add(const function &f, const bool override=false)
Definition: exprtk.hpp:36726
string_concat_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:7980
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7824
igeneric_function(const std::string &param_seq="", const return_type rtr_type=e_rtrn_scalar)
Definition: exprtk.hpp:16104
unknown_symbol_resolver(const usr_mode m=e_usrmode_default)
Definition: exprtk.hpp:19247
bool add_vector(const std::string &vector_name, exprtk::vector_view< T > &v)
Definition: exprtk.hpp:17360
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6319
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9391
T log2_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1335
T derivative(const expression< T > &e, T &x, const T &h=T(0.00000001))
Definition: exprtk.hpp:35666
virtual T const T &virtual empty_method_body T const T const T const T &virtual empty_method_body T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T &virtual empty_method_body T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T const T &empty_method_body std::size_t param_count
Definition: exprtk.hpp:16064
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12128
expression< T > & release()
Definition: exprtk.hpp:17951
symbol_table(const symbol_table< T > &st)
Definition: exprtk.hpp:16859
lexer::token_scanner * error_token_scanner
Definition: exprtk.hpp:4048
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32513
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30176
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12567
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
Definition: exprtk.hpp:14150
swap_generic_node(expression_ptr var0, expression_ptr var1)
Definition: exprtk.hpp:7467
token & set_string(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2092
T log10_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1334
void update(const T &v0, const T &v1)
Definition: exprtk.hpp:36300
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31588
binary_ext_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:5959
bool compile_expression(const std::string &name, const std::string &expression, const Sequence< std::string, Allocator > &input_var_list, bool return_present=false)
Definition: exprtk.hpp:36735
static const double _2_pi
Definition: exprtk.hpp:757
expression_node_ptr get_variable(const T &v)
Definition: exprtk.hpp:18684
bool add(const std::string &symbol_name, RawType &t, const bool is_const=false)
Definition: exprtk.hpp:16505
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12748
control_block * control_block_
Definition: exprtk.hpp:18121
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33879
static std::string result()
Definition: exprtk.hpp:13593
generic_type::parameter_list parameter_list_t
Definition: exprtk.hpp:11910
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:14738
static bool cmp(const char_t c0, const char_t c1)
Definition: exprtk.hpp:569
static std::string id()
Definition: exprtk.hpp:14235
#define poly_rtrn(NN)
Definition: exprtk.hpp:36089
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:13693
#define register_sf4ext(Op)
void parse_function_prototypes(const std::string &func_prototypes)
Definition: exprtk.hpp:23643
details::T0oT1oT2_define< T, cref_t, cref_t, const_t > vovoc_t
Definition: exprtk.hpp:18409
#define exprtk_register_int_type_tag(T)
Definition: exprtk.hpp:785
token & set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2082
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37886
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37979
#define case_stmt(N)
Definition: exprtk.hpp:27116
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3) const
Definition: exprtk.hpp:15686
bool in_use() const
Definition: exprtk.hpp:37203
static T_ execute(ifunction &f, T_(&v)[11])
Definition: exprtk.hpp:11340
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:7846
std::vector< type_store_t > typestore_list_t
Definition: exprtk.hpp:11540
std::vector< std::pair< lexer::token, lexer::token > > error_list_
Definition: exprtk.hpp:3894
static T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36059
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32294
std::size_t min_num_args_
Definition: exprtk.hpp:15930
token_scanner(const std::size_t &stride)
Definition: exprtk.hpp:2882
static std::pair< bool, vector_t * > make(exprtk::vector_view< T > &v, const bool is_const=false)
Definition: exprtk.hpp:16457
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10629
functor_t::qfunc_t quaternary_functor_t
Definition: exprtk.hpp:18386
details::operator_type operation
Definition: exprtk.hpp:20687
bool is_conststr_stringvar(const std::string &symbol_name) const
Definition: exprtk.hpp:17542
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30302
std::string str() const
Definition: exprtk.hpp:9060
bool is_uv_node(const expression_node< T > *node)
Definition: exprtk.hpp:15451
token & set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2072
T roundn_impl(const T v0, const T, int_type_tag)
Definition: exprtk.hpp:1043
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:5645
static details::operator_type operation()
Definition: exprtk.hpp:12318
bool add_element(const scope_element &se)
Definition: exprtk.hpp:18593
T0oT1oT2oT3_sf4< T, T0, T1, T2, T3 > node_type
Definition: exprtk.hpp:14280
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37932
T tan_impl(const T, int_type_tag)
Definition: exprtk.hpp:1355
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12595
void disable_unknown_symbol_resolver()
Definition: exprtk.hpp:20492
functor_t::bfunc_t binary_functor_t
Definition: exprtk.hpp:18388
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9534
bool commutative_check_enabled() const
Definition: exprtk.hpp:19658
string_literal_node(const std::string &v)
Definition: exprtk.hpp:5706
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12613
bool create_variable(const std::string &variable_name, const T &value=T(0))
Definition: exprtk.hpp:17095
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:34037
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12758
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12316
bool empty() const
Definition: exprtk.hpp:2245
cov_node(const T &const_var, const T &var)
Definition: exprtk.hpp:14546
expression_node_ptr parse_const_string()
Definition: exprtk.hpp:23180
vector_holder(Type *vec, const std::size_t &vec_size)
Definition: exprtk.hpp:5508
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32956
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30944
std::size_t process(generator &g)
Definition: exprtk.hpp:3014
T frac_impl(const T, int_type_tag)
Definition: exprtk.hpp:1343
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32574
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15036
bool is_bracket(const char_t c)
Definition: exprtk.hpp:144
std::size_t size() const
Definition: exprtk.hpp:4346
expression_node_ptr parse_continue_statement()
Definition: exprtk.hpp:24197
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11466
std::size_t process(generator &g)
Definition: exprtk.hpp:2891
static const std::size_t assignment_ops_list_size
Definition: exprtk.hpp:491
std::size_t max_num_args_
Definition: exprtk.hpp:15931
#define exprtk_debug(params)
Definition: exprtk.hpp:64
details::char_cptr s_itr_
Definition: exprtk.hpp:2855
vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7196
expression_node< T > * move_branch(const std::size_t &)
Definition: exprtk.hpp:14778
settings_store & disable_all_arithmetic_ops()
Definition: exprtk.hpp:19624
symbol_table_list_t symtab_list_
Definition: exprtk.hpp:18757
void set_strength_reduction_state(const bool enabled)
Definition: exprtk.hpp:26061
bool invalid_range(const Vector &v, const std::size_t r0, const std::size_t r1)
Definition: exprtk.hpp:37870
void add_symbol(const std::string &symbol, const symbol_type st)
Definition: exprtk.hpp:19403
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38161
bool is_string_vararg_node(const expression_node< T > *node)
Definition: exprtk.hpp:15511
T cos_impl(const T, int_type_tag)
Definition: exprtk.hpp:1351
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32776
virtual bool populate_value_list() const
Definition: exprtk.hpp:11667
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9446
std::vector< expression_node_ptr > arg_list_t
Definition: exprtk.hpp:27114
void register_return_results(results_context_t *rc)
Definition: exprtk.hpp:18105
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12131
static std::string id(expression_generator< Type > &, const details::operator_type, const details::operator_type, const details::operator_type)
Definition: exprtk.hpp:33260
static details::operator_type operation()
Definition: exprtk.hpp:12134
const results_context_t & results() const
Definition: exprtk.hpp:18000
const std::string inequality_ops_list[]
Definition: exprtk.hpp:493
bool compile(const std::string &expression_string, expression< T > &expr)
Definition: exprtk.hpp:20173
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38476
bool collect_assignments_enabled() const
Definition: exprtk.hpp:19666
std::string to_str(int i)
Definition: exprtk.hpp:263
std::vector< function_prototype_t > function_definition_list_t
Definition: exprtk.hpp:23451
bool match_impl(const Iterator pattern_begin, const Iterator pattern_end, const Iterator data_begin, const Iterator data_end, const typename std::iterator_traits< Iterator >::value_type &zero_or_more, const typename std::iterator_traits< Iterator >::value_type &zero_or_one)
Definition: exprtk.hpp:584
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10593
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11660
node_type & operator=(node_type &)
Definition: exprtk.hpp:14160
inv_binary_op_map_t * inv_binary_op_map_
Definition: exprtk.hpp:35092
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14637
void load_sf3_map(sf3_map_t &sf3_map)
Definition: exprtk.hpp:35287
const T & v() const
Definition: exprtk.hpp:14713
bfunc_t f1() const
Definition: exprtk.hpp:13952
expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type &opr, T0 s0, T1 s1, range_t rp0)
Definition: exprtk.hpp:34398
bool symbol_exists(const std::string &symbol_name, const bool check_reserved_symb=true) const
Definition: exprtk.hpp:17500
std::vector< ifunction< T > * > free_function_list_
Definition: exprtk.hpp:16796
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:13605
function_ptr get_function(const std::string &function_name) const
Definition: exprtk.hpp:16985
static details::operator_type operation()
Definition: exprtk.hpp:12171
static const double _1_pi
Definition: exprtk.hpp:756
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12469
details::T0oT1oT2oT3_sf4< T, T0, T1, T2, T3 > sf4_type
Definition: exprtk.hpp:14484
bool add(const std::string &symbol_name, T *v, const std::size_t v_size, const bool is_const=false)
Definition: exprtk.hpp:16479
expression_node_ptr multi_switch_statement(Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27243
functor_t::qfunc_t quaternary_functor_t
Definition: exprtk.hpp:9121
bool operator()(const std::string &s1, const std::string &s2) const
Definition: exprtk.hpp:201
results_context< T > results_context_t
Definition: exprtk.hpp:11927
bool is_reserved_symbol(const std::string &symbol) const
Definition: exprtk.hpp:16777
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode2 > type2
Definition: exprtk.hpp:14481
static bool compile(expression_generator< Type > &expr_gen, const std::string &id, T0 t0, T1 t1, T2 t2, expression_node_ptr &result)
Definition: exprtk.hpp:29720
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32474
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11765
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30317
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12201
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37672
std::string branch_to_id(expression_node_ptr branch) const
Definition: exprtk.hpp:26320
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12191
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:5804
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12156
opr_base< T >::Type Type
Definition: exprtk.hpp:12263
stringvar_node(std::string &v)
Definition: exprtk.hpp:7614
const std::string reserved_symbols[]
Definition: exprtk.hpp:430
details::variable_node< T > variable_node_t
Definition: exprtk.hpp:18352
expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
Definition: exprtk.hpp:21746
static const double pow10[]
Definition: exprtk.hpp:737
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:37344
static bool test(const variable_node_t *p, const void *ptr)
Definition: exprtk.hpp:16570
generic_type::vector_view vector_t
Definition: exprtk.hpp:37981
null_igenfunc< T > igeneric_function_t
Definition: exprtk.hpp:11924
settings_store & enable_assignment_operation(settings_assignment_opr assignment)
Definition: exprtk.hpp:19932
#define define_sfop4(NN, OP0, OP1)
static T evaluate(const Type x, const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:35979
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33077
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38903
void set_retinvk(bool *retinvk_ptr)
Definition: exprtk.hpp:18113
control_block * control_block_
Definition: exprtk.hpp:4859
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:37833
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30443
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6521
vararg_function_ptr get_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:18892
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38613
virtual std::string type_id() const =0
assignment_vec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9757
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28950
stringvar_node_ptr str_node
Definition: exprtk.hpp:18515
void set_uom(unary_op_map_t &unary_op_map)
Definition: exprtk.hpp:26031
scope_element & get_active_element(const std::string &var_name, const std::size_t index=std::numeric_limits< std::size_t >::max())
Definition: exprtk.hpp:18571
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:13836
vec_binop_valvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10789
node_type & operator=(node_type &)
Definition: exprtk.hpp:14075
static void destroy(control_block *&cntrl_blck)
Definition: exprtk.hpp:4714
bool valid_function_name(const std::string &symbol) const
Definition: exprtk.hpp:18801
lexer::token_modifier * error_token_modifier
Definition: exprtk.hpp:4049
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38214
vec_data_store(const std::size_t &size, data_t data, bool dstrct=false)
Definition: exprtk.hpp:4759
bool is_neg_unary_node(const expression_node< T > *node)
Definition: exprtk.hpp:5120
T modulus(const T v0, const T v1)
Definition: exprtk.hpp:1432
expression_node_ptr synthesize_sos_expression_impl(const details::operator_type &opr, T0 s0, T1 s1)
Definition: exprtk.hpp:34452
settings_store & enable_all_logic_ops()
Definition: exprtk.hpp:19567
bool valid() const
Definition: exprtk.hpp:17604
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7192
void set_allocator(details::node_allocator &na)
Definition: exprtk.hpp:26056
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33615
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31395
std::size_t size() const
Definition: exprtk.hpp:5530
void load_binary_operations_map(binary_op_map_t &m)
Definition: exprtk.hpp:35231
generic_function_t * generic_function_ptr
Definition: exprtk.hpp:16736
type_store_t::parameter_list parameter_list_t
Definition: exprtk.hpp:4483
#define exprtk_error_location
Definition: exprtk.hpp:67
bool is_null_node(const expression_node< T > *node)
Definition: exprtk.hpp:5204
string_range_node(std::string &v, const range_t &rp)
Definition: exprtk.hpp:7696
expression_node_ptr synthesize_string_expression(const details::operator_type &opr, expression_node_ptr(&branch)[3])
Definition: exprtk.hpp:34799
void copy(const lvr_vec_t &src_v, var_t &dest_v)
Definition: exprtk.hpp:36427
bool is_conststr_stringvar(const std::string &symbol_name) const
Definition: exprtk.hpp:19079
functor_t::tfunc_t tfunc_t
Definition: exprtk.hpp:14092
std::set< token_pair_t > set_t
Definition: exprtk.hpp:3645
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33237
static details::operator_type operation()
Definition: exprtk.hpp:12215
details::T0oT1oT2oT3_define< T, cref_t, const_t, cref_t, cref_t > vocovov_t
Definition: exprtk.hpp:18419
const std::string reserved_words[]
Definition: exprtk.hpp:419
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12828
token_t & peek_next_token()
Definition: exprtk.hpp:2281
bool is_const_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:15469
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38760
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7124
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5720
str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
Definition: exprtk.hpp:15040
const return_type_t default_return_type_
Definition: exprtk.hpp:23699
assignment_vec_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10175
unsigned long long int _uint64_t
Definition: exprtk.hpp:92
std::vector< unsigned char > delete_branch_
Definition: exprtk.hpp:6778
bool is_nan(const T v)
Definition: exprtk.hpp:1397
T cosh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1352
type_store< ivararg_function< T >, ivararg_function< T > > vararg_function_store
Definition: exprtk.hpp:16750
details::T0oT1< T, T0, T1 > type0
Definition: exprtk.hpp:14464
bool is_vector(const std::string &vector_name) const
Definition: exprtk.hpp:17574
std::set< std::string, details::ilesscompare > disabled_entity_set_t
Definition: exprtk.hpp:19458
details::repeat_until_loop_node< T > repeat_until_loop_node_t
Definition: exprtk.hpp:18344
multimode_strfunction_node(StringFunction *func, const std::size_t &param_seq_index, const std::vector< typename str_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:11855
std::vector< lexer::token_scanner * > token_scanner_list
Definition: exprtk.hpp:4043
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38811
expression_node_ptr synthesize_csos_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34539
virtual expression_node< T > * move_branch(const std::size_t &index)=0
T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
Definition: exprtk.hpp:14371
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34240
details::T0oT1oT2oT3_define< T, cref_t, cref_t, const_t, cref_t > vovocov_t
Definition: exprtk.hpp:18418
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30365
vararg_function_t * vararg_function_ptr
Definition: exprtk.hpp:16735
const range_t & range_ref() const
Definition: exprtk.hpp:11790
igeneric_function< T > GF
Definition: exprtk.hpp:18331
#define exprtk_register_function(FunctionName, FunctionType)
bool is_vector_eqineq_logic_operation(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26608
static const std::size_t reserved_words_size
Definition: exprtk.hpp:428
T nequal_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:936
virtual node_type type() const
Definition: exprtk.hpp:5071
static bool parse_nan(Iterator &itr, const Iterator end, T &t)
Definition: exprtk.hpp:1766
operator_type operation() const
Definition: exprtk.hpp:13438
token_list_t token_list_
Definition: exprtk.hpp:2850
generic_type::string_view string_t
Definition: exprtk.hpp:38422
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38906
std::size_t process_stride_2(generator &g)
Definition: exprtk.hpp:3113
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:34279
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12358
std::size_t size() const
Definition: exprtk.hpp:4288
bool is_string_concat_node(const expression_node< T > *node)
Definition: exprtk.hpp:15487
std::vector< scope_element > element_
Definition: exprtk.hpp:18713
bool operator==(const symbol_table< T > &st) const
Definition: exprtk.hpp:16878
STL namespace.
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38259
std::size_t get_variable_list(Sequence< std::pair< std::string, T >, Allocator > &vlist) const
Definition: exprtk.hpp:17450
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15346
assignment_vecvec_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10298
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8544
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) const
Definition: exprtk.hpp:15806
std::map< std::string, std::pair< std::string, token::token_type >, details::ilesscompare > replace_map_t
Definition: exprtk.hpp:3577
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:14688
rebasevector_celem_node< T > * rbvec_node_ptr_
Definition: exprtk.hpp:10162
ifunction< T > ifunction_t
Definition: exprtk.hpp:18332
operator_type operation()
Definition: exprtk.hpp:5930
void rebase(data_ptr_t data)
Definition: exprtk.hpp:4188
sf4_var_node(const T &v0, const T &v1, const T &v2, const T &v3)
Definition: exprtk.hpp:9413
settings_store & enable_all_assignment_ops()
Definition: exprtk.hpp:19579
bool join(const lexer::token &t0, const lexer::token &t1, lexer::token &t)
Definition: exprtk.hpp:3260
std::string get_stringvar_name(const expression_node_ptr &ptr) const
Definition: exprtk.hpp:19161
virtual expression_node< T > * move_branch(const std::size_t &index)=0
T second_derivative(const expression< T > &e, T &x, const T &h=T(0.00001))
Definition: exprtk.hpp:35687
opr_base< T >::Type Type
Definition: exprtk.hpp:12303
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12141
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:37733
settings_store settings_
Definition: exprtk.hpp:35379
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10022
void free_element(scope_element &se)
Definition: exprtk.hpp:18636
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32354
void load_unary_operations_map(unary_op_map_t &m)
Definition: exprtk.hpp:35184
results_context< T > results_context_t
Definition: exprtk.hpp:17803
details::functor_t< T >::Type Type
Definition: exprtk.hpp:9119
details::variable_node< T > variable_t
Definition: exprtk.hpp:16724
vector_node_ptr vec() const
Definition: exprtk.hpp:10583
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:8450
static std::string null_value
Definition: exprtk.hpp:7694
const T1 const T2
Definition: exprtk.hpp:13791
exprtk::ifunction< T > function_t
Definition: exprtk.hpp:36276
T sgn_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1105
std::map< std::string, expression_t > expr_map_
Definition: exprtk.hpp:36908
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33676
void insert_front(token_t::token_type tk_type)
Definition: exprtk.hpp:2312
vector_node(const vds_t &vds, vector_holder_t *vh)
Definition: exprtk.hpp:7135
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5577
std::size_t size() const
Definition: exprtk.hpp:4810
type_map_t::iterator tm_itr_t
Definition: exprtk.hpp:16355
vararg_varnode(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:9507
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38260
void update(const T &v0, const T &v1, const T &v2, const T &v3)
Definition: exprtk.hpp:36311
bool is_constant_node(const std::string &symbol_name) const
Definition: exprtk.hpp:18997
value_ptr operator[](const std::size_t &index) const
Definition: exprtk.hpp:5374
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33375
variable_node< T > * variable_node_ptr
Definition: exprtk.hpp:7435
type_store< T > type_store_t
Definition: exprtk.hpp:4451
static T evaluate(const Type x, const Type c1, const Type c0)
Definition: exprtk.hpp:36069
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28864
generic_function_node< T, StringFunction > gen_function_t
Definition: exprtk.hpp:11723
print(const std::string &scalar_format="%10.5f")
Definition: exprtk.hpp:37300
void load_sf4_map(sf4_map_t &sf4_map)
Definition: exprtk.hpp:35311
static expression_node_ptr process(expression_generator< Type > &, const details::operator_type &, expression_node_ptr(&)[2])
Definition: exprtk.hpp:30927
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12168
file_mode get_file_mode(const std::string &access) const
Definition: exprtk.hpp:37535
#define extended_opr_switch_statements
Definition: exprtk.hpp:28531
settings_store & disable_local_vardef()
Definition: exprtk.hpp:19651
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6008
T round_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1340
static const std::size_t inequality_ops_list_size
Definition: exprtk.hpp:500
bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
Definition: exprtk.hpp:19764
T max_impl(const T v0, const T v1, real_type_tag)
Definition: exprtk.hpp:880
bool is_invalid_arithmetic_operation(const details::operator_type operation) const
Definition: exprtk.hpp:20546
bool is_constpow_operation(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26501
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32994
vector_elem_node< T > * vec_node_ptr_
Definition: exprtk.hpp:9668
ts_list_t parameter_list_
Definition: exprtk.hpp:4492
T0oT1oT2oT3< T, T0, T1, T2, T3, ProcessMode > node_type
Definition: exprtk.hpp:13999
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32272
long long int _int64_t
Definition: exprtk.hpp:93
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:14834
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33737
virtual bool process(const std::string &, usr_symbol_type &st, T &default_value, std::string &error_message)
Definition: exprtk.hpp:19254
expression_node< T > * move_branch(const std::size_t &)
Definition: exprtk.hpp:14839
vec_data_store< T > type
Definition: exprtk.hpp:4663
parser(const settings_t &settings=settings_t())
Definition: exprtk.hpp:20071
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10784
token_list_itr_t token_itr_
Definition: exprtk.hpp:2851
settings_store & disable_all_base_functions()
Definition: exprtk.hpp:19597
bool token_is(const token_t::token_type &ttype, const std::string &value, const token_advance_mode mode=e_advance)
Definition: exprtk.hpp:4134
function_t * function_ptr
Definition: exprtk.hpp:16734
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12157
expression_node_ptr conditional(expression_node_ptr condition, expression_node_ptr consequent, expression_node_ptr alternative) const
Definition: exprtk.hpp:26818
vector_holder(const vds_t &vds)
Definition: exprtk.hpp:5512
std::size_t error_index(const std::size_t &i)
Definition: exprtk.hpp:3554
scope_element & get_element(const std::string &var_name, const std::size_t index=std::numeric_limits< std::size_t >::max())
Definition: exprtk.hpp:18550
#define else_stmt(N)
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32874
static T_ execute(ifunction &f, T_(&v)[18])
Definition: exprtk.hpp:11291
exprtk_define_unary_op(abs) exprtk_define_unary_op(acos) exprtk_define_unary_op(acosh) exprtk_define_unary_op(asin) exprtk_define_unary_op(asinh) exprtk_define_unary_op(atan) exprtk_define_unary_op(atanh) exprtk_define_unary_op(ceil) exprtk_define_unary_op(cos) exprtk_define_unary_op(cosh) exprtk_define_unary_op(cot) exprtk_define_unary_op(csc) exprtk_define_unary_op(d2g) exprtk_define_unary_op(d2r) exprtk_define_unary_op(erf) exprtk_define_unary_op(erfc) exprtk_define_unary_op(exp) exprtk_define_unary_op(expm1) exprtk_define_unary_op(floor) exprtk_define_unary_op(frac) exprtk_define_unary_op(g2d) exprtk_define_unary_op(log) exprtk_define_unary_op(log10) exprtk_define_unary_op(log2) exprtk_define_unary_op(log1p) exprtk_define_unary_op(ncdf) exprtk_define_unary_op(neg) exprtk_define_unary_op(notl) exprtk_define_unary_op(pos) exprtk_define_unary_op(r2d) exprtk_define_unary_op(round) exprtk_define_unary_op(sec) exprtk_define_unary_op(sgn) exprtk_define_unary_op(sin) exprtk_define_unary_op(sinc) exprtk_define_unary_op(sinh) exprtk_define_unary_op(sqrt) exprtk_define_unary_op(tan) exprtk_define_unary_op(tanh) exprtk_define_unary_op(trunc) template< typename T > struct opr_base
Definition: exprtk.hpp:12044
type_view< char > string_view
Definition: exprtk.hpp:4379
std::size_t count() const
Definition: exprtk.hpp:4457
disabled_entity_set_t disabled_arithmetic_set_
Definition: exprtk.hpp:20062
ifunction< T > function_t
Definition: exprtk.hpp:16731
stringvar_node< T > * strvar_node_ptr
Definition: exprtk.hpp:8112
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7125
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14687
expression_node_ptr var_node
Definition: exprtk.hpp:18512
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12475
expression_node_ptr parse_repeat_until_loop()
Definition: exprtk.hpp:21941
vector_holder_base * vector_holder_base_
Definition: exprtk.hpp:5552
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8418
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9549
expression_node_ptr synthesize_strogen_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34695
std::vector< std::size_t > error_list_
Definition: exprtk.hpp:3570
expression_node< T >::node_type type() const
Definition: exprtk.hpp:13846
std::map< std::string, std::pair< quaternary_functor_t, operator_t > > sf4_map_t
Definition: exprtk.hpp:18398
std::string & stringvar_ref(const std::string &symbol_name)
Definition: exprtk.hpp:17059
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12115
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:13903
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37730
opr_base< T >::Type Type
Definition: exprtk.hpp:12335
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12234
T sinc_impl(T v, int_type_tag)
Definition: exprtk.hpp:1291
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38710
static details::operator_type operation()
Definition: exprtk.hpp:12354
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode3 > type3
Definition: exprtk.hpp:14482
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11529
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12532
T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
Definition: exprtk.hpp:14096
opr_base< T >::Type Type
Definition: exprtk.hpp:12140
expression_node_ptr return_envelope(expression_node_ptr body, results_context_t *rc, bool *&return_invoked)
Definition: exprtk.hpp:27904
bool parse_range(range_t &rp, const bool skip_lsqr=false)
Definition: exprtk.hpp:22904
const T & v1() const
Definition: exprtk.hpp:14521
expression_node_ptr parse_branch(precedence_level precedence=e_level00)
Definition: exprtk.hpp:25763
node_type & operator=(node_type &)
Definition: exprtk.hpp:14352
function_N_node(ifunction *func)
Definition: exprtk.hpp:11143
scope_element_manager sem_
Definition: exprtk.hpp:35398
str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
Definition: exprtk.hpp:14914
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32634
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12245
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15358
bool arithmetic_enabled(const details::operator_type &arithmetic_operation) const
Definition: exprtk.hpp:19695
parameter_list(std::vector< type_store > &pl)
Definition: exprtk.hpp:4279
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8193
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34179
std::size_t cache_size() const
Definition: exprtk.hpp:7055
disabled_entity_set_t disabled_ctrl_set_
Definition: exprtk.hpp:20060
std::string get_vector_name(const vector_holder_ptr &ptr) const
Definition: exprtk.hpp:17587
void case_normalise(std::string &s)
Definition: exprtk.hpp:168
results_context< T > results_context_t
Definition: exprtk.hpp:17998
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38761
static details::operator_type operation()
Definition: exprtk.hpp:12247
string_base_node< T > * strbase_ptr_t
Definition: exprtk.hpp:7074
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12672
type_store< T > type_store_t
Definition: exprtk.hpp:4383
functor_t::ufunc_t unary_functor_t
Definition: exprtk.hpp:9124
std::string get_variable_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:17582
expression_node_t * expression_node_ptr
Definition: exprtk.hpp:18445
const control_block::local_data_list_t & local_data_list()
Definition: exprtk.hpp:18092
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:37242
expression_node_ptr vararg_function(const details::operator_type &operation, Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27647
std::string logic_opr_to_string(details::operator_type opr) const
Definition: exprtk.hpp:20030
bool is_sf3ext_node(const expression_node< T > *n)
Definition: exprtk.hpp:14259
std::list< std::string > local_stringvar_list_
Definition: exprtk.hpp:16794
const T const_t
Definition: exprtk.hpp:18328
std::map< binary_functor_t, operator_t > inv_binary_op_map_t
Definition: exprtk.hpp:18400
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12538
std::size_t process(generator &g)
Definition: exprtk.hpp:3095
details::T0oT1oT2< T, T0, T1, T2, typename T0oT1oT2process< T >::mode0 > type0
Definition: exprtk.hpp:14470
bool to_int(IntType &i) const
Definition: exprtk.hpp:4405
std::size_t error_count() const
Definition: exprtk.hpp:20447
const T & operator[](const std::size_t index) const
Definition: exprtk.hpp:4211
virtual const T & v() const =0
static void execute(T_(&v)[1], const branch_t(&b)[1])
Definition: exprtk.hpp:11265
std::vector< symbol_t > symbol_list_t
Definition: exprtk.hpp:19303
exprtk::details::numeric::details::number_type< T >::type num_type
Definition: exprtk.hpp:37245
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) const
Definition: exprtk.hpp:15795
T logn_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:972
bool vov_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26384
std::string error() const
Definition: exprtk.hpp:20437
range_interface< T > irange_t
Definition: exprtk.hpp:7977
std::vector< ptr_t > & vec_
Definition: exprtk.hpp:21099
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12732
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8111
synthesis_node_type_define(const T0 &, const T1 &, e_vov) synthesis_node_type_define(const T0 &
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12246
T nand_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1131
bool unary_optimisable(const details::operator_type &operation) const
Definition: exprtk.hpp:26130
type make_error(const error_mode mode, const lexer::token &tk, const std::string &diagnostic="", const std::string &src_location="")
Definition: exprtk.hpp:18214
details::while_loop_node< T > while_loop_node_t
Definition: exprtk.hpp:18343
bipowninv_node(expression_ptr brnch)
Definition: exprtk.hpp:15380
generic_type::vector_view vector_t
Definition: exprtk.hpp:38263
exprtk::parser< Type > parser_t
Definition: exprtk.hpp:25949
virtual ~ifunction()
Definition: exprtk.hpp:15987
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6085
static T evaluate(const Type x, const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:35953
#define unary_opr_switch_statements
Definition: exprtk.hpp:27257
bool operator==(const expression< T > &e) const
Definition: exprtk.hpp:17938
std::size_t & min_num_args()
Definition: exprtk.hpp:15916
cons_conditional_node(expression_ptr test, expression_ptr consequent)
Definition: exprtk.hpp:6163
static void print(const std::string &scalar_format, const scalar_t &s)
Definition: exprtk.hpp:37269
static bool is_binary(const expression< T > &expr)
Definition: exprtk.hpp:18149
std::multimap< std::string, details::base_operation_t, details::ilesscompare > base_ops_map_t
Definition: exprtk.hpp:18401
bool register_joiner(lexer::token_joiner *joiner)
Definition: exprtk.hpp:3927
bool is_valid_sf_symbol(const std::string &symbol)
Definition: exprtk.hpp:243
static T_ execute(ifunction &f, T_(&v)[10])
Definition: exprtk.hpp:11347
const generator_t & lexer() const
Definition: exprtk.hpp:4081
bool forward(const std::string &name, const std::size_t &arg_count, symbol_table_t &sym_table, const bool ret_present=false)
Definition: exprtk.hpp:36855
const std::string cntrl_struct_list[]
Definition: exprtk.hpp:471
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14506
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12117
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
Definition: exprtk.hpp:14342
switch_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:6712
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38024
vector_holder_ptr vec_node
Definition: exprtk.hpp:18513
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12916
std::string value
Definition: exprtk.hpp:2194
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29938
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37729
T0oT1< T, T0, T1 > node_type
Definition: exprtk.hpp:13838
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33276
bool init(const std::string &str)
Definition: exprtk.hpp:4062
std::pair< bool, std::size_t > n1_c
Definition: exprtk.hpp:7063
const type_store & front() const
Definition: exprtk.hpp:4308
std::map< operator_t, unary_functor_t > unary_op_map_t
Definition: exprtk.hpp:18393
void add_invalid_set1(lexer::token::token_type t)
Definition: exprtk.hpp:3730
expression_node_ptr parse_uninitialised_var_statement(const std::string &var_name)
Definition: exprtk.hpp:24819
static T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36049
T and_opr(const T v0, const T v1)
Definition: exprtk.hpp:1495
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38211
uvouv_node(const T &var0, const T &var1, ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
Definition: exprtk.hpp:13468
int exponent(SIPrefix prefix)
Returns the exponent that corresponds to a given prefix.
Definition: util.cpp:68
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38025
bool is_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:17566
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7226
generic_function_node< T, GenericFunction > gen_function_t
Definition: exprtk.hpp:11807
static T_ execute(ifunction &f, T_(&v)[5])
Definition: exprtk.hpp:11382
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5956
settings_store & disable_base_function(settings_base_funcs bf)
Definition: exprtk.hpp:19782
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7448
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12296
details::switch_node< T > switch_node_t
Definition: exprtk.hpp:18351
null_eq_node(expression_ptr brnch, const bool equality=true)
Definition: exprtk.hpp:5579
#define register_binary_op(Op, BinaryFunctor)
bool is_false(const expression_node< T > *node)
Definition: exprtk.hpp:5108
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32716
static void execute(std::pair< expression_node< T > *, bool >(&branch)[N])
Definition: exprtk.hpp:5870
void register_local_data(void *data, const std::size_t &size=0, const std::size_t data_mode=0)
Definition: exprtk.hpp:18069
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10257
std::string to_str(const details::operator_type &operation) const
Definition: exprtk.hpp:26272
#define parse_digit_2(d)
expression_node_ptr const_optimise_sf3(const details::operator_type &operation, expression_node_ptr(&branch)[3])
Definition: exprtk.hpp:27347
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9600
type_view< T > vector_view
Definition: exprtk.hpp:4378
details::rebasevector_elem_node< T > rebasevector_elem_node_t
Definition: exprtk.hpp:18354
static const std::size_t arithmetic_ops_list_size
Definition: exprtk.hpp:483
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33435
expression_node_ptr synthesize_expression(const details::operator_type &operation, expression_node_ptr(&branch)[N])
Definition: exprtk.hpp:35011
static const double sqrt2
Definition: exprtk.hpp:760
for_loop_bc_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body)
Definition: exprtk.hpp:6603
T xor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1167
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38758
details::string_literal_node< T > string_literal_node_t
Definition: exprtk.hpp:18360
static T_ execute(ifunction &f, T_(&v)[4])
Definition: exprtk.hpp:11389
bool sf4_optimisable(const std::string &sf4id, quaternary_functor_t &qfunc) const
Definition: exprtk.hpp:26166
std::map< std::string, base_func * > funcparam_t
Definition: exprtk.hpp:36487
T tanh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1356
static control_block * create(const std::size_t &dsize, data_t data_ptr=data_t(0), bool dstrct=false)
Definition: exprtk.hpp:4701
expression_node_ptr string_function_call(igeneric_function_t *gf, std::vector< expression_node_ptr > &arg_list, const std::size_t &param_seq_index=std::numeric_limits< std::size_t >::max())
Definition: exprtk.hpp:27819
T shl_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1091
std::string entity_name(const PtrType &ptr) const
Definition: exprtk.hpp:16378
static T evaluate(const Type x, const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:35966
vector_assignment_node(T *vector_base, const std::size_t &size, const std::vector< expression_ptr > &initialiser_list, const bool single_value_initialse)
Definition: exprtk.hpp:7363
#define exprtk_define_freefunction(NN)
Definition: exprtk.hpp:17229
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13189
generic_type::string_view string_t
Definition: exprtk.hpp:37675
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6192
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8113
bool is_negate_node(const expression_node< T > *node)
Definition: exprtk.hpp:5242
T and_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1119
symbol_table< T > & operator=(const symbol_table< T > &st)
Definition: exprtk.hpp:16865
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32655
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8362
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14798
expression_generator< T > expression_generator_
Definition: exprtk.hpp:35380
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:17035
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15236
exprtk::expression< T > expression_t
Definition: exprtk.hpp:36175
settings_store & enable_base_function(settings_base_funcs bf)
Definition: exprtk.hpp:19860
Mac OS X or Android For some we provide binary for others we provide installers and for others we provide AppImage containers that you can run without the need to install anything Check the the usual way to install PulseView is to install the packages provided by your distro s package manager sometimes only outdated packages are made available to you In that you have two options
Definition: installation.txt:2
settings_store & disable_control_structure(settings_control_structs ctrl_struct)
Definition: exprtk.hpp:19795
static void destroy(control_block *&cntrl_blck)
Definition: exprtk.hpp:17865
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6046
generic_function_ptr get_generic_function(const std::string &function_name) const
Definition: exprtk.hpp:18913
void print_type(const std::string &fmt, const T v, exprtk::details::numeric::details::real_type_tag)
Definition: exprtk.hpp:37230
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9378
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12444
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:14718
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32596
details::cons_conditional_str_node< T > cons_conditional_str_node_t
Definition: exprtk.hpp:18368
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15328
bool cardinal_pow_optimisable(const details::operator_type &operation, const T &c) const
Definition: exprtk.hpp:28596
const T & cref_t
Definition: exprtk.hpp:18327
m
Definition: CMakeCache.txt:621
void update(const T &v0, const T &v1, const T &v2, const T &v3, const T &v4)
Definition: exprtk.hpp:36317
virtual bool process(const std::string &, symbol_table_t &, std::string &)
Definition: exprtk.hpp:19269
static const double pi_180
Definition: exprtk.hpp:755
std::pair< std::size_t, std::size_t > cached_range_t
Definition: exprtk.hpp:6945
static const expression_node< T >::node_type result
Definition: exprtk.hpp:13780
static bool process(parameter_list_t &parameters, std::size_t &r0, std::size_t &r1, const std::size_t &r0_prmidx, const std::size_t &r1_prmidx, const std::size_t vec_idx=0)
Definition: exprtk.hpp:37891
#define igeneric_function_empty_body(N)
Definition: exprtk.hpp:16112
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31153
virtual bool process(const std::string &unknown_symbol, symbol_table_t &symbol_table, std::string &)
Definition: exprtk.hpp:35434
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12233
std::size_t size() const
Definition: exprtk.hpp:7726
static T process(const T &, const T &)
Definition: exprtk.hpp:12337
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38572
details::conditional_string_node< T > conditional_string_node_t
Definition: exprtk.hpp:18367
assignment_vec_elem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9640
static details::operator_type operation()
Definition: exprtk.hpp:12307
operator_type operation_
Definition: exprtk.hpp:5816
bool remove_vector(const std::string &vector_name)
Definition: exprtk.hpp:17408
functor_t::bfunc_t binary_functor_t
Definition: exprtk.hpp:9123
bool run_joiners(lexer::generator &g)
Definition: exprtk.hpp:3977
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37885
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11968
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12285
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38163
expression_node_ptr const_optimise_mswitch(Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27078
static void execute(T_(&v)[4], const branch_t(&b)[4])
Definition: exprtk.hpp:11232
#define register_sf4(Op)
for_loop_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body)
Definition: exprtk.hpp:6392
virtual range_t & range_ref()=0
bool operation_optimisable(const details::operator_type &operation) const
Definition: exprtk.hpp:26298
bool uvouv_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26443
cons_conditional_str_node(expression_ptr test, expression_ptr consequent)
Definition: exprtk.hpp:8865
const T & v() const
Definition: exprtk.hpp:14616
expression_node_ptr while_loop(expression_node_ptr &condition, expression_node_ptr &branch, const bool brkcont=false) const
Definition: exprtk.hpp:26915
const T1 const T2 const T3
Definition: exprtk.hpp:13813
const value_t * end() const
Definition: exprtk.hpp:4364
expression_node< typename node_type::value_type > * allocate_c(const T1 &t1) const
Definition: exprtk.hpp:15609
binary_op_map_t binary_op_map_
Definition: exprtk.hpp:35393
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6062
std::size_t get_stringvar_list(Sequence< std::pair< std::string, std::string >, Allocator > &svlist) const
Definition: exprtk.hpp:17471
static details::operator_type operation()
Definition: exprtk.hpp:12204
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14737
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38860
details::vector_holder< T > vector_holder_t
Definition: exprtk.hpp:16725
const vds_t & vds() const
Definition: exprtk.hpp:7170
settings_store & enable_control_structure(settings_control_structs ctrl_struct)
Definition: exprtk.hpp:19878
stringvar_t * stringvar_ptr
Definition: exprtk.hpp:16729
static const std::size_t logic_ops_list_size
Definition: exprtk.hpp:469
details::rebasevector_celem_node< T > rebasevector_celem_node_t
Definition: exprtk.hpp:18355
swap_node(variable_node_ptr var0, variable_node_ptr var1)
Definition: exprtk.hpp:7437
T logn(const T v0, const T v1)
Definition: exprtk.hpp:1446
bool valid(const std::string &name, const std::size_t &arg_count) const
Definition: exprtk.hpp:36842
std::map< operator_t, binary_functor_t > binary_op_map_t
Definition: exprtk.hpp:18394
type_view(type_store_t &ts)
Definition: exprtk.hpp:4336
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6249
ldl
Definition: CMakeCache.txt:618
std::vector< std::string > split_param_seq(const std::string &param_seq, const details::char_t delimiter= '|') const
Definition: exprtk.hpp:23568
void remove_last_error()
Definition: exprtk.hpp:35103
bool collect_variables_enabled() const
Definition: exprtk.hpp:19664
bool valid_symbol(const std::string &symbol, const bool check_reserved_symb=true) const
Definition: exprtk.hpp:17690
generic_type::vector_view vector_t
Definition: exprtk.hpp:38664
static const std::size_t base_function_list_size
Definition: exprtk.hpp:462
std::string branch_to_id(expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26361
void lodge_assignment(symbol_type cst, expression_node_ptr node)
Definition: exprtk.hpp:28022
bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
Definition: exprtk.hpp:3749
details::functor_t< T > functor_t
Definition: exprtk.hpp:13464
parser_error::type get_error(const std::size_t &index) const
Definition: exprtk.hpp:20429
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30001
scalar_view(const type_store_t &ts)
Definition: exprtk.hpp:4390
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38660
bool is_error() const
Definition: exprtk.hpp:2182
bool is_t0ot1ot2_node(const expression_node< T > *node)
Definition: exprtk.hpp:15439
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34000
expression_node< typename node_type::value_type > * allocate(T1 &t1) const
Definition: exprtk.hpp:15603
void copy(const var_t &src_v, varref_t &dest_v)
Definition: exprtk.hpp:36419
details::scor_node< T > scor_node_t
Definition: exprtk.hpp:18377
static const std::size_t cntrl_struct_list_size
Definition: exprtk.hpp:476
static T_ execute(ifunction &f, T_(&v)[1])
Definition: exprtk.hpp:11410
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11139
type_store< ifunction< T >, ifunction< T > > function_store
Definition: exprtk.hpp:16749
operator_type operation() const
Definition: exprtk.hpp:13852
expression_node_ptr parse_expression(precedence_level precedence=e_level00)
Definition: exprtk.hpp:20690
expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:5987
expression_t compile(const std::string &expression_string, symbol_table_t &symtab)
Definition: exprtk.hpp:20269
settings_store & enable_all_control_structures()
Definition: exprtk.hpp:19561
type_ptr get_from_varptr(const void *ptr) const
Definition: exprtk.hpp:16577
bool add_vector(const std::string &vector_name, T *v, const std::size_t &v_size)
Definition: exprtk.hpp:17331
T(* tfunc_t)(Type t0, Type t1, Type t2)
Definition: exprtk.hpp:2017
T0oT1< T, T0, T1 > & operator=(T0oT1< T, T0, T1 > &)
Definition: exprtk.hpp:13890
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12244
expression_node_ptr synthesize_srocsr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34577
details::T0oT1oT2_define< T, cref_t, const_t, cref_t > vocov_t
Definition: exprtk.hpp:18410
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12190
std::string remaining() const
Definition: exprtk.hpp:2334
settings_store & enable_logic_operation(settings_logic_opr logic)
Definition: exprtk.hpp:19896
expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28343
T(* bfunc_t)(Type t0, Type t1)
Definition: exprtk.hpp:2018
static const expression_node< T >::node_type result
Definition: exprtk.hpp:13758
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31307
static bool compile(expression_generator< Type > &expr_gen, const std::string &id, T0 t0, T1 t1, T2 t2, T3 t3, expression_node_ptr &result)
Definition: exprtk.hpp:29788
bool is_digit(const char_t c)
Definition: exprtk.hpp:124
lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_
Definition: exprtk.hpp:35409
T max(const T v0, const T v1)
Definition: exprtk.hpp:1411
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14199
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32896
void init_precompilation()
Definition: exprtk.hpp:20109
virtual int insert(const token &, token &) token_inserter_empty_body inline virtual int insert(const token &
bool is_whitespace(const char_t c)
Definition: exprtk.hpp:95
bool valid_vararg_operation(const std::string &symbol) const
Definition: exprtk.hpp:20514
std::size_t size() const
Definition: exprtk.hpp:7646
static T_ execute(ifunction &f, T_(&v)[14])
Definition: exprtk.hpp:11319
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33016
bool run_inserters(lexer::generator &g)
Definition: exprtk.hpp:3999
generic_type::vector_view vector_t
Definition: exprtk.hpp:38311
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7155
void destroy_node(expression_node< T > *&node)
Definition: exprtk.hpp:5353
details::variable_node< T > variable_node_t
Definition: exprtk.hpp:16342
expression_node_ptr synthesize_csrocs_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34667
details::functor_t< T > functor_t
Definition: exprtk.hpp:9120
virtual void set_c(const T)=0
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12353
settings_store & settings()
Definition: exprtk.hpp:20424
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5) const
Definition: exprtk.hpp:15704
static std::string to_str(token_type t)
Definition: exprtk.hpp:2135
expression_node_ptr parse_symbol()
Definition: exprtk.hpp:25650
igeneric_function< T > igeneric_function_t
Definition: exprtk.hpp:18334
bool voc_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26375
bool remove_variable(const std::string &variable_name, const bool delete_node=true)
Definition: exprtk.hpp:17374
static std::string id()
Definition: exprtk.hpp:14057
libsigrok allows users to import and export data from files in various formats some of them as generic as others very specific For a list and make sure to check not so common and outright exotic ways to represent data and sigrok tries to suit as many needs as it can To see which formats your version of PulseView just click on the small arrow next to the _Open_ PulseView will ask for the file name to open Once you picked the file
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6805
operator_type operation() const
Definition: exprtk.hpp:5799
str_vararg_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:8984
details::expression_node< T > * expression_ptr
Definition: exprtk.hpp:17767
#define empty_method_body
Definition: exprtk.hpp:15990
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12203
static void process(std::pair< expression_node< T > *, bool >(&)[N], expression_node< T > *)
Definition: exprtk.hpp:5825
symbol_table_t::stringvar_ptr stringvar_ptr
Definition: exprtk.hpp:18763
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12338
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9638
assignment_rebasevec_celem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10135
void lodge_symbol(const std::string &symbol, const symbol_type st)
Definition: exprtk.hpp:23079
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:14773
generic_type::vector_view vector_t
Definition: exprtk.hpp:38762
symbol_table< T > symbol_table_t
Definition: exprtk.hpp:18381
bool return_invoked() const
Definition: exprtk.hpp:18011
const std::string & ref() const
Definition: exprtk.hpp:7656
settings_store & enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
Definition: exprtk.hpp:19914
bool register_package(exprtk::symbol_table< T > &symtab)
Definition: exprtk.hpp:38970
data_pack(void *ptr, const data_type dt, const std::size_t sz=0)
Definition: exprtk.hpp:17791
bool is_letter(const char_t c)
Definition: exprtk.hpp:118
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) const
Definition: exprtk.hpp:15695
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12544
details::T0oT1oT2oT3_define< T, const_t, cref_t, cref_t, const_t > covovoc_t
Definition: exprtk.hpp:18424
details(const std::size_t &vsize, const unsigned int loop_batch_size=global_loop_batch_size)
Definition: exprtk.hpp:4629
bool create_stringvar(const std::string &stringvar_name, const std::string &value=std::string(""))
Definition: exprtk.hpp:17111
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32452
std::vector< lvarref_t > lvr_vec_t
Definition: exprtk.hpp:36280
generic_type::vector_view vector_t
Definition: exprtk.hpp:38165
parser_t::unknown_symbol_resolver usr_t
Definition: exprtk.hpp:35424
local_data_t & local_data()
Definition: exprtk.hpp:17744
opr_base< T >::Type Type
Definition: exprtk.hpp:12346
_int64_t to_int64_impl(const T v, real_type_tag)
Definition: exprtk.hpp:850
bool is_string_ccondition_node(const expression_node< T > *node)
Definition: exprtk.hpp:15505
std::size_t position
Definition: exprtk.hpp:2195
static T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36039
expression_node_ptr parse_special_function()
Definition: exprtk.hpp:24080
vov_node(const T &var0, const T &var1)
Definition: exprtk.hpp:14496
details::expression_node< T > * expression_ptr
Definition: exprtk.hpp:16341
bool symbol_exists(const std::string &symbol_name) const
Definition: exprtk.hpp:16367
std::size_t size
Definition: exprtk.hpp:4272
bool is_right_bracket(const char_t c)
Definition: exprtk.hpp:139
bool is_reserved_word(const std::string &symbol)
Definition: exprtk.hpp:502
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12666
std::size_t size() const
Definition: exprtk.hpp:8161
bool finished() const
Definition: exprtk.hpp:2307
T integrate(const expression< T > &e, T &x, const T &r0, const T &r1, const std::size_t number_of_intervals=1000000)
Definition: exprtk.hpp:35616
scoped_delete(parser< T > &pr, ptr_t(&p)[N])
Definition: exprtk.hpp:21014
static details::operator_type operation()
Definition: exprtk.hpp:12329
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12327
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33555
void set_expression(const expression_ptr expr)
Definition: exprtk.hpp:18023
virtual T value() const
Definition: exprtk.hpp:5061
igeneric_function< T > igeneric_function_t
Definition: exprtk.hpp:16345
bool collect_functions_enabled() const
Definition: exprtk.hpp:19665
int insert(const lexer::token &t0, const lexer::token &t1, lexer::token &new_token)
Definition: exprtk.hpp:3205
std::pair< void *, std::size_t > void_t
Definition: exprtk.hpp:11538
bool is_letter_or_digit(const char_t c)
Definition: exprtk.hpp:129
static expression_node_ptr process(parser< Type > &p, const details::operator_type opt_type, const std::string &sf_name)
Definition: exprtk.hpp:24016
bool add_replace(const std::string &target_symbol, const std::string &replace_symbol, const lexer::token::token_type token_type=lexer::token::e_symbol)
Definition: exprtk.hpp:3593
ivararg_function< T > ivararg_function_t
Definition: exprtk.hpp:16344
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6161
value_ptr data() const
Definition: exprtk.hpp:5535
details::stringvar_node< T > stringvar_node_t
Definition: exprtk.hpp:18359
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12495
vector_holder< T > vector_holder_t
Definition: exprtk.hpp:7193
std::vector< branch_t > branch_
Definition: exprtk.hpp:11710
T g2d_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1323
expression_node_ptr parse_function_call(ifunction< T > *function, const std::string &function_name)
Definition: exprtk.hpp:21187
T0oT1oT2oT3_sf4ext< T, T0, T1, T2, T3, SF4Operation > node_type
Definition: exprtk.hpp:14369
expression_node_ptr synthesize_sos_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34466
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9085
virtual ~polynomial()
Definition: exprtk.hpp:36086
_int64_t to_int64(const T v)
Definition: exprtk.hpp:1390
static std::string null_value
Definition: exprtk.hpp:7608
T d2r_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1321
bool is_string_operation(const details::operator_type &operation, expression_node_ptr(&branch)[3]) const
Definition: exprtk.hpp:26576
#define exprtk_loop(N)
expression_node_ptr parse_vector()
Definition: exprtk.hpp:23249
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7497
generic_function_ptr get_overload_function(const std::string &function_name) const
Definition: exprtk.hpp:18955
std::pair< bool, expression_node_ptr > n1_e
Definition: exprtk.hpp:7061
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9870
bool is_integer(const T v)
Definition: exprtk.hpp:1537
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
Definition: exprtk.hpp:13968
virtual expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:5066
static std::string data()
Definition: exprtk.hpp:39024
expression_node_ptr special_function(const details::operator_type &operation, expression_node_ptr(&branch)[4])
Definition: exprtk.hpp:27520
std::vector< std::string > retparam_list_t
Definition: exprtk.hpp:19394
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:5957
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38477
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38420
#define register_sf3(Op)
repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
Definition: exprtk.hpp:6339
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38307
token_t & operator[](const std::size_t &index)
Definition: exprtk.hpp:2291
static T_ execute(ifunction &f, T_(&v)[20])
Definition: exprtk.hpp:11277
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14973
operator_type operation() const
Definition: exprtk.hpp:15004
void enable_unknown_symbol_resolver(unknown_symbol_resolver &usr)
Definition: exprtk.hpp:20487
T nor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1155
base_func(const std::size_t &pc=0)
Definition: exprtk.hpp:36284
expression_node_ptr const_optimise_switch(Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27042
void start()
Definition: exprtk.hpp:37168
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14492
bfunc_t f() const
Definition: exprtk.hpp:13872
opr_base< T >::Type Type
Definition: exprtk.hpp:12253
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12402
vector_view< T > make_vector_view(T *data, const std::size_t size, const std::size_t offset=0)
Definition: exprtk.hpp:4234
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7949
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29088
static bool test(const PtrType, const void *)
Definition: exprtk.hpp:16561
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37241
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12107
expression_node_ptr repeat_until_loop(expression_node_ptr &condition, expression_node_ptr &branch, const bool brkcont=false) const
Definition: exprtk.hpp:26949
vector_node_ptr vec() const
Definition: exprtk.hpp:10895
static T_ execute(ifunction &f, T_(&v)[3])
Definition: exprtk.hpp:11396
disabled_entity_set_t disabled_inequality_set_
Definition: exprtk.hpp:20064
ivararg_function< T > VAF
Definition: exprtk.hpp:18330
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37788
expression_node_ptr varnode_optimise_sf3(const details::operator_type &operation, expression_node_ptr(&branch)[3])
Definition: exprtk.hpp:27383
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12849
void set_ref(data_ptr_t *data_ref)
Definition: exprtk.hpp:4221
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:18444
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12305
#define exprtk_register_real_type_tag(T)
Definition: exprtk.hpp:777
uchar_t const * uchar_cptr
Definition: exprtk.hpp:90
bool boc_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26402
const std::string arithmetic_ops_list[]
Definition: exprtk.hpp:478
std::string get_conststr_stringvar_name(const expression_node_ptr &ptr) const
Definition: exprtk.hpp:19166
std::deque< parser_error::type > error_list_
Definition: exprtk.hpp:35384
bool is_reserved_symbol(const std::string &symbol)
Definition: exprtk.hpp:515
#define base_opr_case(N)
details::functor_t< T > functor_t
Definition: exprtk.hpp:14188
static T_ execute(ifunction &f, T_(&v)[6])
Definition: exprtk.hpp:11375
assignment_vec_elem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10061
bool is_true(const double v)
Definition: exprtk.hpp:5080
unsigned char uchar_t
Definition: exprtk.hpp:86
operator_type operation() const
Definition: exprtk.hpp:15200
std::vector< lexer::token_inserter * > token_inserter_list
Definition: exprtk.hpp:4046
static void execute(T_(&v)[2], const branch_t(&b)[2])
Definition: exprtk.hpp:11255
bool is_vararg_function(const std::string &vararg_function_name) const
Definition: exprtk.hpp:19118
unknown_symbol_resolver default_usr_
Definition: exprtk.hpp:35390
const range_t & range_ref() const
Definition: exprtk.hpp:8539
void update(const T &v0, const T &v1, const T &v2)
Definition: exprtk.hpp:36305
details::scand_node< T > scand_node_t
Definition: exprtk.hpp:18376
vector_holder_ptr get_vector(const std::string &vector_name) const
Definition: exprtk.hpp:17037
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33577
bool run_assemblies()
Definition: exprtk.hpp:20317
details::assignment_vec_elem_node< T > assignment_vec_elem_node_t
Definition: exprtk.hpp:18371
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12275
vector_holder_t * vector_holder_ptr
Definition: exprtk.hpp:7194
bool logic_disabled(const details::operator_type logic_operation) const
Definition: exprtk.hpp:19755
vector_node_ptr vec()
Definition: exprtk.hpp:7150
sf4_map_t sf4_map_
Definition: exprtk.hpp:35396
generic_string_range_node(expression_ptr str_branch, const range_t &brange)
Definition: exprtk.hpp:7852
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[1])
Definition: exprtk.hpp:15552
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32216
static details::operator_type operation()
Definition: exprtk.hpp:12267
T shr_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1079
void activate_side_effect(const std::string &)
Definition: exprtk.hpp:19206
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38518
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38363
expression_node< T > * branch(const std::size_t &index=0) const
Definition: exprtk.hpp:5935
precedence_level left
Definition: exprtk.hpp:20685
const value_t * begin() const
Definition: exprtk.hpp:4361
virtual bool side_effect() const
Definition: exprtk.hpp:7114
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12895
bool wc_match(const std::string &wild_card, const std::string &str)
Definition: exprtk.hpp:645
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32332
bool add_variable(const std::string &variable_name, T &t, const bool is_constant=false)
Definition: exprtk.hpp:17127
virtual const T & v0() const =0
expression_node_ptr parse_for_loop()
Definition: exprtk.hpp:22097
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7973
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12212
expression_node_ptr vararg_function_call(ivararg_function_t *vaf, std::vector< expression_node_ptr > &arg_list)
Definition: exprtk.hpp:27734
bool operator!() const
Definition: exprtk.hpp:17943
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:14799
virtual std::size_t size() const =0
operator_type operation() const
Definition: exprtk.hpp:14109
operator_type operation() const
Definition: exprtk.hpp:14384
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6226
T r2d_impl(const T v, real_type_tag)
Definition: exprtk.hpp:1320
const symbol_table< T > & get_symbol_table(const std::size_t &index=0) const
Definition: exprtk.hpp:17988
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13178
bool add_reserved_function(const std::string &vararg_function_name, vararg_function_t &vararg_function)
Definition: exprtk.hpp:17269
virtual const T c() const =0
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31417
token_t & next_token()
Definition: exprtk.hpp:2271
lexer::helper::sequence_validator sequence_validator_
Definition: exprtk.hpp:35408
bool is_constant_foldable(NodePtr(&b)[N]) const
Definition: exprtk.hpp:27993
static T execute(ifunction &, branch_t(&)[ParamCount])
Definition: exprtk.hpp:11272
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[3])
Definition: exprtk.hpp:15564
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30687
bool is_constant(const std::string &symbol_name) const
Definition: exprtk.hpp:16398
trinary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2)
Definition: exprtk.hpp:6010
details::T0oT1oT2_define< T, const_t, cref_t, const_t > covoc_t
Definition: exprtk.hpp:18412
lexer::token_inserter * error_token_inserter
Definition: exprtk.hpp:4051
opr_base< T >::Type Type
Definition: exprtk.hpp:12562
void register_local_var(vector_holder_ptr vec_holder)
Definition: exprtk.hpp:18054
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11953
std::string type_id() const
Definition: exprtk.hpp:14331
#define def_fp_retval(N)
Definition: exprtk.hpp:36620
details::node_allocator * node_allocator_
Definition: exprtk.hpp:35088
assignment_vecvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9874
data_ptr_t data() const
Definition: exprtk.hpp:4201
bool replace_symbol(const std::string &old_symbol, const std::string &new_symbol)
Definition: exprtk.hpp:20457
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7339
bool string_to_type_converter_impl_ref(Iterator &itr, const Iterator end, T &result)
Definition: exprtk.hpp:1693
static bool cmp(const char_t c0, const char_t c1)
Definition: exprtk.hpp:577
bool branch_deletable(expression_node< T > *node)
Definition: exprtk.hpp:5253
expression_node< typename node_type::value_type > * allocate(const Sequence< Type, Allocator > &seq) const
Definition: exprtk.hpp:15597
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode0 > type0
Definition: exprtk.hpp:14479
bool add_reserved_function(const std::string &function_name, generic_function_t &function)
Definition: exprtk.hpp:17281
static void print(const string_t &s)
Definition: exprtk.hpp:37285
bool peek_token_is(const token_t::token_type &ttype)
Definition: exprtk.hpp:4151
string_size_node(expression_ptr brnch)
Definition: exprtk.hpp:8383
virtual std::string type_id() const =0
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:14668
settings_store & enable_inequality_operation(settings_inequality_opr inequality)
Definition: exprtk.hpp:19950
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8951
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32814
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[5])
Definition: exprtk.hpp:15576
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:9754
const T c() const
Definition: exprtk.hpp:14763
dependent_entity_collector dec_
Definition: exprtk.hpp:35383
details::T0oT1oT2_define< T, const_t, const_t, cref_t > cocov_t
Definition: exprtk.hpp:18413
operator_type operation() const
Definition: exprtk.hpp:13560
details::functor_t< T > functor_t
Definition: exprtk.hpp:14277
generic_type::vector_view vector_t
Definition: exprtk.hpp:38861
void set_error(const parser_error::type &error_type)
Definition: exprtk.hpp:35098
static void execute(T_(&v)[5], const branch_t(&b)[5])
Definition: exprtk.hpp:11219
void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
Definition: exprtk.hpp:3725
file_descriptor(const std::string &fname, const std::string &access)
Definition: exprtk.hpp:37384
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10171
bool is_string_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:15463
type_map_t::const_iterator tm_const_itr_t
Definition: exprtk.hpp:16356
T notl_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1341
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38070
std::vector< unsigned char > delete_branch_
Definition: exprtk.hpp:6877
assignment_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9602
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12428
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33198
generic_type::vector_view vector_t
Definition: exprtk.hpp:37734
bool is_constant_foldable(const Sequence< NodePtr, Allocator > &b) const
Definition: exprtk.hpp:28009
static details::operator_type operation()
Definition: exprtk.hpp:12108
bool is_cob_node(const expression_node< T > *node)
Definition: exprtk.hpp:15427
swap_string_node(expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8119
char_t * char_ptr
Definition: exprtk.hpp:89
expression_node_ptr synthesize_uv_expression(const details::operator_type &operation, expression_node_ptr(&branch)[1])
Definition: exprtk.hpp:27299
std::size_t assignment_symbols(Sequence< symbol_t, Allocator > &assignment_list)
Definition: exprtk.hpp:19339
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8975
details::expression_node< T > * expression_ptr
Definition: exprtk.hpp:16723
lexer::token token_t
Definition: exprtk.hpp:18378
opr_base< T >::Type Type
Definition: exprtk.hpp:12633
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2)
Definition: exprtk.hpp:14241
void parse_pending_string_rangesize(expression_node_ptr &expression)
Definition: exprtk.hpp:22722
control_block(const std::size_t &dsize)
Definition: exprtk.hpp:4677
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10445
virtual const T c() const =0
opr_base< T >::Type Type
Definition: exprtk.hpp:12439
token_inserter(const std::size_t &stride)
Definition: exprtk.hpp:3005
std::map< std::string, std::pair< trinary_functor_t,operator_t > > sf3_map_t
Definition: exprtk.hpp:18397
void clear_local_constants()
Definition: exprtk.hpp:16905
virtual operator_type operation() const
Definition: exprtk.hpp:13374
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11503
bool is_base_function(const std::string &function_name)
Definition: exprtk.hpp:528
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12235
T erfc_impl(T v, int_type_tag)
Definition: exprtk.hpp:1261
const unsigned int global_loop_batch_size
Definition: exprtk.hpp:4622
expression_node_ptr parse_null_statement()
Definition: exprtk.hpp:24125
results_context_t * results_context_
Definition: exprtk.hpp:12014
#define exprtk_disable_fallthrough_begin
Definition: exprtk.hpp:80
void set_bom(binary_op_map_t &binary_op_map)
Definition: exprtk.hpp:26036
expression_ptr branch_
Definition: exprtk.hpp:5817
assignment_string_range_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8573
vec_data_store(const type &vds)
Definition: exprtk.hpp:4763
unary_op_map_t unary_op_map_
Definition: exprtk.hpp:35392
details::T0oT1_define< T, const_t, cref_t > cov_t
Definition: exprtk.hpp:18405
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6390
expression_node_ptr parse_while_loop()
Definition: exprtk.hpp:21859
expression_node_ptr parse_vararg_function_call(ivararg_function< T > *vararg_function, const std::string &vararg_function_name)
Definition: exprtk.hpp:23336
static bool is_variable(const expression< T > &expr)
Definition: exprtk.hpp:18139
generic_function_node< T, igeneric_function_t > gen_function_t
Definition: exprtk.hpp:11926
disabled_entity_set_t disabled_logic_set_
Definition: exprtk.hpp:20061
symbol_table_t::local_data_t local_data_t
Definition: exprtk.hpp:18759
expression_node_ptr synthesize_csocsr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34624
vector_node_ptr vec() const
Definition: exprtk.hpp:10247
vec_binop_vecval_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10634
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12224
bool init_branches(expression_ptr(&b)[NumBranches])
Definition: exprtk.hpp:11154
CMake MinSizeRel FORCE endif() add_subdirectory(manual) include(CheckCSourceCompiles) include(CheckCXXCompilerFlag) include(CheckCXXSourceCompiles) include(CMakePushCheckState) include(memaccess) find_package(PkgConfig) if(CMAKE_VERSION VERSION_EQUAL"3.8.0"OR CMAKE_VERSION VERSION_GREATER"3.8.0") check_cxx_compiler_flag("-std
function_t & setup(expression_t &expr)
Definition: exprtk.hpp:36331
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:14638
details::expression_node< Type > * expression_node_ptr
Definition: exprtk.hpp:25946
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38362
void set_min_num_args(FunctionType &func, const std::size_t &num_args)
Definition: exprtk.hpp:15964
unary_branch_node(expression_ptr brnch)
Definition: exprtk.hpp:13537
#define exprtk_define_unary_function(FunctionName)
Definition: exprtk.hpp:1579
expression_node< typename node_type::value_type > * allocate_tt(T1 t1, T2 t2) const
Definition: exprtk.hpp:15644
value_ptr value_at(const std::size_t &index) const
Definition: exprtk.hpp:5487
expression_node_ptr const_optimise_varargfunc(const details::operator_type &operation, Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27555
expression_node_ptr special_function(const details::operator_type &operation, expression_node_ptr(&branch)[3])
Definition: exprtk.hpp:27415
switch_n_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:6790
std::size_t parse_base_function_call(expression_node_ptr(&param_list)[MaxNumberofParameters], const std::string &function_name="")
Definition: exprtk.hpp:21302
token_joiner(const std::size_t &stride)
Definition: exprtk.hpp:3091
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12143
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) const
Definition: exprtk.hpp:15817
static expression_node_ptr process(expression_generator< Type > &, const details::operator_type &, expression_node_ptr(&)[2])
Definition: exprtk.hpp:30675
vector_node_ptr vec() const
Definition: exprtk.hpp:10740
details::functor_t< T > functor_t
Definition: exprtk.hpp:13992
T sinh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1354
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38116
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12146
static T_ execute(ifunction &f, T_(&v)[13])
Definition: exprtk.hpp:11326
expression_node_ptr parse_base_operation()
Definition: exprtk.hpp:21374
functor_t::ufunc_t ufunc_t
Definition: exprtk.hpp:13466
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12265
RawType & type_ref(const std::string &symbol_name)
Definition: exprtk.hpp:16626
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37674
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38309
sf3_map_t sf3_map_
Definition: exprtk.hpp:35395
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:13465
T min(const T v0, const T v1)
Definition: exprtk.hpp:1404
bool add_function(const std::string &vararg_function_name, vararg_function_t &vararg_function)
Definition: exprtk.hpp:17180
expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type &opr, T0 s0, T1 s1, range_t rp1)
Definition: exprtk.hpp:34416
bool add(const std::string &symbol_name, std::deque< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:16499
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[4])
Definition: exprtk.hpp:15570
bool add(const std::string &symbol_name, T(&v)[v_size], const bool is_const=false)
Definition: exprtk.hpp:16473
virtual operator_type operation() const
Definition: exprtk.hpp:13242
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6337
vector_holder(std::vector< Type, Allocator > &vec)
Definition: exprtk.hpp:5517
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30429
bool is_invalid_string_op(const details::operator_type &operation, expression_node_ptr(&branch)[3]) const
Definition: exprtk.hpp:26547
variable_t * variable_ptr
Definition: exprtk.hpp:16726
expression_node_ptr vectorize_func(const details::operator_type &operation, Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27622
virtual operator_type operation() const
Definition: exprtk.hpp:13388
const range_t & range_ref() const
Definition: exprtk.hpp:5750
std::vector< std::pair< lexer::token, lexer::token > > error_list_
Definition: exprtk.hpp:3809
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38071
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29207
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12709
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33819
bool is_stringvar(const std::string &stringvar_name) const
Definition: exprtk.hpp:17534
exprtk::symbol_table< T > symbol_table_t
Definition: exprtk.hpp:36176
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7250
cob_node(const T const_var, const expression_ptr brnch)
Definition: exprtk.hpp:14742
bool is_constant_string(const std::string &symbol_name) const
Definition: exprtk.hpp:17082
virtual void set_c(const T)=0
bool allow_zero_parameters() const
Definition: exprtk.hpp:23552
details::literal_node< T > literal_node_t
Definition: exprtk.hpp:18336
vector_node_ptr vec() const
Definition: exprtk.hpp:7559
symbol_table_t & get_symbol_table(const std::size_t &index=0)
Definition: exprtk.hpp:19182
exprtk_define_freefunction(00) exprtk_define_freefunction(01) exprtk_define_freefunction(02) exprtk_define_freefunction(03) exprtk_define_freefunction(04) exprtk_define_freefunction(05) exprtk_define_freefunction(06) exprtk_define_freefunction(07) exprtk_define_freefunction(08) exprtk_define_freefunction(09) exprtk_define_freefunction(10) exprtk_define_freefunction(11) exprtk_define_freefunction(12) exprtk_define_freefunction(13) exprtk_define_freefunction(14) exprtk_define_freefunction(15) inline bool add_reserved_function(const std
Definition: exprtk.hpp:17246
details::vector_holder< T > vector_t
Definition: exprtk.hpp:16346
opr_base< T >::Type Type
Definition: exprtk.hpp:12784
T equal(const T v0, const T v1)
Definition: exprtk.hpp:1418
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30049
opr_base< T >::Type Type
Definition: exprtk.hpp:12199
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9503
static void execute(Sequence< std::pair< expression_node< T > *, bool >, Allocator > &branch)
Definition: exprtk.hpp:5884
expression_node< T > * expression_node_ptr
Definition: exprtk.hpp:6944
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37978
type_store & operator[](const std::size_t &index)
Definition: exprtk.hpp:4293
settings_store & enable_all_base_functions()
Definition: exprtk.hpp:19555
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37318
static expression_node_ptr process(expression_generator< Type > &, const details::operator_type &, expression_node_ptr(&)[2])
Definition: exprtk.hpp:33253
conditional_node(expression_ptr test, expression_ptr consequent, expression_ptr alternative)
Definition: exprtk.hpp:6103
generic_type::vector_view vector_t
Definition: exprtk.hpp:38522
const vds_t & vds() const
Definition: exprtk.hpp:9853
#define parse_digit_1(d)
value_ptr operator[](const std::size_t &index) const
Definition: exprtk.hpp:5525
virtual operator_type operation() const
Definition: exprtk.hpp:13338
bool register_inserter(lexer::token_inserter *inserter)
Definition: exprtk.hpp:3941
details::functor_t< T > functor_t
Definition: exprtk.hpp:14091
virtual const T c() const =0
details::trinary_node< T > trinary_node_t
Definition: exprtk.hpp:18339
bool all_nodes_valid(expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5260
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33176
vector_holder_ptr get_vector(const std::string &vector_name) const
Definition: exprtk.hpp:18976
results_context_t * results_context_
Definition: exprtk.hpp:11960
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32836
std::string type_id() const
Definition: exprtk.hpp:14414
voc_node(const T &var, const T &const_var)
Definition: exprtk.hpp:14596
const e_voc T1 e_none const e_none T1 e_none T0
Definition: exprtk.hpp:13779
std::size_t get_list(Sequence< std::pair< std::string, RawType >, Allocator > &list) const
Definition: exprtk.hpp:16680
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31610
vector_node_ptr vec() const
Definition: exprtk.hpp:7145
std::vector< unsigned char > delete_branch_
Definition: exprtk.hpp:9098
#define vector_ops
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12511
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15195
expression_node_ptr synthesize_srosr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34513
bool vob_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26452
generic_function_ptr get_overload_function(const std::string &function_name) const
Definition: exprtk.hpp:17025
bool join(const lexer::token &t0, const lexer::token &t1, const lexer::token &t2, lexer::token &t)
Definition: exprtk.hpp:3405
details::range_pack< T > range_t
Definition: exprtk.hpp:18357
T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
Definition: exprtk.hpp:14002
static bool collection_pass(const std::string &expression_string, std::set< std::string > &symbol_set, const bool collect_variables, const bool collect_functions, const bool vector_pass, symbol_table_t &ext_symbol_table)
Definition: exprtk.hpp:35444
bool sequence_check_enabled() const
Definition: exprtk.hpp:19662
expression_node< T >::node_type type() const
Definition: exprtk.hpp:13482
generic_function_ptr get_generic_function(const std::string &function_name) const
Definition: exprtk.hpp:17005
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6583
bool verify(const std::string &param_seq, std::size_t &pseq_index)
Definition: exprtk.hpp:23470
vararg_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:9450
bool is_vector(const std::string &vector_name) const
Definition: exprtk.hpp:19134
functor_t::tfunc_t trinary_functor_t
Definition: exprtk.hpp:9122
exprtk::expression< T > expression_t
Definition: exprtk.hpp:35421
const range_t & range_ref() const
Definition: exprtk.hpp:8946
void set_sf4m(sf4_map_t &sf4_map)
Definition: exprtk.hpp:26051
std::vector< const T * > arg_list_
Definition: exprtk.hpp:9541
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12213
expression_node_ptr parse_function_invocation(ifunction< T > *function, const std::string &function_name)
Definition: exprtk.hpp:21134
println(const std::string &scalar_format="%10.5f")
Definition: exprtk.hpp:37322
std::size_t get_vector_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:17492
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:6063
std::size_t vector_count() const
Definition: exprtk.hpp:16946
parser_helper prsrhlpr_t
Definition: exprtk.hpp:18429
scor_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11116
function & var(const std::string &v)
Definition: exprtk.hpp:36260
void advance_token(const token_advance_mode mode)
Definition: exprtk.hpp:4114
std::vector< data_pack > local_data_list_t
Definition: exprtk.hpp:17802
std::vector< type_store_t > ts_list_t
Definition: exprtk.hpp:4482
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9425
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38905
T erf_impl(T v, int_type_tag)
Definition: exprtk.hpp:1235
str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
Definition: exprtk.hpp:14977
T acos_impl(const T, int_type_tag)
Definition: exprtk.hpp:1345
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12328
bool is_invalid_string_op(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26527
assignment_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10024
expression_node_ptr parse_string_function_call(igeneric_function< T > *function, const std::string &function_name)
Definition: exprtk.hpp:23889
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37601
T nor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1516
scand_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:11092
static T process_6(const Sequence &arg_list)
Definition: exprtk.hpp:12935
while_loop_node(expression_ptr condition, expression_ptr loop_body)
Definition: exprtk.hpp:6287
virtual std::size_t size() const =0
details::generic_string_range_node< T > generic_string_range_node_t
Definition: exprtk.hpp:18363
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12181
expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28601
expression_node_ptr simplify(Sequence< expression_node_ptr, Allocator1 > &expression_list, Sequence< bool, Allocator2 > &side_effect_list, const bool specialise_on_final_type=false)
Definition: exprtk.hpp:22745
opr_base< T >::Type Type
Definition: exprtk.hpp:12127
details::assignment_string_range_node< T > assignment_string_range_node_t
Definition: exprtk.hpp:18366
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:7974
details::vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:17768
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12678
std::string & s0()
Definition: exprtk.hpp:14884
static T process(const T &t0, const T &t1, const T &t2)
Definition: exprtk.hpp:12348
bool add_constant(const std::string &constant_name, const T &value)
Definition: exprtk.hpp:17139
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38164
expression< T > & operator=(const expression< T > &e)
Definition: exprtk.hpp:17913
details::T0oT1oT2oT3_define< T, const_t, cref_t, cref_t, cref_t > covovov_t
Definition: exprtk.hpp:18420
bool is_null_present(expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26600
bool local_variable_is_shadowed(const std::string &symbol)
Definition: exprtk.hpp:24630
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6708
bool special_one_parameter_vararg(const details::operator_type &operation) const
Definition: exprtk.hpp:27586
control_block * control_block_
Definition: exprtk.hpp:17754
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12488
static T_ execute(ifunction &f, T_(&v)[17])
Definition: exprtk.hpp:11298
virtual std::string & ref()
Definition: exprtk.hpp:7736
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38421
T root(const T v0, const T v1)
Definition: exprtk.hpp:1453
expression_node_ptr parse_vararg_function()
Definition: exprtk.hpp:22589
settings_store & enable_all_arithmetic_ops()
Definition: exprtk.hpp:19573
bool synthesize_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2], expression_node_ptr &result)
Definition: exprtk.hpp:29567
literal_node(literal_node< T > &)
Definition: exprtk.hpp:5652
type_store< T > generic_type
Definition: exprtk.hpp:11909
opr_base< T >::Type Type
Definition: exprtk.hpp:12293
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7479
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14290
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12223
expression_node_ptr parse_overload_function_call(igeneric_function< T > *function, const std::string &function_name)
Definition: exprtk.hpp:23941
static T process(const ivector_ptr v)
Definition: exprtk.hpp:12976
bool assignment_enabled(const details::operator_type &assignment) const
Definition: exprtk.hpp:19704
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30662
T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
Definition: exprtk.hpp:14282
static T evaluate(const Type x, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36003
expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28129
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5770
details::functor_t< T > functor_t
Definition: exprtk.hpp:13647
operator_type operation() const
Definition: exprtk.hpp:14511
expression_ptr return_
Definition: exprtk.hpp:6256
pv::util::Timestamp ts
Definition: util.cpp:26
virtual operator_type operation() const
Definition: exprtk.hpp:13358
lexer::helper::commutative_inserter commutative_inserter_
Definition: exprtk.hpp:35402
symbol_table_t & symbol_table()
Definition: exprtk.hpp:36696
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32046
std::set< std::string > reserved_symbol_table_
Definition: exprtk.hpp:16795
bool strength_reduction_enabled() const
Definition: exprtk.hpp:19663
bool run_scanners(lexer::generator &g)
Definition: exprtk.hpp:4021
void load_inv_binary_operations_map(inv_binary_op_map_t &m)
Definition: exprtk.hpp:35259
T value() const
Definition: exprtk.hpp:17963
bool to_uint(UIntType &u) const
Definition: exprtk.hpp:4416
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6786
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:37676
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12170
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12869
generic_type::vector_view vector_t
Definition: exprtk.hpp:38073
#define exprtk_process_digit
expression_node_ptr synthesize_csocs_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34593
functor_t::tfunc_t tfunc_t
Definition: exprtk.hpp:14189
symbol_table< T > & get_symbol_table(const std::size_t &index=0)
Definition: exprtk.hpp:17993
lexer::helper::symbol_replacer symbol_replacer_
Definition: exprtk.hpp:35405
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37933
static void process(std::pair< expression_node< T > *, bool >(&branch)[N], expression_node< T > *b)
Definition: exprtk.hpp:5833
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33918
bool is_invalid(const char_t c)
Definition: exprtk.hpp:154
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12266
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, bfunc_t p2)
Definition: exprtk.hpp:13878
const range_t & range_ref() const
Definition: exprtk.hpp:7666
#define basic_opr_switch_statements
Definition: exprtk.hpp:28523
details::binary_node< T > binary_node_t
Definition: exprtk.hpp:18338
token & set_string(const std::string &s, const std::size_t p)
Definition: exprtk.hpp:2101
variable_node_t * variable_node_ptr
Definition: exprtk.hpp:18443
static details::operator_type operation()
Definition: exprtk.hpp:12225
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8325
rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7255
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:34157
exprtk::parser< T > parser_t
Definition: exprtk.hpp:36177
bool is_rebasevector_elem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5156
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30254
T shr(const T v0, const T v1)
Definition: exprtk.hpp:1481
multimode_genfunction_node(GenericFunction *func, const std::size_t &param_seq_index, const std::vector< typename gen_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:11810
void dump(lexer::generator &generator)
Definition: exprtk.hpp:3177
token & set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2060
expression_node_ptr parse_not_statement()
Definition: exprtk.hpp:21843
std::pair< bool, expression_node_ptr > n0_e
Definition: exprtk.hpp:7060
expression_node_ptr parse_string()
Definition: exprtk.hpp:23086
static details::operator_type operation()
Definition: exprtk.hpp:12159
bool assignment_disabled(const details::operator_type assignment_operation) const
Definition: exprtk.hpp:19746
bool is_vector_elem_node(const expression_node< T > *node)
Definition: exprtk.hpp:5150
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:5614
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:34218
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6539
bool valid_string_operation(const details::operator_type &operation) const
Definition: exprtk.hpp:26249
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33055
literal_node< T > & operator=(literal_node< T > &)
Definition: exprtk.hpp:5653
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:34097
bool control_struct_disabled(const std::string &control_struct) const
Definition: exprtk.hpp:19730
const std::string logic_ops_list[]
Definition: exprtk.hpp:464
const vds_t & vds() const
Definition: exprtk.hpp:7584
multi_switch_node(const Sequence< expression_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:6809
#define exprtk_crtype(Type)
Definition: exprtk.hpp:13598
std::vector< lexer::token_modifier * > token_modifier_list
Definition: exprtk.hpp:4044
std::map< std::string, synthesize_functor_t > synthesize_map_t
Definition: exprtk.hpp:25948
details::quaternary_node< T > quaternary_node_t
Definition: exprtk.hpp:18340
local_data_t & local_data(const std::size_t &index=0)
Definition: exprtk.hpp:19172
std::size_t stringvar_count() const
Definition: exprtk.hpp:16929
expression_node_ptr synthesize_socs_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34529
str_sogens_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:15119
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38809
generic_type::vector_view vector_t
Definition: exprtk.hpp:38617
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38858
void deactivate(const std::size_t &scope_depth)
Definition: exprtk.hpp:18616
static T process(const T &t0, const T &t1, const T &t2, const bfunc_t bf0, const bfunc_t bf1)
Definition: exprtk.hpp:13609
vob_node(const T &var, const expression_ptr brnch)
Definition: exprtk.hpp:14642
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38479
std::map< std::string, type_pair_t, details::ilesscompare > type_map_t
Definition: exprtk.hpp:16354
void set_c(const T new_c)
Definition: exprtk.hpp:14768
string_function_node(StringFunction *func, const std::vector< typename gen_function_t::expression_ptr > &arg_list)
Definition: exprtk.hpp:11726
T0oT1oT2_sf3ext< T, T0, T1, T2, SF3Operation > node_type
Definition: exprtk.hpp:14191
scope_element & get_element(const std::size_t &index)
Definition: exprtk.hpp:18542
bool imatch(const char_t c1, const char_t c2)
Definition: exprtk.hpp:176
#define case_stmt1(op)
static expression_node_ptr error_node()
Definition: exprtk.hpp:20998
static QTextStream & operator<<(QTextStream &stream, SIPrefix prefix)
Definition: util.cpp:44
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15221
std::vector< expression_ptr > initialiser_list_
Definition: exprtk.hpp:7424
std::pair< token_t, std::pair< token_t, token_t > > token_triplet_t
Definition: exprtk.hpp:3817
vector_holder(exprtk::vector_view< Type > &vec)
Definition: exprtk.hpp:5521
binary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:5904
bool valid_base_operation(const std::string &symbol) const
Definition: exprtk.hpp:20500
functor_t::bfunc_t bfunc_t
Definition: exprtk.hpp:13993
bool post_bracket_process(const typename token_t::token_type &token, expression_node_ptr &branch)
Definition: exprtk.hpp:25285
generic_type::vector_view vector_t
Definition: exprtk.hpp:38027
bool register_modifier(lexer::token_modifier *modifier)
Definition: exprtk.hpp:3913
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:29986
vector_node< T > * vec1_node_ptr_
Definition: exprtk.hpp:7592
variable_ptr get_variable(const std::string &variable_name) const
Definition: exprtk.hpp:18809
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11057
void dump_ptr(const std::string &, const void *)
Definition: exprtk.hpp:4654
const char_t & back(const std::string &s)
Definition: exprtk.hpp:258
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38478
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5640
opr_base< T >::Type Type
Definition: exprtk.hpp:12221
void add_assignment(const std::string &symbol, const symbol_type st)
Definition: exprtk.hpp:19426
T0oT1oT2< T, T0, T1, T2, ProcessMode > node_type
Definition: exprtk.hpp:13905
expression_node_ptr parse_conditional_statement()
Definition: exprtk.hpp:21685
std::string str() const
Definition: exprtk.hpp:8151
std::vector< type_store > & parameter_list_
Definition: exprtk.hpp:4325
void add_invalid(token_t t0, token_t t1, token_t t2)
Definition: exprtk.hpp:3888
const T c() const
Definition: exprtk.hpp:14824
sf4_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3)
Definition: exprtk.hpp:9354
bool is_vov_node(const expression_node< T > *node)
Definition: exprtk.hpp:15409
operator_type operation() const
Definition: exprtk.hpp:5609
T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
Definition: exprtk.hpp:13908
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &sf4opr, T0 t0, T1 t1, T2 t2, T3 t3)
Definition: exprtk.hpp:29739
bool add_impl(const std::string &symbol_name, RType t, const bool is_const)
Definition: exprtk.hpp:16414
void ignore_symbol(const std::string &symbol)
Definition: exprtk.hpp:3200
void swap(ViewItemIterator< Owner, Item > &a, ViewItemIterator< Owner, Item > &b)
lexer::token_joiner * error_token_joiner
Definition: exprtk.hpp:4050
details::char_cptr base_itr_
Definition: exprtk.hpp:2854
bool is_constant_node(const std::string &symbol_name) const
Definition: exprtk.hpp:17071
value_ptr value_at(const std::size_t &index) const
Definition: exprtk.hpp:5448
bool is_swap_node(const expression_node< T > *node)
Definition: exprtk.hpp:5222
settings_store & disable_all_assignment_ops()
Definition: exprtk.hpp:19633
bool add_function(const std::string &function_name, function_t &function)
Definition: exprtk.hpp:17168
variable_ptr get_variable(const T &var_ref) const
Definition: exprtk.hpp:16964
local_data_list_t local_data_list
Definition: exprtk.hpp:17883
string_function_node< T, StringFunction > str_function_t
Definition: exprtk.hpp:11852
T const_pi_impl(real_type_tag)
Definition: exprtk.hpp:1328
bool pgo_primer()
Definition: exprtk.hpp:36914
bool collect_functions(const std::string &expression, Sequence< std::string, Allocator > &symbol_list)
Definition: exprtk.hpp:35556
unsigned long long int usec_time() const
Definition: exprtk.hpp:37180
return_node(const std::vector< typename gen_function_t::expression_ptr > &arg_list, results_context_t &rc)
Definition: exprtk.hpp:11929
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12179
#define register_sf3_extid(Id, Op)
details::char_t char_t
Definition: exprtk.hpp:2205
std::size_t paramseq_count() const
Definition: exprtk.hpp:23532
virtual operator_type operation() const
Definition: exprtk.hpp:13260
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15310
expression_node< T > * expression_ptr
Definition: exprtk.hpp:13463
const T & v0() const
Definition: exprtk.hpp:14516
build_string(const std::size_t &initial_size=64)
Definition: exprtk.hpp:387
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12295
expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
Definition: exprtk.hpp:21441
T asinh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1348
expression_node< T > * expression_ptr
Definition: exprtk.hpp:10939
static bool compile_left(expression_generator< Type > &expr_gen, ExternalType t, const details::operator_type &operation, expression_node_ptr &sf3node, expression_node_ptr &result)
Definition: exprtk.hpp:29847
bool add(const std::string &symbol_name, std::vector< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:16486
bool logic_disabled(const std::string &logic_operation) const
Definition: exprtk.hpp:19738
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37731
expression_node_ptr parse_switch_statement()
Definition: exprtk.hpp:22329
variable_node< T > * var_node_ptr_
Definition: exprtk.hpp:10051
operator_type operation() const
Definition: exprtk.hpp:14758
bool is_vector_arithmetic_operation(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26630
const std::string base_function_list[]
Definition: exprtk.hpp:449
bool is_variable(const std::string &variable_name) const
Definition: exprtk.hpp:19046
file_descriptor * make_handle(T v)
Definition: exprtk.hpp:37567
bool valid_function(const std::string &symbol) const
Definition: exprtk.hpp:17716
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37980
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33698
std::string arith_opr_to_string(details::operator_type opr) const
Definition: exprtk.hpp:20001
const range_t & range_ref() const
Definition: exprtk.hpp:8083
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8380
T atan_impl(const T, int_type_tag)
Definition: exprtk.hpp:1349
rebasevector_elem_node< T > * rbvec_node_ptr_
Definition: exprtk.hpp:10125
const type_store & back() const
Definition: exprtk.hpp:4318
const T & v() const
Definition: exprtk.hpp:14663
T or_opr(const T v0, const T v1)
Definition: exprtk.hpp:1509
functor_t::ufunc_t unary_functor_t
Definition: exprtk.hpp:18389
igfun_t::generic_type generic_type
Definition: exprtk.hpp:37602
bool read(View &view, const std::size_t amount, const std::size_t offset=0)
Definition: exprtk.hpp:37496
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38310
generic_type::string_view string_t
Definition: exprtk.hpp:37732
details::functor_t< T > functor_t
Definition: exprtk.hpp:14366
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38810
std::string assign_opr_to_string(details::operator_type opr) const
Definition: exprtk.hpp:19987
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7496
bool is_assignment_operation(const details::operator_type &operation) const
Definition: exprtk.hpp:26236
static void execute(T_(&v)[BranchCount], const branch_t(&b)[BranchCount])
Definition: exprtk.hpp:11207
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14999
std::string get_variable_name(const expression_node_ptr &ptr) const
Definition: exprtk.hpp:19150
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8858
variable_node< T > * var_node_ptr_
Definition: exprtk.hpp:9630
precedence_level right
Definition: exprtk.hpp:20686
static bool is_function(const expression< T > &expr)
Definition: exprtk.hpp:18154
T axn(T a, T x)
Definition: exprtk.hpp:9103
bool is_const_string_range_node(const expression_node< T > *node)
Definition: exprtk.hpp:15475
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11887
bool valid_operator(const details::operator_type &operation, binary_functor_t &bop)
Definition: exprtk.hpp:26071
generic_type::vector_view vector_t
Definition: exprtk.hpp:38480
#define exprtk_define_erf(TT, impl)
Definition: exprtk.hpp:1197
expression_node< T >::node_type type() const
Definition: exprtk.hpp:13555
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33978
std::string scalar_format_
Definition: exprtk.hpp:37312
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10406
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:11709
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:31065
static T process(const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12202
variable_node_ptr var1_
Definition: exprtk.hpp:7456
details::T0oT1_define< T, cref_t, cref_t > vov_t
Definition: exprtk.hpp:18404
details::for_loop_bc_node< T > for_loop_bc_node_t
Definition: exprtk.hpp:18349
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:10631
base_ops_map_t base_ops_map_
Definition: exprtk.hpp:35391
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32754
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33397
std::vector< token_t > token_list_t
Definition: exprtk.hpp:2203
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12377
static void execute(std::string &s, char_cptr data, const std::size_t size)
Definition: exprtk.hpp:8438
igeneric_function< T >::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37296
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12408
bool is_variable_node(const expression_node< T > *node)
Definition: exprtk.hpp:5132
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:13565
bool is_cov_node(const expression_node< T > *node)
Definition: exprtk.hpp:15415
details::operator_type get_operator(const binary_functor_t &bop) const
Definition: exprtk.hpp:26095
operator_type operation() const
Definition: exprtk.hpp:14205
bool write(const View &view, const std::size_t amount, const std::size_t offset=0)
Definition: exprtk.hpp:37477
bool post_variable_process(const std::string &symbol)
Definition: exprtk.hpp:25260
T or_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1143
static T process_8(const Sequence &arg_list)
Definition: exprtk.hpp:12958
function_ptr get_function(const std::string &function_name) const
Definition: exprtk.hpp:18871
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:13714
T xor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1523
bool function_disabled(const std::string &function_name) const
Definition: exprtk.hpp:19722
void free_all_nodes(NodeAllocator &node_allocator, expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5314
lexer::helper::bracket_checker bracket_checker_
Definition: exprtk.hpp:35406
break_node(expression_ptr ret=expression_ptr(0))
Definition: exprtk.hpp:6228
vector_node< T > * vector_node_ptr
Definition: exprtk.hpp:7098
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37600
expression_node< T > * expression_ptr
Definition: exprtk.hpp:13534
rebasevector_celem_node< T > * rbvec_node_ptr_
Definition: exprtk.hpp:9744
bool is_logic_opr(const std::string &lgc_opr)
Definition: exprtk.hpp:554
generic_type::vector_view vector_t
Definition: exprtk.hpp:37677
int to_int32(const T v)
Definition: exprtk.hpp:1383
static details::operator_type operation()
Definition: exprtk.hpp:12147
std::vector< funcparam_t > fp_map_
Definition: exprtk.hpp:36909
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12306
inv_binary_op_map_t inv_binary_op_map_
Definition: exprtk.hpp:35394
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6685
const std::size_t stride_
Definition: exprtk.hpp:2979
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14910
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38570
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6928
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30380
std::string type_id() const
Definition: exprtk.hpp:14052
static const char * date
Definition: exprtk.hpp:39022
const range_t & range_ref() const
Definition: exprtk.hpp:7944
dependent_entity_collector & dec()
Definition: exprtk.hpp:20452
bool remove_stringvar(const std::string &string_name)
Definition: exprtk.hpp:17383
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15309
char_t const * char_cptr
Definition: exprtk.hpp:91
base_operation_t(const operator_type t, const unsigned int &np)
Definition: exprtk.hpp:4610
vector_interface< T > * ivector_ptr
Definition: exprtk.hpp:13075
quaternary_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3)
Definition: exprtk.hpp:6065
bool cob_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26393
static details::operator_type operation()
Definition: exprtk.hpp:12277
unary_node(const operator_type &opr, expression_ptr brnch)
Definition: exprtk.hpp:5772
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
static const std::size_t reserved_symbols_size
Definition: exprtk.hpp:447
void enable_has_side_effects(FunctionType &func)
Definition: exprtk.hpp:15952
bool is_string_operation(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26568
void cleanup_escapes(std::string &s)
Definition: exprtk.hpp:337
std::string get_conststr_stringvar_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:17598
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12214
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12106
vector_view(data_ptr_t data, const std::size_t &size)
Definition: exprtk.hpp:4176
bool is_nan_impl(const T v, real_type_tag)
Definition: exprtk.hpp:838
function_compositor(const symbol_table_t &st)
Definition: exprtk.hpp:36684
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14378
type_store< typename details::variable_node< T >, T > variable_store
Definition: exprtk.hpp:16745
std::string & s1()
Definition: exprtk.hpp:14889
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38364
bool is_string_assignment_node(const expression_node< T > *node)
Definition: exprtk.hpp:15481
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33797
bool is_valid_token(std::string param_seq, function_prototype_t &funcproto) const
Definition: exprtk.hpp:23594
static T_ execute(ifunction &f, T_(&v)[8])
Definition: exprtk.hpp:11361
static std::pair< bool, vector_t * > make(std::pair< T *, std::size_t > v, const bool is_const=false)
Definition: exprtk.hpp:16440
vector_holder_ptr vec_holder_
Definition: exprtk.hpp:7239
std::string inequality_opr_to_string(details::operator_type opr) const
Definition: exprtk.hpp:20014
bool simplify_unary_negation_branch(expression_node_ptr &node)
Definition: exprtk.hpp:20943
expression_node< typename node_type::value_type > * allocate_rrr(T1 &t1, T2 &t2, T3 &t3) const
Definition: exprtk.hpp:15665
details::char_cptr s_end_
Definition: exprtk.hpp:2856
bool bracket_check_enabled() const
Definition: exprtk.hpp:19661
details::functor_t< T > functor_t
Definition: exprtk.hpp:18385
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:10786
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11414
static control_block * create()
Definition: exprtk.hpp:16817
expression_node_ptr synthesize_assignment_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28072
vector_holder_t & vec_holder()
Definition: exprtk.hpp:7175
T(* qfunc_t)(Type t0, Type t1, Type t2, Type t3)
Definition: exprtk.hpp:2016
symbol_table_t::variable_ptr variable_ptr
Definition: exprtk.hpp:18760
bfunc_t f0() const
Definition: exprtk.hpp:13947
expression_node_ptr varnode_optimise_sf4(const details::operator_type &operation, expression_node_ptr(&branch)[4])
Definition: exprtk.hpp:27486
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33138
results_context< T > results_context_t
Definition: exprtk.hpp:18427
generic_function_node(const std::vector< expression_ptr > &arg_list, GenericFunction *func=(GenericFunction *)(0))
Definition: exprtk.hpp:11543
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38663
generic_type::vector_view vector_t
Definition: exprtk.hpp:37935
details::functor_t< T > functor_t
Definition: exprtk.hpp:13902
expression_node< T >::node_type type() const
Definition: exprtk.hpp:12002
manual txt set(MANUAL_OUT_HTML"${CMAKE_CURRENT_BINARY_DIR}/manual.html") set(MANUAL_OUT_PDF"$
Definition: CMakeLists.txt:36
T process(const operator_type operation, const T arg0, const T arg1)
Definition: exprtk.hpp:5003
details::T0oT1oT2< T, T0, T1, T2, typename T0oT1oT2process< T >::mode1 > type1
Definition: exprtk.hpp:14471
void update(const T &v0, const T &v1, const T &v2, const T &v3, const T &v4, const T &v5)
Definition: exprtk.hpp:36324
operator_joiner(const std::size_t &stride)
Definition: exprtk.hpp:3256
operator_type operation() const
Definition: exprtk.hpp:14819
std::vector< lexer::token_joiner * > token_joiner_list
Definition: exprtk.hpp:4045
bool resolve_unknown_symbol_
Definition: exprtk.hpp:35387
expression_node< T >::node_type type() const
Definition: exprtk.hpp:14556
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:32238
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7464
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:13652
std::size_t get_stringvar_list(Sequence< std::string, Allocator > &svlist) const
Definition: exprtk.hpp:17481
expression_node_ptr switch_statement(Sequence< expression_node_ptr, Allocator > &arg_list)
Definition: exprtk.hpp:27203
static const double pi_4
Definition: exprtk.hpp:754
bool all_nodes_variables(expression_node< T > *(&b)[N])
Definition: exprtk.hpp:5284
T cot_impl(const T, int_type_tag)
Definition: exprtk.hpp:1357
virtual vector_node_ptr vec() const =0
expression_node< typename node_type::value_type > * allocate_rr(T1 &t1, T2 &t2) const
Definition: exprtk.hpp:15637
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7361
#define register_op(Symbol, Type, Args)
#define exprtk_register_complex_type_tag(T)
Definition: exprtk.hpp:781
bool binext_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26470
const local_data_t & local_data() const
Definition: exprtk.hpp:17749
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8449
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30545
static T process_1(const Sequence &arg_list)
Definition: exprtk.hpp:12526
T process_impl(const operator_type operation, const T arg)
Definition: exprtk.hpp:4867
expression_node_ptr synthesize_uvouv_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34310
std::size_t symbols(Sequence< symbol_t, Allocator > &symbols_list)
Definition: exprtk.hpp:19316
details::while_loop_bc_node< T > while_loop_bc_node_t
Definition: exprtk.hpp:18347
type_store< igeneric_function< T >, igeneric_function< T > > generic_function_store
Definition: exprtk.hpp:16751
symbol_table_t::vector_holder_ptr vector_holder_ptr
Definition: exprtk.hpp:18765
std::size_t & max_num_args()
Definition: exprtk.hpp:15921
details::T0oT1oT2oT3_define< T, cref_t, const_t, const_t, cref_t > vococov_t
Definition: exprtk.hpp:18425
results_context_t * results
Definition: exprtk.hpp:17884
static details::operator_type operation()
Definition: exprtk.hpp:12340
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3)
Definition: exprtk.hpp:14425
T hypot_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1055
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12120
#define exprtk_define_erfc(TT, impl)
Definition: exprtk.hpp:1241
data_ptr_t data_
Definition: exprtk.hpp:4229
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7311
bool is_t0ot1ot2ot3_node(const expression_node< T > *node)
Definition: exprtk.hpp:15445
static T_ execute(ifunction &f, T_(&v)[7])
Definition: exprtk.hpp:11368
unary_vector_node(const operator_type &opr, expression_ptr branch0)
Definition: exprtk.hpp:10944
bool is_break_node(const expression_node< T > *node)
Definition: exprtk.hpp:5210
std::size_t function_count() const
Definition: exprtk.hpp:16938
static void process(const std::string &scalar_format, parameter_list_t parameters)
Definition: exprtk.hpp:37247
std::size_t size() const
Definition: exprtk.hpp:4206
void enable_unknown_symbol_resolver(unknown_symbol_resolver *usr=reinterpret_cast< unknown_symbol_resolver * >(0))
Definition: exprtk.hpp:20477
operator_type operation() const
Definition: exprtk.hpp:13922
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33637
static const std::size_t pow10_size
Definition: exprtk.hpp:745
expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
Definition: exprtk.hpp:21534
expression< T >::symtab_list_t symbol_table_list_t
Definition: exprtk.hpp:18382
details::T0oT1oT2oT3_define< T, cref_t, const_t, cref_t, const_t > vocovoc_t
Definition: exprtk.hpp:18423
details::vector_node< T > vector_node_t
Definition: exprtk.hpp:18356
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12222
bool remove_replace_symbol(const std::string &symbol)
Definition: exprtk.hpp:20467
bool is_comment_start(details::char_cptr itr)
Definition: exprtk.hpp:2351
bool & allow_zero_parameters()
Definition: exprtk.hpp:15906
details::operator_type operator_t
Definition: exprtk.hpp:18391
sosos_node(SType0 p0, SType1 p1, SType2 p2)
Definition: exprtk.hpp:15225
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38419
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38213
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30913
it will come up with a session that has the demo device selected That you can get to know the program even when you don t have any hardware to use it you see a list of devices PulseView has recognized If the device you want to use is you can just select it here image::device_selector_dropdown png[] If it s not you ll need to scan for it first Since most serial port and Ethernet devices can t be auto this is usually required for those To do either choose the Connect to Device option from the list or click on the button itself You will see the following you ll need to pick a driver that you want to use In order to do this
Definition: acquisition.txt:14
vec_data_store< T > vds_t
Definition: exprtk.hpp:7099
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12421
expression_node_ptr parse_function_call_0(ifunction< T > *function, const std::string &function_name)
Definition: exprtk.hpp:21274
const token_t & current_token() const
Definition: exprtk.hpp:4103
expression(const expression< T > &e)
Definition: exprtk.hpp:17899
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5925
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:15377
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38857
static T evaluate(const Type x, const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:35940
details::stringvar_node< T > stringvar_t
Definition: exprtk.hpp:16728
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7671
expression_node< T >::node_type type() const
Definition: exprtk.hpp:13433
T floor_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1339
expression_node_ptr return_call(std::vector< expression_node_ptr > &arg_list)
Definition: exprtk.hpp:27874
void clear(const bool delete_node=true)
Definition: exprtk.hpp:16646
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8700
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30239
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14592
void set_ibom(inv_binary_op_map_t &inv_binary_op_map)
Definition: exprtk.hpp:26041
details::T0oT1oT2_define< T, cref_t, const_t, const_t > vococ_t
Definition: exprtk.hpp:18414
vector_node< T > * vec_node_ptr_
Definition: exprtk.hpp:9860
type_checker(parser_t &p, const std::string &func_name, const std::string &func_prototypes, const return_type_t default_return_type)
Definition: exprtk.hpp:23453
bool valid_symbol(const std::string &symbol) const
Definition: exprtk.hpp:18793
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6273
std::deque< std::string > v_
Definition: exprtk.hpp:36268
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9, const T10 &t10) const
Definition: exprtk.hpp:15766
void copy(const varref_t &src_v, var_t &dest_v)
Definition: exprtk.hpp:36411
#define register_synthezier(S)
opr_base< T >::Type Type
Definition: exprtk.hpp:12114
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:9097
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12684
expression_node_ptr synthesize_csosr_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34549
operator_type operation() const
Definition: exprtk.hpp:14658
expression_node_ptr generic_function_call(igeneric_function_t *gf, std::vector< expression_node_ptr > &arg_list, const std::size_t &param_seq_index=std::numeric_limits< std::size_t >::max())
Definition: exprtk.hpp:27764
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12901
ivararg_function< T > vararg_function_t
Definition: exprtk.hpp:16732
virtual operator_type operation() const
Definition: exprtk.hpp:13318
static T process(const T &t0, const T &t1, const T &t2, const bfunc_t bf0, const bfunc_t bf1)
Definition: exprtk.hpp:13627
range_interface< T > range_interface_t
Definition: exprtk.hpp:11534
std::size_t process(generator &g)
Definition: exprtk.hpp:2986
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38711
store_type type
Definition: exprtk.hpp:4273
static void execute(T_(&v)[3], const branch_t(&b)[3])
Definition: exprtk.hpp:11244
expression_node_ptr cardinal_pow_optimisation_impl(const TType &v, const unsigned int &p)
Definition: exprtk.hpp:28547
bool string_to_real(Iterator &itr_external, const Iterator end, T &t, numeric::details::real_type_tag)
Definition: exprtk.hpp:1833
static T_ execute(ifunction &f, T_(&v)[2])
Definition: exprtk.hpp:11403
value_t & operator[](const std::size_t &i)
Definition: exprtk.hpp:4351
expression_node_ptr parse_string_range_statement(expression_node_ptr &expression)
Definition: exprtk.hpp:22670
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7) const
Definition: exprtk.hpp:15725
bool is_voc_node(const expression_node< T > *node)
Definition: exprtk.hpp:15421
opr_base< T >::Type Type
Definition: exprtk.hpp:12324
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12192
bool is_hex_digit(const std::string::value_type digit)
Definition: exprtk.hpp:297
parser_state state_
Definition: exprtk.hpp:35386
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8677
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[2])
Definition: exprtk.hpp:15558
static T_ execute(ifunction &f, T_(&v)[16])
Definition: exprtk.hpp:11305
static void execute(std::string &s, char_cptr data, const std::size_t size)
Definition: exprtk.hpp:8432
std::string paramseq(const std::size_t &index) const
Definition: exprtk.hpp:23537
stringvar_ptr get_stringvar(const std::string &string_name) const
Definition: exprtk.hpp:18849
virtual const T & v() const =0
settings_store & disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
Definition: exprtk.hpp:19821
void disable_type_checking(Parser &p)
Definition: exprtk.hpp:18297
details::T0oT1oT2_define< T, cref_t, cref_t, cref_t > vovov_t
Definition: exprtk.hpp:18408
bool bov_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26461
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13077
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15279
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38026
expression_node_ptr vector_element(const std::string &symbol, vector_holder_ptr vector_base, expression_node_ptr index)
Definition: exprtk.hpp:27931
bool coboc_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26427
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34059
symbol_table_t::generic_function_ptr generic_function_ptr
Definition: exprtk.hpp:18767
void free(expression_node< T > *&e) const
Definition: exprtk.hpp:15826
expression_node< typename node_type::value_type > * allocate_ttt(T1 t1, T2 t2, T3 t3) const
Definition: exprtk.hpp:15651
lexer::helper::operator_joiner operator_joiner_2_
Definition: exprtk.hpp:35403
static std::string id()
Definition: exprtk.hpp:14144
expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28466
generic_type::scalar_view scalar_t
Definition: exprtk.hpp:38616
static T_ execute(ifunction &f, T_(&v)[19])
Definition: exprtk.hpp:11284
bool is_ivariable_node(const expression_node< T > *node)
Definition: exprtk.hpp:5138
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &sf3opr, T0 t0, T1 t1, T2 t2)
Definition: exprtk.hpp:29696
static bool compile_left_impl(expression_generator< Type > &expr_gen, const std::string &id, ExternalType t, expression_node_ptr &node, expression_node_ptr &result)
Definition: exprtk.hpp:29911
details::T0oT1oT2oT3_define< T, cref_t, cref_t, cref_t, cref_t > vovovov_t
Definition: exprtk.hpp:18416
static void match_sizes(type &vds0, type &vds1)
Definition: exprtk.hpp:4839
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33759
details::cons_conditional_node< T > cons_conditional_node_t
Definition: exprtk.hpp:18342
assignment_rebasevec_elem_op_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10098
void init_branches(std::pair< expression_node< T > *, bool >(&branch)[N], expression_node< T > *b0, expression_node< T > *b1=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b2=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b3=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b4=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b5=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b6=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b7=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b8=reinterpret_cast< expression_node< T > * >(0), expression_node< T > *b9=reinterpret_cast< expression_node< T > * >(0))
Definition: exprtk.hpp:5843
static T process(const T &, const T &)
Definition: exprtk.hpp:12315
expression_node< T > * expression_ptr
Definition: exprtk.hpp:15112
static T process_4(const Sequence &arg_list)
Definition: exprtk.hpp:12838
static T evaluate(const Type x, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:36027
details::stringvar_node< T > stringvar_node_t
Definition: exprtk.hpp:16348
token & set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin=Iterator(0))
Definition: exprtk.hpp:2110
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:6777
const range_t & range_ref() const
Definition: exprtk.hpp:7751
details::T0oT1_define< T, cref_t, const_t > voc_t
Definition: exprtk.hpp:18406
bool remove_function(const std::string &function_name)
Definition: exprtk.hpp:17392
virtual bool join(const token &, const token &, token &)
Definition: exprtk.hpp:3108
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6601
T log1p_impl(const T v, int_type_tag)
Definition: exprtk.hpp:994
expression_node_ptr synthesize_sros_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34474
static std::string id(expression_generator< Type > &, const details::operator_type, const details::operator_type, const details::operator_type)
Definition: exprtk.hpp:34302
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29616
const T & v() const
Definition: exprtk.hpp:14571
symtab_list_t get_symbol_table_list() const
Definition: exprtk.hpp:18018
unknown_symbol_resolver * unknown_symbol_resolver_
Definition: exprtk.hpp:35389
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7569
define_sfop3(00,(x+y)/z,"(t+t)/t") define_sfop3(01
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11090
type_store< typename details::stringvar_node< T >, std::string > stringvar_store
Definition: exprtk.hpp:16747
scope_handler(parser< T > &p)
Definition: exprtk.hpp:18724
expression_node< T >::node_type type() const
Definition: exprtk.hpp:13916
bool sf3_optimisable(const std::string &sf3id, details::operator_type &operation) const
Definition: exprtk.hpp:26178
bool is_variable(const std::string &variable_name) const
Definition: exprtk.hpp:17525
generic_type::string_view string_t
Definition: exprtk.hpp:37244
const_string_range_node(const std::string &v, const range_t &rp)
Definition: exprtk.hpp:7779
settings_store & disable_assignment_operation(settings_assignment_opr assignment)
Definition: exprtk.hpp:19834
expression_node< T > * expression_ptr
Definition: exprtk.hpp:7844
std::set< std::string, details::ilesscompare > disabled_func_set_t
Definition: exprtk.hpp:18402
T abs_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1331
static std::pair< bool, vector_t * > make(std::vector< T, Allocator > &v, const bool is_const=false)
Definition: exprtk.hpp:16449
bool is_invalid_assignment_op(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26479
repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
Definition: exprtk.hpp:6541
scoped_delete(parser< T > &pr, ptr_t &p)
Definition: exprtk.hpp:21008
igeneric_function< T > generic_function_t
Definition: exprtk.hpp:16733
scalar_view(type_store_t &ts)
Definition: exprtk.hpp:4386
T roundn(const T v0, const T v1)
Definition: exprtk.hpp:1460
T sin_impl(const T, int_type_tag)
Definition: exprtk.hpp:1353
operator_type operation() const
Definition: exprtk.hpp:14606
rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
Definition: exprtk.hpp:7316
T pow(const T v0, const T v1)
Definition: exprtk.hpp:1439
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12925
T log_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1333
ifunction< T > F
Definition: exprtk.hpp:18329
uchar_t hex_to_bin(uchar_t h)
Definition: exprtk.hpp:304
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38859
rebasevector_elem_node< T > * rbvec_node_ptr_
Definition: exprtk.hpp:9706
static const double log2
Definition: exprtk.hpp:759
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37673
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6101
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38759
virtual operator_type operation() const
Definition: exprtk.hpp:13278
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7756
vec_binop_vecvec_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:10450
T atanh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1350
bool add_package(Package &package)
Definition: exprtk.hpp:17443
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12255
operator_type operation() const
Definition: exprtk.hpp:13487
std::size_t size() const
Definition: exprtk.hpp:7574
void copy(const var_t &src_v, lvr_vec_t &dest_v)
Definition: exprtk.hpp:36446
std::pair< T *, std::size_t > lvarref_t
Definition: exprtk.hpp:36279
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12169
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30803
opr_base< T >::Type Type
Definition: exprtk.hpp:12704
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33495
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:9494
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12102
static bool parse_inf(Iterator &itr, const Iterator end, T &t, bool negative)
Definition: exprtk.hpp:1799
details::vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:18383
bov_node(const expression_ptr brnch, const T &var)
Definition: exprtk.hpp:14692
node_type & operator=(node_type &)
Definition: exprtk.hpp:14435
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10750
expression_node< T > * branch(const std::size_t &) const
Definition: exprtk.hpp:5725
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8859
expression_node_ptr parse_generic_function_call(igeneric_function< T > *function, const std::string &function_name)
Definition: exprtk.hpp:23703
bool logic_enabled(const std::string &logic_operation) const
Definition: exprtk.hpp:19687
expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type &opr, T0 s0, T1 s1, range_t rp0, range_t rp1)
Definition: exprtk.hpp:34434
bool is_shortcircuit_expression(const details::operator_type &operation) const
Definition: exprtk.hpp:26586
retparam_list_t return_param_type_list() const
Definition: exprtk.hpp:19396
bool function_enabled(const std::string &function_name) const
Definition: exprtk.hpp:19671
details::vec_data_store< Type > vds_t
Definition: exprtk.hpp:5506
generic_type::vector_view vector_t
Definition: exprtk.hpp:38813
T root_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1019
const local_data_t & local_data(const std::size_t &index=0) const
Definition: exprtk.hpp:19177
#define batch_eqineq_logic_case
static T process(const Sequence< Type, Allocator > &arg_list)
Definition: exprtk.hpp:12638
generic_type::vector_view vector_t
Definition: exprtk.hpp:37243
static control_block * create(expression_ptr e)
Definition: exprtk.hpp:17860
static T process(const ivector_ptr v)
Definition: exprtk.hpp:13215
std::pair< lexer::token, lexer::token > error(const std::size_t index)
Definition: exprtk.hpp:3705
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12144
range_data_type< T > range_data_type_t
Definition: exprtk.hpp:5685
generic_type::vector_view vector_t
Definition: exprtk.hpp:38573
bool process(const std::string &str)
Definition: exprtk.hpp:2225
T0oT1oT2_sf3< T, T0, T1, T2 > node_type
Definition: exprtk.hpp:14094
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12256
bool is_invalid_logic_operation(const details::operator_type operation) const
Definition: exprtk.hpp:20541
details::string_range_node< T > string_range_node_t
Definition: exprtk.hpp:18361
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32934
functor_t::tfunc_t trinary_functor_t
Definition: exprtk.hpp:18387
void disable_zero_parameters(FunctionType &func)
Definition: exprtk.hpp:15946
bool add_function(const std::string &function_name, generic_function_t &function)
Definition: exprtk.hpp:17192
scoped_vec_delete(parser< T > &pr, std::vector< ptr_t > &vec)
Definition: exprtk.hpp:21078
opr_base< T >::Type Type
Definition: exprtk.hpp:12177
std::pair< expression_ptr, bool > branch_t
Definition: exprtk.hpp:5902
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:10447
generic_function_ptr get_string_function(const std::string &function_name) const
Definition: exprtk.hpp:17015
#define string_opr_switch_statements
Definition: exprtk.hpp:34386
virtual std::size_t process(generator &)
Definition: exprtk.hpp:2871
expression_node< T > * expression_ptr
Definition: exprtk.hpp:13421
opr_base< T >::Type Type
Definition: exprtk.hpp:12273
bool add_vector(const std::string &vector_name, std::vector< T, Allocator > &v)
Definition: exprtk.hpp:17346
array_vector_impl(const Type *vec, const std::size_t &vec_size)
Definition: exprtk.hpp:5406
details::functor_t< T > functor_t
Definition: exprtk.hpp:13835
void return_cleanup()
Definition: exprtk.hpp:35361
expression_node< T > * expression_ptr
Definition: exprtk.hpp:6285
void load_compile_options(const std::size_t compile_options)
Definition: exprtk.hpp:19970
expression_node_ptr synthesize_uvec_expression(const details::operator_type &operation, expression_node_ptr(&branch)[1])
Definition: exprtk.hpp:27316
return_type_t return_type(const std::size_t &index) const
Definition: exprtk.hpp:23542
operator_type operation() const
Definition: exprtk.hpp:14561
opr_base< T >::Type Type
Definition: exprtk.hpp:12372
vector_holder_t * vector_holder_
Definition: exprtk.hpp:7182
static T process(Type t1, Type t2)
Definition: exprtk.hpp:12104
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38118
static const double pi_2
Definition: exprtk.hpp:753
bool control_struct_enabled(const std::string &control_struct) const
Definition: exprtk.hpp:19679
control_block::st_data local_data_t
Definition: exprtk.hpp:17742
details::assignment_vecvec_node< T > assignment_vecvec_node_t
Definition: exprtk.hpp:18375
static bool is_constant(const expression< T > &expr)
Definition: exprtk.hpp:18134
expression_node< T > * expression_ptr
Definition: exprtk.hpp:5056
T third_derivative(const expression< T > &e, T &x, const T &h=T(0.0001))
Definition: exprtk.hpp:35709
static const char * version
Definition: exprtk.hpp:39020
bool peek_token_is(const std::string &s)
Definition: exprtk.hpp:4156
T & variable_ref(const std::string &symbol_name)
Definition: exprtk.hpp:17047
T shl(const T v0, const T v1)
Definition: exprtk.hpp:1488
std::vector< range_data_type_t > range_list_t
Definition: exprtk.hpp:11541
bool is_constant_node(const expression_node< T > *node)
Definition: exprtk.hpp:5198
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode1 > type1
Definition: exprtk.hpp:14480
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6) const
Definition: exprtk.hpp:15714
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9) const
Definition: exprtk.hpp:15751
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12551
disabled_entity_set_t::iterator des_itr_t
Definition: exprtk.hpp:19459
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12692
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28639
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30064
type_store< T > type_store_t
Definition: exprtk.hpp:4333
details::const_string_range_node< T > const_string_range_node_t
Definition: exprtk.hpp:18362
vectorize_node(const expression_ptr v)
Definition: exprtk.hpp:9551
std::pair< bool, std::size_t > n0_c
Definition: exprtk.hpp:7062
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8976
opr_base< T >::Type Type
Definition: exprtk.hpp:12153
const bfunc_t f_
Definition: exprtk.hpp:13894
bool symbol_used(const std::string &symbol) const
Definition: exprtk.hpp:36831
expression_node< typename ResultNode::value_type > * allocate(OpType &operation, ExprNode(&branch)[6])
Definition: exprtk.hpp:15582
std::string scalar_format_
Definition: exprtk.hpp:37335
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:30560
void free_node(NodeAllocator &node_allocator, expression_node< T > *&node, const bool force_delete=false)
Definition: exprtk.hpp:5337
T nand_opr(const T v0, const T v1)
Definition: exprtk.hpp:1502
T & operator[](const std::size_t index)
Definition: exprtk.hpp:4216
uchar_t * uchar_ptr
Definition: exprtk.hpp:88
void set_c(const T new_c)
Definition: exprtk.hpp:14829
T xnor_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:1185
expression_node< T > * expression_ptr
Definition: exprtk.hpp:8699
T sec_impl(const T, int_type_tag)
Definition: exprtk.hpp:1358
opr_base< T >::RefType RefType
Definition: exprtk.hpp:12154
type_store< vector_holder_t, vector_holder_t > vector_store
Definition: exprtk.hpp:16754
exprtk::parser< T > parser_t
Definition: exprtk.hpp:35422
std::string as_string() const
Definition: exprtk.hpp:409
token_t operator[](const std::size_t &index) const
Definition: exprtk.hpp:2299
vector_node< T > * vec0_node_ptr_
Definition: exprtk.hpp:7591
bool sequence_match(const std::string &pattern, const std::string &str, std::size_t &diff_index, char_t &diff_value)
Definition: exprtk.hpp:667
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38709
vector_node(vector_holder_t *vh)
Definition: exprtk.hpp:7128
parser_t::settings_store settings_t
Definition: exprtk.hpp:36178
std::size_t get_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:16702
expression_node_ptr parse_multi_switch_statement()
Definition: exprtk.hpp:22476
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15074
expression_node< T > * expression_ptr
Definition: exprtk.hpp:11114
std::size_t size() const
Definition: exprtk.hpp:7160
igeneric_function< T >::generic_type generic_type
Definition: exprtk.hpp:37240
static T return_value(expression_t &e)
Definition: exprtk.hpp:36601
static const double _180_pi
Definition: exprtk.hpp:758
static details::operator_type operation()
Definition: exprtk.hpp:12287
bool is_function(const std::string &function_name) const
Definition: exprtk.hpp:19102
char_cptr base() const
Definition: exprtk.hpp:7641
assignment_rebasevec_celem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9716
std::size_t variable_count() const
Definition: exprtk.hpp:16920
static void print(const std::string &scalar_format, const vector_t &v)
Definition: exprtk.hpp:37274
function & expression(const std::string &e)
Definition: exprtk.hpp:36254
generic_type::string_view string_t
Definition: exprtk.hpp:37603
variable_ptr get_variable(const std::string &variable_name) const
Definition: exprtk.hpp:16954
static expression_node< T >::node_type type()
Definition: exprtk.hpp:12158
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33517
static void destroy(control_block *&cntrl_blck, SymTab *sym_tab)
Definition: exprtk.hpp:16823
range_interface< T > irange_t
Definition: exprtk.hpp:15116
std::size_t size() const
Definition: exprtk.hpp:9070
assignment_rebasevec_elem_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:9678
std::string str() const
Definition: exprtk.hpp:7716
void enable_zero_parameters(FunctionType &func)
Definition: exprtk.hpp:15935
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:38708
T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
Definition: exprtk.hpp:4958
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8381
exprtk::symbol_table< T > symbol_table_t
Definition: exprtk.hpp:35420
bool inequality_disabled(const details::operator_type &inequality) const
Definition: exprtk.hpp:19773
settings_store & enable_all_inequality_ops()
Definition: exprtk.hpp:19585
const T & ref() const
Definition: exprtk.hpp:6923
static T process_5(const Sequence &arg_list)
Definition: exprtk.hpp:12769
static T process(Type t1, Type t2, Type t3)
Definition: exprtk.hpp:12105
expression_node< typename node_type::value_type > * allocate_type(T1 t1, T2 t2, T3 t3) const
Definition: exprtk.hpp:15777
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33940
operator_type operation() const
Definition: exprtk.hpp:15241
details::vector_holder< T > vector_holder_t
Definition: exprtk.hpp:18442
bool collect_variables(const std::string &expression, Sequence< std::string, Allocator > &symbol_list)
Definition: exprtk.hpp:35495
void set_sf3m(sf3_map_t &sf3_map)
Definition: exprtk.hpp:26046
bool is_function(const std::string &function_name) const
Definition: exprtk.hpp:17558
std::string construct_subexpr(lexer::token &begin_token, lexer::token &end_token)
Definition: exprtk.hpp:20653
void load_operations_map(std::multimap< std::string, details::base_operation_t, details::ilesscompare > &m)
Definition: exprtk.hpp:15833
operator_type operation() const
Definition: exprtk.hpp:15079
opr_base< T >::Type Type
Definition: exprtk.hpp:12231
void set_ref(value_ptr *ref)
Definition: exprtk.hpp:5540
T pow_impl(const T v0, const T v1, int_type_tag)
Definition: exprtk.hpp:960
ifunction(const std::size_t &pc)
Definition: exprtk.hpp:15983
std::pair< std::string, symbol_type > symbol_t
Definition: exprtk.hpp:19302
settings_store & disable_all_control_structures()
Definition: exprtk.hpp:19606
type_store< igeneric_function< T >, igeneric_function< T > > string_function_store
Definition: exprtk.hpp:16752
type_view(const type_store_t &ts)
Definition: exprtk.hpp:4341
static const char * library
Definition: exprtk.hpp:39019
std::string synthesis_error_
Definition: exprtk.hpp:35397
T axnb(T a, T x, T b)
Definition: exprtk.hpp:9110
igeneric_function_t * igeneric_function_ptr
Definition: exprtk.hpp:11925
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12601
variable_node_ptr var0_
Definition: exprtk.hpp:7455
static details::operator_type operation()
Definition: exprtk.hpp:12193
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5604
bool is_constant_string(const std::string &symbol_name) const
Definition: exprtk.hpp:19014
symtab_list_t symbol_table_list_
Definition: exprtk.hpp:18122
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8088
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:29592
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38904
expression_node< T >::node_type type() const
Definition: exprtk.hpp:6140
std::deque< bool > brkcnt_list_
Definition: exprtk.hpp:35385
void register_local_var(expression_ptr expr)
Definition: exprtk.hpp:18039
bool is_return_node(const expression_node< T > *node)
Definition: exprtk.hpp:5234
static T process(const T &t0, const T &t1, const T &t2, const T &t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
Definition: exprtk.hpp:13735
conditional_string_node(expression_ptr test, expression_ptr consequent, expression_ptr alternative)
Definition: exprtk.hpp:8706
expression_node_ptr parse_define_var_statement()
Definition: exprtk.hpp:24636
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38662
exprtk::igeneric_function< T > igfun_t
Definition: exprtk.hpp:37786
static details::operator_type operation()
Definition: exprtk.hpp:12182
static T process(const std::string &t0, const std::string &t1, const std::string &t2)
Definition: exprtk.hpp:12349
int to_int32_impl(const T v, real_type_tag)
Definition: exprtk.hpp:844
while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
Definition: exprtk.hpp:6480
static void assign(RefType t1, Type t2)
Definition: exprtk.hpp:12145
details::T0oT1oT2oT3< T, T0, T1, T2, T3, typename T0oT1oT20T3process< T >::mode4 > type4
Definition: exprtk.hpp:14483
expression_node_ptr synthesize_string_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34712
expression_node< T > * expression_ptr
Definition: exprtk.hpp:14542
details::expression_node< T > expression_node_t
Definition: exprtk.hpp:18335
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:33336
expression_node_ptr parse_swap_statement()
Definition: exprtk.hpp:24905
boc_node(const expression_ptr brnch, const T const_var)
Definition: exprtk.hpp:14803
details::assignment_rebasevec_celem_node< T > assignment_rebasevec_celem_node_t
Definition: exprtk.hpp:18373
static expression_node_ptr process(expression_generator< Type > &expr_gen, const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34119
std::size_t get_variable_list(Sequence< std::string, Allocator > &vlist) const
Definition: exprtk.hpp:17460
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38308
string_base_node< T > * str_base_ptr
Definition: exprtk.hpp:8194
const char_t & front(const std::string &s)
Definition: exprtk.hpp:253
std::vector< expression_ptr > arg_list_
Definition: exprtk.hpp:6876
expression_node< T > * expression_ptr
Definition: exprtk.hpp:9411
const type_store & operator[](const std::size_t &index) const
Definition: exprtk.hpp:4298
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38212
generic_type::vector_view vector_t
Definition: exprtk.hpp:38119
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12908
static T evaluate(const Type x, const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
Definition: exprtk.hpp:35991
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9988
T hypot(const T v0, const T v1)
Definition: exprtk.hpp:1467
T xnor_opr(const T v0, const T v1)
Definition: exprtk.hpp:1530
static details::operator_type operation()
Definition: exprtk.hpp:12297
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38661
static expression_node< T > * allocate(Allocator &allocator, T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
Definition: exprtk.hpp:14063
static T_ execute(ifunction &f, T_(&v)[15])
Definition: exprtk.hpp:11312
vector_holder< T > * vector_holder_ptr
Definition: exprtk.hpp:10941
details::for_loop_node< T > for_loop_node_t
Definition: exprtk.hpp:18345
bool register_scanner(lexer::token_scanner *scanner)
Definition: exprtk.hpp:3899
std::vector< symbol_table_t * > auxiliary_symtab_list_
Definition: exprtk.hpp:36910
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38117
bool add_vector(const std::string &vector_name, T(&v)[N])
Definition: exprtk.hpp:17319
#define exprtk_disable_fallthrough_end
Definition: exprtk.hpp:81
std::vector< data_ptr_t * > data_ref_
Definition: exprtk.hpp:4230
expression_node< T >::node_type type() const
Definition: exprtk.hpp:15291
static bool is_null(const expression< T > &expr)
Definition: exprtk.hpp:18159
bool is_valid(const expression< T > &expr)
Definition: exprtk.hpp:18166
type_store< igeneric_function< T >, igeneric_function< T > > overload_function_store
Definition: exprtk.hpp:16753
std::deque< ptr_t > & deq_
Definition: exprtk.hpp:21066
vector_node_ptr vec() const
Definition: exprtk.hpp:9978
expression_node< T >::node_type type() const
Definition: exprtk.hpp:8831
virtual const T c() const =0
expression_node< T >::node_type type() const
Definition: exprtk.hpp:9838
T nequal(const T v0, const T v1)
Definition: exprtk.hpp:1425
bool is_integer_impl(const T &, int_type_tag)
Definition: exprtk.hpp:1368
expression_node< typename node_type::value_type > * allocate_rc(T1 &t1, const T2 &t2) const
Definition: exprtk.hpp:15630
T atan2(const T v0, const T v1)
Definition: exprtk.hpp:1474
details::repeat_until_loop_bc_node< T > repeat_until_loop_bc_node_t
Definition: exprtk.hpp:18348
T pos_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1337
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:33116
std::string get_stringvar_name(const expression_ptr &ptr) const
Definition: exprtk.hpp:17593
expression_node< T >::node_type type() const
Definition: exprtk.hpp:5794
bool cov_optimisable(const details::operator_type &operation, expression_node_ptr(&branch)[2]) const
Definition: exprtk.hpp:26366
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38261
T acosh_impl(const T, int_type_tag)
Definition: exprtk.hpp:1346
details::assignment_string_node< T > assignment_string_node_t
Definition: exprtk.hpp:18365
std::string to_str(error_mode mode)
Definition: exprtk.hpp:18228
virtual T value(expression_t &e)
Definition: exprtk.hpp:36473
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7287
T ncdf_impl(T v, int_type_tag)
Definition: exprtk.hpp:1276
vector_node_ptr vec() const
Definition: exprtk.hpp:9828
variable_ptr get_variable(const T &var_ref) const
Definition: exprtk.hpp:18830
bool symbol_exists(const std::string &symbol) const
Definition: exprtk.hpp:19033
static const expression_node< T >::node_type result
Definition: exprtk.hpp:13802
vector_interface< T > * ivec_ptr_
Definition: exprtk.hpp:9590
std::size_t error_count() const
Definition: exprtk.hpp:3549
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:38162
bool is_function(const expression_node< T > *node)
Definition: exprtk.hpp:5228
symbol_table_t::vararg_function_ptr vararg_function_ptr
Definition: exprtk.hpp:18766
static T process_2(const Sequence &arg_list)
Definition: exprtk.hpp:12739
bool add_stringvar(const std::string &stringvar_name, std::string &s, const bool is_constant=false)
Definition: exprtk.hpp:17155
details::unary_node< T > unary_node_t
Definition: exprtk.hpp:18337
void disable_has_side_effects(FunctionType &func)
Definition: exprtk.hpp:15958
expression_node< T >::node_type type() const
Definition: exprtk.hpp:11451
T asin_impl(const T, int_type_tag)
Definition: exprtk.hpp:1347
assignment_string_node(const operator_type &opr, expression_ptr branch0, expression_ptr branch1)
Definition: exprtk.hpp:8457
generic_type::parameter_list parameter_list_t
Definition: exprtk.hpp:16102
expression_node_ptr synthesize_csros_expression(const details::operator_type &opr, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:34638
bool zero_return_disabled() const
Definition: exprtk.hpp:19669
expression_node< typename node_type::value_type > * allocate(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8) const
Definition: exprtk.hpp:15738
igfun_t::parameter_list_t parameter_list_t
Definition: exprtk.hpp:37787
details::conditional_node< T > conditional_node_t
Definition: exprtk.hpp:18341
details::functor_t< T > functor_t
Definition: exprtk.hpp:13604
expression< T > expression_t
Definition: exprtk.hpp:18380
bool sf3_optimisable(const std::string &sf3id, trinary_functor_t &tfunc) const
Definition: exprtk.hpp:26154
expression_node_ptr cardinal_pow_optimisation(const T &v, const T &c)
Definition: exprtk.hpp:28575
igfun_t::generic_type generic_type
Definition: exprtk.hpp:38520
T sqrt_impl(const T v, int_type_tag)
Definition: exprtk.hpp:1342
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1)
Definition: exprtk.hpp:30789
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:31219
std::size_t const_size() const
Definition: exprtk.hpp:7050
vec_data_store< T > vds_t
Definition: exprtk.hpp:7126
expression_node< T >::node_type type() const
Definition: exprtk.hpp:10905
bool is_string_node(const expression_node< T > *node)
Definition: exprtk.hpp:15457
std::string type_id() const
Definition: exprtk.hpp:13957
#define token_inserter_empty_body
Definition: exprtk.hpp:3060
const value_ptr const_value_ptr
Definition: exprtk.hpp:5366
expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type &operation, expression_node_ptr(&branch)[2])
Definition: exprtk.hpp:28274
const type_store_t & operator[](const std::size_t &index) const
Definition: exprtk.hpp:4470
std::string str() const
Definition: exprtk.hpp:7636
bool is_boc_node(const expression_node< T > *node)
Definition: exprtk.hpp:15433
static std::string id(expression_generator< Type > &expr_gen, const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
Definition: exprtk.hpp:32024
disabled_entity_set_t disabled_assignment_set_
Definition: exprtk.hpp:20063
const T c() const
Definition: exprtk.hpp:14566
std::vector< symbol_table< T > > symtab_list_t
Definition: exprtk.hpp:17769
static T process_3(const Sequence &arg_list)
Definition: exprtk.hpp:12481
expression_node< T >::node_type type() const
Definition: exprtk.hpp:7414
opr_base< T >::Type Type
Definition: exprtk.hpp:12165
const T c() const
Definition: exprtk.hpp:14611
T atan2_impl(const T, const T, int_type_tag)
Definition: exprtk.hpp:1067
static bool compile_right_impl(expression_generator< Type > &expr_gen, const std::string &id, ExternalType t, expression_node_ptr &node, expression_node_ptr &result)
Definition: exprtk.hpp:29889
bool parse_igeneric_function_params(std::string &param_type_list, std::vector< expression_node_ptr > &arg_list, const std::string &function_name, igeneric_function< T > *function, const type_checker &tc)
Definition: exprtk.hpp:23824
bool is_left_bracket(const char_t c)
Definition: exprtk.hpp:134
disabled_entity_set_t disabled_func_set_
Definition: exprtk.hpp:20059