Changes in v2:
* Re-initialize inner loop variables.
* Compute result optimistically, check outcome reliably.
Changes:
* Whitespace tweaks aside, this just strips out the existing fixup and
wraps the generator in a do .. while loop.
Implement P0952R2 "A new specification for std::generate_canonical".
It has us start over if the naive generation of a float in 0..1
comes up exactly equal to 1, which occurs too rarely for the change
to measurably affect performance.
A test for the case already appears in 64351.cc. This change amounts
to a different resolution for PR64351 and LWG 2524.
libstdc++-v3/ChangeLog:
PR libstdc++/119739
* include/bits/random.tcc
---
libstdc++-v3/include/bits/random.tcc | 40 +++++++++++-----------------
1 file changed, 15 insertions(+), 25 deletions(-)
diff --git a/libstdc++-v3/include/bits/random.tcc
b/libstdc++-v3/include/bits/random.tcc
index 53ccacb2e38..e2c90e52c48 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -3355,38 +3355,28 @@ namespace __detail
generate_canonical(_UniformRandomNumberGenerator& __urng)
{
static_assert(std::is_floating_point<_RealType>::value,
- "template argument must be a floating point type");
+ "template argument must be a floating point type");
- const size_t __b
- = std::min(static_cast<size_t>(std::numeric_limits<_RealType>::digits),
- __bits);
- const long double __r = static_cast<long double>(__urng.max())
- - static_cast<long double>(__urng.min()) + 1.0L;
+ const size_t __b = std::min(
+ static_cast<size_t>(std::numeric_limits<_RealType>::digits), __bits);
+ const long double __r =
+ static_cast<long double>(__urng.max()) -
+ static_cast<long double>(__urng.min()) + 1.0L;
const size_t __log2r = std::log(__r) / std::log(2.0L);
- const size_t __m = std::max<size_t>(1UL,
- (__b + __log2r - 1UL) / __log2r);
+ const size_t __m = std::max<size_t>(1UL, (__b + __log2r - 1UL) /
__log2r);
_RealType __ret;
- _RealType __sum = _RealType(0);
- _RealType __tmp = _RealType(1);
- for (size_t __k = __m; __k != 0; --__k)
+ do
{
- __sum += _RealType(__urng() - __urng.min()) * __tmp;
- __tmp *= __r;
- }
- __ret = __sum / __tmp;
- if (__builtin_expect(__ret >= _RealType(1), 0))
- {
-#if _GLIBCXX_USE_C99_MATH_FUNCS
- __ret = std::nextafter(_RealType(1), _RealType(0));
-#else
- __ret = _RealType(1)
- - std::numeric_limits<_RealType>::epsilon() / _RealType(2);
-#endif
- }
+ _RealType __sum = _RealType(0);
+ _RealType __tmp = _RealType(1);
+ for (size_t __k = __m; __k != 0; --__k, __tmp *= __r)
+ __sum += _RealType(__urng() - __urng.min()) * __tmp;
+ __ret = __sum / __tmp;
+ } while (__builtin_expect(__ret >= _RealType(1), false));
return __ret;
}
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
+ } // namespace
#endif
--
2.50.0