1 ///////////////////////////////////////////////////////////////////////////////
2 // mean.hpp
3 //
4 //  Copyright 2005 Eric Niebler. 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_MEAN_HPP_EAN_28_10_2005
9 #define BOOST_ACCUMULATORS_STATISTICS_MEAN_HPP_EAN_28_10_2005
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/depends_on.hpp>
17 #include <boost/accumulators/statistics_fwd.hpp>
18 #include <boost/accumulators/statistics/count.hpp>
19 #include <boost/accumulators/statistics/sum.hpp>
20 
21 namespace boost { namespace accumulators
22 {
23 
24 namespace impl
25 {
26     ///////////////////////////////////////////////////////////////////////////////
27     // mean_impl
28     //      lazy, by default
29     template<typename Sample, typename SumFeature>
30     struct mean_impl
31       : accumulator_base
32     {
33         // for boost::result_of
34         typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type;
35 
mean_implboost::accumulators::impl::mean_impl36         mean_impl(dont_care) {}
37 
38         template<typename Args>
resultboost::accumulators::impl::mean_impl39         result_type result(Args const &args) const
40         {
41             extractor<SumFeature> sum;
42             return numeric::fdiv(sum(args), count(args));
43         }
44 
45         // serialization is done by accumulators it depends on
46         template<class Archive>
serializeboost::accumulators::impl::mean_impl47         void serialize(Archive & ar, const unsigned int file_version) {}
48     };
49 
50     template<typename Sample, typename Tag>
51     struct immediate_mean_impl
52       : accumulator_base
53     {
54         // for boost::result_of
55         typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type;
56 
57         template<typename Args>
immediate_mean_implboost::accumulators::impl::immediate_mean_impl58         immediate_mean_impl(Args const &args)
59           : mean(numeric::fdiv(args[sample | Sample()], numeric::one<std::size_t>::value))
60         {
61         }
62 
63         template<typename Args>
operator ()boost::accumulators::impl::immediate_mean_impl64         void operator ()(Args const &args)
65         {
66             std::size_t cnt = count(args);
67             this->mean = numeric::fdiv(
68                 (this->mean * (cnt - 1)) + args[parameter::keyword<Tag>::get()]
69               , cnt
70             );
71         }
72 
resultboost::accumulators::impl::immediate_mean_impl73         result_type result(dont_care) const
74         {
75             return this->mean;
76         }
77 
78         template<class Archive>
serializeboost::accumulators::impl::immediate_mean_impl79         void serialize(Archive & ar, const unsigned int file_version)
80         {
81             ar & mean;
82         }
83 
84     private:
85         result_type mean;
86     };
87 
88 } // namespace impl
89 
90 ///////////////////////////////////////////////////////////////////////////////
91 // tag::mean
92 // tag::immediate_mean
93 // tag::mean_of_weights
94 // tag::immediate_mean_of_weights
95 // tag::mean_of_variates
96 // tag::immediate_mean_of_variates
97 //
98 namespace tag
99 {
100     struct mean
101       : depends_on<count, sum>
102     {
103         /// INTERNAL ONLY
104         ///
105         typedef accumulators::impl::mean_impl<mpl::_1, sum> impl;
106     };
107     struct immediate_mean
108       : depends_on<count>
109     {
110         /// INTERNAL ONLY
111         ///
112         typedef accumulators::impl::immediate_mean_impl<mpl::_1, tag::sample> impl;
113     };
114     struct mean_of_weights
115       : depends_on<count, sum_of_weights>
116     {
117         typedef mpl::true_ is_weight_accumulator;
118         /// INTERNAL ONLY
119         ///
120         typedef accumulators::impl::mean_impl<mpl::_2, sum_of_weights> impl;
121     };
122     struct immediate_mean_of_weights
123       : depends_on<count>
124     {
125         typedef mpl::true_ is_weight_accumulator;
126         /// INTERNAL ONLY
127         ///
128         typedef accumulators::impl::immediate_mean_impl<mpl::_2, tag::weight> impl;
129     };
130     template<typename VariateType, typename VariateTag>
131     struct mean_of_variates
132       : depends_on<count, sum_of_variates<VariateType, VariateTag> >
133     {
134         /// INTERNAL ONLY
135         ///
136         typedef mpl::always<accumulators::impl::mean_impl<VariateType, sum_of_variates<VariateType, VariateTag> > > impl;
137     };
138     template<typename VariateType, typename VariateTag>
139     struct immediate_mean_of_variates
140       : depends_on<count>
141     {
142         /// INTERNAL ONLY
143         ///
144         typedef mpl::always<accumulators::impl::immediate_mean_impl<VariateType, VariateTag> > impl;
145     };
146 }
147 
148 ///////////////////////////////////////////////////////////////////////////////
149 // extract::mean
150 // extract::mean_of_weights
151 // extract::mean_of_variates
152 //
153 namespace extract
154 {
155     extractor<tag::mean> const mean = {};
156     extractor<tag::mean_of_weights> const mean_of_weights = {};
157     BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, mean_of_variates, (typename)(typename))
158 
159     BOOST_ACCUMULATORS_IGNORE_GLOBAL(mean)
160     BOOST_ACCUMULATORS_IGNORE_GLOBAL(mean_of_weights)
161 }
162 
163 using extract::mean;
164 using extract::mean_of_weights;
165 using extract::mean_of_variates;
166 
167 // mean(lazy) -> mean
168 template<>
169 struct as_feature<tag::mean(lazy)>
170 {
171     typedef tag::mean type;
172 };
173 
174 // mean(immediate) -> immediate_mean
175 template<>
176 struct as_feature<tag::mean(immediate)>
177 {
178     typedef tag::immediate_mean type;
179 };
180 
181 // mean_of_weights(lazy) -> mean_of_weights
182 template<>
183 struct as_feature<tag::mean_of_weights(lazy)>
184 {
185     typedef tag::mean_of_weights type;
186 };
187 
188 // mean_of_weights(immediate) -> immediate_mean_of_weights
189 template<>
190 struct as_feature<tag::mean_of_weights(immediate)>
191 {
192     typedef tag::immediate_mean_of_weights type;
193 };
194 
195 // mean_of_variates<VariateType, VariateTag>(lazy) -> mean_of_variates<VariateType, VariateTag>
196 template<typename VariateType, typename VariateTag>
197 struct as_feature<tag::mean_of_variates<VariateType, VariateTag>(lazy)>
198 {
199     typedef tag::mean_of_variates<VariateType, VariateTag> type;
200 };
201 
202 // mean_of_variates<VariateType, VariateTag>(immediate) -> immediate_mean_of_variates<VariateType, VariateTag>
203 template<typename VariateType, typename VariateTag>
204 struct as_feature<tag::mean_of_variates<VariateType, VariateTag>(immediate)>
205 {
206     typedef tag::immediate_mean_of_variates<VariateType, VariateTag> type;
207 };
208 
209 // for the purposes of feature-based dependency resolution,
210 // immediate_mean provides the same feature as mean
211 template<>
212 struct feature_of<tag::immediate_mean>
213   : feature_of<tag::mean>
214 {
215 };
216 
217 // for the purposes of feature-based dependency resolution,
218 // immediate_mean provides the same feature as mean
219 template<>
220 struct feature_of<tag::immediate_mean_of_weights>
221   : feature_of<tag::mean_of_weights>
222 {
223 };
224 
225 // for the purposes of feature-based dependency resolution,
226 // immediate_mean provides the same feature as mean
227 template<typename VariateType, typename VariateTag>
228 struct feature_of<tag::immediate_mean_of_variates<VariateType, VariateTag> >
229   : feature_of<tag::mean_of_variates<VariateType, VariateTag> >
230 {
231 };
232 
233 // So that mean can be automatically substituted with
234 // weighted_mean when the weight parameter is non-void.
235 template<>
236 struct as_weighted_feature<tag::mean>
237 {
238     typedef tag::weighted_mean type;
239 };
240 
241 template<>
242 struct feature_of<tag::weighted_mean>
243   : feature_of<tag::mean>
244 {};
245 
246 // So that immediate_mean can be automatically substituted with
247 // immediate_weighted_mean when the weight parameter is non-void.
248 template<>
249 struct as_weighted_feature<tag::immediate_mean>
250 {
251     typedef tag::immediate_weighted_mean type;
252 };
253 
254 template<>
255 struct feature_of<tag::immediate_weighted_mean>
256   : feature_of<tag::immediate_mean>
257 {};
258 
259 // So that mean_of_weights<> can be automatically substituted with
260 // weighted_mean_of_variates<> when the weight parameter is non-void.
261 template<typename VariateType, typename VariateTag>
262 struct as_weighted_feature<tag::mean_of_variates<VariateType, VariateTag> >
263 {
264     typedef tag::weighted_mean_of_variates<VariateType, VariateTag> type;
265 };
266 
267 template<typename VariateType, typename VariateTag>
268 struct feature_of<tag::weighted_mean_of_variates<VariateType, VariateTag> >
269   : feature_of<tag::mean_of_variates<VariateType, VariateTag> >
270 {
271 };
272 
273 // So that immediate_mean_of_weights<> can be automatically substituted with
274 // immediate_weighted_mean_of_variates<> when the weight parameter is non-void.
275 template<typename VariateType, typename VariateTag>
276 struct as_weighted_feature<tag::immediate_mean_of_variates<VariateType, VariateTag> >
277 {
278     typedef tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> type;
279 };
280 
281 template<typename VariateType, typename VariateTag>
282 struct feature_of<tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> >
283   : feature_of<tag::immediate_mean_of_variates<VariateType, VariateTag> >
284 {
285 };
286 
287 ////////////////////////////////////////////////////////////////////////////
288 //// droppable_accumulator<mean_impl>
289 ////  need to specialize droppable lazy mean to cache the result at the
290 ////  point the accumulator is dropped.
291 ///// INTERNAL ONLY
292 /////
293 //template<typename Sample, typename SumFeature>
294 //struct droppable_accumulator<impl::mean_impl<Sample, SumFeature> >
295 //  : droppable_accumulator_base<
296 //        with_cached_result<impl::mean_impl<Sample, SumFeature> >
297 //    >
298 //{
299 //    template<typename Args>
300 //    droppable_accumulator(Args const &args)
301 //      : droppable_accumulator::base(args)
302 //    {
303 //    }
304 //};
305 
306 }} // namespace boost::accumulators
307 
308 #endif
309