annotate DEPENDENCIES/generic/include/boost/accumulators/statistics/median.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 // median.hpp
Chris@16 3 //
Chris@16 4 // Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost
Chris@16 5 // Software License, Version 1.0. (See accompanying file
Chris@16 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005
Chris@16 9 #define BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005
Chris@16 10
Chris@16 11 #include <boost/mpl/placeholders.hpp>
Chris@16 12 #include <boost/range/iterator_range.hpp>
Chris@16 13 #include <boost/accumulators/framework/accumulator_base.hpp>
Chris@16 14 #include <boost/accumulators/framework/extractor.hpp>
Chris@16 15 #include <boost/accumulators/numeric/functional.hpp>
Chris@16 16 #include <boost/accumulators/framework/parameters/sample.hpp>
Chris@16 17 #include <boost/accumulators/framework/depends_on.hpp>
Chris@16 18 #include <boost/accumulators/statistics_fwd.hpp>
Chris@16 19 #include <boost/accumulators/statistics/count.hpp>
Chris@16 20 #include <boost/accumulators/statistics/p_square_quantile.hpp>
Chris@16 21 #include <boost/accumulators/statistics/density.hpp>
Chris@16 22 #include <boost/accumulators/statistics/p_square_cumul_dist.hpp>
Chris@16 23
Chris@16 24 namespace boost { namespace accumulators
Chris@16 25 {
Chris@16 26
Chris@16 27 namespace impl
Chris@16 28 {
Chris@16 29 ///////////////////////////////////////////////////////////////////////////////
Chris@16 30 // median_impl
Chris@16 31 //
Chris@16 32 /**
Chris@16 33 @brief Median estimation based on the \f$P^2\f$ quantile estimator
Chris@16 34
Chris@16 35 The \f$P^2\f$ algorithm is invoked with a quantile probability of 0.5.
Chris@16 36 */
Chris@16 37 template<typename Sample>
Chris@16 38 struct median_impl
Chris@16 39 : accumulator_base
Chris@16 40 {
Chris@16 41 // for boost::result_of
Chris@16 42 typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type;
Chris@16 43
Chris@16 44 median_impl(dont_care) {}
Chris@16 45
Chris@16 46 template<typename Args>
Chris@16 47 result_type result(Args const &args) const
Chris@16 48 {
Chris@16 49 return p_square_quantile_for_median(args);
Chris@16 50 }
Chris@16 51 };
Chris@16 52 ///////////////////////////////////////////////////////////////////////////////
Chris@16 53 // with_density_median_impl
Chris@16 54 //
Chris@16 55 /**
Chris@16 56 @brief Median estimation based on the density estimator
Chris@16 57
Chris@16 58 The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being
Chris@16 59 the total number of samples. It returns the approximate horizontal position of this sample,
Chris@16 60 based on a linear interpolation inside the bin.
Chris@16 61 */
Chris@16 62 template<typename Sample>
Chris@16 63 struct with_density_median_impl
Chris@16 64 : accumulator_base
Chris@16 65 {
Chris@16 66 typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
Chris@16 67 typedef std::vector<std::pair<float_type, float_type> > histogram_type;
Chris@16 68 typedef iterator_range<typename histogram_type::iterator> range_type;
Chris@16 69 // for boost::result_of
Chris@16 70 typedef float_type result_type;
Chris@16 71
Chris@16 72 template<typename Args>
Chris@16 73 with_density_median_impl(Args const &args)
Chris@16 74 : sum(numeric::fdiv(args[sample | Sample()], (std::size_t)1))
Chris@16 75 , is_dirty(true)
Chris@16 76 {
Chris@16 77 }
Chris@16 78
Chris@16 79 void operator ()(dont_care)
Chris@16 80 {
Chris@16 81 this->is_dirty = true;
Chris@16 82 }
Chris@16 83
Chris@16 84
Chris@16 85 template<typename Args>
Chris@16 86 result_type result(Args const &args) const
Chris@16 87 {
Chris@16 88 if (this->is_dirty)
Chris@16 89 {
Chris@16 90 this->is_dirty = false;
Chris@16 91
Chris@16 92 std::size_t cnt = count(args);
Chris@16 93 range_type histogram = density(args);
Chris@16 94 typename range_type::iterator it = histogram.begin();
Chris@16 95 while (this->sum < 0.5 * cnt)
Chris@16 96 {
Chris@16 97 this->sum += it->second * cnt;
Chris@16 98 ++it;
Chris@16 99 }
Chris@16 100 --it;
Chris@16 101 float_type over = numeric::fdiv(this->sum - 0.5 * cnt, it->second * cnt);
Chris@16 102 this->median = it->first * over + (it + 1)->first * (1. - over);
Chris@16 103 }
Chris@16 104
Chris@16 105 return this->median;
Chris@16 106 }
Chris@16 107
Chris@16 108 private:
Chris@16 109 mutable float_type sum;
Chris@16 110 mutable bool is_dirty;
Chris@16 111 mutable float_type median;
Chris@16 112 };
Chris@16 113
Chris@16 114 ///////////////////////////////////////////////////////////////////////////////
Chris@16 115 // with_p_square_cumulative_distribution_median_impl
Chris@16 116 //
Chris@16 117 /**
Chris@16 118 @brief Median estimation based on the \f$P^2\f$ cumulative distribution estimator
Chris@16 119
Chris@16 120 The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It
Chris@16 121 returns the approximate horizontal position of where the cumulative distribution
Chris@16 122 equals 0.5, based on a linear interpolation inside the bin.
Chris@16 123 */
Chris@16 124 template<typename Sample>
Chris@16 125 struct with_p_square_cumulative_distribution_median_impl
Chris@16 126 : accumulator_base
Chris@16 127 {
Chris@16 128 typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
Chris@16 129 typedef std::vector<std::pair<float_type, float_type> > histogram_type;
Chris@16 130 typedef iterator_range<typename histogram_type::iterator> range_type;
Chris@16 131 // for boost::result_of
Chris@16 132 typedef float_type result_type;
Chris@16 133
Chris@16 134 with_p_square_cumulative_distribution_median_impl(dont_care)
Chris@16 135 : is_dirty(true)
Chris@16 136 {
Chris@16 137 }
Chris@16 138
Chris@16 139 void operator ()(dont_care)
Chris@16 140 {
Chris@16 141 this->is_dirty = true;
Chris@16 142 }
Chris@16 143
Chris@16 144 template<typename Args>
Chris@16 145 result_type result(Args const &args) const
Chris@16 146 {
Chris@16 147 if (this->is_dirty)
Chris@16 148 {
Chris@16 149 this->is_dirty = false;
Chris@16 150
Chris@16 151 range_type histogram = p_square_cumulative_distribution(args);
Chris@16 152 typename range_type::iterator it = histogram.begin();
Chris@16 153 while (it->second < 0.5)
Chris@16 154 {
Chris@16 155 ++it;
Chris@16 156 }
Chris@16 157 float_type over = numeric::fdiv(it->second - 0.5, it->second - (it - 1)->second);
Chris@16 158 this->median = it->first * over + (it + 1)->first * ( 1. - over );
Chris@16 159 }
Chris@16 160
Chris@16 161 return this->median;
Chris@16 162 }
Chris@16 163 private:
Chris@16 164
Chris@16 165 mutable bool is_dirty;
Chris@16 166 mutable float_type median;
Chris@16 167 };
Chris@16 168
Chris@16 169 } // namespace impl
Chris@16 170
Chris@16 171 ///////////////////////////////////////////////////////////////////////////////
Chris@16 172 // tag::median
Chris@16 173 // tag::with_densisty_median
Chris@16 174 // tag::with_p_square_cumulative_distribution_median
Chris@16 175 //
Chris@16 176 namespace tag
Chris@16 177 {
Chris@16 178 struct median
Chris@16 179 : depends_on<p_square_quantile_for_median>
Chris@16 180 {
Chris@16 181 /// INTERNAL ONLY
Chris@16 182 ///
Chris@16 183 typedef accumulators::impl::median_impl<mpl::_1> impl;
Chris@16 184 };
Chris@16 185 struct with_density_median
Chris@16 186 : depends_on<count, density>
Chris@16 187 {
Chris@16 188 /// INTERNAL ONLY
Chris@16 189 ///
Chris@16 190 typedef accumulators::impl::with_density_median_impl<mpl::_1> impl;
Chris@16 191 };
Chris@16 192 struct with_p_square_cumulative_distribution_median
Chris@16 193 : depends_on<p_square_cumulative_distribution>
Chris@16 194 {
Chris@16 195 /// INTERNAL ONLY
Chris@16 196 ///
Chris@16 197 typedef accumulators::impl::with_p_square_cumulative_distribution_median_impl<mpl::_1> impl;
Chris@16 198 };
Chris@16 199 }
Chris@16 200
Chris@16 201 ///////////////////////////////////////////////////////////////////////////////
Chris@16 202 // extract::median
Chris@16 203 // extract::with_density_median
Chris@16 204 // extract::with_p_square_cumulative_distribution_median
Chris@16 205 //
Chris@16 206 namespace extract
Chris@16 207 {
Chris@16 208 extractor<tag::median> const median = {};
Chris@16 209 extractor<tag::with_density_median> const with_density_median = {};
Chris@16 210 extractor<tag::with_p_square_cumulative_distribution_median> const with_p_square_cumulative_distribution_median = {};
Chris@16 211
Chris@16 212 BOOST_ACCUMULATORS_IGNORE_GLOBAL(median)
Chris@16 213 BOOST_ACCUMULATORS_IGNORE_GLOBAL(with_density_median)
Chris@16 214 BOOST_ACCUMULATORS_IGNORE_GLOBAL(with_p_square_cumulative_distribution_median)
Chris@16 215 }
Chris@16 216
Chris@16 217 using extract::median;
Chris@16 218 using extract::with_density_median;
Chris@16 219 using extract::with_p_square_cumulative_distribution_median;
Chris@16 220
Chris@16 221 // median(with_p_square_quantile) -> median
Chris@16 222 template<>
Chris@16 223 struct as_feature<tag::median(with_p_square_quantile)>
Chris@16 224 {
Chris@16 225 typedef tag::median type;
Chris@16 226 };
Chris@16 227
Chris@16 228 // median(with_density) -> with_density_median
Chris@16 229 template<>
Chris@16 230 struct as_feature<tag::median(with_density)>
Chris@16 231 {
Chris@16 232 typedef tag::with_density_median type;
Chris@16 233 };
Chris@16 234
Chris@16 235 // median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_median
Chris@16 236 template<>
Chris@16 237 struct as_feature<tag::median(with_p_square_cumulative_distribution)>
Chris@16 238 {
Chris@16 239 typedef tag::with_p_square_cumulative_distribution_median type;
Chris@16 240 };
Chris@16 241
Chris@16 242 // for the purposes of feature-based dependency resolution,
Chris@16 243 // with_density_median and with_p_square_cumulative_distribution_median
Chris@16 244 // provide the same feature as median
Chris@16 245 template<>
Chris@16 246 struct feature_of<tag::with_density_median>
Chris@16 247 : feature_of<tag::median>
Chris@16 248 {
Chris@16 249 };
Chris@16 250
Chris@16 251 template<>
Chris@16 252 struct feature_of<tag::with_p_square_cumulative_distribution_median>
Chris@16 253 : feature_of<tag::median>
Chris@16 254 {
Chris@16 255 };
Chris@16 256
Chris@16 257 // So that median can be automatically substituted with
Chris@16 258 // weighted_median when the weight parameter is non-void.
Chris@16 259 template<>
Chris@16 260 struct as_weighted_feature<tag::median>
Chris@16 261 {
Chris@16 262 typedef tag::weighted_median type;
Chris@16 263 };
Chris@16 264
Chris@16 265 template<>
Chris@16 266 struct feature_of<tag::weighted_median>
Chris@16 267 : feature_of<tag::median>
Chris@16 268 {
Chris@16 269 };
Chris@16 270
Chris@16 271 // So that with_density_median can be automatically substituted with
Chris@16 272 // with_density_weighted_median when the weight parameter is non-void.
Chris@16 273 template<>
Chris@16 274 struct as_weighted_feature<tag::with_density_median>
Chris@16 275 {
Chris@16 276 typedef tag::with_density_weighted_median type;
Chris@16 277 };
Chris@16 278
Chris@16 279 template<>
Chris@16 280 struct feature_of<tag::with_density_weighted_median>
Chris@16 281 : feature_of<tag::with_density_median>
Chris@16 282 {
Chris@16 283 };
Chris@16 284
Chris@16 285 // So that with_p_square_cumulative_distribution_median can be automatically substituted with
Chris@16 286 // with_p_square_cumulative_distribution_weighted_median when the weight parameter is non-void.
Chris@16 287 template<>
Chris@16 288 struct as_weighted_feature<tag::with_p_square_cumulative_distribution_median>
Chris@16 289 {
Chris@16 290 typedef tag::with_p_square_cumulative_distribution_weighted_median type;
Chris@16 291 };
Chris@16 292
Chris@16 293 template<>
Chris@16 294 struct feature_of<tag::with_p_square_cumulative_distribution_weighted_median>
Chris@16 295 : feature_of<tag::with_p_square_cumulative_distribution_median>
Chris@16 296 {
Chris@16 297 };
Chris@16 298
Chris@16 299 }} // namespace boost::accumulators
Chris@16 300
Chris@16 301 #endif