RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
planck.hpp
Go to the documentation of this file.
1#pragma once
2
9
10namespace randlib
11{
12
25template <typename RealType>
26class PlanckRand final : public ContinuousDistribution<RealType>
27{
28 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
29 void sample(detail::EngineRef g, std::span<RealType> outputData) const override;
30
31 double a = 1;
32 double b = 1;
35
37 GammaRand<RealType> gammaVariable{2};
38
39public:
40 PlanckRand(double shape = 1, double scale = 1);
41
42 [[nodiscard]] std::string Name() const override;
43 [[nodiscard]] Support SupportType() const override { return Support::RightSemiFinite; }
44 [[nodiscard]] RealType MinValue() const override { return 0; }
45 [[nodiscard]] RealType MaxValue() const override { return INFINITY; }
46
47 void SetParameters(double shape, double scale);
48 [[nodiscard]] inline double GetShape() const noexcept { return a; }
49 [[nodiscard]] inline double GetScale() const noexcept { return b; }
50
51private:
56 double h(double t) const;
57
58public:
59 [[nodiscard]] double f(const RealType &x) const override;
60 [[nodiscard]] double logf(const RealType &x) const override;
61 [[nodiscard]] double F(const RealType &x) const override;
62 [[nodiscard]] double S(const RealType &x) const override;
63 template <std::uniform_random_bit_generator G>
64 [[nodiscard]] RealType operator()(G &g) const;
65
66 [[nodiscard]] long double Mean() const override;
67 [[nodiscard]] long double SecondMoment() const override;
68 [[nodiscard]] long double Variance() const override;
69 [[nodiscard]] RealType Mode() const override;
70 [[nodiscard]] long double ThirdMoment() const override;
71 [[nodiscard]] long double Skewness() const override;
72 [[nodiscard]] long double FourthMoment() const override;
73 [[nodiscard]] long double ExcessKurtosis() const override;
74
75private:
76 std::complex<double> CFImpl(double t) const override;
77};
78
79} // namespace randlib
80
81namespace randlib
82{
83
84template <typename RealType>
85PlanckRand<RealType>::PlanckRand(double shape, double scale)
86{
87 SetParameters(shape, scale);
88}
89
90template <typename RealType>
91std::string PlanckRand<RealType>::Name() const
92{
93 return "Planck(" + this->toStringWithPrecision(GetShape()) + ", " + this->toStringWithPrecision(GetScale()) + ")";
94}
95
96template <typename RealType>
97void PlanckRand<RealType>::SetParameters(double shape, double scale)
98{
99 if (!(shape > 0.0))
100 throw std::invalid_argument("Planck distribution: shape should be positive, but it's equal to " +
101 std::to_string(shape));
102 if (!(scale > 0.0))
103 throw std::invalid_argument("Planck distribution: scale should be positive, but it's equal to " +
104 std::to_string(scale));
105 a = shape;
106 b = scale;
107
108 double ap1 = a + 1;
109 Z.SetExponent(ap1);
110 gammaVariable.SetParameters(ap1, b);
111
112 pdfCoef = -Z.GetLogZetaFunction();
113 pdfCoef += ap1 * std::log(b);
114 pdfCoef -= gammaVariable.GetLogGammaShape();
115}
116
117template <typename RealType>
118double PlanckRand<RealType>::h(double t) const
119{
120 if (t <= 0)
121 return 0.0;
122 double y = pdfCoef + a * std::log(t);
123 double expY = std::exp(y);
124 double bt = b * t;
125 double z = 1.0 / std::expm1l(bt) - 1.0 / bt;
126 return expY * z;
127}
128
129template <typename RealType>
130double PlanckRand<RealType>::f(const RealType &x) const
131{
132 if (x < 0)
133 return 0;
134 if (x == 0) {
135 if (a > 1)
136 return 0.0;
137 if (a == 1)
138 return std::exp(pdfCoef) / b;
139 return INFINITY;
140 }
141 double y = pdfCoef + a * std::log(x);
142 return std::exp(y) / std::expm1l(b * x);
143}
144
145template <typename RealType>
146double PlanckRand<RealType>::logf(const RealType &x) const
147{
148 if (x < 0.0)
149 return -INFINITY;
150 if (x == 0) {
151 if (a > 1)
152 return -INFINITY;
153 if (a == 1)
154 return pdfCoef - gammaVariable.GetLogRate();
155 return INFINITY;
156 }
157 double y = pdfCoef + a * std::log(x);
158 return y - math::logexpm1l(b * x);
159}
160
161template <typename RealType>
162double PlanckRand<RealType>::F(const RealType &x) const
163{
164 if (x <= 0)
165 return 0.0;
166
167 if (a >= 1) {
168 return math::integrate([this](double t) { return f(t); }, 0, x);
169 }
170
172 double aux = pdfCoef + a * std::log(x);
173 double integral1 = std::exp(aux) / (b * a);
174 double integral2 = math::integrate([this](double t) { return h(t); }, 0, x);
175 return integral1 + integral2;
176}
177
178template <typename RealType>
179double PlanckRand<RealType>::S(const RealType &x) const
180{
181 if (x <= 0)
182 return 1.0;
184 double upper = math::integrate([this](double t) { return f(t); }, x, INFINITY);
185 return (upper < 0.5) ? upper : 1.0 - F(x);
186}
187
188template <typename RealType>
189template <std::uniform_random_bit_generator G>
191{
192 return gammaVariable(g) / Z(g);
193}
194
195template <typename RealType>
196void PlanckRand<RealType>::sample(detail::EngineRef g, std::span<RealType> outputData) const
197{
198 gammaVariable.Sample(g, outputData);
199 for (RealType &var : outputData)
200 var /= Z(g);
201}
202
203template <typename RealType>
204long double PlanckRand<RealType>::Mean() const
205{
206 double y = (a + 1) / b;
207 y *= math::riemannZeta(a + 2);
208 return y / Z.GetZetaFunction();
209}
210
211template <typename RealType>
213{
214 long double secondMoment = (a + 1) * (a + 2);
215 secondMoment /= (b * b);
216 secondMoment *= math::riemannZeta(a + 3);
217 secondMoment /= Z.GetZetaFunction();
218 return secondMoment;
219}
220
221template <typename RealType>
223{
224 long double mean = Mean();
225 return SecondMoment() - mean * mean;
226}
227
228template <typename RealType>
230{
231 if (a <= 1)
232 return 0.0;
233 double y = -a * std::exp(-a);
234 y = math::W0Lambert(y);
235 return (y + a) / b;
236}
237
238template <typename RealType>
240{
241 long double thirdMoment = (a + 3) * (a + 2) * (a + 1);
242 thirdMoment /= (b * b * b);
243 thirdMoment *= math::riemannZeta(a + 4);
244 thirdMoment /= Z.GetZetaFunction();
245 return thirdMoment;
246}
247
248template <typename RealType>
250{
251 long double mean = Mean();
252 long double secondMoment = SecondMoment();
253 long double thirdMoment = ThirdMoment();
254 long double meanSq = mean * mean;
255 long double variance = secondMoment - meanSq;
256 long double numerator = thirdMoment - 3 * mean * variance - mean * meanSq;
257 long double denominator = std::pow(variance, 1.5);
258 return numerator / denominator;
259}
260
261template <typename RealType>
263{
264 long double fourthMoment = (a + 4) * (a + 3) * (a + 2) * (a + 1);
265 long double bSq = b * b;
266 fourthMoment /= (bSq * bSq);
267 fourthMoment *= math::riemannZeta(a + 5);
268 fourthMoment /= Z.GetZetaFunction();
269 return fourthMoment;
270}
271
272template <typename RealType>
274{
275 long double mean = Mean();
276 long double secondMoment = SecondMoment();
277 long double thirdMoment = ThirdMoment();
278 long double fourthMoment = FourthMoment();
279 long double meanSq = mean * mean;
280 long double variance = secondMoment - meanSq;
281 long double numerator = fourthMoment - 4 * thirdMoment * mean + 6 * secondMoment * meanSq - 3 * meanSq * meanSq;
282 long double denominator = variance * variance;
283 return numerator / denominator - 3.0;
284}
285
286template <typename RealType>
287std::complex<double> PlanckRand<RealType>::CFImpl(double t) const
288{
289 if (a >= 1)
291
298 double re1 = math::integrate([this, t](double x) { return std::cos(t * x) * h(x); }, 0.0, 1.0);
299
300 double re2 = this->ExpectedValue([t](double x) { return std::cos(t * x); }, 1.0, INFINITY);
301
302 double re3 = t * math::integrate(
303 [this, t](double x) {
304 if (x <= 0.0)
305 return 0.0;
306 return std::sin(t * x) * std::pow(x, a);
307 },
308 0.0, 1.0);
309
310 re3 += std::cos(t);
311 re3 *= std::exp(pdfCoef) / (b * a);
312
313 double im = this->ExpectedValue([t](double x) { return std::sin(t * x); }, 0.0, INFINITY);
314
315 double re = re1 + re2 + re3;
316 return std::complex<double>(re, im);
317}
318
319} // namespace randlib
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
The GammaRand class Gamma distribution.
Definition continuous/gamma.hpp:295
The PlanckRand class Planck distribution.
Definition planck.hpp:27
std::string Name() const override
Definition planck.hpp:91
double S(const RealType &x) const override
Definition planck.hpp:179
PlanckRand(double shape=1, double scale=1)
Definition planck.hpp:85
RealType operator()(G &g) const
Definition planck.hpp:190
long double SecondMoment() const override
Definition planck.hpp:212
RealType MinValue() const override
Definition planck.hpp:44
Support SupportType() const override
Definition planck.hpp:43
long double Skewness() const override
Definition planck.hpp:249
double GetShape() const noexcept
Definition planck.hpp:48
long double ExcessKurtosis() const override
Definition planck.hpp:273
double F(const RealType &x) const override
Definition planck.hpp:162
long double Mean() const override
Definition planck.hpp:204
double f(const RealType &x) const override
Definition planck.hpp:130
long double ThirdMoment() const override
Definition planck.hpp:239
long double FourthMoment() const override
Definition planck.hpp:262
long double Variance() const override
Definition planck.hpp:222
RealType MaxValue() const override
Definition planck.hpp:45
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition planck.hpp:229
void SetParameters(double shape, double scale)
Definition planck.hpp:97
double logf(const RealType &x) const override
Definition planck.hpp:146
double GetScale() const noexcept
Definition planck.hpp:49
void Sample(std::span< T > outputData) const
Fills the output with variates drawn with the engine of this object.
Definition distribution.hpp:139
virtual std::complex< double > CFImpl(double t) const
Definition univariate.hpp:365
The ZetaRand class Zeta distribution.
Definition zeta.hpp:21
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
constexpr long double ln3
Definition constants.hpp:19
constexpr long double lnpi
Definition constants.hpp:21
Real W0Lambert(Real x, std::type_identity_t< Real > epsilon=Real{1e-11})
Definition functions.hpp:689
Real riemannZeta(Real s)
Definition special_functions.hpp:340
Real integrate(const F &f, std::type_identity_t< Real > a, std::type_identity_t< Real > b, std::type_identity_t< Real > tolerance=1e-11, int maxSubdivisions=512)
Global adaptive Gauss-Kronrod quadrature (QUADPACK QAG).
Definition quadrature.hpp:226
Real logexpm1l(Real x)
Definition functions.hpp:266
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)