File indexing completed on 2025-04-26 08:52:44
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 for (std::uint64_t i {}; i < z; ++i)
0120 {
0121 next();
0122 }
0123 }
0124
0125
0126
0127
0128
0129 inline friend bool operator==(const splitmix64& lhs, const splitmix64& rhs) noexcept
0130 {
0131 return lhs.state_ == rhs.state_;
0132 }
0133
0134
0135
0136
0137
0138 inline friend bool operator!=(const splitmix64& lhs, const splitmix64& rhs) noexcept
0139 {
0140 return !(lhs == rhs);
0141 }
0142
0143
0144 template <typename CharT, typename Traits>
0145 inline friend std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& ost,
0146 const splitmix64& e)
0147 {
0148 ost << e.state_;
0149 return ost;
0150 }
0151
0152
0153 template <typename CharT, typename Traits>
0154 inline friend std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& ist,
0155 splitmix64& e)
0156 {
0157 std::string sstate;
0158 CharT val;
0159 while (ist >> val)
0160 {
0161 if (std::isdigit(val))
0162 {
0163 sstate.push_back(val);
0164 }
0165 }
0166
0167 e.state_ = std::strtoull(sstate.c_str(), nullptr, 10);
0168
0169 return ist;
0170 }
0171
0172
0173 template <typename FIter>
0174 inline void generate(FIter first, FIter last) noexcept
0175 {
0176 while (first != last)
0177 {
0178 *first++ = next();
0179 }
0180 }
0181
0182
0183
0184
0185
0186 static constexpr result_type (max)() noexcept
0187 {
0188 return (std::numeric_limits<std::uint64_t>::max)();
0189 }
0190
0191
0192
0193
0194
0195 static constexpr result_type (min)() noexcept
0196 {
0197 return (std::numeric_limits<std::uint64_t>::min)();
0198 }
0199 };
0200
0201 }}
0202
0203 #endif