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