RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
logarithmic.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
19template <typename IntType>
20class LogarithmicRand final : public DiscreteDistribution<IntType>
21{
22 IntType variate(detail::EngineRef g) const override { return (*this)(g); }
23
24 double p = 0.5;
25 double logProb = -randlib::consts::ln2;
26 double log1mProb = -randlib::consts::ln2;
27public:
28 explicit LogarithmicRand(double probability);
29 [[nodiscard]] std::string Name() const override;
30 [[nodiscard]] Support SupportType() const override { return Support::RightSemiFinite; }
31 [[nodiscard]] IntType MinValue() const override { return 1; }
32 [[nodiscard]] IntType MaxValue() const override { return std::numeric_limits<IntType>::max(); }
33
34 void SetProbability(double probability);
35 [[nodiscard]] inline double GetProbability() const noexcept { return p; }
36
37 [[nodiscard]] double P(const IntType &k) const override;
38 [[nodiscard]] double logP(const IntType &k) const override;
39
40private:
46 double betaFun(IntType a) const;
47
48public:
49 [[nodiscard]] double F(const IntType &k) const override;
50 [[nodiscard]] double S(const IntType &k) const override;
51 template <std::uniform_random_bit_generator G>
52 [[nodiscard]] IntType operator()(G &g) const;
53
54 [[nodiscard]] long double Mean() const override;
55 [[nodiscard]] long double Variance() const override;
56 [[nodiscard]] IntType Mode() const override;
57
58private:
59 std::complex<double> CFImpl(double t) const override;
60};
61
62} // namespace randlib
63
65
66namespace randlib
67{
68
69template <typename IntType>
71{
72 SetProbability(probability);
73}
74
75template <typename IntType>
77{
78 return "Logarithmic(" + this->toStringWithPrecision(GetProbability()) + ")";
79}
80
81template <typename IntType>
83{
84 if (!(probability > 0.0 && probability < 1.0))
85 throw std::invalid_argument("Logarithmic distribution: probability parameter should in interval (0, 1)");
86 p = probability;
87 logProb = std::log(p);
88 log1mProb = std::log1pl(-p);
89}
90
91template <typename IntType>
92double LogarithmicRand<IntType>::P(const IntType &k) const
93{
94 return (k < 1) ? 0.0 : -std::pow(p, k) / (k * log1mProb);
95}
96
97template <typename IntType>
98double LogarithmicRand<IntType>::logP(const IntType &k) const
99{
100 return (k < 1) ? -INFINITY : k * logProb - std::log(-k * log1mProb);
101}
102
103template <typename IntType>
104double LogarithmicRand<IntType>::betaFun(IntType a) const
105{
107 double denom = a + 2;
108 double sum = p * p / (a + 2) + p / (a + 1) + 1.0 / a;
109 double add = 1;
110 int i = 3;
111 do {
112 add = std::exp(i * logProb) / (++denom);
113 sum += add;
114 ++i;
115 } while (add > math::detail::minimumTolerance * sum);
116 return std::exp(a * logProb) * sum;
117}
118
119template <typename IntType>
120double LogarithmicRand<IntType>::F(const IntType &k) const
121{
122 return (k < 1) ? 0.0 : 1 + betaFun(k + 1) / log1mProb;
123}
124
125template <typename IntType>
126double LogarithmicRand<IntType>::S(const IntType &k) const
127{
128 return (k < 1) ? 1.0 : -betaFun(k + 1) / log1mProb;
129}
130
131template <typename IntType>
132template <std::uniform_random_bit_generator G>
134{
137 float V = detail::uniform01<float>(g);
138 if (V >= p)
139 return 1.0;
140 float U = detail::uniform01<float>(g);
141 double y = -std::expm1l(U * log1mProb);
142 if (V > y)
143 return 1.0;
144 if (V > y * y)
145 return 2.0;
146 return std::floor(1.0 + std::log(V) / std::log(y));
147}
148
149template <typename IntType>
151{
152 return -p / (1.0 - p) / log1mProb;
153}
154
155template <typename IntType>
157{
158 long double var = p / log1mProb + 1;
159 var /= log1mProb;
160 var *= p;
161 long double q = 1.0 - p;
162 return -var / (q * q);
163}
164
165template <typename IntType>
166std::complex<double> LogarithmicRand<IntType>::CFImpl(double t) const
167{
168 std::complex<double> y(std::cos(t), std::sin(t));
169 y = std::log(1.0 - p * y);
170 return y / log1mProb;
171}
172
173template <typename IntType>
175{
176 return 1.0;
177}
178
179} // namespace randlib
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
The LogarithmicRand class Logarithmic distribution.
Definition logarithmic.hpp:21
std::string Name() const override
Definition logarithmic.hpp:76
double P(const IntType &k) const override
Definition logarithmic.hpp:92
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition logarithmic.hpp:174
IntType MinValue() const override
Definition logarithmic.hpp:31
Support SupportType() const override
Definition logarithmic.hpp:30
double GetProbability() const noexcept
Definition logarithmic.hpp:35
void SetProbability(double probability)
Definition logarithmic.hpp:82
LogarithmicRand(double probability)
Definition logarithmic.hpp:70
double S(const IntType &k) const override
Definition logarithmic.hpp:126
long double Variance() const override
Definition logarithmic.hpp:156
IntType operator()(G &g) const
Definition logarithmic.hpp:133
double logP(const IntType &k) const override
Definition logarithmic.hpp:98
long double Mean() const override
Definition logarithmic.hpp:150
double F(const IntType &k) const override
Definition logarithmic.hpp:120
IntType MaxValue() const override
Definition logarithmic.hpp:32
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
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
constexpr long double minimumTolerance
Definition constants.hpp:44
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)