RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
binomial.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4
11
13
14namespace randlib
15{
16
27template <typename IntType>
28class BinomialDistribution : public DiscreteDistribution<IntType>, public ExponentialFamily<IntType, double>
29{
30 IntType variate(detail::EngineRef g) const override { return (*this)(g); }
31 void sample(detail::EngineRef g, std::span<IntType> outputData) const override;
32
33protected:
34 double p = 0.5;
35 double q = 0.5;
38
39private:
40 IntType n = 1;
41 double np = 0.5;
42 double lfactn = 0;
43
44 double delta1{}, delta2{};
45 double sigma1{}, sigma2{}, c{};
46 double a1{}, a2{}, a3{}, a4{};
47 double coefa3{}, coefa4{};
48
49 double minpq = 0.5;
50 double pFloor = 0;
51 double logPFloor = -INFINITY;
52 double logQFloor = 0;
53 double pRes = 0.5;
54 double npFloor = 0;
55 double nqFloor = 0;
56 double logPnpInv = 0;
57
58 GeometricRand<IntType> geometric{};
59
60protected:
61 BinomialDistribution(IntType number, double probability);
62
63public:
64 [[nodiscard]] Support SupportType() const override { return Support::Finite; }
65 [[nodiscard]] IntType MinValue() const override { return 0; }
66 [[nodiscard]] IntType MaxValue() const override { return n; }
67
68private:
69 void SetGeneratorConstants();
70
71protected:
72 void SetParameters(IntType number, double probability);
73
74public:
75 [[nodiscard]] inline IntType GetNumber() const noexcept { return n; }
76 [[nodiscard]] inline double GetProbability() const noexcept { return p; }
77
78 double SufficientStatistic(IntType x) const override;
79 double SourceParameters() const override;
80 double SourceToNatural(double sourceParameters) const override;
81 double NaturalParameters() const override;
82 double LogNormalizer(double theta) const override;
83 double LogNormalizerGradient(double theta) const override;
84 double CarrierMeasure(IntType x) const override;
85 double EntropyAdjusted() const override;
86
87private:
92 double logProbFloor(int k) const;
93
94public:
95 [[nodiscard]] double P(const IntType &k) const override;
96 [[nodiscard]] double logP(const IntType &k) const override;
97 [[nodiscard]] double F(const IntType &k) const override;
98 [[nodiscard]] double S(const IntType &k) const override;
99
100private:
101 enum GENERATOR_ID
102 {
103 BERNOULLI_SUM,
104 WAITING,
105 REJECTION
106 };
107
108 [[nodiscard]] GENERATOR_ID GetIdOfUsedGenerator() const
109 {
112 if ((n <= 3) || (n <= 13 && minpq > 0.025 * (n + 6)) || (n <= 200 && math::detail::areClose(p, 0.5)))
113 return BERNOULLI_SUM;
114
116 if ((npFloor <= 12) || (pRes > 0 && npFloor <= 16))
117 return WAITING;
118
120 return REJECTION;
121 }
122
123 template <std::uniform_random_bit_generator G>
124 IntType variateRejection(G &g) const;
125 template <std::uniform_random_bit_generator G>
126 IntType variateWaiting(IntType number, G &g) const;
127 template <std::uniform_random_bit_generator G>
128 static IntType variateWaiting(IntType number, double probability, G &g);
129 template <std::uniform_random_bit_generator G>
130 static IntType variateBernoulliSum(IntType number, double probability, G &g);
131 template <std::uniform_random_bit_generator G>
132 static IntType variateInversion(IntType number, double probability, G &g);
133 template <std::uniform_random_bit_generator G>
134 static IntType variateTransformedRejection(IntType number, double probability, G &g);
135
136public:
137 template <std::uniform_random_bit_generator G>
138 [[nodiscard]] IntType operator()(G &g) const;
139
140 template <std::uniform_random_bit_generator G>
141 [[nodiscard]] static IntType Variate(IntType number, double probability, G &g);
142
143 [[nodiscard]] long double Mean() const override;
144 [[nodiscard]] long double Variance() const override;
145 [[nodiscard]] IntType Median() const override;
146 [[nodiscard]] IntType Mode() const override;
147 [[nodiscard]] long double Skewness() const override;
148 [[nodiscard]] long double ExcessKurtosis() const override;
149
153 [[nodiscard]] inline double GetLogFactorialN() const noexcept { return lfactn; }
157 [[nodiscard]] inline double GetLogProbability() const noexcept { return logProb; }
161 [[nodiscard]] inline double GetLog1mProbability() const noexcept { return log1mProb; }
162
163private:
164 std::complex<double> CFImpl(double t) const override;
165
166public:
171 RANDLIB_DEPRECATED_FIT_MEMBER void FitProbability(std::span<const IntType> sample);
172
181 FitProbabilityBayes(std::span<const IntType> sample, const BetaDistribution<> &priorDistribution, bool MAP = false);
182
189};
190
195template <typename IntType>
196class BinomialRand final : public BinomialDistribution<IntType>
197{
198public:
199 BinomialRand(int number = 1, double probability = 0.5) : BinomialDistribution<IntType>(number, probability) {}
200 [[nodiscard]] std::string Name() const override;
202};
203
204} // namespace randlib
205
211
212namespace randlib
213{
214
215template <typename IntType>
217{
218 SetParameters(number, probability);
219}
220
221template <typename IntType>
223{
224 minpq = std::min(p, q);
225 if (minpq == 0.0)
226 return;
227 npFloor = std::floor(n * minpq);
228 pFloor = npFloor / n;
229 pRes = math::detail::areClose(npFloor, n * minpq) ? 0.0 : minpq - pFloor;
230
231 GENERATOR_ID genId = GetIdOfUsedGenerator();
232 if (genId == BERNOULLI_SUM)
233 return;
234 else if (genId == WAITING) {
235 geometric.SetProbability(minpq);
236 return;
237 }
238
239 nqFloor = n - npFloor;
240 double qFloor = 1.0 - pFloor;
241 if (pRes > 0)
242 geometric.SetProbability(pRes / qFloor);
243
245 double npq = npFloor * qFloor;
246 double coef = 128.0 * n / randlib::consts::pi;
247 delta1 = coef * pFloor / (81.0 * qFloor);
248 delta1 = npq * std::log(delta1);
249 if (delta1 > 1.0)
250 delta1 = std::sqrt(delta1);
251 else
252 delta1 = 1.0;
253 delta2 = coef * qFloor / pFloor;
254 delta2 = npq * std::log(delta2);
255 if (delta2 > 1.0)
256 delta2 = std::sqrt(delta2);
257 else
258 delta2 = 1.0;
259
261 double npqSqrt = std::sqrt(npq);
262 sigma1 = npqSqrt * (1.0 + 0.25 * delta1 / npFloor);
263 sigma2 = npqSqrt * (1.0 + 0.25 * delta2 / nqFloor);
264 c = 2.0 * delta1 / npFloor;
265
267 a1 = 0.5 * std::exp(c) * sigma1 * randlib::consts::sqrt2pi;
268
269 a2 = 0.5 * sigma2 * randlib::consts::sqrt2pi;
270 a2 += a1;
271
272 coefa3 = 0.5 * delta1 / (sigma1 * sigma1);
273 a3 = 1.0 / nqFloor - coefa3;
274 a3 *= delta1;
275 a3 = std::exp(a3);
276 a3 /= coefa3;
277 a3 += a2;
278
279 coefa4 = 0.5 * delta2 / (sigma2 * sigma2);
280 a4 = std::exp(-delta2 * coefa4) / coefa4;
281 a4 += a3;
282
283 logPFloor = std::log(pFloor);
284 logQFloor = (pFloor == qFloor) ? logPFloor : std::log1pl(-pFloor);
285
286 logPnpInv = logProbFloor(npFloor);
287}
288
289template <typename IntType>
290void BinomialDistribution<IntType>::SetParameters(IntType number, double probability)
291{
292 if (!(probability >= 0.0 && probability <= 1.0))
293 throw std::invalid_argument("Binomial distribution: probability parameter should in interval [0, 1]");
294 if (!(number > 0))
295 throw std::invalid_argument("Binomial distribution: number should be positive");
296 n = number;
297 p = probability;
298 q = 1.0 - p;
299 np = n * p;
300 lfactn = math::lfact(n);
301 logProb = std::log(p);
302 log1mProb = std::log1pl(-p);
303 SetGeneratorConstants();
304}
305
306template <typename IntType>
308{
309 return x;
310}
311
312template <typename IntType>
314{
315 return this->p;
316}
317
318template <typename IntType>
319double BinomialDistribution<IntType>::SourceToNatural(double sourceParameters) const
320{
321 return std::log(sourceParameters) - std::log1p(-sourceParameters);
322}
323
324template <typename IntType>
326{
327 return this->logProb - this->log1mProb;
328}
329
330template <typename IntType>
332{
333 double F = n * math::softplus(theta);
334 F -= this->lfactn;
335 return F;
336}
337
338template <typename IntType>
340{
341 double expTheta = std::exp(theta);
342 return this->n * expTheta / (1.0 + expTheta);
343}
344
345template <typename IntType>
347{
348 double k = -math::lfact(x);
349 k -= math::lfact(n - x);
350 return k;
351}
352
353template <typename IntType>
355{
356 double H = this->p * this->logProb;
357 H += this->q * this->log1mProb;
358 H *= this->n;
359 H += this->lfactn;
360 return -H;
361}
362
363template <typename IntType>
365{
366 double y = lfactn;
367 y -= math::lfact(n - k);
368 y -= math::lfact(k);
369 y += k * logPFloor;
370 y += (n - k) * logQFloor;
371 return y;
372}
373
374template <typename IntType>
375double BinomialDistribution<IntType>::P(const IntType &k) const
376{
377 return (k < 0 || k > n) ? 0.0 : std::exp(logP(k));
378}
379
380template <typename IntType>
381double BinomialDistribution<IntType>::logP(const IntType &k) const
382{
383 if (k < 0 || k > n)
384 return -INFINITY;
385 if (k == 0)
386 return n * log1mProb;
387 if (k == n)
388 return n * logProb;
391 y -= math::bd0(k, n * p) + math::bd0(n - k, n * q);
392 return y - 0.5 * std::log(2 * randlib::consts::pi * k * (1.0 - static_cast<double>(k) / n));
393}
394
395template <typename IntType>
396double BinomialDistribution<IntType>::F(const IntType &k) const
397{
398 if (k < 0)
399 return 0.0;
400 if (k >= n)
401 return 1.0;
402 int nmk = n - k, kp1 = k + 1;
404 double logBetaFun = math::logBeta(nmk, kp1);
405 return math::ibeta(q, nmk, kp1, logBetaFun, log1mProb, logProb);
406}
407
408template <typename IntType>
409double BinomialDistribution<IntType>::S(const IntType &k) const
410{
411 if (k < 0)
412 return 1.0;
413 if (k >= n)
414 return 0.0;
415 int nmk = n - k, kp1 = k + 1;
416 double logBetaFun = math::logBeta(kp1, nmk);
417 return math::ibeta(p, kp1, nmk, logBetaFun, logProb, log1mProb);
418}
419
420template <typename IntType>
421template <std::uniform_random_bit_generator G>
423{
427 bool reject = true;
428 size_t iter = 0;
429 float Y, V = 0;
430 IntType X = 0;
431 do {
432 float U = a4 * detail::uniform01<float>(g);
433 if (U <= a1) {
435 Y = sigma1 * std::fabs(N);
436 reject = (Y >= delta1);
437 if (!reject) {
439 X = std::floor(Y);
440 V = -W - 0.5 * N * N + c;
441 }
442 } else if (U <= a2) {
444 Y = sigma2 * std::fabs(N);
445 reject = (Y >= delta2);
446 if (!reject) {
448 X = std::floor(-Y);
449 V = -W - 0.5 * N * N;
450 }
451 } else if (U <= a3) {
454 Y = delta1 + W1 / coefa3;
455 X = std::floor(Y);
456 V = -W2 - coefa3 * Y + delta1 / nqFloor;
457 reject = false;
458 } else {
461 Y = delta2 + W1 / coefa4;
462 X = std::floor(-Y);
463 V = -W2 - coefa4 * Y;
464 reject = false;
465 }
466
467 if (!reject) {
468 X += npFloor;
469 if (X >= 0 && X <= n && V <= logProbFloor(X) - logPnpInv)
470 return X;
471 }
472 } while (++iter <= ProbabilityDistribution<IntType>::MAX_ITER_REJECTION);
473 throw std::runtime_error("Binomial distribution: sampling failed");
474}
475
476template <typename IntType>
477template <std::uniform_random_bit_generator G>
478IntType BinomialDistribution<IntType>::variateWaiting(IntType number, G &g) const
479{
482 IntType X = 0, sum = 0;
483 while (true) {
484 IntType wait = geometric(g);
485 if (wait >= number - sum)
486 return X;
487 sum += wait + 1;
488 ++X;
489 }
490}
491
492template <typename IntType>
493template <std::uniform_random_bit_generator G>
494IntType BinomialDistribution<IntType>::variateWaiting(IntType number, double probability, G &g)
495{
496 IntType X = 0, sum = 0;
497 while (true) {
498 IntType wait = GeometricRand<IntType>::Variate(probability, g);
499 if (wait >= number - sum)
500 return X;
501 sum += wait + 1;
502 ++X;
503 }
504}
505
506template <typename IntType>
507template <std::uniform_random_bit_generator G>
508IntType BinomialDistribution<IntType>::variateBernoulliSum(IntType number, double probability, G &g)
509{
510 IntType var = 0;
511 if (math::detail::areClose(probability, 0.5)) {
512 for (int i = 0; i != number; ++i)
513 var += static_cast<IntType>(detail::randomBits(g, 1));
514 } else {
515 for (int i = 0; i != number; ++i)
516 var += static_cast<IntType>(detail::uniform01<double>(g) < probability);
517 }
518 return var;
519}
520
521template <typename IntType>
522template <std::uniform_random_bit_generator G>
524{
525 if (p == 0.0)
526 return 0;
527 if (p == 1.0)
528 return n;
529 GENERATOR_ID genId = GetIdOfUsedGenerator();
530 switch (genId) {
531 case WAITING: {
532 IntType var = variateWaiting(n, g);
533 return (p <= 0.5) ? var : n - var;
534 }
535 case REJECTION: {
538 IntType Z = variateRejection(g);
539 if (pRes > 0)
540 Z += variateWaiting(n - Z, g);
541 return (p > 0.5) ? n - Z : Z;
542 }
543 case BERNOULLI_SUM:
544 return variateBernoulliSum(n, p, g);
545 default:
546 throw std::invalid_argument("Binomial distribution: invalid generator id");
547 }
548}
549
550template <typename IntType>
551template <std::uniform_random_bit_generator G>
552IntType BinomialDistribution<IntType>::Variate(IntType number, double probability, G &g)
553{
555 if (!(number >= 0))
556 throw std::invalid_argument("Binomial distribution: number should be positive, but it's equal to " +
557 std::to_string(number));
558 if (!(probability >= 0.0 && probability <= 1.0))
559 throw std::invalid_argument(
560 "Binomial distribution: probability parameter should in interval [0, 1], but it's equal to " +
561 std::to_string(probability));
562 if (probability == 0.0)
563 return 0;
564 if (probability == 1.0)
565 return number;
566
567 if (number < 10)
568 return variateBernoulliSum(number, probability, g);
569 const bool complement = probability >= 0.5;
570 const double q = complement ? 1.0 - probability : probability;
571 const IntType var = (number * q < 10) ? variateInversion(number, q, g) : variateTransformedRejection(number, q, g);
572 return complement ? number - var : var;
573}
574
575template <typename IntType>
576template <std::uniform_random_bit_generator G>
577IntType BinomialDistribution<IntType>::variateInversion(IntType number, double probability, G &g)
578{
580 const double ratio = probability / (1.0 - probability), first = std::exp(number * std::log1p(-probability));
581 for (size_t iter = 0; iter < ProbabilityDistribution<IntType>::MAX_ITER_REJECTION; ++iter) {
582 const double u = detail::uniform01<double>(g);
583 double probabilityOfK = first, cumulative = first;
584 IntType k = 0;
585 while (u > cumulative && probabilityOfK > 0 && k < number) {
586 ++k;
587 probabilityOfK *= ratio * static_cast<double>(number - k + 1) / k;
588 cumulative += probabilityOfK;
589 }
591 if (u <= cumulative)
592 return k;
593 }
594 throw std::runtime_error("Binomial distribution: sampling failed");
595}
596
597template <typename IntType>
598template <std::uniform_random_bit_generator G>
599IntType BinomialDistribution<IntType>::variateTransformedRejection(IntType number, double probability, G &g)
600{
603 const double q = 1.0 - probability, spq = std::sqrt(number * probability * q);
604 const double b = 1.15 + 2.53 * spq, a = -0.0873 + 0.0248 * b + 0.01 * probability;
605 const double c = number * probability + 0.5, squeeze = 0.92 - 4.2 / b, alpha = (2.83 + 5.1 / b) * spq;
606 const double n = number, mode = std::floor((n + 1) * probability);
607 const double logOddsAtMode = std::log((n - mode + 1) * probability / ((mode + 1) * q));
608 auto correction = [](double x) { return math::stirlingError<double>(static_cast<size_t>(x) + 1); };
609 const double peakCorrection = correction(mode) + correction(n - mode);
610 for (size_t iter = 0; iter < 1000 * ProbabilityDistribution<IntType>::MAX_ITER_REJECTION; ++iter) {
611 const double u = detail::uniform01<double>(g) - 0.5, v = detail::uniform01<double>(g);
612 const double us = 0.5 - std::fabs(u);
613 const double x = std::floor((2 * a / us + b) * u + c);
614 if (x < 0 || x > n)
615 continue;
616 if (us >= 0.07 && v <= squeeze)
617 return static_cast<IntType>(x);
619 const double logRatio = (x + 0.5) * std::log1p((mode - x) / (x + 1)) +
620 (n - x + 0.5) * std::log1p((x - mode) / (n - x + 1)) + (x - mode) * logOddsAtMode +
621 peakCorrection - correction(x) - correction(n - x);
622 if (std::log(v * alpha / (a / (us * us) + b)) <= logRatio)
623 return static_cast<IntType>(x);
624 }
625 throw std::runtime_error("Binomial distribution: sampling failed");
626}
627
628template <typename IntType>
629void BinomialDistribution<IntType>::sample(detail::EngineRef g, std::span<IntType> outputData) const
630{
631 if (p == 0.0) {
632 std::fill(outputData.begin(), outputData.end(), 0);
633 return;
634 }
635 if (p == 1.0) {
636 std::fill(outputData.begin(), outputData.end(), n);
637 return;
638 }
639
640 GENERATOR_ID genId = GetIdOfUsedGenerator();
641 switch (genId) {
642 case WAITING: {
643 if (p <= 0.5) {
644 for (IntType &var : outputData)
645 var = variateWaiting(n, g);
646 } else {
647 for (IntType &var : outputData)
648 var = n - variateWaiting(n, g);
649 }
650 return;
651 }
652 case REJECTION: {
653 for (IntType &var : outputData)
654 var = variateRejection(g);
655 if (pRes > 0) {
656 for (IntType &var : outputData)
657 var += variateWaiting(n - var, g);
658 }
659 if (p > 0.5) {
660 for (IntType &var : outputData)
661 var = n - var;
662 }
663 return;
664 }
665 case BERNOULLI_SUM:
666 default: {
667 for (IntType &var : outputData)
668 var = variateBernoulliSum(n, p, g);
669 return;
670 }
671 }
672}
673
674template <typename IntType>
676{
677 return np;
678}
679
680template <typename IntType>
682{
683 return np * q;
684}
685
686template <typename IntType>
688{
690 IntType lower = std::floor(np);
691 return (this->F(lower) >= 0.5) ? lower : lower + 1;
692}
693
694template <typename IntType>
696{
697 return std::min(n, static_cast<IntType>(std::floor(np + p)));
698}
699
700template <typename IntType>
702{
703 return (q - p) / std::sqrt(np * q);
704}
705
706template <typename IntType>
708{
709 long double y = 1.0 / (p * q);
710 y -= 6.0;
711 return y / n;
712}
713
714template <typename IntType>
715std::complex<double> BinomialDistribution<IntType>::CFImpl(double t) const
716{
717 std::complex<double> y(q + p * std::cos(t), p * std::sin(t));
718 return std::pow(y, n);
719}
720
721template <typename IntType>
722void BinomialDistribution<IntType>::FitProbability(std::span<const IntType> sample)
723{
724 if (!this->allElementsAreNonNegative(sample))
725 throw this->fitError(FitErrorCode::WrongSample, this->NON_NEGATIVITY_VIOLATION);
726 if (!this->allElementsAreNotGreaterThan(n, sample))
727 throw this->fitError(FitErrorCode::WrongSample, this->UPPER_LIMIT_VIOLATION + this->toStringWithPrecision(n));
728 SetParameters(n, this->GetSampleMean(sample) / n);
729}
730
731template <typename IntType>
733 const BetaDistribution<> &priorDistribution, bool MAP)
734{
735 if (!this->allElementsAreNonNegative(sample))
736 throw this->fitError(FitErrorCode::WrongSample, this->NON_NEGATIVITY_VIOLATION);
737 if (!this->allElementsAreNotGreaterThan(n, sample))
738 throw this->fitError(FitErrorCode::WrongSample, this->UPPER_LIMIT_VIOLATION + this->toStringWithPrecision(n));
739 int N = sample.size();
740 double sum = this->GetSampleSum(sample);
741 double alpha = priorDistribution.GetAlpha();
742 double beta = priorDistribution.GetBeta();
743 BetaRand posteriorDistribution(sum + alpha, N * n - sum + beta);
744 SetParameters(n, MAP ? posteriorDistribution.Mode() : posteriorDistribution.Mean());
745 return posteriorDistribution;
746}
747
748template <typename IntType>
750{
751 double shape = 0.5 * std::sqrt(n);
752 BetaRand B(shape, shape);
753 return FitProbabilityBayes(sample, B);
754}
755template <typename IntType>
757{
758 return "Binomial(" + this->toStringWithPrecision(this->GetNumber()) + ", " +
759 this->toStringWithPrecision(this->GetProbability()) + ")";
760}
761
762} // namespace randlib
763
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 BinomialDistribution class Abstract class for Binomial distribution.
Definition binomial.hpp:29
long double Variance() const override
Definition binomial.hpp:681
double EntropyAdjusted() const override
Definition binomial.hpp:354
long double Mean() const override
Definition binomial.hpp:675
Support SupportType() const override
Definition binomial.hpp:64
double F(const IntType &k) const override
Definition binomial.hpp:396
double LogNormalizerGradient(double theta) const override
Definition binomial.hpp:339
double P(const IntType &k) const override
Definition binomial.hpp:375
double GetLogProbability() const noexcept
Definition binomial.hpp:157
BetaRand FitProbabilityMinimax(std::span< const IntType > sample)
Fit probability p with minimax estimator.
Definition binomial.hpp:749
double NaturalParameters() const override
Definition binomial.hpp:325
double GetLog1mProbability() const noexcept
Definition binomial.hpp:161
double SufficientStatistic(IntType x) const override
Definition binomial.hpp:307
double logProb
log(p)
Definition binomial.hpp:36
void SetParameters(IntType number, double probability)
Definition binomial.hpp:290
double logP(const IntType &k) const override
Definition binomial.hpp:381
IntType operator()(G &g) const
Definition binomial.hpp:523
double S(const IntType &k) const override
Definition binomial.hpp:409
long double ExcessKurtosis() const override
Definition binomial.hpp:707
double q
probability of failure
Definition binomial.hpp:35
IntType MaxValue() const override
Definition binomial.hpp:66
BinomialDistribution(IntType number, double probability)
Definition binomial.hpp:216
BetaRand FitProbabilityBayes(std::span< const IntType > sample, const BetaDistribution<> &priorDistribution, bool MAP=false)
Fit probability p with prior assumption p ~ Beta(α, β)
Definition binomial.hpp:732
IntType MinValue() const override
Definition binomial.hpp:65
IntType Median() const override
Definition binomial.hpp:687
double SourceParameters() const override
Definition binomial.hpp:313
double GetProbability() const noexcept
Definition binomial.hpp:76
double SourceToNatural(double sourceParameters) const override
Definition binomial.hpp:319
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition binomial.hpp:695
void FitProbability(std::span< const IntType > sample)
Fit probability p with maximum-likelihood estimation.
Definition binomial.hpp:722
double CarrierMeasure(IntType x) const override
Definition binomial.hpp:346
double log1mProb
log(q)
Definition binomial.hpp:37
double LogNormalizer(double theta) const override
Definition binomial.hpp:331
double p
probability of success
Definition binomial.hpp:34
long double Skewness() const override
Definition binomial.hpp:701
static IntType Variate(IntType number, double probability, G &g)
Definition binomial.hpp:552
double GetLogFactorialN() const noexcept
Definition binomial.hpp:153
IntType GetNumber() const noexcept
Definition binomial.hpp:75
The BinomialRand class Binomial distribution.
Definition binomial.hpp:197
BinomialRand(int number=1, double probability=0.5)
Definition binomial.hpp:199
std::string Name() const override
Definition binomial.hpp:756
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
Definition exponential_family.hpp:14
T Variate() const
Uses the engine of this object, so it is not thread-safe for one object; use operator() with one engi...
Definition distribution.hpp:133
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
#define RANDLIB_DETAIL_SUPPRESS_DEPRECATED_END
Definition fwd.hpp:26
#define RANDLIB_DETAIL_SUPPRESS_DEPRECATED_BEGIN
Definition fwd.hpp:25
#define RANDLIB_DEPRECATED_FIT_MEMBER
Definition fwd.hpp:9
constexpr long double ln2
Definition constants.hpp:18
constexpr long double pi
Definition constants.hpp:22
constexpr long double sqrt2pi
Definition constants.hpp:32
std::uint64_t randomBits(G &g, int count)
Definition engine/uniform.hpp:33
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
bool areClose(RealType a, RealType b, RealType eps=1e-6)
Definition functions.hpp:38
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 bd0(std::type_identity_t< Real > x, Real m)
Deviance term of the saddle-point expansions of Poisson and binomial probabilities (C.
Definition math/gamma.hpp:620
Real stirlingError(size_t n)
Definition math/gamma.hpp:598
Real softplus(Real x)
Definition functions.hpp:252
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
Definition bivariate_normal.hpp:10
@ WrongSample
the sample could not have been drawn from this distribution
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15