RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
skellam.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
20template <typename IntType>
21class SkellamRand final : public DiscreteDistribution<IntType>
22{
23 IntType variate(detail::EngineRef g) const override { return (*this)(g); }
24 void sample(detail::EngineRef g, std::span<IntType> outputData) const override;
25
26 double mu1 = 1;
27 double mu2 = 1;
28 double logMu1 = 0;
29 double logMu2 = 0;
30 double sqrtMu1 = 1;
31 double sqrtMu2 = 1;
32
33 PoissonRand<IntType> X{}, Y{};
34
35public:
36 SkellamRand(double rate1 = 1.0, double rate2 = 1.0);
37 [[nodiscard]] std::string Name() const override;
38 [[nodiscard]] Support SupportType() const override { return Support::Infinite; }
39 [[nodiscard]] IntType MinValue() const override { return std::numeric_limits<IntType>::lowest(); }
40 [[nodiscard]] IntType MaxValue() const override { return std::numeric_limits<IntType>::max(); }
41
42 void SetRates(double rate1, double rate2);
43 [[nodiscard]] inline double GetFirstRate() const noexcept { return mu1; }
44 [[nodiscard]] inline double GetSecondRate() const noexcept { return mu2; }
45
46 [[nodiscard]] double P(const IntType &k) const override;
47 [[nodiscard]] double logP(const IntType &k) const override;
48 [[nodiscard]] double F(const IntType &k) const override;
49 [[nodiscard]] double S(const IntType &k) const override;
50 template <std::uniform_random_bit_generator G>
51 [[nodiscard]] IntType operator()(G &g) const;
52
53 [[nodiscard]] long double Mean() const override;
54 [[nodiscard]] long double Variance() const override;
55 [[nodiscard]] IntType Median() const override;
56 [[nodiscard]] IntType Mode() const override;
57 [[nodiscard]] long double Skewness() const override;
58 [[nodiscard]] long double ExcessKurtosis() const override;
59
60private:
61 std::complex<double> CFImpl(double t) const override;
62};
63
64} // namespace randlib
65
68
69namespace randlib
70{
71
72template <typename IntType>
73SkellamRand<IntType>::SkellamRand(double rate1, double rate2)
74{
75 SetRates(rate1, rate2);
76}
77
78template <typename IntType>
79std::string SkellamRand<IntType>::Name() const
80{
81 return "Skellam(" + this->toStringWithPrecision(GetFirstRate()) + ", " +
82 this->toStringWithPrecision(GetSecondRate()) + ")";
83}
84
85template <typename IntType>
86void SkellamRand<IntType>::SetRates(double rate1, double rate2)
87{
88 if (!(rate1 > 0.0 && rate2 > 0.0))
89 throw std::invalid_argument("Skellam distribution: rates should be positive");
90
91 X.SetRate(rate1);
92 mu1 = X.GetRate();
93 logMu1 = std::log(mu1);
94 sqrtMu1 = std::sqrt(mu1);
95
96 Y.SetRate(rate2);
97 mu2 = Y.GetRate();
98 logMu2 = std::log(mu2);
99 sqrtMu2 = std::sqrt(mu2);
100}
101
102template <typename IntType>
103double SkellamRand<IntType>::P(const IntType &k) const
104{
105 return std::exp(logP(k));
106}
107
108template <typename IntType>
109double SkellamRand<IntType>::logP(const IntType &k) const
110{
111 double y = math::logBesselI(k, 2 * sqrtMu1 * sqrtMu2);
112 y += 0.5 * k * (logMu1 - logMu2);
113 y -= mu1 + mu2;
114 return y;
115}
116
117template <typename IntType>
118double SkellamRand<IntType>::F(const IntType &k) const
119{
120 return (k < 0) ? math::MarcumP(-k, mu1, mu2, sqrtMu1, sqrtMu2, logMu1, logMu2)
121 : math::MarcumQ(k + 1, mu2, mu1, sqrtMu2, sqrtMu1, logMu2, logMu1);
122}
123
124template <typename IntType>
125double SkellamRand<IntType>::S(const IntType &k) const
126{
127 return (k < 0) ? math::MarcumQ(-k, mu1, mu2, sqrtMu1, sqrtMu2, logMu1, logMu2)
128 : math::MarcumP(k + 1, mu2, mu1, sqrtMu2, sqrtMu1, logMu2, logMu1);
129}
130
131template <typename IntType>
132template <std::uniform_random_bit_generator G>
134{
135 return X(g) - Y(g);
136}
137
138template <typename IntType>
139void SkellamRand<IntType>::sample(detail::EngineRef g, std::span<IntType> outputData) const
140{
141 X.Sample(g, outputData);
142 for (IntType &var : outputData)
143 var -= Y(g);
144}
145
146template <typename IntType>
147long double SkellamRand<IntType>::Mean() const
148{
149 return mu1 - mu2;
150}
151
152template <typename IntType>
154{
155 return mu1 + mu2;
156}
157
158template <typename IntType>
160{
161 return DiscreteDistribution<IntType>::quantileImpl(0.5, mu1 - mu2);
162}
163
164template <typename IntType>
165std::complex<double> SkellamRand<IntType>::CFImpl(double t) const
166{
167 double cosT = std::cos(t), sinT = std::sin(t);
168 double x = (cosT - 1) * (mu1 + mu2);
169 double y = sinT * (mu1 - mu2);
170 std::complex<double> z(x, y);
171 return std::exp(z);
172}
173
174template <typename IntType>
179
180template <typename IntType>
182{
183 return (mu1 - mu2) / std::pow(mu1 + mu2, 1.5);
184}
185
186template <typename IntType>
188{
189 return 1.0 / (mu1 + mu2);
190}
191
192} // namespace randlib
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition discrete.hpp:152
IntType quantileImpl(double p, IntType initValue) const override
Definition discrete.hpp:175
The PoissonRand class Poisson distribution.
Definition poisson.hpp:26
void Sample(std::span< T > outputData) const
Fills the output with variates drawn with the engine of this object.
Definition distribution.hpp:139
The SkellamRand class Skellam distribution.
Definition skellam.hpp:22
double S(const IntType &k) const override
Definition skellam.hpp:125
std::string Name() const override
Definition skellam.hpp:79
double GetSecondRate() const noexcept
Definition skellam.hpp:44
double F(const IntType &k) const override
Definition skellam.hpp:118
IntType Median() const override
Definition skellam.hpp:159
double logP(const IntType &k) const override
Definition skellam.hpp:109
IntType operator()(G &g) const
Definition skellam.hpp:133
IntType MinValue() const override
Definition skellam.hpp:39
double P(const IntType &k) const override
Definition skellam.hpp:103
Support SupportType() const override
Definition skellam.hpp:38
SkellamRand(double rate1=1.0, double rate2=1.0)
Definition skellam.hpp:73
void SetRates(double rate1, double rate2)
Definition skellam.hpp:86
long double Mean() const override
Definition skellam.hpp:147
long double Variance() const override
Definition skellam.hpp:153
long double Skewness() const override
Definition skellam.hpp:181
double GetFirstRate() const noexcept
Definition skellam.hpp:43
IntType MaxValue() const override
Definition skellam.hpp:40
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition skellam.hpp:175
long double ExcessKurtosis() const override
Definition skellam.hpp:187
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
Real logBesselI(std::type_identity_t< Real > nu, Real x)
Calculates logarithm of modified Bessel function of the 1st kind.
Definition functions.hpp:577
Real MarcumP(std::type_identity_t< Real > mu, Real x, std::type_identity_t< Real > y, std::type_identity_t< Real > sqrtX, std::type_identity_t< Real > sqrtY, std::type_identity_t< Real > logX, std::type_identity_t< Real > logY)
Definition functions.hpp:1023
Real MarcumQ(std::type_identity_t< Real > mu, Real x, std::type_identity_t< Real > y, std::type_identity_t< Real > sqrtX, std::type_identity_t< Real > sqrtY, std::type_identity_t< Real > logX, std::type_identity_t< Real > logY)
Definition functions.hpp:1079
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ Infinite
(-∞, ∞)