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_OPERATORS_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
0009 
0010 #include <boost/histogram/detail/detect.hpp>
0011 #include <boost/mp11/algorithm.hpp>
0012 #include <boost/mp11/list.hpp>
0013 #include <boost/mp11/utility.hpp>
0014 #include <type_traits>
0015 
0016 namespace boost {
0017 namespace histogram {
0018 namespace detail {
0019 
0020 template <class T, class U>
0021 using if_not_same = std::enable_if_t<(!std::is_same<T, U>::value), bool>;
0022 
0023 // template <class T, class U>
0024 // using if_not_same_and_has_eq =
0025 //     std::enable_if_t<(!std::is_same<T, U>::value && !has_method_eq<T, U>::value),
0026 //     bool>;
0027 
0028 // totally_ordered is for types with a <= b == !(a > b) [floats with NaN violate this]
0029 // Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
0030 
0031 // partially_ordered is for types with a <= b == a < b || a == b [for floats with NaN]
0032 // Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
0033 
0034 template <class T, class U>
0035 struct mirrored {
0036   friend bool operator<(const U& a, const T& b) noexcept { return b > a; }
0037   friend bool operator>(const U& a, const T& b) noexcept { return b < a; }
0038   friend bool operator==(const U& a, const T& b) noexcept { return b == a; }
0039   friend bool operator<=(const U& a, const T& b) noexcept { return b >= a; }
0040   friend bool operator>=(const U& a, const T& b) noexcept { return b <= a; }
0041   friend bool operator!=(const U& a, const T& b) noexcept { return b != a; }
0042 }; // namespace histogram
0043 
0044 template <class T>
0045 struct mirrored<T, void> {
0046   template <class U>
0047   friend if_not_same<T, U> operator<(const U& a, const T& b) noexcept {
0048     return b > a;
0049   }
0050   template <class U>
0051   friend if_not_same<T, U> operator>(const U& a, const T& b) noexcept {
0052     return b < a;
0053   }
0054   template <class U>
0055   friend std::enable_if_t<(!has_method_eq<U, T>::value), bool> operator==(
0056       const U& a, const T& b) noexcept {
0057     return b.operator==(a);
0058   }
0059   template <class U>
0060   friend if_not_same<T, U> operator<=(const U& a, const T& b) noexcept {
0061     return b >= a;
0062   }
0063   template <class U>
0064   friend if_not_same<T, U> operator>=(const U& a, const T& b) noexcept {
0065     return b <= a;
0066   }
0067   template <class U>
0068   friend if_not_same<T, U> operator!=(const U& a, const T& b) noexcept {
0069     return b != a;
0070   }
0071 };
0072 
0073 template <class T>
0074 struct mirrored<T, T> {
0075   friend bool operator>(const T& a, const T& b) noexcept { return b.operator<(a); }
0076 };
0077 
0078 template <class T, class U>
0079 struct equality {
0080   friend bool operator!=(const T& a, const U& b) noexcept { return !a.operator==(b); }
0081 };
0082 
0083 template <class T>
0084 struct equality<T, void> {
0085   template <class U>
0086   friend if_not_same<T, U> operator!=(const T& a, const U& b) noexcept {
0087     return !(a == b);
0088   }
0089 };
0090 
0091 template <class T, class U>
0092 struct totally_ordered_impl : equality<T, U>, mirrored<T, U> {
0093   friend bool operator<=(const T& a, const U& b) noexcept { return !(a > b); }
0094   friend bool operator>=(const T& a, const U& b) noexcept { return !(a < b); }
0095 };
0096 
0097 template <class T>
0098 struct totally_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
0099   template <class U>
0100   friend if_not_same<T, U> operator<=(const T& a, const U& b) noexcept {
0101     return !(a > b);
0102   }
0103   template <class U>
0104   friend if_not_same<T, U> operator>=(const T& a, const U& b) noexcept {
0105     return !(a < b);
0106   }
0107 };
0108 
0109 template <class T, class... Ts>
0110 using totally_ordered = mp11::mp_rename<
0111     mp11::mp_product<totally_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
0112     mp11::mp_inherit>;
0113 
0114 template <class T, class U>
0115 struct partially_ordered_impl : equality<T, U>, mirrored<T, U> {
0116   friend bool operator<=(const T& a, const U& b) noexcept { return a < b || a == b; }
0117   friend bool operator>=(const T& a, const U& b) noexcept { return a > b || a == b; }
0118 };
0119 
0120 template <class T>
0121 struct partially_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
0122   template <class U>
0123   friend if_not_same<T, U> operator<=(const T& a, const U& b) noexcept {
0124     return a < b || a == b;
0125   }
0126   template <class U>
0127   friend if_not_same<T, U> operator>=(const T& a, const U& b) noexcept {
0128     return a > b || a == b;
0129   }
0130 };
0131 
0132 template <class T, class... Ts>
0133 using partially_ordered = mp11::mp_rename<
0134     mp11::mp_product<partially_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
0135     mp11::mp_inherit>;
0136 
0137 } // namespace detail
0138 } // namespace histogram
0139 } // namespace boost
0140 
0141 #endif // BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP