From 32fbfc8e7410c86968ab57e2e235d33bb90782c3 Mon Sep 17 00:00:00 2001 From: Soeren Sonnenburg Date: Tue, 21 May 2013 22:40:13 +0200 Subject: [PATCH] use lower order bits in prng - This is about 2 times faster compared to the previous rng. - Add unit tests to ensure things are correct --- src/shogun/lib/Cache.h | 1 - src/shogun/lib/common.h | 6 -- src/shogun/mathematics/Math.h | 38 ++----- src/shogun/mathematics/Random.h | 62 ++++++++++- tests/unit/mathematics/Random_unittest.cc | 126 ++++++++++++++++++++-- 5 files changed, 185 insertions(+), 48 deletions(-) diff --git a/src/shogun/lib/Cache.h b/src/shogun/lib/Cache.h index 1abb546cbdc..76da9a6cce3 100644 --- a/src/shogun/lib/Cache.h +++ b/src/shogun/lib/Cache.h @@ -165,7 +165,6 @@ template class CCache : public CSGObject if (lookup_table) { // first look for the element with smallest usage count - //int64_t min_idx=((nr_cache_lines-1)*random())/(RAND_MAX+1); //avoid the last elem and the scratch line int64_t min_idx=0; int64_t min=-1; bool found_free_line=false; diff --git a/src/shogun/lib/common.h b/src/shogun/lib/common.h index ed0b944aa5b..1253b634059 100644 --- a/src/shogun/lib/common.h +++ b/src/shogun/lib/common.h @@ -19,12 +19,6 @@ #include #include -#ifndef LINUX -#define RANDOM_MAX 2147483647 -#else -#define RANDOM_MAX RAND_MAX -#endif - /**@name Standard Types * Definition of Platform independent Types */ diff --git a/src/shogun/mathematics/Math.h b/src/shogun/mathematics/Math.h index 5ec3c30a824..fb8fe8f85d1 100644 --- a/src/shogun/mathematics/Math.h +++ b/src/shogun/mathematics/Math.h @@ -461,64 +461,42 @@ class CMath : public CSGObject static inline uint64_t random() { - uint64_t rnd = sg_rand->random_64(); - - return rnd; + return sg_rand->random_64(); } static inline uint64_t random(uint64_t min_value, uint64_t max_value) { - uint64_t ret = min_value + (uint64_t) ((max_value-min_value+1) * (CMath::random() / (RAND_MAX_64))); - ASSERT(ret>=min_value && ret<=max_value) - return ret ; + return sg_rand->random(min_value, max_value); } static inline int64_t random(int64_t min_value, int64_t max_value) { - int64_t ret = min_value + (int64_t) ((max_value-min_value+1) * (CMath::random() / (RAND_MAX_64))); - ASSERT(ret>=min_value && ret<=max_value) - return ret ; + return sg_rand->random(min_value, max_value); } static inline uint32_t random(uint32_t min_value, uint32_t max_value) { - uint32_t ret = min_value + (uint32_t) ((max_value-min_value+1) * (CMath::random() / (RAND_MAX_64))); - ASSERT(ret>=min_value && ret<=max_value) - return ret ; + return sg_rand->random(min_value, max_value); } static inline int32_t random(int32_t min_value, int32_t max_value) { - int32_t ret = min_value + (int32_t) ((max_value-min_value+1) * (CMath::random() / (RAND_MAX_64))); - ASSERT(ret>=min_value && ret<=max_value) - return ret ; + return sg_rand->random(min_value, max_value); } static inline float32_t random(float32_t min_value, float32_t max_value) { - float32_t ret = min_value + ((max_value-min_value) * sg_rand->random_close()); - if (retmax_value) - SG_SPRINT("min_value:%10.10f value: %10.10f max_value:%10.10f", min_value, ret, max_value) - ASSERT(ret>=min_value && ret<=max_value) - return ret; + return sg_rand->random(min_value, max_value); } static inline float64_t random(float64_t min_value, float64_t max_value) { - float64_t ret = min_value + ((max_value-min_value) * sg_rand->random_close()); - if (retmax_value) - SG_SPRINT("min_value:%10.10f value: %10.10f max_value:%10.10f", min_value, ret, max_value) - ASSERT(ret>=min_value && ret<=max_value) - return ret; + return sg_rand->random(min_value, max_value); } static inline floatmax_t random(floatmax_t min_value, floatmax_t max_value) { - floatmax_t ret = min_value + ((max_value-min_value) * sg_rand->random_close()); - if (retmax_value) - SG_SPRINT("min_value:%10.10f value: %10.10f max_value:%10.10f", min_value, ret, max_value) - ASSERT(ret>=min_value && ret<=max_value) - return ret; + return sg_rand->random(min_value, max_value); } /// Returns a Gaussian or Normal random number. diff --git a/src/shogun/mathematics/Random.h b/src/shogun/mathematics/Random.h index 19ece2150b9..33db45c6242 100644 --- a/src/shogun/mathematics/Random.h +++ b/src/shogun/mathematics/Random.h @@ -18,9 +18,6 @@ #include #include -#define RAND_MAX_32 ((float32_t)std::numeric_limits::max()) -#define RAND_MAX_64 ((float64_t)std::numeric_limits::max()) - namespace shogun { /** @brief: Pseudo random number geneartor @@ -56,19 +53,74 @@ namespace shogun uint32_t get_seed() const; /** - * Generate an unsinged 32-bit random integer + * Generate an unsigned 32-bit random integer * * @return the random 32-bit unsigned integer */ uint32_t random_32() const; /** - * Generate an unsinged 64-bit random integer + * Generate an unsigned 64-bit random integer * * @return the random 64-bit unsigned integer */ uint64_t random_64() const; + /** + * Generate a signed 32-bit random integer + * + * @return the random 32-bit signed integer + */ + inline int32_t random_s32() const + { + return random_32() & 0x7fffffff; + } + + /** + * Generate a signed 64-bit random integer + * + * @return the random 64-bit signed integer + */ + int64_t random_s64() const + { + return random_64() & 0x7fffffffffffffffl; + } + + inline uint64_t random(uint64_t min_value, uint64_t max_value) + { + return min_value + random_64() % (max_value-min_value+1); + } + + inline int64_t random(int64_t min_value, int64_t max_value) + { + return min_value + random_s64() % (max_value-min_value+1); + } + + inline uint32_t random(uint32_t min_value, uint32_t max_value) + { + return min_value + random_32() % (max_value-min_value+1); + } + + inline int32_t random(int32_t min_value, int32_t max_value) + { + return min_value + random_s32() % (max_value-min_value+1); + } + + inline float32_t random(float32_t min_value, float32_t max_value) + { + return min_value + ((max_value-min_value) * random_close()); + } + + inline float64_t random(float64_t min_value, float64_t max_value) + { + return min_value + ((max_value-min_value) * random_close()); + } + + inline floatmax_t random(floatmax_t min_value, floatmax_t max_value) + { + return min_value + ((max_value-min_value) * random_close()); + } + /** * Fill an array of unsinged 32 bit integer * diff --git a/tests/unit/mathematics/Random_unittest.cc b/tests/unit/mathematics/Random_unittest.cc index 95c166edac7..2b324b5388c 100644 --- a/tests/unit/mathematics/Random_unittest.cc +++ b/tests/unit/mathematics/Random_unittest.cc @@ -3,9 +3,13 @@ #include #include #include +#include using namespace shogun; +const uint32_t n_runs=1200000; +const uint32_t array_len=23; + /** * NOTE: these unit tests were generated with MEXP=19937 * with other exponents it is expected to fail! @@ -193,17 +197,127 @@ TEST(Random, random_int32_1_2) } } -TEST(Random, random_int32_0_10) +TEST(Random, random_int64_range) { CMath::init_random(17); - int rnds[10] = {0,0,0,0,0,0}; - for (int32_t i=0; i<10000; i++) + int rnds[array_len]; + for (uint32_t i=0; i0); + for (uint32_t i=0; iset_seed(17); + int rnds[array_len]; + for (uint32_t i=0; irandom_32() % array_len; + rnds[r]++; + } + + for (uint32_t i=0; i