17template <
typename RealType>
48 void SetParameters(
double exponent,
double skewness,
double scale = 1.0,
double location = 0.0,
double shift = 0.);
74 [[nodiscard]] RealType
MinValue()
const override;
75 [[nodiscard]] RealType
MaxValue()
const override;
84 double pdfByLevy(
double x)
const;
85 double pdfByCauchy(
double x)
const;
91 double conditionalShift(
double w)
const;
97 double lowerLogMixingVariable(
double x0)
const;
103 template <
typename Function>
104 double mixtureIntegral(
const Function &g,
double logWMin)
const;
107 [[nodiscard]]
double f(
const RealType &x)
const override;
108 [[nodiscard]]
double logf(
const RealType &x)
const override;
109 [[nodiscard]]
double F(
const RealType &x)
const override;
112 template <std::uniform_random_bit_generator G>
113 double variateForUnityExponent(
double z, G &g)
const;
114 template <std::uniform_random_bit_generator G>
115 double variateForGeneralExponent(
double z, G &g)
const;
116 template <std::uniform_random_bit_generator G>
117 double variateForOneHalfExponent(
double z, G &g)
const;
118 template <std::uniform_random_bit_generator G>
119 double variateByCauchy(
double z, G &g)
const;
122 template <std::uniform_random_bit_generator G>
123 [[nodiscard]] RealType
operator()(G &g)
const;
125 [[nodiscard]]
long double Mean()
const override;
126 [[nodiscard]]
long double Variance()
const override;
127 [[nodiscard]] RealType
Median()
const override;
128 [[nodiscard]] RealType
Mode()
const override;
129 [[nodiscard]]
long double Skewness()
const override;
151 std::complex<double>
CFImpl(
double t)
const override;
162template <
typename RealType>
167 double location = 0);
170 [[nodiscard]] std::string
Name()
const override;
173 void ChangeAsymmetry();
179 [[nodiscard]]
inline double GetLocation() const noexcept {
return this->
mu; }
192template <
typename RealType>
194 double scale,
double location,
197 SetParameters(exponent, skewness, scale, location, shift);
200template <
typename RealType>
202 double location,
double shift)
204 if (!(exponent >= 0.1 && exponent <= 2.0))
205 throw std::invalid_argument(
206 "Geometric-Stable distribution: exponent should be inside the interval [0.1, 2], but it's equal to " +
207 std::to_string(exponent));
208 if (!(std::fabs(skewness) <= 1.0))
209 throw std::invalid_argument(
210 "Geometric-Stable distribution: skewness should be inside the interval [-1, 1], but it's equal to " +
211 std::to_string(skewness));
214 alphaInv = 1.0 / alpha;
216 Z.SetExponent(alpha);
220 SetLocation(location);
224 distributionType = (mu == 0.0) ? LAPLACE : ASYMMETRIC_LAPLACE;
225 else if (alpha == 0.5)
226 distributionType = (std::fabs(beta) == 1.0) ? LEVY : ONEHALF_EXPONENT;
227 else if (alpha == 1.0)
228 distributionType = (beta == 0.0) ? CAUCHY : UNITY_EXPONENT;
230 distributionType = GENERAL;
233template <
typename RealType>
236 if (!std::isfinite(location))
237 throw std::invalid_argument(
"Geometric-Stable distribution: location should be finite");
241template <
typename RealType>
244 if (!std::isfinite(shift))
245 throw std::invalid_argument(
"Geometric-Stable distribution: shift should be finite");
249template <
typename RealType>
253 throw std::invalid_argument(
"Asymmetric-Laplace distribution: scale should be positive, but it's equal to " +
254 std::to_string(scale));
256 logGamma = std::log(gamma);
259template <
typename RealType>
262 if (!(asymmetry > 0.0))
263 throw std::invalid_argument(
264 "Asymmetric-Laplace distribution: asymmetry parameter should be positive, but it's equal to " +
265 std::to_string(asymmetry));
267 kappaInv = 1.0 / kappa;
268 kappaSq = kappa * kappa;
269 log1pKappaSq = std::log1pl(kappaSq);
270 logKappa = std::log(kappa);
273template <
typename RealType>
277 if (beta == 1 && mu >= 0)
279 if (beta == -1 && mu <= 0)
285template <
typename RealType>
288 if (alpha < 1 && beta == 1 && mu >= 0)
293template <
typename RealType>
296 if (alpha < 1 && beta == -1 && mu <= 0)
301template <
typename RealType>
304 return std::exp(logpdfLaplace(x));
307template <
typename RealType>
310 double y = x / gamma;
311 y *= (x < 0) ? kappaInv : -kappa;
312 return y - logGamma - log1pKappaSq + logKappa;
315template <
typename RealType>
318 double y = x / gamma;
321 y += 2 * logKappa - log1pKappaSq;
324 return -std::expm1l(-log1pKappaSq - kappa * y);
327template <
typename RealType>
330 double y = x / gamma;
333 y += 2 * logKappa - log1pKappaSq;
334 return -std::expm1l(y);
336 return std::exp(-log1pKappaSq - kappa * y);
339template <
typename RealType>
349 double halfSigmaInv = 0.5 / gamma;
350 double z = std::sqrt(halfSigmaInv * x);
352 return 0.5 * y / (gamma * z);
356 return std::fabs(1.0 / mu);
359 double a = x / gamma, c = mu / gamma;
368 double h = std::sqrt(1 - 2 * c);
370 double y = 2 * a / (hm1 * hm1);
371 y -= std::log(gamma * hm1 * h);
376 double sqrt2a = std::sqrt(2 * a);
379 double h = std::sqrt(1 - 2 * c);
380 double term1 =
math::sign(c) * sqrt2a / (1 - h);
381 double term2 = sqrt2a / (1 + h);
384 y /= h * gamma * sqrt2a;
390 y *= (8.0 * a + 2.0) / sqrt2a;
397 double adivc = x / mu;
399 [a, c, adivc](
double t) {
400 if (t <= 0 || t >= adivc)
402 double amct = a - c * t;
403 double integrand = 0.5 * t / amct;
406 integrand = std::exp(-integrand);
408 integrand /= amct * std::sqrt(amct);
415template <
typename RealType>
416double GeneralGeometricStableDistribution<RealType>::pdfByCauchy(
double x)
const
425 [
this, x](
double t) {
426 if (t <= 0.0 || t >= 1.0)
428 double logt = std::log(t);
429 double a = gamma * logt;
431 double b = x + mu * logt;
433 return logt / (a + b);
438template <
typename RealType>
439double GeneralGeometricStableDistribution<RealType>::conditionalShift(
double w)
const
443 double shift = mu * w;
444 if (distributionType == UNITY_EXPONENT)
449template <
typename RealType>
450double GeneralGeometricStableDistribution<RealType>::lowerLogMixingVariable(
double x0)
const
456 return std::min(-20.0, alpha * std::log(std::fabs(x0) / gamma) - 20.0);
459template <
typename RealType>
460template <
typename Function>
461double GeneralGeometricStableDistribution<RealType>::mixtureIntegral(
const Function &g,
double logWMin)
const
466 static constexpr double LOG_W_MAX = 7.0;
467 double wMin = std::exp(logWMin);
468 double head = -std::expm1(-wMin) * g(wMin);
471 double w = std::exp(u);
472 return w * std::exp(-w) * g(w);
474 logWMin, LOG_W_MAX, 1
e-13);
477template <
typename RealType>
482 if (alpha < 1 && std::fabs(beta) == 1) {
483 if (x0 < 0 && mu >= 0 && beta > 0)
485 if (x0 > 0 && mu <= 0 && beta < 0)
490 if (distributionType == LAPLACE || distributionType == ASYMMETRIC_LAPLACE)
491 return pdfLaplace(x0);
492 if (distributionType == CAUCHY)
493 return pdfByCauchy(x0);
494 if (distributionType == LEVY)
495 return pdfByLevy(x0);
501 double coef = std::tgammal(1.0 - alphaInv);
502 if (!std::isfinite(coef))
504 return Z.f(0) * coef / gamma;
508 if (distributionType != UNITY_EXPONENT) {
509 return mixtureIntegral(
510 [
this, x0](
double w) {
511 double tau = 1.0 / (gamma * std::pow(w, alphaInv));
512 return tau * Z.f(tau * x0 - tau * conditionalShift(w));
514 lowerLogMixingVariable(x0));
520 [
this, x0](
double z) {
521 if (z <= 0 || z >= 1)
523 double logz = std::log(z);
524 double tau = 1.0 / (gamma * std::pow(-logz, alphaInv));
525 double par = tau * (x0 - conditionalShift(-logz));
526 return tau * Z.f(par);
531template <
typename RealType>
534 return (distributionType == LAPLACE || distributionType == ASYMMETRIC_LAPLACE) ? logpdfLaplace(x - m)
538template <
typename RealType>
542 if (distributionType == LAPLACE || distributionType == ASYMMETRIC_LAPLACE)
543 return cdfLaplace(x0);
544 if (distributionType != UNITY_EXPONENT) {
545 return mixtureIntegral(
546 [
this, x0](
double w) {
return Z.F((x0 - conditionalShift(w)) / (gamma * std::pow(w, alphaInv))); },
547 lowerLogMixingVariable(x0));
552 [
this, x0](
double z) {
554 return (x0 == 0.0) ? Z.F(-mu / gamma) : ((x0 < 0.0) ? 0.0 : 1.0);
556 return Z.F(-mu / gamma);
557 double denominator = 1.0 - z;
558 double t = z / denominator;
559 double par = x0 - conditionalShift(t);
560 par /= std::pow(t, alphaInv) * gamma;
561 double y = std::exp(-t) * Z.F(par);
562 return y / (denominator * denominator);
567template <
typename RealType>
568template <std::uniform_random_bit_generator G>
578template <
typename RealType>
579template <std::uniform_random_bit_generator G>
580double GeneralGeometricStableDistribution<RealType>::variateForGeneralExponent(
double z, G &g)
const
583 double X = std::pow(W, alphaInv) * gamma * z;
587template <
typename RealType>
588template <std::uniform_random_bit_generator G>
589double GeneralGeometricStableDistribution<RealType>::variateForOneHalfExponent(
double z, G &g)
const
592 double X = mu + gamma * W * z;
596template <
typename RealType>
597template <std::uniform_random_bit_generator G>
598double GeneralGeometricStableDistribution<RealType>::variateByCauchy(
double z, G &g)
const
601 double X = mu + gamma * z;
605template <
typename RealType>
606template <std::uniform_random_bit_generator G>
609 switch (distributionType) {
612 case ASYMMETRIC_LAPLACE:
614 case ONEHALF_EXPONENT:
616 return variateForOneHalfExponent(Z(g), g);
618 return variateByCauchy(Z(g), g);
620 return variateForUnityExponent(Z(g), g);
622 return variateForGeneralExponent(Z(g), g);
624 throw std::runtime_error(
"Shifted Geometric Stable distribution: invalid distribution type");
628template <
typename RealType>
631 switch (distributionType) {
633 for (RealType &var : outputData)
634 var = gamma *
LaplaceRand<RealType>::StandardVariate(g);
636 case ASYMMETRIC_LAPLACE: {
637 for (RealType &var : outputData)
638 var = gamma * AsymmetricLaplaceRand<RealType>::StandardVariate(kappa, g);
640 case ONEHALF_EXPONENT:
643 for (RealType &var : outputData)
644 var = variateForOneHalfExponent(var, g);
647 Z.Sample(g, outputData);
648 for (RealType &var : outputData)
649 var = variateByCauchy(var, g);
651 case UNITY_EXPONENT: {
652 Z.Sample(g, outputData);
653 for (RealType &var : outputData)
654 var = variateForUnityExponent(var, g);
657 Z.Sample(g, outputData);
658 for (RealType &var : outputData)
659 var = variateForGeneralExponent(var, g);
662 throw std::runtime_error(
"Shifted Geometric Stable distribution: invalid distribution type");
666template <
typename RealType>
673 return (beta == -1) ? -INFINITY : NAN;
676template <
typename RealType>
679 if (distributionType == LAPLACE || distributionType == ASYMMETRIC_LAPLACE)
680 return mu * mu + 2 * gamma * gamma;
684template <
typename RealType>
688 if (alpha != 2 && beta != 0) {
692 double re = std::pow(gamma * t, alpha);
693 std::complex<double> psi = std::complex<double>(re, re * x - mu * t);
694 return 1.0 / (1.0 + psi);
697template <
typename RealType>
700 if (distributionType == LAPLACE || distributionType == ASYMMETRIC_LAPLACE)
701 return quantileLaplace(0.5);
705template <
typename RealType>
709 if (alpha == 1 || alpha == 2)
714template <
typename RealType>
717 if (distributionType != LAPLACE && distributionType != ASYMMETRIC_LAPLACE)
719 long double k4 = kappaSq * kappaSq;
720 long double k6 = k4 * kappaSq;
721 long double z = (k4 + 1);
723 long double y = 2 * (1 - k6);
727template <
typename RealType>
730 if (distributionType != LAPLACE && distributionType != ASYMMETRIC_LAPLACE)
732 long double denominator = kappaSq + kappaInv * kappaInv;
733 denominator *= denominator;
734 return 6.0 - 12.0 / denominator;
737template <
typename RealType>
740 double tail = std::min(p, 1.0 - p);
741 double guess = (tail < 0.05) ?
stableTailQuantile(tail, upperTail != (p > 0.5), alpha, beta, gamma, mu) : NAN;
742 return this->searchQuantile(p, upperTail, guess, 0.05);
745template <
typename RealType>
748 return searchTailQuantile(p,
false);
751template <
typename RealType>
754 return searchTailQuantile(p,
true);
757template <
typename RealType>
760 if (p < kappaSq / (1 + kappaSq)) {
761 RealType q = p / kappaSq + p;
766 RealType q = (kappaSq + 1) * (1 - p);
773template <
typename RealType>
776 if (p > 1.0 / (1 + kappaSq)) {
777 RealType pm1 = p - 1.0;
778 RealType q = -pm1 / kappaSq - pm1;
783 RealType q = (kappaSq + 1) * p;
789template <
typename RealType>
796template <
typename RealType>
799 return "Geometric Stable(" + this->toStringWithPrecision(this->GetExponent()) +
", " +
800 this->toStringWithPrecision(this->GetSkewness()) +
", " + this->toStringWithPrecision(this->GetScale()) +
801 ", " + this->toStringWithPrecision(this->GetLocation()) +
")";
804template <
typename RealType>
807 if (this->distributionType != this->LAPLACE && this->distributionType != this->ASYMMETRIC_LAPLACE)
809 double gamma2 = 2 * this->gamma;
810 double asymmetry = this->mu * this->mu + gamma2 * gamma2;
811 asymmetry = std::sqrt(asymmetry) - this->mu;
813 this->SetAsymmetry(asymmetry);
816template <
typename RealType>
823template <
typename RealType>
830template <
typename RealType>
static RealType StandardVariate(double asymmetry, G &g)
Definition laplace.hpp:376
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition continuous.hpp:285
The GeneralGeometricStableDistribution class Abstract class for general interface of Asymmetric Lapla...
Definition geometric_stable.hpp:19
double gamma
scale γ
Definition geometric_stable.hpp:31
RealType searchTailQuantile(double p, bool upperTail) const
Quantile search that starts far tails from their power-law asymptote.
Definition geometric_stable.hpp:738
double logf(const RealType &x) const override
Definition geometric_stable.hpp:532
double GetLogScale() const noexcept
Definition geometric_stable.hpp:71
long double Mean() const override
Definition geometric_stable.hpp:667
RealType quantileLaplace(double p) const
Definition geometric_stable.hpp:758
RealType quantileImpl(double p) const override
Definition geometric_stable.hpp:746
double kappaInv
1 / κ
Definition geometric_stable.hpp:36
virtual ~GeneralGeometricStableDistribution()
Definition geometric_stable.hpp:45
DISTRIBUTION_TYPE distributionType
type of distribution (Laplace by default)
Definition geometric_stable.hpp:65
RealType MinValue() const override
Definition geometric_stable.hpp:286
double log1pKappaSq
log(1 + κ^2)
Definition geometric_stable.hpp:38
void SetAsymmetry(double asymmetry)
Definition geometric_stable.hpp:260
long double ExcessKurtosis() const override
Definition geometric_stable.hpp:728
double alphaInv
Definition geometric_stable.hpp:27
double cdfLaplace(double x) const
Definition geometric_stable.hpp:316
long double Variance() const override
Definition geometric_stable.hpp:677
void SetLocation(double location)
Definition geometric_stable.hpp:234
double mu
location μ
Definition geometric_stable.hpp:29
DISTRIBUTION_TYPE
Definition geometric_stable.hpp:55
@ LAPLACE
α = 2, μ = 0
Definition geometric_stable.hpp:56
@ LEVY
α = 0.5, |β| = 1
Definition geometric_stable.hpp:59
@ ONEHALF_EXPONENT
α = 0.5, |β| ≠ 1
Definition geometric_stable.hpp:61
@ CAUCHY
α = 1, β = 0
Definition geometric_stable.hpp:58
@ ASYMMETRIC_LAPLACE
α = 2, μ ≠ 0
Definition geometric_stable.hpp:57
@ UNITY_EXPONENT
α = 1, β ≠ 0
Definition geometric_stable.hpp:60
@ GENERAL
the rest
Definition geometric_stable.hpp:62
double logGamma
log(γ)
Definition geometric_stable.hpp:32
double GetExponent() const noexcept
Definition geometric_stable.hpp:68
double F(const RealType &x) const override
Definition geometric_stable.hpp:539
double m
shift m
Definition geometric_stable.hpp:30
void SetShift(double shift)
Definition geometric_stable.hpp:242
double logpdfLaplace(double x) const
Definition geometric_stable.hpp:308
RealType MaxValue() const override
Definition geometric_stable.hpp:294
double kappa
parameters for α = 2
Definition geometric_stable.hpp:35
RealType quantileImpl1m(double p) const override
Definition geometric_stable.hpp:752
void SetParameters(double exponent, double skewness, double scale=1.0, double location=0.0, double shift=0.)
Definition geometric_stable.hpp:201
long double Skewness() const override
Definition geometric_stable.hpp:715
double alpha
characteristic exponent α
Definition geometric_stable.hpp:26
double f(const RealType &x) const override
Definition geometric_stable.hpp:478
double kappaSq
κ^2
Definition geometric_stable.hpp:37
double cdfLaplaceCompl(double x) const
Definition geometric_stable.hpp:328
RealType Median() const override
Definition geometric_stable.hpp:698
RealType quantileLaplace1m(double p) const
Definition geometric_stable.hpp:774
Support SupportType() const override
Definition geometric_stable.hpp:274
std::complex< double > CFImpl(double t) const override
Definition geometric_stable.hpp:685
double pdfLaplace(double x) const
Definition geometric_stable.hpp:302
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition geometric_stable.hpp:706
void SetScale(double scale)
Definition geometric_stable.hpp:250
GeneralGeometricStableDistribution(double exponent, double skewness, double scale=1.0, double location=0.0, double shift=0.0)
log(κ)
Definition geometric_stable.hpp:193
RealType operator()(G &g) const
Definition geometric_stable.hpp:607
double beta
1/α
Definition geometric_stable.hpp:28
double GetScale() const noexcept
Definition geometric_stable.hpp:70
double GetSkewness() const noexcept
Definition geometric_stable.hpp:69
double logKappa
Definition geometric_stable.hpp:39
The GeometricStableRand class Geometric-Stable distribution.
Definition geometric_stable.hpp:164
GeometricStableRand(double exponent=2, double skewness=0, double scale=randlib::consts::sqrt2, double location=0)
Definition geometric_stable.hpp:790
std::string Name() const override
Definition geometric_stable.hpp:797
void SetScale(double scale)
Definition geometric_stable.hpp:831
void SetParameters(double exponent, double skewness)
Definition geometric_stable.hpp:817
void SetLocation(double location)
Definition geometric_stable.hpp:824
double GetLocation() const noexcept
Definition geometric_stable.hpp:179
virtual ~GeometricStableRand()
Definition geometric_stable.hpp:168
The LaplaceRand class Laplace distribution.
Definition laplace.hpp:150
static RealType StandardVariate(G &g)
Definition laplace.hpp:442
void Sample(std::span< T > outputData) const
Fills the output with variates drawn with the engine of this object.
Definition distribution.hpp:139
The StableRand class Stable distribution.
Definition stable.hpp:521
virtual RealType Median() const
Definition univariate.hpp:396
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 ln2
Definition constants.hpp:18
constexpr long double half_pi
Definition constants.hpp:23
constexpr long double sqrtpi
Definition constants.hpp:31
constexpr long double pi
Definition constants.hpp:22
constexpr long double two_inv_pi
Definition constants.hpp:25
constexpr long double inv_sqrtpi
Definition constants.hpp:33
constexpr long double sqrt2
Definition constants.hpp:27
constexpr long double e
Definition constants.hpp:15
constexpr long double sqrt2pi
Definition constants.hpp:32
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
int sign(Real x)
Definition functions.hpp:232
Real xexpxsqerfc(Real x)
xexpxsqerfc
Definition functions.hpp:504
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
double stableTailQuantile(double p, bool upperTail, double alpha, double beta, double gamma, double mu)
Quantile of the power-law tails of a stable law with α < 2: P(X > x) ~ C (1 + β) γ^α x^(-α) and P(X <...
Definition stable.hpp:49