61 #ifndef THRILL_COMMON_HYPERGEOMETRIC_DISTRIBUTION_HEADER 62 #define THRILL_COMMON_HYPERGEOMETRIC_DISTRIBUTION_HEADER 72 template <
typename int_t =
int64_t,
typename fp_t =
double>
85 sLOG1 <<
"hypergeometric distribution error: sample < 1:" << sample;
86 return static_cast<int_t
>(-1);
88 if (good + bad < sample) {
89 sLOG1 <<
"hypergeometric distribution error: good + bad < sample:" 90 <<
"good:" << good <<
"bad:" << bad <<
"sample:" << sample;
91 return static_cast<int_t
>(-1);
96 void seed(
size_t seed_val) {
107 fp_t x0, x2, xp, gl, gl0;
110 static fp_t a[10] = {
111 8.333333333333333e-02, -2.777777777777778e-03,
112 7.936507936507937e-04, -5.952380952380952e-04,
113 8.417508417508418e-04, -1.917526917526918e-03,
114 6.410256410256410e-03, -2.955065359477124e-02,
115 1.796443723688307e-01, -1.39243221690590e+00
119 if ((x == 1.0) || (x == 2.0))
125 n =
static_cast<int_t
>(7 -
x);
128 x2 = 1.0 / (x0 * x0);
131 for (k = 8; k >= 0; k--)
136 gl = gl0 / x0 + 0.5 * std::log(xp) + (x0 - 0.5) * std::log(x0) - x0;
139 for (k = 1; k <= n; k++)
141 gl -= std::log(x0 - 1.0);
150 static constexpr fp_t
D1 = 1.7155277699214135;
151 static constexpr fp_t
D2 = 0.8989161620588988;
157 d1 = bad + good - sample;
158 d2 =
static_cast<fp_t
>(
std::min(bad, good));
164 Y -=
static_cast<int_t
>(floor(U + Y / (d1 + K)));
168 Z =
static_cast<int_t
>(d2 - Y);
169 if (good > bad) Z = sample - Z;
174 int_t mingoodbad, maxgoodbad, popsize, m, d9;
175 fp_t d4, d5, d6, d7, d8, d10, d11;
180 popsize = good + bad;
182 m =
std::min(sample, popsize - sample);
183 d4 =
static_cast<fp_t
>(mingoodbad) / popsize;
186 d7 = sqrt(static_cast<fp_t>(popsize - m) * sample * d4 * d5 /
187 (popsize - 1) + 0.5);
189 d9 =
static_cast<int_t
>(floor(static_cast<fp_t>(m + 1) *
190 (mingoodbad + 1) / (popsize + 2)));
193 loggam(maxgoodbad - m + d9 + 1));
200 W = d6 + d8 * (Y - 0.5) / X;
203 if ((W < 0.0) || (W >= d11))
continue;
205 Z =
static_cast<int_t
>(floor(W));
210 if ((X * (4.0 - X) - 3.0) <=
T)
break;
213 if (X * (X - T) >= 1)
continue;
215 if (2.0 * std::log(X) <=
T)
break;
219 if (good > bad) Z = m - Z;
222 if (m < sample) Z = good - Z;
238 std::uniform_real_distribution<fp_t>
dist;
246 #endif // !THRILL_COMMON_HYPERGEOMETRIC_DISTRIBUTION_HEADER
static uint_pair max()
return an uint_pair instance containing the largest value possible
void seed(size_t seed_val)
int_t operator()(int_t good, int_t bad, int_t sample)
int_t rk_hypergeometric_hrua(int_t good, int_t bad, int_t sample)
std::uniform_real_distribution< fp_t > dist
static const uint64_t K[80]
hypergeometric_distribution(size_t seed=0)
static uint_pair min()
return an uint_pair instance containing the smallest value possible
int_t rk_hypergeometric_hyp(int_t good, int_t bad, int_t sample)
int_t rk_hypergeometric(int_t good, int_t bad, int_t sample)
fp_t loggam(fp_t x) const