123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #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 {
- 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>;
-
- virtual interval_type operator()(value_type successes,
- value_type failures) const noexcept = 0;
-
- template <class T>
- interval_type operator()(const accumulators::fraction<T>& fraction) const noexcept {
- return operator()(fraction.successes(), fraction.failures());
- }
- };
- class deviation;
- class confidence_level;
- class deviation {
- public:
-
- explicit deviation(double d) : d_{d} {
- if (d <= 0)
- BOOST_THROW_EXCEPTION(std::invalid_argument("scaling factor must be positive"));
- }
-
- template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
- explicit operator T() const noexcept {
- return static_cast<T>(d_);
- }
-
- operator confidence_level() const noexcept;
- 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_;
- };
- class confidence_level {
- public:
-
- explicit confidence_level(double cl) : cl_{cl} {
- if (cl <= 0 || cl >= 1)
- BOOST_THROW_EXCEPTION(std::invalid_argument("0 < cl < 1 is required"));
- }
-
- template <class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
- explicit operator T() const noexcept {
- return static_cast<T>(cl_);
- }
-
- 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 {
-
- return confidence_level{std::fma(2.0, detail::normal_cdf(d_), -1.0)};
- }
- }
- }
- }
- #endif
|