File indexing completed on 2026-08-10 09:10:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_RANDOM_SPLITMIX64_HPP
0011 #define BOOST_RANDOM_SPLITMIX64_HPP
0012
0013 #include <cstdint>
0014 #include <cstdlib>
0015 #include <limits>
0016 #include <array>
0017 #include <string>
0018 #include <ios>
0019 #include <type_traits>
0020
0021 namespace boost { namespace random {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 class splitmix64
0034 {
0035 private:
0036 std::uint64_t state_;
0037
0038 inline std::uint64_t concatenate(std::uint32_t word1, std::uint32_t word2) noexcept
0039 {
0040 return static_cast<std::uint64_t>(word1) << 32 | word2;
0041 }
0042
0043 public:
0044 using result_type = std::uint64_t;
0045 using seed_type = std::uint64_t;
0046
0047
0048 static constexpr bool has_fixed_range {false};
0049
0050
0051 void seed(result_type value = 0) noexcept
0052 {
0053 if (value == 0)
0054 {
0055 state_ = UINT64_C(0xA164B43C8F634A13);
0056 }
0057 else
0058 {
0059 state_ = value;
0060 }
0061 }
0062
0063
0064
0065
0066 template <typename Sseq, typename std::enable_if<!std::is_convertible<Sseq, std::uint64_t>::value, bool>::type = true>
0067 void seed(Sseq& seq)
0068 {
0069 std::array<std::uint32_t, 2> seeds;
0070 seq.generate(seeds.begin(), seeds.end());
0071
0072 state_ = concatenate(seeds[0], seeds[1]);
0073 }
0074
0075
0076
0077
0078 template <typename Sseq, typename std::enable_if<!std::is_convertible<Sseq, splitmix64>::value, bool>::type = true>
0079 explicit splitmix64(Sseq& seq)
0080 {
0081 seed(seq);
0082 }
0083
0084
0085 template <typename T, typename std::enable_if<std::is_convertible<T, std::uint64_t>::value, bool>::type = true>
0086 void seed(T value = 0) noexcept
0087 {
0088 seed(static_cast<std::uint64_t>(value));
0089 }
0090
0091
0092 explicit splitmix64(std::uint64_t state = 0) noexcept
0093 {
0094 seed(state);
0095 }
0096
0097 splitmix64(const splitmix64& other) = default;
0098 splitmix64& operator=(const splitmix64& other) = default;
0099
0100
0101 inline result_type next() noexcept
0102 {
0103 std::uint64_t z {state_ += UINT64_C(0x9E3779B97F4A7C15)};
0104 z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
0105 z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
0106
0107 return z ^ (z >> 31);
0108 }
0109
0110
0111 inline result_type operator()() noexcept
0112 {
0113 return next();
0114 }
0115
0116
0117 inline void discard(std::uint64_t z) noexcept
0118 {
0119 state_ += z * UINT64_C(0x9E3779B97F4A7C15);
0120 }
0121
0122
0123
0124
0125
0126 inline friend bool operator==(const splitmix64& lhs, const splitmix64& rhs) noexcept
0127 {
0128 return lhs.state_ == rhs.state_;
0129 }
0130
0131
0132
0133
0134
0135 inline friend bool operator!=(const splitmix64& lhs, const splitmix64& rhs) noexcept
0136 {
0137 return !(lhs == rhs);
0138 }
0139
0140
0141 template <typename CharT, typename Traits>
0142 inline friend std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& ost,
0143 const splitmix64& e)
0144 {
0145 ost << e.state_;
0146 return ost;
0147 }
0148
0149
0150 template <typename CharT, typename Traits>
0151 inline friend std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& ist,
0152 splitmix64& e)
0153 {
0154 std::string sstate;
0155 CharT val;
0156 while (ist >> val)
0157 {
0158 if (std::isdigit(val))
0159 {
0160 sstate.push_back(val);
0161 }
0162 }
0163
0164 e.state_ = std::strtoull(sstate.c_str(), nullptr, 10);
0165
0166 return ist;
0167 }
0168
0169
0170 template <typename FIter>
0171 inline void generate(FIter first, FIter last) noexcept
0172 {
0173 while (first != last)
0174 {
0175 *first++ = next();
0176 }
0177 }
0178
0179
0180
0181
0182
0183 static constexpr result_type (max)() noexcept
0184 {
0185 return (std::numeric_limits<std::uint64_t>::max)();
0186 }
0187
0188
0189
0190
0191
0192 static constexpr result_type (min)() noexcept
0193 {
0194 return (std::numeric_limits<std::uint64_t>::min)();
0195 }
0196 };
0197
0198 }}
0199
0200 #endif