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 <typename RealType> 20 class weighted_sum { 21 public: 22 weighted_sum() = default; weighted_sum(const RealType & value)23 explicit weighted_sum(const RealType& value) noexcept 24 : sum_of_weights_(value), sum_of_weights_squared_(value) {} weighted_sum(const RealType & value,const RealType & variance)25 weighted_sum(const RealType& value, const RealType& variance) noexcept 26 : sum_of_weights_(value), sum_of_weights_squared_(variance) {} 27 28 /// Increment by one. operator ++()29 weighted_sum& operator++() { return operator+=(1); } 30 31 /// Increment by value. 32 template <typename T> operator +=(const T & value)33 weighted_sum& operator+=(const T& value) { 34 sum_of_weights_ += value; 35 sum_of_weights_squared_ += value * value; 36 return *this; 37 } 38 39 /// Added another weighted sum. 40 template <typename T> operator +=(const weighted_sum<T> & rhs)41 weighted_sum& operator+=(const weighted_sum<T>& rhs) { 42 sum_of_weights_ += static_cast<RealType>(rhs.sum_of_weights_); 43 sum_of_weights_squared_ += static_cast<RealType>(rhs.sum_of_weights_squared_); 44 return *this; 45 } 46 47 /// Scale by value. operator *=(const RealType & x)48 weighted_sum& operator*=(const RealType& x) { 49 sum_of_weights_ *= x; 50 sum_of_weights_squared_ *= x * x; 51 return *this; 52 } 53 operator ==(const RealType & rhs) const54 bool operator==(const RealType& rhs) const noexcept { 55 return sum_of_weights_ == rhs && sum_of_weights_squared_ == rhs; 56 } 57 58 template <typename T> operator ==(const weighted_sum<T> & rhs) const59 bool operator==(const weighted_sum<T>& rhs) const noexcept { 60 return sum_of_weights_ == rhs.sum_of_weights_ && 61 sum_of_weights_squared_ == rhs.sum_of_weights_squared_; 62 } 63 64 template <typename T> operator !=(const T & rhs) const65 bool operator!=(const T& rhs) const noexcept { 66 return !operator==(rhs); 67 } 68 69 /// Return value of the sum. value() const70 const RealType& value() const noexcept { return sum_of_weights_; } 71 72 /// Return estimated variance of the sum. variance() const73 const RealType& variance() const noexcept { return sum_of_weights_squared_; } 74 75 // lossy conversion must be explicit 76 template <class T> operator T() const77 explicit operator T() const { 78 return static_cast<T>(sum_of_weights_); 79 } 80 81 template <class Archive> serialize(Archive & ar,unsigned)82 void serialize(Archive& ar, unsigned /* version */) { 83 ar& make_nvp("sum_of_weights", sum_of_weights_); 84 ar& make_nvp("sum_of_weights_squared", sum_of_weights_squared_); 85 } 86 87 private: 88 RealType sum_of_weights_ = RealType(); 89 RealType sum_of_weights_squared_ = RealType(); 90 }; 91 92 } // namespace accumulators 93 } // namespace histogram 94 } // namespace boost 95 96 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED 97 namespace std { 98 template <class T, class U> 99 struct common_type<boost::histogram::accumulators::weighted_sum<T>, 100 boost::histogram::accumulators::weighted_sum<U>> { 101 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 102 }; 103 104 template <class T, class U> 105 struct common_type<boost::histogram::accumulators::weighted_sum<T>, U> { 106 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 107 }; 108 109 template <class T, class U> 110 struct common_type<T, boost::histogram::accumulators::weighted_sum<U>> { 111 using type = boost::histogram::accumulators::weighted_sum<common_type_t<T, U>>; 112 }; 113 } // namespace std 114 #endif 115 116 #endif 117