• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <boost/core/lightweight_test.hpp>
8 #include <boost/core/lightweight_test_trait.hpp>
9 #include <boost/histogram/detail/operators.hpp>
10 #include <limits>
11 #include <ostream>
12 
13 using namespace boost::histogram::detail;
14 
15 struct TotallyOrdered : totally_ordered<TotallyOrdered, TotallyOrdered, void> {
TotallyOrderedTotallyOrdered16   TotallyOrdered(int i) : x(i) {}
17 
operator <TotallyOrdered18   bool operator<(const TotallyOrdered& o) const noexcept { return x < o.x; }
operator ==TotallyOrdered19   bool operator==(const TotallyOrdered& o) const noexcept { return x == o.x; }
operator <TotallyOrdered20   bool operator<(const int& o) const noexcept { return x < o; }
operator >TotallyOrdered21   bool operator>(const int& o) const noexcept { return x > o; }
operator ==TotallyOrdered22   bool operator==(const int& o) const noexcept { return x == o; }
23 
24   int x;
25 };
26 
operator <<(std::ostream & os,const TotallyOrdered & t)27 std::ostream& operator<<(std::ostream& os, const TotallyOrdered& t) {
28   os << t.x;
29   return os;
30 }
31 
32 struct PartiallyOrdered : partially_ordered<PartiallyOrdered, PartiallyOrdered, void> {
PartiallyOrderedPartiallyOrdered33   PartiallyOrdered(double i) : x(i) {}
34 
operator <PartiallyOrdered35   bool operator<(const PartiallyOrdered& o) const noexcept { return x < o.x; }
operator ==PartiallyOrdered36   bool operator==(const PartiallyOrdered& o) const noexcept { return x == o.x; }
operator <PartiallyOrdered37   bool operator<(const double& o) const noexcept { return x < o; }
operator >PartiallyOrdered38   bool operator>(const double& o) const noexcept { return x > o; }
operator ==PartiallyOrdered39   bool operator==(const double& o) const noexcept { return x == o; }
40 
41   double x;
42 };
43 
operator <<(std::ostream & os,const PartiallyOrdered & t)44 std::ostream& operator<<(std::ostream& os, const PartiallyOrdered& t) {
45   os << t.x;
46   return os;
47 }
48 
49 template <class T, class U>
test_nan(std::false_type)50 void test_nan(std::false_type) {}
51 
52 template <class T, class U>
test_nan(std::true_type)53 void test_nan(std::true_type) {
54   const U nan = std::numeric_limits<U>::quiet_NaN();
55 
56   // IEEE 754: Any comparison with nan is false, except != which is true.
57   // But some of the following tests fail on MSVC:
58   //   BOOST_TEST_NOT(nan < nan); // true, should be false
59   //   BOOST_TEST_NOT(nan > nan);
60   //   BOOST_TEST_NOT(nan == nan);
61   //   BOOST_TEST_NOT(nan <= nan); // true, should be false
62   //   BOOST_TEST_NOT(nan >= nan);
63   //   BOOST_TEST(nan != nan);
64   // Probably related:
65   // https://developercommunity.visualstudio.com/content/problem/445462/nan-nan-is-constant-folded-to-true-but-should-prob.html
66   // The tests below don't fail probably because constant-folding doesn't happen.
67 
68   BOOST_TEST_NOT(T(1.0) < T(nan));
69   BOOST_TEST_NOT(T(1.0) > T(nan));
70   BOOST_TEST_NOT(T(1.0) == T(nan));
71   BOOST_TEST_NOT(T(1.0) <= T(nan));
72   BOOST_TEST_NOT(T(1.0) >= T(nan));
73   BOOST_TEST(T(1.0) != T(nan));
74 
75   BOOST_TEST_NOT(T(nan) < 1.0);
76   BOOST_TEST_NOT(T(nan) > 1.0);
77   BOOST_TEST_NOT(T(nan) == 1.0);
78   BOOST_TEST_NOT(T(nan) <= 1.0);
79   BOOST_TEST_NOT(T(nan) >= 1.0);
80   BOOST_TEST(T(nan) != 1.0);
81 
82   BOOST_TEST_NOT(1.0 < T(nan));
83   BOOST_TEST_NOT(1.0 > T(nan));
84   BOOST_TEST_NOT(1.0 == T(nan));
85   BOOST_TEST_NOT(1.0 <= T(nan));
86   BOOST_TEST_NOT(1.0 >= T(nan));
87   BOOST_TEST(1.0 != T(nan));
88 
89   BOOST_TEST_NOT(T(nan) < T(nan));
90   BOOST_TEST_NOT(T(nan) > T(nan));
91   BOOST_TEST_NOT(T(nan) == T(nan));
92   BOOST_TEST_NOT(T(nan) <= T(nan));
93   BOOST_TEST_NOT(T(nan) >= T(nan));
94   BOOST_TEST(T(nan) != T(nan));
95 
96   BOOST_TEST_NOT(T(nan) < nan);
97   BOOST_TEST_NOT(T(nan) > nan);
98   BOOST_TEST_NOT(T(nan) == nan);
99   BOOST_TEST_NOT(T(nan) <= nan);
100   BOOST_TEST_NOT(T(nan) >= nan);
101   BOOST_TEST(T(nan) != nan);
102 
103   BOOST_TEST_NOT(nan < T(nan));
104   BOOST_TEST_NOT(nan > T(nan));
105   BOOST_TEST_NOT(nan == T(nan));
106   BOOST_TEST_NOT(nan <= T(nan));
107   BOOST_TEST_NOT(nan >= T(nan));
108   BOOST_TEST(nan != T(nan));
109 }
110 
111 template <class T, class U>
test()112 void test() {
113   T x{1};
114   U e{1}, l{0}, u{2};
115   BOOST_TEST_EQ(x, e);
116   BOOST_TEST_NE(x, l);
117   BOOST_TEST_LT(x, u);
118   BOOST_TEST_GT(x, l);
119   BOOST_TEST_LE(x, e);
120   BOOST_TEST_LE(x, u);
121   BOOST_TEST_GE(x, e);
122   BOOST_TEST_GE(x, l);
123 
124   BOOST_TEST_EQ(e, x);
125   BOOST_TEST_NE(l, x);
126   BOOST_TEST_LT(l, x);
127   BOOST_TEST_GT(u, x);
128   BOOST_TEST_LE(e, x);
129   BOOST_TEST_LE(l, x);
130   BOOST_TEST_GE(e, x);
131   BOOST_TEST_GE(u, x);
132 
133   test_nan<T, U>(std::is_floating_point<U>{});
134 }
135 
main()136 int main() {
137   test<TotallyOrdered, TotallyOrdered>();
138   test<TotallyOrdered, int>();
139   test<PartiallyOrdered, PartiallyOrdered>();
140   test<PartiallyOrdered, double>();
141 
142   return boost::report_errors();
143 }
144