aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib/random
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2018-04-19 10:33:42 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-04-19 10:36:13 -0700
commit6a7779f3384e48012d3e27ae0f48d410f5174d06 (patch)
treeaa202c75c264095193250261fa13868e65a0fdc6 /tensorflow/core/lib/random
parentba3bc495bbf1140e9375e1ec03c3ff788b8ebc6e (diff)
Fix undefined signed integer overflow by performing addition more carefully.
PiperOrigin-RevId: 193537461
Diffstat (limited to 'tensorflow/core/lib/random')
-rw-r--r--tensorflow/core/lib/random/random_distributions.h19
1 files changed, 17 insertions, 2 deletions
diff --git a/tensorflow/core/lib/random/random_distributions.h b/tensorflow/core/lib/random/random_distributions.h
index 4cf3a999f6..e963511f5c 100644
--- a/tensorflow/core/lib/random/random_distributions.h
+++ b/tensorflow/core/lib/random/random_distributions.h
@@ -23,6 +23,7 @@ limitations under the License.
#include <string.h>
#include <algorithm>
+#include <type_traits>
#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/lib/bfloat16/bfloat16.h"
@@ -40,6 +41,20 @@ PHILOX_DEVICE_INLINE float Uint32ToFloat(uint32 x);
// Helper function to convert two 32-bit integers to a double between [0..1).
PHILOX_DEVICE_INLINE double Uint64ToDouble(uint32 x0, uint32 x1);
+// Computes a + b. Requires that the result is representable in the destination
+// type and that b is not maximal (i.e. b + 1 is not 0). Notably, the addend b
+// need *not* be representable in that type. (The condition on b excludes the
+// extremal case INT_MIN + UINT_MAX = INT_MAX, which this function cannot
+// compute.)
+template <typename Int>
+PHILOX_DEVICE_INLINE Int SignedAdd(Int a,
+ typename std::make_unsigned<Int>::type b) {
+ // Implementation note: both b_div_2 and b - b_div_2 are positive and
+ // representatble as Int.
+ auto b_div_2 = b >> 1;
+ return a + static_cast<Int>(b_div_2) + static_cast<Int>(b - b_div_2);
+}
+
// A class that generates uniform distribution random numbers from the
// underlying random integer generator.
// Arguments:
@@ -172,7 +187,7 @@ class UniformDistribution<Generator, int32> {
typename Generator::ResultType sample = (*gen)();
ResultType result;
for (int i = 0; i < kResultElementCount; ++i) {
- result[i] = lo_ + static_cast<int32>(sample[i] % range_);
+ result[i] = SignedAdd(lo_, sample[i] % range_);
}
return result;
}
@@ -208,7 +223,7 @@ class UniformDistribution<Generator, int64> {
ResultType result;
for (int i = 0; i < kResultElementCount; ++i) {
auto bits = sample[2 * i] | static_cast<uint64>(sample[2 * i + 1]) << 32;
- result[i] = lo_ + static_cast<int64>(bits % range_);
+ result[i] = SignedAdd(lo_, bits % range_);
}
return result;
}