Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:43

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_ACCUMULATORS_COUNT_HPP
0008 #define BOOST_HISTOGRAM_ACCUMULATORS_COUNT_HPP
0009 
0010 #include <boost/core/nvp.hpp>
0011 #include <boost/histogram/detail/atomic_number.hpp>
0012 #include <boost/histogram/fwd.hpp> // for count<>
0013 #include <type_traits>             // for std::common_type
0014 
0015 namespace boost {
0016 namespace histogram {
0017 namespace accumulators {
0018 
0019 /**
0020   Wraps a C++ arithmetic type with optionally thread-safe increments and adds.
0021 
0022   This adaptor optionally uses atomic operations to make concurrent increments and
0023   additions thread-safe for the stored arithmetic value, which can be integral or
0024   floating point. For small histograms, the performance will still be poor because of
0025   False Sharing, see https://en.wikipedia.org/wiki/False_sharing for details.
0026 
0027   Warning: Assignment is not thread-safe in this implementation, so don't assign
0028   concurrently.
0029 
0030   This wrapper class can be used as a base class by users to add arbitrary metadata to
0031   each bin of a histogram.
0032 
0033   When weighted samples are accumulated and high precision is required, use
0034   `accumulators::sum` instead (at the cost of lower performance). If a local variance
0035   estimate for the weight distribution should be computed as well (generally needed for a
0036   detailed statistical analysis), use `accumulators::weighted_sum`.
0037 
0038   @tparam T C++ builtin arithmetic type (integer or floating point).
0039   @tparam ThreadSafe Set to true to make increments and adds thread-safe.
0040 */
0041 template <class ValueType, bool ThreadSafe>
0042 class count {
0043   using internal_type =
0044       std::conditional_t<ThreadSafe, detail::atomic_number<ValueType>, ValueType>;
0045 
0046 public:
0047   using value_type = ValueType;
0048   using const_reference = const value_type&;
0049 
0050   count() noexcept = default;
0051 
0052   /// Initialize count to value and allow implicit conversion
0053   count(const_reference value) noexcept : value_{value} {}
0054 
0055   /// Allow implicit conversion from other count
0056   template <class T, bool B>
0057   count(const count<T, B>& c) noexcept : count{c.value()} {}
0058 
0059   /// Increment count by one
0060   count& operator++() noexcept {
0061     ++value_;
0062     return *this;
0063   }
0064 
0065   /// Increment count by value
0066   count& operator+=(const_reference value) noexcept {
0067     value_ += value;
0068     return *this;
0069   }
0070 
0071   /// Add another count
0072   count& operator+=(const count& s) noexcept {
0073     value_ += s.value_;
0074     return *this;
0075   }
0076 
0077   /// Scale by value
0078   count& operator*=(const_reference value) noexcept {
0079     value_ *= value;
0080     return *this;
0081   }
0082 
0083   bool operator==(const count& rhs) const noexcept { return value_ == rhs.value_; }
0084 
0085   bool operator!=(const count& rhs) const noexcept { return !operator==(rhs); }
0086 
0087   /// Return count
0088   value_type value() const noexcept { return value_; }
0089 
0090   // conversion to value_type must be explicit
0091   explicit operator value_type() const noexcept { return value_; }
0092 
0093   template <class Archive>
0094   void serialize(Archive& ar, unsigned /* version */) {
0095     auto v = value();
0096     ar& make_nvp("value", v);
0097     value_ = v;
0098   }
0099 
0100   static constexpr bool thread_safe() noexcept { return ThreadSafe; }
0101 
0102   // begin: extra operators to make count behave like a regular number
0103 
0104   count& operator*=(const count& rhs) noexcept {
0105     value_ *= rhs.value_;
0106     return *this;
0107   }
0108 
0109   count operator*(const count& rhs) const noexcept {
0110     count x = *this;
0111     x *= rhs;
0112     return x;
0113   }
0114 
0115   count& operator/=(const count& rhs) noexcept {
0116     value_ /= rhs.value_;
0117     return *this;
0118   }
0119 
0120   count operator/(const count& rhs) const noexcept {
0121     count x = *this;
0122     x /= rhs;
0123     return x;
0124   }
0125 
0126   bool operator<(const count& rhs) const noexcept { return value_ < rhs.value_; }
0127 
0128   bool operator>(const count& rhs) const noexcept { return value_ > rhs.value_; }
0129 
0130   bool operator<=(const count& rhs) const noexcept { return value_ <= rhs.value_; }
0131 
0132   bool operator>=(const count& rhs) const noexcept { return value_ >= rhs.value_; }
0133 
0134   friend bool operator==(const_reference x, const count& rhs) noexcept {
0135     return x == rhs.value_;
0136   }
0137 
0138   friend bool operator!=(const_reference x, const count& rhs) noexcept {
0139     return x != rhs.value_;
0140   }
0141 
0142   friend bool operator<(const_reference x, const count& rhs) noexcept {
0143     return x < rhs.value_;
0144   }
0145 
0146   friend bool operator>(const_reference x, const count& rhs) noexcept {
0147     return x > rhs.value_;
0148   }
0149 
0150   friend bool operator<=(const_reference x, const count& rhs) noexcept {
0151     return x <= rhs.value_;
0152   }
0153   friend bool operator>=(const_reference x, const count& rhs) noexcept {
0154     return x >= rhs.value_;
0155   }
0156 
0157   // end: extra operators
0158 
0159 private:
0160   internal_type value_{};
0161 };
0162 
0163 } // namespace accumulators
0164 } // namespace histogram
0165 } // namespace boost
0166 
0167 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
0168 namespace std {
0169 template <class T, class U, bool B1, bool B2>
0170 struct common_type<boost::histogram::accumulators::count<T, B1>,
0171                    boost::histogram::accumulators::count<U, B2>> {
0172   using type = boost::histogram::accumulators::count<common_type_t<T, U>, (B1 || B2)>;
0173 };
0174 } // namespace std
0175 #endif
0176 
0177 #endif