diff options
author | Gael Guennebaud <g.gael@free.fr> | 2016-08-23 13:25:31 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2016-08-23 13:25:31 +0200 |
commit | 82147cefffdf5ed445f79a8cdb57dd71012948bd (patch) | |
tree | c1263698ac72503262c72a90b91705ea707d86eb /Eigen/src/Core | |
parent | 581b6472d16c5dddfdc76762b3b76b5c933361a7 (diff) |
Fix possible overflow and biais in integer random generator
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r-- | Eigen/src/Core/MathFunctions.h | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 9934e5601..ac7ef6d23 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -615,16 +615,18 @@ struct random_default_impl<Scalar, false, true> typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX; if(y<x) return x; + // the following difference might overflow on a 32 bits system, + // but since y>=x the result converted to an unsigned long is still correct. std::size_t range = ScalarX(y)-ScalarX(x); std::size_t offset = 0; // rejection sampling - std::size_t divisor = (range+RAND_MAX-1)/(range+1); - std::size_t multiplier = (range+RAND_MAX-1)/std::size_t(RAND_MAX); - + std::size_t divisor = 1; + std::size_t multiplier = 1; + if(range<RAND_MAX) divisor = (std::size_t(RAND_MAX)+1)/(range+1); + else multiplier = 1 + range/(std::size_t(RAND_MAX)+1); do { - offset = ( (std::size_t(std::rand()) * multiplier) / divisor ); + offset = (std::size_t(std::rand()) * multiplier) / divisor; } while (offset > range); - return Scalar(ScalarX(x) + offset); } |