QtBase  v6.3.1
qrandom.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 Intel Corporation.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QRANDOM_H
41 #define QRANDOM_H
42 
43 #include <QtCore/qalgorithms.h>
44 #include <algorithm> // for std::generate
45 #include <random> // for std::mt19937
46 
47 #ifdef min
48 # undef min
49 #endif
50 #ifdef max
51 # undef max
52 #endif
53 
55 
57 {
58  // restrict the template parameters to unsigned integers 32 bits wide or larger
59  template <typename UInt> using IfValidUInt =
60  typename std::enable_if<std::is_unsigned<UInt>::value && sizeof(UInt) >= sizeof(uint), bool>::type;
61 public:
62  QRandomGenerator(quint32 seedValue = 1)
63  : QRandomGenerator(&seedValue, 1)
64  {}
65  template <qsizetype N> QRandomGenerator(const quint32 (&seedBuffer)[N])
66  : QRandomGenerator(seedBuffer, seedBuffer + N)
67  {}
68  QRandomGenerator(const quint32 *seedBuffer, qsizetype len)
69  : QRandomGenerator(seedBuffer, seedBuffer + len)
70  {}
71  Q_CORE_EXPORT QRandomGenerator(std::seed_seq &sseq) noexcept;
72  Q_CORE_EXPORT QRandomGenerator(const quint32 *begin, const quint32 *end);
73 
74  // copy constructor & assignment operator (move unnecessary)
75  Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other);
76  Q_CORE_EXPORT QRandomGenerator &operator=(const QRandomGenerator &other);
77 
78  friend Q_CORE_EXPORT bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2);
79  friend bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
80  {
81  return !(rng1 == rng2);
82  }
83 
85  {
86  return quint32(_fillRange(nullptr, 1));
87  }
88 
90  {
91  return _fillRange(nullptr, sizeof(quint64) / sizeof(quint32));
92  }
93 
94  double generateDouble()
95  {
96  // IEEE 754 double precision has:
97  // 1 bit sign
98  // 10 bits exponent
99  // 53 bits mantissa
100  // In order for our result to be normalized in the range [0, 1), we
101  // need exactly 53 bits of random data. Use generate64() to get enough.
102  quint64 x = generate64();
103  quint64 limit = Q_UINT64_C(1) << std::numeric_limits<double>::digits;
104  x >>= std::numeric_limits<quint64>::digits - std::numeric_limits<double>::digits;
105  return double(x) / double(limit);
106  }
107 
108  double bounded(double highest)
109  {
110  return generateDouble() * highest;
111  }
112 
114  {
115  quint64 value = generate();
116  value *= highest;
117  value /= (max)() + quint64(1);
118  return quint32(value);
119  }
120 
121  quint32 bounded(quint32 lowest, quint32 highest)
122  {
123  Q_ASSERT(highest > lowest);
124  return bounded(highest - lowest) + lowest;
125  }
126 
127  int bounded(int highest)
128  {
129  Q_ASSERT(highest > 0);
130  return int(bounded(0U, quint32(highest)));
131  }
132 
133  int bounded(int lowest, int highest)
134  {
135  return bounded(highest - lowest) + lowest;
136  }
137 
138  quint64 bounded(quint64 highest);
139 
140  quint64 bounded(quint64 lowest, quint64 highest)
141  {
142  Q_ASSERT(highest > lowest);
143  return bounded(highest - lowest) + lowest;
144  }
145 
147  {
148  Q_ASSERT(highest > 0);
149  return qint64(bounded(quint64(0), quint64(highest)));
150  }
151 
152  qint64 bounded(qint64 lowest, qint64 highest)
153  {
154  return bounded(highest - lowest) + lowest;
155  }
156 
157  // these functions here only to help with ambiguous overloads
158  qint64 bounded(int lowest, qint64 highest)
159  {
160  return bounded(qint64(lowest), qint64(highest));
161  }
162  qint64 bounded(qint64 lowest, int highest)
163  {
164  return bounded(qint64(lowest), qint64(highest));
165  }
166 
167  quint64 bounded(unsigned lowest, quint64 highest)
168  {
169  return bounded(quint64(lowest), quint64(highest));
170  }
171  quint64 bounded(quint64 lowest, unsigned highest)
172  {
173  return bounded(quint64(lowest), quint64(highest));
174  }
175 
176  template <typename UInt, IfValidUInt<UInt> = true>
178  {
179  _fillRange(buffer, count * sizeof(UInt) / sizeof(quint32));
180  }
181 
182  template <typename UInt, size_t N, IfValidUInt<UInt> = true>
183  void fillRange(UInt (&buffer)[N])
184  {
185  _fillRange(buffer, N * sizeof(UInt) / sizeof(quint32));
186  }
187 
188  // API like std::seed_seq
189  template <typename ForwardIterator>
190  void generate(ForwardIterator begin, ForwardIterator end)
191  {
192  std::generate(begin, end, [this]() { return generate(); });
193  }
194 
196  {
197  _fillRange(begin, end - begin);
198  }
199 
200  // API like std:: random engines
203  void seed(quint32 s = 1) { *this = { s }; }
204  void seed(std::seed_seq &sseq) noexcept { *this = { sseq }; }
205  Q_CORE_EXPORT void discard(unsigned long long z);
206  static constexpr result_type min() { return (std::numeric_limits<result_type>::min)(); }
207  static constexpr result_type max() { return (std::numeric_limits<result_type>::max)(); }
208 
211  static inline QRandomGenerator securelySeeded();
212 
213 protected:
214  enum System {};
216 
217 private:
218  Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);
219 
220  struct InitialRandomData {
221  quintptr data[16 / sizeof(quintptr)];
222  };
223  friend InitialRandomData qt_initial_random_value() noexcept;
224  friend class QRandomGenerator64;
225  struct SystemGenerator;
227  using RandomEngine = std::mersenne_twister_engine<quint32,
228  32,624,397,31,0x9908b0df,11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253>;
229 
230  union Storage {
231  uint dummy;
232  RandomEngine twister;
233  RandomEngine &engine() { return twister; }
234  const RandomEngine &engine() const { return twister; }
235 
237  "std::mersenne_twister not trivially destructible as expected");
238  constexpr Storage();
239  };
240  uint type;
241  Storage storage;
242 };
243 
245 {
247 public:
248  // unshadow generate() overloads, since we'll override.
250  quint64 generate() { return generate64(); }
251 
254 
255 #ifndef Q_QDOC
257  : QRandomGenerator(seedValue)
258  {}
259  template <qsizetype N> QRandomGenerator64(const quint32 (&seedBuffer)[N])
260  : QRandomGenerator(seedBuffer)
261  {}
263  : QRandomGenerator(seedBuffer, len)
264  {}
265  QRandomGenerator64(std::seed_seq &sseq) noexcept
267  {}
270  {}
272 
273  void discard(unsigned long long z)
274  {
275  Q_ASSERT_X(z * 2 > z, "QRandomGenerator64::discard",
276  "Overflow. Are you sure you want to skip over 9 quintillion samples?");
278  }
279 
280  static constexpr result_type min() { return (std::numeric_limits<result_type>::min)(); }
281  static constexpr result_type max() { return (std::numeric_limits<result_type>::max)(); }
282  static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *system();
283  static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 *global();
284  static Q_CORE_EXPORT QRandomGenerator64 securelySeeded();
285 #endif // Q_QDOC
286 };
287 
289 {
290  // Implement an algorithm similar to libc++'s uniform_int_distribution:
291  // loop around getting a random number, mask off any bits that "highest"
292  // will never need, then check if it's higher than "highest". The number of
293  // times the loop will run is unbounded but the probability of terminating
294  // is better than 1/2 on each iteration. Therefore, the average loop count
295  // should be less than 2.
296 
297  const int width = qCountLeadingZeroBits(highest - 1);
298  const quint64 mask = (quint64(1) << (std::numeric_limits<quint64>::digits - width)) - 1;
299  quint64 v;
300  do {
301  v = generate64() & mask;
302  } while (v >= highest);
303  return v;
304 }
305 
307 {
309 }
310 
312 {
314 }
315 
317 {
319 }
320 
322 
323 #endif // QRANDOM_H
#define value
[5]
The QRandomGenerator64 class allows one to obtain 64-bit random values from a high-quality,...
Definition: qrandom.h:245
void discard(unsigned long long z)
Definition: qrandom.h:273
static Q_CORE_EXPORT QRandomGenerator64 securelySeeded()
Definition: qrandom.cpp:1188
result_type operator()()
Definition: qrandom.h:253
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 * global()
Definition: qrandom.cpp:1170
static constexpr result_type min()
Definition: qrandom.h:280
QRandomGenerator64(std::seed_seq &sseq) noexcept
Definition: qrandom.h:265
quint64 result_type
Definition: qrandom.h:252
QRandomGenerator64(const QRandomGenerator &other)
Definition: qrandom.h:271
quint64 generate()
Definition: qrandom.h:250
QRandomGenerator64(quint32 seedValue=1)
Definition: qrandom.h:256
QRandomGenerator64(const quint32 *begin, const quint32 *end)
Definition: qrandom.h:268
QRandomGenerator64(const quint32 *seedBuffer, qsizetype len)
Definition: qrandom.h:262
static constexpr result_type max()
Definition: qrandom.h:281
QRandomGenerator64(const quint32(&seedBuffer)[N])
Definition: qrandom.h:259
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 * system()
Definition: qrandom.cpp:1163
The QRandomGenerator class allows one to obtain random values from a high-quality Random Number Gener...
Definition: qrandom.h:57
friend InitialRandomData qt_initial_random_value() noexcept
Definition: qrandom.cpp:1324
friend class QRandomGenerator64
Definition: qrandom.h:224
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
Definition: qrandom.h:306
void fillRange(UInt(&buffer)[N])
Definition: qrandom.h:183
Q_CORE_EXPORT QRandomGenerator & operator=(const QRandomGenerator &other)
Definition: qrandom.cpp:1216
qint64 bounded(qint64 highest)
Definition: qrandom.h:146
double generateDouble()
Definition: qrandom.h:94
quint64 bounded(quint64 lowest, unsigned highest)
Definition: qrandom.h:171
Q_CORE_EXPORT void discard(unsigned long long z)
Definition: qrandom.cpp:1247
QRandomGenerator(quint32 seedValue=1)
Definition: qrandom.h:62
void generate(quint32 *begin, quint32 *end)
Definition: qrandom.h:195
QRandomGenerator(const quint32 *seedBuffer, qsizetype len)
Definition: qrandom.h:68
quint32 generate()
Definition: qrandom.h:84
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
Definition: qrandom.h:311
int bounded(int highest)
Definition: qrandom.h:127
quint64 generate64()
Definition: qrandom.h:89
static constexpr result_type max()
Definition: qrandom.h:207
qint64 bounded(int lowest, qint64 highest)
Definition: qrandom.h:158
double bounded(double highest)
Definition: qrandom.h:108
quint64 bounded(quint64 lowest, quint64 highest)
Definition: qrandom.h:140
quint32 result_type
Definition: qrandom.h:201
friend Q_CORE_EXPORT bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition: qrandom.cpp:1256
void generate(ForwardIterator begin, ForwardIterator end)
Definition: qrandom.h:190
quint32 bounded(quint32 lowest, quint32 highest)
Definition: qrandom.h:121
void seed(std::seed_seq &sseq) noexcept
Definition: qrandom.h:204
static constexpr result_type min()
Definition: qrandom.h:206
qint64 bounded(qint64 lowest, qint64 highest)
Definition: qrandom.h:152
quint32 bounded(quint32 highest)
Definition: qrandom.h:113
friend bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition: qrandom.h:79
QRandomGenerator(const quint32(&seedBuffer)[N])
Definition: qrandom.h:65
quint64 bounded(unsigned lowest, quint64 highest)
Definition: qrandom.h:167
static QRandomGenerator securelySeeded()
Definition: qrandom.h:316
result_type operator()()
Definition: qrandom.h:202
qint64 bounded(qint64 lowest, int highest)
Definition: qrandom.h:162
int bounded(int lowest, int highest)
Definition: qrandom.h:133
void fillRange(UInt *buffer, qsizetype count)
Definition: qrandom.h:177
void seed(quint32 s=1)
Definition: qrandom.h:203
unsigned int UInt
Definition: ftraster.c:308
auto generate(StringRef generatorName, SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
Definition: catch_p_p.h:4085
Definition: qfloat16.h:381
QT_POPCOUNT_RELAXED_CONSTEXPR uint qCountLeadingZeroBits(quint32 v) noexcept
Definition: qalgorithms.h:411
#define Q_DECL_CONST_FUNCTION
EGLOutputLayerEXT EGLint EGLAttrib value
#define Q_UINT64_C(c)
Definition: qglobal.h:296
unsigned int quint32
Definition: qglobal.h:288
size_t quintptr
Definition: qglobal.h:310
ptrdiff_t qptrdiff
Definition: qglobal.h:307
unsigned long long quint64
Definition: qglobal.h:299
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
GLenum type
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLuint GLuint end
GLenum GLenum GLsizei count
GLenum GLuint buffer
GLint GLsizei width
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLenum GLsizei len
Definition: qopenglext.h:3292
GLint limit
Definition: qopenglext.h:9975
GLdouble s
[6]
Definition: qopenglext.h:235
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
std::seed_seq sseq(seedBuffer, seedBuffer+len)
[3]
QSharedPointer< T > other(t)
[5]
QThreadStorage< int * > dummy[8]