@@ -147,8 +147,6 @@ template<typename T>
147147concept RandomNumberGenerator = requires (T& rng, Span<std::byte> s) {
148148 // A random number generator must provide rand64().
149149 { rng.rand64 () } noexcept -> std::same_as<uint64_t >;
150- // A random number generator must provide randfill(Span<std::byte>).
151- { rng.fillrand (s) } noexcept ;
152150 // A random number generator must derive from RandomMixin, which adds other rand* functions.
153151 requires std::derived_from<std::remove_reference_t <T>, RandomMixin<std::remove_reference_t <T>>>;
154152};
@@ -261,6 +259,25 @@ class RandomMixin
261259 }
262260 }
263261
262+ /* * Fill a Span with random bytes. */
263+ void fillrand (Span<std::byte> span) noexcept
264+ {
265+ while (span.size () >= 8 ) {
266+ uint64_t gen = Impl ().rand64 ();
267+ WriteLE64 (UCharCast (span.data ()), gen);
268+ span = span.subspan (8 );
269+ }
270+ if (span.size () >= 4 ) {
271+ uint32_t gen = Impl ().rand32 ();
272+ WriteLE32 (UCharCast (span.data ()), gen);
273+ span = span.subspan (4 );
274+ }
275+ while (span.size ()) {
276+ span[0 ] = std::byte (Impl ().template randbits <8 >());
277+ span = span.subspan (1 );
278+ }
279+ }
280+
264281 /* * Generate random bytes. */
265282 template <BasicByte B = unsigned char >
266283 std::vector<B> randbytes (size_t len) noexcept
@@ -345,19 +362,19 @@ class FastRandomContext : public RandomMixin<FastRandomContext>
345362 return ReadLE64 (UCharCast (buf.data ()));
346363 }
347364
348- /* * Fill a byte Span with random bytes. */
365+ /* * Fill a byte Span with random bytes. This overrides the RandomMixin version. */
349366 void fillrand (Span<std::byte> output) noexcept ;
350367};
351368
352369/* * xoroshiro128++ PRNG. Extremely fast, not appropriate for cryptographic purposes.
353370 *
354- * Memory footprint is 128bit , period is 2^128 - 1.
371+ * Memory footprint is very small , period is 2^128 - 1.
355372 * This class is not thread-safe.
356373 *
357374 * Reference implementation available at https://prng.di.unimi.it/xoroshiro128plusplus.c
358375 * See https://prng.di.unimi.it/
359376 */
360- class XoRoShiRo128PlusPlus
377+ class InsecureRandomContext : public RandomMixin <InsecureRandomContext>
361378{
362379 uint64_t m_s0;
363380 uint64_t m_s1;
@@ -371,21 +388,19 @@ class XoRoShiRo128PlusPlus
371388 }
372389
373390public:
374- using result_type = uint64_t ;
375-
376- constexpr explicit XoRoShiRo128PlusPlus (uint64_t seedval) noexcept
391+ constexpr explicit InsecureRandomContext (uint64_t seedval) noexcept
377392 : m_s0(SplitMix64(seedval)), m_s1(SplitMix64(seedval)) {}
378393
379394 // no copy - that is dangerous, we don't want accidentally copy the RNG and then have two streams
380395 // with exactly the same results.
381- XoRoShiRo128PlusPlus (const XoRoShiRo128PlusPlus &) = delete ;
382- XoRoShiRo128PlusPlus & operator =(const XoRoShiRo128PlusPlus &) = delete ;
396+ InsecureRandomContext (const InsecureRandomContext &) = delete ;
397+ InsecureRandomContext & operator =(const InsecureRandomContext &) = delete ;
383398
384399 // allow moves
385- XoRoShiRo128PlusPlus (XoRoShiRo128PlusPlus &&) = default ;
386- XoRoShiRo128PlusPlus & operator =(XoRoShiRo128PlusPlus &&) = default ;
400+ InsecureRandomContext (InsecureRandomContext &&) = default ;
401+ InsecureRandomContext & operator =(InsecureRandomContext &&) = default ;
387402
388- constexpr result_type operator () () noexcept
403+ constexpr uint64_t rand64 () noexcept
389404 {
390405 uint64_t s0 = m_s0, s1 = m_s1;
391406 const uint64_t result = std::rotl (s0 + s1, 17 ) + s0;
@@ -394,10 +409,6 @@ class XoRoShiRo128PlusPlus
394409 m_s1 = std::rotl (s1, 28 );
395410 return result;
396411 }
397-
398- static constexpr result_type min () noexcept { return std::numeric_limits<result_type>::min (); }
399- static constexpr result_type max () noexcept { return std::numeric_limits<result_type>::max (); }
400- static constexpr double entropy () noexcept { return 0.0 ; }
401412};
402413
403414/* * More efficient than using std::shuffle on a FastRandomContext.
0 commit comments