123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- #ifndef BOOST_NUMERIC_EXCEPTION
- #define BOOST_NUMERIC_EXCEPTION
- #include <algorithm>
- #include <system_error> // error_code, system_error
- #include <string>
- #include <cassert>
- #include <cstdint> // std::uint8_t
- namespace boost {
- namespace safe_numerics {
- enum class safe_numerics_error : std::uint8_t {
- success = 0,
- positive_overflow_error,
- negative_overflow_error,
- domain_error,
- range_error,
- precision_overflow_error,
- underflow_error,
- negative_value_shift,
- negative_shift,
- shift_too_large,
- uninitialized_value
- };
- constexpr inline const char * literal_string(const safe_numerics_error & e){
- switch(e){
- case safe_numerics_error::success: return "success";
- case safe_numerics_error::positive_overflow_error: return "positive_overflow_error";
- case safe_numerics_error::negative_overflow_error: return "negative_overflow_error";
- case safe_numerics_error::domain_error: return "domain_error";
- case safe_numerics_error::range_error: return "range_error";
- case safe_numerics_error::precision_overflow_error: return "precision_overflow_error";
- case safe_numerics_error::underflow_error: return "underflow_error";
- case safe_numerics_error::negative_value_shift: return "negative_value_shift";
- case safe_numerics_error::negative_shift: return "negative_shift";
- case safe_numerics_error::shift_too_large: return "shift_too_large";
- case safe_numerics_error::uninitialized_value: return "uninitialized_value";
- default:
- assert(false);
- }
- }
- const std::uint8_t safe_numerics_casting_error_count =
- static_cast<std::uint8_t>(safe_numerics_error::domain_error) + 1;
- const std::uint8_t safe_numerics_error_count =
- static_cast<std::uint8_t>(safe_numerics_error::uninitialized_value) + 1;
- }
- }
- namespace std {
- template <>
- struct is_error_code_enum<boost::safe_numerics::safe_numerics_error>
- : public true_type {};
- }
- namespace boost {
- namespace safe_numerics {
- const class : public std::error_category {
- public:
- virtual const char* name() const noexcept{
- return "safe numerics error";
- }
- virtual std::string message(int ev) const {
- switch(static_cast<safe_numerics_error>(ev)){
- case safe_numerics_error::success:
- return "success";
- case safe_numerics_error::positive_overflow_error:
- return "positive overflow error";
- case safe_numerics_error::negative_overflow_error:
- return "negative overflow error";
- case safe_numerics_error::underflow_error:
- return "underflow error";
- case safe_numerics_error::range_error:
- return "range error";
- case safe_numerics_error::precision_overflow_error:
- return "precision_overflow_error";
- case safe_numerics_error::domain_error:
- return "domain error";
- case safe_numerics_error::negative_shift:
- return "negative shift";
- case safe_numerics_error::negative_value_shift:
- return "negative value shift";
- case safe_numerics_error::shift_too_large:
- return "shift too large";
- case safe_numerics_error::uninitialized_value:
- return "uninitialized value";
- default:
- assert(false);
- }
- return "";
- }
- } safe_numerics_error_category {};
- inline std::error_code make_error_code(const safe_numerics_error & e){
- return std::error_code(static_cast<int>(e), safe_numerics_error_category);
- }
- enum class safe_numerics_actions {
- no_action = 0,
- uninitialized_value,
- arithmetic_error,
- implementation_defined_behavior,
- undefined_behavior
- };
- }
- }
- namespace std {
- template <>
- struct is_error_condition_enum<boost::safe_numerics::safe_numerics_actions>
- : public true_type {};
- }
- namespace boost {
- namespace safe_numerics {
- const class : public std::error_category {
- public:
- virtual const char* name() const noexcept {
- return "safe numerics error group";
- }
- virtual std::string message(int) const {
- return "safe numerics error group";
- }
-
-
- virtual bool equivalent(
- const std::error_code & code,
- int condition
- ) const noexcept {
- if(code.category() != safe_numerics_error_category)
- return false;
- switch (static_cast<safe_numerics_actions>(condition)){
- case safe_numerics_actions::no_action:
- return code == safe_numerics_error::success;
- case safe_numerics_actions::uninitialized_value:
- return code == safe_numerics_error::uninitialized_value;
- case safe_numerics_actions::arithmetic_error:
- return code == safe_numerics_error::positive_overflow_error
- || code == safe_numerics_error::negative_overflow_error
- || code == safe_numerics_error::underflow_error
- || code == safe_numerics_error::range_error
- || code == safe_numerics_error::domain_error;
- case safe_numerics_actions::implementation_defined_behavior:
- return code == safe_numerics_error::negative_value_shift
- || code == safe_numerics_error::negative_shift
- || code == safe_numerics_error::shift_too_large;
- case safe_numerics_actions::undefined_behavior:
- return false;
- default:
- ;
- }
-
- assert(false);
-
- return false;
- }
- } safe_numerics_actions_category {};
- #if 0
- std::error_condition make_error_condition(const safe_numerics_error & e) {
- return std::error_condition(
- static_cast<int>(e),
- safe_numerics_error_category
- );
- }
- #endif
- }
- }
- #endif
|