123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- #ifndef BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP
- #define BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP
- #include <cmath>
- #include <algorithm>
- #include <boost/math/statistics/univariate_statistics.hpp>
- #include <boost/math/special_functions/erf.hpp>
- namespace boost { namespace math { namespace statistics {
- template<class RandomAccessContainer>
- auto anderson_darling_normality_statistic(RandomAccessContainer const & v,
- typename RandomAccessContainer::value_type mu = std::numeric_limits<typename RandomAccessContainer::value_type>::quiet_NaN(),
- typename RandomAccessContainer::value_type sd = std::numeric_limits<typename RandomAccessContainer::value_type>::quiet_NaN())
- {
- using Real = typename RandomAccessContainer::value_type;
- using std::log;
- using std::sqrt;
- using boost::math::erfc;
- if (std::isnan(mu)) {
- mu = boost::math::statistics::mean(v);
- }
- if (std::isnan(sd)) {
- sd = sqrt(boost::math::statistics::sample_variance(v));
- }
- typedef boost::math::policies::policy<
- boost::math::policies::promote_float<false>,
- boost::math::policies::promote_double<false> >
- no_promote_policy;
-
-
-
-
-
-
-
-
-
- Real inv_var_scale = 1/(sd*sqrt(Real(2)));
- Real s0 = (v[0] - mu)*inv_var_scale;
- Real erfcs0 = erfc(s0, no_promote_policy());
-
- if (erfcs0 <= 0) {
- return std::numeric_limits<Real>::infinity();
- }
-
- Real left_tail = -1 + log(Real(2));
-
-
-
-
-
-
-
-
- Real sf = (v[v.size()-1] - mu)*inv_var_scale;
-
-
-
-
- Real erfcmsf = erfc<Real>(-sf, no_promote_policy());
-
- if (erfcmsf == 0) {
- return std::numeric_limits<Real>::infinity();
- }
- Real right_tail = log(2/erfcmsf);
-
-
-
-
-
- Real integrals = 0;
- int64_t N = v.size();
- for (int64_t i = 0; i < N - 1; ++i) {
- if (v[i] > v[i+1]) {
- throw std::domain_error("Input data must be sorted in increasing order v[0] <= v[1] <= . . . <= v[n-1]");
- }
- Real k = (i+1)/Real(N);
- Real s1 = (v[i+1]-mu)*inv_var_scale;
- Real erfcs1 = erfc<Real>(s1, no_promote_policy());
- Real term = k*(k*log(erfcs0*(-2 + erfcs1)/(erfcs1*(-2 + erfcs0))) + 2*log(erfcs1/erfcs0));
- integrals += term;
- s0 = s1;
- erfcs0 = erfcs1;
- }
- integrals -= log(erfcs0);
- return v.size()*(left_tail + right_tail + integrals);
- }
- }}}
- #endif
|