RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
kolmogorov_smirnov.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
17template <typename RealType>
18class KolmogorovSmirnovRand final : public ContinuousDistribution<RealType>
19{
20 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
21
22public:
24 [[nodiscard]] std::string Name() const override;
25 [[nodiscard]] Support SupportType() const override { return Support::RightSemiFinite; }
26 [[nodiscard]] RealType MinValue() const override { return 0; }
27 [[nodiscard]] RealType MaxValue() const override { return INFINITY; }
28
29private:
30 static double L(RealType x);
31 static double K(RealType x);
32
33public:
34 [[nodiscard]] double f(const RealType &x) const override;
35 [[nodiscard]] double logf(const RealType &x) const override;
36 [[nodiscard]] double F(const RealType &x) const override;
37 [[nodiscard]] double S(const RealType &x) const override;
38 double logF(const RealType &x) const;
39 double logS(const RealType &x) const;
40
41private:
42 template <std::uniform_random_bit_generator G>
43 RealType truncatedGammaVariate(G &g) const;
44 template <std::uniform_random_bit_generator G>
45 RealType variateForTheLeftMostInterval(G &g) const;
46 template <std::uniform_random_bit_generator G>
47 RealType variateForTheRightMostInterval(G &g) const;
48
49public:
50 template <std::uniform_random_bit_generator G>
51 [[nodiscard]] RealType operator()(G &g) const;
52
53 [[nodiscard]] long double Mean() const override;
54 [[nodiscard]] long double Variance() const override;
55 [[nodiscard]] RealType Mode() const override;
56 [[nodiscard]] RealType Median() const override;
57
58private:
59 RealType quantileImpl(double p) const override;
60 RealType quantileImpl1m(double p) const override;
61};
62
63} // namespace randlib
64
67
68namespace randlib
69{
70
71template <typename RealType>
75
76template <typename RealType>
78{
79 return "Kolmogorov-Smirnov";
80}
81
82template <typename RealType>
84{
85 if (x <= 0.0)
86 return 0.0;
87 double sum = 0.0, addon = 0.0;
88 int k = 1;
89 double aux = randlib::consts::pi_sq * 0.125 / (x * x);
90 do {
91 int temp = (2 * k - 1);
92 temp *= temp;
93 addon = std::exp(-temp * aux);
94 sum += addon;
95 ++k;
96 } while (addon > math::detail::minimumTolerance * sum);
97 return randlib::consts::sqrt2pi * sum / x;
98}
99
100template <typename RealType>
101double KolmogorovSmirnovRand<RealType>::K(RealType x)
102{
103 if (x <= 0.0)
104 return 1.0;
105 double sum = 0.0, addon = 0.0;
106 int k = 1;
107 double xSq = x * x;
108 do {
109 int temp = 2 * k * k;
110 addon = std::exp(-temp * xSq);
111 sum += (k & 1) ? addon : -addon;
112 ++k;
113 } while (addon > math::detail::minimumTolerance * sum);
114 return 2 * sum;
115}
116
117template <typename RealType>
118double KolmogorovSmirnovRand<RealType>::f(const RealType &x) const
119{
120 if (x <= 0.0)
121 return 0.0;
122 double sum = 0.0, addon = 0.0;
123 int k = 1;
124 double xSq = x * x;
125 if (x < 1.0) {
126 double aux = 0.125 / xSq;
127 do {
128 double temp = randlib::consts::pi * (2 * k - 1);
129 temp *= temp;
130 addon = temp - 4 * xSq;
131 addon *= std::exp(-temp * aux);
132 sum += addon;
133 ++k;
134 } while (addon > math::detail::minimumTolerance * sum);
135 return randlib::consts::sqrt2pi * sum * 0.25 / std::pow(x, 4);
136 }
138 do {
139 int temp = k * k;
140 addon = std::exp(-2 * temp * xSq);
141 addon *= temp;
142 sum += (k & 1) ? addon : -addon;
143 ++k;
144 } while (addon > math::detail::minimumTolerance * sum);
145 return 8 * sum * x;
146}
147
148template <typename RealType>
149double KolmogorovSmirnovRand<RealType>::logf(const RealType &x) const
150{
151 return std::log(f(x));
152}
153
154template <typename RealType>
155double KolmogorovSmirnovRand<RealType>::F(const RealType &x) const
156{
157 return (x > 1.0) ? 1.0 - K(x) : L(x);
158}
159
160template <typename RealType>
161double KolmogorovSmirnovRand<RealType>::S(const RealType &x) const
162{
163 return (x > 1.0) ? K(x) : 1.0 - L(x);
164}
165
166template <typename RealType>
167double KolmogorovSmirnovRand<RealType>::logF(const RealType &x) const
168{
169 return (x > 1.0) ? std::log1pl(-K(x)) : std::log(L(x));
170}
171
172template <typename RealType>
173double KolmogorovSmirnovRand<RealType>::logS(const RealType &x) const
174{
175 return (x > 1.0) ? std::log(K(x)) : std::log1pl(-L(x));
176}
177
178template <typename RealType>
179template <std::uniform_random_bit_generator G>
181{
183 static constexpr long double tp = 2.193245422464302l;
184 static constexpr long double rate = 1.2952909208355123l;
185 size_t iter = 0;
186 do {
187 RealType E0 = rate * detail::standardExponential<RealType>(g);
188 RealType E1 = 2 * detail::standardExponential<RealType>(g);
189 RealType gammaValue = tp + E0;
190 if (E0 * E0 <= tp * E1 * (gammaValue + tp))
191 return gammaValue;
192 RealType Wp = E0 / tp;
193 if (Wp - std::log1pl(Wp) <= E1)
194 return gammaValue;
195 } while (++iter <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION);
196 throw std::runtime_error("Kolmogorov-Smirnov distribution: sampling failed");
197}
198
199template <typename RealType>
200template <std::uniform_random_bit_generator G>
201RealType KolmogorovSmirnovRand<RealType>::variateForTheLeftMostInterval(G &g) const
202{
203 size_t iter1 = 0;
204 do {
205 RealType gammaValue = truncatedGammaVariate(g);
206 RealType X = randlib::consts::pi / std::sqrt(8 * gammaValue);
207 RealType W = 0.0;
208 RealType Z = 0.5 / gammaValue;
209 size_t n = 1, iter2 = 0;
210 RealType Q = 1.0;
211 RealType U = detail::uniform01<RealType>(g);
212 while (U >= W && ++iter2 <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION) {
213 W += Z * Q;
214 if (U >= W)
215 return X;
216 n += 2;
217 int nSq = n * n;
218 Q = std::exp(gammaValue - gammaValue * nSq);
219 W -= nSq * Q;
220 }
221 } while (++iter1 <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION);
222 throw std::runtime_error("Kolmogorov-Smirnov distribution: sampling failed");
223}
224
225template <typename RealType>
226template <std::uniform_random_bit_generator G>
227RealType KolmogorovSmirnovRand<RealType>::variateForTheRightMostInterval(G &g) const
228{
229 static constexpr double tSq = 0.5625;
230 size_t iter1 = 0;
231 do {
233 RealType U = detail::uniform01<RealType>(g);
234 RealType X = std::sqrt(tSq + 0.5 * E);
235 RealType W = 0.0;
236 size_t n = 1, iter2 = 0;
237 RealType Z = -2 * X * X;
238 while (U > W && ++iter2 <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION) {
239 ++n;
240 int nSq = n * n;
241 W += nSq * std::exp(Z * (nSq - 1));
242 if (U >= W)
243 return X;
244 ++n;
245 nSq = n * n;
246 W -= nSq * std::exp(Z * (nSq - 1));
247 }
248 } while (++iter1 <= ProbabilityDistribution<RealType>::MAX_ITER_REJECTION);
249 throw std::runtime_error("Kolmogorov-Smirnov distribution: sampling failed");
250}
251
252template <typename RealType>
253template <std::uniform_random_bit_generator G>
255{
258 bool isLeft = detail::uniform01<RealType>(g) < 0.3728329582237386;
259 return isLeft ? variateForTheLeftMostInterval(g) : variateForTheRightMostInterval(g);
260}
261
262template <typename RealType>
267
268template <typename RealType>
270{
271 long double mean = Mean();
272 return randlib::consts::pi_sq / 12 - mean * mean;
273}
274
275template <typename RealType>
277{
278 return 0.735467812776958l;
279}
280
281template <typename RealType>
283{
284 return 0.82757355518990761l;
285}
286
287template <typename RealType>
289{
290 RealType guess = std::sqrt(-0.5 * (std::log1pl(-p) - randlib::consts::ln2));
292}
293
294template <typename RealType>
295RealType KolmogorovSmirnovRand<RealType>::quantileImpl1m(double p) const
296{
297 RealType guess = std::sqrt(-0.5 * std::log(0.5 * p));
299}
300
301} // namespace randlib
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 KolmogorovSmirnovRand class Kolmogorov-Smirnov distribution.
Definition kolmogorov_smirnov.hpp:19
double logf(const RealType &x) const override
Definition kolmogorov_smirnov.hpp:149
Support SupportType() const override
Definition kolmogorov_smirnov.hpp:25
long double Variance() const override
Definition kolmogorov_smirnov.hpp:269
RealType operator()(G &g) const
Definition kolmogorov_smirnov.hpp:254
std::string Name() const override
Definition kolmogorov_smirnov.hpp:77
long double Mean() const override
Definition kolmogorov_smirnov.hpp:263
double S(const RealType &x) const override
Definition kolmogorov_smirnov.hpp:161
double logS(const RealType &x) const
Definition kolmogorov_smirnov.hpp:173
RealType MinValue() const override
Definition kolmogorov_smirnov.hpp:26
double f(const RealType &x) const override
Definition kolmogorov_smirnov.hpp:118
RealType Median() const override
Definition kolmogorov_smirnov.hpp:282
RealType MaxValue() const override
Definition kolmogorov_smirnov.hpp:27
KolmogorovSmirnovRand()
Definition kolmogorov_smirnov.hpp:72
double logF(const RealType &x) const
Definition kolmogorov_smirnov.hpp:167
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition kolmogorov_smirnov.hpp:276
double F(const RealType &x) const override
Definition kolmogorov_smirnov.hpp:155
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 sqrtpi
Definition constants.hpp:31
constexpr long double pi
Definition constants.hpp:22
constexpr long double inv_sqrt2
Definition constants.hpp:28
constexpr long double pi_sq
Definition constants.hpp:39
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
constexpr long double minimumTolerance
Definition constants.hpp:44
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)