• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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