detail_large_int_test.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2018-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/histogram/detail/large_int.hpp>
  8. #include <cstdint>
  9. #include <iosfwd>
  10. #include <limits>
  11. #include "std_ostream.hpp"
  12. namespace boost {
  13. namespace histogram {
  14. namespace detail {
  15. template <class Allocator>
  16. std::ostream& operator<<(std::ostream& os, const large_int<Allocator>& x) {
  17. os << "large_int" << x.data;
  18. return os;
  19. }
  20. } // namespace detail
  21. } // namespace histogram
  22. } // namespace boost
  23. using namespace boost::histogram;
  24. using large_int = detail::large_int<std::allocator<std::uint64_t>>;
  25. template <class... Ts>
  26. auto make_large_int(Ts... ts) {
  27. large_int r;
  28. r.data = {static_cast<uint64_t>(ts)...};
  29. return r;
  30. }
  31. int main() {
  32. // low-level tools
  33. {
  34. uint8_t c = 0;
  35. BOOST_TEST_EQ(detail::safe_increment(c), true);
  36. BOOST_TEST_EQ(c, 1);
  37. c = 255;
  38. BOOST_TEST_EQ(detail::safe_increment(c), false);
  39. BOOST_TEST_EQ(c, 255);
  40. c = 0;
  41. BOOST_TEST_EQ(detail::safe_radd(c, 255u), true);
  42. BOOST_TEST_EQ(c, 255);
  43. c = 1;
  44. BOOST_TEST_EQ(detail::safe_radd(c, 255u), false);
  45. BOOST_TEST_EQ(c, 1);
  46. c = 255;
  47. BOOST_TEST_EQ(detail::safe_radd(c, 1u), false);
  48. BOOST_TEST_EQ(c, 255);
  49. }
  50. const auto vmax = (std::numeric_limits<std::uint64_t>::max)();
  51. // ctors, assign
  52. {
  53. large_int a(42);
  54. large_int b(a);
  55. BOOST_TEST_EQ(b.data.front(), 42);
  56. large_int c(std::move(b));
  57. BOOST_TEST_EQ(c.data.front(), 42);
  58. large_int d, e;
  59. d = a;
  60. BOOST_TEST_EQ(d.data.front(), 42);
  61. e = std::move(c);
  62. BOOST_TEST_EQ(e.data.front(), 42);
  63. }
  64. // comparison
  65. {
  66. BOOST_TEST_EQ(large_int(), 0u);
  67. BOOST_TEST_EQ(large_int(1u), 1u);
  68. BOOST_TEST_EQ(large_int(1u), 1.0);
  69. BOOST_TEST_EQ(large_int(1u), large_int(1u));
  70. BOOST_TEST_NE(large_int(1u), 2u);
  71. BOOST_TEST_NE(large_int(1u), 2.0);
  72. BOOST_TEST_NE(large_int(1u), 2.0f);
  73. BOOST_TEST_NE(large_int(1u), large_int(2u));
  74. BOOST_TEST_LT(large_int(1u), 2u);
  75. BOOST_TEST_LT(large_int(1u), 2.0);
  76. BOOST_TEST_LT(large_int(1u), 2.0f);
  77. BOOST_TEST_LT(large_int(1u), large_int(2u));
  78. BOOST_TEST_LE(large_int(1u), 2u);
  79. BOOST_TEST_LE(large_int(1u), 2.0);
  80. BOOST_TEST_LE(large_int(1u), 2.0f);
  81. BOOST_TEST_LE(large_int(1u), large_int(2u));
  82. BOOST_TEST_LE(large_int(1u), 1u);
  83. BOOST_TEST_GT(large_int(1u), 0u);
  84. BOOST_TEST_GT(large_int(1u), 0.0);
  85. BOOST_TEST_GT(large_int(1u), 0.0f);
  86. BOOST_TEST_GT(large_int(1u), large_int(0u));
  87. BOOST_TEST_GE(large_int(1u), 0u);
  88. BOOST_TEST_GE(large_int(1u), 0.0);
  89. BOOST_TEST_GE(large_int(1u), 0.0f);
  90. BOOST_TEST_GE(large_int(1u), 1u);
  91. BOOST_TEST_GE(large_int(1u), large_int(0u));
  92. BOOST_TEST_NOT(large_int(1u) < large_int(1u));
  93. BOOST_TEST_NOT(large_int(1u) > large_int(1u));
  94. BOOST_TEST_GT(1, large_int());
  95. BOOST_TEST_LT(-1, large_int());
  96. BOOST_TEST_GE(1, large_int());
  97. BOOST_TEST_LE(-1, large_int());
  98. BOOST_TEST_NE(1, large_int());
  99. constexpr auto nan = std::numeric_limits<double>::quiet_NaN();
  100. BOOST_TEST_NOT(large_int(1u) < nan);
  101. BOOST_TEST_NOT(large_int(1u) > nan);
  102. BOOST_TEST_NOT(large_int(1u) == nan);
  103. BOOST_TEST(large_int(1u) != nan); // same behavior as int compared to nan
  104. BOOST_TEST_NOT(large_int(1u) <= nan);
  105. BOOST_TEST_NOT(large_int(1u) >= nan);
  106. BOOST_TEST_NOT(nan < large_int(1u));
  107. BOOST_TEST_NOT(nan > large_int(1u));
  108. BOOST_TEST_NOT(nan == large_int(1u));
  109. BOOST_TEST(nan != large_int(1u)); // same behavior as int compared to nan
  110. BOOST_TEST_NOT(nan <= large_int(1u));
  111. BOOST_TEST_NOT(nan >= large_int(1u));
  112. }
  113. // increment
  114. {
  115. auto a = large_int();
  116. ++a;
  117. BOOST_TEST_EQ(a.data.size(), 1);
  118. BOOST_TEST_EQ(a.data[0], 1);
  119. ++a;
  120. BOOST_TEST_EQ(a.data[0], 2);
  121. a = vmax;
  122. BOOST_TEST_EQ(a, vmax);
  123. BOOST_TEST_EQ(a, static_cast<double>(vmax));
  124. ++a;
  125. BOOST_TEST_EQ(a, make_large_int(0, 1));
  126. ++a;
  127. BOOST_TEST_EQ(a, make_large_int(1, 1));
  128. a += a;
  129. BOOST_TEST_EQ(a, make_large_int(2, 2));
  130. BOOST_TEST_EQ(a, 2 * static_cast<double>(vmax) + 2);
  131. // carry once A
  132. a.data[0] = vmax;
  133. a.data[1] = 1;
  134. ++a;
  135. BOOST_TEST_EQ(a, make_large_int(0, 2));
  136. // carry once B
  137. a.data[0] = vmax;
  138. a.data[1] = 1;
  139. a += 1;
  140. BOOST_TEST_EQ(a, make_large_int(0, 2));
  141. // carry once C
  142. a.data[0] = vmax;
  143. a.data[1] = 1;
  144. a += make_large_int(1, 1);
  145. BOOST_TEST_EQ(a, make_large_int(0, 3));
  146. a.data[0] = vmax - 1;
  147. a.data[1] = vmax;
  148. ++a;
  149. BOOST_TEST_EQ(a, make_large_int(vmax, vmax));
  150. // carry two times A
  151. ++a;
  152. BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
  153. // carry two times B
  154. a = make_large_int(vmax, vmax);
  155. a += 1;
  156. BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
  157. // carry two times C
  158. a = make_large_int(vmax, vmax);
  159. a += large_int(1);
  160. BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
  161. // carry and enlarge
  162. a = make_large_int(vmax, vmax);
  163. a += a;
  164. BOOST_TEST_EQ(a, make_large_int(vmax - 1, vmax, 1));
  165. // add smaller to larger
  166. a = make_large_int(1, 1, 1);
  167. a += make_large_int(1, 1);
  168. BOOST_TEST_EQ(a, make_large_int(2, 2, 1));
  169. // add larger to smaller
  170. a = make_large_int(1, 1);
  171. a += make_large_int(1, 1, 1);
  172. BOOST_TEST_EQ(a, make_large_int(2, 2, 1));
  173. a = large_int(1);
  174. auto b = 1.0;
  175. BOOST_TEST_EQ(a, b);
  176. for (unsigned i = 0; i < 80; ++i) {
  177. b += b;
  178. BOOST_TEST_NE(a, b);
  179. a += a;
  180. BOOST_TEST_EQ(a, b);
  181. }
  182. BOOST_TEST_GT(a.data.size(), 1u);
  183. }
  184. return boost::report_errors();
  185. }