RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
xoshiro.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6#include <bit>
7#include <concepts>
8#include <cstdint>
9
10namespace randlib
11{
12
20{
21public:
22 using result_type = std::uint64_t;
23 static constexpr std::uint64_t default_seed = 0x853C49E6748FEA9BULL;
24
25 constexpr explicit Xoshiro256pp(std::uint64_t value = default_seed) noexcept { seed(value); }
26
27 template <class SeedSeq>
28 requires(!std::convertible_to<SeedSeq &, std::uint64_t>)
29 explicit Xoshiro256pp(SeedSeq &sequence)
30 {
31 seed(sequence);
32 }
33
34 static constexpr result_type min() noexcept { return 0; }
35 static constexpr result_type max() noexcept { return ~result_type{0}; }
36
38 constexpr void seed(std::uint64_t value) noexcept
39 {
40 SplitMix64 expand(value);
41 for (std::uint64_t &word : s)
42 word = expand();
43 }
44
45 template <class SeedSeq>
46 requires(!std::convertible_to<SeedSeq &, std::uint64_t>)
47 void seed(SeedSeq &sequence)
48 {
49 std::array<std::uint32_t, 8> words{};
50 sequence.generate(words.begin(), words.end());
51 for (std::size_t i = 0; i < s.size(); ++i)
52 s[i] = (static_cast<std::uint64_t>(words[2 * i]) << 32) | words[2 * i + 1];
53 if (s[0] == 0 && s[1] == 0 && s[2] == 0 && s[3] == 0)
54 s[0] = 1;
55 }
56
57 constexpr result_type operator()() noexcept
58 {
59 const std::uint64_t result = std::rotl(s[0] + s[3], 23) + s[0];
60 const std::uint64_t t = s[1] << 17;
61 s[2] ^= s[0];
62 s[3] ^= s[1];
63 s[1] ^= s[2];
64 s[0] ^= s[3];
65 s[2] ^= t;
66 s[3] = std::rotl(s[3], 45);
67 return result;
68 }
69
70 constexpr void discard(unsigned long long n) noexcept
71 {
72 while (n-- > 0)
73 (*this)();
74 }
75
77 constexpr void jump() noexcept
78 {
79 polynomialJump({0x180EC6D33CFD0ABAULL, 0xD5A61266F0C9392CULL, 0xA9582618E03FC9AAULL, 0x39ABDC4529B1661CULL});
80 }
81
83 constexpr void long_jump() noexcept
84 {
85 polynomialJump({0x76E15D3EFEFDCBBFULL, 0xC5004E441C522FB3ULL, 0x77710069854EE241ULL, 0x39109BB02ACBE635ULL});
86 }
87
88 friend constexpr bool operator==(const Xoshiro256pp &, const Xoshiro256pp &) = default;
89
90private:
91 std::array<std::uint64_t, 4> s{};
92
93 constexpr void polynomialJump(const std::array<std::uint64_t, 4> &polynomial) noexcept
94 {
95 std::array<std::uint64_t, 4> next{};
96 for (std::uint64_t word : polynomial) {
97 for (int b = 0; b < 64; ++b) {
98 if (word & (std::uint64_t{1} << b)) {
99 for (std::size_t i = 0; i < s.size(); ++i)
100 next[i] ^= s[i];
101 }
102 (*this)();
103 }
104 }
105 s = next;
106 }
107};
108
109} // namespace randlib
The SplitMix64 class Sebastiano Vigna's SplitMix64 generator.
Definition splitmix64.hpp:14
The Xoshiro256pp class xoshiro256++ 1.0 by David Blackman and Sebastiano Vigna: 256 bits of state,...
Definition xoshiro.hpp:20
static constexpr result_type min() noexcept
Definition xoshiro.hpp:34
Xoshiro256pp(SeedSeq &sequence)
Definition xoshiro.hpp:29
std::uint64_t result_type
Definition xoshiro.hpp:22
static constexpr result_type max() noexcept
Definition xoshiro.hpp:35
constexpr void seed(std::uint64_t value) noexcept
Expands the seed with SplitMix64, as recommended by the authors.
Definition xoshiro.hpp:38
constexpr void long_jump() noexcept
Advances the state by 2^192 steps.
Definition xoshiro.hpp:83
constexpr result_type operator()() noexcept
Definition xoshiro.hpp:57
constexpr void discard(unsigned long long n) noexcept
Definition xoshiro.hpp:70
constexpr Xoshiro256pp(std::uint64_t value=default_seed) noexcept
Definition xoshiro.hpp:25
constexpr void jump() noexcept
Advances the state by 2^128 steps.
Definition xoshiro.hpp:77
static constexpr std::uint64_t default_seed
Definition xoshiro.hpp:23
void seed(SeedSeq &sequence)
Definition xoshiro.hpp:47
friend constexpr bool operator==(const Xoshiro256pp &, const Xoshiro256pp &)=default
Definition bivariate_normal.hpp:10