detail_operators_test.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. #include <boost/core/lightweight_test.hpp>
  7. #include <boost/core/lightweight_test_trait.hpp>
  8. #include <boost/histogram/detail/operators.hpp>
  9. #include <limits>
  10. #include <ostream>
  11. using namespace boost::histogram::detail;
  12. struct TotallyOrdered : totally_ordered<TotallyOrdered, TotallyOrdered, void> {
  13. TotallyOrdered(int i) : x(i) {}
  14. bool operator<(const TotallyOrdered& o) const noexcept { return x < o.x; }
  15. bool operator==(const TotallyOrdered& o) const noexcept { return x == o.x; }
  16. bool operator<(const int& o) const noexcept { return x < o; }
  17. bool operator>(const int& o) const noexcept { return x > o; }
  18. bool operator==(const int& o) const noexcept { return x == o; }
  19. int x;
  20. };
  21. std::ostream& operator<<(std::ostream& os, const TotallyOrdered& t) {
  22. os << t.x;
  23. return os;
  24. }
  25. struct PartiallyOrdered : partially_ordered<PartiallyOrdered, PartiallyOrdered, void> {
  26. PartiallyOrdered(double i) : x(i) {}
  27. bool operator<(const PartiallyOrdered& o) const noexcept { return x < o.x; }
  28. bool operator==(const PartiallyOrdered& o) const noexcept { return x == o.x; }
  29. bool operator<(const double& o) const noexcept { return x < o; }
  30. bool operator>(const double& o) const noexcept { return x > o; }
  31. bool operator==(const double& o) const noexcept { return x == o; }
  32. double x;
  33. };
  34. std::ostream& operator<<(std::ostream& os, const PartiallyOrdered& t) {
  35. os << t.x;
  36. return os;
  37. }
  38. template <class T, class U>
  39. void test_nan(std::false_type) {}
  40. template <class T, class U>
  41. void test_nan(std::true_type) {
  42. const U nan = std::numeric_limits<U>::quiet_NaN();
  43. // IEEE 754: Any comparison with nan is false, except != which is true.
  44. // But some of the following tests fail on MSVC:
  45. // BOOST_TEST_NOT(nan < nan); // true, should be false
  46. // BOOST_TEST_NOT(nan > nan);
  47. // BOOST_TEST_NOT(nan == nan);
  48. // BOOST_TEST_NOT(nan <= nan); // true, should be false
  49. // BOOST_TEST_NOT(nan >= nan);
  50. // BOOST_TEST(nan != nan);
  51. // Probably related:
  52. // https://developercommunity.visualstudio.com/content/problem/445462/nan-nan-is-constant-folded-to-true-but-should-prob.html
  53. // The tests below don't fail probably because constant-folding doesn't happen.
  54. BOOST_TEST_NOT(T(1.0) < T(nan));
  55. BOOST_TEST_NOT(T(1.0) > T(nan));
  56. BOOST_TEST_NOT(T(1.0) == T(nan));
  57. BOOST_TEST_NOT(T(1.0) <= T(nan));
  58. BOOST_TEST_NOT(T(1.0) >= T(nan));
  59. BOOST_TEST(T(1.0) != T(nan));
  60. BOOST_TEST_NOT(T(nan) < 1.0);
  61. BOOST_TEST_NOT(T(nan) > 1.0);
  62. BOOST_TEST_NOT(T(nan) == 1.0);
  63. BOOST_TEST_NOT(T(nan) <= 1.0);
  64. BOOST_TEST_NOT(T(nan) >= 1.0);
  65. BOOST_TEST(T(nan) != 1.0);
  66. BOOST_TEST_NOT(1.0 < T(nan));
  67. BOOST_TEST_NOT(1.0 > T(nan));
  68. BOOST_TEST_NOT(1.0 == T(nan));
  69. BOOST_TEST_NOT(1.0 <= T(nan));
  70. BOOST_TEST_NOT(1.0 >= T(nan));
  71. BOOST_TEST(1.0 != T(nan));
  72. BOOST_TEST_NOT(T(nan) < T(nan));
  73. BOOST_TEST_NOT(T(nan) > T(nan));
  74. BOOST_TEST_NOT(T(nan) == T(nan));
  75. BOOST_TEST_NOT(T(nan) <= T(nan));
  76. BOOST_TEST_NOT(T(nan) >= T(nan));
  77. BOOST_TEST(T(nan) != T(nan));
  78. BOOST_TEST_NOT(T(nan) < nan);
  79. BOOST_TEST_NOT(T(nan) > nan);
  80. BOOST_TEST_NOT(T(nan) == nan);
  81. BOOST_TEST_NOT(T(nan) <= nan);
  82. BOOST_TEST_NOT(T(nan) >= nan);
  83. BOOST_TEST(T(nan) != nan);
  84. BOOST_TEST_NOT(nan < T(nan));
  85. BOOST_TEST_NOT(nan > T(nan));
  86. BOOST_TEST_NOT(nan == T(nan));
  87. BOOST_TEST_NOT(nan <= T(nan));
  88. BOOST_TEST_NOT(nan >= T(nan));
  89. BOOST_TEST(nan != T(nan));
  90. }
  91. template <class T, class U>
  92. void test() {
  93. T x{1};
  94. U e{1}, l{0}, u{2};
  95. BOOST_TEST_EQ(x, e);
  96. BOOST_TEST_NE(x, l);
  97. BOOST_TEST_LT(x, u);
  98. BOOST_TEST_GT(x, l);
  99. BOOST_TEST_LE(x, e);
  100. BOOST_TEST_LE(x, u);
  101. BOOST_TEST_GE(x, e);
  102. BOOST_TEST_GE(x, l);
  103. BOOST_TEST_EQ(e, x);
  104. BOOST_TEST_NE(l, x);
  105. BOOST_TEST_LT(l, x);
  106. BOOST_TEST_GT(u, x);
  107. BOOST_TEST_LE(e, x);
  108. BOOST_TEST_LE(l, x);
  109. BOOST_TEST_GE(e, x);
  110. BOOST_TEST_GE(u, x);
  111. test_nan<T, U>(std::is_floating_point<U>{});
  112. }
  113. int main() {
  114. test<TotallyOrdered, TotallyOrdered>();
  115. test<TotallyOrdered, int>();
  116. test<PartiallyOrdered, PartiallyOrdered>();
  117. test<PartiallyOrdered, double>();
  118. return boost::report_errors();
  119. }