RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
generalized_pareto.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <cmath>
8#include <limits>
9#include <string>
10
11namespace randlib
12{
13
14template <typename RealType>
15class GeneralizedParetoRand final : public ContinuousDistribution<RealType>
16{
17 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
18
19 double shape = 0;
20 double scale = 1;
21 double location = 0;
22 double logScale = 0;
23
24 [[nodiscard]] double supportLog(double z) const
25 {
26 const double product = shape * z;
27 return std::fabs(product) < 0.5 ? std::log1p(product) : std::log(std::fma(shape, z, 1.0));
28 }
29
30public:
31 GeneralizedParetoRand(double shapeParameter = 0, double scaleParameter = 1, double locationParameter = 0)
32 {
33 SetParameters(shapeParameter, scaleParameter, locationParameter);
34 }
35
36 void SetParameters(double newShape, double newScale, double newLocation)
37 {
38 if (!std::isfinite(newShape))
39 throw std::invalid_argument("Generalized Pareto distribution: shape should be finite");
40 if (!(newScale > 0) || !std::isfinite(newScale))
41 throw std::invalid_argument("Generalized Pareto distribution: scale should be positive and finite");
42 if (!std::isfinite(newLocation))
43 throw std::invalid_argument("Generalized Pareto distribution: location should be finite");
44 shape = newShape;
45 scale = newScale;
46 location = newLocation;
47 logScale = std::log(scale);
48 }
49
50 [[nodiscard]] double GetShape() const noexcept { return shape; }
51 [[nodiscard]] double GetScale() const noexcept { return scale; }
52 [[nodiscard]] double GetLocation() const noexcept { return location; }
53
54 [[nodiscard]] std::string Name() const override
55 {
56 return "GeneralizedPareto(" + this->toStringWithPrecision(shape) + ", " + this->toStringWithPrecision(scale) +
57 ", " + this->toStringWithPrecision(location) + ")";
58 }
59
60 [[nodiscard]] Support SupportType() const override
61 {
62 return shape < 0 ? Support::Finite : Support::RightSemiFinite;
63 }
64 [[nodiscard]] RealType MinValue() const override { return static_cast<RealType>(location); }
65 [[nodiscard]] RealType MaxValue() const override
66 {
67 return shape < 0 ? static_cast<RealType>(location - scale / shape) : std::numeric_limits<RealType>::infinity();
68 }
69
70 [[nodiscard]] double logf(const RealType &x) const override
71 {
72 if (x < location || (shape < 0 && x > MaxValue()))
73 return -INFINITY;
74 const double z = (x - location) / scale;
75 if (shape == 0)
76 return -logScale - z;
77 const double support = std::fma(shape, z, 1.0);
78 if (!(support > 0)) {
79 if (support == 0) {
80 if (shape < -1)
81 return INFINITY;
82 if (shape == -1)
83 return -logScale;
84 }
85 return -INFINITY;
86 }
87 return -logScale - (1 / shape + 1) * supportLog(z);
88 }
89
90 [[nodiscard]] double f(const RealType &x) const override { return std::exp(logf(x)); }
91
92 [[nodiscard]] double S(const RealType &x) const override
93 {
94 if (x <= location)
95 return 1;
96 if (shape < 0 && x >= MaxValue())
97 return 0;
98 const double z = (x - location) / scale;
99 return shape == 0 ? std::exp(-z) : std::exp(-supportLog(z) / shape);
100 }
101
102 [[nodiscard]] double F(const RealType &x) const override
103 {
104 if (x <= location)
105 return 0;
106 if (shape < 0 && x >= MaxValue())
107 return 1;
108 const double z = (x - location) / scale;
109 const double logSurvival = shape == 0 ? -z : -supportLog(z) / shape;
110 return -std::expm1(logSurvival);
111 }
112
113 template <std::uniform_random_bit_generator G>
114 [[nodiscard]] RealType operator()(G &g) const
115 {
116 const RealType exponential = detail::standardExponential<RealType>(g);
117 if (shape == 0)
118 return static_cast<RealType>(location + scale * exponential);
119 return static_cast<RealType>(location + scale * std::expm1(shape * exponential) / shape);
120 }
121
122 [[nodiscard]] long double Mean() const override { return shape < 1 ? location + scale / (1 - shape) : INFINITY; }
123
124 [[nodiscard]] long double Variance() const override
125 {
126 if (shape >= 0.5)
127 return INFINITY;
128 const long double denominator = (1 - shape) * (1 - shape) * (1 - 2 * shape);
129 return scale * scale / denominator;
130 }
131
132 [[nodiscard]] RealType Median() const override { return quantileImpl(0.5); }
133
134 [[nodiscard]] RealType Mode() const override { return shape < -1 ? MaxValue() : static_cast<RealType>(location); }
135
136 [[nodiscard]] long double Skewness() const override
137 {
138 if (shape >= 1.0 / 3)
139 return INFINITY;
140 return 2 * (1 + shape) * std::sqrt(1 - 2 * shape) / (1 - 3 * shape);
141 }
142
143 [[nodiscard]] long double ExcessKurtosis() const override
144 {
145 if (shape >= 0.25)
146 return INFINITY;
147 const long double numerator = 3 * (1 - 2 * shape) * (2 * shape * shape + shape + 3);
148 return numerator / ((1 - 3 * shape) * (1 - 4 * shape)) - 3;
149 }
150
151 [[nodiscard]] long double Entropy() const { return logScale + shape + 1; }
152
153private:
154 RealType quantileImpl(double p) const override
155 {
156 const double exponential = -std::log1p(-p);
157 if (shape == 0)
158 return static_cast<RealType>(location + scale * exponential);
159 return static_cast<RealType>(location + scale * std::expm1(shape * exponential) / shape);
160 }
161
162 RealType quantileImpl1m(double p) const override
163 {
164 const double exponential = -std::log(p);
165 if (shape == 0)
166 return static_cast<RealType>(location + scale * exponential);
167 return static_cast<RealType>(location + scale * std::expm1(shape * exponential) / shape);
168 }
169};
170
171} // namespace randlib
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
Definition generalized_pareto.hpp:16
long double Entropy() const
Definition generalized_pareto.hpp:151
RealType MinValue() const override
Definition generalized_pareto.hpp:64
double GetScale() const noexcept
Definition generalized_pareto.hpp:51
double logf(const RealType &x) const override
Definition generalized_pareto.hpp:70
double F(const RealType &x) const override
Definition generalized_pareto.hpp:102
RealType Median() const override
Definition generalized_pareto.hpp:132
double f(const RealType &x) const override
Definition generalized_pareto.hpp:90
double GetLocation() const noexcept
Definition generalized_pareto.hpp:52
RealType operator()(G &g) const
Definition generalized_pareto.hpp:114
double S(const RealType &x) const override
Definition generalized_pareto.hpp:92
long double Mean() const override
Definition generalized_pareto.hpp:122
long double Variance() const override
Definition generalized_pareto.hpp:124
Support SupportType() const override
Definition generalized_pareto.hpp:60
long double ExcessKurtosis() const override
Definition generalized_pareto.hpp:143
RealType MaxValue() const override
Definition generalized_pareto.hpp:65
void SetParameters(double newShape, double newScale, double newLocation)
Definition generalized_pareto.hpp:36
double GetShape() const noexcept
Definition generalized_pareto.hpp:50
std::string Name() const override
Definition generalized_pareto.hpp:54
long double Skewness() const override
Definition generalized_pareto.hpp:136
GeneralizedParetoRand(double shapeParameter=0, double scaleParameter=1, double locationParameter=0)
Definition generalized_pareto.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 generalized_pareto.hpp:134
std::string toStringWithPrecision(const double a_value, const int n=6) const
Definition distribution.hpp:181
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)