2 ******************************************************************
3 * C++ Mathematical Expression Toolkit Library *
5 * Author: Arash Partow (1999-2020) *
6 * URL: http://www.partow.net/programming/exprtk/index.html *
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 *
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)] *
29 ******************************************************************
33 #ifndef INCLUDE_EXPRTK_HPP
34 #define INCLUDE_EXPRTK_HPP
61 #ifdef exprtk_enable_debugging
62 #define exprtk_debug(params) printf params
64 #define exprtk_debug(params) (void)0
67 #define exprtk_error_location \
68 "exprtk.hpp:" + details::to_str(__LINE__) \
70 #if defined(__GNUC__) && (__GNUC__ >= 7)
72 #define exprtk_disable_fallthrough_begin \
73 _Pragma ("GCC diagnostic push") \
74 _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
76 #define exprtk_disable_fallthrough_end \
77 _Pragma ("GCC diagnostic pop") \
80 #define exprtk_disable_fallthrough_begin (void)0;
81 #define exprtk_disable_fallthrough_end (void)0;
86 typedef unsigned char uchar_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;
95 inline bool is_whitespace(const char_t c)
97 return (' ' == c) || ('\n' == c) ||
98 ('\r' == c) || ('\t' == c) ||
99 ('\b' == c) || ('\v' == c) ||
103 inline bool is_operator_char(const char_t c)
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) ;
118 inline bool is_letter(const char_t c)
120 return (('a' <= c) && (c <= 'z')) ||
121 (('A' <= c) && (c <= 'Z')) ;
124 inline bool is_digit(const char_t c)
126 return ('0' <= c) && (c <= '9');
129 inline bool is_letter_or_digit(const char_t c)
131 return is_letter(c) || is_digit(c);
134 inline bool is_left_bracket(const char_t c)
136 return ('(' == c) || ('[' == c) || ('{' == c);
139 inline bool is_right_bracket(const char_t c)
141 return (')' == c) || (']' == c) || ('}' == c);
144 inline bool is_bracket(const char_t c)
146 return is_left_bracket(c) || is_right_bracket(c);
149 inline bool is_sign(const char_t c)
151 return ('+' == c) || ('-' == c);
154 inline bool is_invalid(const char_t c)
156 return !is_whitespace (c) &&
157 !is_operator_char(c) &&
167 #ifndef exprtk_disable_caseinsensitivity
168 inline void case_normalise(std::string& s)
170 for (std::size_t i = 0; i < s.size(); ++i)
172 s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
176 inline bool imatch(const char_t c1, const char_t c2)
178 return std::tolower(c1) == std::tolower(c2);
181 inline bool imatch(const std::string& s1, const std::string& s2)
183 if (s1.size() == s2.size())
185 for (std::size_t i = 0; i < s1.size(); ++i)
187 if (std::tolower(s1[i]) != std::tolower(s2[i]))
201 inline bool operator() (const std::string& s1, const std::string& s2) const
203 const std::size_t length = std::min(s1.size(),s2.size());
205 for (std::size_t i = 0; i < length; ++i)
207 const char_t c1 = static_cast<char>(std::tolower(s1[i]));
208 const char_t c2 = static_cast<char>(std::tolower(s2[i]));
216 return s1.size() < s2.size();
221 inline void case_normalise(std::string&)
224 inline bool imatch(const char_t c1, const char_t c2)
229 inline bool imatch(const std::string& s1, const std::string& s2)
236 inline bool operator() (const std::string& s1, const std::string& s2) const
243 inline bool is_valid_sf_symbol(const std::string& symbol)
245 // Special function: $f12 or $F34
246 return (4 == symbol.size()) &&
247 ('$' == symbol[0]) &&
248 imatch('f',symbol[1]) &&
249 is_digit(symbol[2]) &&
253 inline const char_t& front(const std::string& s)
258 inline const char_t& back(const std::string& s)
260 return s[s.size() - 1];
263 inline std::string to_str(int i)
266 return std::string("0");
274 result += '0' + char(-(i % 10));
283 result += '0' + char(i % 10);
287 std::reverse(result.begin(), result.end());
292 inline std::string to_str(std::size_t i)
294 return to_str(static_cast<int>(i));
297 inline bool is_hex_digit(const std::string::value_type digit)
299 return (('0' <= digit) && (digit <= '9')) ||
300 (('A' <= digit) && (digit <= 'F')) ||
301 (('a' <= digit) && (digit <= 'f')) ;
304 inline uchar_t hex_to_bin(uchar_t h)
306 if (('0' <= h) && (h <= '9'))
309 return static_cast<unsigned char>(std::toupper(h) - 'A');
312 template <typename Iterator>
313 inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
317 (end != (itr + 1)) &&
318 (end != (itr + 2)) &&
319 (end != (itr + 3)) &&
322 ('x' == *(itr + 1)) ||
325 (is_hex_digit(*(itr + 2))) &&
326 (is_hex_digit(*(itr + 3)))
329 result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
330 hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
337 inline void cleanup_escapes(std::string& s)
339 typedef std::string::iterator str_itr_t;
341 str_itr_t itr1 = s.begin();
342 str_itr_t itr2 = s.begin();
343 str_itr_t end = s.end ();
345 std::size_t removal_count = 0;
355 else if ('\\' != (*itr1))
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));
380 s.resize(s.size() - removal_count);
387 build_string(const std::size_t& initial_size = 64)
389 data_.reserve(initial_size);
392 inline build_string& operator << (const std::string& s)
398 inline build_string& operator << (char_cptr s)
400 data_ += std::string(s);
404 inline operator std::string () const
409 inline std::string as_string() const
419 static const std::string reserved_words[] =
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",
428 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
430 static const std::string reserved_symbols[] =
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", "&", "|"
447 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
449 static const std::string base_function_list[] =
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"
462 static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
464 static const std::string logic_ops_list[] =
466 "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
469 static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
471 static const std::string cntrl_struct_list[] =
473 "if", "switch", "for", "while", "repeat", "return"
476 static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
478 static const std::string arithmetic_ops_list[] =
480 "+", "-", "*", "/", "%", "^"
483 static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
485 static const std::string assignment_ops_list[] =
491 static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
493 static const std::string inequality_ops_list[] =
500 static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
502 inline bool is_reserved_word(const std::string& symbol)
504 for (std::size_t i = 0; i < reserved_words_size; ++i)
506 if (imatch(symbol, reserved_words[i]))
515 inline bool is_reserved_symbol(const std::string& symbol)
517 for (std::size_t i = 0; i < reserved_symbols_size; ++i)
519 if (imatch(symbol, reserved_symbols[i]))
528 inline bool is_base_function(const std::string& function_name)
530 for (std::size_t i = 0; i < base_function_list_size; ++i)
532 if (imatch(function_name, base_function_list[i]))
541 inline bool is_control_struct(const std::string& cntrl_strct)
543 for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
545 if (imatch(cntrl_strct, cntrl_struct_list[i]))
554 inline bool is_logic_opr(const std::string& lgc_opr)
556 for (std::size_t i = 0; i < logic_ops_list_size; ++i)
558 if (imatch(lgc_opr, logic_ops_list[i]))
569 static inline bool cmp(const char_t c0, const char_t c1)
577 static inline bool cmp(const char_t c0, const char_t c1)
579 return (std::tolower(c0) == std::tolower(c1));
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 )
591 const Iterator null_itr(0);
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;
598 while (d_itr != data_end)
600 if (zero_or_more == *p_itr)
602 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
607 if (pattern_end == p_itr)
610 const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
612 while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
622 else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
624 if (null_itr == tb_d_itr)
637 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
642 return (pattern_end == p_itr);
645 inline bool wc_match(const std::string& wild_card,
646 const std::string& str)
648 return match_impl<char_cptr,cs_match>(wild_card.data(),
649 wild_card.data() + wild_card.size(),
651 str.data() + str.size(),
656 inline bool wc_imatch(const std::string& wild_card,
657 const std::string& str)
659 return match_impl<char_cptr,cis_match>(wild_card.data(),
660 wild_card.data() + wild_card.size(),
662 str.data() + str.size(),
667 inline bool sequence_match(const std::string& pattern,
668 const std::string& str,
669 std::size_t& diff_index,
674 return ("Z" == pattern);
676 else if ('*' == pattern[0])
679 typedef std::string::const_iterator itr_t;
681 itr_t p_itr = pattern.begin();
682 itr_t s_itr = str .begin();
684 itr_t p_end = pattern.end();
685 itr_t s_end = str .end();
687 while ((s_end != s_itr) && (p_end != p_itr))
691 const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
695 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
696 diff_value = static_cast<char>(std::toupper(*p_itr));
703 while (s_itr != s_end)
705 if (target != std::toupper(*s_itr))
715 std::toupper(*p_itr) != std::toupper(*s_itr)
718 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
719 diff_value = static_cast<char>(std::toupper(*p_itr));
737 static const double pow10[] = {
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
745 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
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;
765 struct unknown_type_tag { unknown_type_tag() {} };
766 struct real_type_tag { real_type_tag () {} };
767 struct complex_type_tag { complex_type_tag() {} };
768 struct int_type_tag { int_type_tag () {} };
770 template <typename T>
773 typedef unknown_type_tag type;
777 #define exprtk_register_real_type_tag(T) \
778 template<> struct number_type<T> \
779 { typedef real_type_tag type; number_type() {} }; \
781 #define exprtk_register_complex_type_tag(T) \
782 template<> struct number_type<std::complex<T> > \
783 { typedef complex_type_tag type; number_type() {} }; \
785 #define exprtk_register_int_type_tag(T) \
786 template<> struct number_type<T> \
787 { typedef int_type_tag type; number_type() {} }; \
789 exprtk_register_real_type_tag(double )
790 exprtk_register_real_type_tag(long double)
791 exprtk_register_real_type_tag(float )
793 exprtk_register_complex_type_tag(double )
794 exprtk_register_complex_type_tag(long double)
795 exprtk_register_complex_type_tag(float )
797 exprtk_register_int_type_tag(short )
798 exprtk_register_int_type_tag(int )
799 exprtk_register_int_type_tag(_int64_t )
800 exprtk_register_int_type_tag(unsigned short)
801 exprtk_register_int_type_tag(unsigned int )
802 exprtk_register_int_type_tag(_uint64_t )
804 #undef exprtk_register_real_type_tag
805 #undef exprtk_register_int_type_tag
807 template <typename T>
810 static inline T value()
812 const T epsilon = T(0.0000000001);
818 struct epsilon_type <float>
820 static inline float value()
822 const float epsilon = float(0.000001f);
828 struct epsilon_type <long double>
830 static inline long double value()
832 const long double epsilon = (long double)(0.000000000001);
837 template <typename T>
838 inline bool is_nan_impl(const T v, real_type_tag)
840 return std::not_equal_to<T>()(v,v);
843 template <typename T>
844 inline int to_int32_impl(const T v, real_type_tag)
846 return static_cast<int>(v);
849 template <typename T>
850 inline _int64_t to_int64_impl(const T v, real_type_tag)
852 return static_cast<_int64_t>(v);
855 template <typename T>
856 inline bool is_true_impl(const T v)
858 return std::not_equal_to<T>()(T(0),v);
861 template <typename T>
862 inline bool is_false_impl(const T v)
864 return std::equal_to<T>()(T(0),v);
867 template <typename T>
868 inline T abs_impl(const T v, real_type_tag)
870 return ((v < T(0)) ? -v : v);
873 template <typename T>
874 inline T min_impl(const T v0, const T v1, real_type_tag)
876 return std::min<T>(v0,v1);
879 template <typename T>
880 inline T max_impl(const T v0, const T v1, real_type_tag)
882 return std::max<T>(v0,v1);
885 template <typename T>
886 inline T equal_impl(const T v0, const T v1, real_type_tag)
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);
892 inline float equal_impl(const float v0, const float v1, real_type_tag)
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;
898 template <typename T>
899 inline T equal_impl(const T v0, const T v1, int_type_tag)
901 return (v0 == v1) ? 1 : 0;
904 template <typename T>
905 inline T expm1_impl(const T v, real_type_tag)
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);
911 return std::exp(v) - T(1);
914 template <typename T>
915 inline T expm1_impl(const T v, int_type_tag)
917 return T(std::exp<double>(v)) - T(1);
920 template <typename T>
921 inline T nequal_impl(const T v0, const T v1, real_type_tag)
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);
928 inline float nequal_impl(const float v0, const float v1, real_type_tag)
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;
935 template <typename T>
936 inline T nequal_impl(const T v0, const T v1, int_type_tag)
938 return (v0 != v1) ? 1 : 0;
941 template <typename T>
942 inline T modulus_impl(const T v0, const T v1, real_type_tag)
944 return std::fmod(v0,v1);
947 template <typename T>
948 inline T modulus_impl(const T v0, const T v1, int_type_tag)
953 template <typename T>
954 inline T pow_impl(const T v0, const T v1, real_type_tag)
956 return std::pow(v0,v1);
959 template <typename T>
960 inline T pow_impl(const T v0, const T v1, int_type_tag)
962 return std::pow(static_cast<double>(v0),static_cast<double>(v1));
965 template <typename T>
966 inline T logn_impl(const T v0, const T v1, real_type_tag)
968 return std::log(v0) / std::log(v1);
971 template <typename T>
972 inline T logn_impl(const T v0, const T v1, int_type_tag)
974 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
977 template <typename T>
978 inline T log1p_impl(const T v, real_type_tag)
982 if (abs_impl(v,real_type_tag()) > T(0.0001))
984 return std::log(T(1) + v);
987 return (T(-0.5) * v + T(1)) * v;
990 return std::numeric_limits<T>::quiet_NaN();
993 template <typename T>
994 inline T log1p_impl(const T v, int_type_tag)
998 return std::log(T(1) + v);
1001 return std::numeric_limits<T>::quiet_NaN();
1004 template <typename T>
1005 inline T root_impl(const T v0, const T v1, real_type_tag)
1008 return std::numeric_limits<T>::quiet_NaN();
1010 const std::size_t n = static_cast<std::size_t>(v1);
1012 if ((v0 < T(0)) && (0 == (n % 2)))
1013 return std::numeric_limits<T>::quiet_NaN();
1015 return std::pow(v0, T(1) / n);
1018 template <typename T>
1019 inline T root_impl(const T v0, const T v1, int_type_tag)
1021 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1024 template <typename T>
1025 inline T round_impl(const T v, real_type_tag)
1027 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1030 template <typename T>
1031 inline T roundn_impl(const T v0, const T v1, real_type_tag)
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]);
1037 return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1039 return T(std::floor((v0 * p10) + T(0.5)) / p10);
1042 template <typename T>
1043 inline T roundn_impl(const T v0, const T, int_type_tag)
1048 template <typename T>
1049 inline T hypot_impl(const T v0, const T v1, real_type_tag)
1051 return std::sqrt((v0 * v0) + (v1 * v1));
1054 template <typename T>
1055 inline T hypot_impl(const T v0, const T v1, int_type_tag)
1057 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1060 template <typename T>
1061 inline T atan2_impl(const T v0, const T v1, real_type_tag)
1063 return std::atan2(v0,v1);
1066 template <typename T>
1067 inline T atan2_impl(const T, const T, int_type_tag)
1072 template <typename T>
1073 inline T shr_impl(const T v0, const T v1, real_type_tag)
1075 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1078 template <typename T>
1079 inline T shr_impl(const T v0, const T v1, int_type_tag)
1084 template <typename T>
1085 inline T shl_impl(const T v0, const T v1, real_type_tag)
1087 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1090 template <typename T>
1091 inline T shl_impl(const T v0, const T v1, int_type_tag)
1096 template <typename T>
1097 inline T sgn_impl(const T v, real_type_tag)
1099 if (v > T(0)) return T(+1);
1100 else if (v < T(0)) return T(-1);
1104 template <typename T>
1105 inline T sgn_impl(const T v, int_type_tag)
1107 if (v > T(0)) return T(+1);
1108 else if (v < T(0)) return T(-1);
1112 template <typename T>
1113 inline T and_impl(const T v0, const T v1, real_type_tag)
1115 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1118 template <typename T>
1119 inline T and_impl(const T v0, const T v1, int_type_tag)
1124 template <typename T>
1125 inline T nand_impl(const T v0, const T v1, real_type_tag)
1127 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1130 template <typename T>
1131 inline T nand_impl(const T v0, const T v1, int_type_tag)
1136 template <typename T>
1137 inline T or_impl(const T v0, const T v1, real_type_tag)
1139 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1142 template <typename T>
1143 inline T or_impl(const T v0, const T v1, int_type_tag)
1148 template <typename T>
1149 inline T nor_impl(const T v0, const T v1, real_type_tag)
1151 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1154 template <typename T>
1155 inline T nor_impl(const T v0, const T v1, int_type_tag)
1160 template <typename T>
1161 inline T xor_impl(const T v0, const T v1, real_type_tag)
1163 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1166 template <typename T>
1167 inline T xor_impl(const T v0, const T v1, int_type_tag)
1172 template <typename T>
1173 inline T xnor_impl(const T v0, const T v1, real_type_tag)
1175 const bool v0_true = is_true_impl(v0);
1176 const bool v1_true = is_true_impl(v1);
1178 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1184 template <typename T>
1185 inline T xnor_impl(const T v0, const T v1, int_type_tag)
1187 const bool v0_true = is_true_impl(v0);
1188 const bool v1_true = is_true_impl(v1);
1190 if ((v0_true && v1_true) || (!v0_true && !v1_true))
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); } \
1200 exprtk_define_erf( float,::erff)
1201 exprtk_define_erf( double,::erf )
1202 exprtk_define_erf(long double,::erfl)
1203 #undef exprtk_define_erf
1206 template <typename T>
1207 inline T erf_impl(T v, real_type_tag)
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)
1219 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
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]))))))))));
1228 return (v >= T(0)) ? result : -result;
1234 template <typename T>
1235 inline T erf_impl(T v, int_type_tag)
1237 return erf_impl(static_cast<double>(v),real_type_tag());
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); } \
1244 exprtk_define_erfc( float,::erfcf)
1245 exprtk_define_erfc( double,::erfc )
1246 exprtk_define_erfc(long double,::erfcl)
1247 #undef exprtk_define_erfc
1250 template <typename T>
1251 inline T erfc_impl(T v, real_type_tag)
1253 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1254 return T(1) - erf_impl(v,real_type_tag());
1256 return erfc_impl(v);
1260 template <typename T>
1261 inline T erfc_impl(T v, int_type_tag)
1263 return erfc_impl(static_cast<double>(v),real_type_tag());
1266 template <typename T>
1267 inline T ncdf_impl(T v, real_type_tag)
1269 T cnd = T(0.5) * (T(1) + erf_impl(
1270 abs_impl(v,real_type_tag()) /
1271 T(numeric::constant::sqrt2),real_type_tag()));
1272 return (v < T(0)) ? (T(1) - cnd) : cnd;
1275 template <typename T>
1276 inline T ncdf_impl(T v, int_type_tag)
1278 return ncdf_impl(static_cast<double>(v),real_type_tag());
1281 template <typename T>
1282 inline T sinc_impl(T v, real_type_tag)
1284 if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1285 return(std::sin(v) / v);
1290 template <typename T>
1291 inline T sinc_impl(T v, int_type_tag)
1293 return sinc_impl(static_cast<double>(v),real_type_tag());
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)); }
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); }
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(); }
1361 template <typename T>
1362 inline bool is_integer_impl(const T& v, real_type_tag)
1364 return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1367 template <typename T>
1368 inline bool is_integer_impl(const T&, int_type_tag)
1374 template <typename Type>
1375 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
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}; };
1382 template <typename T>
1383 inline int to_int32(const T v)
1385 const typename details::number_type<T>::type num_type;
1386 return to_int32_impl(v, num_type);
1389 template <typename T>
1390 inline _int64_t to_int64(const T v)
1392 const typename details::number_type<T>::type num_type;
1393 return to_int64_impl(v, num_type);
1396 template <typename T>
1397 inline bool is_nan(const T v)
1399 const typename details::number_type<T>::type num_type;
1400 return is_nan_impl(v, num_type);
1403 template <typename T>
1404 inline T min(const T v0, const T v1)
1406 const typename details::number_type<T>::type num_type;
1407 return min_impl(v0, v1, num_type);
1410 template <typename T>
1411 inline T max(const T v0, const T v1)
1413 const typename details::number_type<T>::type num_type;
1414 return max_impl(v0, v1, num_type);
1417 template <typename T>
1418 inline T equal(const T v0, const T v1)
1420 const typename details::number_type<T>::type num_type;
1421 return equal_impl(v0, v1, num_type);
1424 template <typename T>
1425 inline T nequal(const T v0, const T v1)
1427 const typename details::number_type<T>::type num_type;
1428 return nequal_impl(v0, v1, num_type);
1431 template <typename T>
1432 inline T modulus(const T v0, const T v1)
1434 const typename details::number_type<T>::type num_type;
1435 return modulus_impl(v0, v1, num_type);
1438 template <typename T>
1439 inline T pow(const T v0, const T v1)
1441 const typename details::number_type<T>::type num_type;
1442 return pow_impl(v0, v1, num_type);
1445 template <typename T>
1446 inline T logn(const T v0, const T v1)
1448 const typename details::number_type<T>::type num_type;
1449 return logn_impl(v0, v1, num_type);
1452 template <typename T>
1453 inline T root(const T v0, const T v1)
1455 const typename details::number_type<T>::type num_type;
1456 return root_impl(v0, v1, num_type);
1459 template <typename T>
1460 inline T roundn(const T v0, const T v1)
1462 const typename details::number_type<T>::type num_type;
1463 return roundn_impl(v0, v1, num_type);
1466 template <typename T>
1467 inline T hypot(const T v0, const T v1)
1469 const typename details::number_type<T>::type num_type;
1470 return hypot_impl(v0, v1, num_type);
1473 template <typename T>
1474 inline T atan2(const T v0, const T v1)
1476 const typename details::number_type<T>::type num_type;
1477 return atan2_impl(v0, v1, num_type);
1480 template <typename T>
1481 inline T shr(const T v0, const T v1)
1483 const typename details::number_type<T>::type num_type;
1484 return shr_impl(v0, v1, num_type);
1487 template <typename T>
1488 inline T shl(const T v0, const T v1)
1490 const typename details::number_type<T>::type num_type;
1491 return shl_impl(v0, v1, num_type);
1494 template <typename T>
1495 inline T and_opr(const T v0, const T v1)
1497 const typename details::number_type<T>::type num_type;
1498 return and_impl(v0, v1, num_type);
1501 template <typename T>
1502 inline T nand_opr(const T v0, const T v1)
1504 const typename details::number_type<T>::type num_type;
1505 return nand_impl(v0, v1, num_type);
1508 template <typename T>
1509 inline T or_opr(const T v0, const T v1)
1511 const typename details::number_type<T>::type num_type;
1512 return or_impl(v0, v1, num_type);
1515 template <typename T>
1516 inline T nor_opr(const T v0, const T v1)
1518 const typename details::number_type<T>::type num_type;
1519 return nor_impl(v0, v1, num_type);
1522 template <typename T>
1523 inline T xor_opr(const T v0, const T v1)
1525 const typename details::number_type<T>::type num_type;
1526 return xor_impl(v0, v1, num_type);
1529 template <typename T>
1530 inline T xnor_opr(const T v0, const T v1)
1532 const typename details::number_type<T>::type num_type;
1533 return xnor_impl(v0, v1, num_type);
1536 template <typename T>
1537 inline bool is_integer(const T v)
1539 const typename details::number_type<T>::type num_type;
1540 return is_integer_impl(v, num_type);
1543 template <typename T, unsigned int N>
1546 static inline T result(T v)
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); } };
1579 #define exprtk_define_unary_function(FunctionName) \
1580 template <typename T> \
1581 inline T FunctionName (const T v) \
1583 const typename details::number_type<T>::type num_type; \
1584 return FunctionName##_impl(v,num_type); \
1587 exprtk_define_unary_function(abs )
1588 exprtk_define_unary_function(acos )
1589 exprtk_define_unary_function(acosh)
1590 exprtk_define_unary_function(asin )
1591 exprtk_define_unary_function(asinh)
1592 exprtk_define_unary_function(atan )
1593 exprtk_define_unary_function(atanh)
1594 exprtk_define_unary_function(ceil )
1595 exprtk_define_unary_function(cos )
1596 exprtk_define_unary_function(cosh )
1597 exprtk_define_unary_function(exp )
1598 exprtk_define_unary_function(expm1)
1599 exprtk_define_unary_function(floor)
1600 exprtk_define_unary_function(log )
1601 exprtk_define_unary_function(log10)
1602 exprtk_define_unary_function(log2 )
1603 exprtk_define_unary_function(log1p)
1604 exprtk_define_unary_function(neg )
1605 exprtk_define_unary_function(pos )
1606 exprtk_define_unary_function(round)
1607 exprtk_define_unary_function(sin )
1608 exprtk_define_unary_function(sinc )
1609 exprtk_define_unary_function(sinh )
1610 exprtk_define_unary_function(sqrt )
1611 exprtk_define_unary_function(tan )
1612 exprtk_define_unary_function(tanh )
1613 exprtk_define_unary_function(cot )
1614 exprtk_define_unary_function(sec )
1615 exprtk_define_unary_function(csc )
1616 exprtk_define_unary_function(r2d )
1617 exprtk_define_unary_function(d2r )
1618 exprtk_define_unary_function(d2g )
1619 exprtk_define_unary_function(g2d )
1620 exprtk_define_unary_function(notl )
1621 exprtk_define_unary_function(sgn )
1622 exprtk_define_unary_function(erf )
1623 exprtk_define_unary_function(erfc )
1624 exprtk_define_unary_function(ncdf )
1625 exprtk_define_unary_function(frac )
1626 exprtk_define_unary_function(trunc)
1627 #undef exprtk_define_unary_function
1630 template <typename T>
1631 inline T compute_pow10(T d, const int exponent)
1633 static const double fract10[] =
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
1669 static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1671 const int e = std::abs(exponent);
1673 if (exponent >= std::numeric_limits<T>::min_exponent10)
1675 if (e < fract10_size)
1678 return T(d * fract10[e]);
1680 return T(d / fract10[e]);
1683 return T(d * std::pow(10.0, 10.0 * exponent));
1687 d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1688 return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1692 template <typename Iterator, typename T>
1693 inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1698 const bool negative = ('-' == (*itr));
1700 if (negative || ('+' == (*itr)))
1706 static const uchar_t zero = static_cast<uchar_t>('0');
1708 while ((end != itr) && (zero == (*itr))) ++itr;
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));
1716 exprtk_disable_fallthrough_begin
1719 #ifdef exprtk_use_lut
1721 #define exprtk_process_digit \
1722 if ((digit = details::digit_table[(int)*itr++]) < 10) \
1723 result = result * 10 + (digit); \
1726 return_result = false; \
1732 #define exprtk_process_digit \
1733 if ((digit = (*itr++ - zero)) < 10) \
1734 result = result * T(10) + digit; \
1737 return_result = false; \
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; }
1748 #undef exprtk_process_digit
1750 exprtk_disable_fallthrough_end
1753 return_result = false;
1755 if (length && return_result)
1757 result = result * 10 + static_cast<T>(digit);
1761 result = negative ? -result : result;
1762 return return_result;
1765 template <typename Iterator, typename T>
1766 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1768 typedef typename std::iterator_traits<Iterator>::value_type type;
1770 static const std::size_t nan_length = 3;
1772 if (std::distance(itr,end) != static_cast<int>(nan_length))
1775 if (static_cast<type>('n') == (*itr))
1778 (static_cast<type>('a') != *(itr + 1)) ||
1779 (static_cast<type>('n') != *(itr + 2))
1786 (static_cast<type>('A') != *(itr + 1)) ||
1787 (static_cast<type>('N') != *(itr + 2))
1793 t = std::numeric_limits<T>::quiet_NaN();
1798 template <typename Iterator, typename T>
1799 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
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;
1805 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1807 if ((3 != length) && (inf_length != length))
1810 char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1814 if (*inf_itr == static_cast<char>(*itr))
1825 t = -std::numeric_limits<T>::infinity();
1827 t = std::numeric_limits<T>::infinity();
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)
1835 if (end == itr_external) return false;
1837 Iterator itr = itr_external;
1841 const bool negative = ('-' == (*itr));
1843 if (negative || '+' == (*itr))
1849 bool instate = false;
1851 static const char_t zero = static_cast<uchar_t>('0');
1853 #define parse_digit_1(d) \
1854 if ((digit = (*itr - zero)) < 10) \
1855 { d = d * T(10) + digit; } \
1858 if (end == ++itr) break; \
1860 #define parse_digit_2(d) \
1861 if ((digit = (*itr - zero)) < 10) \
1862 { d = d * T(10) + digit; } \
1868 const Iterator curr = itr;
1870 while ((end != itr) && (zero == (*itr))) ++itr;
1876 // Note: For 'physical' superscalar architectures it
1877 // is advised that the following loop be: 4xPD1 and 1xPD2
1878 #ifdef exprtk_enable_superscalar
1887 if (curr != itr) instate = true;
1896 const Iterator curr = ++itr;
1902 #ifdef exprtk_enable_superscalar
1903 parse_digit_1(tmp_d)
1904 parse_digit_1(tmp_d)
1905 parse_digit_1(tmp_d)
1907 parse_digit_1(tmp_d)
1908 parse_digit_1(tmp_d)
1909 parse_digit_2(tmp_d)
1915 d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
1918 #undef parse_digit_1
1919 #undef parse_digit_2
1924 typename std::iterator_traits<Iterator>::value_type c = (*itr);
1926 if (('e' == c) || ('E' == c))
1930 if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1943 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1949 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1951 if (('i' == (*itr)) || ('I' == (*itr)))
1953 return parse_inf(itr, end, t, negative);
1955 else if (('n' == (*itr)) || ('N' == (*itr)))
1957 return parse_nan(itr, end, t);
1965 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1967 if (('i' == (*itr)) || ('I' == (*itr)))
1969 return parse_inf(itr, end, t, negative);
1971 else if (('n' == (*itr)) || ('N' == (*itr)))
1973 return parse_nan(itr, end, t);
1984 if ((end != itr) || (!instate))
1987 d = compute_pow10(d,exponent);
1989 t = static_cast<T>((negative) ? -d : d);
1993 template <typename T>
1994 inline bool string_to_real(const std::string& s, T& t)
1996 const typename numeric::details::number_type<T>::type num_type;
1998 char_cptr begin = s.data();
1999 char_cptr end = s.data() + s.size();
2001 return string_to_real(begin, end, t, num_type);
2004 template <typename T>
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.
2013 //typedef const T Type;
2014 typedef const T& Type;
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);
2022 } // namespace details
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 = ':',
2049 position(std::numeric_limits<std::size_t>::max())
2056 position = std::numeric_limits<std::size_t>::max();
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))
2065 value.assign(begin,end);
2067 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2071 template <typename Iterator>
2072 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2075 value.assign(begin,end);
2077 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2081 template <typename Iterator>
2082 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2085 value.assign(begin,end);
2087 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2091 template <typename Iterator>
2092 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2095 value.assign(begin,end);
2097 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2101 inline token& set_string(const std::string& s, const std::size_t p)
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))
2116 (e_err_symbol == et) ||
2117 (e_err_number == et) ||
2118 (e_err_string == et) ||
2127 value.assign(begin,end);
2130 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2135 static inline std::string to_str(token_type t)
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";
2182 inline bool is_error() const
2185 (e_error == type) ||
2186 (e_err_symbol == type) ||
2187 (e_err_number == type) ||
2188 (e_err_string == type) ||
2189 (e_err_sfunc == type)
2195 std::size_t position;
2202 typedef token token_t;
2203 typedef std::vector<token_t> token_list_t;
2204 typedef std::vector<token_t>::iterator token_list_itr_t;
2205 typedef details::char_t char_t;
2220 token_list_.clear();
2221 token_itr_ = token_list_.end();
2222 store_token_itr_ = token_list_.end();
2225 inline bool process(const std::string& str)
2227 base_itr_ = str.data();
2228 s_itr_ = str.data();
2229 s_end_ = str.data() + str.size();
2231 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2232 token_list_.clear();
2234 while (!is_end(s_itr_))
2238 if (!token_list_.empty() && token_list_.back().is_error())
2245 inline bool empty() const
2247 return token_list_.empty();
2250 inline std::size_t size() const
2252 return token_list_.size();
2257 token_itr_ = token_list_.begin();
2258 store_token_itr_ = token_list_.begin();
2263 store_token_itr_ = token_itr_;
2266 inline void restore()
2268 token_itr_ = store_token_itr_;
2271 inline token_t& next_token()
2273 if (token_list_.end() != token_itr_)
2275 return *token_itr_++;
2281 inline token_t& peek_next_token()
2283 if (token_list_.end() != token_itr_)
2291 inline token_t& operator[](const std::size_t& index)
2293 if (index < token_list_.size())
2294 return token_list_[index];
2299 inline token_t operator[](const std::size_t& index) const
2301 if (index < token_list_.size())
2302 return token_list_[index];
2307 inline bool finished() const
2309 return (token_list_.end() == token_itr_);
2312 inline void insert_front(token_t::token_type tk_type)
2315 !token_list_.empty() &&
2316 (token_list_.end() != token_itr_)
2319 token_t t = *token_itr_;
2322 token_itr_ = token_list_.insert(token_itr_,t);
2326 inline std::string substr(const std::size_t& begin, const std::size_t& end)
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_;
2331 return std::string(begin_itr,end_itr);
2334 inline std::string remaining() const
2338 else if (token_list_.begin() != token_itr_)
2339 return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2341 return std::string(base_itr_ + token_itr_->position, s_end_);
2346 inline bool is_end(details::char_cptr itr)
2348 return (s_end_ == itr);
2351 inline bool is_comment_start(details::char_cptr itr)
2353 #ifndef exprtk_disable_comments
2354 const char_t c0 = *(itr + 0);
2355 const char_t c1 = *(itr + 1);
2359 else if (!is_end(itr + 1))
2361 if (('/' == c0) && ('/' == c1)) return true;
2362 if (('/' == c0) && ('*' == c1)) return true;
2368 inline void skip_whitespace()
2370 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2376 inline void skip_comments()
2378 #ifndef exprtk_disable_comments
2379 // The following comment styles are supported:
2385 static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2388 if ('#' == c0) { mode = 1; incr = 1; }
2391 if ('/' == c1) { mode = 1; incr = 2; }
2392 else if ('*' == c1) { mode = 2; incr = 2; }
2397 static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2400 ((1 == mode) && ('\n' == c0)) ||
2401 ((2 == mode) && ( '*' == c0) && ('/' == c1))
2417 else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2420 details::char_cptr cmt_start = s_itr_;
2422 s_itr_ += increment;
2424 while (!is_end(s_itr_))
2426 if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2434 if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2447 t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2448 token_list_.push_back(t);
2453 inline void scan_token()
2455 if (details::is_whitespace(*s_itr_))
2460 else if (is_comment_start(s_itr_))
2465 else if (details::is_operator_char(*s_itr_))
2470 else if (details::is_letter(*s_itr_))
2475 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2480 else if ('$' == (*s_itr_))
2482 scan_special_function();
2485 #ifndef exprtk_disable_string_capabilities
2486 else if ('\'' == (*s_itr_))
2492 else if ('~' == (*s_itr_))
2495 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2496 token_list_.push_back(t);
2503 t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2504 token_list_.push_back(t);
2509 inline void scan_operator()
2513 const char_t c0 = s_itr_[0];
2515 if (!is_end(s_itr_ + 1))
2517 const char_t c1 = s_itr_[1];
2519 if (!is_end(s_itr_ + 2))
2521 const char_t c2 = s_itr_[2];
2523 if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2525 t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2526 token_list_.push_back(t);
2532 token_t::token_type ttype = token_t::e_none;
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;
2548 if (token_t::e_none != ttype)
2550 t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2551 token_list_.push_back(t);
2558 t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2560 t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2562 t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2564 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2566 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2568 t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2570 token_list_.push_back(t);
2574 inline void scan_symbol()
2576 details::char_cptr initial_itr = s_itr_;
2578 while (!is_end(s_itr_))
2580 if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2582 if ('.' != (*s_itr_))
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 +,-,*,/...>
2590 (s_itr_ != initial_itr) &&
2591 !is_end(s_itr_ + 1) &&
2592 !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2593 ('_' != (*(s_itr_ + 1)))
2602 t.set_symbol(initial_itr,s_itr_,base_itr_);
2603 token_list_.push_back(t);
2606 inline void scan_number()
2609 Attempt to match a valid numeric value in one of the following formats:
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;
2634 while (!is_end(s_itr_))
2636 if ('.' == (*s_itr_))
2640 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2641 token_list_.push_back(t);
2650 else if ('e' == std::tolower(*s_itr_))
2652 const char_t& c = *(s_itr_ + 1);
2654 if (is_end(s_itr_ + 1))
2656 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2657 token_list_.push_back(t);
2664 !details::is_digit(c)
2667 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2668 token_list_.push_back(t);
2678 else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2680 if (post_e_sign_found)
2682 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2683 token_list_.push_back(t);
2688 post_e_sign_found = true;
2693 else if (e_found && details::is_digit(*s_itr_))
2695 post_e_digit_found = true;
2700 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2706 t.set_numeric(initial_itr, s_itr_, base_itr_);
2707 token_list_.push_back(t);
2712 inline void scan_special_function()
2714 details::char_cptr initial_itr = s_itr_;
2717 // $fdd(x,x,x) = at least 11 chars
2718 if (std::distance(s_itr_,s_end_) < 11)
2720 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2721 token_list_.push_back(t);
2727 !(('$' == *s_itr_) &&
2728 (details::imatch ('f',*(s_itr_ + 1))) &&
2729 (details::is_digit(*(s_itr_ + 2))) &&
2730 (details::is_digit(*(s_itr_ + 3))))
2733 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2734 token_list_.push_back(t);
2739 s_itr_ += 4; // $fdd = 4chars
2741 t.set_symbol(initial_itr, s_itr_, base_itr_);
2742 token_list_.push_back(t);
2747 #ifndef exprtk_disable_string_capabilities
2748 inline void scan_string()
2750 details::char_cptr initial_itr = s_itr_ + 1;
2753 if (std::distance(s_itr_,s_end_) < 2)
2755 t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2756 token_list_.push_back(t);
2762 bool escaped_found = false;
2763 bool escaped = false;
2765 while (!is_end(s_itr_))
2767 if (!escaped && ('\\' == *s_itr_))
2769 escaped_found = true;
2777 if ('\'' == *s_itr_)
2782 if (!is_end(s_itr_) && ('0' == *(s_itr_)))
2785 Note: The following 'awkward' conditional is
2786 due to various broken msvc compilers.
2788 #if defined(_MSC_VER) && (_MSC_VER == 1600)
2789 const bool within_range = !is_end(s_itr_ + 2) &&
2790 !is_end(s_itr_ + 3) ;
2792 const bool within_range = !is_end(s_itr_ + 1) &&
2793 !is_end(s_itr_ + 2) &&
2794 !is_end(s_itr_ + 3) ;
2797 const bool x_seperator = ('x' == *(s_itr_ + 1)) ||
2798 ('X' == *(s_itr_ + 1)) ;
2800 const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2801 details::is_hex_digit(*(s_itr_ + 3)) ;
2803 if (!within_range || !x_seperator || !both_digits)
2805 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2806 token_list_.push_back(t);
2822 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2823 token_list_.push_back(t);
2829 t.set_string(initial_itr, s_itr_, base_itr_);
2832 std::string parsed_string(initial_itr,s_itr_);
2834 details::cleanup_escapes(parsed_string);
2838 static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2841 token_list_.push_back(t);
2850 token_list_t token_list_;
2851 token_list_itr_t token_itr_;
2852 token_list_itr_t store_token_itr_;
2854 details::char_cptr base_itr_;
2855 details::char_cptr s_itr_;
2856 details::char_cptr s_end_;
2858 friend class token_scanner;
2859 friend class token_modifier;
2860 friend class token_inserter;
2861 friend class token_joiner;
2864 class helper_interface
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() { }
2875 class token_scanner : public helper_interface
2879 virtual ~token_scanner()
2882 explicit token_scanner(const std::size_t& stride)
2887 throw std::invalid_argument("token_scanner() - Invalid stride value");
2891 inline std::size_t process(generator& g)
2893 if (g.token_list_.size() >= stride_)
2895 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2903 const token& t0 = g.token_list_[i];
2905 if (!operator()(t0))
2914 const token& t0 = g.token_list_[i ];
2915 const token& t1 = g.token_list_[i + 1];
2917 if (!operator()(t0, t1))
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];
2930 if (!operator()(t0, t1, t2))
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];
2944 if (!operator()(t0, t1, t2, t3))
2954 return (g.token_list_.size() - stride_ + 1);
2957 virtual bool operator() (const token&)
2962 virtual bool operator() (const token&, const token&)
2967 virtual bool operator() (const token&, const token&, const token&)
2972 virtual bool operator() (const token&, const token&, const token&, const token&)
2979 const std::size_t stride_;
2982 class token_modifier : public helper_interface
2986 inline std::size_t process(generator& g)
2988 std::size_t changes = 0;
2990 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
2992 if (modify(g.token_list_[i])) changes++;
2998 virtual bool modify(token& t) = 0;
3001 class token_inserter : public helper_interface
3005 explicit token_inserter(const std::size_t& stride)
3010 throw std::invalid_argument("token_inserter() - Invalid stride value");
3014 inline std::size_t process(generator& g)
3016 if (g.token_list_.empty())
3018 else if (g.token_list_.size() < stride_)
3021 std::size_t changes = 0;
3023 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3025 int insert_index = -1;
3030 case 1 : insert_index = insert(g.token_list_[i],t);
3033 case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3036 case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
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);
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);
3046 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3048 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3050 g.token_list_.insert(
3051 g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
3060 #define token_inserter_empty_body \
3065 inline virtual int insert(const token&, token&)
3066 token_inserter_empty_body
3068 inline virtual int insert(const token&, const token&, token&)
3069 token_inserter_empty_body
3071 inline virtual int insert(const token&, const token&, const token&, token&)
3072 token_inserter_empty_body
3074 inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3075 token_inserter_empty_body
3077 inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3078 token_inserter_empty_body
3080 #undef token_inserter_empty_body
3084 const std::size_t stride_;
3087 class token_joiner : public helper_interface
3091 explicit token_joiner(const std::size_t& stride)
3095 inline std::size_t process(generator& g)
3097 if (g.token_list_.empty())
3102 case 2 : return process_stride_2(g);
3103 case 3 : return process_stride_3(g);
3108 virtual bool join(const token&, const token&, token&) { return false; }
3109 virtual bool join(const token&, const token&, const token&, token&) { return false; }
3113 inline std::size_t process_stride_2(generator& g)
3115 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3117 if (g.token_list_.size() < 2)
3120 std::size_t changes = 0;
3122 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3126 while (join(g[i], g[i + 1], t))
3128 g.token_list_[i] = t;
3130 g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
3134 if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
3142 inline std::size_t process_stride_3(generator& g)
3144 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3146 if (g.token_list_.size() < 3)
3149 std::size_t changes = 0;
3151 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3155 while (join(g[i], g[i + 1], g[i + 2], t))
3157 g.token_list_[i] = t;
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));
3163 if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
3171 const std::size_t stride_;
3177 inline void dump(lexer::generator& generator)
3179 for (std::size_t i = 0; i < generator.size(); ++i)
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(),
3190 class commutative_inserter : public lexer::token_inserter
3194 using lexer::token_inserter::insert;
3196 commutative_inserter()
3197 : lexer::token_inserter(2)
3200 inline void ignore_symbol(const std::string& symbol)
3202 ignore_set_.insert(symbol);
3205 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3208 new_token.type = lexer::token::e_mul;
3209 new_token.value = "*";
3210 new_token.position = t1.position;
3212 if (t0.type == lexer::token::e_symbol)
3214 if (ignore_set_.end() != ignore_set_.find(t0.value))
3218 else if (!t0.value.empty() && ('$' == t0.value[0]))
3224 if (t1.type == lexer::token::e_symbol)
3226 if (ignore_set_.end() != ignore_set_.find(t1.value))
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;
3244 return (match) ? 1 : -1;
3249 std::set<std::string,details::ilesscompare> ignore_set_;
3252 class operator_joiner : public token_joiner
3256 explicit operator_joiner(const std::size_t& stride)
3257 : token_joiner(stride)
3260 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3263 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3265 t.type = lexer::token::e_assign;
3267 t.position = t0.position;
3272 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3274 t.type = lexer::token::e_addass;