Branch data Line data Source code
1 : : // Copyright (c) 2022 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #ifndef BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H 6 : : #define BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H 7 : : 8 : : #include <cstdint> 9 : : #include <limits> 10 : : 11 : : /** xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes. 12 : : * 13 : : * Memory footprint is 128bit, period is 2^128 - 1. 14 : : * This class is not thread-safe. 15 : : * 16 : : * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c 17 : : * See https://prng.di.unimi.it/ 18 : : */ 19 : : class XoRoShiRo128PlusPlus 20 : : { 21 : : uint64_t m_s0; 22 : : uint64_t m_s1; 23 : : 24 : 0 : [[nodiscard]] constexpr static uint64_t rotl(uint64_t x, int n) 25 : : { 26 : 0 : return (x << n) | (x >> (64 - n)); 27 : : } 28 : : 29 : 0 : [[nodiscard]] constexpr static uint64_t SplitMix64(uint64_t& seedval) noexcept 30 : : { 31 : 0 : uint64_t z = (seedval += UINT64_C(0x9e3779b97f4a7c15)); 32 : 0 : z = (z ^ (z >> 30U)) * UINT64_C(0xbf58476d1ce4e5b9); 33 : 0 : z = (z ^ (z >> 27U)) * UINT64_C(0x94d049bb133111eb); 34 : 0 : return z ^ (z >> 31U); 35 : : } 36 : : 37 : : public: 38 : : using result_type = uint64_t; 39 : : 40 : 0 : constexpr explicit XoRoShiRo128PlusPlus(uint64_t seedval) noexcept 41 : 0 : : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) 42 : : { 43 : 0 : } 44 : : 45 : : // no copy - that is dangerous, we don't want accidentally copy the RNG and then have two streams 46 : : // with exactly the same results. If you need a copy, call copy(). 47 : : XoRoShiRo128PlusPlus(const XoRoShiRo128PlusPlus&) = delete; 48 : : XoRoShiRo128PlusPlus& operator=(const XoRoShiRo128PlusPlus&) = delete; 49 : : 50 : : // allow moves 51 : : XoRoShiRo128PlusPlus(XoRoShiRo128PlusPlus&&) = default; 52 : : XoRoShiRo128PlusPlus& operator=(XoRoShiRo128PlusPlus&&) = default; 53 : : 54 : : ~XoRoShiRo128PlusPlus() = default; 55 : : 56 : 0 : constexpr result_type operator()() noexcept 57 : : { 58 : 0 : uint64_t s0 = m_s0, s1 = m_s1; 59 [ # # ]: 0 : const uint64_t result = rotl(s0 + s1, 17) + s0; 60 : 0 : s1 ^= s0; 61 [ # # ]: 0 : m_s0 = rotl(s0, 49) ^ s1 ^ (s1 << 21); 62 [ # # ]: 0 : m_s1 = rotl(s1, 28); 63 : 0 : return result; 64 : : } 65 : : 66 : : static constexpr result_type min() noexcept { return std::numeric_limits<result_type>::min(); } 67 : : static constexpr result_type max() noexcept { return std::numeric_limits<result_type>::max(); } 68 : : static constexpr double entropy() noexcept { return 0.0; } 69 : : }; 70 : : 71 : : #endif // BITCOIN_TEST_UTIL_XOROSHIRO128PLUSPLUS_H