/exprtk.hpp
C++ Header | 8207 lines | 7224 code | 873 blank | 110 comment | 1334 complexity | c5a4ad74bc8e61645a0da25ec83d8579 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- ****************************************************************
- * C++ Mathematical Expression Toolkit Library *
- * *
- * Author: Arash Partow (1999-2012) *
- * URL: http://www.partow.net/programming/exprtk/index.html *
- * *
- * Copyright notice: *
- * Free use of the C++ Mathematical Expression Toolkit Library *
- * is permitted under the guidelines and in accordance with the *
- * most current version of the Common Public License. *
- * http://www.opensource.org/licenses/cpl1.0.php *
- * *
- * Example expressions: *
- * (00) (y+x/y)*(x-y/x) *
- * (01) (x^2/sin(2*pi/y))-x/2 *
- * (02) sqrt(1-(x^2)) *
- * (03) 1-sin(2*x)+cos(pi/y) *
- * (04) a*exp(2*t)+c *
- * (05) if(((x+2)==3)and((y+5)<=9),1+w,2/z) *
- * (06) if(avg(x,y)<=x+y,x-y,x*y)+2*pi/x *
- * (07) z:=x+sin(2*pi/y) *
- * (08) u:=2*(pi*z)/(w:=x+cos(y/pi)) *
- * (09) clamp(-1,sin(2*pi*x)+cos(y/2*pi),+1) *
- * (10) inrange(-2,m,+2)==if(({-2<=m}and[m<=+2]),1,0) *
- * (11) (12.34sin(x)cos(2y)7+1)==(12.34*sin(x)*cos(2*y)*7+1) *
- * (12) (x ilike 's*ri?g') and [y<(3z^7+w)] *
- * *
- ****************************************************************
- */
- #ifndef INCLUDE_EXPRTK_HPP
- #define INCLUDE_EXPRTK_HPP
- #include <cctype>
- #include <iostream>
- #include <string>
- #include <algorithm>
- #include <cmath>
- #include <limits>
- #include <deque>
- #include <list>
- #include <map>
- #include <set>
- #include <stack>
- #define exprtk_lean_and_mean
- #ifdef exprtk_lean_and_mean_numeric_only
- #ifndef exprtk_lean_and_mean
- #define exprtk_lean_and_mean
- #endif
- #ifndef exprtk_disable_string_capabilities
- #define exprtk_disable_string_capabilities
- #endif
- #endif
- #ifdef exprtk_lean_and_mean
- #ifndef exprtk_disable_extended_operator_optimizations
- #define exprtk_disable_extended_operator_optimizations
- #endif
- #ifndef exprtk_disable_extended_optimisations
- #define exprtk_disable_extended_optimisations
- #endif
- #endif
- namespace exprtk
- {
- namespace details
- {
- inline bool is_whitespace(const char& c)
- {
- return (' ' == c) ||
- ('\n' == c) ||
- ('\r' == c) ||
- ('\t' == c) ||
- ('\b' == c);
- }
- inline bool is_operator_char(const char& c)
- {
- return ('+' == c) || ('-' == c) ||
- ('*' == c) || ('/' == c) ||
- ('^' == c) || ('<' == c) ||
- ('>' == c) || ('=' == c) ||
- (',' == c) || ('!' == c) ||
- ('(' == c) || (')' == c) ||
- ('[' == c) || (']' == c) ||
- ('{' == c) || ('}' == c) ||
- ('%' == c) || (':' == c) ||
- ('?' == c);
- }
- inline bool is_letter(const char c)
- {
- return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
- }
- inline bool is_digit(const char c)
- {
- return ('0' <= c) && (c <= '9');
- }
- inline bool is_left_bracket(const char c)
- {
- return ('(' == c) || ('[' == c) || ('{' == c);
- }
- inline bool is_right_bracket(const char c)
- {
- return (')' == c) || (']' == c) || ('}' == c);
- }
- inline bool is_sign(const char c)
- {
- return ('+' == c) || ('-' == c);
- }
- inline bool is_invalid(const char& c)
- {
- return !is_whitespace(c) &&
- !is_operator_char(c) &&
- !is_letter(c) &&
- !is_digit(c) &&
- ('.' != c) &&
- ('_' != c) &&
- ('$' != c) &&
- ('\'' != c);
- }
- inline bool imatch(const char& c1, const char& c2)
- {
- return std::tolower(c1) == std::tolower(c2);
- }
- inline bool imatch(const std::string& s1, const std::string& s2)
- {
- if (s1.size() == s2.size())
- {
- for (std::size_t i = 0; i < s1.size(); ++i)
- {
- if (std::tolower(s1[i]) != std::tolower(s2[i]))
- {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- static const std::string reserved_words[] =
- {
- "and", "false", "for", "if", "ilike", "in", "like", "nand", "nor", "not",
- "or", "true", "while", "xor"
- };
- static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
- static const std::string reserved_symbols[] =
- {
- "abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp",
- "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc",
- "exp", "false", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in",
- "inrange", "like", "log", "log10", "logn", "max", "min", "mod", "mul",
- "nand", "nor", "not", "not_equal", "or", "rad2deg", "root", "round",
- "roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum",
- "tan", "tanh", "true", "while", "xor"
- };
- static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
- inline bool is_reserved_word(const std::string& symbol)
- {
- for (std::size_t i = 0; i < reserved_words_size; ++i)
- {
- if (imatch(symbol,reserved_words[i]))
- {
- return true;
- }
- }
- return false;
- }
- inline bool is_reserved_symbol(const std::string& symbol)
- {
- for (std::size_t i = 0; i < reserved_symbols_size; ++i)
- {
- if (imatch(symbol,reserved_symbols[i]))
- {
- return true;
- }
- }
- return false;
- }
- struct cs_match { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } };
- struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } };
- template <typename Iterator, typename Compare>
- inline 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)
- {
- if (0 == std::distance(data_begin,data_end)) return false;
- Iterator d_itr = data_begin;
- Iterator p_itr = pattern_begin;
- Iterator c_itr = data_begin;
- Iterator m_itr = data_begin;
- while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
- {
- if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
- {
- return false;
- }
- ++p_itr;
- ++d_itr;
- }
- while (data_end != d_itr)
- {
- if (zero_or_more == (*p_itr))
- {
- if (pattern_end == (++p_itr))
- {
- return true;
- }
- m_itr = p_itr;
- c_itr = d_itr;
- ++c_itr;
- }
- else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
- {
- ++p_itr;
- ++d_itr;
- }
- else
- {
- p_itr = m_itr;
- d_itr = c_itr++;
- }
- }
- while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr;
- return (p_itr == pattern_end);
- }
- inline bool wc_match(const std::string& wild_card,
- const std::string& str)
- {
- return match_impl<const char*,cs_match>(wild_card.data(),
- wild_card.data() + wild_card.size(),
- str.data(),
- str.data() + str.size(),
- '*',
- '?');
- }
- inline bool wc_imatch(const std::string& wild_card,
- const std::string& str)
- {
- return match_impl<const char*,cis_match>(wild_card.data(),
- wild_card.data() + wild_card.size(),
- str.data(),
- str.data() + str.size(),
- '*',
- '?');
- }
- static const double pow10[] = {
- 1.0,
- 10.0,
- 100.0,
- 1000.0,
- 10000.0,
- 100000.0,
- 1000000.0,
- 10000000.0,
- 100000000.0,
- 1000000000.0,
- 10000000000.0,
- 100000000000.0,
- 1000000000000.0,
- 10000000000000.0,
- 100000000000000.0,
- 1000000000000000.0,
- 10000000000000000.0,
- };
- namespace numeric
- {
- namespace constant
- {
- static const double e = 2.718281828459045235360;
- static const double pi = 3.141592653589793238462;
- static const double pi_2 = 1.570796326794896619231;
- static const double pi_4 = 0.785398163397448309616;
- static const double pi_180 = 0.017453292519943295769;
- static const double _1_pi = 0.318309886183790671538;
- static const double _2_pi = 0.636619772367581343076;
- static const double _180_pi = 57.295779513082320876798;
- }
- namespace details
- {
- struct unknown_type_tag {};
- struct real_type_tag {};
- struct int_type_tag {};
- template <typename T>
- struct number_type { typedef unknown_type_tag type; };
- #define exprtk_register_real_type_tag(T)\
- template<> struct number_type<T> { typedef real_type_tag type; };
- #define exprtk_register_int_type_tag(T)\
- template<> struct number_type<T> { typedef int_type_tag type; };
- exprtk_register_real_type_tag(double)
- exprtk_register_real_type_tag(long double)
- exprtk_register_real_type_tag(float)
- exprtk_register_int_type_tag(short)
- exprtk_register_int_type_tag(int)
- exprtk_register_int_type_tag(long long int)
- exprtk_register_int_type_tag(unsigned short)
- exprtk_register_int_type_tag(unsigned int)
- exprtk_register_int_type_tag(unsigned long long int)
- #undef exprtk_register_real_type_tag
- #undef exprtk_register_int_type_tag
- template <typename T>
- inline T equal_impl(const T& v0, const T& v1, real_type_tag)
- {
- static const T epsilon = T(0.0000000001);
- return (std::abs(v0 - v1) <= (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0);
- }
- template <typename T>
- inline T equal_impl(const T& v0, const T& v1, int_type_tag)
- {
- return (v0 == v1) ? 1 : 0;
- }
- template <typename T>
- inline T nequal_impl(const T& v0, const T& v1, real_type_tag)
- {
- static const T epsilon = T(0.0000000001);
- return (std::abs(v0 - v1) > (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0);
- }
- template <typename T>
- inline T nequal_impl(const T& v0, const T& v1, int_type_tag)
- {
- return (v0 != v1) ? 1 : 0;
- }
- template <typename T>
- inline T modulus_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::fmod(v0,v1);
- }
- template <typename T>
- inline T modulus_impl(const T& v0, const T& v1, int_type_tag)
- {
- return v0 % v1;
- }
- template <typename T>
- inline T pow_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::pow(v0,v1);
- }
- template <typename T>
- inline T pow_impl(const T& v0, const T& v1, int_type_tag)
- {
- return std::pow(static_cast<double>(v0),static_cast<double>(v1));
- }
- template <typename T>
- inline T logn_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::log(v0) / std::log(v1);
- }
- template <typename T>
- inline T logn_impl(const T& v0, const T& v1, int_type_tag)
- {
- return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
- }
- template <typename T>
- inline T root_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::pow(v0,T(1)/v1);
- }
- template <typename T>
- inline T root_impl(const T& v0, const T& v1, int_type_tag)
- {
- return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
- }
- template <typename T>
- inline T roundn_impl(const T& v0, const T& v1, real_type_tag)
- {
- return T(std::floor((v0 * pow10[(int)std::floor(v1)]) + T(0.5)) / T(pow10[(int)std::floor(v1)]));
- }
- template <typename T>
- inline T roundn_impl(const T& v0, const T&, int_type_tag)
- {
- return v0;
- }
- template <typename T>
- inline T hyp_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::sqrt((v0 * v0) + (v1 * v1));
- }
- template <typename T>
- inline T hyp_impl(const T& v0, const T& v1, int_type_tag)
- {
- return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
- }
- template <typename T>
- inline T atan2_impl(const T& v0, const T& v1, real_type_tag)
- {
- return std::atan2(v0,v1);
- }
- template <typename T>
- inline T atan2_impl(const T&, const T&, int_type_tag)
- {
- return 0;
- }
- template <typename T>
- inline T shr_impl(const T& v0, const T& v1, real_type_tag)
- {
- return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
- }
- template <typename T>
- inline T shr_impl(const T& v0, const T& v1, int_type_tag)
- {
- return v0 >> v1;
- }
- template <typename T>
- inline T shl_impl(const T& v0, const T& v1, real_type_tag)
- {
- return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
- }
- template <typename T>
- inline T shl_impl(const T& v0, const T& v1, int_type_tag)
- {
- return v0 << v1;
- }
- template <typename T>
- inline T sgn_impl(const T& v, real_type_tag)
- {
- if (v > T(0.0)) return T(+1.0);
- else if (v < T(0.0)) return T(-1.0);
- else return T( 0.0);
- }
- template <typename T>
- inline T sgn_impl(const T& v, int_type_tag)
- {
- if (v > T(0)) return T(+1);
- else if (v < T(0)) return T(-1);
- else return T( 0);
- }
- template <typename T>
- inline T xor_impl(const T& v0, const T& v1, real_type_tag)
- {
- return v0 != v1;
- }
- template <typename T>
- inline T xor_impl(const T& v0, const T& v1, int_type_tag)
- {
- return v0 ^ v1;
- }
- template <typename T>
- inline T erf_impl(T v, real_type_tag)
- {
- #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
- //Note: This should not be required for mscv 11.+
- T a1 = T(+0.254829592);
- T a2 = T(-0.284496736);
- T a3 = T(+1.421413741);
- T a4 = T(-1.453152027);
- T a5 = T(+1.061405429);
- T p = T( 0.327591100);
- T sign = T(1.0);
- if (v < 0)
- {
- sign = -1;
- v = abs(v);
- }
- T t = T(1.0) / (T(1.0) + p * v);
- T y = T(1.0) - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * std::exp(-v * v);
- return sign * y;
- #else
- return ::erf(v);
- #endif
- }
- template <typename T>
- inline T erf_impl(T v, int_type_tag)
- {
- return erf_impl(static_cast<double>(v),real_type_tag());
- }
- template <typename T>
- inline T erfc_impl(T v, real_type_tag)
- {
- #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
- return T(1.0) - erf_impl(v,real_type_tag());
- #else
- return ::erfc(v);
- #endif
- }
- template <typename T>
- inline T erfc_impl(T v, int_type_tag)
- {
- return erfc_impl(static_cast<double>(v),real_type_tag());
- }
- template <typename T> inline T abs_impl(const T& v, real_type_tag) { return std::abs (v); }
- template <typename T> inline T acos_impl(const T& v, real_type_tag) { return std::acos (v); }
- template <typename T> inline T asin_impl(const T& v, real_type_tag) { return std::asin (v); }
- template <typename T> inline T atan_impl(const T& v, real_type_tag) { return std::atan (v); }
- template <typename T> inline T ceil_impl(const T& v, real_type_tag) { return std::ceil (v); }
- template <typename T> inline T cos_impl(const T& v, real_type_tag) { return std::cos (v); }
- template <typename T> inline T cosh_impl(const T& v, real_type_tag) { return std::cosh (v); }
- template <typename T> inline T exp_impl(const T& v, real_type_tag) { return std::exp (v); }
- template <typename T> inline T floor_impl(const T& v, real_type_tag) { return std::floor(v); }
- template <typename T> inline T log_impl(const T& v, real_type_tag) { return std::log (v); }
- template <typename T> inline T log10_impl(const T& v, real_type_tag) { return std::log10(v); }
- template <typename T> inline T neg_impl(const T& v, real_type_tag) { return -v; }
- template <typename T> inline T pos_impl(const T& v, real_type_tag) { return +v; }
- template <typename T> inline T round_impl(const T& v, real_type_tag) { return std::floor(v + T(0.5)); }
- template <typename T> inline T sin_impl(const T& v, real_type_tag) { return std::sin (v); }
- template <typename T> inline T sinh_impl(const T& v, real_type_tag) { return std::sinh (v); }
- template <typename T> inline T sqrt_impl(const T& v, real_type_tag) { return std::sqrt (v); }
- template <typename T> inline T tan_impl(const T& v, real_type_tag) { return std::tan (v); }
- template <typename T> inline T tanh_impl(const T& v, real_type_tag) { return std::tanh (v); }
- template <typename T> inline T cot_impl(const T& v, real_type_tag) { return T(1) / std::tan(v); }
- template <typename T> inline T sec_impl(const T& v, real_type_tag) { return T(1) / std::cos(v); }
- template <typename T> inline T csc_impl(const T& v, real_type_tag) { return T(1) / std::sin(v); }
- template <typename T> inline T r2d_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
- template <typename T> inline T d2r_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
- template <typename T> inline T d2g_impl(const T& v, real_type_tag) { return (v * T(20.0/9.0)); }
- template <typename T> inline T g2d_impl(const T& v, real_type_tag) { return (v * T(9.0/20.0)); }
- template <typename T> inline T notl_impl(const T& v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
- template <typename T> inline T abs_impl(const T& v, int_type_tag) { return std::abs (v); }
- template <typename T> inline T exp_impl(const T& v, int_type_tag) { return std::exp (v); }
- template <typename T> inline T log_impl(const T& v, int_type_tag) { return std::log (v); }
- template <typename T> inline T log10_impl(const T& v, int_type_tag) { return std::log10(v); }
- template <typename T> inline T neg_impl(const T& v, int_type_tag) { return -v; }
- template <typename T> inline T pos_impl(const T& v, int_type_tag) { return +v; }
- template <typename T> inline T ceil_impl(const T& v, int_type_tag) { return v; }
- template <typename T> inline T floor_impl(const T& v, int_type_tag) { return v; }
- template <typename T> inline T round_impl(const T& v, int_type_tag) { return v; }
- template <typename T> inline T notl_impl(const T& v, int_type_tag) { return !v; }
- template <typename T> inline T sqrt_impl(const T& v, int_type_tag) { return std::sqrt (v); }
- template <typename T> inline T acos_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T asin_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T atan_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cos_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cosh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sin_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sinh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T tan_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T tanh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T cot_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T sec_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T> inline T csc_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
- template <typename T>
- inline bool is_integer_impl(const T& v, real_type_tag)
- {
- return (T(0.0) == std::fmod(v,T(1.0)));
- }
- template <typename T>
- inline bool is_integer_impl(const T&, int_type_tag)
- {
- return true;
- }
- }
- template <typename Type>
- struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
- template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
- template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
- template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
- template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
- template <typename T>
- inline T equal(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::equal_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T nequal(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::nequal_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T modulus(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::modulus_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T pow(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::pow_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T logn(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::logn_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T root(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::root_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T roundn(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::roundn_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T hyp(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::hyp_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T atan2(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::atan2_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T shr(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::shr_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T shl(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::shl_impl(v0,v1,num_type);
- }
- template <typename T>
- inline T xor_opr(const T& v0, const T& v1)
- {
- typename details::number_type<T>::type num_type;
- return details::xor_impl(v0,v1,num_type);
- }
- template <typename T>
- inline bool is_integer(const T& v)
- {
- typename details::number_type<T>::type num_type;
- return details::is_integer_impl(v,num_type);
- }
- template <typename T, unsigned int N>
- struct fast_exp
- {
- static inline T result(T v)
- {
- unsigned int k = N;
- T l = T(1);
- while (k)
- {
- if (k & 1)
- {
- l *= v;
- --k;
- }
- v *= v;
- k >>= 1;
- }
- return l;
- }
- };
- 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; } };
- template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
- 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; } };
- template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
- 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; } };
- template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
- template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
- template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
- template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
- template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
- template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
- #define exprtk_define_unary_function(FunctionName) \
- template <typename T> \
- inline T FunctionName (const T& v) \
- { \
- typename details::number_type<T>::type num_type; \
- return details:: FunctionName##_impl(v,num_type); \
- }
- exprtk_define_unary_function(abs )
- exprtk_define_unary_function(acos )
- exprtk_define_unary_function(asin )
- exprtk_define_unary_function(atan )
- exprtk_define_unary_function(ceil )
- exprtk_define_unary_function(cos )
- exprtk_define_unary_function(cosh )
- exprtk_define_unary_function(exp )
- exprtk_define_unary_function(floor)
- exprtk_define_unary_function(log )
- exprtk_define_unary_function(log10)
- exprtk_define_unary_function(neg )
- exprtk_define_unary_function(pos )
- exprtk_define_unary_function(round)
- exprtk_define_unary_function(sin )
- exprtk_define_unary_function(sinh )
- exprtk_define_unary_function(sqrt )
- exprtk_define_unary_function(tan )
- exprtk_define_unary_function(tanh )
- exprtk_define_unary_function(cot )
- exprtk_define_unary_function(sec )
- exprtk_define_unary_function(csc )
- exprtk_define_unary_function(r2d )
- exprtk_define_unary_function(d2r )
- exprtk_define_unary_function(d2g )
- exprtk_define_unary_function(g2d )
- exprtk_define_unary_function(notl )
- exprtk_define_unary_function(sgn )
- exprtk_define_unary_function(erf )
- exprtk_define_unary_function(erfc )
- #undef exprtk_define_unary_function
- }
- template <typename T>
- struct token
- {
- enum token_type
- {
- none = 0,
- error = 1,
- eof = 2,
- number = 3,
- symbol = 4,
- string = 5,
- assign = 6,
- shr = 7,
- shl = 8,
- lte = 9,
- ne = 10,
- gte = 11,
- lt = '<',
- gt = '>',
- eq = '=',
- rbracket = ')',
- lbracket = '(',
- rsqrbracket = ']',
- lsqrbracket = '[',
- rcrlbracket = '}',
- lcrlbracket = '{',
- comma = ',',
- add = '+',
- sub = '-',
- div = '/',
- mul = '*',
- mod = '%',
- pow = '^'
- };
- token() {}
- explicit token(token_type ttype)
- : type(ttype)
- {}
- token(token_type ttype,
- const char* begin, const char* end)
- : type(ttype),
- value(std::string(begin,end)),
- numeric_value(T(0))
- {}
- token(token_type ttype, const std::string& v)
- : type(ttype),
- value(v),
- numeric_value(T(0))
- {}
- token(token_type ttype, const T& num_val)
- : type(ttype),
- numeric_value(num_val)
- {}
- token_type type;
- std::string value;
- T numeric_value;
- };
- template <typename T>
- class lexer
- {
- public:
- typedef token<T> token_t;
- inline bool process(const std::string& str)
- {
- error_description_ = "";
- s_itr = str.data();
- s_end = str.data() + str.size();
- eof_token_ = token_t(token_t::eof,s_end,s_end);
- token_list_.clear();
- while (s_end != s_itr)
- {
- scan_token();
- if (!error_description_.empty())
- {
- return false;
- }
- }
- process_commutative_symbols();
- token_itr_ = token_list_.begin();
- store_token_itr_ = token_list_.begin();
- return true;
- }
- inline void store()
- {
- store_token_itr_ = token_itr_;
- }
- inline void restore()
- {
- token_itr_ = store_token_itr_;
- }
- inline token_t& next_token()
- {
- if (token_list_.end() != token_itr_)
- {
- return *token_itr_++;
- }
- else
- return eof_token_;
- }
- inline std::string error() const
- {
- return error_description_;
- }
- private:
- inline void skip_whitespace()
- {
- while ((s_end != s_itr) && is_whitespace(*s_itr))
- {
- ++s_itr;
- }
- }
- inline void scan_token()
- {
- skip_whitespace();
- if (s_end == s_itr)
- {
- return;
- }
- else if (is_operator_char(*s_itr))
- {
- scan_operator();
- return;
- }
- else if (is_letter(*s_itr))
- {
- scan_symbol();
- return;
- }
- else if (is_digit((*s_itr)) || ('.' == (*s_itr)))
- {
- scan_number();
- return;
- }
- else if ('$' == (*s_itr))
- {
- scan_special_function();
- return;
- }
- #ifndef exprtk_disable_string_capabilities
- else if ('\'' == (*s_itr))
- {
- scan_string();
- return;
- }
- #endif
- else
- {
- set_error(std::string("scan_token() - error invalid token: ") + std::string(s_itr,s_itr + 2));
- token_list_.push_back(error(s_itr,s_itr + 1));
- ++s_itr;
- }
- }
- inline void scan_operator()
- {
- if ((s_itr + 1) != s_end)
- {
- typename token_t::token_type ttype = token_t::none;
- char c0 = s_itr[0];
- char c1 = s_itr[1];
- if ((c0 == '<') && (c1 == '=')) ttype = token_t::lte;
- else if ((c0 == '>') && (c1 == '=')) ttype = token_t::gte;
- else if ((c0 == '<') && (c1 == '>')) ttype = token_t::ne;
- else if ((c0 == '!') && (c1 == '=')) ttype = token_t::ne;
- else if ((c0 == '=') && (c1 == '=')) ttype = token_t::eq;
- else if ((c0 == ':') && (c1 == '=')) ttype = token_t::assign;
- else if ((c0 == '<') && (c1 == '<')) ttype = token_t::shl;
- else if ((c0 == '>') && (c1 == '>')) ttype = token_t::shr;
- if (token_t::none != ttype)
- {
- token_list_.push_back(token_t(ttype));
- s_itr += 2;
- return;
- }
- }
- if ('<' == *s_itr) token_list_.push_back(token_t(token_t::lt));
- else if ('>' == *s_itr) token_list_.push_back(token_t(token_t::gt));
- else
- token_list_.push_back(token_t(typename token_t::token_type((*s_itr))));
- ++s_itr;
- }
- inline void scan_symbol()
- {
- const char* begin = s_itr;
- while ((s_end != s_itr) &&
- (is_letter((*s_itr)) || is_digit ((*s_itr)) || ((*s_itr) == '_')))
- {
- ++s_itr;
- }
- static const std::string true_string = "true";
- static const std::string false_string = "false";
- if (details::imatch(std::string(begin,s_itr),true_string))
- token_list_.push_back(token_t(token_t::number,T(1)));
- else if (details::imatch(std::string(begin,s_itr),false_string))
- token_list_.push_back(token_t(token_t::number,T(0)));
- else
- token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
- }
- inline void scan_number()
- {
- /*
- Attempt to match a valid numeric value in one of the following formats:
- 1. 123456
- 2. 123.456
- 3. 123.456e3
- 4. 123.456E3
- 5. 123.456e+3
- 6. 123.456E+3
- 7. 123.456e-3
- 8. 123.456E-3
- */
- const char* begin = s_itr;
- bool dot_found = false;
- bool e_found = false;
- bool post_e_sign_found = false;
- while (s_end != s_itr)
- {
- if ('.' == (*s_itr))
- {
- if (dot_found)
- {
- set_error(std::string("scan_number() - error invalid numeric token[1]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- dot_found = true;
- ++s_itr;
- continue;
- }
- else if (imatch('e',(*s_itr)))
- {
- const char& c = *(s_itr + 1);
- if (s_end == (s_itr + 1))
- {
- set_error(std::string("scan_number() - error invalid numeric token[2]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- else if (('+' != c) && ('-' != c) && !is_digit(c))
- {
- set_error(std::string("scan_number() - error invalid numeric token[3]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- e_found = true;
- ++s_itr;
- continue;
- }
- else if (e_found && is_sign(*s_itr))
- {
- if (post_e_sign_found)
- {
- set_error(std::string("scan_number() - error invalid numeric token[4]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- post_e_sign_found = true;
- ++s_itr;
- continue;
- }
- else if (('.' != (*s_itr)) && !is_digit(*s_itr))
- break;
- else
- ++s_itr;
- }
- T value = T(0.0);
- if (string_to_real(begin,s_itr,value))
- token_list_.push_back(token_t(token_t::number,value));
- else
- {
- set_error(std::string("scan_number() - error failed to parse token to real type. ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- }
- return;
- }
- inline void scan_special_function()
- {
- const char* begin = s_itr;
- //$fdd(x,x,x) = 11 chars
- if (std::distance(s_itr,s_end) < 11)
- {
- set_error(std::string("scan_special_function() - error invalid special function [1]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- if (!(('$' == *s_itr) &&
- (imatch('f',*(s_itr + 1))) &&
- ('(' == *(s_itr + 4)) &&
- (is_digit(*(s_itr + 2))) &&
- (is_digit(*(s_itr + 3)))))
- {
- set_error(std::string("scan_special_function() - error invalid special function [2]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- s_itr += 4;
- token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
- return;
- }
- #ifndef exprtk_disable_string_capabilities
- inline void scan_string()
- {
- const char* begin = s_itr + 1;
- if (std::distance(s_itr,s_end) < 2)
- {
- set_error(std::string("scan_string() - error invalid string [1]: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- ++s_itr;
- bool escaped = false;
- std::string result_string;
- while (s_end != s_itr)
- {
- if ('\\' == *s_itr)
- {
- escaped = true;
- ++s_itr;
- continue;
- }
- else if (!escaped)
- {
- if ('\'' == *s_itr)
- break;
- }
- else if (escaped)
- escaped = false;
- result_string += *s_itr;
- ++s_itr;
- }
- if (s_end == s_itr)
- {
- set_error(std::string("scan_string() - error string has not been terminated: ") + std::string(begin,s_itr));
- token_list_.push_back(error(begin,s_itr));
- return;
- }
- token_list_.push_back(token_t(token_t::string,result_string));
- ++s_itr;
- return;
- }
- #endif
- inline void process_commutative_symbols()
- {
- if (token_list_.size() < 2)
- return;
- typename std::deque<token_t>::iterator itr = token_list_.begin() + 1;
- typename std::deque<token_t>::iterator prev_itr = token_list_.begin();
- while (token_list_.end() != itr)
- {
- token_t& curr_token = *itr;
- token_t& prev_token = *prev_itr;
- bool curr_token_not_reserved = !is_reserved_word(curr_token.value);
- if (
- //3x -> 3*x
- ((token_t::symbol == curr_token.type) && (token_t::number == prev_token.type) && curr_token_not_reserved) ||
- //3(x+1) -> 3*(x+1)
- (is_left_bracket (static_cast<char>(curr_token.type)) && (token_t::number == prev_token.type)) ||
- //(x+1)3 -> (x+1)*3
- (is_right_bracket(static_cast<char>(prev_token.type)) && (token_t::number == curr_token.type)) ||
- //(x+1)y -> (x+1)*y
- (is_right_bracket(static_cast<char>(prev_token.type)) && (token_t::symbol == curr_token.type) && curr_token_not_reserved)
- )
- {
- prev_itr = itr = token_list_.insert(itr,token_t(token_t::mul));
- ++itr;
- continue;
- }
- ++itr;
- ++prev_itr;
- }
- }
- inline void set_error(const std::string& s)
- {
- if (error_description_.empty())
- {
- error_description_ = s;
- }
- }
- inline token_t error(const char* begin, const char* end) const
- {
- return token_t(token_t::error,begin,end);
- }
- private:
- template <typename Iterator, typename Type>
- static inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, Type& result)
- {
- if (end == itr) return false;
- Type t = 0;
- bool negative = false;
- if ('+' == (*itr))
- ++itr;
- else if ('-' == (*itr))
- {
- ++itr;
- negative = true;
- }
- if (end == itr)
- return false;
- unsigned int digit_count = 0;
- while ((end != itr) && ('0' == (*itr))) ++itr;
- bool return_result = true;
- while (end != itr)
- {
- const unsigned char digit = (*itr - '0');
- if (digit > 9)
- {
- return_result = false;
- break;
- }
- if ((++digit_count) <= numeric::numeric_info<Type>::bound_length)
- {
- t *= 10;
- t += digit;
- }
- else
- {
- typedef unsigned long long int base_type;
- static const base_type max_limit = +std::numeric_limits<Type>::max();
- static const base_type min_limit = -std::numeric_limits<Type>::min();
- base_type tmp = static_cast<base_type>(t) * 10 + digit;
- if (negative && static_cast<base_type>(tmp) > min_limit)
- return_result = false;
- else if (static_cast<base_type>(tmp) > max_limit)
- return_result = false;
- t = static_cast<Type>(tmp);
- }
- ++itr;
- }
- result = static_cast<Type>((negative) ? -t : t);
- return return_result;
- }
- template <typename Iterator>
- static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
- {
- typedef typename std::iterator_traits<Iterator>::value_type type;
- static const std::size_t nan_length = 3;
- if (std::distance(itr,end) != static_cast<int>(nan_length))
- return false;
- if (static_cast<type>('n') == (*itr))
- {
- if ((static_cast<type>('a') != *(itr + 1)) || (static_cast<type>('n') != *(itr + 2)))
- {
- return false;
- }
- }
- else if ((static_cast<type>('A') != *(itr + 1)) || (static_cast<type>('N') != *(itr + 2)))
- {
- return false;
- }
- t = std::numeric_limits<T>::quiet_NaN();
- return true;
- }
- template <typename Iterator>
- static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
- {
- static const char inf_uc[] = "INFINITY";
- static const char inf_lc[] = "infinity";
- static const std::size_t inf_length = 8;
- const std::size_t length = std::distance(itr,end);
- if ((3 != length) && (inf_length != length))
- return false;
- const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
- while (end != itr)
- {
- if (*inf_itr == static_cast<char>(*itr))
- {
- ++itr;
- ++inf_itr;
- continue;
- }
- else
- return false;
- }
- if (negative)
- t = -std::numeric_limits<T>::infinity();
- else
- t = std::numeric_limits<T>::infinity();
- return true;
- }
- template <typename Iterator>
- inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t)
- {
- if (end == itr_external) return false;
- Iterator itr = itr_external;
- double d = 0.0;
- bool negative = false;
- if ('+' == (*itr))
- ++itr;
- else if ('-' == (*itr))
- …
Large files files are truncated, but you can click here to view the full file