41 const DistributionFamily &family()
const override;
42 double mean()
const override {
43 if (!(p1_ > 1.0))
return kInf;
44 return p2_ / (p1_ - 1.0);
46 double variance()
const override {
47 if (!(p1_ > 2.0))
return kInf;
48 const double am1 = p1_ - 1.0;
49 return p2_ * p2_ / (am1 * am1 * (p1_ - 2.0));
51 double rawMoment(
unsigned k)
const override {
52 if (k == 0)
return 1.0;
53 const double alpha = p1_;
54 const double kd =
static_cast<double>(k);
55 if (!(alpha > kd))
return kInf;
58 for (
unsigned i = 1; i <= k; ++i) denom *= (alpha -
static_cast<double>(i));
59 return std::pow(p2_, kd) / denom;
61 double pdf(
double c)
const override {
62 const double alpha = p1_, beta = p2_;
63 if (!(alpha > 0.0) || !(beta > 0.0))
return kNaN;
64 if (c <= 0.0)
return 0.0;
66 return std::exp(alpha * std::log(beta) - std::lgamma(alpha)
67 - (alpha + 1.0) * std::log(c) - beta / c);
69 double cdf(
double c)
const override {
70 const double alpha = p1_, beta = p2_;
71 if (!(alpha > 0.0) || !(beta > 0.0))
return kNaN;
72 if (c <= 0.0)
return 0.0;
74 const double p =
gammaP(alpha, beta / c);
75 if (std::isnan(p))
return kNaN;
78 DistSupport support()
const override {
return {0.0,
kInf}; }
79 bool integrationRange(
double &lo,
double &hi)
const override {
80 const double alpha = p1_, beta = p2_;
81 if (!(alpha > 0.0 && beta > 0.0))
return false;
85 const double m = beta / (alpha - 1.0);
87 std::sqrt(beta * beta / ((alpha - 1.0) * (alpha - 1.0) * (alpha - 2.0)));
92 hi = beta * std::pow(1e9, 1.0 / alpha);
96 std::pair<double, double> plotRange(
double trunc_lo,
double trunc_hi)
const override {
97 double lo = trunc_lo, hi = trunc_hi;
98 if (!std::isfinite(lo)) lo = 0.0;
99 if (!std::isfinite(hi)) {
101 const double m = p2_ / (p1_ - 1.0);
102 const double sd = std::sqrt(
103 p2_ * p2_ / ((p1_ - 1.0) * (p1_ - 1.0) * (p1_ - 2.0)));
106 hi = p2_ * std::pow(1e3, 1.0 / p1_);
111 double sample(std::mt19937_64 &rng)
const override {
113 std::gamma_distribution<double> d(p1_, 1.0 / p2_);
114 const double y = d(rng);
117 std::unique_ptr<Distribution> affine(
double a,
double b)
const override {
121 if (!(a > 0.0) || b != 0.0)
return nullptr;
122 if (!(p1_ > 0.0))
return nullptr;
123 return std::make_unique<InverseGammaDistribution>(p1_, a * p2_);
125 std::string serialise()
const override {
131 "inverse_gamma", 2,
"IΓ", {
"α",
"β"},
132 +[](
double p1,
double p2) -> std::unique_ptr<Distribution> {
133 return std::make_unique<InverseGammaDistribution>(p1, p2);
138 return inverse_gamma_family;
141[[maybe_unused]]
const DistributionFamilyRegistrar inverse_gamma_family_registrar(
142 inverse_gamma_family);
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 gammaP(double a, double x)
Regularised lower incomplete gamma for a > 0, x >= 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.