diff options
author | Benoit Jacob <jacob.benoit.1@gmail.com> | 2011-02-07 10:55:41 -0500 |
---|---|---|
committer | Benoit Jacob <jacob.benoit.1@gmail.com> | 2011-02-07 10:55:41 -0500 |
commit | ba9f6a2c3b8e775f2e49eaead6fac9ba21a1ced8 (patch) | |
tree | cbe8cefc9576c7a46fa58e511ce5225244d5a95c | |
parent | 3386a946f8d061fc89e813b64761055fa9bb4647 (diff) |
now random<integer types> spans over 0..RAND_MAX, or -RAND_MAX/2..RAND_MAX/2 for signed types, or the most significant bits for smaller integer types.
-rw-r--r-- | Eigen/Core | 1 | ||||
-rw-r--r-- | 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 <cstring> #include <string> #include <limits> +#include <climits> // for CHAR_BIT // for min/max: #include <algorithm> 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<Scalar, false, false> { 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<Scalar, false, false> } }; +enum { + floor_log2_terminate, + floor_log2_move_up, + floor_log2_move_down, + floor_log2_bogus +}; + +template<unsigned int n, int lower, int upper> 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<unsigned int n, + int lower = 0, + int upper = sizeof(unsigned int) * CHAR_BIT - 1, + int selector = floor_log2_selector<n, lower, upper>::value> +struct floor_log2 {}; + +template<unsigned int n, int lower, int upper> +struct floor_log2<n, lower, upper, floor_log2_move_down> +{ + enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value }; +}; + +template<unsigned int n, int lower, int upper> +struct floor_log2<n, lower, upper, floor_log2_move_up> +{ + enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value }; +}; + +template<unsigned int n, int lower, int upper> +struct floor_log2<n, lower, upper, floor_log2_terminate> +{ + enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; +}; + +template<unsigned int n, int lower, int upper> +struct floor_log2<n, lower, upper, floor_log2_bogus> +{ + // no value, error at compile time +}; + template<typename Scalar> struct random_default_impl<Scalar, false, true> { + typedef typename NumTraits<Scalar>::NonInteger NonInteger; + static inline Scalar run(const Scalar& x, const Scalar& y) { - return x + Scalar((y-x+1) * (std::rand() / (RAND_MAX + typename NumTraits<Scalar>::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<Scalar>::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<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0); + return x - offset; +#endif } }; |