| 1 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 2 | // histogram.h
|
|---|
| 3 | //
|
|---|
| 4 | // Copyright 2006 Daniel Egloff, 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 | // Georg Gast (12.02.2017)
|
|---|
| 9 | // based on density.hpp
|
|---|
| 10 |
|
|---|
| 11 | #ifndef BOOST_ACCUMULATORS_STATISTICS_HISTOGRAM
|
|---|
| 12 | #define BOOST_ACCUMULATORS_STATISTICS_HISTOGRAM
|
|---|
| 13 |
|
|---|
| 14 | #include <boost/accumulators/accumulators_fwd.hpp>
|
|---|
| 15 | #include <boost/accumulators/framework/accumulator_base.hpp>
|
|---|
| 16 | #include <boost/accumulators/framework/depends_on.hpp>
|
|---|
| 17 | #include <boost/accumulators/framework/extractor.hpp>
|
|---|
| 18 | #include <boost/accumulators/framework/parameters/sample.hpp>
|
|---|
| 19 | #include <boost/accumulators/numeric/functional.hpp>
|
|---|
| 20 | #include <boost/accumulators/statistics_fwd.hpp>
|
|---|
| 21 | #include <boost/mpl/placeholders.hpp>
|
|---|
| 22 | #include <boost/parameter/keyword.hpp>
|
|---|
| 23 | #include <boost/range.hpp>
|
|---|
| 24 | #include <functional>
|
|---|
| 25 | #include <limits>
|
|---|
| 26 | #include <vector>
|
|---|
| 27 |
|
|---|
| 28 | namespace boost
|
|---|
| 29 | {
|
|---|
| 30 | namespace accumulators
|
|---|
| 31 | {
|
|---|
| 32 |
|
|---|
| 33 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 34 | // cache_size and num_bins named parameters
|
|---|
| 35 | //
|
|---|
| 36 | BOOST_PARAMETER_NESTED_KEYWORD(tag, histogram_limit_low, limit_low)
|
|---|
| 37 | BOOST_PARAMETER_NESTED_KEYWORD(tag, histogram_limit_high, limit_high)
|
|---|
| 38 | BOOST_PARAMETER_NESTED_KEYWORD(tag, histogram_num_bins, num_bins)
|
|---|
| 39 |
|
|---|
| 40 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(histogram_limit_low)
|
|---|
| 41 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(histogram_limit_high)
|
|---|
| 42 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(histogram_num_bins)
|
|---|
| 43 |
|
|---|
| 44 | namespace impl
|
|---|
| 45 | {
|
|---|
| 46 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 47 | // histogram_impl
|
|---|
| 48 | // histogram
|
|---|
| 49 | /**
|
|---|
| 50 | @brief Histogram
|
|---|
| 51 |
|
|---|
| 52 | Just a simple histogram with out averaging or anything else
|
|---|
| 53 |
|
|---|
| 54 | @param histogram_limit_low lower limit of the histogram
|
|---|
| 55 | @param histogram_limit_high high limit of the histogram
|
|---|
| 56 | @param histogram_num_bins Number of bins (two additional bins collect
|
|---|
| 57 | under- and overflow samples).
|
|---|
| 58 | */
|
|---|
| 59 | template <typename Sample>
|
|---|
| 60 | struct histogram_impl : accumulator_base
|
|---|
| 61 | {
|
|---|
| 62 | typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type
|
|---|
| 63 | float_type;
|
|---|
| 64 | typedef std::vector<std::pair<float_type, float_type>> histogram_type;
|
|---|
| 65 | typedef std::vector<float_type> array_type;
|
|---|
| 66 | // for boost::result_of
|
|---|
| 67 | typedef iterator_range<typename histogram_type::iterator> result_type;
|
|---|
| 68 |
|
|---|
| 69 | template <typename Args>
|
|---|
| 70 | histogram_impl(Args const &args)
|
|---|
| 71 | : num_bins(args[histogram_num_bins]),
|
|---|
| 72 | limit_low(args[histogram_limit_low]),
|
|---|
| 73 | limit_high(args[histogram_limit_high]),
|
|---|
| 74 | samples_in_bin(num_bins + 2, 0.), bin_positions(num_bins + 2),
|
|---|
| 75 | histogram(
|
|---|
| 76 | num_bins + 2,
|
|---|
| 77 | std::make_pair(
|
|---|
| 78 | numeric::fdiv(args[sample | Sample()], (std::size_t)1),
|
|---|
| 79 | numeric::fdiv(args[sample | Sample()], (std::size_t)1))),
|
|---|
| 80 | is_dirty(true)
|
|---|
| 81 | {
|
|---|
| 82 | float_type bin_size =
|
|---|
| 83 | numeric::fdiv(this->limit_high - this->limit_low, this->num_bins);
|
|---|
| 84 |
|
|---|
| 85 | // determine bin positions (their lower bounds)
|
|---|
| 86 | for (std::size_t i = 0; i < this->num_bins + 2; ++i)
|
|---|
| 87 | {
|
|---|
| 88 | this->bin_positions[i] = this->limit_low + (i - 1.) * bin_size;
|
|---|
| 89 | }
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | template <typename Args>
|
|---|
| 93 | void operator()(Args const &args)
|
|---|
| 94 | {
|
|---|
| 95 | this->is_dirty = true;
|
|---|
| 96 |
|
|---|
| 97 | // Add each subsequent sample to the correct bin
|
|---|
| 98 | if (args[sample] < this->bin_positions[1])
|
|---|
| 99 | {
|
|---|
| 100 | ++(this->samples_in_bin[0]);
|
|---|
| 101 | }
|
|---|
| 102 | else if (args[sample] >= this->bin_positions[this->num_bins + 1])
|
|---|
| 103 | {
|
|---|
| 104 | ++(this->samples_in_bin[this->num_bins + 1]);
|
|---|
| 105 | }
|
|---|
| 106 | else
|
|---|
| 107 | {
|
|---|
| 108 | typename array_type::iterator it =
|
|---|
| 109 | std::upper_bound(this->bin_positions.begin(),
|
|---|
| 110 | this->bin_positions.end(), args[sample]);
|
|---|
| 111 |
|
|---|
| 112 | std::size_t d = std::distance(this->bin_positions.begin(), it);
|
|---|
| 113 | ++(this->samples_in_bin[d - 1]);
|
|---|
| 114 | }
|
|---|
| 115 | }
|
|---|
| 116 |
|
|---|
| 117 | template <typename Args>
|
|---|
| 118 | result_type result(Args const &args) const
|
|---|
| 119 | {
|
|---|
| 120 | if (this->is_dirty)
|
|---|
| 121 | {
|
|---|
| 122 | this->is_dirty = false;
|
|---|
| 123 |
|
|---|
| 124 | // creates a vector of std::pair where each pair i holds
|
|---|
| 125 | // the values bin_positions[i] (x-axis of histogram) and
|
|---|
| 126 | // samples_in_bin[i] (y-axis of histogram).
|
|---|
| 127 |
|
|---|
| 128 | for (std::size_t i = 0; i < this->num_bins + 2; ++i)
|
|---|
| 129 | {
|
|---|
| 130 | this->histogram[i] = std::make_pair(this->bin_positions[i],
|
|---|
| 131 | this->samples_in_bin[i]);
|
|---|
| 132 | }
|
|---|
| 133 | }
|
|---|
| 134 | // returns a range of pairs
|
|---|
| 135 | return make_iterator_range(this->histogram);
|
|---|
| 136 | }
|
|---|
| 137 |
|
|---|
| 138 | private:
|
|---|
| 139 | std::size_t num_bins; // number of bins
|
|---|
| 140 | float_type limit_low; // the lower limit
|
|---|
| 141 | float_type limit_high; // the high limit
|
|---|
| 142 | array_type samples_in_bin; // number of samples in each bin
|
|---|
| 143 | array_type bin_positions; // lower bounds of bins
|
|---|
| 144 | mutable histogram_type histogram; // histogram
|
|---|
| 145 | mutable bool is_dirty;
|
|---|
| 146 | };
|
|---|
| 147 |
|
|---|
| 148 | } // namespace impl
|
|---|
| 149 |
|
|---|
| 150 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 151 | // tag::histogram
|
|---|
| 152 | //
|
|---|
| 153 | namespace tag
|
|---|
| 154 | {
|
|---|
| 155 | struct histogram : depends_on<>,
|
|---|
| 156 | histogram_limit_low,
|
|---|
| 157 | histogram_limit_high,
|
|---|
| 158 | histogram_num_bins
|
|---|
| 159 | {
|
|---|
| 160 | /// INTERNAL ONLY
|
|---|
| 161 | ///
|
|---|
| 162 | typedef accumulators::impl::histogram_impl<mpl::_1> impl;
|
|---|
| 163 |
|
|---|
| 164 | #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
|
|---|
| 165 | /// tag::histogram::limit_low named parameter
|
|---|
| 166 | /// tag::histogram::limit_high named parameter
|
|---|
| 167 | /// tag::histogram::num_bins named parameter
|
|---|
| 168 | static boost::parameter::keyword<histogram_limit_low> const limit_low;
|
|---|
| 169 | static boost::parameter::keyword<histogram_limit_high> const limit_high;
|
|---|
| 170 | static boost::parameter::keyword<histogram_num_bins> const num_bins;
|
|---|
| 171 | #endif
|
|---|
| 172 | };
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 176 | // extract::histogram
|
|---|
| 177 | //
|
|---|
| 178 | namespace extract
|
|---|
| 179 | {
|
|---|
| 180 | extractor<tag::histogram> const histogram = {};
|
|---|
| 181 |
|
|---|
| 182 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(histogram)
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | using extract::histogram;
|
|---|
| 186 | }
|
|---|
| 187 | } // namespace boost::accumulators
|
|---|
| 188 |
|
|---|
| 189 | #endif // BOOST_ACCUMULATORS_STATISTICS_HISTOGRAM
|
|---|