From ba9f6a2c3b8e775f2e49eaead6fac9ba21a1ced8 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 7 Feb 2011 10:55:41 -0500 Subject: [PATCH] now random spans over 0..RAND_MAX, or -RAND_MAX/2..RAND_MAX/2 for signed types, or the most significant bits for smaller integer types. --- Eigen/Core | 1 + Eigen/src/Core/MathFunctions.h | 64 ++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Eigen/Core b/Eigen/Core index 190832398..da84ca1bb 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -152,6 +152,7 @@ #include #include #include +#include // for CHAR_BIT // for min/max: #include diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 4138ab436..3f1405c62 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -756,7 +756,7 @@ struct random_default_impl { static inline Scalar run(const Scalar& x, const Scalar& y) { - return x + (y-x) * Scalar(std::rand()) / float(RAND_MAX); + return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); } static inline Scalar run() { @@ -764,16 +764,76 @@ struct random_default_impl } }; +enum { + floor_log2_terminate, + floor_log2_move_up, + floor_log2_move_down, + floor_log2_bogus +}; + +template struct floor_log2_selector +{ + enum { middle = (lower + upper) / 2, + value = (upper <= lower + 1) ? int(floor_log2_terminate) + : (n < (1 << middle)) ? int(floor_log2_move_down) + : (n==0) ? int(floor_log2_bogus) + : int(floor_log2_move_up) + }; +}; + +template::value> +struct floor_log2 {}; + +template +struct floor_log2 +{ + enum { value = floor_log2::middle>::value }; +}; + +template +struct floor_log2 +{ + enum { value = floor_log2::middle, upper>::value }; +}; + +template +struct floor_log2 +{ + enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; +}; + +template +struct floor_log2 +{ + // no value, error at compile time +}; + template struct random_default_impl { + typedef typename NumTraits::NonInteger NonInteger; + static inline Scalar run(const Scalar& x, const Scalar& y) { - return x + Scalar((y-x+1) * (std::rand() / (RAND_MAX + typename NumTraits::NonInteger(1)))); + return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1))); } + static inline Scalar run() { +#ifdef EIGEN_MAKING_DOCS return run(Scalar(NumTraits::IsSigned ? -10 : 0), Scalar(10)); +#else + enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value, + scalar_bits = sizeof(Scalar) * CHAR_BIT, + shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)) + }; + Scalar x = Scalar(std::rand() >> shift); + Scalar offset = NumTraits::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0); + return x - offset; +#endif } };