1 ///////////////////////////////////////////////////////////////
2 // Copyright 2018 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
6 // Contains Quickbook snippets used by boost/libs/multiprecision/doc/multiprecision.qbk,
7 // used in section Literal Types and constexpr Support, last example on constexpr randoms.
9 // A implementation and demonstration of the Keep It Simple Stupid random number generator algorithm https://en.wikipedia.org/wiki/KISS_(algorithm) for cpp_int integers.
10 // b2 --abbreviate-paths toolset=clang-9.0.0 address-model=64 cxxstd=2a release misc > multiprecision_clang_misc.log
12 #include <boost/multiprecision/cpp_int.hpp>
18 typedef std::uint64_t result_type
;
20 constexpr kiss_rand() : x(0x8207ebe160468b32uLL
), y(0x2871283e01d45bbduLL
), z(0x9c80bfd5db9680c9uLL
), c(0x2e2683c2abb878b8uLL
) {}
21 constexpr kiss_rand(std::uint64_t seed
) : x(seed
), y(0x2871283e01d45bbduLL
), z(0x9c80bfd5db9680c9uLL
), c(0x2e2683c2abb878b8uLL
) {}
22 constexpr kiss_rand(std::uint64_t seed_x
, std::uint64_t seed_y
) : x(seed_x
), y(seed_y
), z(0x9c80bfd5db9680c9uLL
), c(0x2e2683c2abb878b8uLL
) {}
23 constexpr kiss_rand(std::uint64_t seed_x
, std::uint64_t seed_y
, std::uint64_t seed_z
) : x(seed_x
), y(seed_y
), z(seed_z
), c(0x2e2683c2abb878b8uLL
) {}
25 constexpr std::uint64_t operator()()
27 return MWC() + XSH() + CNG();
31 constexpr std::uint64_t MWC()
33 std::uint64_t t
= (x
<< 58) + c
;
39 constexpr std::uint64_t XSH()
43 return y
^= (y
<< 43);
45 constexpr std::uint64_t CNG()
47 return z
= 6906969069LL * z
+ 1234567;
49 std::uint64_t x
, y
, z
, c
;
52 inline constexpr void hash_combine(std::uint64_t& h
, std::uint64_t k
)
54 constexpr const std::uint64_t m
= 0xc6a4a7935bd1e995uLL
;
55 constexpr const int r
= 47;
64 // Completely arbitrary number, to prevent 0's from hashing to 0.
68 template <std::size_t N
>
69 inline constexpr std::uint64_t string_to_hash(const char (&s
)[N
])
71 std::uint64_t hash(0);
72 for (unsigned i
= 0; i
< N
; ++i
)
73 hash_combine(hash
, s
[i
]);
77 template <class UnsignedInteger
>
78 struct multiprecision_generator
80 typedef UnsignedInteger result_type
;
81 constexpr multiprecision_generator(std::uint64_t seed1
) : m_gen64(seed1
) {}
82 constexpr multiprecision_generator(std::uint64_t seed1
, std::uint64_t seed2
) : m_gen64(seed1
, seed2
) {}
83 constexpr multiprecision_generator(std::uint64_t seed1
, std::uint64_t seed2
, std::uint64_t seed3
) : m_gen64(seed1
, seed2
, seed3
) {}
85 static constexpr result_type (min
)()
89 static constexpr result_type (max
)()
91 return ~result_type(0u);
93 constexpr result_type
operator()()
95 result_type
result(m_gen64());
97 while (digits
< std::numeric_limits
<result_type
>::digits
)
110 template <class UnsignedInteger
>
111 constexpr UnsignedInteger
nth_random_value(unsigned count
= 0)
113 std::uint64_t date_hash
= string_to_hash(__DATE__
);
114 std::uint64_t time_hash
= string_to_hash(__TIME__
);
115 multiprecision_generator
<UnsignedInteger
> big_gen(date_hash
, time_hash
);
116 for (unsigned i
= 0; i
< count
; ++i
)
123 using namespace boost::multiprecision
;
125 //[random_constexpr_cppint
126 constexpr uint1024_t rand
= nth_random_value
<uint1024_t
>(1000);
127 std::cout
<< std::hex
<< rand
<< std::endl
;
128 //] [/random_constexpr_cppint]