summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-10-23 19:16:34 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-11-11 08:11:07 +0000
commit08bf28de03f16e5b014b23e228dfc3cfc2ac7feb (patch)
tree0919b98368e7f6ed8faf7bb2fa71b1d711d09a27 /src/corelib
parentcfad4e298f4d65fe26c3a4109d19839bdfcd30c2 (diff)
QRandomGenerator: add more of the std Random Engine API
This brings us to almost parity with the C++11 Random Engine API requirements (see chapter 26.5.1.4 [rand.req.eng]). We don't implement the templated Sseq requirements because it would require moving the implementation details to the public API. And we don't implement the <iostreams> code because we don't want to. Change-Id: Icaa86fc7b54d4b368c0efffd14f05ff813ebd759 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qrandom.cpp90
-rw-r--r--src/corelib/global/qrandom.h24
2 files changed, 101 insertions, 13 deletions
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 2241dc7095..a9596df432 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -558,7 +558,15 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
QRandomGenerator is modeled after the requirements for random number
engines in the C++ Standard Library and may be used in almost all contexts
- that the Standard Library engines can.
+ that the Standard Library engines can. Exceptions to the requirements are
+ the following:
+
+ \list
+ \li QRandomGenerator does not support seeding from another seed
+ sequence-like class besides std::seed_seq itself;
+ \li QRandomGenerator is not comparable (but is copyable) or
+ streamable to \c{std::ostream} or from \c{std::istream}.
+ \endlist
QRandomGenerator is also compatible with the uniform distribution classes
\c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as
@@ -575,13 +583,13 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
*/
/*!
- \fn QRandomGenerator::QRandomGenerator(quint32 seed)
+ \fn QRandomGenerator::QRandomGenerator(quint32 seedValue)
- Initializes this QRandomGenerator object with the value \a seed as
- the seed. Two objects constructed with the same seed value will
+ Initializes this QRandomGenerator object with the value \a seedValue as
+ the seed. Two objects constructed or reseeded with the same seed value will
produce the same number sequence.
- \sa securelySeeded()
+ \sa seed(), securelySeeded()
*/
/*!
@@ -592,7 +600,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
array \a seedBuffer as the seed. Two objects constructed or reseeded with
the same seed value will produce the same number sequence.
- \sa securelySeeded()
+ \sa seed(), securelySeeded()
*/
/*!
@@ -609,7 +617,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
QRandomGenerator generator(sseq);
\endcode
- \sa securelySeeded()
+ \sa seed(), securelySeeded()
*/
/*!
@@ -626,7 +634,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
QRandomGenerator generator(sseq);
\endcode
- \sa securelySeeded()
+ \sa seed(), securelySeeded()
*/
/*!
@@ -637,7 +645,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
sseq as the seed. Two objects constructed or reseeded with the same seed
value will produce the same number sequence.
- \sa securelySeeded()
+ \sa seed(), securelySeeded()
*/
/*!
@@ -659,6 +667,24 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
*/
/*!
+ \fn bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
+ \relates QRandomGenerator
+
+ Returns true if the two the two engines \a rng1 and \a rng2 are at the same
+ state or if they are both reading from the operating system facilities,
+ false otherwise.
+*/
+
+/*!
+ \fn bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
+ \relates QRandomGenerator
+
+ Returns true if the two the two engines \a rng1 and \a rng2 are at
+ different states or if one of them is reading from the operating system
+ facilities and the other is not, false otherwise.
+*/
+
+/*!
\typedef QRandomGenerator::result_type
A typedef to the type that operator()() returns. That is, quint32.
@@ -692,6 +718,31 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
*/
/*!
+ \fn void QRandomGenerator::seed(quint32 seed)
+
+ Reseeds this object using the value \a seed as the seed.
+ */
+
+/*!
+ \fn void QRandomGenerator::seed(std::seed_seq &seed)
+ \overload
+
+ Reseeds this object using the seed sequence \a sseq as the seed.
+ */
+
+/*!
+ \fn void QRandomGenerator::discard(unsigned long long z)
+
+ Discards the next \a z entries from the sequence. This method is equivalent
+ to calling generate() \a z times and discarding the result, as in:
+
+ \code
+ while (z--)
+ generator.generate();
+ \endcode
+*/
+
+/*!
\fn void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end)
Generates 32-bit quantities and stores them in the range between \a begin
@@ -1086,6 +1137,27 @@ QRandomGenerator::QRandomGenerator(const quint32 *begin, const quint32 *end)
new (&storage.engine()) RandomEngine(s);
}
+void QRandomGenerator::discard(unsigned long long z)
+{
+ if (Q_UNLIKELY(type == SystemRNG))
+ return;
+
+ PRNGLocker lock(this);
+ storage.engine().discard(z);
+}
+
+bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
+{
+ if (rng1.type != rng2.type)
+ return false;
+ if (rng1.type == SystemRNG)
+ return true;
+
+ // Lock global() if either is it (otherwise this locking is a no-op)
+ PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2);
+ return rng1.storage.engine() == rng2.storage.engine();
+}
+
/*!
\internal
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
index c25a0ad643..c31c9afddb 100644
--- a/src/corelib/global/qrandom.h
+++ b/src/corelib/global/qrandom.h
@@ -52,8 +52,8 @@ class QRandomGenerator
template <typename UInt> using IfValidUInt =
typename std::enable_if<std::is_unsigned<UInt>::value && sizeof(UInt) >= sizeof(uint), bool>::type;
public:
- QRandomGenerator(quint32 seed = 1)
- : QRandomGenerator(&seed, 1)
+ QRandomGenerator(quint32 seedValue = 1)
+ : QRandomGenerator(&seedValue, 1)
{}
template <qssize_t N> QRandomGenerator(const quint32 (&seedBuffer)[N])
: QRandomGenerator(seedBuffer, seedBuffer + N)
@@ -68,6 +68,12 @@ public:
Q_CORE_EXPORT QRandomGenerator(const QRandomGenerator &other);
Q_CORE_EXPORT QRandomGenerator &operator=(const QRandomGenerator &other);
+ friend Q_CORE_EXPORT bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2);
+ friend bool operator!=(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
+ {
+ return !(rng1 == rng2);
+ }
+
quint32 generate()
{
quint32 ret;
@@ -151,6 +157,9 @@ public:
// API like std:: random engines
typedef quint32 result_type;
result_type operator()() { return generate(); }
+ void seed(quint32 s = 1) { *this = { s }; }
+ void seed(std::seed_seq &sseq) Q_DECL_NOTHROW { *this = { sseq }; }
+ Q_CORE_EXPORT void discard(unsigned long long z);
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
@@ -202,8 +211,8 @@ public:
result_type operator()() { return generate64(); }
#ifndef Q_QDOC
- QRandomGenerator64(quint32 seed = 1)
- : QRandomGenerator(seed)
+ QRandomGenerator64(quint32 seedValue = 1)
+ : QRandomGenerator(seedValue)
{}
template <qssize_t N> QRandomGenerator64(const quint32 (&seedBuffer)[N])
: QRandomGenerator(seedBuffer)
@@ -219,6 +228,13 @@ public:
{}
QRandomGenerator64(const QRandomGenerator &other) : QRandomGenerator(other) {}
+ void discard(unsigned long long z)
+ {
+ Q_ASSERT_X(z * 2 > z, "QRandomGenerator64::discard",
+ "Overflow. Are you sure you want to skip over 9 quintillion samples?");
+ QRandomGenerator::discard(z * 2);
+ }
+
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
static Q_CORE_EXPORT QRandomGenerator64 *system();