15template <
typename RealType>
25 [[nodiscard]]
double standardized(
const RealType &x)
const {
return (x - location) / scale; }
26 [[nodiscard]]
double supportTerm(
const RealType &x)
const {
return std::fma(shape, standardized(x), 1.0); }
27 [[nodiscard]]
double supportLog(
const RealType &x)
const
29 const double product = shape * standardized(x);
30 return std::fabs(product) < 0.5 ? std::log1p(product) : std::log(supportTerm(x));
36 SetParameters(shapeParameter, scaleParameter, locationParameter);
39 void SetParameters(
double newShape,
double newScale,
double newLocation)
41 if (!std::isfinite(newShape))
42 throw std::invalid_argument(
"Generalized extreme-value distribution: shape should be finite");
43 if (!(newScale > 0) || !std::isfinite(newScale))
44 throw std::invalid_argument(
"Generalized extreme-value distribution: scale should be positive and finite");
45 if (!std::isfinite(newLocation))
46 throw std::invalid_argument(
"Generalized extreme-value distribution: location should be finite");
49 location = newLocation;
50 logScale = std::log(scale);
53 [[nodiscard]]
double GetShape() const noexcept {
return shape; }
54 [[nodiscard]]
double GetScale() const noexcept {
return scale; }
55 [[nodiscard]]
double GetLocation() const noexcept {
return location; }
57 [[nodiscard]] std::string
Name()
const override
72 [[nodiscard]] RealType
MinValue()
const override
74 return shape > 0 ?
static_cast<RealType
>(location - scale / shape) : -std::numeric_limits<RealType>::infinity();
77 [[nodiscard]] RealType
MaxValue()
const override
79 return shape < 0 ? static_cast<RealType>(location - scale / shape) : std::numeric_limits<RealType>::infinity();
82 [[nodiscard]]
double logf(
const RealType &x)
const override
85 const double z = standardized(x);
86 return -logScale - z - std::exp(-z);
88 const double support = supportTerm(x);
90 if (support == 0 && shape < 0) {
98 const double logSupport = supportLog(x);
99 return -logScale - (1 / shape + 1) * logSupport - std::exp(-logSupport / shape);
102 [[nodiscard]]
double f(
const RealType &x)
const override {
return std::exp(
logf(x)); }
104 [[nodiscard]]
double F(
const RealType &x)
const override
110 const double exponent = shape == 0 ? std::exp(-standardized(x)) : std::exp(-supportLog(x) / shape);
111 return std::exp(-exponent);
114 [[nodiscard]]
double S(
const RealType &x)
const override
120 const double exponent = shape == 0 ? std::exp(-standardized(x)) : std::exp(-supportLog(x) / shape);
121 return -std::expm1(-exponent);
124 template <std::uniform_random_bit_generator G>
129 return static_cast<RealType
>(location - scale * std::log(exponential));
130 return static_cast<RealType
>(location + scale * std::expm1(-shape * std::log(exponential)) / shape);
133 [[nodiscard]]
long double Mean()
const override
139 if (std::fabs(shape) < SMALL_SHAPE)
140 return location + scale * standardMean();
141 return location + scale * (std::tgamma(1 - shape) - 1) / shape;
144 [[nodiscard]]
long double Variance()
const override
150 return value * value / 6;
152 if (std::fabs(shape) < SMALL_SHAPE) {
154 const long double scaled = std::exp(2 * logGammaOneMinusShape()) * std::expm1(logGammaExcess(2)) / shape;
155 return scale * scale * scaled / shape;
157 const long double first = std::tgamma(1 - shape);
158 return scale * scale * (std::tgamma(1 - 2 * shape) - first * first) / (shape * shape);
161 [[nodiscard]] RealType
Median()
const override {
return quantileImpl(0.5); }
163 [[nodiscard]] RealType
Mode()
const override
168 return static_cast<RealType
>(location);
169 return static_cast<RealType
>(location + scale * std::expm1(-shape * std::log1p(shape)) / shape);
172 [[nodiscard]]
long double Skewness()
const override
174 if (shape >= 1.0 / 3)
180 if (std::fabs(shape) < SMALL_SHAPE) {
181 const long double mean = standardMean();
182 return standardCentralMoment(3, mean) / std::pow(standardCentralMoment(2, mean), 1.5L);
184 const long double first = std::tgamma(1 - shape);
185 const long double second = std::tgamma(1 - 2 * shape);
186 const long double third = std::tgamma(1 - 3 * shape);
187 const long double variance = second - first * first;
188 const long double centralThird = third - 3 * first * second + 2 * first * first * first;
189 return centralThird / std::pow(variance, 1.5L) * (shape > 0 ? 1 : -1);
198 if (std::fabs(shape) < SMALL_SHAPE) {
199 const long double mean = standardMean();
200 const long double variance = standardCentralMoment(2, mean);
201 return standardCentralMoment(4, mean) / (variance * variance) - 3;
203 const long double first = std::tgamma(1 - shape);
204 const long double second = std::tgamma(1 - 2 * shape);
205 const long double third = std::tgamma(1 - 3 * shape);
206 const long double fourth = std::tgamma(1 - 4 * shape);
207 const long double variance = second - first * first;
208 const long double centralFourth =
209 fourth - 4 * first * third + 6 * first * first * second - 3 * first * first * first * first;
210 return centralFourth / (variance * variance) - 3;
217 static constexpr double SMALL_SHAPE = 0.05;
220 [[nodiscard]]
long double zetaPowerSeries(
int m,
int subtracted)
const
222 long double sum = 0, power = shape;
223 for (
int k = 2; k < 64; ++k) {
225 const long double term =
math::riemannZeta(
static_cast<long double>(k)) * power *
226 (std::pow(
static_cast<long double>(m), k) - subtracted) / k;
228 if (std::fabs(term) <= std::numeric_limits<long double>::epsilon() * std::fabs(sum))
235 [[nodiscard]]
long double logGammaExcess(
int m)
const {
return zetaPowerSeries(m, m); }
238 [[nodiscard]]
long double logGammaOneMinusShape()
const
244 [[nodiscard]]
long double standardMean()
const {
return std::expm1(logGammaOneMinusShape()) / shape; }
247 [[nodiscard]]
long double standardCentralMoment(
int order,
long double mean)
const
249 const double xi = shape, center =
static_cast<double>(mean);
251 [xi, center, order](
double logExponential) {
252 const double density = std::exp(logExponential - std::exp(logExponential));
253 return density == 0 ? 0.0 : std::pow(std::expm1(-xi * logExponential) / xi - center, order) * density;
255 -INFINITY, INFINITY);
258 RealType quantileImpl(
double p)
const override
260 const double logExponential = std::log(-std::log(p));
262 return static_cast<RealType
>(location - scale * logExponential);
263 return static_cast<RealType
>(location + scale * std::expm1(-shape * logExponential) / shape);
266 RealType quantileImpl1m(
double p)
const override
268 const double logExponential = std::log(-std::log1p(-p));
270 return static_cast<RealType
>(location - scale * logExponential);
271 return static_cast<RealType
>(location + scale * std::expm1(-shape * logExponential) / shape);
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
Definition generalized_extreme_value.hpp:17
GeneralizedExtremeValueRand(double shapeParameter=0, double scaleParameter=1, double locationParameter=0)
Definition generalized_extreme_value.hpp:34
double F(const RealType &x) const override
Definition generalized_extreme_value.hpp:104
double f(const RealType &x) const override
Definition generalized_extreme_value.hpp:102
long double Skewness() const override
Definition generalized_extreme_value.hpp:172
long double Variance() const override
Definition generalized_extreme_value.hpp:144
double GetScale() const noexcept
Definition generalized_extreme_value.hpp:54
double logf(const RealType &x) const override
Definition generalized_extreme_value.hpp:82
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition generalized_extreme_value.hpp:163
void SetParameters(double newShape, double newScale, double newLocation)
Definition generalized_extreme_value.hpp:39
long double Entropy() const
Definition generalized_extreme_value.hpp:213
double GetLocation() const noexcept
Definition generalized_extreme_value.hpp:55
RealType Median() const override
Definition generalized_extreme_value.hpp:161
RealType MinValue() const override
Definition generalized_extreme_value.hpp:72
Support SupportType() const override
Definition generalized_extreme_value.hpp:63
double S(const RealType &x) const override
Definition generalized_extreme_value.hpp:114
double GetShape() const noexcept
Definition generalized_extreme_value.hpp:53
long double Mean() const override
Definition generalized_extreme_value.hpp:133
RealType MaxValue() const override
Definition generalized_extreme_value.hpp:77
long double ExcessKurtosis() const override
Definition generalized_extreme_value.hpp:192
RealType operator()(G &g) const
Definition generalized_extreme_value.hpp:125
std::string Name() const override
Definition generalized_extreme_value.hpp:57
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
constexpr long double egamma
Definition constants.hpp:36
constexpr long double apery
Definition constants.hpp:37
constexpr long double pi
Definition constants.hpp:22
constexpr long double pi_sq
Definition constants.hpp:39
constexpr long double sqrt2
Definition constants.hpp:27
constexpr long double sqrt3
Definition constants.hpp:29
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
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
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15