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
|
---|