summaryrefslogtreecommitdiff
path: root/absl/random/internal/uniform_helper.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-08-02 14:23:26 -0700
committerGravatar Derek Mauro <dmauro@google.com>2020-08-03 13:24:24 -0400
commit1995c6a3c2f9080160d9d8716504dc004e5e1ec0 (patch)
tree0b1e861b0d2c16f78d0f2e861a94a2bccf38965a /absl/random/internal/uniform_helper.h
parent184cf2524101310a0ba315c743e82cf45fccccf8 (diff)
Export of internal Abseil changes
-- 790f9061df340cd900e8da70e66c363f7af3c2eb by Abseil Team <absl-team@google.com>: Add support for rvalue reference to function types. PiperOrigin-RevId: 324508531 -- 51fe201dbb41a3ebc3d49ff65250b5f464279d43 by Abseil Team <absl-team@google.com>: Cleaning up function comment style; no substantive change. PiperOrigin-RevId: 324497401 -- da8595d5266577d0c170528d12f6de17b8affcc2 by Abseil Team <absl-team@google.com>: Add support for demangling GNU vector types. PiperOrigin-RevId: 324494559 -- 0cb0acf88c1750f6963c9cb85249f9b4f0bd5104 by Abseil Team <absl-team@google.com>: Add support for thread-local types. PiperOrigin-RevId: 324491183 -- c676bc8380560599cd26f7f231e04e6be532e904 by Abseil Team <absl-team@google.com>: Add support for demangling "Du" (char8_t). PiperOrigin-RevId: 324441607 -- b218bf6467bc62b327214782c881e8224ad91509 by Abseil Team <absl-team@google.com>: Update doc comments in header of `any.h` to reflect that `absl::variant` has been released. PiperOrigin-RevId: 324431690 -- e5b579f3f1aa598c1f62e71dba7103b98811de59 by Laramie Leavitt <lar@google.com>: Bugfix: Fix bounds in absl::Uniform where one of the bounds is min/max. When absl::Uniform(rng, tag, a, b) is called, the tag is used in conjunction with the type to determine whether or not to manipulate the bounds to make them inclusive or exclusive through the uniform_*_bound functions. Unfortunately, at limits of the interval the function was not well behaved. The previous implementation used wrapping arithmetic. This causes incorrect bounds computation at the extremes (numeric_limits::min / numeric_limits::max) the bound would wrap. Improve this situation by: 1/ Changing the uniform_*_bound functions to use saturating arithmetic instead of wrapping, thus in the unsigned case, the upper_bound of IntervalOpenOpen for 0 is now 0, rather than numeric_limits::max, likewise for the lower bound. 2/ Adjusting the hi/lo checks in the distributions. When the interval is empty, such as for absl::Uniform(absl::IntervalOpenOpen, gen, 1, 0), the return value is somewhat nonsensical. Now absl::Uniform more consistently returns the low input rather than any adjusted input. In the above case, that means that 1 is returned rather than 2. NOTE: Calls to absl::Uniform where the resolved upper bound is < the lower bound are still ill-formed and should be avoided. 3/ Adding better tests. The underlying uniform_*_distribution classes are not affected. PiperOrigin-RevId: 324240873 GitOrigin-RevId: 790f9061df340cd900e8da70e66c363f7af3c2eb Change-Id: I2a2208650ea3135c575e200b868ce1d275069fc8
Diffstat (limited to 'absl/random/internal/uniform_helper.h')
-rw-r--r--absl/random/internal/uniform_helper.h38
1 files changed, 36 insertions, 2 deletions
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index 5b2afecb..1243bc1c 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -105,7 +105,7 @@ typename absl::enable_if_t<
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
IntType>
uniform_lower_bound(Tag, IntType a, IntType) {
- return a + 1;
+ return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;
}
template <typename FloatType, typename Tag>
@@ -136,7 +136,7 @@ typename absl::enable_if_t<
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
IntType>
uniform_upper_bound(Tag, IntType, IntType b) {
- return b - 1;
+ return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;
}
template <typename FloatType, typename Tag>
@@ -172,6 +172,40 @@ uniform_upper_bound(Tag, FloatType, FloatType b) {
return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
}
+// Returns whether the bounds are valid for the underlying distribution.
+// Inputs must have already been resolved via uniform_*_bound calls.
+//
+// The c++ standard constraints in [rand.dist.uni.int] are listed as:
+// requires: lo <= hi.
+//
+// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus:
+// [0, 0] is legal.
+// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0].
+// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1].
+// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1].
+//
+// The c++ standard constraints in [rand.dist.uni.real] are listed as:
+// requires: lo <= hi.
+// requires: (hi - lo) <= numeric_limits<T>::max()
+//
+// In the uniform_real_distribution, {lo, hi} are closed, open, Thus:
+// [0, 0] is legal, which is [0, 0+epsilon).
+// [0, 0) is legal.
+// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is.
+// (0, 0] is not legal, but (0, 0+epsilon] is.
+//
+template <typename FloatType>
+absl::enable_if_t<std::is_floating_point<FloatType>::value, bool>
+is_uniform_range_valid(FloatType a, FloatType b) {
+ return a <= b && std::isfinite(b - a);
+}
+
+template <typename IntType>
+absl::enable_if_t<std::is_integral<IntType>::value, bool>
+is_uniform_range_valid(IntType a, IntType b) {
+ return a <= b;
+}
+
// UniformDistribution selects either absl::uniform_int_distribution
// or absl::uniform_real_distribution depending on the NumType parameter.
template <typename NumType>