File indexing completed on 2025-10-31 08:56:04
0001 #ifndef BOOST_NUMERIC_EXCEPTION
0002 #define BOOST_NUMERIC_EXCEPTION
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 #include <algorithm>
0014 #include <system_error> // error_code, system_error
0015 #include <string>
0016 #include <cassert>
0017 #include <cstdint> // std::uint8_t
0018 
0019 
0020 
0021 
0022 
0023 
0024 namespace boost {
0025 namespace safe_numerics {
0026 
0027 
0028 
0029 
0030 
0031 
0032 
0033 
0034 enum class safe_numerics_error : std::uint8_t {
0035     success = 0,
0036     positive_overflow_error,    
0037     negative_overflow_error,    
0038     domain_error,               
0039     range_error,                
0040     precision_overflow_error,   
0041     underflow_error,            
0042     negative_value_shift,       
0043     negative_shift,             
0044     shift_too_large,            
0045     uninitialized_value         
0046 };
0047 
0048 constexpr inline const char * literal_string(const safe_numerics_error & e){
0049     switch(e){
0050     case safe_numerics_error::success: return "success";
0051     case safe_numerics_error::positive_overflow_error: return "positive_overflow_error";
0052     case safe_numerics_error::negative_overflow_error: return "negative_overflow_error";
0053     case safe_numerics_error::domain_error: return "domain_error";
0054     case safe_numerics_error::range_error: return "range_error";
0055     case safe_numerics_error::precision_overflow_error: return "precision_overflow_error";
0056     case safe_numerics_error::underflow_error: return "underflow_error";
0057     case safe_numerics_error::negative_value_shift: return "negative_value_shift";
0058     case safe_numerics_error::negative_shift: return "negative_shift";
0059     case safe_numerics_error::shift_too_large: return "shift_too_large";
0060     case safe_numerics_error::uninitialized_value: return "uninitialized_value";
0061     default:
0062         assert(false); 
0063     }
0064 }
0065 
0066 const std::uint8_t safe_numerics_casting_error_count =
0067     static_cast<std::uint8_t>(safe_numerics_error::domain_error) + 1;
0068 
0069 const std::uint8_t safe_numerics_error_count =
0070     static_cast<std::uint8_t>(safe_numerics_error::uninitialized_value) + 1;
0071 
0072 } 
0073 } 
0074 
0075 namespace std {
0076     template <>
0077     struct is_error_code_enum<boost::safe_numerics::safe_numerics_error>
0078         : public true_type {};
0079 } 
0080 
0081 namespace boost {
0082 namespace safe_numerics {
0083 
0084 const class : public std::error_category {
0085 public:
0086     virtual const char* name() const noexcept{
0087         return "safe numerics error";
0088     }
0089     virtual std::string message(int ev) const {
0090         switch(static_cast<safe_numerics_error>(ev)){
0091         case safe_numerics_error::success:
0092             return "success";
0093         case safe_numerics_error::positive_overflow_error:
0094             return "positive overflow error";
0095         case safe_numerics_error::negative_overflow_error:
0096             return "negative overflow error";
0097         case safe_numerics_error::underflow_error:
0098             return "underflow error";
0099         case safe_numerics_error::range_error:
0100             return "range error";
0101         case safe_numerics_error::precision_overflow_error:
0102             return "precision_overflow_error";
0103         case safe_numerics_error::domain_error:
0104             return "domain error";
0105         case safe_numerics_error::negative_shift:
0106             return "negative shift";
0107         case safe_numerics_error::negative_value_shift:
0108             return "negative value shift";
0109         case safe_numerics_error::shift_too_large:
0110             return "shift too large";
0111         case safe_numerics_error::uninitialized_value:
0112             return "uninitialized value";
0113         default:
0114             assert(false);
0115         }
0116         return ""; 
0117     }
0118 } safe_numerics_error_category {};
0119 
0120 
0121 inline std::error_code make_error_code(const safe_numerics_error & e){
0122     return std::error_code(static_cast<int>(e), safe_numerics_error_category);
0123 }
0124 
0125 
0126 
0127 
0128 
0129 enum class safe_numerics_actions {
0130     no_action = 0,
0131     uninitialized_value,
0132     arithmetic_error,
0133     implementation_defined_behavior,
0134     undefined_behavior
0135 };
0136 
0137 } 
0138 } 
0139 
0140 namespace std {
0141     template <>
0142     struct is_error_condition_enum<boost::safe_numerics::safe_numerics_actions>
0143         : public true_type {};
0144 } 
0145 
0146 namespace boost {
0147 namespace safe_numerics {
0148 
0149 const class : public std::error_category {
0150 public:
0151     virtual const char* name() const noexcept {
0152         return "safe numerics error group";
0153     }
0154     virtual std::string message(int) const {
0155         return "safe numerics error group";
0156     }
0157     
0158     
0159     virtual bool equivalent(
0160         const std::error_code & code,
0161         int condition
0162     ) const noexcept {
0163         if(code.category() != safe_numerics_error_category)
0164             return false;
0165         switch (static_cast<safe_numerics_actions>(condition)){
0166         case safe_numerics_actions::no_action:
0167             return code == safe_numerics_error::success;
0168         case safe_numerics_actions::uninitialized_value:
0169             return code == safe_numerics_error::uninitialized_value;
0170         case safe_numerics_actions::arithmetic_error:
0171             return code == safe_numerics_error::positive_overflow_error
0172                 || code == safe_numerics_error::negative_overflow_error
0173                 || code == safe_numerics_error::underflow_error
0174                 || code == safe_numerics_error::range_error
0175                 || code == safe_numerics_error::domain_error;
0176         case safe_numerics_actions::implementation_defined_behavior:
0177             return code == safe_numerics_error::negative_value_shift
0178                 || code == safe_numerics_error::negative_shift
0179                 || code == safe_numerics_error::shift_too_large;
0180         case safe_numerics_actions::undefined_behavior:
0181             return false;
0182         default:
0183             ;
0184         }
0185         
0186         assert(false);
0187         
0188         return false; 
0189     }
0190 } safe_numerics_actions_category {};
0191 
0192 
0193 
0194 
0195 
0196 #if 0
0197 std::error_condition make_error_condition(const safe_numerics_error & e) {
0198     return std::error_condition(
0199         static_cast<int>(e),
0200         safe_numerics_error_category
0201     );
0202 }
0203 #endif
0204 
0205 } 
0206 } 
0207 
0208 #endif