File indexing completed on 2025-01-18 09:51:36
0001 #ifndef BOOST_NUMERIC_CPP_HPP
0002 #define BOOST_NUMERIC_CPP_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <type_traits> // integral constant, remove_cv, conditional
0016 #include <limits>
0017 #include <boost/integer.hpp> // integer type selection
0018
0019 #include "safe_common.hpp"
0020 #include "checked_result.hpp"
0021
0022 namespace boost {
0023 namespace safe_numerics {
0024
0025
0026
0027
0028
0029
0030
0031
0032 template<
0033 int CharBits,
0034 int ShortBits,
0035 int IntBits,
0036 int LongBits,
0037 int LongLongBits
0038 >
0039 struct cpp {
0040 public:
0041 using local_char_type = typename boost::int_t<CharBits>::exact;
0042 using local_short_type = typename boost::int_t<ShortBits>::exact;
0043 using local_int_type = typename boost::int_t<IntBits>::exact;
0044 using local_long_type = typename boost::int_t<LongBits>::exact;
0045 using local_long_long_type = typename boost::int_t<LongLongBits>::exact;
0046
0047 template<class T>
0048 using rank =
0049 typename std::conditional<
0050 std::is_same<local_char_type, typename std::make_signed<T>::type>::value,
0051 std::integral_constant<int, 1>,
0052 typename std::conditional<
0053 std::is_same<local_short_type, typename std::make_signed<T>::type>::value,
0054 std::integral_constant<int, 2>,
0055 typename std::conditional<
0056 std::is_same<local_int_type, typename std::make_signed<T>::type>::value,
0057 std::integral_constant<int, 3>,
0058 typename std::conditional<
0059 std::is_same<local_long_type, typename std::make_signed<T>::type>::value,
0060 std::integral_constant<int, 4>,
0061 typename std::conditional<
0062 std::is_same<local_long_long_type, typename std::make_signed<T>::type>::value,
0063 std::integral_constant<int, 5>,
0064 std::integral_constant<int, 6>
0065 >::type >::type >::type >::type >::type;
0066
0067
0068
0069
0070 template<class T, class U>
0071 using higher_ranked_type = typename std::conditional<
0072 (rank<T>::value < rank<U>::value),
0073 U,
0074 T
0075 >::type;
0076
0077 template<class T, class U>
0078 using copy_sign = typename std::conditional<
0079 std::is_signed<U>::value,
0080 typename std::make_signed<T>::type,
0081 typename std::make_unsigned<T>::type
0082 >::type;
0083
0084 template<class T>
0085 using integral_promotion = copy_sign<
0086 higher_ranked_type<local_int_type, T>,
0087 T
0088 >;
0089
0090
0091
0092 template<class T, class U>
0093 using select_signed = typename std::conditional<
0094 std::numeric_limits<T>::is_signed,
0095 T,
0096 U
0097 >::type;
0098
0099 template<class T, class U>
0100 using select_unsigned = typename std::conditional<
0101 std::numeric_limits<T>::is_signed,
0102 U,
0103 T
0104 >::type;
0105
0106
0107 template<typename T, typename U>
0108 using usual_arithmetic_conversions =
0109
0110 typename std::conditional<
0111 std::is_same<T, U>::value,
0112
0113 T,
0114
0115 typename std::conditional<
0116 std::numeric_limits<T>::is_signed
0117 == std::numeric_limits<U>::is_signed,
0118
0119 higher_ranked_type<T, U>,
0120
0121
0122 typename std::conditional<
0123 rank<select_unsigned<T, U>>::value
0124 >= rank< select_signed<T, U>>::value,
0125
0126 select_unsigned<T, U>,
0127
0128
0129 typename std::conditional<
0130 std::numeric_limits< select_signed<T, U>>::digits >=
0131 std::numeric_limits< select_unsigned<T, U>>::digits,
0132
0133 select_signed<T, U>,
0134
0135 std::make_signed< select_signed<T, U>>
0136 >::type >::type >::type
0137 >;
0138
0139 template<typename T, typename U>
0140 using result_type = typename usual_arithmetic_conversions<
0141 integral_promotion<typename base_type<T>::type>,
0142 integral_promotion<typename base_type<U>::type>
0143 >::type;
0144 public:
0145 template<typename T, typename U>
0146 struct addition_result {
0147 using type = result_type<T, U>;
0148 };
0149 template<typename T, typename U>
0150 struct subtraction_result {
0151 using type = result_type<T, U>;
0152 };
0153 template<typename T, typename U>
0154 struct multiplication_result {
0155 using type = result_type<T, U>;
0156 };
0157 template<typename T, typename U>
0158 struct division_result {
0159 using type = result_type<T, U>;
0160 };
0161 template<typename T, typename U>
0162 struct modulus_result {
0163 using type = result_type<T, U>;
0164 };
0165
0166
0167
0168 template<typename T, typename U>
0169 struct comparison_result {
0170 using type = result_type<T, U>;
0171 };
0172 template<typename T, typename U>
0173 struct left_shift_result {
0174 using type = result_type<T, U>;
0175 };
0176 template<typename T, typename U>
0177 struct right_shift_result {
0178 using type = result_type<T, U>;
0179 };
0180 template<typename T, typename U>
0181 struct bitwise_and_result {
0182 using type = result_type<T, U>;
0183 };
0184 template<typename T, typename U>
0185 struct bitwise_or_result {
0186 using type = result_type<T, U>;
0187 };
0188 template<typename T, typename U>
0189 struct bitwise_xor_result {
0190 using type = result_type<T, U>;
0191 };
0192 };
0193
0194 }
0195 }
0196
0197 #endif