diff options
author | A. Unique TensorFlower <gardener@tensorflow.org> | 2018-04-19 10:33:42 -0700 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2018-04-19 10:36:13 -0700 |
commit | 6a7779f3384e48012d3e27ae0f48d410f5174d06 (patch) | |
tree | aa202c75c264095193250261fa13868e65a0fdc6 /tensorflow/core/lib/random | |
parent | ba3bc495bbf1140e9375e1ec03c3ff788b8ebc6e (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.h | 19 |
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; } |