RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
inverse_gaussian.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
17template <typename RealType>
18class InverseGaussianRand final : public ContinuousDistribution<RealType>
19{
20 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
21
22 double mu = 1;
23 double lambda = 1;
25 double cdfCoef = randlib::consts::e * randlib::consts::e;
26public:
27 InverseGaussianRand(double mean = 1, double shape = 1);
28
29 [[nodiscard]] std::string Name() const override;
30 [[nodiscard]] Support SupportType() const override { return Support::RightSemiFinite; }
31 [[nodiscard]] RealType MinValue() const override { return 0; }
32 [[nodiscard]] RealType MaxValue() const override { return INFINITY; }
33
34 void SetParameters(double mean, double shape);
35 [[nodiscard]] inline double GetMean() const noexcept { return mu; }
36 [[nodiscard]] inline double GetShape() const noexcept { return lambda; }
37
38 [[nodiscard]] double f(const RealType &x) const override;
39 [[nodiscard]] double logf(const RealType &x) const override;
40 [[nodiscard]] double F(const RealType &x) const override;
41 [[nodiscard]] double S(const RealType &x) const override;
42 template <std::uniform_random_bit_generator G>
43 [[nodiscard]] RealType operator()(G &g) const;
44
45 [[nodiscard]] long double Mean() const override;
46 [[nodiscard]] long double Variance() const override;
47 [[nodiscard]] RealType Mode() const override;
48 [[nodiscard]] long double Skewness() const override;
49 [[nodiscard]] long double ExcessKurtosis() const override;
50
51private:
52 std::complex<double> CFImpl(double t) const override;
53};
54
55} // namespace randlib
56
59
60namespace randlib
61{
62
63template <typename RealType>
65{
66 SetParameters(mean, shape);
67}
68
69template <typename RealType>
71{
72 return "Inverse-Gaussian(" + this->toStringWithPrecision(GetMean()) + ", " +
73 this->toStringWithPrecision(GetShape()) + ")";
74}
75
76template <typename RealType>
77void InverseGaussianRand<RealType>::SetParameters(double mean, double shape)
78{
79 if (!(mean > 0.0))
80 throw std::invalid_argument("Inverse-Gaussian distribution: mean should be positive");
81 if (!(shape > 0.0))
82 throw std::invalid_argument("Inverse-Gaussian distribution: shape should be positive");
83 mu = mean;
84 lambda = shape;
85
86 pdfCoef = 0.5 * std::log(0.5 * lambda * randlib::consts::inv_pi);
87 cdfCoef = std::exp(2 * lambda / mu);
88}
89
90template <typename RealType>
91double InverseGaussianRand<RealType>::f(const RealType &x) const
92{
93 return (x > 0.0) ? std::exp(logf(x)) : 0.0;
94}
95
96template <typename RealType>
97double InverseGaussianRand<RealType>::logf(const RealType &x) const
98{
99 if (x <= 0.0)
100 return -INFINITY;
101 double y = -1.5 * std::log(x);
102 double z = (x - mu);
103 z *= z;
104 z *= -0.5 * lambda / (x * mu * mu);
105 z += pdfCoef;
106 return y + z;
107}
108
109template <typename RealType>
110double InverseGaussianRand<RealType>::F(const RealType &x) const
111{
112 if (x <= 0.0)
113 return 0.0;
114 double b = std::sqrt(0.5 * lambda / x);
115 double a = b * x / mu;
116 if (b > a) {
120 double d = b - a;
121 return 0.5 * std::exp(-d * d) * (math::erfcx(d) + math::erfcx(a + b));
122 }
123 return 1.0 - S(x);
124}
125
126template <typename RealType>
127double InverseGaussianRand<RealType>::S(const RealType &x) const
128{
129 if (x <= 0.0)
130 return 1.0;
131 double b = std::sqrt(0.5 * lambda / x);
132 double a = b * x / mu;
133 if (a >= b) {
135 double d = a - b;
136 return 0.5 * std::exp(-d * d) * (math::erfcx(d) - math::erfcx(a + b));
137 }
138 return 1.0 - F(x);
139}
140
141template <typename RealType>
142template <std::uniform_random_bit_generator G>
144{
145 RealType X = detail::standardNormal<RealType>(g);
146 RealType U = detail::uniform01<RealType>(g);
147 X *= X;
148 RealType mupX = mu * X;
149 RealType y = 4 * lambda + mupX;
150 y = std::sqrt(y * mupX);
151 y -= mupX;
152 y *= -0.5 / lambda;
153 ++y;
154 if (U * (1 + y) > 1.0)
155 y = 1.0 / y;
156 return mu * y;
157}
158
159template <typename RealType>
161{
162 return mu;
163}
164
165template <typename RealType>
167{
168 return mu * mu * mu / lambda;
169}
170
171template <typename RealType>
172std::complex<double> InverseGaussianRand<RealType>::CFImpl(double t) const
173{
174 double im = mu * mu;
175 im *= t / lambda;
176 std::complex<double> y(1, -im - im);
177 y = 1.0 - std::sqrt(y);
178 y *= lambda / mu;
179 return std::exp(y);
180}
181
182template <typename RealType>
184{
185 RealType aux = 1.5 * mu / lambda;
186 RealType mode = 1 + aux * aux;
187 mode = std::sqrt(mode);
188 mode -= aux;
189 return mu * mode;
190}
191
192template <typename RealType>
194{
195 return 3 * std::sqrt(mu / lambda);
196}
197
198template <typename RealType>
200{
201 return 15 * mu / lambda;
202}
203
204} // namespace randlib
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
The InverseGaussianRand class Inverse Gaussian (Wald) distribution.
Definition inverse_gaussian.hpp:19
double GetMean() const noexcept
Definition inverse_gaussian.hpp:35
RealType MaxValue() const override
Definition inverse_gaussian.hpp:32
double f(const RealType &x) const override
Definition inverse_gaussian.hpp:91
double F(const RealType &x) const override
Definition inverse_gaussian.hpp:110
double logf(const RealType &x) const override
Definition inverse_gaussian.hpp:97
RealType MinValue() const override
Definition inverse_gaussian.hpp:31
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition inverse_gaussian.hpp:183
RealType operator()(G &g) const
Definition inverse_gaussian.hpp:143
double GetShape() const noexcept
Definition inverse_gaussian.hpp:36
void SetParameters(double mean, double shape)
Definition inverse_gaussian.hpp:77
double S(const RealType &x) const override
Definition inverse_gaussian.hpp:127
std::string Name() const override
Definition inverse_gaussian.hpp:70
long double Variance() const override
Definition inverse_gaussian.hpp:166
long double Skewness() const override
Definition inverse_gaussian.hpp:193
long double ExcessKurtosis() const override
Definition inverse_gaussian.hpp:199
long double Mean() const override
Definition inverse_gaussian.hpp:160
InverseGaussianRand(double mean=1, double shape=1)
Definition inverse_gaussian.hpp:64
Support SupportType() const override
Definition inverse_gaussian.hpp:30
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double inv_pi
Definition constants.hpp:24
constexpr long double sqrtpi
Definition constants.hpp:31
constexpr long double inv_sqrt2
Definition constants.hpp:28
constexpr long double e
Definition constants.hpp:15
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real erfcx(Real x)
Definition functions.hpp:525
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)