22 const double reduced = std::remainder(0.5 * alpha, 1.0);
24 return std::copysign(1.0,
reduced);
30 if (std::fabs(value) == 1.0)
49inline double stableTailQuantile(
double p,
bool upperTail,
double alpha,
double beta,
double gamma,
double mu)
51 double weight = upperTail ? 1 + beta : 1 - beta;
52 if (alpha >= 2 || weight <= 0)
54 double C = (alpha == 1)
57 double distance = gamma * std::pow(C * weight / p, 1.0 / alpha);
58 return upperTail ? mu + distance : mu - distance;
72template <
typename RealType>
93 double alphaInv = 0.5;
97 double alpha_alpham1 = 2;
100 double locationParameter = 0;
102 static constexpr double BIG_NUMBER = 1e9;
103 static constexpr double ALMOST_TWO = 1.99999;
104 static constexpr double S0_PROBABILITY_UNITY_TOLERANCE = 1.1e-8;
105 static constexpr double S0_DIRECT_KERNEL_ALPHA_TOLERANCE = 1e-5;
106 static constexpr double S0_DIRECT_KERNEL_RANGE = 100;
107 static constexpr double S0_SAMPLING_UNITY_TOLERANCE = 1e-10;
109 enum DISTRIBUTION_TYPE
118 DISTRIBUTION_TYPE distributionType = NORMAL;
126 StableDistribution(
double exponent,
double skewness,
double scale = 1,
double location = 0,
133 [[nodiscard]] RealType
MinValue()
const override;
134 [[nodiscard]] RealType
MaxValue()
const override;
137 void parametersVerification(
double exponent,
double skewness,
double scale);
138 void setParametersForNormal();
139 void setParametersForCauchy();
140 void setParametersForLevy();
141 void setParametersForUnityExponent();
142 void setParametersForGeneralExponent();
143 static double s0LocationShift(
double exponent,
double skewness,
double scale);
146 void SetParameters(
double exponent,
double skewness,
double scale = 1,
double location = 0);
168 [[nodiscard]]
inline double GetLocation() const noexcept {
return locationParameter; }
203 double pdfLevy(RealType x)
const;
215 static double fastpdfExponentiation(
double u);
221 double pdfShortTailExpansionForUnityExponent(
double x)
const;
222 std::complex<double> unityTailIntegral(
int power,
int logarithmPower,
double distance)
const;
223 double unityTailExpansion(
double distance,
bool integrated)
const;
230 double limitCaseForIntegrandAuxForUnityExponent(
double theta,
double xAdj)
const;
236 double integrandAuxForUnityExponent(
double theta,
double xAdj)
const;
242 double integrandForUnityExponent(
double theta,
double xAdj)
const;
247 double pdfForUnityExponent(
double x)
const;
251 static double rootOfMonotone(
const std::function<
double(
double)> &u,
double a,
double b);
255 static double integrateAroundRoot(
const std::function<
double(
double)> &integrand,
256 const std::function<
double(
double)> &u,
double a,
double b,
double root);
261 double peakForUnityExponent(
double xAdj)
const;
269 double pdfShortTailExpansionForGeneralExponent(
double logX)
const;
274 double cdfShortTailExpansion(
double logX)
const;
278 double pdfAtZero()
const;
285 double pdfSeriesExpansionAtZero(
double logX,
double xiAdj,
int k)
const;
291 double pdfSeriesExpansionAtInf(
double logX,
double xiAdj)
const;
296 double pdfTaylorExpansionTailNearCauchy(
double x)
const;
302 double limitCaseForIntegrandAuxForGeneralExponent(
double theta,
double xiAdj)
const;
309 double integrandAuxForGeneralExponent(
double theta,
double xAdj,
double xiAdj)
const;
316 double integrandFoGeneralExponent(
double theta,
double xAdj,
double xiAdj)
const;
321 double pdfForGeneralExponent(
double x)
const;
322 [[nodiscard]]
bool useS0UnityLimit() const noexcept;
323 double pdfS0UnityLimit(
double x) const;
324 double cdfS0UnityLimit(
double x,
bool complement) const;
325 [[nodiscard]]
bool useS0NearUnityKernel(
double x) const noexcept;
326 double s0NearUnityPhase(
double u,
double standardizedX) const;
327 double pdfS0NearUnity(
double x) const;
328 double cdfS0NearUnity(
double x,
bool complement) const;
331 [[nodiscard]]
double f(const RealType &x) const override;
332 [[nodiscard]]
double logf(const RealType &x) const override;
359 double cdfLevy(RealType x) const;
371 static
double fastcdfExponentiation(
double u);
376 static
double fastccdfExponentiation(
double u);
381 double cdfAtZero(
double xiAdj) const;
387 double cdfForUnityExponent(
double x,
bool complement) const;
394 double cdfSeriesExpansionAtZero(
double logX,
double xiAdj,
int k) const;
400 double cdfSeriesExpansionAtInf(
double logX,
double xiAdj) const;
406 double cdfIntegralRepresentation(
double logX,
double xiAdj,
bool complement) const;
411 double cdfForGeneralExponent(
double x) const;
416 double ccdfForGeneralExponent(
double x) const;
419 [[nodiscard]]
double F(const RealType &x) const override;
420 [[nodiscard]]
double S(const RealType &x) const override;
426 template <std::uniform_random_bit_generator G>
427 double variateForUnityExponent(G &g) const;
428 template <std::uniform_random_bit_generator G>
429 double variateForS0UnityLimit(G &g) const;
433 template <std::uniform_random_bit_generator G>
434 double variateForGeneralExponent(G &g) const;
438 template <std::uniform_random_bit_generator G>
439 double variateForExponentEqualOneHalf(G &g) const;
442 template <std::uniform_random_bit_generator G>
443 [[nodiscard]] RealType operator()(G &g) const;
445 [[nodiscard]]
long double Mean() const override;
446 [[nodiscard]]
long double Variance() const override;
447 [[nodiscard]] RealType
Median() const override;
448 [[nodiscard]] RealType
Mode() const override;
449 [[nodiscard]]
long double Skewness() const override;
490 RealType searchTailQuantile(
double p,
bool upperTail) const;
491 RealType quantileImpl(
double p) const override;
492 RealType quantileImpl1m(
double p) const override;
499 std::complex<
double>
cfNormal(
double t) const;
504 std::complex<
double>
cfCauchy(
double t) const;
509 std::complex<
double>
cfLevy(
double t) const;
512 std::complex<
double> CFImpl(
double t) const override;
519template <typename RealType>
525 StableRand(
double exponent = 2,
double skewness = 0,
double scale = 1,
double location = 0,
527 :
StableDistribution<RealType>(exponent, skewness, scale, location, selectedParameterization)
530 [[nodiscard]] std::string
Name()
const override;
532 void SetExponent(
double exponent);
533 void SetSkewness(
double skewness);
545template <
typename RealType>
550 [[nodiscard]] std::string Name()
const override;
562template <
typename RealType>
567 [[nodiscard]] std::string Name()
const override;
581template <
typename RealType>
584 : parameterization(selectedParameterization)
589template <
typename RealType>
601template <
typename RealType>
604 return (alpha < 1 && beta == 1) ? mu : -INFINITY;
607template <
typename RealType>
610 return (alpha < 1 && beta == -1) ? mu : INFINITY;
613template <
typename RealType>
616 if (!(exponent > 0.0 && exponent <= 2.0))
617 throw std::invalid_argument(
618 "Stable distribution: exponent should be in the interval (0, 2], but it's equal to " +
619 std::to_string(exponent));
620 if (!(std::fabs(skewness) <= 1.0))
621 throw std::invalid_argument(
622 "Stable distribution: skewness should be in the interval [-1, 1], but it's equal to " +
623 std::to_string(skewness));
625 throw std::invalid_argument(
"Stable distribution: scale should be positive, but it's equal to " +
626 std::to_string(scale));
629template <
typename RealType>
630void StableDistribution<RealType>::setParametersForNormal()
632 distributionType = NORMAL;
636template <
typename RealType>
637void StableDistribution<RealType>::setParametersForCauchy()
639 distributionType = CAUCHY;
643template <
typename RealType>
644void StableDistribution<RealType>::setParametersForLevy()
646 distributionType = LEVY;
650template <
typename RealType>
651void StableDistribution<RealType>::setParametersForUnityExponent()
653 distributionType = UNITY_EXPONENT;
654 pdfCoef = 0.5 / (gamma * std::fabs(beta));
660template <
typename RealType>
661void StableDistribution<RealType>::setParametersForGeneralExponent()
663 distributionType = GENERAL;
666 const double zetaSquared = zeta * zeta;
668 : 0.5 * alphaInv * std::log1pl(zetaSquared);
671 zeta = omega = xi = 0.0;
677 if (alpha <= ALMOST_TWO) {
678 seriesZeroParams.first = std::round(std::min(alpha * alpha * 40 + 1, 10.0));
679 seriesZeroParams.second =
682 seriesZeroParams.first = 85;
687template <
typename RealType>
688double StableDistribution<RealType>::s0LocationShift(
double exponent,
double skewness,
double scale)
690 if (skewness == 0.0 || exponent == 2.0)
697template <
typename RealType>
700 if (!std::isfinite(location))
701 throw std::invalid_argument(
"Stable distribution: location should be finite");
702 parametersVerification(exponent, skewness, scale);
704 alphaInv = 1.0 / alpha;
706 locationParameter = location;
707 mu = locationParameter -
708 ((parameterization == Parameterization::S0) ? s0LocationShift(exponent, skewness, scale) : 0.0);
710 logGamma = std::log(gamma);
711 alpha_alpham1 = alpha / (alpha - 1.0);
715 return setParametersForNormal();
717 return (beta == 0.0) ? setParametersForCauchy() : setParametersForUnityExponent();
718 if (alpha == 0.5 && std::fabs(beta) == 1.0)
719 return setParametersForLevy();
720 return setParametersForGeneralExponent();
723template <
typename RealType>
726 SetParameters(alpha, beta, gamma, location);
729template <
typename RealType>
732 SetParameters(alpha, beta, scale, GetLocation());
735template <
typename RealType>
738 parameterization = value;
739 locationParameter = mu + ((parameterization == Parameterization::S0) ? s0LocationShift(alpha, beta, gamma) : 0.0);
742template <
typename RealType>
745 return std::exp(logpdfNormal(x));
748template <
typename RealType>
758template <
typename RealType>
768template <
typename RealType>
773 double xSq = x0 * x0;
774 return pdfCoef - std::log1pl(xSq);
777template <
typename RealType>
780 return (x <= mu) ? 0.0 : std::exp(logpdfLevy(x));
783template <
typename RealType>
789 double y = gamma / x0;
790 y += 3 * std::log(x0);
795template <
typename RealType>
799 return (u < -700) ? std::exp(u) : std::exp(u - std::exp(u));
802template <
typename RealType>
803double StableDistribution<RealType>::pdfShortTailExpansionForUnityExponent(
double x)
const
807 double xm1 = x - 1.0;
808 double y = 0.5 * xm1 - std::exp(xm1);
813template <
typename RealType>
814std::complex<double> StableDistribution<RealType>::unityTailIntegral(
int power,
int logarithmPower,
815 double distance)
const
817 const double absoluteDistance = std::fabs(distance);
818 const double direction = std::copysign(1.0, distance);
820 const std::complex<double> imaginary(0, 1);
821 const std::complex<double> integral = std::tgamma(power + 1.0) * std::pow(absoluteDistance, -power - 1.0) *
822 std::exp(imaginary * direction * halfPi * (power + 1.0));
823 if (logarithmPower == 0)
826 std::array<std::complex<double>, 9> derivatives{};
827 derivatives[1] =
math::digamma(power + 1.0) - std::log(absoluteDistance) + imaginary * direction * halfPi;
828 for (
int order = 2; order <= logarithmPower; ++order) {
830 for (
int term = 1; term <= power; ++term)
831 harmonic += std::pow(
static_cast<double>(term), -order);
832 const double factorial = std::tgamma(
static_cast<double>(order));
833 const double sign = (order % 2 == 0) ? 1.0 : -1.0;
837 std::array<std::complex<double>, 9> bell{};
839 for (
int order = 1; order <= logarithmPower; ++order) {
840 double combination = 1;
841 for (
int part = 1; part <= order; ++part) {
842 bell[order] += combination * bell[order - part] * derivatives[part];
843 combination *=
static_cast<double>(order - part) / part;
846 return integral * bell[logarithmPower];
849template <
typename RealType>
850double StableDistribution<RealType>::unityTailExpansion(
double distance,
bool integrated)
const
852 static constexpr int ORDER = 8;
853 const std::complex<double> imaginary(0, 1);
855 std::complex<double> sum = 0;
856 for (
int totalOrder = 1; totalOrder <= ORDER; ++totalOrder) {
857 for (
int logarithmPower = 0; logarithmPower <= totalOrder; ++logarithmPower) {
858 const int exponentialPower = totalOrder - logarithmPower;
859 const std::complex<double> coefficient =
860 std::pow(-gamma, exponentialPower) / std::tgamma(exponentialPower + 1.0) *
861 std::pow(imaginary * logarithmicCoefficient, logarithmPower) / std::tgamma(logarithmPower + 1.0);
862 const int power = totalOrder - (integrated ? 1 : 0);
863 sum += coefficient * unityTailIntegral(power, logarithmPower, distance);
868 return std::max(0.0, sum.real() * inversePi);
869 return std::clamp(-std::copysign(1.0, distance) * sum.imag() * inversePi, 0.0, 1.0);
872template <
typename RealType>
873double StableDistribution<RealType>::limitCaseForIntegrandAuxForUnityExponent(
double theta,
double xAdj)
const
878 return (beta == -1) ? xAdj - 1.0 : -BIG_NUMBER;
882 return (beta == 1) ? xAdj - 1.0 : -BIG_NUMBER;
885template <
typename RealType>
886double StableDistribution<RealType>::integrandAuxForUnityExponent(
double theta,
double xAdj)
const
889 return limitCaseForIntegrandAuxForUnityExponent(theta, xAdj);
893 double u = std::log(thetaAdj);
894 u += thetaAdj * std::sin(theta) / beta;
895 return std::isfinite(u) ? u + xAdj : limitCaseForIntegrandAuxForUnityExponent(theta, xAdj);
898template <
typename RealType>
899double StableDistribution<RealType>::integrandForUnityExponent(
double theta,
double xAdj)
const
903 double u = integrandAuxForUnityExponent(theta, xAdj);
904 return fastpdfExponentiation(u);
907template <
typename RealType>
908double StableDistribution<RealType>::rootOfMonotone(
const std::function<
double(
double)> &u,
double a,
double b)
911 bool increasing = u(b) > u(a);
912 for (
int i = 0; i < 200; ++i) {
913 double middle = 0.5 * (a + b);
914 if (!(middle > a && middle < b))
916 bool belowRoot = (u(middle) < 0) == increasing;
917 (belowRoot ? a : b) = middle;
919 return 0.5 * (a + b);
922template <
typename RealType>
923double StableDistribution<RealType>::integrateAroundRoot(
const std::function<
double(
double)> &integrand,
924 const std::function<
double(
double)> &u,
double a,
double b,
931 double h = 1
e-7 * std::max(std::min(root - a, b - root), 1e-300);
932 double slope = (u(root + h) - u(root - h)) / (2 * h);
933 double width = (std::isfinite(slope) && slope != 0.0) ? 1.0 / std::fabs(slope) : b - a;
934 std::vector<double> points = {a, root, b};
935 for (
double scale : {1
e-3, 1
e-2, 1
e-1, 1.0, 10.0, 100.0, 1000.0}) {
936 points.push_back(root - scale * width);
937 points.push_back(root + scale * width);
939 std::sort(points.begin(), points.end());
940 double sum = 0.0, left = a;
941 for (
double point : points) {
942 if (point <= left || point > b)
950template <
typename RealType>
951double StableDistribution<RealType>::peakForUnityExponent(
double xAdj)
const
953 return rootOfMonotone([
this, xAdj](
double theta) {
return integrandAuxForUnityExponent(theta, xAdj); },
957template <
typename RealType>
958double StableDistribution<RealType>::pdfForUnityExponent(
double x)
const
960 if (std::fabs(x - mu) >= 100 * gamma)
961 return unityTailExpansion(x - mu,
false);
962 double xSt = (x - mu) / gamma;
966 double theta0 = peakForUnityExponent(xAdj);
967 auto integrand = [
this, xAdj](
double theta) {
return integrandForUnityExponent(theta, xAdj); };
968 auto u = [
this, xAdj](
double theta) {
return integrandAuxForUnityExponent(theta, xAdj); };
972template <
typename RealType>
973double StableDistribution<RealType>::pdfShortTailExpansionForGeneralExponent(
double logX)
const
975 double logAlpha = std::log(alpha);
976 double log1mAlpha = (alpha < 1) ? std::log1pl(-alpha) : std::log(alpha - 1);
977 double temp = logX - logAlpha;
978 double y = std::exp(alpha_alpham1 * temp);
979 y *= -std::fabs(1.0 - alpha);
980 double z = (1.0 - 0.5 * alpha) / (alpha - 1) * temp;
982 return std::exp(y + z);
985template <
typename RealType>
986double StableDistribution<RealType>::cdfShortTailExpansion(
double logX)
const
990 double logU = alpha / (alpha - 1.0) * (logX - std::log(alpha));
991 double u = std::exp(logU);
992 double y = -(1.0 - alpha) * u -
997template <
typename RealType>
998double StableDistribution<RealType>::pdfAtZero()
const
1002 y0 = std::tgammal(alphaInv);
1004 y0 = std::lgammal(alphaInv) - omega;
1005 y0 = std::exp(y0) * std::cos(xi);
1010template <
typename RealType>
1011double StableDistribution<RealType>::pdfSeriesExpansionAtZero(
double logX,
double xiAdj,
int k)
const
1015 double y0 = pdfAtZero();
1019 for (
int n = 1; n <= k; ++n) {
1021 double term = std::lgammal((n2 + 1) / alpha);
1024 term = std::exp(term);
1025 sum += (n & 1) ? -term : term;
1030 for (
int n = 1; n <= k; ++n) {
1032 double term = std::lgammal(np1 * alphaInv);
1035 term = std::exp(term - omega);
1036 term *= std::sin(np1 * rhoPi_alpha);
1037 sum += (n & 1) ? -term : term;
1043template <
typename RealType>
1044double StableDistribution<RealType>::pdfSeriesExpansionAtInf(
double logX,
double xiAdj)
const
1046 static constexpr int k = 10;
1050 for (
int n = 1; n <= k; ++n) {
1051 double aux = n * alpha + 1.0;
1052 double term = std::lgammal(aux);
1055 term = std::exp(term - omega);
1056 term *= std::sin(rhoPi * n);
1057 sum += (n & 1) ? term : -term;
1062template <
typename RealType>
1063double StableDistribution<RealType>::pdfTaylorExpansionTailNearCauchy(
double x)
const
1066 double y = 1.0 + xSq;
1070 double logY = std::log1pl(xSq);
1071 double alpham1 = alpha - 1.0;
1078 static constexpr long double M_PI_SQ_6 = 1.64493406684822643647l;
1080 double f_aa1 = M_PI_SQ_6;
1081 f_aa1 += temp * temp;
1082 f_aa1 -= 1.0 + z * z;
1083 f_aa1 *= xSq * xSq - 6.0 * xSq + 1.0;
1084 double f_aa2 = 0.5 + temp;
1086 f_aa2 *= 8 * x * (xSq - 1.0);
1087 double f_aa3 = (1.0 - 3 * xSq) * temp;
1090 double f_aa = f_aa1 + f_aa2 + f_aa3;
1091 f_aa /= std::pow(y, 3);
1094 static constexpr int gammaTable[] = {1, 2, 6};
1099 static constexpr long double gammaSecDerTable[] = {0.82368066085287938958l, 2.49292999190269305794l,
1100 11.1699273161019477314l};
1105 static constexpr long double digammaDerTable[] = {M_PI_SQ_6 - 1.0, M_PI_SQ_6 - 1.25, M_PI_SQ_6 - 49.0 / 36};
1107 static constexpr long double digammaSecDerTable[] = {-0.40411380631918857080l, -0.15411380631918857080l,
1108 -0.08003973224511449673l};
1110 double gTable[] = {0, 0, 0};
1111 for (
int i = 0; i < 3; ++i) {
1112 double g_11 = 0.25 * gammaTable[i] * logY * logY;
1113 g_11 -= gammaDerTable[i] * logY;
1114 g_11 += gammaSecDerTable[i];
1115 double aux = digammaTable[i] - 0.5 * logY;
1117 double zip2 = z * (i + 2);
1118 double cosZNu = std::cos(zip2), zSinZNu = z * std::sin(zip2);
1121 double g_1 = g_11 * g_12;
1122 double g_21 = -gammaTable[i] * logY + 2 * gammaDerTable[i];
1123 double g_22 = -zSinZNu * aux;
1124 g_22 -= zSq * cosZNu;
1125 g_22 += cosZNu * digammaDerTable[i];
1126 double g_2 = g_21 * g_22;
1127 double g_3 = -zSq * cosZNu * aux;
1128 g_3 -= 2 * zSinZNu * digammaDerTable[i];
1129 g_3 += zSq * zSinZNu;
1130 g_3 += cosZNu * digammaSecDerTable[i];
1131 g_3 *= gammaTable[i];
1132 double g = g_1 + g_2 + g_3;
1133 g *= std::pow(y, -0.5 * i - 1);
1136 double f_aaa = -gTable[0] + 3 * gTable[1] - gTable[2];
1138 double tail = f_a * alpham1;
1139 tail += 0.5 * f_aa * alpham1 * alpham1;
1140 tail += std::pow(alpham1, 3) * f_aaa / 6.0;
1145template <
typename RealType>
1146double StableDistribution<RealType>::limitCaseForIntegrandAuxForGeneralExponent(
double theta,
double xiAdj)
const
1150 return alpha < 1 ? -BIG_NUMBER : BIG_NUMBER;
1151 return alpha < 1 ? BIG_NUMBER : -BIG_NUMBER;
1154template <
typename RealType>
1155double StableDistribution<RealType>::integrandAuxForGeneralExponent(
double theta,
double xAdj,
double xiAdj)
const
1159 if (theta >= halfPi && alpha > 1.0 && std::fabs(beta) == 1.0 && xiAdj > 0.0)
1160 return xAdj + std::log(alpha - 1.0) - alpha_alpham1 * std::log(alpha);
1161 if (std::fabs(theta) >= halfPi || theta <= -xiAdj)
1162 return limitCaseForIntegrandAuxForGeneralExponent(theta, xiAdj);
1163 double thetaAdj = alpha * (theta + xiAdj);
1164 double sinThetaAdj = std::sin(thetaAdj);
1165 double y = std::log(std::cos(theta));
1166 y -= alpha * std::log(sinThetaAdj);
1168 y += std::log(std::cos(thetaAdj - theta));
1170 return std::isfinite(y) ? y : limitCaseForIntegrandAuxForGeneralExponent(theta, xiAdj);
1173template <
typename RealType>
1174double StableDistribution<RealType>::integrandFoGeneralExponent(
double theta,
double xAdj,
double xiAdj)
const
1178 if (theta <= -xiAdj)
1180 double u = integrandAuxForGeneralExponent(theta, xAdj, xiAdj);
1181 return fastpdfExponentiation(u);
1184template <
typename RealType>
1185double StableDistribution<RealType>::pdfForGeneralExponent(
double x)
const
1188 double xSt = (x - mu) / gamma;
1189 double absXSt = xSt;
1193 if (alpha < 1 && beta == -1)
1196 if (alpha < 1 && beta == 1)
1203 if (beta == 0.0 && std::fabs(alpha - 1.0) < 0.01)
1204 return pdfCauchy(x) + pdfTaylorExpansionTailNearCauchy(absXSt) / gamma;
1208 return pdfAtZero() / gamma;
1210 double logAbsX = std::log(absXSt) - omega;
1213 if (logAbsX < seriesZeroParams.second) {
1214 if (alpha < 1 && std::fabs(beta) == 1)
1215 return pdfShortTailExpansionForGeneralExponent(logAbsX);
1216 return pdfSeriesExpansionAtZero(logAbsX, xiAdj, seriesZeroParams.first) / gamma;
1220 if (logAbsX > pdftailBound && alpha <= ALMOST_TWO) {
1222 double skewnessTowardsX = (xSt > 0) ? beta : -beta;
1223 if (alpha > 1 && skewnessTowardsX == -1)
1224 return pdfShortTailExpansionForGeneralExponent(logAbsX);
1225 return pdfSeriesExpansionAtInf(logAbsX, xiAdj) / gamma;
1228 double xAdj = alpha_alpham1 * logAbsX;
1231 auto u = [
this, xAdj, xiAdj](
double theta) {
return integrandAuxForGeneralExponent(theta, xAdj, xiAdj); };
1232 auto integrand = [
this, xAdj, xiAdj](
double theta) {
return integrandFoGeneralExponent(theta, xAdj, xiAdj); };
1235 double res = pdfCoef * integral / absXSt;
1238 if (alpha <= ALMOST_TWO)
1243 double alphap1 = alpha + 1.0;
1244 double tail = std::lgammal(alphap1);
1245 tail -= alphap1 * logAbsX;
1246 tail = std::exp(tail);
1247 tail *= (1.0 - 0.5 * alpha) / gamma;
1248 return std::max(tail, res);
1251template <
typename RealType>
1252bool StableDistribution<RealType>::useS0UnityLimit() const noexcept
1254 return parameterization == Parameterization::S0 && alpha != 1.0 && beta != 0.0 &&
1255 std::fabs(alpha - 1.0) <= S0_PROBABILITY_UNITY_TOLERANCE;
1258template <
typename RealType>
1259double StableDistribution<RealType>::pdfS0UnityLimit(
double x)
const
1262 if (std::fabs(x - unityMu) >= 100 * gamma)
1263 return unityTailExpansion(x - unityMu,
false);
1264 const double standardizedX = (x - unityMu) / gamma;
1267 const double theta0 = peakForUnityExponent(xAdjusted);
1268 const auto integrand = [
this, xAdjusted](
double theta) {
return integrandForUnityExponent(theta, xAdjusted); };
1269 const auto auxiliary = [
this, xAdjusted](
double theta) {
return integrandAuxForUnityExponent(theta, xAdjusted); };
1270 const double coefficient = 0.5 / (gamma * std::fabs(beta));
1271 return coefficient *
1275template <
typename RealType>
1276double StableDistribution<RealType>::cdfS0UnityLimit(
double x,
bool complement)
const
1279 if (std::fabs(x - unityMu) >= 100 * gamma) {
1280 const double tail = unityTailExpansion(x - unityMu,
true);
1281 return complement == (x < unityMu) ? 1.0 - tail : tail;
1283 const double standardizedX = (x - unityMu) / gamma;
1286 const bool useComplement = complement == (beta > 0);
1287 const auto integrand = [
this, xAdjusted, useComplement](
double theta) {
1288 const double value = integrandAuxForUnityExponent(theta, xAdjusted);
1289 return useComplement ? fastccdfExponentiation(value) : fastcdfExponentiation(value);
1291 const double theta0 = peakForUnityExponent(xAdjusted);
1292 const auto auxiliary = [
this, xAdjusted](
double theta) {
return integrandAuxForUnityExponent(theta, xAdjusted); };
1297template <
typename RealType>
1298bool StableDistribution<RealType>::useS0NearUnityKernel(
double x)
const noexcept
1300 const double standardizedX = (x - locationParameter) / gamma;
1301 return parameterization == Parameterization::S0 && alpha != 1.0 && beta != 0.0 &&
1302 std::fabs(alpha - 1.0) < S0_DIRECT_KERNEL_ALPHA_TOLERANCE &&
1303 std::fabs(standardizedX) <= S0_DIRECT_KERNEL_RANGE;
1306template <
typename RealType>
1307double StableDistribution<RealType>::s0NearUnityPhase(
double u,
double standardizedX)
const
1309 const double epsilon = alpha - 1.0;
1310 const double difference = std::expm1(epsilon * std::log(u));
1312 return skewPhase - standardizedX * u;
1315template <
typename RealType>
1316double StableDistribution<RealType>::pdfS0NearUnity(
double x)
const
1318 const double standardizedX = (x - locationParameter) / gamma;
1319 const double cutoff = std::pow(36.0, 1.0 / alpha);
1321 [
this, standardizedX](
double u) {
1322 const double attenuation = std::exp(-std::pow(u, alpha));
1323 return attenuation * std::cos(s0NearUnityPhase(u, standardizedX));
1325 0.0, cutoff, 2
e-13);
1329template <
typename RealType>
1330double StableDistribution<RealType>::cdfS0NearUnity(
double x,
bool complement)
const
1332 const double standardizedX = (x - locationParameter) / gamma;
1333 const double cutoff = std::pow(36.0, 1.0 / alpha);
1335 [
this, standardizedX](
double u) {
1336 const double attenuation = std::exp(-std::pow(u, alpha));
1337 return attenuation * std::sin(s0NearUnityPhase(u, standardizedX)) / u;
1339 0.0, cutoff, 2
e-13);
1341 return std::clamp(complement ? 0.5 + correction : 0.5 - correction, 0.0, 1.0);
1344template <
typename RealType>
1347 if (useS0UnityLimit())
1348 return pdfS0UnityLimit(x);
1349 if (useS0NearUnityKernel(x))
1350 return pdfS0NearUnity(x);
1351 switch (distributionType) {
1353 return pdfNormal(x);
1355 return pdfCauchy(x);
1357 return (beta > 0) ? pdfLevy(x) : pdfLevy(2 * mu - x);
1358 case UNITY_EXPONENT:
1359 return pdfForUnityExponent(x);
1361 return pdfForGeneralExponent(x);
1363 throw std::runtime_error(
"Stable distribution: invalid distribution type");
1367template <
typename RealType>
1370 if (useS0UnityLimit())
1371 return std::log(pdfS0UnityLimit(x));
1372 if (useS0NearUnityKernel(x))
1373 return std::log(pdfS0NearUnity(x));
1374 switch (distributionType) {
1376 return logpdfNormal(x);
1378 return logpdfCauchy(x);
1380 return (beta > 0) ? logpdfLevy(x) : logpdfLevy(2 * mu - x);
1381 case UNITY_EXPONENT:
1382 return std::log(pdfForUnityExponent(x));
1384 return std::log(pdfForGeneralExponent(x));
1386 throw std::runtime_error(
"Stable distribution: invalid distribution type");
1390template <
typename RealType>
1395 return 0.5 * std::erfc(y);
1398template <
typename RealType>
1403 return 0.5 * std::erfc(y);
1406template <
typename RealType>
1415template <
typename RealType>
1423template <
typename RealType>
1432 return std::erfc(y);
1435template <
typename RealType>
1447template <
typename RealType>
1451 return std::exp(-std::exp(u));
1454template <
typename RealType>
1455double StableDistribution<RealType>::fastccdfExponentiation(
double u)
1457 return (u > 5.0) ? 1.0 : -std::expm1(-std::exp(u));
1460template <
typename RealType>
1461double StableDistribution<RealType>::cdfAtZero(
double xiAdj)
const
1466template <
typename RealType>
1467double StableDistribution<RealType>::cdfForUnityExponent(
double x,
bool complement)
const
1472 if (std::fabs(x - mu) >= 100 * gamma) {
1473 const double tail = unityTailExpansion(x - mu,
true);
1474 return complement == (x < mu) ? 1.0 - tail : tail;
1476 double xSt = (x - mu) / gamma;
1478 bool useComplement = complement == (beta > 0);
1479 auto integrand = [
this, xAdj, useComplement](
double theta) {
1480 double u = integrandAuxForUnityExponent(theta, xAdj);
1481 return useComplement ? fastccdfExponentiation(u) : fastcdfExponentiation(u);
1483 double theta0 = peakForUnityExponent(xAdj);
1484 auto u = [
this, xAdj](
double theta) {
return integrandAuxForUnityExponent(theta, xAdj); };
1489template <
typename RealType>
1490double StableDistribution<RealType>::cdfSeriesExpansionAtZero(
double logX,
double xiAdj,
int k)
const
1494 double y0 = cdfAtZero(xiAdj);
1498 for (
int m = 0; m <= k; ++m) {
1499 int m2p1 = 2 * m + 1;
1500 double term = std::lgammal(m2p1 * alphaInv);
1501 term += m2p1 * logX;
1503 term = std::exp(term);
1504 sum += (m & 1) ? -term : term;
1509 for (
int n = 1; n <= k; ++n) {
1510 double term = std::lgammal(n * alphaInv);
1513 term = std::exp(term);
1514 term *= std::sin(n * rhoPi_alpha);
1515 sum += (n & 1) ? term : -term;
1521template <
typename RealType>
1522double StableDistribution<RealType>::cdfSeriesExpansionAtInf(
double logX,
double xiAdj)
const
1524 static constexpr int k = 10;
1528 for (
int n = 1; n <= k; ++n) {
1529 double aux = n * alpha;
1530 double term = std::lgammal(aux);
1533 term = std::exp(term);
1534 term *= std::sin(rhoPi * n);
1535 sum += (n & 1) ? term : -term;
1540template <
typename RealType>
1541double StableDistribution<RealType>::cdfIntegralRepresentation(
double logX,
double xiAdj,
bool complement)
const
1544 double xAdj = alpha_alpham1 * logX;
1545 auto u = [
this, xAdj, xiAdj](
double theta) {
return integrandAuxForGeneralExponent(theta, xAdj, xiAdj); };
1546 auto integrand = [&u, complement](
double theta) {
1547 return complement ? fastccdfExponentiation(u(theta)) : fastcdfExponentiation(u(theta));
1554template <
typename RealType>
1555double StableDistribution<RealType>::cdfForGeneralExponent(
double x)
const
1557 double xSt = (x - mu) / gamma;
1560 if (alpha < 1 && std::fabs(beta) == 1)
1561 return (beta > 0) ? 0.0 : 1.0;
1562 return cdfAtZero(xi);
1566 return 1.0 - ccdfForGeneralExponent(x);
1570 double logAbsX = std::log(xSt) - omega;
1571 if (logAbsX > cdftailBound)
1572 return 1.0 - cdfSeriesExpansionAtInf(logAbsX, xi);
1573 if (logAbsX < seriesZeroParams.second)
1574 return (beta == 1.0) ? cdfShortTailExpansion(logAbsX)
1575 : cdfSeriesExpansionAtZero(logAbsX, xi, seriesZeroParams.first);
1576 double atZero = (beta == 1.0) ? 0.0 : cdfAtZero(xi);
1577 return atZero + cdfIntegralRepresentation(logAbsX, xi,
false);
1580 double logAbsX = std::log(-xSt) - omega;
1581 if (logAbsX < seriesZeroParams.second) {
1582 if (alpha < 1.0 && beta == -1.0)
1583 return 1.0 - cdfShortTailExpansion(logAbsX);
1584 return 1.0 - cdfSeriesExpansionAtZero(logAbsX, -xi, seriesZeroParams.first);
1586 if (logAbsX > cdftailBound)
1587 return cdfSeriesExpansionAtInf(logAbsX, -xi);
1589 return cdfIntegralRepresentation(logAbsX, -xi,
false);
1590 return (beta == 1.0) ? 0.0 : cdfIntegralRepresentation(logAbsX, -xi,
true);
1593template <
typename RealType>
1594double StableDistribution<RealType>::ccdfForGeneralExponent(
double x)
const
1596 double xSt = (x - mu) / gamma;
1598 return 1.0 - cdfForGeneralExponent(x);
1599 double logAbsX = std::log(xSt) - omega;
1601 if (logAbsX < seriesZeroParams.second) {
1602 if (alpha < 1.0 && beta == 1.0)
1603 return 1.0 - cdfShortTailExpansion(logAbsX);
1604 if (alpha < 1.0 && beta == -1.0)
1605 return cdfShortTailExpansion(logAbsX);
1606 return 1.0 - cdfSeriesExpansionAtZero(logAbsX, xi, seriesZeroParams.first);
1609 if (logAbsX > cdftailBound)
1610 return cdfSeriesExpansionAtInf(logAbsX, xi);
1612 return cdfIntegralRepresentation(logAbsX, xi,
false);
1613 return (beta == -1.0) ? 0.0 : cdfIntegralRepresentation(logAbsX, xi,
true);
1616template <
typename RealType>
1619 if (useS0UnityLimit())
1620 return cdfS0UnityLimit(x,
false);
1621 if (useS0NearUnityKernel(x))
1622 return cdfS0NearUnity(x,
false);
1623 switch (distributionType) {
1625 return cdfNormal(x);
1627 return cdfCauchy(x);
1629 return (beta > 0) ? cdfLevy(x) : cdfLevyCompl(2 * mu - x);
1630 case UNITY_EXPONENT:
1631 return cdfForUnityExponent(x,
false);
1633 return cdfForGeneralExponent(x);
1635 throw std::runtime_error(
"Stable distribution: invalid distribution type");
1639template <
typename RealType>
1642 if (useS0UnityLimit())
1643 return cdfS0UnityLimit(x,
true);
1644 if (useS0NearUnityKernel(x))
1645 return cdfS0NearUnity(x,
true);
1646 switch (distributionType) {
1648 return cdfNormalCompl(x);
1650 return cdfCauchyCompl(x);
1652 return (beta > 0) ? cdfLevyCompl(x) : cdfLevy(2 * mu - x);
1653 case UNITY_EXPONENT:
1654 return cdfForUnityExponent(x,
true);
1656 return ccdfForGeneralExponent(x);
1658 throw std::runtime_error(
"Stable distribution: invalid distribution type");
1662template <
typename RealType>
1663template <std::uniform_random_bit_generator G>
1669 RealType Y = W * std::cos(U) / pi_2pBetaU;
1670 RealType X = std::log(Y);
1673 X += pi_2pBetaU * std::tan(U);
1675 return mu + gamma * X;
1678template <
typename RealType>
1679template <std::uniform_random_bit_generator G>
1680double StableDistribution<RealType>::variateForS0UnityLimit(G &g)
const
1685 const RealType logRatio = std::log(w * std::cos(u) / angle);
1686 const RealType standardized =
1689 return locationParameter + gamma * standardized;
1692template <
typename RealType>
1693template <std::uniform_random_bit_generator G>
1694double StableDistribution<RealType>::variateForGeneralExponent(G &g)
const
1698 RealType alphaUpxi = alpha * (U + xi);
1699 RealType X = std::sin(alphaUpxi);
1700 RealType W_adj = W / std::cos(U - alphaUpxi);
1702 RealType R = omega - alphaInv * std::log(W_adj * std::cos(U));
1704 return mu + gamma * X;
1707template <
typename RealType>
1708template <std::uniform_random_bit_generator G>
1709double StableDistribution<RealType>::variateForExponentEqualOneHalf(G &g)
const
1713 RealType temp1 = (1.0 + beta) / Z1, temp2 = (1.0 - beta) / Z2;
1714 RealType var = temp1 - temp2;
1715 var *= temp1 + temp2;
1717 return mu + gamma * var;
1720template <
typename RealType>
1721template <std::uniform_random_bit_generator G>
1724 if (parameterization == Parameterization::S0 && alpha != 1.0 &&
1725 std::fabs(alpha - 1.0) < S0_SAMPLING_UNITY_TOLERANCE)
1726 return variateForS0UnityLimit(g);
1727 switch (distributionType) {
1734 case UNITY_EXPONENT:
1735 return variateForUnityExponent(g);
1737 return (alpha == 0.5) ? variateForExponentEqualOneHalf(g) : variateForGeneralExponent(g);
1739 throw std::runtime_error(
"Stable distribution: invalid distribution type");
1743template <
typename RealType>
1746 if (parameterization == Parameterization::S0 && alpha != 1.0 &&
1747 std::fabs(alpha - 1.0) < S0_SAMPLING_UNITY_TOLERANCE) {
1748 for (RealType &var : outputData)
1749 var = variateForS0UnityLimit(g);
1752 switch (distributionType) {
1755 for (RealType &var : outputData)
1756 var = mu + stdev * detail::standardNormal<RealType>(g);
1759 for (RealType &var : outputData)
1760 var = mu + gamma * CauchyRand<RealType>::StandardVariate(g);
1764 for (RealType &var : outputData)
1765 var = mu + gamma * LevyRand<RealType>::StandardVariate(g);
1767 for (RealType &var : outputData)
1768 var = mu - gamma * LevyRand<RealType>::StandardVariate(g);
1771 case UNITY_EXPONENT: {
1772 for (RealType &var : outputData)
1773 var = variateForUnityExponent(g);
1777 for (RealType &var : outputData)
1778 var = variateForExponentEqualOneHalf(g);
1780 for (RealType &var : outputData)
1781 var = variateForGeneralExponent(g);
1789template <
typename RealType>
1796 return (beta == -1) ? -INFINITY : NAN;
1799template <
typename RealType>
1802 return (distributionType == NORMAL) ? 2 * gamma * gamma : INFINITY;
1805template <
typename RealType>
1809 if (beta == 0 || distributionType == NORMAL)
1811 if (distributionType == LEVY)
1812 return mu + beta * gamma / 3.0;
1816template <
typename RealType>
1820 if (beta == 0 || distributionType == NORMAL)
1825template <
typename RealType>
1828 return (distributionType == NORMAL) ? 0 : NAN;
1831template <
typename RealType>
1834 return (distributionType == NORMAL) ? 0 : NAN;
1837template <
typename RealType>
1843template <
typename RealType>
1849template <
typename RealType>
1855template <
typename RealType>
1861template <
typename RealType>
1865 return mu + 0.5 * gamma / (y * y);
1868template <
typename RealType>
1872 return mu + 0.5 * gamma / (y * y);
1875template <
typename RealType>
1878 double tail = std::min(p, 1.0 - p);
1880 (tail < 0.05) ?
stableTailQuantile(tail, upperTail != (p > 0.5), alpha, beta, gamma, GetLocation()) : NAN;
1881 return this->searchQuantile(p, upperTail, guess, 0.05);
1884template <
typename RealType>
1885RealType StableDistribution<RealType>::quantileImpl(
double p)
const
1887 switch (distributionType) {
1889 return quantileNormal(p);
1891 return quantileCauchy(p);
1893 return (beta > 0) ? quantileLevy(p) : 2 * mu - quantileLevy1m(p);
1895 return searchTailQuantile(p,
false);
1899template <
typename RealType>
1900RealType StableDistribution<RealType>::quantileImpl1m(
double p)
const
1902 switch (distributionType) {
1904 return quantileNormal1m(p);
1906 return quantileCauchy1m(p);
1908 return (beta > 0) ? quantileLevy1m(p) : 2 * mu - quantileLevy(p);
1910 return searchTailQuantile(p,
true);
1914template <
typename RealType>
1917 double gammaT = gamma * t;
1918 std::complex<double> y(-gammaT * gammaT, mu * t);
1922template <
typename RealType>
1925 std::complex<double> y(-gamma * t, mu * t);
1929template <
typename RealType>
1932 std::complex<double> y(0.0, -2 * gamma * t);
1934 y += std::complex<double>(0.0, mu * t);
1938template <
typename RealType>
1941 if (parameterization == Parameterization::S0) {
1942 const double scaledT = gamma * t;
1943 const double attenuation = std::pow(scaledT, alpha);
1944 double phase = locationParameter * t;
1948 else if (alpha != 2.0)
1949 phase -= beta * scaledT * std::expm1((alpha - 1.0) * std::log(scaledT)) /
1952 return std::exp(std::complex<double>(-attenuation, phase));
1955 switch (distributionType) {
1961 std::complex<double> phi = cfLevy(t);
1962 return (beta > 0) ? phi : std::conj(phi);
1964 case UNITY_EXPONENT:
1970 double re = std::pow(gamma * t, alpha);
1971 std::complex<double> psi = std::complex<double>(re, re * x - mu * t);
1972 return std::exp(-psi);
1974template <
typename RealType>
1977 std::string name =
"Stable(" + this->toStringWithPrecision(this->GetExponent()) +
", " +
1978 this->toStringWithPrecision(this->GetSkewness()) +
", " +
1979 this->toStringWithPrecision(this->GetScale()) +
", " +
1980 this->toStringWithPrecision(this->GetLocation());
1981 if (this->GetParameterization() == Parameterization::S0)
1986template <
typename RealType>
1989 this->SetParameters(exponent, this->GetSkewness(), this->GetScale(), this->GetLocation());
1992template <
typename RealType>
1995 this->SetParameters(this->GetExponent(), skewness, this->GetScale(), this->GetLocation());
1997template <
typename RealType>
2000 return "Holtsmark(" + this->toStringWithPrecision(this->GetScale()) +
", " +
2001 this->toStringWithPrecision(this->GetLocation()) +
")";
2003template <
typename RealType>
2006 return "Landau(" + this->toStringWithPrecision(this->GetScale()) +
", " +
2007 this->toStringWithPrecision(this->GetLocation()) +
")";
static RealType StandardVariate(G &g)
Definition cauchy.hpp:101
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 HoltsmarkRand class Holtsmark distribution.
Definition stable.hpp:547
std::string Name() const override
Definition stable.hpp:1998
HoltsmarkRand(double scale=1, double location=0)
Definition stable.hpp:549
The LandauRand class Landau distribution.
Definition stable.hpp:564
LandauRand(double scale=1, double location=0)
Definition stable.hpp:566
std::string Name() const override
Definition stable.hpp:2004
static RealType StandardVariate(G &g)
Definition levy.hpp:115
virtual std::string Name() const =0
The StableDistribution class Abstract class for Stable distribution.
Definition stable.hpp:74
double cdfLevy(RealType x) const
Definition stable.hpp:1424
double gamma
scale γ
Definition stable.hpp:89
double logpdfCauchy(RealType x) const
Definition stable.hpp:769
double cdfNormal(RealType x) const
Definition stable.hpp:1391
RealType operator()(G &g) const
Definition stable.hpp:1722
double logpdfLevy(RealType x) const
Definition stable.hpp:784
double S(const RealType &x) const override
Definition stable.hpp:1640
RealType MinValue() const override
Definition stable.hpp:602
long double Skewness() const override
Definition stable.hpp:1826
void SetParameterization(Parameterization value) noexcept
Definition stable.hpp:736
void SetLocation(double location)
Definition stable.hpp:724
double GetLogScale() const noexcept
Definition stable.hpp:176
double logGamma
log(γ)
Definition stable.hpp:90
RealType Median() const override
Definition stable.hpp:1817
double GetScale() const noexcept
Definition stable.hpp:164
RealType quantileLevy(double p) const
Definition stable.hpp:1862
double f(const RealType &x) const override
Definition stable.hpp:1345
long double Variance() const override
Definition stable.hpp:1800
RealType quantileNormal1m(double p) const
Definition stable.hpp:1844
double GetExponent() const noexcept
Definition stable.hpp:156
double pdfCoef
hashed coefficient for faster pdf calculations
Definition stable.hpp:121
StableDistribution(double exponent, double skewness, double scale=1, double location=0, Parameterization selectedParameterization=Parameterization::S1)
Definition stable.hpp:582
double pdfCauchy(RealType x) const
Definition stable.hpp:759
RealType quantileCauchy(double p) const
Definition stable.hpp:1850
std::complex< double > cfNormal(double t) const
Definition stable.hpp:1915
double F(const RealType &x) const override
Definition stable.hpp:1617
std::complex< double > cfCauchy(double t) const
Definition stable.hpp:1923
RealType quantileLevy1m(double p) const
Definition stable.hpp:1869
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition stable.hpp:1806
double cdfNormalCompl(RealType x) const
Definition stable.hpp:1399
RealType quantileCauchy1m(double p) const
Definition stable.hpp:1856
double cdfLevyCompl(RealType x) const
Definition stable.hpp:1436
RealType quantileNormal(double p) const
Definition stable.hpp:1838
void SetScale(double scale)
Definition stable.hpp:730
Support SupportType() const override
Definition stable.hpp:590
void SetParameters(double exponent, double skewness, double scale=1, double location=0)
Definition stable.hpp:698
Parameterization
Nolan parameterization used for the public location parameter.
Definition stable.hpp:81
@ S1
classical parameterization used by RandLib before v2.1
@ S0
continuous in all four parameters, including at alpha = 1
double GetLocation() const noexcept
Definition stable.hpp:168
virtual ~StableDistribution()
Definition stable.hpp:130
double logf(const RealType &x) const override
Definition stable.hpp:1368
double pdfLevy(RealType x) const
Definition stable.hpp:778
double pdfNormal(RealType x) const
Definition stable.hpp:743
long double Mean() const override
Definition stable.hpp:1790
RealType MaxValue() const override
Definition stable.hpp:608
double pdftailBound
boundary k such that for |x| > k we can use pdf tail approximation
Definition stable.hpp:123
double cdfCauchy(RealType x) const
Definition stable.hpp:1407
double GetSkewness() const noexcept
Definition stable.hpp:160
double cdfCauchyCompl(RealType x) const
Definition stable.hpp:1416
double cdftailBound
boundary k such that for |x| > k we can use cdf tail approximation
Definition stable.hpp:124
double alpha
characteristic exponent α
Definition stable.hpp:86
Parameterization GetParameterization() const noexcept
Definition stable.hpp:172
double logpdfNormal(RealType x) const
Definition stable.hpp:749
double beta
skewness β
Definition stable.hpp:87
long double ExcessKurtosis() const override
Definition stable.hpp:1832
double mu
location μ
Definition stable.hpp:88
std::complex< double > cfLevy(double t) const
Definition stable.hpp:1930
The StableRand class Stable distribution.
Definition stable.hpp:521
typename StableDistribution< RealType >::Parameterization Parameterization
Definition stable.hpp:523
std::string Name() const override
Definition stable.hpp:1975
void SetExponent(double exponent)
Definition stable.hpp:1987
void SetSkewness(double skewness)
Definition stable.hpp:1993
StableRand(double exponent=2, double skewness=0, double scale=1, double location=0, Parameterization selectedParameterization=Parameterization::S1)
Definition stable.hpp:525
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 egamma
Definition constants.hpp:36
constexpr long double half_pi
Definition constants.hpp:23
constexpr long double pi
Definition constants.hpp:22
constexpr long double two_inv_pi
Definition constants.hpp:25
constexpr long double ln10
Definition constants.hpp:20
constexpr long double sqrt2
Definition constants.hpp:27
constexpr long double ln3
Definition constants.hpp:19
constexpr long double e
Definition constants.hpp:15
constexpr long double lnpi
Definition constants.hpp:21
double stableAtan(double value)
Definition stable.hpp:28
double stableTanHalfPi(double alpha)
Definition stable.hpp:20
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real factorial(Real n)
Calculate n! using table values for small n <= 255 and built-in gamma function for large n > 255.
Definition math/gamma.hpp:307
Real erfinv(Real p)
Definition functions.hpp:464
Real digamma(Real x)
Definition math/gamma.hpp:691
Real lfact(size_t n)
Calculate log(n!) using table values for small n <= 255 and built-in lgamma function for large n > 25...
Definition math/gamma.hpp:591
int sign(Real x)
Definition functions.hpp:232
Real integrateTanhSinh(const F &f, std::type_identity_t< Real > a, std::type_identity_t< Real > b, std::type_identity_t< Real > tolerance=1e-11, int maxRefinements=12)
Double-exponential tanh-sinh quadrature on a finite interval.
Definition quadrature.hpp:266
Real atan(Real x)
Definition functions.hpp:238
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
Real erfcinv(Real p)
Definition functions.hpp:485
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
Pair< double > DoublePair
Definition fwd.hpp:39