RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
log_stable.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <complex>
5
11
12namespace randlib
13{
14
23template <typename RealType>
24class LogStableRand final : public ContinuousDistribution<RealType>
25{
26 RealType variate(detail::EngineRef g) const override { return std::exp(stable(g)); }
27
28 StableRand<RealType> stable{};
29
30 [[nodiscard]] bool hasMoments() const noexcept;
31 [[nodiscard]] long double logRawMoment(int order) const;
32
33public:
35
36 LogStableRand(double exponent = 2, double skewness = 0, double scale = 1, double location = 0,
37 Parameterization parameterization = Parameterization::S1)
38 : stable(exponent, skewness, scale, location, parameterization)
39 {
40 }
41
42 [[nodiscard]] std::string Name() const override { return "Log-" + stable.Name(); }
43 [[nodiscard]] Support SupportType() const override;
44 [[nodiscard]] RealType MinValue() const override;
45 [[nodiscard]] RealType MaxValue() const override;
46
47 void SetParameters(double exponent, double skewness, double scale = 1, double location = 0,
48 Parameterization parameterization = Parameterization::S1);
49 void SetExponent(double exponent) { stable.SetExponent(exponent); }
50 void SetSkewness(double skewness) { stable.SetSkewness(skewness); }
51 void SetScale(double scale) { stable.SetScale(scale); }
52 void SetLocation(double location) { stable.SetLocation(location); }
53 void SetParameterization(Parameterization parameterization) noexcept
54 {
55 stable.SetParameterization(parameterization);
56 }
57
58 [[nodiscard]] double GetExponent() const noexcept { return stable.GetExponent(); }
59 [[nodiscard]] double GetSkewness() const noexcept { return stable.GetSkewness(); }
60 [[nodiscard]] double GetScale() const noexcept { return stable.GetScale(); }
61 [[nodiscard]] double GetLocation() const noexcept { return stable.GetLocation(); }
62 [[nodiscard]] Parameterization GetParameterization() const noexcept { return stable.GetParameterization(); }
63
64 [[nodiscard]] double f(const RealType &x) const override;
65 [[nodiscard]] double logf(const RealType &x) const override;
66 [[nodiscard]] double F(const RealType &x) const override;
67 [[nodiscard]] double S(const RealType &x) const override;
68
69 template <std::uniform_random_bit_generator G>
70 [[nodiscard]] RealType operator()(G &g) const
71 {
72 return std::exp(stable(g));
73 }
74
75 [[nodiscard]] long double Mean() const override;
76 [[nodiscard]] long double Variance() const override;
77 [[nodiscard]] long double Skewness() const override;
78 [[nodiscard]] long double ExcessKurtosis() const override;
79 [[nodiscard]] RealType Median() const override { return std::exp(stable.Median()); }
80 [[nodiscard]] RealType Mode() const override;
81
82private:
83 RealType quantileImpl(double p) const override { return std::exp(stable.Quantile(p)); }
84 RealType quantileImpl1m(double p) const override { return std::exp(stable.Quantile1m(p)); }
85 std::complex<double> CFImpl(double t) const override;
86};
87
88template <typename RealType>
89void LogStableRand<RealType>::SetParameters(double exponent, double skewness, double scale, double location,
90 Parameterization parameterization)
91{
92 stable = StableRand<RealType>(exponent, skewness, scale, location, parameterization);
93}
94
95template <typename RealType>
97{
98 return std::isfinite(stable.MaxValue()) ? Support::Finite : Support::RightSemiFinite;
99}
100
101template <typename RealType>
103{
104 const RealType minimum = stable.MinValue();
105 return std::isfinite(minimum) ? std::exp(minimum) : RealType{0};
106}
107
108template <typename RealType>
110{
111 const RealType maximum = stable.MaxValue();
112 return std::isfinite(maximum) ? std::exp(maximum) : static_cast<RealType>(INFINITY);
113}
114
115template <typename RealType>
116double LogStableRand<RealType>::f(const RealType &x) const
117{
118 return (x >= 0) ? std::exp(logf(x)) : 0;
119}
120
121template <typename RealType>
122double LogStableRand<RealType>::logf(const RealType &x) const
123{
124 if (x < 0)
125 return -INFINITY;
126 if (x == 0)
127 return (stable.GetExponent() < 2 && stable.GetSkewness() < 1) ? INFINITY : -INFINITY;
128 const RealType logX = std::log(x);
129 return stable.logf(logX) - logX;
130}
131
132template <typename RealType>
133double LogStableRand<RealType>::F(const RealType &x) const
134{
135 return (x > 0) ? stable.F(std::log(x)) : 0;
136}
137
138template <typename RealType>
139double LogStableRand<RealType>::S(const RealType &x) const
140{
141 return (x > 0) ? stable.S(std::log(x)) : 1;
142}
143
144template <typename RealType>
145bool LogStableRand<RealType>::hasMoments() const noexcept
146{
147 return stable.GetExponent() == 2 || stable.GetSkewness() == -1;
148}
149
150template <typename RealType>
151long double LogStableRand<RealType>::logRawMoment(int order) const
152{
153 StableRand<RealType> s1 = stable;
154 s1.SetParameterization(Parameterization::S1);
155 const long double alpha = stable.GetExponent();
156 const long double momentOrder = order;
157 const long double scaleOrder = static_cast<long double>(stable.GetScale()) * momentOrder;
158 const long double location = s1.GetLocation();
159 if (alpha == 1)
160 return momentOrder * location + randlib::consts::two_inv_pi * scaleOrder * std::log(momentOrder);
161 return momentOrder * location - std::pow(scaleOrder, alpha) / std::cos(randlib::consts::half_pi * alpha);
162}
163
164template <typename RealType>
166{
167 return hasMoments() ? std::exp(logRawMoment(1)) : INFINITY;
168}
169
170template <typename RealType>
172{
173 if (!hasMoments())
174 return INFINITY;
175 const long double first = logRawMoment(1);
176 return std::exp(2 * first) * std::expm1(logRawMoment(2) - 2 * first);
177}
178
179template <typename RealType>
181{
182 if (!hasMoments())
183 return NAN;
184 if (stable.GetExponent() == 2) {
185 const long double varianceRatio = std::expm1(2 * stable.GetScale() * stable.GetScale());
186 return (varianceRatio + 3) * std::sqrt(varianceRatio);
187 }
188 const long double first = logRawMoment(1);
189 const long double second = logRawMoment(2) - 2 * first;
190 const long double third = logRawMoment(3) - 3 * first;
191 const long double variance = std::expm1(second);
192 return (std::expm1(third) - 3 * std::expm1(second)) / std::pow(variance, 1.5L);
193}
194
195template <typename RealType>
197{
198 if (!hasMoments())
199 return NAN;
200 if (stable.GetExponent() == 2) {
201 const long double logVariance = 2 * stable.GetScale() * stable.GetScale();
202 return std::expm1(4 * logVariance) + 2 * std::expm1(3 * logVariance) + 3 * std::expm1(2 * logVariance);
203 }
204 const long double first = logRawMoment(1);
205 const long double second = logRawMoment(2) - 2 * first;
206 const long double third = logRawMoment(3) - 3 * first;
207 const long double fourth = logRawMoment(4) - 4 * first;
208 const long double variance = std::expm1(second);
209 return (std::expm1(fourth) - 4 * std::expm1(third) + 6 * std::expm1(second)) / (variance * variance) - 3;
210}
211
212template <typename RealType>
214{
215 if (stable.GetExponent() < 2 && stable.GetSkewness() < 1)
216 return 0;
217 if (stable.GetExponent() == 2) {
218 StableRand<RealType> s1 = stable;
219 s1.SetParameterization(Parameterization::S1);
220 return std::exp(static_cast<RealType>(s1.GetLocation() - 2 * stable.GetScale() * stable.GetScale()));
221 }
222 RealType mode = stable.Median();
223 math::findMin<RealType>([this](RealType logValue) { return -stable.logf(logValue) + logValue; }, mode, mode);
224 return std::exp(mode);
225}
226
227template <typename RealType>
228std::complex<double> LogStableRand<RealType>::CFImpl(double t) const
229{
230 return this->integrateCharacteristicFunction(t);
231}
232
233} // namespace randlib
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
Exponential transform of a stable distribution.
Definition log_stable.hpp:25
RealType MinValue() const override
Definition log_stable.hpp:102
double F(const RealType &x) const override
Definition log_stable.hpp:133
double f(const RealType &x) const override
Definition log_stable.hpp:116
double S(const RealType &x) const override
Definition log_stable.hpp:139
double GetScale() const noexcept
Definition log_stable.hpp:60
Support SupportType() const override
Definition log_stable.hpp:96
RealType operator()(G &g) const
Definition log_stable.hpp:70
RealType MaxValue() const override
Definition log_stable.hpp:109
void SetScale(double scale)
Definition log_stable.hpp:51
double GetSkewness() const noexcept
Definition log_stable.hpp:59
Parameterization GetParameterization() const noexcept
Definition log_stable.hpp:62
typename StableRand< RealType >::Parameterization Parameterization
Definition log_stable.hpp:34
long double Variance() const override
Definition log_stable.hpp:171
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition log_stable.hpp:213
long double Mean() const override
Definition log_stable.hpp:165
void SetParameters(double exponent, double skewness, double scale=1, double location=0, Parameterization parameterization=Parameterization::S1)
Definition log_stable.hpp:89
double GetLocation() const noexcept
Definition log_stable.hpp:61
LogStableRand(double exponent=2, double skewness=0, double scale=1, double location=0, Parameterization parameterization=Parameterization::S1)
Definition log_stable.hpp:36
long double Skewness() const override
Definition log_stable.hpp:180
double GetExponent() const noexcept
Definition log_stable.hpp:58
void SetSkewness(double skewness)
Definition log_stable.hpp:50
void SetExponent(double exponent)
Definition log_stable.hpp:49
std::string Name() const override
Definition log_stable.hpp:42
double logf(const RealType &x) const override
Definition log_stable.hpp:122
RealType Median() const override
Definition log_stable.hpp:79
long double ExcessKurtosis() const override
Definition log_stable.hpp:196
void SetParameterization(Parameterization parameterization) noexcept
Definition log_stable.hpp:53
void SetLocation(double location)
Definition log_stable.hpp:52
void SetParameterization(Parameterization value) noexcept
Definition stable.hpp:736
double GetLocation() const noexcept
Definition stable.hpp:168
The StableRand class Stable distribution.
Definition stable.hpp:521
typename StableDistribution< RealType >::Parameterization Parameterization
Definition stable.hpp:523
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double half_pi
Definition constants.hpp:23
constexpr long double two_inv_pi
Definition constants.hpp:25
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)