File indexing completed on 2025-12-16 09:55:37
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP
0009 #define BOOST_MATH_STATISTICS_ANDERSON_DARLING_HPP
0010
0011 #include <cmath>
0012 #include <algorithm>
0013 #include <boost/math/statistics/univariate_statistics.hpp>
0014 #include <boost/math/special_functions/erf.hpp>
0015
0016 namespace boost { namespace math { namespace statistics {
0017
0018 template<class RandomAccessContainer>
0019 auto anderson_darling_normality_statistic(RandomAccessContainer const & v,
0020 typename RandomAccessContainer::value_type mu = std::numeric_limits<typename RandomAccessContainer::value_type>::quiet_NaN(),
0021 typename RandomAccessContainer::value_type sd = std::numeric_limits<typename RandomAccessContainer::value_type>::quiet_NaN())
0022 {
0023 using Real = typename RandomAccessContainer::value_type;
0024 using std::log;
0025 using std::sqrt;
0026 using boost::math::erfc;
0027
0028 if (std::isnan(mu)) {
0029 mu = boost::math::statistics::mean(v);
0030 }
0031 if (std::isnan(sd)) {
0032 sd = sqrt(boost::math::statistics::sample_variance(v));
0033 }
0034
0035 typedef boost::math::policies::policy<
0036 boost::math::policies::promote_float<false>,
0037 boost::math::policies::promote_double<false> >
0038 no_promote_policy;
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 Real inv_var_scale = 1/(sd*sqrt(Real(2)));
0052 Real s0 = (v[0] - mu)*inv_var_scale;
0053 Real erfcs0 = erfc(s0, no_promote_policy());
0054
0055 if (erfcs0 <= 0) {
0056 return std::numeric_limits<Real>::infinity();
0057 }
0058
0059
0060 Real left_tail = -1 + log(Real(2));
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 Real sf = (v[v.size()-1] - mu)*inv_var_scale;
0073
0074
0075
0076
0077
0078 Real erfcmsf = erfc<Real>(-sf, no_promote_policy());
0079
0080 if (erfcmsf == 0) {
0081 return std::numeric_limits<Real>::infinity();
0082 }
0083 Real right_tail = log(2/erfcmsf);
0084
0085
0086
0087
0088
0089
0090
0091 Real integrals = 0;
0092 int64_t N = v.size();
0093 for (int64_t i = 0; i < N - 1; ++i) {
0094 if (v[i] > v[i+1]) {
0095 throw std::domain_error("Input data must be sorted in increasing order v[0] <= v[1] <= . . . <= v[n-1]");
0096 }
0097
0098 Real k = (i+1)/Real(N);
0099 Real s1 = (v[i+1]-mu)*inv_var_scale;
0100 Real erfcs1 = erfc<Real>(s1, no_promote_policy());
0101 Real term = k*(k*log(erfcs0*(-2 + erfcs1)/(erfcs1*(-2 + erfcs0))) + 2*log(erfcs1/erfcs0));
0102
0103 integrals += term;
0104 s0 = s1;
0105 erfcs0 = erfcs1;
0106 }
0107 integrals -= log(erfcs0);
0108 return v.size()*(left_tail + right_tail + integrals);
0109 }
0110
0111 }}}
0112 #endif