Back to home page

EIC code displayed by LXR

 
 

    


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 //  Copyright (c) 2012 Robert Ramey
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #include <type_traits>
0011 #include <limits>
0012 
0013 namespace boost {
0014 namespace safe_numerics {
0015 namespace safe_compare {
0016 
0017 ////////////////////////////////////////////////////
0018 // safe comparison on primitive integral types
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     // both arguments unsigned or signed
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     // T unsigned, U signed
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     // T signed, U unsigned
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 } // safe_compare_detail
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     // both arguments unsigned or signed
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     // T unsigned, U signed
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     // T signed, U unsigned
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 } // safe_compare_detail
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 } // safe_compare
0177 } // safe_numerics
0178 } // boost
0179 
0180 #endif // BOOST_NUMERIC_SAFE_COMPARE_HPP