histogram_operators_test.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2015-2018 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/is_same.hpp>
  7. #include <boost/core/lightweight_test.hpp>
  8. #include <boost/core/lightweight_test_trait.hpp>
  9. #include <boost/histogram/axis.hpp>
  10. #include <boost/histogram/axis/ostream.hpp>
  11. #include <boost/histogram/histogram.hpp>
  12. #include <boost/histogram/ostream.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <string>
  15. #include <vector>
  16. #include "std_ostream.hpp"
  17. #include "throw_exception.hpp"
  18. #include "utility_histogram.hpp"
  19. using namespace boost::histogram;
  20. template <typename Tag>
  21. void run_tests() {
  22. // arithmetic operators
  23. {
  24. auto a = make(Tag(), axis::integer<int, use_default, axis::option::none_t>(0, 2));
  25. auto b = a;
  26. a(0);
  27. b(1);
  28. auto c = a + b;
  29. BOOST_TEST_EQ(c.at(0), 1);
  30. BOOST_TEST_EQ(c.at(1), 1);
  31. c += b;
  32. BOOST_TEST_EQ(c.at(0), 1);
  33. BOOST_TEST_EQ(c.at(1), 2);
  34. auto d = a + b + c;
  35. BOOST_TEST_TRAIT_SAME(decltype(d), decltype(a));
  36. BOOST_TEST_EQ(d.at(0), 2);
  37. BOOST_TEST_EQ(d.at(1), 3);
  38. auto d2 = d - a - b - c;
  39. BOOST_TEST_TRAIT_SAME(decltype(d2), decltype(a));
  40. BOOST_TEST_EQ(d2.at(0), 0);
  41. BOOST_TEST_EQ(d2.at(1), 0);
  42. d2 -= a;
  43. BOOST_TEST_EQ(d2.at(0), -1);
  44. BOOST_TEST_EQ(d2.at(1), 0);
  45. auto d3 = d;
  46. d3 *= d;
  47. BOOST_TEST_EQ(d3.at(0), 4);
  48. BOOST_TEST_EQ(d3.at(1), 9);
  49. auto d4 = d3 * (1 * d); // converted return type
  50. BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(d4), decltype(d3)>));
  51. BOOST_TEST_EQ(d4.at(0), 8);
  52. BOOST_TEST_EQ(d4.at(1), 27);
  53. d4 /= d;
  54. BOOST_TEST_EQ(d4.at(0), 4);
  55. BOOST_TEST_EQ(d4.at(1), 9);
  56. auto d5 = d4 / d;
  57. BOOST_TEST_EQ(d5.at(0), 2);
  58. BOOST_TEST_EQ(d5.at(1), 3);
  59. auto e = 3 * a; // converted return type
  60. auto f = b * 2; // converted return type
  61. BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(e), decltype(a)>));
  62. BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(f), decltype(a)>));
  63. BOOST_TEST_EQ(e.at(0), 3);
  64. BOOST_TEST_EQ(e.at(1), 0);
  65. BOOST_TEST_EQ(f.at(0), 0);
  66. BOOST_TEST_EQ(f.at(1), 2);
  67. auto r = 1.0 * a;
  68. r += b;
  69. r += e;
  70. BOOST_TEST_EQ(r.at(0), 4);
  71. BOOST_TEST_EQ(r.at(1), 1);
  72. BOOST_TEST_EQ(r, a + b + 3 * a);
  73. auto s = r / 4;
  74. r /= 4;
  75. BOOST_TEST_EQ(r.at(0), 1);
  76. BOOST_TEST_EQ(r.at(1), 0.25);
  77. BOOST_TEST_EQ(r, s);
  78. }
  79. // arithmetic operators with mixed storage: unlimited vs. vector<unsigned>
  80. {
  81. auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
  82. auto a = make(Tag(), ia);
  83. a(0, weight(2));
  84. a(1, weight(2));
  85. auto b = a;
  86. auto c = make_s(Tag(), std::vector<int>(), ia);
  87. c(0, weight(2));
  88. c(1, weight(2));
  89. auto a2 = a;
  90. a2 += c;
  91. BOOST_TEST_EQ(a2, (a + b));
  92. auto a3 = a;
  93. a3 *= c;
  94. BOOST_TEST_EQ(a3, (a * b));
  95. auto a4 = a;
  96. a4 -= c;
  97. BOOST_TEST_EQ(a4, (a - b));
  98. auto a5 = a;
  99. a5 /= c;
  100. BOOST_TEST_EQ(a5, (a / b));
  101. }
  102. // arithmetic operators with mixed storage: vector<unsigned char> vs. vector<unsigned>
  103. {
  104. auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
  105. auto a = make_s(Tag(), std::vector<unsigned long>{}, ia);
  106. auto c = make_s(Tag(), std::vector<unsigned>(), ia);
  107. a(0, weight(2u));
  108. a(1, weight(2u));
  109. auto b = a;
  110. c(0, weight(2u));
  111. c(1, weight(2u));
  112. auto a2 = a;
  113. a2 += c;
  114. BOOST_TEST_EQ(a2, (a + b));
  115. auto a3 = a;
  116. a3 *= c;
  117. BOOST_TEST_EQ(a3, (a * b));
  118. auto a4 = a;
  119. a4 -= c;
  120. BOOST_TEST_EQ(a4, (a - b));
  121. auto a5 = a;
  122. a5 /= c;
  123. BOOST_TEST_EQ(a5, (a / b));
  124. }
  125. // add operators with weighted storage
  126. {
  127. auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
  128. auto a = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
  129. auto b = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
  130. a(0);
  131. BOOST_TEST_EQ(a.at(0).variance(), 1);
  132. b(weight(3), 1);
  133. BOOST_TEST_EQ(b.at(1).variance(), 9);
  134. auto c = a;
  135. c += b;
  136. BOOST_TEST_EQ(c.at(0).value(), 1);
  137. BOOST_TEST_EQ(c.at(0).variance(), 1);
  138. BOOST_TEST_EQ(c.at(1).value(), 3);
  139. BOOST_TEST_EQ(c.at(1).variance(), 9);
  140. auto d = a;
  141. d += b;
  142. BOOST_TEST_EQ(d.at(0).value(), 1);
  143. BOOST_TEST_EQ(d.at(0).variance(), 1);
  144. BOOST_TEST_EQ(d.at(1).value(), 3);
  145. BOOST_TEST_EQ(d.at(1).variance(), 9);
  146. }
  147. // bad operations
  148. {
  149. auto a = make(Tag(), axis::integer<>(0, 2));
  150. auto b = make(Tag(), axis::integer<>(0, 3));
  151. BOOST_TEST_THROWS(a += b, std::invalid_argument);
  152. BOOST_TEST_THROWS(a -= b, std::invalid_argument);
  153. BOOST_TEST_THROWS(a *= b, std::invalid_argument);
  154. BOOST_TEST_THROWS(a /= b, std::invalid_argument);
  155. }
  156. }
  157. int main() {
  158. run_tests<static_tag>();
  159. run_tests<dynamic_tag>();
  160. return boost::report_errors();
  161. }