27template <
typename IntType,
typename T>
43 static constexpr int tableSize = 16;
44 double table[tableSize];
52 [[nodiscard]] IntType
MinValue()
const override {
return 0; }
53 [[nodiscard]] IntType
MaxValue()
const override {
return std::numeric_limits<IntType>::max(); }
60 [[nodiscard]]
inline T
GetNumber() const noexcept {
return r; }
62 [[nodiscard]]
double P(
const IntType &k)
const override;
63 [[nodiscard]]
double logP(
const IntType &k)
const override;
64 [[nodiscard]]
double F(
const IntType &k)
const override;
65 [[nodiscard]]
double S(
const IntType &k)
const override;
84 static constexpr T LARGEST_SUMMED_NUMBER = 4;
85 if (r <= LARGEST_SUMMED_NUMBER && r == std::round(r))
90 template <std::uniform_random_bit_generator G>
92 template <std::uniform_random_bit_generator G>
96 template <std::uniform_random_bit_generator G>
97 IntType variateByTable(G &g)
const;
98 template <std::uniform_random_bit_generator G>
99 IntType variateThroughExponential(G &g)
const;
100 template <std::uniform_random_bit_generator G>
101 IntType variateThroughGammaPoisson(G &g)
const;
104 template <std::uniform_random_bit_generator G>
107 [[nodiscard]]
long double Mean()
const override;
108 [[nodiscard]]
long double Variance()
const override;
109 [[nodiscard]] IntType
Mode()
const override;
110 [[nodiscard]]
long double Skewness()
const override;
114 std::complex<double> CFImpl(
double t)
const override;
131template <
typename IntType,
typename T>
139 [[nodiscard]] std::string
Name()
const override;
152template <
typename IntType =
int>
155template <
typename IntType =
int>
168template <
typename IntType,
typename T>
171 SetParameters(number, probability);
174template <
typename IntType,
typename T>
178 throw std::invalid_argument(
"Negative-Binomial distribution: number parameter should be positive");
179 if (!(probability > 0.0 && probability <= 1.0))
180 throw std::invalid_argument(
181 "Negative-Binomial distribution: probability parameter should be in interval (0, 1]");
185 logProb = std::log(p);
186 log1mProb = std::log1pl(-p);
189 pdfCoef = -std::lgamma(r);
192 GammaRV.SetParameters(r, p / q);
193 qDivP = GammaRV.GetScale();
194 pdfCoef = r * logProb;
195 pdfCoef -= GammaRV.GetLogGammaShape();
197 if (GetIdOfUsedGenerator() == TABLE) {
201 for (
int i = 1; i < tableSize; ++i) {
203 table[i] = table[i - 1] + prod;
208template <
typename IntType,
typename T>
211 return (k < 0) ? 0.0 : std::exp(logP(k));
214template <
typename IntType,
typename T>
220 return (k == 0) ? 0.0 : -INFINITY;
221 double y = std::lgammal(r + k);
228template <
typename IntType,
typename T>
237 return math::ibeta(p, r, kp1, logBetaFun, logProb, log1mProb);
240template <
typename IntType,
typename T>
249 return math::ibeta(q, kp1, r, logBetaFun, log1mProb, logProb);
252template <
typename IntType,
typename T>
253template <std::uniform_random_bit_generator G>
257 const float rate = GammaRV(g);
261template <
typename IntType,
typename T>
262template <std::uniform_random_bit_generator G>
267 if (U > table[tableSize - 1])
268 return tableSize + variateGeometricByTable(g);
276template <
typename IntType,
typename T>
277template <std::uniform_random_bit_generator G>
281 if (!std::isfinite(X) || X >=
static_cast<long double>(std::numeric_limits<IntType>::max()))
282 return std::numeric_limits<IntType>::max();
283 return static_cast<IntType
>(X);
286template <
typename IntType,
typename T>
287template <std::uniform_random_bit_generator G>
291 for (
int i = 0; i < r; ++i) {
292 IntType add = variateGeometricByTable(g);
293 if (add > std::numeric_limits<IntType>::max() - var)
294 return std::numeric_limits<IntType>::max();
300template <
typename IntType,
typename T>
301template <std::uniform_random_bit_generator G>
302IntType NegativeBinomialDistribution<IntType, T>::variateThroughExponential(G &g)
const
305 for (
int i = 0; i < r; ++i) {
306 IntType add = variateGeometricThroughExponential(g);
307 if (add > std::numeric_limits<IntType>::max() - var)
308 return std::numeric_limits<IntType>::max();
314template <
typename IntType,
typename T>
315template <std::uniform_random_bit_generator G>
322 return variateByTable(g);
323 return (genId == EXPONENTIAL) ? variateThroughExponential(g) : variateThroughGammaPoisson(g);
326template <
typename IntType,
typename T>
330 std::fill(outputData.begin(), outputData.end(), 0);
333 GENERATOR_ID genId = GetIdOfUsedGenerator();
334 if (genId == TABLE) {
335 for (IntType &var : outputData)
336 var = variateByTable(g);
337 }
else if (genId == EXPONENTIAL) {
338 for (IntType &var : outputData)
339 var = variateThroughExponential(g);
341 for (IntType &var : outputData)
342 var = variateThroughGammaPoisson(g);
346template <
typename IntType,
typename T>
352template <
typename IntType,
typename T>
355 return qDivP * r / p;
358template <
typename IntType,
typename T>
361 std::complex<double> denominator(1.0 - q * std::cos(t), -q * std::sin(t));
362 return std::pow(p / denominator, r);
365template <
typename IntType,
typename T>
368 return (r > 1) ? std::floor((r - 1) * qDivP) : 0;
371template <
typename IntType,
typename T>
376 return (1 + q) / std::sqrt(q * r);
379template <
typename IntType,
typename T>
384 long double kurtosis = p / qDivP;
389template <
typename IntType,
typename T>
394 if (!this->allElementsAreNonNegative(sample))
396 int n = sample.size();
397 double alpha = priorDistribution.
GetAlpha();
398 double beta = priorDistribution.
GetBeta();
399 BetaRand<> posteriorDistribution(alpha + r * n, beta + this->GetSampleSum(sample));
400 SetParameters(r, MAP ? posteriorDistribution.
Mode() : posteriorDistribution.
Mean());
401 return posteriorDistribution;
403template <
typename IntType,
typename T>
406 if (std::is_integral_v<T>)
407 return "Pascal(" + this->toStringWithPrecision(this->GetNumber()) +
", " +
408 this->toStringWithPrecision(this->GetProbability()) +
")";
409 return "Polya(" + this->toStringWithPrecision(this->GetNumber()) +
", " +
410 this->toStringWithPrecision(this->GetProbability()) +
")";
413template <
typename IntType,
typename T>
416template <
typename IntType,
typename T>
420 if (!this->allElementsAreNonNegative(sample))
423 DoublePair stats = this->GetSampleMeanAndVariance(sample);
424 double mean = stats.first, variance = stats.second;
426 if (variance <= mean)
428 double guess = mean * mean / (variance - mean);
429 size_t n = sample.size();
430 auto score = [sample, mean, n](
double x) {
431 double first = 0.0, second = 0.0;
432 for (
const IntType &var : sample) {
440 double logGuess = std::log(guess);
441 if (!math::findRootNewtonFirstOrder<double>(
442 [&score](
double logNumber) {
443 double number = std::exp(logNumber);
445 value.second *= number;
450 guess = std::exp(logGuess);
451 if (!std::isfinite(guess) || guess <= 0.0)
453 "Number should be positive, but returned value is " + this->toStringWithPrecision(guess));
454 SetParameters(guess, guess / (guess + mean));
The BetaDistribution class Abstract class for Beta distribution.
Definition continuous/beta.hpp:33
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition continuous/beta.hpp:808
double GetAlpha() const noexcept
Definition continuous/beta.hpp:128
long double Mean() const override
Definition continuous/beta.hpp:761
double GetBeta() const noexcept
Definition continuous/beta.hpp:132
The BetaRand class Beta distribution.
Definition continuous/beta.hpp:246
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
The GammaRand class Gamma distribution.
Definition continuous/gamma.hpp:295
The NegativeBinomialDistribution class Abstract class for Negative binomial distribution.
Definition negative_binomial.hpp:29
BetaRand FitProbabilityBayes(std::span< const IntType > sample, const BetaDistribution<> &priorDistribution, bool MAP=false)
Definition negative_binomial.hpp:390
IntType MinValue() const override
Definition negative_binomial.hpp:52
NegativeBinomialDistribution(T number=1, double probability=0.5)
Definition negative_binomial.hpp:169
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition negative_binomial.hpp:366
double P(const IntType &k) const override
Definition negative_binomial.hpp:209
T GetNumber() const noexcept
Definition negative_binomial.hpp:60
long double Mean() const override
Definition negative_binomial.hpp:347
double F(const IntType &k) const override
Definition negative_binomial.hpp:229
double log1mProb
log(q)
Definition negative_binomial.hpp:37
double S(const IntType &k) const override
Definition negative_binomial.hpp:241
double q
probability of success
Definition negative_binomial.hpp:35
long double Variance() const override
Definition negative_binomial.hpp:353
GENERATOR_ID GetIdOfUsedGenerator() const
For a small integer r the variate is a sum of r geometric variates, drawn by a table or,...
Definition negative_binomial.hpp:81
double logProb
log(p)
Definition negative_binomial.hpp:36
double p
probability of failure
Definition negative_binomial.hpp:34
long double ExcessKurtosis() const override
Definition negative_binomial.hpp:380
IntType variateGeometricByTable(G &g) const
Definition negative_binomial.hpp:263
Support SupportType() const override
Definition negative_binomial.hpp:51
void SetParameters(T number, double probability)
Definition negative_binomial.hpp:175
double GetProbability() const noexcept
Definition negative_binomial.hpp:59
double logP(const IntType &k) const override
Definition negative_binomial.hpp:215
GENERATOR_ID
Definition negative_binomial.hpp:69
@ TABLE
Definition negative_binomial.hpp:70
@ EXPONENTIAL
Definition negative_binomial.hpp:71
@ GAMMA_POISSON
Definition negative_binomial.hpp:72
IntType operator()(G &g) const
Definition negative_binomial.hpp:316
IntType variateGeometricThroughExponential(G &g) const
Definition negative_binomial.hpp:278
long double Skewness() const override
Definition negative_binomial.hpp:372
IntType MaxValue() const override
Definition negative_binomial.hpp:53
The NegativeBinomialRand class Negative binomial distribution.
Definition negative_binomial.hpp:133
NegativeBinomialRand(T number=1, double probability=0.5)
Definition negative_binomial.hpp:135
void Fit(std::span< const IntType > sample)
set number and probability, estimated via maximum-likelihood method
Definition negative_binomial.hpp:417
std::string Name() const override
Definition negative_binomial.hpp:404
static constexpr char TOO_SMALL_VARIANCE[]
Definition negative_binomial.hpp:143
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
#define RANDLIB_DEPRECATED_FIT_MEMBER
Definition fwd.hpp:9
constexpr long double ln2
Definition constants.hpp:18
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real digamma(Real x)
Definition math/gamma.hpp:691
Real logBeta(Real a, std::type_identity_t< Real > b)
Calculate logarithm of beta function.
Definition math/beta.hpp:72
Real lfact(size_t n)
Calculate log(n!) using table values for small n <= 255 and built-in lgamma function for large n > 25...
Definition math/gamma.hpp:591
Real ibeta(Real x, std::type_identity_t< Real > a, std::type_identity_t< Real > b, std::type_identity_t< Real > logBetaFun, std::type_identity_t< Real > logX, std::type_identity_t< Real > log1mX)
Fast calculation of regularized beta function, using precalculated values.
Definition math/beta.hpp:250
Real trigamma(Real x)
Definition math/gamma.hpp:720
Real digammamLog(Real x)
Definition math/gamma.hpp:710
Definition bivariate_normal.hpp:10
@ WrongSample
the sample could not have been drawn from this distribution
@ NotApplicable
the method cannot be applied to this distribution or sample
@ WrongReturn
the method returned invalid parameters
@ Undefined
any other failure
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
Pair< double > DoublePair
Definition fwd.hpp:39