diff --git a/exprtk.hpp b/exprtk.hpp index b4530ba..0451be2 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -827,6 +827,12 @@ namespace exprtk exprtk_define_epsilon_type(float , 0.00000100000f) exprtk_define_epsilon_type(double , 0.000000000100) exprtk_define_epsilon_type(long double, 0.000000000001) + exprtk_define_epsilon_type(int, 0) + exprtk_define_epsilon_type(short, 0) + exprtk_define_epsilon_type(_int64_t, 0) + exprtk_define_epsilon_type(unsigned short, 0) + exprtk_define_epsilon_type(unsigned int, 0) + exprtk_define_epsilon_type(_uint64_t, 0) #undef exprtk_define_epsilon_type @@ -836,18 +842,36 @@ namespace exprtk return std::not_equal_to()(v,v); } + template + inline bool is_nan_impl(const T v, int_type_tag) + { + return false; + } + template inline int to_int32_impl(const T v, real_type_tag) { return static_cast(v); } + template + inline int to_int32_impl(const T v, int_type_tag) + { + return static_cast(v); + } + template inline _int64_t to_int64_impl(const T v, real_type_tag) { return static_cast<_int64_t>(v); } + template + inline _int64_t to_int64_impl(const T v, int_type_tag) + { + return static_cast<_int64_t>(v); + } + template inline bool is_true_impl(const T v) { @@ -910,7 +934,7 @@ namespace exprtk template inline T expm1_impl(const T v, int_type_tag) { - return T(std::exp(v)) - T(1); + return T(std::exp(static_cast(v))) - T(1); } template @@ -1325,11 +1349,16 @@ namespace exprtk template inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } template inline T const_qnan_impl(real_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T r2d_impl(const T v, int_type_tag) { return (static_cast(v * numeric::constant::_180_pi)); } + template inline T d2r_impl(const T v, int_type_tag) { return (static_cast(v * numeric::constant::pi_180)); } + template inline T d2g_impl(const T v, int_type_tag) { return (static_cast(v * 20.0/9.0)); } + template inline T g2d_impl(const T v, int_type_tag) { return (static_cast(v * 9.0/20.0)); } + template inline T const_pi_impl(int_type_tag) { return T(numeric::constant::pi); } template inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } template inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } template inline T log_impl(const T v, int_type_tag) { return std::log (v); } template inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } - template inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } + template inline T log2_impl(const T v, int_type_tag) { return static_cast(std::log(v)/numeric::constant::log2); } template inline T neg_impl(const T v, int_type_tag) { return -v; } template inline T pos_impl(const T v, int_type_tag) { return +v; } template inline T ceil_impl(const T v, int_type_tag) { return v; } @@ -1371,7 +1400,12 @@ namespace exprtk template struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; - template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9 }; }; + template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; + template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; + template <> struct numeric_info<_int64_t > { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; + template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; + template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; + template <> struct numeric_info<_uint64_t > { enum { length = 10, size = 16, bound_length = 9, min_exp = 0, max_exp = 0 }; }; template <> struct numeric_info { enum { min_exp = -38, max_exp = +38 }; }; template <> struct numeric_info { enum { min_exp = -308, max_exp = +308 }; }; template <> struct numeric_info { enum { min_exp = -308, max_exp = +308 }; }; @@ -1556,7 +1590,6 @@ namespace exprtk v *= v; k /= 2; } - return l; } }; @@ -1995,6 +2028,176 @@ namespace exprtk return true; } + template + inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::int_type_tag) + { + if (end == itr_external) return false; + + Iterator itr = itr_external; + + T d = T(0); + + const bool negative = ('-' == (*itr)); + + if (negative || '+' == (*itr)) + { + if (end == ++itr) + return false; + } + + bool instate = false; + + static const char_t zero = static_cast('0'); + + #define parse_digit_1(d) \ + if ((digit = (*itr - zero)) < 10) \ + { d = d * T(10) + digit; } \ + else \ + { break; } \ + if (end == ++itr) break; \ + + #define parse_digit_2(d) \ + if ((digit = (*itr - zero)) < 10) \ + { d = d * T(10) + digit; } \ + else { break; } \ + ++itr; \ + + if ('.' != (*itr)) + { + const Iterator curr = itr; + + while ((end != itr) && (zero == (*itr))) ++itr; + + while (end != itr) + { + // Note: For 'physical' superscalar architectures it + // is advised that the following loop be: 4xPD1 and 1xPD2 + unsigned int digit; + + #ifdef exprtk_enable_superscalar + parse_digit_1(d) + parse_digit_1(d) + #endif + parse_digit_1(d) + parse_digit_1(d) + parse_digit_2(d) + } + + if (curr != itr) instate = true; + } + + int exponent = 0; + + if (end != itr) + { + if ('.' == (*itr)) + { + const Iterator curr = ++itr; + T tmp_d = T(0); + + while (end != itr) + { + unsigned int digit; + + #ifdef exprtk_enable_superscalar + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + #endif + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + parse_digit_2(tmp_d) + } + + if (curr != itr) + { + instate = true; + + const int exponent = static_cast(-std::distance(curr, itr)); + + if (!valid_exponent(exponent, numeric::details::real_type_tag())) + return false; + + d += compute_pow10(tmp_d, exponent); + } + + #undef parse_digit_1 + #undef parse_digit_2 + } + + if (end != itr) + { + typename std::iterator_traits::value_type c = (*itr); + + if (('e' == c) || ('E' == c)) + { + int exp = 0; + + if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) + { + if (end == itr) + return false; + else + c = (*itr); + } + + exponent += exp; + } + + if (end != itr) + { + if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) + ++itr; + else if ('#' == c) + { + if (end == ++itr) + return false; + else if (('I' <= (*itr)) && ((*itr) <= 'n')) + { + if (('i' == (*itr)) || ('I' == (*itr))) + { + return parse_inf(itr, end, t, negative); + } + else if (('n' == (*itr)) || ('N' == (*itr))) + { + return parse_nan(itr, end, t); + } + else + return false; + } + else + return false; + } + else if (('I' <= (*itr)) && ((*itr) <= 'n')) + { + if (('i' == (*itr)) || ('I' == (*itr))) + { + return parse_inf(itr, end, t, negative); + } + else if (('n' == (*itr)) || ('N' == (*itr))) + { + return parse_nan(itr, end, t); + } + else + return false; + } + else + return false; + } + } + } + + if ((end != itr) || (!instate)) + return false; + else if (!valid_exponent(exponent, numeric::details::real_type_tag())) + return false; + else if (exponent) + d = compute_pow10(d,exponent); + + t = static_cast((negative) ? -d : d); + return true; + } + template inline bool string_to_real(const std::string& s, T& t) { @@ -5212,6 +5415,22 @@ namespace exprtk template inline bool is_generally_string_node(const expression_node* node); + inline bool is_true(const uint32_t v) { + return v != 0; + } + + inline bool is_true(const uint64_t v) { + return v != 0; + } + + inline bool is_true(const int32_t v) { + return v != 0; + } + + inline bool is_true(const int64_t v) { + return v != 0; + } + inline bool is_true(const double v) { return std::not_equal_to()(0.0,v);