Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:12

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_SAFE_COMPARISON_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_SAFE_COMPARISON_HPP
0009 
0010 #include <boost/mp11/utility.hpp>
0011 #include <boost/type.hpp>
0012 #include <type_traits>
0013 
0014 namespace boost {
0015 namespace histogram {
0016 namespace detail {
0017 
0018 template <class T>
0019 auto make_unsigned(const T& t) noexcept {
0020   static_assert(std::is_integral<T>::value, "");
0021   return static_cast<std::make_unsigned_t<T>>(t);
0022 }
0023 
0024 template <class T>
0025 using number_category =
0026     mp11::mp_if<std::is_integral<T>,
0027                 mp11::mp_if<std::is_signed<T>, type<int>, type<unsigned>>, type<void>>;
0028 
0029 // version of std::equal_to<> which handles signed and unsigned integers correctly
0030 struct safe_equal {
0031   template <class T, class U>
0032   bool operator()(const T& t, const U& u) const noexcept {
0033     return impl(number_category<T>{}, number_category<U>{}, t, u);
0034   }
0035 
0036   template <class C1, class C2, class T, class U>
0037   bool impl(C1, C2, const T& t, const U& u) const noexcept {
0038     return t == u;
0039   }
0040 
0041   template <class T, class U>
0042   bool impl(type<int>, type<unsigned>, const T& t, const U& u) const noexcept {
0043     return t >= 0 && make_unsigned(t) == u;
0044   }
0045 
0046   template <class T, class U>
0047   bool impl(type<unsigned>, type<int>, const T& t, const U& u) const noexcept {
0048     return impl(type<int>{}, type<unsigned>{}, u, t);
0049   }
0050 };
0051 
0052 // version of std::less<> which handles signed and unsigned integers correctly
0053 struct safe_less {
0054   template <class T, class U>
0055   bool operator()(const T& t, const U& u) const noexcept {
0056     return impl(number_category<T>{}, number_category<U>{}, t, u);
0057   }
0058 
0059   template <class C1, class C2, class T, class U>
0060   bool impl(C1, C2, const T& t, const U& u) const noexcept {
0061     return t < u;
0062   }
0063 
0064   template <class T, class U>
0065   bool impl(type<int>, type<unsigned>, const T& t, const U& u) const noexcept {
0066     return t < 0 || make_unsigned(t) < u;
0067   }
0068 
0069   template <class T, class U>
0070   bool impl(type<unsigned>, type<int>, const T& t, const U& u) const noexcept {
0071     return 0 < u && t < make_unsigned(u);
0072   }
0073 };
0074 
0075 // version of std::greater<> which handles signed and unsigned integers correctly
0076 struct safe_greater {
0077   template <class T, class U>
0078   bool operator()(const T& t, const U& u) const noexcept {
0079     return safe_less()(u, t);
0080   }
0081 };
0082 
0083 } // namespace detail
0084 } // namespace histogram
0085 } // namespace boost
0086 
0087 #endif