89double compute(Count_ drawn_inside, Count_ num_inside, Count_ num_outside, Count_ num_drawn,
const Options& options) {
92 if (drawn_inside <= 0 || (num_drawn >= num_outside && drawn_inside <= num_drawn - num_outside)) {
93 return (options.
log ? 0 : 1);
95 if (drawn_inside > num_drawn || drawn_inside > num_inside) {
96 return (options.
log ? -std::numeric_limits<double>::infinity() : 0);
99 if (drawn_inside < 0 || (num_drawn >= num_outside && drawn_inside < num_drawn - num_outside)) {
100 return (options.
log ? -std::numeric_limits<double>::infinity() : 0);
102 if (drawn_inside >= num_drawn || drawn_inside >= num_inside) {
103 return (options.
log ? 0 : 1);
117 if (
static_cast<double>(drawn_inside) *
static_cast<double>(num_inside + num_outside) >
static_cast<double>(num_drawn) *
static_cast<double>(num_inside)) {
118 std::swap(num_inside, num_outside);
119 drawn_inside = num_drawn - drawn_inside - 1;
120 needs_upper = !needs_upper;
134 Count_ denom1a = drawn_inside, denom1b = num_inside - denom1a;
135 Count_ denom2a = num_drawn - drawn_inside, denom2b = num_outside - denom2a;
136 Count_ num_total = num_outside + num_inside;
137 long double log_probability =
138 + internal::lfactorial(num_inside) - internal::lfactorial(denom1a) - internal::lfactorial(denom1b)
139 + internal::lfactorial(num_outside) - internal::lfactorial(denom2a) - internal::lfactorial(denom2b)
140 - internal::lfactorial(num_total) + internal::lfactorial(num_drawn) + internal::lfactorial(num_total - num_drawn);
142 long double cumulative = 0;
143 long double partial_probability = 1;
145 for (Count_ k = drawn_inside; k > 0; --k) {
149 long double mult = (
static_cast<long double>(denom1a) *
static_cast<long double>(denom2b)) / (
static_cast<long double>(denom1b) *
static_cast<long double>(denom2a));
150 partial_probability *= mult;
151 if (partial_probability == 0) {
154 cumulative += partial_probability;
160 long double log_cumulative = std::log1p(cumulative) + log_probability;
163 return log_cumulative;
165 return std::exp(log_cumulative);
174 if (log_cumulative > -std::log(2)) {
175 auto p = -std::expm1(log_cumulative);
176 return (p > 0 ? std::log(p) : -std::numeric_limits<double>::infinity());
178 auto p = -std::exp(log_cumulative);
179 return (p > -1 ? std::log1p(p) : -std::numeric_limits<double>::infinity());
182 return -std::expm1(log_cumulative);
double compute(Count_ drawn_inside, Count_ num_inside, Count_ num_outside, Count_ num_drawn, const Options &options)
Definition phyper.hpp:89