Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
@@ -0,0 +1,132 @@
// Copyright 2022 Jay Gohil, Hans Dembinski
//
// Distributed under the Boost Software License, version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HISTOGRAM_UTILITY_BINOMIAL_PROPORTION_INTERVAL_HPP
#define BOOST_HISTOGRAM_UTILITY_BINOMIAL_PROPORTION_INTERVAL_HPP
#include <boost/histogram/detail/normal.hpp>
#include <boost/histogram/fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cmath>
#include <stdexcept>
#include <type_traits>
namespace boost {
namespace histogram {
namespace utility {
/**
Common base class for interval calculators.
*/
template <class ValueType>
class binomial_proportion_interval {
static_assert(std::is_floating_point<ValueType>::value,
"Value must be a floating point!");
public:
using value_type = ValueType;
using interval_type = std::pair<value_type, value_type>;
/** Compute interval for given number of successes and failures.
@param successes Number of successful trials.
@param failures Number of failed trials.
*/
virtual interval_type operator()(value_type successes,
value_type failures) const noexcept = 0;
/** Compute interval for a fraction accumulator.
@param fraction Fraction accumulator.
*/
template <class T>
interval_type operator()(const accumulators::fraction<T>& fraction) const noexcept {
return operator()(fraction.successes(), fraction.failures());
}
};
class deviation;
class confidence_level;
/** Confidence level in units of deviations for intervals.
Intervals become wider as the deviation value increases. The standard deviation
corresponds to a value of 1 and corresponds to 68.3 % confidence level. The conversion
between confidence level and deviations is based on a two-sided interval on the normal
distribution.
*/
class deviation {
public:
/// constructor from units of standard deviations
explicit deviation(double d) : d_{d} {
if (d <= 0)
BOOST_THROW_EXCEPTION(std::invalid_argument("scaling factor must be positive"));
}
/// explicit conversion to units of standard deviations
template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
explicit operator T() const noexcept {
return static_cast<T>(d_);
}
/// implicit conversion to confidence level
operator confidence_level() const noexcept; // need to implement confidence_level first
friend deviation operator*(deviation d, double z) noexcept {
return deviation(d.d_ * z);
}
friend deviation operator*(double z, deviation d) noexcept { return d * z; }
friend bool operator==(deviation a, deviation b) noexcept { return a.d_ == b.d_; }
friend bool operator!=(deviation a, deviation b) noexcept { return !(a == b); }
private:
double d_;
};
/** Confidence level for intervals.
Intervals become wider as the deviation value increases.
*/
class confidence_level {
public:
/// constructor from confidence level (a probability)
explicit confidence_level(double cl) : cl_{cl} {
if (cl <= 0 || cl >= 1)
BOOST_THROW_EXCEPTION(std::invalid_argument("0 < cl < 1 is required"));
}
/// explicit conversion to numerical confidence level
template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
explicit operator T() const noexcept {
return static_cast<T>(cl_);
}
/// implicit conversion to units of standard deviation
operator deviation() const noexcept {
return deviation{detail::normal_ppf(std::fma(0.5, cl_, 0.5))};
}
friend bool operator==(confidence_level a, confidence_level b) noexcept {
return a.cl_ == b.cl_;
}
friend bool operator!=(confidence_level a, confidence_level b) noexcept {
return !(a == b);
}
private:
double cl_;
};
inline deviation::operator confidence_level() const noexcept {
// solve normal cdf(z) - cdf(-z) = 2 (cdf(z) - 0.5)
return confidence_level{std::fma(2.0, detail::normal_cdf(d_), -1.0)};
}
} // namespace utility
} // namespace histogram
} // namespace boost
#endif
+83
View File
@@ -0,0 +1,83 @@
// Copyright 2022 Jay Gohil, Hans Dembinski
//
// Distributed under the Boost Software License, version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HISTOGRAM_UTILITY_CLOPPER_PEARSON_INTERVAL_HPP
#define BOOST_HISTOGRAM_UTILITY_CLOPPER_PEARSON_INTERVAL_HPP
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/utility/binomial_proportion_interval.hpp>
#include <boost/math/distributions/beta.hpp>
#include <cmath>
namespace boost {
namespace histogram {
namespace utility {
/**
Clopper-Pearson interval.
This is the classic frequentist interval obtained with the Neyman construction.
It is therefore often called the 'exact' interval. It is guaranteed to have at least the
requested confidence level for all values of the fraction.
The interval is wider than others that produce coverage closer to the expected
confidence level over a random ensemble of factions. The Clopper-Pearson interval
essentially always overcovers for such a random ensemble, which is undesirable in
practice. The Clopper-Pearson interval is recommended when it is important to be
conservative, but the Wilson interval should be preferred in most applications.
C. Clopper, E.S. Pearson (1934), Biometrika 26 (4): 404-413.
doi:10.1093/biomet/26.4.404.
*/
template <class ValueType>
class clopper_pearson_interval : public binomial_proportion_interval<ValueType> {
public:
using value_type = typename clopper_pearson_interval::value_type;
using interval_type = typename clopper_pearson_interval::interval_type;
/** Construct Clopper-Pearson interval computer.
@param cl Confidence level for the interval. The default value produces a
confidence level of 68 % equivalent to one standard deviation. Both `deviation` and
`confidence_level` objects can be used to initialize the interval.
*/
explicit clopper_pearson_interval(confidence_level cl = deviation{1}) noexcept
: alpha_half_{static_cast<value_type>(0.5 - 0.5 * static_cast<double>(cl))} {}
using binomial_proportion_interval<ValueType>::operator();
/** Compute interval for given number of successes and failures.
@param successes Number of successful trials.
@param failures Number of failed trials.
*/
interval_type operator()(value_type successes, value_type failures) const noexcept {
// analytical solution when successes or failures are zero
// T. Mans (2014), Electronic Journal of Statistics. 8 (1): 817-840.
// arXiv:1303.1288. doi:10.1214/14-EJS909.
const value_type total = successes + failures;
if (successes == 0) return {0, 1 - std::pow(alpha_half_, 1 / total)};
if (failures == 0) return {std::pow(alpha_half_, 1 / total), 1};
// Source:
// https://en.wikipedia.org/wiki/
// Binomial_proportion_confidence_interval#Clopper%E2%80%93Pearson_interval
math::beta_distribution<value_type> beta_a(successes, failures + 1);
const value_type a = math::quantile(beta_a, alpha_half_);
math::beta_distribution<value_type> beta_b(successes + 1, failures);
const value_type b = math::quantile(beta_b, 1 - alpha_half_);
return {a, b};
}
private:
value_type alpha_half_;
};
} // namespace utility
} // namespace histogram
} // namespace boost
#endif
+78
View File
@@ -0,0 +1,78 @@
// Copyright 2022 Jay Gohil, Hans Dembinski
//
// Distributed under the Boost Software License, version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HISTOGRAM_UTILITY_JEFFREYS_INTERVAL_HPP
#define BOOST_HISTOGRAM_UTILITY_JEFFREYS_INTERVAL_HPP
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/utility/binomial_proportion_interval.hpp>
#include <boost/math/distributions/beta.hpp>
#include <cmath>
namespace boost {
namespace histogram {
namespace utility {
/**
Jeffreys interval.
This is the Bayesian credible interval with a Jeffreys prior. Although it has a
Bayesian derivation, it has good coverage. The interval boundaries are close to the
Wilson interval. A special property of this interval is that it is equal-tailed; the
probability of the true value to be above or below the interval is approximately equal.
To avoid coverage probability tending to zero when the fraction approaches 0 or 1,
this implementation uses a modification described in section 4.1.2 of the
paper by L.D. Brown, T.T. Cai, A. DasGupta, Statistical Science 16 (2001) 101-133,
doi:10.1214/ss/1009213286.
*/
template <class ValueType>
class jeffreys_interval : public binomial_proportion_interval<ValueType> {
public:
using value_type = typename jeffreys_interval::value_type;
using interval_type = typename jeffreys_interval::interval_type;
/** Construct Jeffreys interval computer.
@param cl Confidence level for the interval. The default value produces a
confidence level of 68 % equivalent to one standard deviation. Both `deviation` and
`confidence_level` objects can be used to initialize the interval.
*/
explicit jeffreys_interval(confidence_level cl = deviation{1}) noexcept
: alpha_half_{static_cast<value_type>(0.5 - 0.5 * static_cast<double>(cl))} {}
using binomial_proportion_interval<ValueType>::operator();
/** Compute interval for given number of successes and failures.
@param successes Number of successful trials.
@param failures Number of failed trials.
*/
interval_type operator()(value_type successes, value_type failures) const noexcept {
// See L.D. Brown, T.T. Cai, A. DasGupta, Statistical Science 16 (2001) 101-133,
// doi:10.1214/ss/1009213286, section 4.1.2.
const value_type half{0.5};
const value_type total = successes + failures;
// if successes or failures are 0, modified interval is equal to Clopper-Pearson
if (successes == 0) return {0, 1 - std::pow(alpha_half_, 1 / total)};
if (failures == 0) return {std::pow(alpha_half_, 1 / total), 1};
math::beta_distribution<value_type> beta(successes + half, failures + half);
const value_type a = successes == 1 ? 0 : math::quantile(beta, alpha_half_);
const value_type b = failures == 1 ? 1 : math::quantile(beta, 1 - alpha_half_);
return {a, b};
}
private:
value_type alpha_half_;
};
} // namespace utility
} // namespace histogram
} // namespace boost
#endif
+80
View File
@@ -0,0 +1,80 @@
// Copyright 2022 Jay Gohil, Hans Dembinski
//
// Distributed under the Boost Software License, version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HISTOGRAM_UTILITY_WALD_INTERVAL_HPP
#define BOOST_HISTOGRAM_UTILITY_WALD_INTERVAL_HPP
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/utility/binomial_proportion_interval.hpp>
#include <cmath>
#include <utility>
namespace boost {
namespace histogram {
namespace utility {
/**
Wald interval or normal approximation interval.
The Wald interval is a symmetric interval. It is simple to compute, but has poor
statistical properties and is universally rejected by statisticians. It should always be
replaced by another iternal, for example, the Wilson interval.
The Wald interval can be derived easily using the plug-in estimate of the variance for
the binomial distribution, which is likely a reason for its omnipresence. Without
further insight into statistical theory, it is not obvious that this derivation is
flawed and that better alternatives exist.
The Wald interval undercovers on average. It is unsuitable when the sample size is small
or when the fraction is close to 0 or 1. e. Its limits are not naturally bounded by 0
or 1. It produces empty intervals if the number of successes or failures is zero.
For a critique of the Wald interval, see (a selection):
L.D. Brown, T.T. Cai, A. DasGupta, Statistical Science 16 (2001) 101-133.
R. D. Cousins, K. E. Hymes, J. Tucker, Nucl. Instrum. Meth. A 612 (2010) 388-398.
*/
template <class ValueType>
class wald_interval : public binomial_proportion_interval<ValueType> {
public:
using value_type = typename wald_interval::value_type;
using interval_type = typename wald_interval::interval_type;
/** Construct Wald interval computer.
@param d Number of standard deviations for the interval. The default value 1
corresponds to a confidence level of 68 %. Both `deviation` and `confidence_level`
objects can be used to initialize the interval.
*/
explicit wald_interval(deviation d = deviation{1.0}) noexcept
: z_{static_cast<value_type>(d)} {}
using binomial_proportion_interval<ValueType>::operator();
/** Compute interval for given number of successes and failures.
@param successes Number of successful trials.
@param failures Number of failed trials.
*/
interval_type operator()(value_type successes, value_type failures) const noexcept {
// See https://en.wikipedia.org/wiki/
// Binomial_proportion_confidence_interval
// #Normal_approximation_interval_or_Wald_interval
const value_type total_inv = 1 / (successes + failures);
const value_type a = successes * total_inv;
const value_type b = (z_ * total_inv) * std::sqrt(successes * failures * total_inv);
return {a - b, a + b};
}
private:
value_type z_;
};
} // namespace utility
} // namespace histogram
} // namespace boost
#endif
+86
View File
@@ -0,0 +1,86 @@
// Copyright 2022 Jay Gohil, Hans Dembinski
//
// Distributed under the Boost Software License, version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HISTOGRAM_UTILITY_WILSON_INTERVAL_HPP
#define BOOST_HISTOGRAM_UTILITY_WILSON_INTERVAL_HPP
#include <boost/histogram/fwd.hpp>
#include <boost/histogram/utility/binomial_proportion_interval.hpp>
#include <cmath>
#include <utility>
namespace boost {
namespace histogram {
namespace utility {
/**
Wilson interval.
The Wilson score interval is simple to compute, has good coverage. Intervals are
automatically bounded between 0 and 1 and never empty. The interval is asymmetric.
Wilson, E. B. (1927). "Probable inference, the law of succession, and statistical
inference". Journal of the American Statistical Association. 22 (158): 209-212.
doi:10.1080/01621459.1927.10502953. JSTOR 2276774.
The coverage probability for a random ensemble of fractions is close to the nominal
value. Unlike the Clopper-Pearson interval, the Wilson score interval is not
conservative. For some values of the fractions, the interval undercovers and overcovers
for neighboring values. This is a shared property of all alternatives to the
Clopper-Pearson interval.
The Wilson score intervals is widely recommended for general use in the literature. For
a review of the literature, see R. D. Cousins, K. E. Hymes, J. Tucker, Nucl. Instrum.
Meth. A 612 (2010) 388-398.
*/
template <class ValueType>
class wilson_interval : public binomial_proportion_interval<ValueType> {
public:
using value_type = typename wilson_interval::value_type;
using interval_type = typename wilson_interval::interval_type;
/** Construct Wilson interval computer.
@param d Number of standard deviations for the interval. The default value 1
corresponds to a confidence level of 68 %. Both `deviation` and `confidence_level`
objects can be used to initialize the interval.
*/
explicit wilson_interval(deviation d = deviation{1.0}) noexcept
: z_{static_cast<value_type>(d)} {}
using binomial_proportion_interval<ValueType>::operator();
/** Compute interval for given number of successes and failures.
@param successes Number of successful trials.
@param failures Number of failed trials.
*/
interval_type operator()(value_type successes, value_type failures) const noexcept {
// See https://en.wikipedia.org/wiki/
// Binomial_proportion_confidence_interval
// #Wilson_score_interval
// We make sure calculation is done in single precision if value_type is float
// by converting all literals to value_type. Double literals in the equation
// would turn intermediate values to double.
const value_type half{0.5}, quarter{0.25}, zsq{z_ * z_};
const value_type total = successes + failures;
const value_type minv = 1 / (total + zsq);
const value_type t1 = (successes + half * zsq) * minv;
const value_type t2 =
z_ * minv * std::sqrt(successes * failures / total + quarter * zsq);
return {t1 - t2, t1 + t2};
}
private:
value_type z_;
};
} // namespace utility
} // namespace histogram
} // namespace boost
#endif