aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2016-08-23 13:25:31 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2016-08-23 13:25:31 +0200
commit82147cefffdf5ed445f79a8cdb57dd71012948bd (patch)
treec1263698ac72503262c72a90b91705ea707d86eb /Eigen/src/Core
parent581b6472d16c5dddfdc76762b3b76b5c933361a7 (diff)
Fix possible overflow and biais in integer random generator
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r--Eigen/src/Core/MathFunctions.h12
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);
}