]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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 | |
40 | count(const_reference value) noexcept : value_(value) {} | |
41 | ||
42 | /// Allow implicit conversion from other count | |
43 | template <class T> | |
44 | count(const count<T>& c) noexcept : count(c.value()) {} | |
45 | ||
46 | /// Increment count by one | |
47 | count& operator++() noexcept { | |
48 | ++value_; | |
49 | return *this; | |
50 | } | |
51 | ||
52 | /// Increment count by value | |
53 | count& operator+=(const_reference value) noexcept { | |
54 | value_ += value; | |
55 | return *this; | |
56 | } | |
57 | ||
58 | /// Add another count | |
59 | count& operator+=(const count& s) noexcept { | |
60 | value_ += s.value_; | |
61 | return *this; | |
62 | } | |
63 | ||
64 | /// Scale by value | |
65 | count& operator*=(const_reference value) noexcept { | |
66 | value_ *= value; | |
67 | return *this; | |
68 | } | |
69 | ||
70 | bool operator==(const count& rhs) const noexcept { return value_ == rhs.value_; } | |
71 | ||
72 | bool operator!=(const count& rhs) const noexcept { return !operator==(rhs); } | |
73 | ||
74 | /// Return count | |
75 | const_reference value() const noexcept { return value_; } | |
76 | ||
77 | // conversion to value_type must be explicit | |
78 | explicit operator value_type() const noexcept { return value_; } | |
79 | ||
80 | template <class Archive> | |
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 | ||
87 | count& operator*=(const count& rhs) noexcept { | |
88 | value_ *= rhs.value_; | |
89 | return *this; | |
90 | } | |
91 | ||
92 | count operator*(const count& rhs) const noexcept { | |
93 | count x = *this; | |
94 | x *= rhs; | |
95 | return x; | |
96 | } | |
97 | ||
98 | count& operator/=(const count& rhs) noexcept { | |
99 | value_ /= rhs.value_; | |
100 | return *this; | |
101 | } | |
102 | ||
103 | count operator/(const count& rhs) const noexcept { | |
104 | count x = *this; | |
105 | x /= rhs; | |
106 | return x; | |
107 | } | |
108 | ||
109 | bool operator<(const count& rhs) const noexcept { return value_ < rhs.value_; } | |
110 | ||
111 | bool operator>(const count& rhs) const noexcept { return value_ > rhs.value_; } | |
112 | ||
113 | bool operator<=(const count& rhs) const noexcept { return value_ <= rhs.value_; } | |
114 | ||
115 | 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 |