RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
variates.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <cmath>
7#include <concepts>
8#include <cstddef>
9#include <random>
10#include <stdexcept>
11
12namespace randlib::detail
13{
14
16inline constexpr std::size_t MAX_ITER_REJECTION = 1000;
17
22template <std::floating_point Real, std::uniform_random_bit_generator G>
24{
25 const auto &table = exponentialZiggurat;
26 for (std::size_t iter = 0; iter <= MAX_ITER_REJECTION; ++iter) {
27 int layer = static_cast<int>(randomBits(g, 8));
28 Real x = uniform01<Real>(g) * static_cast<Real>(table[layer].second);
29 if (x < table[layer + 1].second)
30 return x;
31 if (layer == 0)
32 return static_cast<Real>(table[1].second) + standardExponential<Real>(g);
33 Real height = static_cast<Real>(table[layer].first - table[layer - 1].first);
34 if (table[layer - 1].first + height * uniform01<Real>(g) < std::exp(-x))
35 return x;
36 }
37 throw std::runtime_error("Exponential distribution: sampling failed");
38}
39
44template <std::floating_point Real, std::uniform_random_bit_generator G>
46{
47 const auto &table = normalZiggurat;
48 for (std::size_t iter = 0; iter <= MAX_ITER_REJECTION; ++iter) {
49 auto bits = randomBits(g, 9);
50 int layer = static_cast<int>(bits >> 1);
51 bool positive = bits & 1;
52 Real x = uniform01<Real>(g) * static_cast<Real>(table[layer].second);
53 if (x < table[layer + 1].second)
54 return positive ? x : -x;
55 if (layer == 0) {
57 const Real r = static_cast<Real>(table[1].second);
58 Real e = 0;
59 do {
62 } while (e + e <= x * x);
63 return positive ? r + x : -r - x;
64 }
65 Real height = static_cast<Real>(table[layer].first - table[layer - 1].first);
66 if (table[layer - 1].first + height * uniform01<Real>(g) < std::exp(-0.5 * x * x))
67 return positive ? x : -x;
68 }
69 throw std::runtime_error("Normal distribution: sampling failed");
70}
71
72} // namespace randlib::detail
Definition stable.hpp:18
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
Real standardExponential(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers.
Definition variates.hpp:23
constexpr std::array< std::pair< long double, long double >, 257 > normalZiggurat
(exp(-x^2 / 2), x) at the layer boundaries of the normal ziggurat
Definition ziggurat_tables.hpp:12
std::uint64_t randomBits(G &g, int count)
Definition engine/uniform.hpp:33
constexpr std::array< std::pair< long double, long double >, 257 > exponentialZiggurat
(exp(-x), x) at the layer boundaries of the exponential ziggurat
Definition ziggurat_tables.hpp:273
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45