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 Count_ alt_drawn_inside = num_drawn - drawn_inside - 1;
118 if (drawn_inside > alt_drawn_inside) {
119 std::swap(num_inside, num_outside);
120 drawn_inside = alt_drawn_inside;
121 needs_upper = !needs_upper;
135 Count_ denom1a = drawn_inside, denom1b = num_inside - denom1a;
136 Count_ denom2a = num_drawn - drawn_inside, denom2b = num_outside - denom2a;
137 Count_ num_total = num_outside + num_inside;
138 long double log_probability =
139 + internal::lfactorial(num_inside) - internal::lfactorial(denom1a) - internal::lfactorial(denom1b)
140 + internal::lfactorial(num_outside) - internal::lfactorial(denom2a) - internal::lfactorial(denom2b)
141 - internal::lfactorial(num_total) + internal::lfactorial(num_drawn) + internal::lfactorial(num_total - num_drawn);
143 long double cumulative = 0;
144 long double partial_probability = 1;
146 for (Count_ k = drawn_inside; k > 0; --k) {
150 long double mult = (
static_cast<long double>(denom1a) *
static_cast<long double>(denom2b)) / (
static_cast<long double>(denom1b) *
static_cast<long double>(denom2a));
151 partial_probability *= mult;
152 if (partial_probability == 0) {
155 cumulative += partial_probability;
161 long double log_cumulative = std::log1p(cumulative) + log_probability;
164 return log_cumulative;
166 return std::exp(log_cumulative);
175 if (log_cumulative > -std::log(2)) {
176 auto p = -std::expm1(log_cumulative);
177 return (p > 0 ? std::log(p) : -std::numeric_limits<double>::infinity());
179 auto p = -std::exp(log_cumulative);
180 return (p > -1 ? std::log1p(p) : -std::numeric_limits<double>::infinity());
183 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