<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>P0205R1 &mdash; Efficient Seeding of Random Number Engines</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="description" content="The purpose of this proposal is to make properly seeding a random number engine in a (non-)deterministic way easy and fast." />
    <meta name="keywords" content="ISO C++, random, seed, random number engine, RNG, PRNG, std::seed_seq, std::random_device, entropy, Moritz Klammler" />
    <style type="text/css">
      /* <![CDATA[ */

      body {
        font-family: serif;
        font-size: 12pt;
        margin: 2rem;
      }

      p {
        text-align: justify;
      }

      pre, code {
        font-family: monospace;
        font-size: inherit;
      }

      pre .comment {
        font-style: italic;
      }

      blockquote {
        margin: 0;
        padding: 0.2ex 1em 0.3ex 1em;
        background-color: #eeeeec;
        border-left: 3px solid #babdb6;
      }

      ol.toc {
        list-style: none;
        margin-left: 2em;
        padding: 0;
      }

      ol.toc li {}

      ins, .insert { color: #4e9a06; font-style: inherit; }
      del, .delete { color: #a40000; font-style: inherit; }

      a, a:link, a:visited { color: ##204a87; text-decoration: none; }
      a:hover { color: #3465a4; text-decoration: underline;  }
      a:active { color: #729fcf; text-decoration: underline; }
      a.external::after { content: '\1F517'; margin-left: 0.3ex; }
      a.email::after { content: '\1F4E7'; margin-left: 0.3ex; }

      /* ]]> */
    </style>
    <script type="text/javascript">
      /* <![CDATA[ */

      function replace_email() {
        var node = document.getElementById('email');
        var email = node.innerHTML.replace(/\\x2E/g, '\x2E').replace(/\\x40/g, '\x40');
        node.innerHTML = email;
        node.href = 'mailto:' + email;
      }

      /* ]]> */
    </script>
  </head>
  <body onload="replace_email()">
    <h1>Efficient Seeding of Random Number Engines</h1>
    <table border="0" cellspacing="0" cellpadding="5">
      <tr>
        <td>Document number:</td>
        <td>P0205R1</td>
      </tr>
      <tr>
        <td>Date:</td>
        <td>2021-06-04</td>
      </tr>
      <tr>
        <td>Project:</td>
        <td>Programming Language C++</td>
      </tr>
      <tr>
        <td>Audience:</td>
        <td>Study Group 6 (Numerics), Library Evolution Working Group, Library Working Group</td>
      </tr>
      <tr>
        <td>Reply-to:</td>
        <td>
          Moritz Klammler
          &lt;<code><a class="email" id="email">moritz\x40klammler\x2Eeu</a></code>&gt;
          (OpenPGP: <code>2732 DA32 C8D0 EEEC A081 BE9D CF6C 5166 F393 A9C0</code>)
        </td>
      </tr>
    </table>
    <h2 id="sec-toc">Table of Contents</h2>
    <ol class="toc">
      <li><a href="#sec-intro">1 Introduction</a></li>
      <li>
        <a href="#sec-motivation-scope">2 Motivation and Scope</a>
        <ol class="toc">
          <li><a href="#sec-background">2.1 Background</a></li>
          <li><a href="#sec-current-problem">2.2 The Problem with the Current Standard Library</a></li>
          <li><a href="#sec-proposed-solution">2.3 The Proposed Solution</a></li>
        </ol>
      </li>
      <li>
        <a href="#sec-impact-std">3 Impact on the Standard</a>
        <ol class="toc">
          <li><a href="#sec-new-features">3.1 Refinements and Additions to the Standard Library</a></li>
          <li><a href="#sec-rand-req-eng">3.2 Clarification on Random Number Engine Requirements</a></li>
          <li><a href="#sec-deprecation">3.3 Deprecation of Existing Features</a></li>
        </ol>
      </li>
      <li><a href="#sec-design-decisions">4 Design Decisions</a></li>
      <li><a href="#sec-alt-solutions">5 Alternative Solutions</a></li>
      <li><a href="#sec-implementations">6 Implementations</a></li>
      <li><a href="#sec-prop-word">7 Proposed Wording</a></li>
      <li><a href="#sec-acknowledgments">Acknowledgments</a></li>
      <li><a href="#sec-changelog">Changelog</a></li>
      <li><a href="#sec-references">References</a></li>
    </ol>
    <h2 id="sec-intro">1 Introduction</h2>
    <p>
      The purpose of this proposal is to make properly seeding a random number engine in a (non-)deterministic way easy
      and fast.
    </p>
    <p>
      In order to achieve this, the following changes are proposed:
    </p>
    <ul>
      <li>
        <p>
          Introduction of a new named requirement <em>seed generator</em>, which is a relaxation of
          <em>seed sequence</em>
          <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req.seedseq">[rand.req.seedseq]</a>.
        </p>
      </li>
      <li>
        <p>
          Addition of a new helper type <code>std::seed_adapter</code> which makes any
          <em>uniform random bit generator</em>
          <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.urng">[rand.req.urng]</a>
          usable as a <em>seed generator</em>.
        </p>
      </li>
    </ul>
    <p>
      The changes are non-breaking and can be implemented as a pure library solution with current C++20 features.
    </p>
    <h2 id="sec-motivation-scope">2 Motivation and Scope</h2>
    <h3 id="sec-background">2.1 Background</h3>
    <p>
      C++11 introduced a powerful random number generation library
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand">[rand]</a>
      under the <code>&lt;random&gt;</code> header.  It provides <em>random number engines</em>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.eng">[rand.req.eng]</a>
      that can be used either directly as a source of uniformly distributed pseudo random integers of unsigned type or
      together with <em>random number distributions</em>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.dist">[rand.req.dist]</a>
      to produce pseudo random numbers according to a variety of distributions.
    </p>
    <p>
      If an engine has an internal state of <var>N</var> bits, it can produce at most 2<sup><var>N</var></sup> different
      sequences and the longest sequence it can produce will have a period of at most 2<sup><var>N</var></sup> values
      until it necessarily starts repeating itself.  Applications that wish to produce high-quality pseudo random
      numbers will therefore choose an engine such as the Mersenne twister (e.g. <code>std::mt19937</code>) with a large
      internal state.  Choosing an engine with a large internal state helps ensuring that the period of the generated
      sequence will be large.  However, in order to ensure that the number of different sequences the engine can produce
      is also exponential in the size of its state, it has to be made sure that the initial state is evenly distributed
      across all possible states.  This is done by <em>seeding</em> the random number engine.  If each of the
      2<sup><var>N</var></sup> states should be chosen with equal probability as the initial state, seeding requires
      2<sup><var>N</var></sup> bits of entropy.
    </p>
    <p>
      The standard library provides the type <code>std::random_device</code>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#device">[rand.device]</a>,
      a <em>uniform random bit generator</em>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.urng">[rand.req.urng]</a>
      that is supposed (but, unfortunately, not required) to produce a non-deterministic sequence of uniformly
      distributed integers of type
      <code>unsigned int</code>.  The natural choice for an application that wishes to generate pseudo random numbers
      and does not need (and often doesn't want) reproducibility is to use it for seeding a random engine that is then
      used to produce pseudo random numbers.  In addition, the standard library provides the
      type <code>std::seed_seq</code>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#util.seedseq">[rand.util.seedseq]</a>
      which implements the <em>seed sequence</em>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.seedseq">[rand.req.seedseq]</a>
      requirements (and is the only type in the current standard library doing so).  It can be used to seed a random
      number engine using entropy obtained from an arbitrary sequence of integers (e.g. a user-provided byte string
      read from a file or an environment variable to allow reproducing experiments with the same seed).
    </p>
    <h3 id="sec-current-problem">2.2 The Problem with the Current Standard Library</h3>
    <p>
      Unfortunately, the current standard library does not provide any convenient way to use
      a <code>std::random_device</code> to properly (in the sense that each initial state is equally likely) seed a
      random engine.  Nor does it make doing so with a custom uniform random bit generator or writing a custom seed
      sequence easy.
    </p>
    <p>
      The na&iuml;ve approach that most people seem to use is drawing one random number
      from <code>std::random_device</code> (or whatever source of entropy they have) and then use the constructor which
      takes a single integer as seed.
    </p>
    <pre>template &lt;typename EngineT&gt;
void seed_non_deterministically_1st(EngineT&amp; engine)
{
    std::random_device device{};
    engine.seed(device());
}</pre>
    <p>
      This code is severely flawed.  If <code>EngineT</code> is <code>std::mt19937</code>, it has a state size of
      19&#x202f;968&nbsp;bits.  However, if an <code>unsigned int</code> is 32&nbsp;bits (as is the common case on many
      platforms today), then of the up to 2<sup>19&#x202f;968</sup> states, at most 2<sup>32</sup> (that is one
      2<sup>&minus;19&#x202f;936</sup>-th) can possibly be chosen!
    </p>
    <p>
      To illustrate that this is in fact a real problem, O'Neill&nbsp;[<a href="#ref-01">1</a>] has pointed out that a
      <code>std::mt19937</code> engine seeded like above can never produce certain integers as its first value.  This
      can have bad consequences on real-world programs.  A program that incorrectly assumes that an impossible number
      will eventually be produced as the engine's first (or <var>n</var>-th) output is broken in a very subtle way.
      After all, it would take extensive and practically unrealistic unit testing to do an exhaustive search over the
      possible seeds and even detect the bug.
    </p>
    <p>
      In addition to seeding an engine with an integer, the standard library also provides a way to seed it with a
      so-called <em>seed sequence</em>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.seedseq">[rand.req.seedseq]</a>.
      A seed sequence may be constructed in a deterministic way from zero or more integers that provide some initial
      entropy.  The numbers are then possibly scrambled and stored in some internal state of the seed sequence which can
      be externalized using the <code>param</code> member function.  Such a memento may then be used to re-create a seed
      sequence of the same type in the same state.  A seed sequence provides a member function <code>generate</code>
      that takes a pair of random access iterators and assigns a uniformly distributed unsigned 32 bit integer to each
      element in the range denoted by the iterator pair.  The standard library provides a single implementation of a
      seed sequence in <code>std::seed_seq</code>
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#util.seedseq">[rand.util.seedseq]</a>.
      This type can be used to seed a random engine more thoroughly.
    </p>
    <pre>template &lt;typename EngineT, std::size_t StateSize = EngineT::state_size&gt;
void seed_non_deterministically_2nd(EngineT&amp; engine)
{
    using engine_type = typename EngineT::result_type;
    using device_type = std::random_device::result_type;
    using seedseq_type = std::seed_seq::result_type;
    constexpr auto bytes_needed = StateSize * sizeof(engine_type);
    constexpr auto numbers_needed = (sizeof(device_type) &lt; sizeof(seedseq_type))
        ? (bytes_needed / sizeof(device_type))
        : (bytes_needed / sizeof(seedseq_type));
    std::array&lt;device_type, numbers_needed&gt; numbers{};
    std::random_device device{};
    std::generate(std::begin(numbers), std::end(numbers), std::ref(device));
    std::seed_seq seedseq(std::cbegin(numbers), std::cend(numbers));
    engine.seed(seedseq);
}</pre>
    <p>
      This code has a number of problems.
    </p>
    <ul>
      <li>
        <p>
          It is absurdly complicated for what could rightfully be expected to be a simple task.  (Even the author is not
          absolutely sure it is correct.)  It is unrealistic (and unreasonable) to expect a casual user to come up with
          such a seeding procedure.
        </p>
      </li>
      <li>
        <p>
          It is not as general as one might hope it is.  The <em>random number engine</em> requirements do not specify
          that an engine exposes its <code>state_size</code> as the <code>std::mersenne_twister_engine</code> does.
          (The author believes that making this constant part of the requirements would have been a good idea but it is
          too late for this now.)  This forces the user of the function to look up the actual state size in the
          documentation and provide the correct value as the second <code>template</code> parameter.  (One could check
          for the existence of <code>E::state_size</code> and fall back to <code>sizeof(E)</code> as a reasonable
          estimate for third-party types, faithfully assuming they won't allocate memory to hold state on the free
          store.)
        </p>
      </li>
      <li>
        <p>
          It is not as accurate as it should be.  Assuming that <code>std::random_device</code> produces truly
          independent uniform random numbers, <code>std::seed_seq</code> actually
          <em>introduces</em> non-uniformity&nbsp;[<a href="#ref-01">1</a>].  (O'Neill provides experimental evidence for
          this.  Anyway, it is clear that a deterministic algorithm can only ever reduce but never increase the entropy
          of a given seed.)
        </p>
      </li>
      <li>
        <p>
          It is not as efficient as it could be.  While all that's really needed is copying a sequence of random bytes
          into the internal state of the engine, the <code>std::random_device</code> first copies them into a
          stack-based <code>std::array</code> from which the <code>std::seed_seq</code> copies them into a heap
          allocated (!)  internal buffer, scrambles them in a (in this case counter-productive) attempt to remove bias
          until the engine finally copies them to their final destination.  To make matters worse, the
          <code>std::random_device</code> does not know in advance how many bytes will be needed.  Therefore, on
          implementations where it reads from a file such as
          <a class="external" rel="external nofollow noreferrer" href="https://man7.org/linux/man-pages/man4/random.4.html"><code>/dev/urandom</code></a>
          or uses a syscall like
          <a class="external" rel="external nofollow noreferrer" href="https://man7.org/linux/man-pages/man2/getrandom.2.html">getrandom(2)</a>
          on Linux, it cannot buffer the reads efficiently.
        </p>
      </li>
    </ul>
    <p>
      The preceding discussion used <code>std::random_device</code> as an example as it is the go-to solution for
      obtaining system entropy for a non-deterministic seed on C++ today.  However, since nothing special
      about <code>std::random_device</code> was made use of, the same discusison applies to any uniform random bit
      generator.
    </p>
    <p>
      Unfortunately, writing one's own seed sequence isn't a great solution either.
      First of all, doing something like this shouldn't be necessary for a common use case.
      Second and more severely, the seed sequence requirements
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req.seedseq">[rand.req.seedseq]</a>
      mandate a constructor which takes a pair of iterators, another constructor with takes an initializer list and
      finally a <code>size</code> and a <code>param</code> member function that are supposed to externalize the object's
      state such that it can be reconstructed again later.  While this makes sense for <code>std::seed_seq</code> which
      is deterministic and always constructed from a sequence of integers, it makes no sense for a seed sequence that
      obtains its values from a system's entropy source.  The <q>best</q> way to deal with these functions is to either
      not implement them (which isn't strictly valid C++20) and hope that the standard library won't enforce the type
      requirements strictly or implement them to unconditionally throw an exception, which is a sad and annoying option.
    </p>
    <h3 id="sec-proposed-solution">2.3 The Proposed Solution</h3>
    <p>
      With this proposal adopted, properly seeding a random engine could be as simple as this.
    </p>
    <pre>template &lt;typename EngineT&gt;
void seed_non_deterministically_3rd(EngineT&amp; engine)
{
    std::random_device device{};
    std::seed_adapter adapter{device};
    engine.seed(adapter);
}</pre>
    <p>
      There would be no unnecessary copies, no unneeded tempering, no dynamic memory allocation, no introduced bias and
      little chance to get anything wrong on the user's side.
    </p>
    <p>
      The <code>std::seed_adapter</code> would be a class template (the example above using CTAD) that wraps a reference
      to any uniform random bit generator and provides a <code>generate</code> member function which calls through to
      the generator's call operator.  If
      <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1068r4.pdf">P1068R4</a>
      were to be adopted and <code>EngineT</code> implements the proposed <em>uniform vector random bit generator</em>
      concept, the implementation of <code>std::seed_adapter&lt;EngineT&gt;::generate</code> would make exactly one call
      to <code>EngineT::operator()</code>.  Even if that proposal should not be adopted, a standard library
      implementation would be free (and encouraged) to optimize this case for its own implementation
      of <code>std::random_device</code> at least.
    </p>
    <h2 id="sec-impact-std">3 Impact on the Standard</h2>
    <p>
      This proposal could be implemented with very little changes, none of which would be breaking anything.  No core
      language changes are needed.
    </p>
    <h3 id="sec-new-features">3.1 Refinements and Additions to the Standard Library</h3>
    <p>
      The requirements on the type parameter for a random engine's <code>seed</code> member function (and the
      corresponding constructor) should be relaxed such that it only requires the <code>generate</code> member function
      from <em>seed sequence</em>.  Bolas&nbsp;[<a href="#ref-02">2</a>] has argued that even today, a conforming
      implementation isn't allowed to <em>call</em> anything but <code>generate</code> and perhaps <code>size</code> due
      to existing complexity requirements.  Unfortunately, it may still enforce their presence via type checks.
    </p>
    <p>
      To express this relaxed requirement, a new named requirement <em>seed generator</em> and a
      corresponding <code>std::seed_generator</code> concept are proposed.  Only a
      <code>generate</code> member function would be required.  The existing <em>seed sequence</em> named requirement
      would be defined as a refinement of it and a <code>std::seed_sequence</code> concept added for completeness.
    </p>
    <p>
      A new class template <code>std::seed_adapter</code> is proposed that implements the
      <code>std::seed_generator</code> concept and acts as an adapter for making any uniform (vector) random bit
      generator usable as the source for seeding any random number generator.  The adapter would be non-owning (note
      that <code>std::random_device</code> is not copyable and copying a (deterministic) random number engine would
      generally be undesirable because the state transitions would be lost, introducing bad randomness in a way that is
      not necessarily obvious to users.)
    </p>
    <p>
      This proposal has no dependencies on any other proposal.  However, if
      <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1068r4.pdf">P1068R4</a>
      were adopted, there would be optimization potential for the implementation of the
      proposed <code>std::seed_adapter</code>.  The currently proposed wording was chosen to not preclude this
      optimization but it cannot mandate it either.
    </p>
    <p>
      The author is not aware of any other proposal that depends on or conflicts with this proposal.  In particular, it
      is orthogonal to
      <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3547.pdf">N3547</a>.
      (However, the sample implementation of <code>std::randomize</code> in that paper could benefit from the feature
      suggested in this proposal.)
    </p>
    <h3 id="sec-rand-req-eng">3.2 Clarification on Random Number Engine Requirements</h3>
    <p>
      Currently, table&nbsp;94
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req#tab:rand.req.eng">[tab:rand.req.eng]</a>
      defines the various overloads of the <code>seed</code> member function of a type <code>E</code> that meets the
      requirements of <em>random number engine</em> in terms of the corresponding constructor and equality operator.
      For example, <code>e.seed(q)</code> is defined to have the effect
      that <q>post: <code>e&nbsp;==&nbsp;E(q)</code></q> and complexity <q>same as <code>E(q)</code></q>.  This is
      unfortunate because for a <em>seed sequence</em> <code>q</code>, two successive calls to <code>q.generate</code>
      (even for ranges of identical size) do not have to produce the same sequence of numbers, even
      though <code>std::seed_seq</code> happens to behave that way.  The requirements for <em>seed sequence</em> don't
      mandate this; the respective row in table&nbsp;93
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req#tab:rand.req.seedseq">[tab:rand.req.seedseq]</a>
      says about <code>q.generate(rb,&nbsp;re)</code> (emphasis added):
    </p>
    <blockquote>
      <p>
        Does nothing if <code>rb&nbsp;==&nbsp;re</code>.  Otherwise, fills the supplied sequence
        <code>[rb,&nbsp;re)</code> with 32-bit quantities that depend on the sequence supplied to the constructor
        <strong>and possibly also depend on the history of <code>generate</code>'s previous invocations</strong>.
      </p>
    </blockquote>
    <p>
      Therefore, the author believes that it is not intended by the current standard that the following code should be
      guaranteed to work.
    </p>
<pre>template &lt;typename RandEngT, typename SeedSeqT&gt;
void test(RandEngT&amp; engine, SeedSeqT&amp; seedseq)
{
    engine.seed(seedseq);
    assert(engine == RandEngT{seedseq});  <span class="comment">// might fire</span>
}</pre>
    <p>
      Regardless of whether this proposal will be adopted, the wording in table&nbsp;94 should be updated to make it
      clear that calling <code>seed</code> puts the engine into the same state as calling the corresponding constructor
      but not create the impression that the <code>assert</code>ion in the above example would necessarily hold.
    </p>
    <h3 id="sec-deprecation">3.3 Deprecation of Existing Features</h3>
    <p>
      It is not proposed that any existing library features be deprecated.
    </p>
    <p>
      Possible candidates for deprecation could be the overload of <code>E::seed</code> that takes a single value of
      type <code>E::result_type</code> and the corresponding constructor of a <em>random number
      engine</em> <code>E</code>.  Deprecating these overloads might be sensible because those functions actually
      encourage poorly seeding random number engines.  On the other hand, they remain useful in situations where people
      want to hard-code a specific seed (such as in <code>std::minstd_rand{42}</code>) and don't really care about
      uniformly choosing an initial state from the entire state-space of the engine or know that the space is
      sufficiently small.
    </p>
    <h2 id="sec-design-decisions">4 Design Decisions</h2>
    <p>
      The (updated) proposal takes care to be non-breaking with existing and compatible with potential future versions
      of the standard library (which might include
      <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1068r4.pdf">P1068R4</a>).
      For the sake of backwards compatibility, the specification that the <code>generate</code> member function of a
      seed sequence and therefore a seed generator deal in 32&#x202f;bit integers could not be changed.
    </p>
    <h2 id="sec-alt-solutions">5 Alternative Solutions</h2>
    <p>
      If <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1068r4.pdf">P1068R4</a>
      were adopted, this proposal could eventually be made obsolete by instead simply adding an additional constructor
      and <code>seed</code> member function to the random number engine requirements which takes a uniform vector random
      bit generator as lvalue argument and initializes its internal state by calling its range <code>operator()</code>
      instead of the <code>param</code> member function as the seed sequence overload does.
    </p>
    <blockquote>
      <p>
        If <code>p</code> is an lvalue of a type which implements <code>std::uniform_vector_random_bit_generator</code>
        and <code>E</code> is a type which meets the requirements of a random number engine, then the
        expression <code>E(p)</code> shall initialize the engine's state via a single call to <code>p(f, l)</code>
        with <code>f</code> and <code>l</code> being contiguous iterators with a value type that is an unsigned integer.
        For an lvalue <code>e</code> of type <code>E</code>, the expression <code>e.seed(p)</code> shall have the same
        effect as <code>e = E(p)</code>.
      </p>
    </blockquote>
    <p>
      This would be a breaking change as it would strengthen the requirements on an existing named requirement.  Of
      course, the standard library types could implement this nonetheless and the new requirement be made optional by
      introducing yet another concept or named requirement.
    </p>
    <p>
      However, the author is concerned that this solution could be confusing because of the ambiguity with the copy
      constructor.
    </p>
    <p>
      Making <code>std::seed_adapter</code> own the underlying uniform random bit generator instead of holding a
      reference to it was considered but not perused for the reasons discussed earlier, namely concerns about generators
      that are not copyable or non-obvious undesired effects of creating such copies in cases where this is possible.
    </p>
    <p>
      The author notes that – would this proposal be adopted – the seed <em>sequence</em> requirement isn't actually
      used by the standard library itself.  Therefore, the standard might as well just not define it anymore.
    </p>
    <h2 id="sec-implementations">6 Implementations</h2>
    <p>
      The implementation of this proposal would be very simple.  A proof-of-concept is available
      <a class="external" rel="external nofollow noreferrer"  href="https://godbolt.org/z/rEfvT3bbs">online</a>.
    </p>
    <h2 id="sec-prop-word">7 Proposed Wording</h2>
    <p>
      All proposed changes to the standard mentioned in this section are relative to N4861.
    </p>
    <p>
      Add to the synopsis of the <code>&lt;random&gt;</code> header
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.synopsis">[rand.req.synopsis]</a>
      the following three declarations.
    </p>
    <blockquote>
<pre class="insert">
template &lt;class S&gt;
concept seed_generator = <em>see below</em>;

template &lt;class S&gt;
concept seed_sequence = <em>see below</em>;

template &lt;class U&gt;
class seed_adapter&lt;U&gt;;
</pre>
    </blockquote>
    <p>
      Add a new section before the existing §&nbsp;26.6.2.2
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req.seedseq">[rand.req.seedseq]</a>
      to define <em>seed generator</em>.
    </p>
    <blockquote class="insert">
      <p>
        <strong>Seed generator requirements [rand.req.seedgen]</strong>
      </p>
      <p>
        A <em>seed generator</em> is an object that produces a requested number of unsigned integer values <var>i</var>
        with 0 &le; <var>i</var> &lt; 2<sup>32</sup>.  The generated numbers may be obtained from a non-deterministic
        source of entropy.
      </p>
      <p>
        A class <code>S</code> satisfies the requirements of a seed generator if the expressions shown in the below
        table are valid and have the indicated semantics and if <code>S</code> also satisfies all other requirements of
        this section.  In that table and throughout this section:
      </p>
      <ul>
        <li>
          <code>T</code> is the type named by <code>S</code>'s associated
          <code>result_type</code>;
        </li>
        <li>
          <code>q</code> is a value of <code>S</code>;
        </li>
        <li>
          <code>rb</code> and <code>re</code> are mutable random access iterators with an unsigned
          integer <code>value_type</code> of at least 32&nbsp;bits.
        </li>
      </ul>
      <table border="1" cellspacing="0" cellpadding="5">
        <tr>
          <th><p>Expression</p></th>
          <th><p>Return type</p></th>
          <th><p>Pre/post-condition</p></th>
          <th><p>Complexity</p></th>
        </tr>
        <tr>
          <td>
            <p><code>S::result_type</code></p>
          </td>
          <td>
            <p><code>T</code></p>
          </td>
          <td>
            <p><code>T</code> is an unsigned integer type of at least 32 bits.</p>
          </td>
          <td>
            <p>compile-time</p>
          </td>
        </tr>
        <tr>
          <td>
            <p><code>q.generate(rb,&nbsp;re)</code></p>
          </td>
          <td>
            <p><code>void</code></p>
          </td>
          <td>
            <p>
              Does nothing if <code>rb&nbsp;==&nbsp;re</code>.  Otherwise, fills the supplied sequence
              [<code>rb</code>,&nbsp;<code>re</code>) with 32-bit quantities in a possibly non-deterministic way.
            </p>
          </td>
          <td>
            <p><var>&Omicron;</var>(<code>re&nbsp;-&nbsp;rb</code>)</p>
          </td>
        </tr>
      </table>
      <p><!-- phantom space --></p>
    </blockquote>
    <p>
      In the existing section §&nbsp;26.6.2.2
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand.req.seedseq">[rand.req.seedseq]</a>,
      change the beginning of the second paragraph as follows.
    </p>
    <blockquote>
      <p>
        A class <code>S</code> meets the requirements of a seed sequence if
        <ins>it satisfies the requirements of a seed generator and in addition,</ins>
        the expressions [&hellip;]
      </p>
    </blockquote>
    <p>
      In the current table&nbsp;93, remove the first (<code>S::result_type</code>) and the fifth
      (<code>q.generate(rb,&nbsp;re)</code>) row which will already be covered by the <em>seed generator</em>
      requirements.
    </p>
    <p>
      Replace section&nbsp;26.6.2.4
      <a class="external" rel="external nofollow noreferrer" href="https://timsong-cpp.github.io/cppwp/n4861/rand#req.eng">[rand.req.eng]</a>
      paragraph&nbsp;4.4 by the following sentence with the appropriate cross-reference to the section defining the
      requirements of <em>seed generator</em>.
    </p>
    <blockquote>
      <p>
        <code>q</code> is an lvalue satisfying the requirements of a seed <del>sequence</del> <ins>generator</ins>;
      </p>
    </blockquote>
    <p>
      Add the following two new concepts for <code>std::seed_generator</code> and <code>std::seed_sequence</code> at
      appropriate locations.
    </p>
    <blockquote class="insert">
<pre>template &lt;
    class SeedGenerator,
    class RandomAccessIterator = add_pointer_t&lt;typename SeedGenerator::result_type&gt;
&gt;
concept seed_generator = __unsigned_integral_least32&lt;typename SeedGenerator::result_type&gt;
    &amp;&amp; random_access_iterator&lt;RandomAccessIterator&gt;
    &amp;&amp; __unsigned_integral_least32&lt;typename iterator_traits&lt;RandomAccessIterator&gt;::value_type&gt;
    &amp;&amp; requires (SeedGenerator&amp; s, RandomAccessIterator f, RandomAccessIterator l) {
        { s.generate(f, l) } -&gt; same_as&lt;void&gt;;
    };

template &lt;
    class SeedSequence,
    class RandomAccessIterator = add_pointer_t&lt;typename SeedSequence::result_type&gt;,
    class InputIterator = RandomAccessIterator,
    class OutputIterator = RandomAccessIterator
&gt;
concept seed_sequence = seed_generator&lt;SeedSequence, RandomAccessIterator&gt;
    &amp;&amp; default_initializable&lt;SeedSequence&gt;
    &amp;&amp; constructible_from&lt;SeedSequence, InputIterator, InputIterator&gt;
    &amp;&amp; constructible_from&lt;SeedSequence, initializer_list&lt;typename SeedSequence::result_type&gt;&gt;
    &amp;&amp; input_iterator&lt;InputIterator&gt;
    &amp;&amp; __unsigned_integral_least32&lt;typename iterator_traits&lt;InputIterator&gt;::value_type&gt;
    &amp;&amp; output_iterator&lt;OutputIterator, typename SeedSequence::result_type&gt;
    &amp;&amp; requires (const SeedSequence&amp; s, OutputIterator out) {
        { s.size() } -&gt; same_as&lt;size_t&gt;;
        { s.param(out) } -&gt; same_as&lt;void&gt;;
    };</pre>
      <p>
        For better readability, the above code uses the hypothetical concept <code>__unsigned_integral_least32</code>
        which <em>could</em> be defined like this.
      </p>
    <pre>template &lt;typename T&gt;
concept __unsigned_integral_least32 = unsigned_integral&lt;T&gt; &amp;&amp; numeric_limits&lt;T&gt;::digits &gt;= 32;</pre>
    </blockquote>
    <p>Add the following new section.</p>
    <blockquote class="insert">
      <p><strong>Class template <code>seed_adapter</code> [rand.req.seedadapt]</strong></p>
<pre>template &lt;uniform_random_bit_generator U&gt;
class seed_adapter
{
public:
  // types
  using result_type = typename U::result_type;

  // constructors
  explicit constexpr seed_adapter(U&amp; gen) noexcept;

  // generating functions
  template &lt;random_access_iterator It&gt;
    void constexpr generate(const It f, const It l)
    requires __unsigned_integral_least32&lt;typename iterator_traits&lt;It&gt;::value_type&gt;;

private:
  U* m_gen;  // exposition only
};</pre>
      <pre>explicit constexpr seed_adapter(U&amp; gen) noexcept;</pre>
      <p><em>Effects:</em> Stores the address of <code>gen</code> in <code>m_gen</code>.</p>
      <pre>template &lt;random_access_iterator It&gt;
  void constexpr generate(const It begin, const It end)
  requires __unsigned_integral_least32&lt;typename iterator_traits&lt;It&gt;::value_type&gt;;</pre>
      <p><em>Preconditions:</em> The address stored in <code>m_gen</code> (still) refers to a valid object.</p>
      <p><em>Effects:</em> Fills the range [<code>begin</code>, <code>end</code>) with 32 bit values obtained from <code>*m_gen</code>.</p>
      <p><em>Complexity:</em> <var>&Omicron;</var>(<code>end</code> &minus; <code>begin</code>)</p>
    </blockquote>
    <p>
      Restructure the first seven rows of the current table&nbsp;94 as follows.  It is believed that this preserves the
      intended meaning of the current wording but avoids confusion.
    </p>
    <blockquote>
      <p><!-- phantom space --></p>
      <table border="1" cellspacing="0" cellpadding="5">
        <tr>
          <th><p>Expression</p></th>
          <th><p>Return type</p></th>
          <th><p>Pre/post-condition</p></th>
          <th><p>Complexity</p></th>
        </tr>
        <tr>
          <td><p><code>E()</code></p></td>
          <td><p></p></td>
          <td>
            <p>
              Creates an engine with the same initial state as all other default-constructed engines of type
              <code>E</code>.
            </p>
          </td>
          <td><p><var>&Omicron;</var>(size of state)</p></td>
        </tr>
        <tr>
          <td><p><code>E(x)</code></p></td>
          <td><p></p></td>
          <td>
            <p>
              Creates an engine that compares equal to <code>x</code>.
            </p>
          </td>
          <td><p><var>&Omicron;</var>(size of state)</p></td>
        </tr>
        <tr>
          <td><p><code>E(s)</code></p></td>
          <td><p></p></td>
          <td>
            <p>
              Creates an engine with initial state determined by <code>s</code>.<br />
              <ins>
                [&nbsp;<em>Note:</em> For engines with an internal state larger than <code>sizeof(s)</code>, there
                will be impossible states that cannot be created using this constructor.
                &mdash;&nbsp;<em>end note</em>&nbsp;]
              </ins>
            </p>
          </td>
          <td><p><var>&Omicron;</var>(size of state)</p></td>
        </tr>
        <tr>
          <td><p><code>E(q)</code></p></td>
          <td><p></p></td>
          <td>
            <p>
              Creates an engine with an initial state that depends on a sequence produced by one call
              to <code>q.generate</code>.<br />
              <ins>
                [&nbsp;<em>Note:</em> Depending on the behavior of <code>q.generate</code>, this operation might not be
                deterministic.  &mdash;&nbsp;<em>end note</em>&nbsp;]
              </ins>
            </p>
          </td>
          <td>
            <p>same as complexity of <code>q.generate</code> called on a range of the size of the engine's state</p>
          </td>
        </tr>
        <tr>
          <td><p><code>e.seed()</code></p></td>
          <td><p><code>void</code></p></td>
          <td>
            <p>
              <del><em>Postconditions:</em> e == E().</del>
              <ins>Equivalent to <code>e = E()</code>.</ins>
            </p>
          </td>
          <td>
            <p>
              <del>same as <code>E()</code></del>
              <ins>not worse than <code>e = E()</code></ins>
            </p>
          </td>
        </tr>
        <tr>
          <td><p><code>e.seed(s)</code></p></td>
          <td><p><code>void</code></p></td>
          <td>
            <p>
              <del><em>Postconditions:</em> e == E(s).</del>
              <ins>Equivalent to <code>e = E(s)</code>.</ins>
            </p>
          </td>
          <td>
            <p>
              <del>same as <code>E(s)</code></del>
              <ins>not worse than <code>e = E(s)</code></ins>
            </p>
          </td>
        </tr>
        <tr>
          <td><p><code>e.seed(q)</code></p></td>
          <td><p><code>void</code></p></td>
          <td>
            <p>
              <del><em>Postconditions:</em> e == E(q).</del>
              <ins>Equivalent to <code>e = E(q)</code>.</ins>
            </p>
          </td>
          <td>
            <p>
              <del>same as <code>E(q)</code></del>
              <ins>not worse than <code>e = E(q)</code></ins>
            </p>
          </td>
        </tr>
      </table>
      <p><!-- phantom space --></p>
    </blockquote>
    <h2 id="sec-acknowledgments">Acknowledgments</h2>
    <p>
      Melissa O'Neill has written a series of remarkable blog posts that discuss the problems with seeding random
      engines in-depth.  Although not the initial motivation for the author of this proposal, that blog post provided
      valuable theoretical and experimental support and the fact that its author had independently suggested basically
      the same (revision&nbsp;0) addition to the standard library was very affirming.
    </p>
    <p>
      The discussions with the principal author of <code>&lt;random&gt;</code>, Walter Brown, were very enlightening and
      helped the author a lot figuring out the final details of the proposal (revision&nbsp;0).
    </p>
    <p>
      Nicol Bolas, Zhihao Yuan and Seth Cantrell have provided valuable feedback on the
      <code>std-proposals@isocpp.org</code> mailing list (revision&nbsp;0).
    </p>
    <p>
      Baum mit Augen's shared experience of struggling to properly seed a <code>std::mt19937</code> from
      a <code>std::random_device</code> and the following discussion with Deduplicator (out of which came an earlier
      version of the code for <code>seed_non_deterministically_2nd</code>) were part of the motivation for writing this
      proposal&nbsp;[<a href="#ref-03">6</a>].
    </p>
    <p>
      Jonathan Wakely has provided valuable feedback regarding the use-case of custom seed sequence implementations and
      pointed the author to the current state of this proposal in the library evolution working group.
    </p>
    <h2 id="sec-changelog">Changelog</h2>
    <p>
      The following changes were made compared to
      <a class="external" rel="external nofollow noreferrer" href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0205r0.html">revision&nbsp;0</a>
      of this proposal:
    </p>
    <ul>
      <li>
        Instead of proposing modifications to <code>std::random_device</code>, the formerly <q>alternative solution</q>
        of introducing a generic adapter type is now proposed instead.  This change is motivated by feedback regarding
        the usability with types other than <code>std::random_device</code> and compatibility with
        <a class="external" rel="external nofollow noreferrer" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1068r4.pdf">P1068R4</a>
        in particular.
      </li>
      <li>
        The named requirements are accompanied by formal C++20 concepts.
      </li>
      <li>
        The wording and references were updated to the C++20 standard.
      </li>
      <li>
        The title was changed from
        <q>Allow Seeding Random Number Engines with <code>std::random_device</code></q>
        to
        <q>Efficient Seeding of Random Number Engines</q>
        to account for the broadened scope of this proposal.
      </li>
    </ul>
    <p>
      The feedback given by LEWG regarding the relaxation of the restriction to 32&#x202f;bit integer types
      was <em>not</em> applied (yet) because the author does not know how this could be done in a backwards-compatible
      (with C++11 to C++20) way.  We would have to strengthen an existing named requirement for that.
    </p>
    <h2 id="sec-references">References</h2>
    <ol class="references">
      <li id="ref-01">
        Melissa O'Neill,
        <em>C++ Seeding Surprises.</em>  2015-04-16,
        <a class="external" rel="external nofollow noreferrer" href="http://www.pcg-random.org/posts/cpp-seeding-surprises.html">http://www.pcg-random.org/posts/cpp-seeding-surprises.html</a>
      </li>
      <li id="ref-02">
        Nicol Bolas, via <code>std-proposals@isocpp.org</code>, 2016-01-03,
        <a class="external" rel="external nofollow noreferrer" href="https://groups.google.com/a/isocpp.org/d/msg/std-proposals/sF-P4VE2Z3Q/u24T-g-hEgAJ">https://groups.google.com/a/isocpp.org/d/msg/std-proposals/sF-P4VE2Z3Q/u24T-g-hEgAJ</a>
      </li>
      <li id="ref-03">
        <q>Seed <code>std::mt19937</code> from <code>std::random_device</code></q>
        in: <em>Code Review</em>,
        2015-10-30,
        <a class="external" rel="external nofollow noreferrer" href="http://codereview.stackexchange.com/q/109260">http://codereview.stackexchange.com/q/109260</a>
      </li>
    </ol>
  </body>
</html>
