File indexing completed on 2025-01-30 09:59:43
0001 #ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP
0002 #define BOOST_NUMERIC_SAFE_COMPARE_HPP
0003
0004
0005
0006
0007
0008
0009
0010 #include <type_traits>
0011 #include <limits>
0012
0013 namespace boost {
0014 namespace safe_numerics {
0015 namespace safe_compare {
0016
0017
0018
0019 namespace safe_compare_detail {
0020 template<typename T>
0021 using make_unsigned = typename std::conditional<
0022 std::is_signed<T>::value,
0023 std::make_unsigned<T>,
0024 T
0025 >::type;
0026
0027
0028 template<bool TS, bool US>
0029 struct less_than {
0030 template<class T, class U>
0031 constexpr static bool invoke(const T & t, const U & u){
0032 return t < u;
0033 }
0034 };
0035
0036
0037 template<>
0038 struct less_than<false, true> {
0039 template<class T, class U>
0040 constexpr static bool invoke(const T & t, const U & u){
0041 return
0042 (u < 0) ?
0043 false
0044 :
0045 less_than<false, false>::invoke(
0046 t,
0047 static_cast<const typename make_unsigned<U>::type &>(u)
0048 )
0049 ;
0050 }
0051 };
0052
0053 template<>
0054 struct less_than<true, false> {
0055 template<class T, class U>
0056 constexpr static bool invoke(const T & t, const U & u){
0057 return
0058 (t < 0) ?
0059 true
0060 :
0061 less_than<false, false>::invoke(
0062 static_cast<const typename make_unsigned<T>::type &>(t),
0063 u
0064 )
0065 ;
0066 }
0067 };
0068 }
0069
0070 template<class T, class U>
0071 typename std::enable_if<
0072 std::is_integral<T>::value && std::is_integral<U>::value,
0073 bool
0074 >::type
0075 constexpr inline less_than(const T & lhs, const U & rhs) {
0076 return safe_compare_detail::less_than<
0077 std::is_signed<T>::value,
0078 std::is_signed<U>::value
0079 >:: invoke(lhs, rhs);
0080 }
0081
0082 template<class T, class U>
0083 typename std::enable_if<
0084 std::is_floating_point<T>::value && std::is_floating_point<U>::value,
0085 bool
0086 >::type
0087 constexpr inline less_than(const T & lhs, const U & rhs) {
0088 return lhs < rhs;
0089 }
0090
0091 template<class T, class U>
0092 constexpr inline bool greater_than(const T & lhs, const U & rhs) {
0093 return less_than(rhs, lhs);
0094 }
0095
0096 template<class T, class U>
0097 constexpr inline bool less_than_equal(const T & lhs, const U & rhs) {
0098 return ! greater_than(lhs, rhs);
0099 }
0100
0101 template<class T, class U>
0102 constexpr inline bool greater_than_equal(const T & lhs, const U & rhs) {
0103 return ! less_than(lhs, rhs);
0104 }
0105
0106 namespace safe_compare_detail {
0107
0108 template<bool TS, bool US>
0109 struct equal {
0110 template<class T, class U>
0111 constexpr static bool invoke(const T & t, const U & u){
0112 return t == u;
0113 }
0114 };
0115
0116
0117 template<>
0118 struct equal<false, true> {
0119 template<class T, class U>
0120 constexpr static bool invoke(const T & t, const U & u){
0121 return
0122 (u < 0) ?
0123 false
0124 :
0125 equal<false, false>::invoke(
0126 t,
0127 static_cast<const typename make_unsigned<U>::type &>(u)
0128 )
0129 ;
0130 }
0131 };
0132
0133 template<>
0134 struct equal<true, false> {
0135 template<class T, class U>
0136 constexpr static bool invoke(const T & t, const U & u){
0137 return
0138 (t < 0) ?
0139 false
0140 :
0141 equal<false, false>::invoke(
0142 static_cast<const typename make_unsigned<T>::type &>(t),
0143 u
0144 )
0145 ;
0146 }
0147 };
0148 }
0149
0150 template<class T, class U>
0151 typename std::enable_if<
0152 std::is_integral<T>::value && std::is_integral<U>::value,
0153 bool
0154 >::type
0155 constexpr inline equal(const T & lhs, const U & rhs) {
0156 return safe_compare_detail::equal<
0157 std::numeric_limits<T>::is_signed,
0158 std::numeric_limits<U>::is_signed
0159 >:: invoke(lhs, rhs);
0160 }
0161
0162 template<class T, class U>
0163 typename std::enable_if<
0164 std::is_floating_point<T>::value && std::is_floating_point<U>::value,
0165 bool
0166 >::type
0167 constexpr inline equal(const T & lhs, const U & rhs) {
0168 return lhs == rhs;
0169 }
0170
0171 template<class T, class U>
0172 constexpr inline bool not_equal(const T & lhs, const U & rhs) {
0173 return ! equal(lhs, rhs);
0174 }
0175
0176 }
0177 }
0178 }
0179
0180 #endif