Qrack  9.13
General classical-emulating-quantum development framework
rdrandwrapper.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // This class allows access to on-chip RNG capabilities. The class is adapted from these two sources:
6 // https://codereview.stackexchange.com/questions/147656/checking-if-cpu-supports-rdrand/150230
7 // https://stackoverflow.com/questions/45460146/how-to-use-intels-rdrand-using-inline-assembly-with-net
8 //
9 // Licensed under the GNU Lesser General Public License V3.
10 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
11 // for details.
12 
13 #pragma once
14 
15 #include "qrack_types.hpp"
16 
17 #if ENABLE_DEVRAND
18 #include <sys/random.h>
19 #endif
20 
21 #if ENABLE_RDRAND
22 #if _MSC_VER
23 #include <intrin.h>
24 #else
25 #include <cpuid.h>
26 #endif
27 #include <immintrin.h>
28 #endif
29 
30 #if ENABLE_RNDFILE
31 #include <vector>
32 #endif
33 
34 namespace Qrack {
35 
37 private:
39 
42  {
43  // Intentionally left blank
44  }
45 
47  {
48 #if ENABLE_RDRAND
49  constexpr unsigned flag_RDRAND = (1 << 30);
50 
51 #if _MSC_VER
52  int ex[4];
53  __cpuid(ex, 1);
54 
55  return ((ex[2] & flag_RDRAND) == flag_RDRAND);
56 #else
57  unsigned eax, ebx, ecx, edx;
58  ecx = 0;
59  __get_cpuid(1, &eax, &ebx, &ecx, &edx);
60 
61  return ((ecx & flag_RDRAND) == flag_RDRAND);
62 #endif
63 
64 #else
65  return false;
66 #endif
67  }
68 
69 public:
70  // See https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
73  {
74  static RandSupportSingleton instance;
75  return instance;
76  }
78  void operator=(RandSupportSingleton const&) = delete;
79 
80  bool SupportsRDRAND() { return isSupported; }
81 };
82 
83 #if ENABLE_RNDFILE && !ENABLE_DEVRAND
84 // See https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
85 class RandFile {
86 public:
87  static RandFile& getInstance()
88  {
89  static RandFile instance;
90  return instance;
91  }
92 
93  unsigned NextRaw()
94  {
95  size_t fSize = 0;
96  unsigned v;
97  while (!fSize) {
98  fSize = fread(&v, sizeof(unsigned), 1, dataFile);
99  if (!fSize) {
100  _readNextRandDataFile();
101  }
102  }
103 
104  return v;
105  }
106 
107 private:
108  RandFile() { _readNextRandDataFile(); }
109  ~RandFile()
110  {
111  if (dataFile) {
112  fclose(dataFile);
113  }
114  }
115 
116  size_t fileOffset;
117  FILE* dataFile;
118  void _readNextRandDataFile();
119 
120 public:
121  RandFile(RandFile const&) = delete;
122  void operator=(RandFile const&) = delete;
123 };
124 #endif
125 
126 class RdRandom {
127 private:
128  bool getRdRand(unsigned* pv)
129  {
130 #if ENABLE_RDRAND || ENABLE_DEVRAND
131  constexpr int max_rdrand_tries = 10;
132  for (int i = 0; i < max_rdrand_tries; ++i) {
133 #if ENABLE_DEVRAND
134  if (sizeof(unsigned) == getrandom(reinterpret_cast<char*>(pv), sizeof(unsigned), 0))
135 #else
136  if (_rdrand32_step(pv))
137 #endif
138  return true;
139  }
140 #endif
141  return false;
142  }
143 
144 public:
146 
147 #if ENABLE_RNDFILE && !ENABLE_DEVRAND
148  unsigned NextRaw() { return RandFile::getInstance().NextRaw(); }
149 #else
150  unsigned NextRaw()
151  {
152  unsigned v;
153  if (!getRdRand(&v)) {
154  throw std::runtime_error("Random number generator failed up to retry limit.");
155  }
156 
157  return v;
158  }
159 #endif
160 
162  {
163  constexpr double inc = 1.0 / (double)(1ULL << 32U);
164 
165  // NextRaw() has 32 bits; double has >= 53 bits of precision
166 #if FPPOW < 6
167  return (real1_f)(((double)NextRaw()) * inc);
168 #else
169  return ((((double)NextRaw()) * inc) + ((double)NextRaw())) * inc;
170 #endif
171  }
172 };
173 } // namespace Qrack
Definition: rdrandwrapper.hpp:36
bool SupportsRDRAND()
Definition: rdrandwrapper.hpp:80
static bool CheckHardwareRDRANDSupport()
Definition: rdrandwrapper.hpp:46
RandSupportSingleton()
Definition: rdrandwrapper.hpp:40
RandSupportSingleton(RandSupportSingleton const &)=delete
bool isSupported
Definition: rdrandwrapper.hpp:38
static RandSupportSingleton & Instance()
Get a pointer to the Instance of the singleton. (The instance will be instantiated,...
Definition: rdrandwrapper.hpp:72
void operator=(RandSupportSingleton const &)=delete
Definition: rdrandwrapper.hpp:126
bool getRdRand(unsigned *pv)
Definition: rdrandwrapper.hpp:128
unsigned NextRaw()
Definition: rdrandwrapper.hpp:150
real1_f Next()
Definition: rdrandwrapper.hpp:161
bool SupportsRDRAND()
Definition: rdrandwrapper.hpp:145
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
float real1_f
Definition: qrack_types.hpp:95