File indexing completed on 2025-01-18 09:38:12
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_HISTOGRAM_UTILITY_BINOMIAL_PROPORTION_INTERVAL_HPP
0008 #define BOOST_HISTOGRAM_UTILITY_BINOMIAL_PROPORTION_INTERVAL_HPP
0009
0010 #include <boost/histogram/detail/normal.hpp>
0011 #include <boost/histogram/fwd.hpp>
0012 #include <boost/throw_exception.hpp>
0013 #include <cmath>
0014 #include <stdexcept>
0015 #include <type_traits>
0016
0017 namespace boost {
0018 namespace histogram {
0019 namespace utility {
0020
0021
0022
0023
0024 template <class ValueType>
0025 class binomial_proportion_interval {
0026 static_assert(std::is_floating_point<ValueType>::value,
0027 "Value must be a floating point!");
0028
0029 public:
0030 using value_type = ValueType;
0031 using interval_type = std::pair<value_type, value_type>;
0032
0033
0034
0035
0036
0037
0038 virtual interval_type operator()(value_type successes,
0039 value_type failures) const noexcept = 0;
0040
0041
0042
0043
0044
0045 template <class T>
0046 interval_type operator()(const accumulators::fraction<T>& fraction) const noexcept {
0047 return operator()(fraction.successes(), fraction.failures());
0048 }
0049 };
0050
0051 class deviation;
0052 class confidence_level;
0053
0054
0055
0056
0057
0058
0059
0060
0061 class deviation {
0062 public:
0063
0064 explicit deviation(double d) : d_{d} {
0065 if (d <= 0)
0066 BOOST_THROW_EXCEPTION(std::invalid_argument("scaling factor must be positive"));
0067 }
0068
0069
0070 template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
0071 explicit operator T() const noexcept {
0072 return static_cast<T>(d_);
0073 }
0074
0075
0076 operator confidence_level() const noexcept;
0077
0078 friend deviation operator*(deviation d, double z) noexcept {
0079 return deviation(d.d_ * z);
0080 }
0081 friend deviation operator*(double z, deviation d) noexcept { return d * z; }
0082 friend bool operator==(deviation a, deviation b) noexcept { return a.d_ == b.d_; }
0083 friend bool operator!=(deviation a, deviation b) noexcept { return !(a == b); }
0084
0085 private:
0086 double d_;
0087 };
0088
0089
0090
0091
0092
0093 class confidence_level {
0094 public:
0095
0096 explicit confidence_level(double cl) : cl_{cl} {
0097 if (cl <= 0 || cl >= 1)
0098 BOOST_THROW_EXCEPTION(std::invalid_argument("0 < cl < 1 is required"));
0099 }
0100
0101
0102 template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
0103 explicit operator T() const noexcept {
0104 return static_cast<T>(cl_);
0105 }
0106
0107
0108 operator deviation() const noexcept {
0109 return deviation{detail::normal_ppf(std::fma(0.5, cl_, 0.5))};
0110 }
0111
0112 friend bool operator==(confidence_level a, confidence_level b) noexcept {
0113 return a.cl_ == b.cl_;
0114 }
0115 friend bool operator!=(confidence_level a, confidence_level b) noexcept {
0116 return !(a == b);
0117 }
0118
0119 private:
0120 double cl_;
0121 };
0122
0123 inline deviation::operator confidence_level() const noexcept {
0124
0125 return confidence_level{std::fma(2.0, detail::normal_cdf(d_), -1.0)};
0126 }
0127
0128 }
0129 }
0130 }
0131
0132 #endif