1 /////////////////////////////////////////////////////////////////////////////// 2 // weighted_mean.hpp 3 // 4 // Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost 5 // Software License, Version 1.0. (See accompanying file 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 9 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 10 11 #include <boost/mpl/assert.hpp> 12 #include <boost/mpl/eval_if.hpp> 13 #include <boost/mpl/placeholders.hpp> 14 #include <boost/type_traits/is_same.hpp> 15 #include <boost/accumulators/framework/accumulator_base.hpp> 16 #include <boost/accumulators/framework/extractor.hpp> 17 #include <boost/accumulators/numeric/functional.hpp> 18 #include <boost/accumulators/framework/parameters/weights.hpp> 19 #include <boost/accumulators/framework/depends_on.hpp> 20 #include <boost/accumulators/statistics_fwd.hpp> 21 #include <boost/accumulators/statistics/sum.hpp> 22 #include <boost/accumulators/statistics/mean.hpp> 23 #include <boost/accumulators/statistics/weighted_sum.hpp> 24 25 namespace boost { namespace accumulators 26 { 27 28 namespace impl 29 { 30 /////////////////////////////////////////////////////////////////////////////// 31 // weighted_mean_impl 32 // lazy, by default 33 template<typename Sample, typename Weight, typename Tag> 34 struct weighted_mean_impl 35 : accumulator_base 36 { 37 typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; 38 // for boost::result_of 39 typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; 40 weighted_mean_implboost::accumulators::impl::weighted_mean_impl41 weighted_mean_impl(dont_care) {} 42 43 template<typename Args> resultboost::accumulators::impl::weighted_mean_impl44 result_type result(Args const &args) const 45 { 46 typedef 47 typename mpl::if_< 48 is_same<Tag, tag::sample> 49 , tag::weighted_sum 50 , tag::weighted_sum_of_variates<Sample, Tag> 51 >::type 52 weighted_sum_tag; 53 54 extractor<weighted_sum_tag> const some_weighted_sum = {}; 55 56 return numeric::fdiv(some_weighted_sum(args), sum_of_weights(args)); 57 } 58 }; 59 60 /////////////////////////////////////////////////////////////////////////////// 61 // immediate_weighted_mean_impl 62 // immediate 63 template<typename Sample, typename Weight, typename Tag> 64 struct immediate_weighted_mean_impl 65 : accumulator_base 66 { 67 typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; 68 // for boost::result_of 69 typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; 70 71 template<typename Args> immediate_weighted_mean_implboost::accumulators::impl::immediate_weighted_mean_impl72 immediate_weighted_mean_impl(Args const &args) 73 : mean( 74 numeric::fdiv( 75 args[parameter::keyword<Tag>::get() | Sample()] 76 * numeric::one<Weight>::value 77 , numeric::one<Weight>::value 78 ) 79 ) 80 { 81 } 82 83 template<typename Args> operator ()boost::accumulators::impl::immediate_weighted_mean_impl84 void operator ()(Args const &args) 85 { 86 // Matthias: 87 // need to pass the argument pack since the weight might be an external 88 // accumulator set passed as a named parameter 89 Weight w_sum = sum_of_weights(args); 90 Weight w = args[weight]; 91 weighted_sample const &s = args[parameter::keyword<Tag>::get()] * w; 92 this->mean = numeric::fdiv(this->mean * (w_sum - w) + s, w_sum); 93 } 94 resultboost::accumulators::impl::immediate_weighted_mean_impl95 result_type result(dont_care) const 96 { 97 return this->mean; 98 } 99 100 // make this accumulator serializeable 101 template<class Archive> serializeboost::accumulators::impl::immediate_weighted_mean_impl102 void serialize(Archive & ar, const unsigned int file_version) 103 { 104 ar & mean; 105 } 106 107 private: 108 result_type mean; 109 }; 110 111 } // namespace impl 112 113 /////////////////////////////////////////////////////////////////////////////// 114 // tag::weighted_mean 115 // tag::immediate_weighted_mean 116 // 117 namespace tag 118 { 119 struct weighted_mean 120 : depends_on<sum_of_weights, weighted_sum> 121 { 122 /// INTERNAL ONLY 123 /// 124 typedef accumulators::impl::weighted_mean_impl<mpl::_1, mpl::_2, tag::sample> impl; 125 }; 126 struct immediate_weighted_mean 127 : depends_on<sum_of_weights> 128 { 129 /// INTERNAL ONLY 130 /// 131 typedef accumulators::impl::immediate_weighted_mean_impl<mpl::_1, mpl::_2, tag::sample> impl; 132 }; 133 template<typename VariateType, typename VariateTag> 134 struct weighted_mean_of_variates 135 : depends_on<sum_of_weights, weighted_sum_of_variates<VariateType, VariateTag> > 136 { 137 /// INTERNAL ONLY 138 /// 139 typedef accumulators::impl::weighted_mean_impl<VariateType, mpl::_2, VariateTag> impl; 140 }; 141 template<typename VariateType, typename VariateTag> 142 struct immediate_weighted_mean_of_variates 143 : depends_on<sum_of_weights> 144 { 145 /// INTERNAL ONLY 146 /// 147 typedef accumulators::impl::immediate_weighted_mean_impl<VariateType, mpl::_2, VariateTag> impl; 148 }; 149 } 150 151 /////////////////////////////////////////////////////////////////////////////// 152 // extract::weighted_mean 153 // extract::weighted_mean_of_variates 154 // 155 namespace extract 156 { 157 extractor<tag::mean> const weighted_mean = {}; 158 BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, weighted_mean_of_variates, (typename)(typename)) 159 160 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_mean) 161 } 162 163 using extract::weighted_mean; 164 using extract::weighted_mean_of_variates; 165 166 // weighted_mean(lazy) -> weighted_mean 167 template<> 168 struct as_feature<tag::weighted_mean(lazy)> 169 { 170 typedef tag::weighted_mean type; 171 }; 172 173 // weighted_mean(immediate) -> immediate_weighted_mean 174 template<> 175 struct as_feature<tag::weighted_mean(immediate)> 176 { 177 typedef tag::immediate_weighted_mean type; 178 }; 179 180 // weighted_mean_of_variates<VariateType, VariateTag>(lazy) -> weighted_mean_of_variates<VariateType, VariateTag> 181 template<typename VariateType, typename VariateTag> 182 struct as_feature<tag::weighted_mean_of_variates<VariateType, VariateTag>(lazy)> 183 { 184 typedef tag::weighted_mean_of_variates<VariateType, VariateTag> type; 185 }; 186 187 // weighted_mean_of_variates<VariateType, VariateTag>(immediate) -> immediate_weighted_mean_of_variates<VariateType, VariateTag> 188 template<typename VariateType, typename VariateTag> 189 struct as_feature<tag::weighted_mean_of_variates<VariateType, VariateTag>(immediate)> 190 { 191 typedef tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> type; 192 }; 193 194 }} // namespace boost::accumulators 195 196 #endif 197