Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / multiprecision / test / constexpr_test_cpp_int_7.cpp
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_
5
6 #include <boost/multiprecision/cpp_int.hpp>
7 #include <iostream>
8
9 struct kiss_rand
10 {
11    typedef std::uint64_t result_type;
12
13    constexpr kiss_rand() : x(0x8207ebe160468b32uLL), y(0x2871283e01d45bbduLL), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
14    constexpr kiss_rand(std::uint64_t seed) : x(seed), y(0x2871283e01d45bbduLL), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
15    constexpr kiss_rand(std::uint64_t seed_x, std::uint64_t seed_y) : x(seed_x), y(seed_y), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
16    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) {}
17
18    constexpr std::uint64_t operator()()
19    {
20       return MWC() + XSH() + CNG();
21    }
22
23  private:
24    constexpr std::uint64_t MWC()
25    {
26       std::uint64_t t = (x << 58) + c;
27       c               = (x >> 6);
28       x += t;
29       c += (x < t);
30       return x;
31    }
32    constexpr std::uint64_t XSH()
33    {
34       y ^= (y << 13);
35       y ^= (y >> 17);
36       return y ^= (y << 43);
37    }
38    constexpr std::uint64_t CNG()
39    {
40       return z = 6906969069LL * z + 1234567;
41    }
42    std::uint64_t x, y, z, c;
43 };
44
45 inline constexpr void hash_combine(std::uint64_t& h, std::uint64_t k)
46 {
47    constexpr const std::uint64_t m = 0xc6a4a7935bd1e995uLL;
48    constexpr const int           r = 47;
49
50    k *= m;
51    k ^= k >> r;
52    k *= m;
53
54    h ^= k;
55    h *= m;
56
57    // Completely arbitrary number, to prevent 0's
58    // from hashing to 0.
59    h += 0xe6546b64;
60 }
61
62 template <std::size_t N>
63 inline constexpr std::uint64_t string_to_hash(const char (&s)[N])
64 {
65    std::uint64_t hash(0);
66    for (unsigned i = 0; i < N; ++i)
67       hash_combine(hash, s[i]);
68    return hash;
69 }
70
71 template <class UnsignedInteger>
72 struct multiprecision_generator
73 {
74    typedef UnsignedInteger result_type;
75    constexpr               multiprecision_generator(std::uint64_t seed1) : m_gen64(seed1) {}
76    constexpr               multiprecision_generator(std::uint64_t seed1, std::uint64_t seed2) : m_gen64(seed1, seed2) {}
77    constexpr               multiprecision_generator(std::uint64_t seed1, std::uint64_t seed2, std::uint64_t seed3) : m_gen64(seed1, seed2, seed3) {}
78
79    static constexpr result_type (min)()
80    {
81       return 0u;
82    }
83    static constexpr result_type (max)()
84    {
85       return ~result_type(0u);
86    }
87    constexpr result_type operator()()
88    {
89       result_type result(m_gen64());
90       unsigned    digits = 64;
91       while (digits < std::numeric_limits<result_type>::digits)
92       {
93          result <<= 64;
94          result |= m_gen64();
95          digits += 64;
96       }
97       return result;
98    }
99
100  private:
101    kiss_rand m_gen64;
102 };
103
104 template <class UnsignedInteger>
105 constexpr UnsignedInteger nth_random_value(unsigned count = 0)
106 {
107    std::uint64_t                             date_hash = string_to_hash(__DATE__);
108    std::uint64_t                             time_hash = string_to_hash(__TIME__);
109    multiprecision_generator<UnsignedInteger> big_gen(date_hash, time_hash);
110    for (unsigned i = 0; i < count; ++i)
111       big_gen();
112    return big_gen();
113 }
114
115 int main()
116 {
117    using namespace boost::multiprecision;
118
119    constexpr uint1024_t rand = nth_random_value<uint1024_t>(1000);
120    std::cout << std::hex << rand << std::endl;
121    return 0;
122 }