1 ///////////////////////////////////////////////////////////////////////////////
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)
8 #ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006
9 #define BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006
17 #include <boost/throw_exception.hpp>
18 #include <boost/parameter/keyword.hpp>
19 #include <boost/mpl/placeholders.hpp>
20 #include <boost/type_traits/is_same.hpp>
21 #include <boost/accumulators/framework/accumulator_base.hpp>
22 #include <boost/accumulators/framework/extractor.hpp>
23 #include <boost/accumulators/numeric/functional.hpp>
24 #include <boost/accumulators/framework/parameters/sample.hpp>
25 #include <boost/accumulators/statistics_fwd.hpp>
26 #include <boost/accumulators/statistics/count.hpp>
27 #include <boost/accumulators/statistics/tail.hpp>
28 #include <boost/accumulators/statistics/tail_quantile.hpp>
29 #include <boost/accumulators/statistics/parameters/quantile_probability.hpp>
32 # pragma warning(push)
33 # pragma warning(disable: 4127) // conditional expression is constant
36 namespace boost
{ namespace accumulators
42 ///////////////////////////////////////////////////////////////////////////////
43 // coherent_tail_mean_impl
46 @brief Estimation of the coherent tail mean based on order statistics (for both left and right tails)
48 The coherent tail mean \f$\widehat{CTM}_{n,\alpha}(X)\f$ is equal to the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$
49 plus a correction term that ensures coherence in case of non-continuous distributions.
52 \widehat{CTM}_{n,\alpha}^{\mathrm{right}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) +
53 \frac{1}{\lceil n(1-\alpha)\rceil}\hat{q}_{n,\alpha}(X)\left(1 - \alpha - \frac{1}{n}\lceil n(1-\alpha)\rceil \right)
57 \widehat{CTM}_{n,\alpha}^{\mathrm{left}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) +
58 \frac{1}{\lceil n\alpha\rceil}\hat{q}_{n,\alpha}(X)\left(\alpha - \frac{1}{n}\lceil n\alpha\rceil \right)
61 template<typename Sample
, typename LeftRight
>
62 struct coherent_tail_mean_impl
65 typedef typename
numeric::functional::average
<Sample
, std::size_t>::result_type float_type
;
66 // for boost::result_of
67 typedef float_type result_type
;
69 coherent_tail_mean_impl(dont_care
) {}
71 template<typename Args
>
72 result_type
result(Args
const &args
) const
74 std::size_t cnt
= count(args
);
76 std::size_t n
= static_cast<std::size_t>(
78 cnt
* ( ( is_same
<LeftRight
, left
>::value
) ? args
[quantile_probability
] : 1. - args
[quantile_probability
] )
82 extractor
<tag::non_coherent_tail_mean
<LeftRight
> > const some_non_coherent_tail_mean
= {};
84 return some_non_coherent_tail_mean(args
)
85 + numeric::average(quantile(args
), n
)
87 ( is_same
<LeftRight
, left
>::value
) ? args
[quantile_probability
] : 1. - args
[quantile_probability
]
88 - numeric::average(n
, count(args
))
93 ///////////////////////////////////////////////////////////////////////////////
94 // non_coherent_tail_mean_impl
97 @brief Estimation of the (non-coherent) tail mean based on order statistics (for both left and right tails)
99 An estimation of the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ is given by the mean of the
100 \f$\lceil n\alpha\rceil\f$ smallest samples (left tail) or the mean of the \f$\lceil n(1-\alpha)\rceil\f$
101 largest samples (right tail), \f$n\f$ being the total number of samples and \f$\alpha\f$ the quantile level:
104 \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) = \frac{1}{\lceil n(1-\alpha)\rceil} \sum_{i=\lceil \alpha n \rceil}^n X_{i:n}
108 \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) = \frac{1}{\lceil n\alpha\rceil} \sum_{i=1}^{\lceil \alpha n \rceil} X_{i:n}
111 It thus requires the caching of at least the \f$\lceil n\alpha\rceil\f$ smallest or the \f$\lceil n(1-\alpha)\rceil\f$
114 @param quantile_probability
116 template<typename Sample
, typename LeftRight
>
117 struct non_coherent_tail_mean_impl
120 typedef typename
numeric::functional::average
<Sample
, std::size_t>::result_type float_type
;
121 // for boost::result_of
122 typedef float_type result_type
;
124 non_coherent_tail_mean_impl(dont_care
) {}
126 template<typename Args
>
127 result_type
result(Args
const &args
) const
129 std::size_t cnt
= count(args
);
131 std::size_t n
= static_cast<std::size_t>(
133 cnt
* ( ( is_same
<LeftRight
, left
>::value
) ? args
[quantile_probability
] : 1. - args
[quantile_probability
] )
137 // If n is in a valid range, return result, otherwise return NaN or throw exception
138 if (n
<= static_cast<std::size_t>(tail(args
).size()))
139 return numeric::average(
142 , tail(args
).begin() + n
149 if (std::numeric_limits
<result_type
>::has_quiet_NaN
)
151 return std::numeric_limits
<result_type
>::quiet_NaN();
155 std::ostringstream msg
;
156 msg
<< "index n = " << n
<< " is not in valid range [0, " << tail(args
).size() << ")";
157 boost::throw_exception(std::runtime_error(msg
.str()));
167 ///////////////////////////////////////////////////////////////////////////////
168 // tag::coherent_tail_mean<>
169 // tag::non_coherent_tail_mean<>
173 template<typename LeftRight
>
174 struct coherent_tail_mean
175 : depends_on
<count
, quantile
, non_coherent_tail_mean
<LeftRight
> >
177 typedef accumulators::impl::coherent_tail_mean_impl
<mpl::_1
, LeftRight
> impl
;
180 template<typename LeftRight
>
181 struct non_coherent_tail_mean
182 : depends_on
<count
, tail
<LeftRight
> >
184 typedef accumulators::impl::non_coherent_tail_mean_impl
<mpl::_1
, LeftRight
> impl
;
187 struct abstract_non_coherent_tail_mean
193 ///////////////////////////////////////////////////////////////////////////////
194 // extract::non_coherent_tail_mean;
195 // extract::coherent_tail_mean;
199 extractor
<tag::abstract_non_coherent_tail_mean
> const non_coherent_tail_mean
= {};
200 extractor
<tag::tail_mean
> const coherent_tail_mean
= {};
203 using extract::non_coherent_tail_mean
;
204 using extract::coherent_tail_mean
;
206 // for the purposes of feature-based dependency resolution,
207 // coherent_tail_mean<LeftRight> provides the same feature as tail_mean
208 template<typename LeftRight
>
209 struct feature_of
<tag::coherent_tail_mean
<LeftRight
> >
210 : feature_of
<tag::tail_mean
>
214 template<typename LeftRight
>
215 struct feature_of
<tag::non_coherent_tail_mean
<LeftRight
> >
216 : feature_of
<tag::abstract_non_coherent_tail_mean
>
220 // So that non_coherent_tail_mean can be automatically substituted
221 // with weighted_non_coherent_tail_mean when the weight parameter is non-void.
222 template<typename LeftRight
>
223 struct as_weighted_feature
<tag::non_coherent_tail_mean
<LeftRight
> >
225 typedef tag::non_coherent_weighted_tail_mean
<LeftRight
> type
;
228 template<typename LeftRight
>
229 struct feature_of
<tag::non_coherent_weighted_tail_mean
<LeftRight
> >
230 : feature_of
<tag::non_coherent_tail_mean
<LeftRight
> >
233 // NOTE that non_coherent_tail_mean cannot be feature-grouped with tail_mean,
234 // which is the base feature for coherent tail means, since (at least for
235 // non-continuous distributions) non_coherent_tail_mean is a different measure!
237 }} // namespace boost::accumulators
240 # pragma warning(pop)