RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
distribution.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <iomanip>
5#include <optional>
6#include <random>
7#include <span>
8#include <sstream>
9#include <string>
10
12#include <randlib/core/fwd.hpp>
18
19namespace randlib
20{
21
26template <typename T>
28{
29 mutable std::optional<DefaultEngine> ownEngine{};
30
31protected:
39
40 std::string toStringWithPrecision(const double a_value, const int n = 6) const;
41
43
48 {
49 if (!ownEngine)
50 ownEngine.emplace(random_seed());
51 return *ownEngine;
52 }
53
59 virtual T variate(detail::EngineRef g) const = 0;
60
66 virtual void sample(detail::EngineRef g, std::span<T> outputData) const
67 {
68 for (T &var : outputData)
69 var = variate(g);
70 }
71
72public:
73 using value_type = T;
74
75 virtual ~ProbabilityDistribution() = default;
76
80 [[nodiscard]] virtual std::string Name() const = 0;
81
85 [[nodiscard]] virtual T MinValue() const = 0;
86
90 [[nodiscard]] virtual T MaxValue() const = 0;
91
96 [[nodiscard]] virtual double F(const T &x) const = 0;
97
102 void CumulativeDistributionFunction(std::span<const T> x, std::span<double> y) const;
103
108 [[nodiscard]] virtual double S(const T &x) const;
109
114 void SurvivalFunction(std::span<const T> x, std::span<double> y) const;
115
122 template <std::uniform_random_bit_generator G>
123 [[nodiscard]] T operator()(G &g) const
124 {
125 return variate(g);
126 }
127
133 [[nodiscard]] T Variate() const { return variate(engine()); }
134
139 void Sample(std::span<T> outputData) const { sample(engine(), outputData); }
140
146 template <std::uniform_random_bit_generator G>
147 void Sample(G &g, std::span<T> outputData) const
148 {
149 sample(g, outputData);
150 }
151
155 void Reseed(std::uint64_t seed) { ownEngine.emplace(seed); }
156
157protected:
158 static constexpr char POSITIVITY_VIOLATION[] = "All elements should be positive";
159 static constexpr char NON_NEGATIVITY_VIOLATION[] = "All elements should be non-negative";
160 static constexpr char UPPER_LIMIT_VIOLATION[] = "No element should be greater than ";
161 static constexpr char LOWER_LIMIT_VIOLATION[] = "No element should be smaller than ";
162
168 fit_error fitError(FitErrorCode code, const std::string &explanation) const;
169};
170
171} // namespace randlib
172
174#include <randlib/math/roots.hpp>
176
177namespace randlib
178{
179
180template <typename T>
181std::string ProbabilityDistribution<T>::toStringWithPrecision(const double a_value, const int n) const
182{
183 std::ostringstream out;
184 out << std::setprecision(n) << a_value;
185 return out.str();
186}
187
188template <typename T>
189void ProbabilityDistribution<T>::CumulativeDistributionFunction(std::span<const T> x, std::span<double> y) const
190{
191 const size_t size = std::min(x.size(), y.size());
192 for (size_t i = 0; i != size; ++i)
193 y[i] = this->F(x[i]);
194}
195
196template <typename T>
197double ProbabilityDistribution<T>::S(const T &x) const
198{
199 return 1.0 - this->F(x);
200}
201
202template <typename T>
203void ProbabilityDistribution<T>::SurvivalFunction(std::span<const T> x, std::span<double> y) const
204{
205 const size_t size = std::min(x.size(), y.size());
206 for (size_t i = 0; i != size; ++i)
207 y[i] = this->S(x[i]);
208}
209
210template <typename T>
212template <typename T>
214template <typename T>
216template <typename T>
218
219template <typename T>
220fit_error ProbabilityDistribution<T>::fitError(FitErrorCode code, const std::string &explanation) const
221{
222 std::string reason;
223 switch (code) {
225 reason = "Sample couldn't be generated by this distribution. ";
226 break;
228 reason = "Method cannot be applied here. ";
229 break;
231 reason = "Method returns invalid parameters. ";
232 break;
234 reason = "Sample is too small. ";
235 break;
237 reason = "Significance level should be positive and smaller than 1. ";
238 break;
240 reason = "Unknown type of error. ";
241 break;
242 }
243 return fit_error(code, this->Name() + ": " + reason + explanation);
244}
245
250
251} // namespace randlib
The ProbabilityDistribution class Abstract class for all probability distributions.
Definition distribution.hpp:28
virtual ~ProbabilityDistribution()=default
virtual double S(const T &x) const
Definition distribution.hpp:197
void SurvivalFunction(std::span< const T > x, std::span< double > y) const
Definition distribution.hpp:203
virtual T MaxValue() const =0
static constexpr char LOWER_LIMIT_VIOLATION[]
Definition distribution.hpp:161
T Variate() const
Uses the engine of this object, so it is not thread-safe for one object; use operator() with one engi...
Definition distribution.hpp:133
DefaultEngine & engine() const
Definition distribution.hpp:47
std::string toStringWithPrecision(const double a_value, const int n=6) const
Definition distribution.hpp:181
static constexpr char UPPER_LIMIT_VIOLATION[]
Definition distribution.hpp:160
virtual void sample(detail::EngineRef g, std::span< T > outputData) const
Fills the output with variate(g); distributions with a faster bulk algorithm override it.
Definition distribution.hpp:66
static constexpr size_t MAX_ITER_REJECTION
MAX_ITER_REJECTION upper boundary for maximum amount of iterations in rejection methods one thousand ...
Definition distribution.hpp:38
static constexpr char NON_NEGATIVITY_VIOLATION[]
Definition distribution.hpp:159
virtual std::string Name() const =0
void Sample(std::span< T > outputData) const
Fills the output with variates drawn with the engine of this object.
Definition distribution.hpp:139
void CumulativeDistributionFunction(std::span< const T > x, std::span< double > y) const
Definition distribution.hpp:189
void Sample(G &g, std::span< T > outputData) const
Fills the output with variates drawn with the given engine.
Definition distribution.hpp:147
fit_error fitError(FitErrorCode code, const std::string &explanation) const
Definition distribution.hpp:220
virtual double F(const T &x) const =0
virtual T MinValue() const =0
T value_type
Definition distribution.hpp:73
static constexpr char POSITIVITY_VIOLATION[]
Definition distribution.hpp:158
virtual T variate(detail::EngineRef g) const =0
Every concrete distribution implements this by calling its templated operator()
T operator()(G &g) const
Draws a variate with the given engine through the virtual interface.
Definition distribution.hpp:123
void Reseed(std::uint64_t seed)
Definition distribution.hpp:155
The Xoshiro256pp class xoshiro256++ 1.0 by David Blackman and Sebastiano Vigna: 256 bits of state,...
Definition xoshiro.hpp:20
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
The fit_error class Thrown when a distribution cannot be fitted to a sample; code() tells why.
Definition errors.hpp:36
constexpr std::size_t MAX_ITER_REJECTION
Upper bound on the iterations of rejection samplers; reaching it means there is a bug.
Definition variates.hpp:16
Definition bivariate_normal.hpp:10
FitErrorCode
Reason why a distribution could not be fitted to a sample.
Definition errors.hpp:22
@ WrongSample
the sample could not have been drawn from this distribution
@ WrongLevel
the significance level is not in (0, 1)
@ NotApplicable
the method cannot be applied to this distribution or sample
@ WrongReturn
the method returned invalid parameters
@ TooFewElements
the sample is too small
@ Undefined
any other failure
std::uint64_t random_seed()
Definition seeding.hpp:26