1 // Copyright 2015-2018 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_WEIGHTED_SUM_HPP 8 #define BOOST_HISTOGRAM_ACCUMULATORS_WEIGHTED_SUM_HPP 9 10 #include <boost/core/nvp.hpp> 11 #include <boost/histogram/fwd.hpp> // for weighted_sum<> 12 #include <type_traits> 13 14 namespace boost { 15 namespace histogram { 16 namespace accumulators { 17 18 /// Holds sum of weights and its variance estimate 19 template <class ValueType> 20 class weighted_sum { 21 public: 22 using value_type = ValueType; 23 using const_reference = const value_type&; 24 25 weighted_sum() = default; 26 27 /// Initialize sum to value and allow implicit conversion weighted_sum(const_reference value)28 weighted_sum(const_reference value) noexcept : weighted_sum(value, value) {} 29 30 /// Allow implicit conversion from sum<T> 31 template <class T> weighted_sum(const weighted_sum<T> & s)32 weighted_sum(const weighted_sum<T>& s) noexcept 33 : weighted_sum(s.value(), s.variance()) {} 34 35 /// Initialize sum to value and variance weighted_sum(const_reference value,const_reference variance)36 weighted_sum(const_reference value, const_reference variance) noexcept 37 : sum_of_weights_(value), sum_of_weights_squared_(variance) {} 38 39 /// Increment by one. operator ++()40 weighted_sum& operator++() { 41 ++sum_of_weights_; 42 ++sum_of_weights_squared_; 43 return *this; 44 } 45 46 /// Increment by weight. 47 template <class T> operator +=(const weight_type<T> & w)48 weighted_sum& operator+=(const weight_type<T>& w) { 49 sum_of_weights_ += w.value; 50 sum_of_weights_squared_ += w.value * w.value; 51 return *this; 52 } 53 54 /// Added another weighted sum. operator +=(const weighted_sum & rhs)55 weighted_sum& operator+=(const weighted_sum& rhs) { 56 sum_of_weights_ += rhs.sum_of_weights_; 57 sum_of_weights_squared_ += rhs.sum_of_weights_squared_; 58 return *this; 59 } 60 61 /// Scale by value. operator *=(const_reference x)62 weighted_sum& operator*=(const_reference x) { 63 sum_of_weights_ *= x; 64 sum_of_weights_squared_ *= x * x; 65 return *this; 66 } 67 operator ==(const weighted_sum & rhs) const68 bool operator==(const weighted_sum& rhs) const noexcept { 69 return sum_of_weights_ == rhs.sum_of_weights_ && 70 sum_of_weights_squared_ == rhs.sum_of_weights_squared_; 71 } 72 operator !=(const weighted_sum & rhs) const73 bool operator!=(const weighted_sum& rhs) const noexcept { return !operator==(rhs); } 74 75 /// Return value of the sum. value() const76 const_reference value() const noexcept { return sum_of_weights_; } 77 78 /// Return estimated variance of the sum. variance() const79 const_reference variance() const noexcept { return sum_of_weights_squared_; } 80 81 // lossy conversion must be explicit operator const_reference() const82 explicit operator const_reference() const { return sum_of_weights_; } 83 84 template <class Archive> serialize(Archive & ar,unsigned)85 void serialize(Archive& ar, unsigned /* version */) { 86 ar& make_nvp("sum_of_weights", sum_of_weights_); 87 ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_); 88 } 89 90 private: 91 value_type sum_of_weights_{}; 92 value_type sum_of_weights_squared_{}; 93 }; 94 95 } // namespace accumulators 96 } // namespace histogram 97 } // namespace boost 98 99 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED 100 namespace std { 101 template <class T, class U> 102 struct common_type<boost::histogram::accumulators::weighted_sum<T>, 103 boost::histogram::accumulators::weighted_sum<U>> { 104 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 105 }; 106 107 template <class T, class U> 108 struct common_type<boost::histogram::accumulators::weighted_sum<T>, U> { 109 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 110 }; 111 112 template <class T, class U> 113 struct common_type<T, boost::histogram::accumulators::weighted_sum<U>> { 114 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 115 }; 116 } // namespace std 117 #endif 118 119 #endif 120