Qrack  10.0
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  return ((ex[2] & flag_RDRAND) == flag_RDRAND);
55 #else
56  unsigned eax, ebx, ecx, edx;
57  ecx = 0;
58  __get_cpuid(1, &eax, &ebx, &ecx, &edx);
59  return ((ecx & flag_RDRAND) == flag_RDRAND);
60 #endif
61 
62 #else
63  return false;
64 #endif
65  }
66 
67 public:
68  // See https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
71  {
72  static RandSupportSingleton instance;
73  return instance;
74  }
76  void operator=(RandSupportSingleton const&) = delete;
77 
78  bool SupportsRDRAND() { return isSupported; }
79 };
80 
81 #if ENABLE_RNDFILE && !ENABLE_DEVRAND
82 // See https://stackoverflow.com/questions/1008019/c-singleton-design-pattern
83 class RandFile {
84 public:
85  static RandFile& getInstance()
86  {
87  static RandFile instance;
88  return instance;
89  }
90 
91  unsigned NextRaw()
92  {
93  size_t fSize = 0;
94  unsigned v;
95  while (!fSize) {
96  fSize = fread(&v, sizeof(unsigned), 1, dataFile);
97  if (!fSize) {
98  _readNextRandDataFile();
99  }
100  }
101  return v;
102  }
103 
104 private:
105  RandFile() { _readNextRandDataFile(); }
106  ~RandFile()
107  {
108  if (dataFile) {
109  fclose(dataFile);
110  }
111  }
112 
113  size_t fileOffset;
114  FILE* dataFile;
115  void _readNextRandDataFile();
116 
117 public:
118  RandFile(RandFile const&) = delete;
119  void operator=(RandFile const&) = delete;
120 };
121 #endif
122 
123 class RdRandom {
124 private:
125  bool getRdRand(unsigned* pv)
126  {
127 #if ENABLE_RDRAND || ENABLE_DEVRAND
128  constexpr int max_rdrand_tries = 10;
129  for (int i = 0; i < max_rdrand_tries; ++i) {
130 #if ENABLE_DEVRAND
131  if (sizeof(unsigned) == getrandom(reinterpret_cast<char*>(pv), sizeof(unsigned), 0))
132 #else
133  if (_rdrand32_step(pv))
134 #endif
135  return true;
136  }
137 #endif
138 
139  return false;
140  }
141 
142 public:
144 
145 #if ENABLE_RNDFILE && !ENABLE_DEVRAND
146  unsigned NextRaw() { return RandFile::getInstance().NextRaw(); }
147 #else
148  unsigned NextRaw()
149  {
150  unsigned v;
151  if (!getRdRand(&v)) {
152  throw std::runtime_error("Random number generator failed up to retry limit.");
153  }
154 
155  return v;
156  }
157 #endif
158 
160  {
161  // NextRaw() has 32 bits; double has >= 53 bits of precision
162  constexpr double inc = 1.0 / (double)(1ULL << 32U);
163 #if FPPOW < 6
164  return (real1_f)(((double)NextRaw()) * inc);
165 #else
166  return ((((double)NextRaw()) * inc) + ((double)NextRaw())) * inc;
167 #endif
168  }
169 };
170 } // namespace Qrack
Definition: rdrandwrapper.hpp:36
bool SupportsRDRAND()
Definition: rdrandwrapper.hpp:78
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:70
void operator=(RandSupportSingleton const &)=delete
Definition: rdrandwrapper.hpp:123
bool getRdRand(unsigned *pv)
Definition: rdrandwrapper.hpp:125
unsigned NextRaw()
Definition: rdrandwrapper.hpp:148
real1_f Next()
Definition: rdrandwrapper.hpp:159
bool SupportsRDRAND()
Definition: rdrandwrapper.hpp:143
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:103