// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #define CHAISCRIPT_BOXED_NUMERIC_HPP_ #include #include #include #include "../language/chaiscript_algebraic.hpp" #include "any.hpp" #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" #include "type_info.hpp" namespace chaiscript { class Type_Conversions; } // namespace chaiscript namespace chaiscript { namespace exception { struct arithmetic_error : std::runtime_error { arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {} arithmetic_error(const arithmetic_error &) = default; virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {} }; } } namespace chaiscript { // Due to the nature of generating every possible arithmetic operation, there // are going to be warnings generated on every platform regarding size and sign, // this is OK, so we're disabling size/and sign type warnings #ifdef CHAISCRIPT_MSVC #pragma warning(push) #pragma warning(disable : 4244 4018 4389 4146 4365 4267) #endif #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wfloat-equal" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wsign-conversion" #endif /// \brief Represents any numeric type, generically. Used internally for generic operations between POD values class Boxed_Number { private: enum class Common_Types { t_int32, t_double, t_uint8, t_int8, t_uint16, t_int16, t_uint32, t_uint64, t_int64, t_float, t_long_double }; template static inline void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) { #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO if (t == 0) { throw chaiscript::exception::arithmetic_error("divide by zero"); } #endif } template static inline void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) { } static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed) { return (t_size == 1 && t_signed)?(Common_Types::t_int8) :(t_size == 1)?(Common_Types::t_uint8) :(t_size == 2 && t_signed)?(Common_Types::t_int16) :(t_size == 2)?(Common_Types::t_uint16) :(t_size == 4 && t_signed)?(Common_Types::t_int32) :(t_size == 4)?(Common_Types::t_uint32) :(t_size == 8 && t_signed)?(Common_Types::t_int64) :(Common_Types::t_uint64); } static Common_Types get_common_type(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(int)) { return get_common_type(sizeof(int), true); } else if (inp_ == typeid(double)) { return Common_Types::t_double; } else if (inp_ == typeid(long double)) { return Common_Types::t_long_double; } else if (inp_ == typeid(float)) { return Common_Types::t_float; } else if (inp_ == typeid(char)) { return get_common_type(sizeof(char), std::is_signed::value); } else if (inp_ == typeid(unsigned char)) { return get_common_type(sizeof(unsigned char), false); } else if (inp_ == typeid(unsigned int)) { return get_common_type(sizeof(unsigned int), false); } else if (inp_ == typeid(long)) { return get_common_type(sizeof(long), true); } else if (inp_ == typeid(long long)) { return get_common_type(sizeof(long long), true); } else if (inp_ == typeid(unsigned long)) { return get_common_type(sizeof(unsigned long), false); } else if (inp_ == typeid(unsigned long long)) { return get_common_type(sizeof(unsigned long long), false); } else if (inp_ == typeid(std::int8_t)) { return Common_Types::t_int8; } else if (inp_ == typeid(std::int16_t)) { return Common_Types::t_int16; } else if (inp_ == typeid(std::int32_t)) { return Common_Types::t_int32; } else if (inp_ == typeid(std::int64_t)) { return Common_Types::t_int64; } else if (inp_ == typeid(std::uint8_t)) { return Common_Types::t_uint8; } else if (inp_ == typeid(std::uint16_t)) { return Common_Types::t_uint16; } else if (inp_ == typeid(std::uint32_t)) { return Common_Types::t_uint32; } else if (inp_ == typeid(std::uint64_t)) { return Common_Types::t_uint64; } else if (inp_ == typeid(wchar_t)) { return get_common_type(sizeof(wchar_t), std::is_signed::value); } else if (inp_ == typeid(char16_t)) { return get_common_type(sizeof(char16_t), std::is_signed::value); } else if (inp_ == typeid(char32_t)) { return get_common_type(sizeof(char32_t), std::is_signed::value); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::equals: return const_var(t == u); case Operators::less_than: return const_var(t < u); case Operators::greater_than: return const_var(t > u); case Operators::less_than_equal: return const_var(t <= u); case Operators::greater_than_equal: return const_var(t >= u); case Operators::not_equal: return const_var(t != u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value unary_go(Operators::Opers t_oper, T &t, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::pre_increment: ++t; break; case Operators::pre_decrement: --t; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::assign: t = u; break; case Operators::assign_product: t *= u; break; case Operators::assign_sum: t += u; break; case Operators::assign_quotient: check_divide_by_zero(u); t /= u; break; case Operators::assign_difference: t -= u; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value binary_int_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { case Operators::assign_bitwise_and: t &= u; break; case Operators::assign_bitwise_or: t |= u; break; case Operators::assign_shift_left: t <<= u; break; case Operators::assign_shift_right: t >>= u; break; case Operators::assign_remainder: check_divide_by_zero(u); t %= u; break; case Operators::assign_bitwise_xor: t ^= u; break; default: throw chaiscript::detail::exception::bad_any_cast(); } return t_lhs; } template static Boxed_Value const_unary_int_go(Operators::Opers t_oper, const T &t) { switch (t_oper) { case Operators::bitwise_complement: return const_var(~t); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::shift_left: return const_var(t << u); case Operators::shift_right: return const_var(t >> u); case Operators::remainder: check_divide_by_zero(u); return const_var(t % u); case Operators::bitwise_and: return const_var(t & u); case Operators::bitwise_or: return const_var(t | u); case Operators::bitwise_xor: return const_var(t ^ u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_unary_go(Operators::Opers t_oper, const T &t) { switch (t_oper) { case Operators::unary_minus: return const_var(-t); case Operators::unary_plus: return const_var(+t); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { case Operators::sum: return const_var(t + u); case Operators::quotient: check_divide_by_zero(u); return const_var(t / u); case Operators::product: return const_var(t * u); case Operators::difference: return const_var(t - u); default: throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) -> typename std::enable_if::value && !std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { return const_binary_int_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::const_flag) { return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) -> typename std::enable_if::value || std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::const_flag) { return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } } // Unary template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) -> typename std::enable_if::value, Boxed_Value>::type { if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { return const_unary_int_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else if (t_oper > Operators::const_flag) { return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) -> typename std::enable_if::value, Boxed_Value>::type { if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); } else if (t_oper > Operators::const_flag) { return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { switch (get_common_type(t_rhs)) { case Common_Types::t_int32: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint8: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int8: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint16: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int16: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint32: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_uint64: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_int64: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_double: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_float: return go(t_oper, t_lhs, t_rhs); case Common_Types::t_long_double: return go(t_oper, t_lhs, t_rhs); } throw chaiscript::detail::exception::bad_any_cast(); } inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { switch (get_common_type(t_lhs)) { case Common_Types::t_int32: return go(t_oper, t_lhs); case Common_Types::t_uint8: return go(t_oper, t_lhs); case Common_Types::t_int8: return go(t_oper, t_lhs); case Common_Types::t_uint16: return go(t_oper, t_lhs); case Common_Types::t_int16: return go(t_oper, t_lhs); case Common_Types::t_uint32: return go(t_oper, t_lhs); case Common_Types::t_uint64: return go(t_oper, t_lhs); case Common_Types::t_int64: return go(t_oper, t_lhs); case Common_Types::t_double: return go(t_oper, t_lhs); case Common_Types::t_float: return go(t_oper, t_lhs); case Common_Types::t_long_double: return go(t_oper, t_lhs); } throw chaiscript::detail::exception::bad_any_cast(); } inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { switch (get_common_type(t_lhs)) { case Common_Types::t_int32: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint8: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int8: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint16: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int16: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint32: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_uint64: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_int64: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_double: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_float: return oper_rhs(t_oper, t_lhs, t_rhs); case Common_Types::t_long_double: return oper_rhs(t_oper, t_lhs, t_rhs); } throw chaiscript::detail::exception::bad_any_cast(); } template static inline Target get_as_aux(const Boxed_Value &t_bv) { return static_cast(*static_cast(t_bv.get_const_ptr())); } template static std::string to_string_aux(const Boxed_Value &v) { std::ostringstream oss; oss << *static_cast(v.get_const_ptr()); return oss.str(); } public: Boxed_Number() : bv(Boxed_Value(0)) { } Boxed_Number(Boxed_Value v) : bv(std::move(v)) { validate_boxed_number(bv); } Boxed_Number(const Boxed_Number &) = default; #if !defined(_MSC_VER) || _MSC_VER != 1800 Boxed_Number(Boxed_Number &&) = default; Boxed_Number& operator=(Boxed_Number &&) = default; #endif template explicit Boxed_Number(T t) : bv(Boxed_Value(t)) { validate_boxed_number(bv); } static bool is_floating_point(const Boxed_Value &t_bv) { const Type_Info &inp_ = t_bv.get_type_info(); if (inp_ == typeid(double)) { return true; } else if (inp_ == typeid(long double)) { return true; } else if (inp_ == typeid(float)) { return true; } else { return false; } } Boxed_Number get_as(const Type_Info &inp_) const { if (inp_.bare_equal_type_info(typeid(int))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(float))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned char))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(wchar_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned int))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned long long))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int64_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint16_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint32_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint64_t))) { return Boxed_Number(get_as()); } else { throw chaiscript::detail::exception::bad_any_cast(); } } template Target get_as() const { switch (get_common_type(bv)) { case Common_Types::t_int32: return get_as_aux(bv); case Common_Types::t_uint8: return get_as_aux(bv); case Common_Types::t_int8: return get_as_aux(bv); case Common_Types::t_uint16: return get_as_aux(bv); case Common_Types::t_int16: return get_as_aux(bv); case Common_Types::t_uint32: return get_as_aux(bv); case Common_Types::t_uint64: return get_as_aux(bv); case Common_Types::t_int64: return get_as_aux(bv); case Common_Types::t_double: return get_as_aux(bv); case Common_Types::t_float: return get_as_aux(bv); case Common_Types::t_long_double: return get_as_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); } std::string to_string() const { switch (get_common_type(bv)) { case Common_Types::t_int32: return std::to_string(get_as()); case Common_Types::t_uint8: return std::to_string(get_as()); case Common_Types::t_int8: return std::to_string(get_as()); case Common_Types::t_uint16: return std::to_string(get_as()); case Common_Types::t_int16: return std::to_string(get_as()); case Common_Types::t_uint32: return std::to_string(get_as()); case Common_Types::t_uint64: return std::to_string(get_as()); case Common_Types::t_int64: return std::to_string(get_as()); case Common_Types::t_double: return to_string_aux(bv); case Common_Types::t_float: return to_string_aux(bv); case Common_Types::t_long_double: return to_string_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); } bool operator==(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::equals, this->bv, t_rhs.bv)); } bool operator<(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::less_than, this->bv, t_rhs.bv)); } bool operator>(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::greater_than, this->bv, t_rhs.bv)); } bool operator>=(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::greater_than_equal, this->bv, t_rhs.bv)); } bool operator<=(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::less_than_equal, this->bv, t_rhs.bv)); } bool operator!=(const Boxed_Number &t_rhs) const { return boxed_cast(oper(Operators::not_equal, this->bv, t_rhs.bv)); } Boxed_Number operator--() { return oper(Operators::pre_decrement, this->bv); } Boxed_Number operator++() { return oper(Operators::pre_increment, this->bv); } Boxed_Number operator+(const Boxed_Number &t_rhs) const { return oper(Operators::sum, this->bv, t_rhs.bv); } Boxed_Number operator+() const { return oper(Operators::unary_plus, this->bv); } Boxed_Number operator-() const { return oper(Operators::unary_minus, this->bv); } Boxed_Number operator-(const Boxed_Number &t_rhs) const { return oper(Operators::difference, this->bv, t_rhs.bv); } Boxed_Number operator&=(const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); } static void validate_boxed_number(const Boxed_Value &v) { const Type_Info &inp_ = v.get_type_info(); if (inp_ == typeid(bool)) { throw chaiscript::detail::exception::bad_any_cast(); } if (!inp_.is_arithmetic()) { throw chaiscript::detail::exception::bad_any_cast(); } } // cppcheck-suppress operatorEq Boxed_Number operator=(const Boxed_Value &v) { validate_boxed_number(v); bv = v; return *this; } // cppcheck-suppress operatorEq Boxed_Number operator=(const Boxed_Number &t_rhs) const { return oper(Operators::assign, this->bv, t_rhs.bv); } Boxed_Number operator|=(const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv); } Boxed_Number operator^=(const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv); } Boxed_Number operator%=(const Boxed_Number &t_rhs) { return oper(Operators::assign_remainder, this->bv, t_rhs.bv); } Boxed_Number operator<<=(const Boxed_Number &t_rhs) { return oper(Operators::assign_shift_left, this->bv, t_rhs.bv); } Boxed_Number operator>>=(const Boxed_Number &t_rhs) { return oper(Operators::assign_shift_right, this->bv, t_rhs.bv); } Boxed_Number operator&(const Boxed_Number &t_rhs) const { return oper(Operators::bitwise_and, this->bv, t_rhs.bv); } Boxed_Number operator~() const { return oper(Operators::bitwise_complement, this->bv); } Boxed_Number operator^(const Boxed_Number &t_rhs) const { return oper(Operators::bitwise_xor, this->bv, t_rhs.bv); } Boxed_Number operator|(const Boxed_Number &t_rhs) const { return oper(Operators::bitwise_or, this->bv, t_rhs.bv); } Boxed_Number operator*=(const Boxed_Number &t_rhs) { return oper(Operators::assign_product, this->bv, t_rhs.bv); } Boxed_Number operator/=(const Boxed_Number &t_rhs) { return oper(Operators::assign_quotient, this->bv, t_rhs.bv); } Boxed_Number operator+=(const Boxed_Number &t_rhs) { return oper(Operators::assign_sum, this->bv, t_rhs.bv); } Boxed_Number operator-=(const Boxed_Number &t_rhs) { return oper(Operators::assign_difference, this->bv, t_rhs.bv); } Boxed_Number operator/(const Boxed_Number &t_rhs) const { return oper(Operators::quotient, this->bv, t_rhs.bv); } Boxed_Number operator<<(const Boxed_Number &t_rhs) const { return oper(Operators::shift_left, this->bv, t_rhs.bv); } Boxed_Number operator*(const Boxed_Number &t_rhs) const { return oper(Operators::product, this->bv, t_rhs.bv); } Boxed_Number operator%(const Boxed_Number &t_rhs) const { return oper(Operators::remainder, this->bv, t_rhs.bv); } Boxed_Number operator>>(const Boxed_Number &t_rhs) const { return oper(Operators::shift_right, this->bv, t_rhs.bv); } static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::equals, t_lhs.bv, t_rhs.bv)); } static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::less_than, t_lhs.bv, t_rhs.bv)); } static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv)); } static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv)); } static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv)); } static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return boxed_cast(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv)); } static Boxed_Number pre_decrement(Boxed_Number t_lhs) { return oper(Operators::pre_decrement, t_lhs.bv); } static Boxed_Number pre_increment(Boxed_Number t_lhs) { return oper(Operators::pre_increment, t_lhs.bv); } static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::sum, t_lhs.bv, t_rhs.bv); } static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { return oper(Operators::unary_plus, t_lhs.bv); } static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { return oper(Operators::unary_minus, t_lhs.bv); } static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::difference, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv); } static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv); } static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs) { return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0)); } static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv); } static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv); } static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv); } static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::quotient, t_lhs.bv, t_rhs.bv); } static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv); } static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::product, t_lhs.bv, t_rhs.bv); } static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::remainder, t_lhs.bv, t_rhs.bv); } static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) { return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv); } static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { return oper(t_oper, t_lhs, t_rhs); } static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { return oper(t_oper, t_lhs); } Boxed_Value bv; }; namespace detail { /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper { typedef Boxed_Number Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return Boxed_Number(ob); } }; /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { }; /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { }; } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif } #endif