18template <
typename RealType>
35 [[nodiscard]] std::string
Name()
const override;
38 [[nodiscard]] RealType
MinValue()
const override {
return (lambda < 1) ? sigmaSq * a : 0; }
39 [[nodiscard]] RealType
MaxValue()
const override {
return sigmaSq * b; }
42 [[nodiscard]]
double GetRatio() const noexcept {
return lambda; }
43 [[nodiscard]]
double GetScale() const noexcept {
return sigmaSq; }
45 [[nodiscard]]
double f(
const RealType &x)
const override;
46 [[nodiscard]]
double logf(
const RealType &x)
const override;
53 double ccdfForLargeRatio(
const RealType &x)
const;
58 double cdfForSmallRatio(
const RealType &x)
const;
61 [[nodiscard]]
double F(
const RealType &x)
const override;
62 [[nodiscard]]
double S(
const RealType &x)
const override;
73 GENERATOR_ID getIdOfUsedGenerator()
const
79 return (lambda > 3.3) ? HUGE_RATIO : LARGE_RATIO;
82 template <std::uniform_random_bit_generator G>
83 RealType variateForTinyRatio(G &g)
const;
84 template <std::uniform_random_bit_generator G>
85 RealType variateForSmallRatio(G &g)
const;
86 template <std::uniform_random_bit_generator G>
87 RealType variateForLargeRatio(G &g)
const;
88 template <std::uniform_random_bit_generator G>
89 RealType variateForHugeRatio(G &g)
const;
92 template <std::uniform_random_bit_generator G>
96 [[nodiscard]]
long double Moment(
int n)
const;
99 [[nodiscard]]
long double Mean()
const override;
100 [[nodiscard]]
long double Variance()
const override;
101 [[nodiscard]] RealType
Mode()
const override;
102 [[nodiscard]]
long double Skewness()
const override;
106 RealType quantileImpl(
double p)
const override;
107 RealType quantileImpl1m(
double p)
const override;
108 std::complex<double> CFImpl(
double t)
const override;
118template <
typename RealType>
121 SetParameters(ratio, scale);
124template <
typename RealType>
127 return "Marchenko-Pastur(" + this->toStringWithPrecision(GetRatio()) +
", " +
128 this->toStringWithPrecision(GetScale()) +
")";
131template <
typename RealType>
135 throw std::invalid_argument(
"Marchenko-Pastur distribution: ratio parameter should be positive");
137 throw std::invalid_argument(
"Marchenko-Pastur distribution: scale should be positive");
139 double sqrtLambda = std::sqrt(lambda);
140 a = 1.0 - sqrtLambda;
142 b = 1.0 + sqrtLambda;
146 logLambda = std::log(lambda);
148 GENERATOR_ID genId = getIdOfUsedGenerator();
149 if (genId == TINY_RATIO || genId == HUGE_RATIO) {
150 BetaRV.SetShapes(1.5, 1.5);
151 BetaRV.SetSupport(a, b);
152 M = std::min(a / lambda, a);
154 BetaRV.SetShapes(0.5, 1.5);
155 BetaRV.SetSupport(0, b);
156 M = 0.25 * b / sqrtLambda;
158 M /= lambda * lambda;
162template <
typename RealType>
166 return (lambda < 1) ? 0.0 : INFINITY;
167 double xSt = x / sigmaSq;
168 if (xSt < a || xSt > b)
170 double y = 0.5 * std::sqrt((b - xSt) * (xSt - a));
176template <
typename RealType>
180 return (lambda < 1) ? -INFINITY : INFINITY;
181 double xSt = x / sigmaSq;
182 if (xSt < a || xSt > b)
184 double y = 0.5 * std::log((b - xSt) * (xSt - a));
189template <
typename RealType>
192 double y1 = 1.0 - x + lambda;
193 double lambdam1 = lambda - 1.0;
194 double lambdap1 = lambda + 1.0;
195 double temp = std::sqrt(4 * lambda - y1 * y1);
201 double y2 = x * lambdap1;
202 y2 -= lambdam1 * lambdam1;
203 y2 /= temp * lambdam1;
210template <
typename RealType>
211double MarchenkoPasturRand<RealType>::cdfForSmallRatio(
const RealType &x)
const
213 double y1 = 1.0 - x + lambda;
214 double temp = std::sqrt(4 * lambda - y1 * y1);
215 double lambdam1 = lambda - 1.0;
216 double lambdap1 = lambda + 1.0;
225 y2 -= lambdam1 * lambdam1;
226 y2 /= -temp * lambdam1;
234template <
typename RealType>
237 double xSt = x / sigmaSq;
243 return (xSt > a) ? 1.0 - ccdfForLargeRatio(xSt) : 1.0 - 1.0 / lambda;
244 return (xSt > a) ? cdfForSmallRatio(xSt) : 0.0;
247template <
typename RealType>
250 double xSt = x / sigmaSq;
256 return (xSt > a) ? ccdfForLargeRatio(xSt) : 1.0 / lambda;
257 return (xSt > a) ? 1.0 - cdfForSmallRatio(xSt) : 1.0;
260template <
typename RealType>
261template <std::uniform_random_bit_generator G>
266 double X = BetaRV(g);
270 }
while (++iter <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION);
271 throw std::runtime_error(
"Marchenko-Pastur distribution: sampling failed");
274template <
typename RealType>
275template <std::uniform_random_bit_generator G>
276RealType MarchenkoPasturRand<RealType>::variateForSmallRatio(G &g)
const
280 double X = BetaRV(g);
282 double ratio = M * (1.0 - a / X);
285 }
while (++iter <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION);
286 throw std::runtime_error(
"Marchenko-Pastur distribution: sampling failed");
289template <
typename RealType>
290template <std::uniform_random_bit_generator G>
291RealType MarchenkoPasturRand<RealType>::variateForLargeRatio(G &g)
const
296template <
typename RealType>
297template <std::uniform_random_bit_generator G>
298RealType MarchenkoPasturRand<RealType>::variateForHugeRatio(G &g)
const
303template <
typename RealType>
304template <std::uniform_random_bit_generator G>
307 switch (getIdOfUsedGenerator()) {
309 return sigmaSq * variateForTinyRatio(g);
311 return sigmaSq * variateForSmallRatio(g);
313 return sigmaSq * variateForLargeRatio(g);
315 return sigmaSq * variateForHugeRatio(g);
317 throw std::runtime_error(
"Marchenko-Pastur distribution: invalid generator id");
321template <
typename RealType>
324 switch (getIdOfUsedGenerator()) {
326 for (RealType &var : outputData)
327 var = sigmaSq * variateForTinyRatio(g);
330 for (RealType &var : outputData)
331 var = sigmaSq * variateForSmallRatio(g);
334 for (RealType &var : outputData)
335 var = sigmaSq * variateForLargeRatio(g);
338 for (RealType &var : outputData)
339 var = sigmaSq * variateForHugeRatio(g);
346template <
typename RealType>
347long double MarchenkoPasturRand<RealType>::Moment(
int n)
const
350 throw std::invalid_argument(
"Marchenko-Pastur distribution: degree n should be non-negative");
357 return sigmaSq * sigmaSq * lambda;
359 long double sum = 0.0;
361 long double nlogSigmaSq = n * std::log(sigmaSq);
362 for (
int k = 0; k != n; ++k) {
363 long double term = temp;
368 term += k * logLambda;
370 term = std::exp(term) / kp1;
378template <
typename RealType>
384template <
typename RealType>
387 return sigmaSq * sigmaSq * lambda;
390template <
typename RealType>
395 RealType mode = lambda - 1.0;
397 mode /= lambda + 1.0;
398 return sigmaSq * mode;
401template <
typename RealType>
404 long double mu = Mean();
405 long double var = Variance();
406 long double skewness = Moment(3);
407 skewness -= std::pow(mu, 3);
408 skewness -= 3 * mu * var;
409 skewness /= std::pow(var, 1.5);
413template <
typename RealType>
416 long double mu = Mean();
417 long double var = Variance();
418 long double moment3 = Moment(3);
419 long double kurtosis = Moment(4);
420 long double muSq = mu * mu;
421 kurtosis -= 4 * mu * moment3;
422 kurtosis += 3 * muSq * muSq;
423 kurtosis += 6 * muSq * var;
424 kurtosis /= var * var;
425 return kurtosis - 3.0;
428template <
typename RealType>
431 if (p <= 1.0 - 1.0 / lambda)
433 RealType minInitValue = sigmaSq * a;
434 RealType maxInitValue = sigmaSq * b;
435 RealType initValue = minInitValue + p * (maxInitValue - minInitValue);
439template <
typename RealType>
440RealType MarchenkoPasturRand<RealType>::quantileImpl1m(
double p)
const
442 if (p >= 1.0 / lambda)
444 RealType minInitValue = sigmaSq * a;
445 RealType maxInitValue = sigmaSq * b;
446 RealType initValue = maxInitValue - p * (maxInitValue - minInitValue);
450template <
typename RealType>
451std::complex<double> MarchenkoPasturRand<RealType>::CFImpl(
double t)
const
458 double re = this->ExpectedValue([t](
double x) {
return std::cos(t * x) - 1.0; }, 0, 4 * sigmaSq);
459 double im = this->ExpectedValue([t](
double x) {
return std::sin(t * x); }, 0, 4 * sigmaSq);
460 return std::complex<double>(1.0 + re, im);
463 double re = this->ExpectedValue([t](
double x) {
return std::cos(t * x); }, sigmaSq * a, sigmaSq * b);
464 double im = this->ExpectedValue([t](
double x) {
return std::sin(t * x); }, sigmaSq * a, sigmaSq * b);
465 return std::complex<double>(1.0 - 1.0 / lambda + re, im);
The BetaRand class Beta distribution.
Definition continuous/beta.hpp:246
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
The MarchenkoPasturRand class Marchenko-Pastur distribution.
Definition marchenko_pastur.hpp:20
MarchenkoPasturRand(double ratio=1, double scale=1)
Definition marchenko_pastur.hpp:119
std::string Name() const override
Definition marchenko_pastur.hpp:125
double GetScale() const noexcept
Definition marchenko_pastur.hpp:43
double F(const RealType &x) const override
Definition marchenko_pastur.hpp:235
double f(const RealType &x) const override
Definition marchenko_pastur.hpp:163
Support SupportType() const override
Definition marchenko_pastur.hpp:37
RealType operator()(G &g) const
Definition marchenko_pastur.hpp:305
double logf(const RealType &x) const override
Definition marchenko_pastur.hpp:177
long double Skewness() const override
Definition marchenko_pastur.hpp:402
long double Variance() const override
Definition marchenko_pastur.hpp:385
double GetRatio() const noexcept
Definition marchenko_pastur.hpp:42
void SetParameters(double ratio, double scale)
Definition marchenko_pastur.hpp:132
RealType MinValue() const override
Definition marchenko_pastur.hpp:38
RealType MaxValue() const override
Definition marchenko_pastur.hpp:39
long double ExcessKurtosis() const override
Definition marchenko_pastur.hpp:414
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition marchenko_pastur.hpp:391
double S(const RealType &x) const override
Definition marchenko_pastur.hpp:248
long double Mean() const override
Definition marchenko_pastur.hpp:379
virtual std::complex< double > CFImpl(double t) const
Definition univariate.hpp:365
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double ln2
Definition constants.hpp:18
constexpr long double half_pi
Definition constants.hpp:23
constexpr long double pi
Definition constants.hpp:22
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 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 atan(Real x)
Definition functions.hpp:238
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15