RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
wrapped_exponential.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
17template <typename RealType>
18class WrappedExponentialRand final : public CircularDistribution<RealType>
19{
20 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
21
22 double lambda = 1;
23 double logLambda = 0;
24 double scaledLambda = 2 * randlib::consts::pi;
25 double pdfCoef = 0, logpdfCoef = 0, expmScaledLambda = 0;
26
27public:
28 WrappedExponentialRand(double rate);
29
30 [[nodiscard]] std::string Name() const override;
31
32 void SetRate(double rate);
33 [[nodiscard]] inline double GetRate() const noexcept { return lambda; }
34
35 [[nodiscard]] double f(const RealType &x) const override;
36 [[nodiscard]] double logf(const RealType &x) const override;
37 [[nodiscard]] double F(const RealType &x) const override;
38 [[nodiscard]] double S(const RealType &x) const override;
39 template <std::uniform_random_bit_generator G>
40 [[nodiscard]] RealType operator()(G &g) const;
41
42 [[nodiscard]] long double CircularMean() const override;
43 [[nodiscard]] long double CircularVariance() const override;
44 [[nodiscard]] RealType Median() const override;
45 [[nodiscard]] RealType Mode() const override;
46
47protected:
48 RealType quantileImpl(double p) const override;
49 RealType quantileImpl1m(double p) const override;
50 std::complex<double> CFImpl(double t) const override;
51};
52
53} // namespace randlib
54
56
57namespace randlib
58{
59
60template <typename RealType>
62 : CircularDistribution<RealType>(randlib::consts::pi)
63{
64 SetRate(rate);
65}
66
67template <typename RealType>
69{
70 return "Wrapped Exponential(" + this->toStringWithPrecision(GetRate()) + ")";
71}
72
73template <typename RealType>
75{
76 if (!(rate > 0.0))
77 throw std::invalid_argument("Wrapped Exponential distribution: rate parameter should be positive");
78 lambda = rate;
79 logLambda = std::log(lambda);
80 scaledLambda = 2 * randlib::consts::pi * lambda;
81 expmScaledLambda = std::exp(-scaledLambda);
82 pdfCoef = -std::expm1l(-scaledLambda);
83 logpdfCoef = math::log1mexp(-scaledLambda);
84}
85
86template <typename RealType>
87double WrappedExponentialRand<RealType>::f(const RealType &x) const
88{
89 return (x < this->MinValue() || x > this->MaxValue()) ? 0.0 : std::exp(logf(x));
90}
91
92template <typename RealType>
93double WrappedExponentialRand<RealType>::logf(const RealType &x) const
94{
95 return (x < this->MinValue() || x > this->MaxValue()) ? -INFINITY : logLambda - lambda * x - logpdfCoef;
96}
97
98template <typename RealType>
99double WrappedExponentialRand<RealType>::F(const RealType &x) const
100{
101 if (x <= 0.0)
102 return 0.0;
103 return (x < this->MaxValue()) ? std::exp(math::log1mexp(-lambda * x) - logpdfCoef) : 1.0;
104}
105
106template <typename RealType>
107double WrappedExponentialRand<RealType>::S(const RealType &x) const
108{
109 if (x <= 0.0)
110 return 1.0;
111 if (x >= this->MaxValue())
112 return 0.0;
113 double y = std::expm1l(scaledLambda - lambda * x);
114 y /= pdfCoef;
115 return expmScaledLambda * y;
116}
117
118template <typename RealType>
119template <std::uniform_random_bit_generator G>
121{
122 return quantileImpl(detail::uniform01<RealType>(g));
123}
124
125template <typename RealType>
130
131template <typename RealType>
133{
134 return 1.0 - lambda / std::sqrt(1.0 + lambda * lambda);
135}
136
137template <typename RealType>
139{
140 return (randlib::consts::ln2 - math::softplus(-scaledLambda)) / lambda;
141}
142
143template <typename RealType>
145{
146 return 0.0;
147}
148
149template <typename RealType>
151{
152 return -std::log1pl(-p * pdfCoef) / lambda;
153}
154
155template <typename RealType>
157{
158 return -std::log(expmScaledLambda + p * pdfCoef) / lambda;
159}
160
161template <typename RealType>
162std::complex<double> WrappedExponentialRand<RealType>::CFImpl(double t) const
163{
165 std::complex<double> lambdaMinusIt(lambda, -t);
166 std::complex<double> wrap = 1.0 - std::exp(-lambdaMinusIt * static_cast<double>(2 * randlib::consts::pi));
167 return lambda * wrap / (lambdaMinusIt * pdfCoef);
168}
169
170} // namespace randlib
The CircularDistribution class Abstract class for all continuous circular distributions.
Definition circular.hpp:19
The WrappedExponentialRand class Wrapped Exponential distribution.
Definition wrapped_exponential.hpp:19
RealType operator()(G &g) const
Definition wrapped_exponential.hpp:120
WrappedExponentialRand(double rate)
Definition wrapped_exponential.hpp:61
double f(const RealType &x) const override
Definition wrapped_exponential.hpp:87
double S(const RealType &x) const override
Definition wrapped_exponential.hpp:107
void SetRate(double rate)
Definition wrapped_exponential.hpp:74
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition wrapped_exponential.hpp:144
long double CircularMean() const override
Definition wrapped_exponential.hpp:126
std::string Name() const override
Definition wrapped_exponential.hpp:68
double logf(const RealType &x) const override
Definition wrapped_exponential.hpp:93
RealType quantileImpl(double p) const override
Definition wrapped_exponential.hpp:150
long double CircularVariance() const override
Definition wrapped_exponential.hpp:132
std::complex< double > CFImpl(double t) const override
Definition wrapped_exponential.hpp:162
RealType Median() const override
Definition wrapped_exponential.hpp:138
double F(const RealType &x) const override
Definition wrapped_exponential.hpp:99
RealType quantileImpl1m(double p) const override
Definition wrapped_exponential.hpp:156
double GetRate() const noexcept
Definition wrapped_exponential.hpp:33
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
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real log1mexp(Real x)
Definition functions.hpp:260
Real atan(Real x)
Definition functions.hpp:238
Real softplus(Real x)
Definition functions.hpp:252
Definition bivariate_normal.hpp:10