File: constexpr_test_cpp_int_7.cpp

package info (click to toggle)
boost1.74 1.74.0-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 464,084 kB
  • sloc: cpp: 3,338,324; xml: 131,293; python: 33,088; ansic: 14,336; asm: 4,034; sh: 3,351; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (130 lines) | stat: -rw-r--r-- 4,060 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
///////////////////////////////////////////////////////////////
//  Copyright 2018 John Maddock. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).

// Contains Quickbook snippets used by boost/libs/multiprecision/doc/multiprecision.qbk,
// used in section Literal Types and constexpr Support, last example on constexpr randoms.

// 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.
// b2 --abbreviate-paths toolset=clang-9.0.0 address-model=64 cxxstd=2a release misc > multiprecision_clang_misc.log

#include <boost/multiprecision/cpp_int.hpp>

#include <iostream>

struct kiss_rand
{
   typedef std::uint64_t result_type;

   constexpr kiss_rand() : x(0x8207ebe160468b32uLL), y(0x2871283e01d45bbduLL), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
   constexpr kiss_rand(std::uint64_t seed) : x(seed), y(0x2871283e01d45bbduLL), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
   constexpr kiss_rand(std::uint64_t seed_x, std::uint64_t seed_y) : x(seed_x), y(seed_y), z(0x9c80bfd5db9680c9uLL), c(0x2e2683c2abb878b8uLL) {}
   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) {}

   constexpr std::uint64_t operator()()
   {
      return MWC() + XSH() + CNG();
   }

 private:
   constexpr std::uint64_t MWC()
   {
      std::uint64_t t = (x << 58) + c;
      c               = (x >> 6);
      x += t;
      c += (x < t);
      return x;
   }
   constexpr std::uint64_t XSH()
   {
      y ^= (y << 13);
      y ^= (y >> 17);
      return y ^= (y << 43);
   }
   constexpr std::uint64_t CNG()
   {
      return z = 6906969069LL * z + 1234567;
   }
   std::uint64_t x, y, z, c;
};

inline constexpr void hash_combine(std::uint64_t& h, std::uint64_t k)
{
   constexpr const std::uint64_t m = 0xc6a4a7935bd1e995uLL;
   constexpr const int           r = 47;

   k *= m;
   k ^= k >> r;
   k *= m;

   h ^= k;
   h *= m;

   // Completely arbitrary number, to prevent 0's from hashing to 0.
   h += 0xe6546b64;
}

template <std::size_t N>
inline constexpr std::uint64_t string_to_hash(const char (&s)[N])
{
   std::uint64_t hash(0);
   for (unsigned i = 0; i < N; ++i)
      hash_combine(hash, s[i]);
   return hash;
}

template <class UnsignedInteger>
struct multiprecision_generator
{
   typedef UnsignedInteger result_type;
   constexpr               multiprecision_generator(std::uint64_t seed1) : m_gen64(seed1) {}
   constexpr               multiprecision_generator(std::uint64_t seed1, std::uint64_t seed2) : m_gen64(seed1, seed2) {}
   constexpr               multiprecision_generator(std::uint64_t seed1, std::uint64_t seed2, std::uint64_t seed3) : m_gen64(seed1, seed2, seed3) {}

   static constexpr result_type (min)()
   {
      return 0u;
   }
   static constexpr result_type (max)()
   {
      return ~result_type(0u);
   }
   constexpr result_type operator()()
   {
      result_type result(m_gen64());
      unsigned    digits = 64;
      while (digits < std::numeric_limits<result_type>::digits)
      {
         result <<= 64;
         result |= m_gen64();
         digits += 64;
      }
      return result;
   }

 private:
   kiss_rand m_gen64;
};

template <class UnsignedInteger>
constexpr UnsignedInteger nth_random_value(unsigned count = 0)
{
   std::uint64_t                             date_hash = string_to_hash(__DATE__);
   std::uint64_t                             time_hash = string_to_hash(__TIME__);
   multiprecision_generator<UnsignedInteger> big_gen(date_hash, time_hash);
   for (unsigned i = 0; i < count; ++i)
      big_gen();
   return big_gen();
}

int main()
{
   using namespace boost::multiprecision;

//[random_constexpr_cppint
   constexpr uint1024_t rand = nth_random_value<uint1024_t>(1000);
   std::cout << std::hex << rand << std::endl;
//] [/random_constexpr_cppint]
   return 0;
}