1 /////////////////////////////////////////////////////////////////////////////// 2 // weighted_sum_kahan.hpp 3 // 4 // Copyright 2011 Simon West. 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_SUM_KAHAN_HPP_EAN_11_05_2011 9 #define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_KAHAN_HPP_EAN_11_05_2011 10 11 #include <boost/mpl/placeholders.hpp> 12 #include <boost/accumulators/framework/accumulator_base.hpp> 13 #include <boost/accumulators/framework/extractor.hpp> 14 #include <boost/accumulators/numeric/functional.hpp> 15 #include <boost/accumulators/framework/parameters/sample.hpp> 16 #include <boost/accumulators/framework/parameters/weight.hpp> 17 #include <boost/accumulators/framework/accumulators/external_accumulator.hpp> 18 #include <boost/accumulators/framework/depends_on.hpp> 19 #include <boost/accumulators/statistics_fwd.hpp> 20 #include <boost/accumulators/statistics/weighted_sum.hpp> 21 #include <boost/numeric/conversion/cast.hpp> 22 23 namespace boost { namespace accumulators 24 { 25 26 namespace impl 27 { 28 #if _MSC_VER > 1400 29 # pragma float_control(push) 30 # pragma float_control(precise, on) 31 #endif 32 33 /////////////////////////////////////////////////////////////////////////////// 34 // weighted_sum_kahan_impl 35 template<typename Sample, typename Weight, typename Tag> 36 struct weighted_sum_kahan_impl 37 : accumulator_base 38 { 39 typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; 40 41 // for boost::result_of 42 typedef weighted_sample result_type; 43 44 template<typename Args> weighted_sum_kahan_implboost::accumulators::impl::weighted_sum_kahan_impl45 weighted_sum_kahan_impl(Args const &args) 46 : weighted_sum_( 47 args[parameter::keyword<Tag>::get() | Sample()] * numeric::one<Weight>::value), 48 compensation(boost::numeric_cast<weighted_sample>(0.0)) 49 { 50 } 51 52 template<typename Args> 53 void 54 #if BOOST_ACCUMULATORS_GCC_VERSION > 40305 55 __attribute__((__optimize__("no-associative-math"))) 56 #endif operator ()boost::accumulators::impl::weighted_sum_kahan_impl57 operator ()(Args const &args) 58 { 59 const weighted_sample myTmp1 = args[parameter::keyword<Tag>::get()] * args[weight] - this->compensation; 60 const weighted_sample myTmp2 = this->weighted_sum_ + myTmp1; 61 this->compensation = (myTmp2 - this->weighted_sum_) - myTmp1; 62 this->weighted_sum_ = myTmp2; 63 64 } 65 resultboost::accumulators::impl::weighted_sum_kahan_impl66 result_type result(dont_care) const 67 { 68 return this->weighted_sum_; 69 } 70 71 // make this accumulator serializeable 72 template<class Archive> serializeboost::accumulators::impl::weighted_sum_kahan_impl73 void serialize(Archive & ar, const unsigned int file_version) 74 { 75 ar & weighted_sum_; 76 ar & compensation; 77 } 78 79 private: 80 weighted_sample weighted_sum_; 81 weighted_sample compensation; 82 }; 83 84 #if _MSC_VER > 1400 85 # pragma float_control(pop) 86 #endif 87 88 } // namespace impl 89 90 /////////////////////////////////////////////////////////////////////////////// 91 // tag::weighted_sum_kahan 92 // tag::weighted_sum_of_variates_kahan 93 // 94 namespace tag 95 { 96 struct weighted_sum_kahan 97 : depends_on<> 98 { 99 /// INTERNAL ONLY 100 /// 101 typedef accumulators::impl::weighted_sum_kahan_impl<mpl::_1, mpl::_2, tag::sample> impl; 102 }; 103 104 template<typename VariateType, typename VariateTag> 105 struct weighted_sum_of_variates_kahan 106 : depends_on<> 107 { 108 /// INTERNAL ONLY 109 /// 110 typedef accumulators::impl::weighted_sum_kahan_impl<VariateType, mpl::_2, VariateTag> impl; 111 }; 112 113 } 114 115 /////////////////////////////////////////////////////////////////////////////// 116 // extract::weighted_sum_kahan 117 // extract::weighted_sum_of_variates_kahan 118 // 119 namespace extract 120 { 121 extractor<tag::weighted_sum_kahan> const weighted_sum_kahan = {}; 122 extractor<tag::abstract_weighted_sum_of_variates> const weighted_sum_of_variates_kahan = {}; 123 124 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_kahan) 125 BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_of_variates_kahan) 126 } 127 128 using extract::weighted_sum_kahan; 129 using extract::weighted_sum_of_variates_kahan; 130 131 // weighted_sum(kahan) -> weighted_sum_kahan 132 template<> 133 struct as_feature<tag::weighted_sum(kahan)> 134 { 135 typedef tag::weighted_sum_kahan type; 136 }; 137 138 template<typename VariateType, typename VariateTag> 139 struct feature_of<tag::weighted_sum_of_variates_kahan<VariateType, VariateTag> > 140 : feature_of<tag::abstract_weighted_sum_of_variates> 141 { 142 }; 143 144 }} // namespace boost::accumulators 145 146 #endif 147