<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - std::generate_canonical can produce 1.0"
   href="https://bugs.llvm.org/show_bug.cgi?id=34932">34932</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>std::generate_canonical can produce 1.0
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>5.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>thiago@kde.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Take the following 64-bit generator:

struct G
{
    typedef uint64_t result_type;
    result_type operator()() { return ~0ULL; }
    static constexpr result_type min() { return
(std::numeric_limits<result_type>::min)(); }
    static constexpr result_type max() { return
(std::numeric_limits<result_type>::max)(); }
};

When used with std::generate_canonical, like so:

double generateDouble3(uint64_t x)
{
    G rd;
    return std::generate_canonical<double, 64>(rd);
}

It will produce a result of exact 1.0. See <a href="https://godbolt.org/g/A1Wfhx">https://godbolt.org/g/A1Wfhx</a> for
compilation.

The reason for that is the rounding. The implementation does:

Then:

    _RealType __base = _Rp;  // 2.0 ^ 64
    _RealType _Sp = __g() - _URNG::min();
    for (size_t __i = 1; __i < __k; ++__i, __base *= _Rp) // does not execute
(__k == 1)
        _Sp += (__g() - _URNG::min()) * __base;
    return _Sp / __base;

When the input is in the range 0xfffffffffffff000 to 0xffffffffffffffff, the
division  the last line is an exact result of (1.0L - 0x1.p-53) to (1.0L -
0x1.p-64), but those round up to 1.0.

libstdc++ catches this case and returns std::nextafter<_RealType>(1, 0) [the
largest _RealType smaller than 1].</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>