34 const DistributionFamily &family()
const override;
36 long n()
const {
return static_cast<long>(std::llround(p1_)); }
38 double mean()
const override {
return p1_ * p2_; }
39 bool isDiscrete()
const override {
return true; }
40 double variance()
const override {
return p1_ * p2_ * (1.0 - p2_); }
41 double rawMoment(
unsigned k)
const override {
42 if (k == 0)
return 1.0;
46 for (
long j = 0; j <= nn; ++j)
47 total += std::pow(
static_cast<double>(j),
static_cast<double>(k)) * pmf(j);
50 double pdf(
double c)
const override {
51 if (!valid())
return kNaN;
52 const double r = std::nearbyint(c);
53 if (std::fabs(c - r) > 1e-9)
return 0.0;
54 const long k =
static_cast<long>(r);
55 if (k < 0 || k > n())
return 0.0;
58 double cdf(
double c)
const override {
59 if (!valid())
return kNaN;
60 if (c < 0.0)
return 0.0;
62 const long kmax = std::min(nn,
static_cast<long>(std::floor(c)));
64 for (
long k = 0; k <= kmax; ++k) s += pmf(k);
65 return s > 1.0 ? 1.0 : s;
67 DistSupport support()
const override {
68 return {0.0,
static_cast<double>(n())};
70 bool integrationRange(
double &lo,
double &hi)
const override {
72 if (!valid())
return false;
74 hi =
static_cast<double>(n());
77 std::pair<double, double> plotRange(
double trunc_lo,
78 double trunc_hi)
const override {
79 double lo = trunc_lo, hi = trunc_hi;
80 if (!std::isfinite(lo)) lo = 0.0;
81 if (!std::isfinite(hi)) hi =
static_cast<double>(n());
84 double sample(std::mt19937_64 &rng)
const override {
85 std::binomial_distribution<long> d(n(), p2_);
86 return static_cast<double>(d(rng));
88 std::optional<double> quantile(
double p)
const override {
89 if (!valid())
return std::nullopt;
90 if (p <= 0.0)
return 0.0;
93 for (
long k = 0; k <= nn; ++k) {
95 if (s >= p)
return static_cast<double>(k);
97 return static_cast<double>(nn);
99 std::unique_ptr<Distribution> affine(
double,
double)
const override {
102 std::string serialise()
const override {
108 return std::isfinite(p1_) && p1_ >= 0.0 &&
109 p2_ >= 0.0 && p2_ <= 1.0;
111 double pmf(
long k)
const {
113 if (k < 0 || k > nn)
return 0.0;
115 if (p2_ <= 0.0)
return (k == 0) ? 1.0 : 0.0;
116 if (p2_ >= 1.0)
return (k == nn) ? 1.0 : 0.0;
117 const double logC = std::lgamma(nn + 1.0) - std::lgamma(k + 1.0)
118 - std::lgamma(nn - k + 1.0);
119 return std::exp(logC + k * std::log(p2_)
120 + (nn - k) * std::log1p(-p2_));
125 "binomial", 2,
"Bin", {
"n",
"p"},
126 +[](
double p1,
double p2) -> std::unique_ptr<Distribution> {
127 return std::make_unique<BinomialDistribution>(p1, p2);
132 return binomial_family;
141bool binomialPConjugateUpdate(
double &alpha,
double &beta,
142 const DistributionTemplate &lik,
double d)
144 const double n = lik.p1.literal;
145 if (!(alpha > 0.0) || !(beta > 0.0))
return false;
146 if (n < 1.0 || n != std::floor(n))
return false;
147 const double r = std::nearbyint(d);
148 if (std::fabs(d - r) > 1e-9 || r < 0.0 || r > n)
return false;
154double binomialPLogPredictive(
double alpha,
double beta,
155 const DistributionTemplate &lik,
double d)
157 const double n = lik.p1.literal;
158 if (!(alpha > 0.0) || !(beta > 0.0))
return kNaN;
159 if (n < 1.0 || n != std::floor(n))
return kNaN;
160 const double r = std::nearbyint(d);
161 if (std::fabs(d - r) > 1e-9 || r < 0.0 || r > n)
return kNaN;
162 return std::lgamma(n + 1.0) - std::lgamma(r + 1.0)
163 - std::lgamma(n - r + 1.0)
164 +
lbeta(alpha + r, beta + n - r) -
lbeta(alpha, beta);
167[[maybe_unused]]
const ConjugateRuleRegistrar binomial_p_conjugate(
168 "binomial", 1,
"beta",
169 {&binomialPConjugateUpdate, &binomialPLogPredictive});
171[[maybe_unused]]
const DistributionFamilyRegistrar binomial_family_registrar(
Internal helpers shared by the per-family Distribution implementations under src/distributions/.
Base holding the two parameters; subclasses add closed forms.
BaseDistribution(double p1, double p2)
double lbeta(double a, double b)
ln B(a, b) = lnΓ(a) + lnΓ(b) − lnΓ(a+b), for a, b > 0.
std::string double_to_text(double v)
Format a double back into the canonical text form used by gate_value extras and gate_rv distribution ...
A registered family's descriptor: its complete identity.