count.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #ifndef BOOST_HISTOGRAM_ACCUMULATORS_NUMBER_HPP
  7. #define BOOST_HISTOGRAM_ACCUMULATORS_NUMBER_HPP
  8. #include <boost/core/nvp.hpp>
  9. #include <boost/histogram/fwd.hpp> // for count<>
  10. #include <type_traits> // for std::common_type
  11. namespace boost {
  12. namespace histogram {
  13. namespace accumulators {
  14. /**
  15. Uses a C++ builtin arithmetic type to accumulate a count.
  16. This wrapper class may be used as a base class by users who want to add custom metadata
  17. to each bin of a histogram. Otherwise, arithmetic types should be used directly as
  18. accumulators in storages for simplicity. In other words, prefer `dense_storage<double>`
  19. over `dense_storage<count<double>>`, both are functionally equivalent.
  20. When weighted data is accumulated and high precision is required, use
  21. `accumulators::sum` instead. If a local variance estimate for the weight distribution
  22. should be computed as well (generally needed for a detailed statistical analysis), use
  23. `accumulators::weighted_sum`.
  24. */
  25. template <class ValueType>
  26. class count {
  27. public:
  28. using value_type = ValueType;
  29. using const_reference = const value_type&;
  30. count() = default;
  31. /// Initialize count to value and allow implicit conversion
  32. count(const_reference value) noexcept : value_(value) {}
  33. /// Allow implicit conversion from other count
  34. template <class T>
  35. count(const count<T>& c) noexcept : count(c.value()) {}
  36. /// Increment count by one
  37. count& operator++() noexcept {
  38. ++value_;
  39. return *this;
  40. }
  41. /// Increment count by value
  42. count& operator+=(const_reference value) noexcept {
  43. value_ += value;
  44. return *this;
  45. }
  46. /// Add another count
  47. count& operator+=(const count& s) noexcept {
  48. value_ += s.value_;
  49. return *this;
  50. }
  51. /// Scale by value
  52. count& operator*=(const_reference value) noexcept {
  53. value_ *= value;
  54. return *this;
  55. }
  56. bool operator==(const count& rhs) const noexcept { return value_ == rhs.value_; }
  57. bool operator!=(const count& rhs) const noexcept { return !operator==(rhs); }
  58. /// Return count
  59. const_reference value() const noexcept { return value_; }
  60. // conversion to value_type must be explicit
  61. explicit operator value_type() const noexcept { return value_; }
  62. template <class Archive>
  63. void serialize(Archive& ar, unsigned /* version */) {
  64. ar& make_nvp("value", value_);
  65. }
  66. // begin: extra operators to make count behave like a regular number
  67. count& operator*=(const count& rhs) noexcept {
  68. value_ *= rhs.value_;
  69. return *this;
  70. }
  71. count operator*(const count& rhs) const noexcept {
  72. count x = *this;
  73. x *= rhs;
  74. return x;
  75. }
  76. count& operator/=(const count& rhs) noexcept {
  77. value_ /= rhs.value_;
  78. return *this;
  79. }
  80. count operator/(const count& rhs) const noexcept {
  81. count x = *this;
  82. x /= rhs;
  83. return x;
  84. }
  85. bool operator<(const count& rhs) const noexcept { return value_ < rhs.value_; }
  86. bool operator>(const count& rhs) const noexcept { return value_ > rhs.value_; }
  87. bool operator<=(const count& rhs) const noexcept { return value_ <= rhs.value_; }
  88. bool operator>=(const count& rhs) const noexcept { return value_ >= rhs.value_; }
  89. // end: extra operators
  90. private:
  91. value_type value_{};
  92. };
  93. } // namespace accumulators
  94. } // namespace histogram
  95. } // namespace boost
  96. #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
  97. namespace std {
  98. template <class T, class U>
  99. struct common_type<boost::histogram::accumulators::count<T>,
  100. boost::histogram::accumulators::count<U>> {
  101. using type = boost::histogram::accumulators::count<common_type_t<T, U>>;
  102. };
  103. } // namespace std
  104. #endif
  105. #endif