37template <
typename RealType>
47 double logNormalization = std::lgamma(3.0);
50 [[nodiscard]]
double standardLogDensity(
double x)
const;
51 [[nodiscard]]
double wrightSeries(
double x,
bool integrated)
const;
52 [[nodiscard]]
double directStandardCdf(
double x)
const;
53 [[nodiscard]]
double directStandardSurvival(
double x)
const;
54 [[nodiscard]]
long double standardMoment(
long double order)
const;
56 RealType quantileImpl(
double p)
const override;
57 RealType quantileImpl1m(
double p)
const override;
65 [[nodiscard]] std::string
Name()
const override;
67 [[nodiscard]] RealType
MinValue()
const override {
return static_cast<RealType
>(nu); }
68 [[nodiscard]] RealType
MaxValue()
const override {
return std::numeric_limits<RealType>::infinity(); }
70 void SetParameters(
double exponent,
double scale = 1,
double location = 0);
75 [[nodiscard]]
double GetExponent() const noexcept {
return alpha; }
76 [[nodiscard]]
double GetScale() const noexcept {
return theta; }
77 [[nodiscard]]
double GetLocation() const noexcept {
return nu; }
79 [[nodiscard]]
double f(
const RealType &x)
const override;
80 [[nodiscard]]
double logf(
const RealType &x)
const override;
81 [[nodiscard]]
double F(
const RealType &x)
const override;
82 [[nodiscard]]
double S(
const RealType &x)
const override;
84 template <std::uniform_random_bit_generator G>
88 [[nodiscard]]
long double StandardMoment(
long double order)
const {
return standardMoment(order); }
90 [[nodiscard]]
long double Moment(
int order)
const;
91 [[nodiscard]]
long double Mean()
const override {
return Moment(1); }
92 [[nodiscard]]
long double Variance()
const override;
96 [[nodiscard]]
long double Skewness()
const override;
98 [[nodiscard]] RealType
Mode()
const override;
101template <
typename RealType>
107 math::findMin<double>([
this](
double u) {
return -standardLogDensity(std::exp(u)); }, 0.0, logMode);
108 return static_cast<RealType
>(nu + theta * std::exp(logMode));
111template <
typename RealType>
114 if (!(exponent > 0 && exponent < 1) || !std::isfinite(exponent))
115 throw std::invalid_argument(
"Stable Count distribution: exponent should be in the interval (0, 1)");
116 if (!(scale > 0) || !std::isfinite(scale))
117 throw std::invalid_argument(
"Stable Count distribution: scale should be finite and positive");
118 if (!std::isfinite(location))
119 throw std::invalid_argument(
"Stable Count distribution: location should be finite");
124 logTheta = std::log(theta);
125 logNormalization = std::lgamma(1 / alpha + 1);
130template <
typename RealType>
133 return "Stable Count(" + this->toStringWithPrecision(alpha) +
", " + this->toStringWithPrecision(theta) +
", " +
134 this->toStringWithPrecision(nu) +
")";
137template <
typename RealType>
140 if (!(x > 0) || !std::isfinite(x))
143 return 0.5 * std::log(x) - 0.25 * x - std::log(4.0) - 0.5 *
static_cast<double>(
randlib::consts::lnpi);
144 const double series = wrightSeries(x,
false);
145 if (series > 0 && std::isfinite(series))
146 return std::log(series);
147 return positiveStable.logf(
static_cast<RealType
>(1 / x)) - logNormalization - std::log(x);
150template <
typename RealType>
151double StableCountRand<RealType>::wrightSeries(
double x,
bool integrated)
const
153 if (!(x > 0) || !std::isfinite(x) || alpha == 0.5)
155 const long double exponent = alpha;
156 const long double logX = std::log(
static_cast<long double>(x));
159 long double correction = 0;
160 long double largest = 0;
161 int largestIndex = 0;
163 for (
int k = 1; k <= 4096; ++k) {
164 const long double ak = exponent * k;
168 long double logMagnitude = std::lgamma(1 + ak) - std::lgamma(
static_cast<long double>(k) + 1) + ak * logX +
169 std::log(std::fabs(sine)) - logPi -
static_cast<long double>(logNormalization);
171 logMagnitude += logX - std::log(ak + 1);
172 if (logMagnitude > 15)
174 const long double magnitude = std::exp(logMagnitude);
175 const long double sign = ((k % 2 == 0) ? -1 : 1) * std::copysign(1.0L, sine);
176 const long double term = sign * magnitude;
177 const long double adjusted = term - correction;
178 const long double next = sum + adjusted;
179 correction = (next - sum) - adjusted;
181 if (magnitude > largest) {
185 }
else if (k > largestIndex + 8 &&
186 magnitude <= 8 * std::numeric_limits<long double>::epsilon() * std::max(std::fabs(sum), 1.0L)) {
188 if (smallTerms >= 24)
189 return (sum >= 0) ?
static_cast<double>(sum) : NAN;
197template <
typename RealType>
198double StableCountRand<RealType>::directStandardCdf(
double x)
const
204 const double series = wrightSeries(x,
true);
205 if (series >= 0 && series <= 1 && std::isfinite(series))
207 const double normalization = std::exp(logNormalization);
208 return std::clamp(math::integrate<double>(
209 [
this, normalization](
double t) {
210 return positiveStable.f(
static_cast<RealType
>(t)) / (normalization * t);
212 1 / x, INFINITY, 2
e-13, 1024),
216template <
typename RealType>
217double StableCountRand<RealType>::directStandardSurvival(
double x)
const
223 const double normalization = std::exp(logNormalization);
224 return std::clamp(math::integrate<double>(
225 [
this, normalization](
double t) {
226 return positiveStable.f(
static_cast<RealType
>(t)) / (normalization * t);
228 0.0, 1 / x, 2
e-13, 1024),
232template <
typename RealType>
235 const double standardized = (
static_cast<double>(x) - nu) / theta;
236 return standardLogDensity(standardized) - logTheta;
239template <
typename RealType>
242 return std::exp(logf(x));
245template <
typename RealType>
248 const double standardized = (
static_cast<double>(x) - nu) / theta;
249 if (!(standardized > 0))
252 static const double logShape = std::log(1.5);
253 static const double logGammaShape = std::lgamma(1.5);
254 return math::pgamma(1.5, 0.25 * standardized, logShape, logGammaShape);
256 const double lower = directStandardCdf(standardized);
257 return (lower <= 0.95) ? lower : 1 - directStandardSurvival(standardized);
260template <
typename RealType>
263 const double standardized = (
static_cast<double>(x) - nu) / theta;
264 if (!(standardized > 0))
267 static const double logShape = std::log(1.5);
268 static const double logGammaShape = std::lgamma(1.5);
269 return math::qgamma(1.5, 0.25 * standardized, logShape, logGammaShape);
271 const double lower = directStandardCdf(standardized);
272 return (lower <= 0.95) ? 1 - lower : directStandardSurvival(standardized);
275template <
typename RealType>
278 const long double mean = standardMoment(1);
279 const RealType guess =
280 std::isfinite(mean) ?
static_cast<RealType
>(nu + theta * mean) : std::numeric_limits<RealType>::quiet_NaN();
284template <
typename RealType>
285RealType StableCountRand<RealType>::quantileImpl1m(
double p)
const
287 const long double mean = standardMoment(1);
288 const RealType guess =
289 std::isfinite(mean) ?
static_cast<RealType
>(nu + theta * mean) : std::numeric_limits<RealType>::quiet_NaN();
293template <
typename RealType>
294template <std::uniform_random_bit_generator G>
300 const RealType standard = 4 * (exponential + 0.5 * normal * normal);
301 return static_cast<RealType
>(nu) +
static_cast<RealType
>(theta) * standard;
306template <
typename RealType>
309 for (RealType &value : outputData)
313template <
typename RealType>
314long double StableCountRand<RealType>::standardMoment(
long double order)
const
316 if (!(order > -1) || !std::isfinite(order))
317 throw std::invalid_argument(
"Stable Count distribution: standard moment order should be finite and above -1");
330 const long double inverseAlpha = 1 /
static_cast<long double>(alpha);
331 const long double logarithm =
332 std::lgamma((order + 1) * inverseAlpha) - std::lgamma(order + 1) - std::lgamma(inverseAlpha);
333 return std::exp(logarithm);
336template <
typename RealType>
340 throw std::invalid_argument(
"Stable Count distribution: raw moment order should be non-negative");
342 long double binomial = 1;
343 for (
int k = 0; k <= order; ++k) {
344 sum += binomial * std::pow(
static_cast<long double>(nu), order - k) *
345 std::pow(
static_cast<long double>(theta), k) * standardMoment(k);
346 binomial *=
static_cast<long double>(order - k) / (k + 1);
351template <
typename RealType>
354 const long double first = standardMoment(1);
355 const long double second = standardMoment(2);
356 return static_cast<long double>(theta) * theta * (second - first * first);
359template <
typename RealType>
362 const long double first = standardMoment(1);
363 const long double second = standardMoment(2);
364 const long double third = standardMoment(3);
365 const long double variance = second - first * first;
366 return (third - 3 * first * second + 2 * first * first * first) / std::pow(variance, 1.5L);
369template <
typename RealType>
372 const long double first = standardMoment(1);
373 const long double second = standardMoment(2);
374 const long double third = standardMoment(3);
375 const long double fourth = standardMoment(4);
376 const long double variance = second - first * first;
377 const long double centralFourth =
378 fourth - 4 * first * third + 6 * first * first * second - 3 * first * first * first * first;
379 return centralFourth / (variance * variance) - 3;
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
RealType quantileImpl(double p, RealType initValue) const override
Definition continuous.hpp:140
RealType quantileImpl1m(double p, RealType initValue) const override
Definition continuous.hpp:152
Stable Count distribution.
Definition stable_count.hpp:39
void SetScale(double scale)
Definition stable_count.hpp:72
double F(const RealType &x) const override
Definition stable_count.hpp:246
std::string Name() const override
Definition stable_count.hpp:131
long double FourthMoment() const override
Definition stable_count.hpp:95
long double Variance() const override
Definition stable_count.hpp:352
void SetParameters(double exponent, double scale=1, double location=0)
Definition stable_count.hpp:112
double GetExponent() const noexcept
Definition stable_count.hpp:75
double logf(const RealType &x) const override
Definition stable_count.hpp:233
RealType operator()(G &g) const
Definition stable_count.hpp:295
RealType MinValue() const override
Definition stable_count.hpp:67
double f(const RealType &x) const override
Definition stable_count.hpp:240
long double Mean() const override
Definition stable_count.hpp:91
long double Moment(int order) const
Definition stable_count.hpp:337
long double StandardMoment(long double order) const
Definition stable_count.hpp:88
RealType MaxValue() const override
Definition stable_count.hpp:68
long double ExcessKurtosis() const override
Definition stable_count.hpp:370
Support SupportType() const override
Definition stable_count.hpp:66
long double Skewness() const override
Definition stable_count.hpp:360
void SetLocation(double location)
Definition stable_count.hpp:73
double GetLocation() const noexcept
Definition stable_count.hpp:77
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition stable_count.hpp:102
double GetScale() const noexcept
Definition stable_count.hpp:76
long double SecondMoment() const override
Definition stable_count.hpp:93
double S(const RealType &x) const override
Definition stable_count.hpp:261
StableCountRand(double exponent=0.5, double scale=1, double location=0)
Definition stable_count.hpp:60
long double ThirdMoment() const override
Definition stable_count.hpp:94
void SetExponent(double exponent)
Definition stable_count.hpp:71
The StableRand class Stable distribution.
Definition stable.hpp:521
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 pi
Definition constants.hpp:22
constexpr long double e
Definition constants.hpp:15
constexpr long double lnpi
Definition constants.hpp:21
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real qgamma(std::type_identity_t< Real > a, Real x, std::type_identity_t< Real > logA, std::type_identity_t< Real > lgammaA)
Calculate upper regularized incomplete gamma function, accelerated by using precalculated values of l...
Definition math/gamma.hpp:938
Real pgamma(std::type_identity_t< Real > a, Real x, std::type_identity_t< Real > logA, std::type_identity_t< Real > lgammaA)
Calculate lower regularized incomplete gamma function, accelerated by using precalculated value of lo...
Definition math/gamma.hpp:896
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15