diff --git a/include/ulib/base/utility.h b/include/ulib/base/utility.h index bd83fb1b..797f7ee6 100644 --- a/include/ulib/base/utility.h +++ b/include/ulib/base/utility.h @@ -182,20 +182,77 @@ static inline uint32_t u_nextPowerOfTwo(uint32_t n) #endif } -/* Random number generator */ - -U_EXPORT double u_get_uniform(void); -U_EXPORT uint32_t u_get_num_random(uint32_t range); +/** + * Random number generator + * + * We use George Marsaglia's MWC algorithm to produce an unsigned integer + * + * see http://www.bobwheeler.com/statistics/Password/MarsagliaPost.txt + */ static inline void u_set_seed_random(uint32_t u, uint32_t v) { U_INTERNAL_TRACE("u_set_seed_random(%u,%u)", u, v) - if (u != 0) u_m_w = u; - if (v != 0) u_m_z = v; + U_INTERNAL_ASSERT_MAJOR(u, 0) + U_INTERNAL_ASSERT_MAJOR(v, 0) + + u_m_w = u; + u_m_z = v; +} + +static inline uint32_t u_get_num_random(void) +{ + U_INTERNAL_TRACE("u_get_num_random()") U_INTERNAL_ASSERT_MAJOR(u_m_w, 0) U_INTERNAL_ASSERT_MAJOR(u_m_z, 0) + + u_m_z = 36969 * (u_m_z & 65535) + (u_m_z >> 16); + u_m_w = 18000 * (u_m_w & 65535) + (u_m_w >> 16); + + return (u_m_z << 16) + u_m_w; /* 0 <= u < 2^32 */ +} + +static inline uint32_t u_get_num_random_range0(uint32_t range) +{ + uint32_t result; + + U_INTERNAL_TRACE("u_get_num_random_range0(%u)", range) + + U_INTERNAL_ASSERT_MAJOR(range, 1) + + result = u_get_num_random() % range; + + U_INTERNAL_ASSERT_MINOR(result,range) + + return result; +} + +static inline uint32_t u_get_num_random_range1(uint32_t range) +{ + uint32_t result; + + U_INTERNAL_TRACE("u_get_num_random_range1(%u)", range) + + U_INTERNAL_ASSERT_MAJOR(range, 2) + + result = (u_get_num_random() % (range-1))+1; + + U_INTERNAL_ASSERT_RANGE(1,result,range-1) + + return result; +} + +/* Produce a uniform random sample from the open interval (0, 1). The method will not return either end point */ + +static inline double u_get_uniform(void) +{ + U_INTERNAL_TRACE("u_get_uniform()") + + /* The magic number below is 1/(2^32 + 2). The result is strictly between 0 and 1 */ + + return (u_get_num_random() + 1.0) * 2.328306435454494e-10; } U_EXPORT const char* u_get_mimetype(const char* restrict suffix, int* pmime_index); diff --git a/include/ulib/utility/services.h b/include/ulib/utility/services.h index 0f097767..9b33c093 100644 --- a/include/ulib/utility/services.h +++ b/include/ulib/utility/services.h @@ -176,7 +176,10 @@ struct U_EXPORT UServices { UString code(len); char* ptr = code.data(); - for (uint32_t i = 0; i < len; ++i, ++ptr) *ptr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[u_get_num_random(64 - 3)]; + for (uint32_t i = 0; i < len; ++i, ++ptr) + { + *ptr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[u_get_num_random_range0(U_CONSTANT_SIZE("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))]; + } code.size_adjust(len); diff --git a/src/ulib/base/base.c b/src/ulib/base/base.c index d097f994..252ad2e0 100644 --- a/src/ulib/base/base.c +++ b/src/ulib/base/base.c @@ -514,7 +514,7 @@ void u_initRandom(void) /* seed the random generator */ - u_set_seed_random(u_seed_hash >> 16, u_seed_hash % 4294967296); + u_set_seed_random(1+(u_seed_hash >> 16), 1+(u_seed_hash % 4294967296)); } time_t u_getLocalNow(time_t sec) diff --git a/src/ulib/base/utility.c b/src/ulib/base/utility.c index cfe23dc7..32b932dd 100644 --- a/src/ulib/base/utility.c +++ b/src/ulib/base/utility.c @@ -2671,53 +2671,6 @@ int u_splitCommand(char* restrict s, uint32_t n, char** restrict argv, char* res return result; } -/** - * We use George Marsaglia's MWC algorithm to produce an unsigned integer. - * - * see http://www.bobwheeler.com/statistics/Password/MarsagliaPost.txt - */ - -uint32_t u_get_num_random(uint32_t range) -{ - uint32_t result; - - U_INTERNAL_TRACE("u_get_num_random(%u)", range) - - U_INTERNAL_ASSERT_MAJOR(u_m_w, 0) - U_INTERNAL_ASSERT_MAJOR(u_m_z, 0) - - u_m_z = 36969 * (u_m_z & 65535) + (u_m_z >> 16); - u_m_w = 18000 * (u_m_w & 65535) + (u_m_w >> 16); - - result = (u_m_z << 16) + u_m_w; - - if (range) - { - result = (result % range)+1; - - U_INTERNAL_ASSERT(result <= range) - } - - return result; -} - -/* Produce a uniform random sample from the open interval (0, 1). The method will not return either end point */ - -double u_get_uniform(void) -{ - uint32_t u; - - U_INTERNAL_TRACE("u_get_uniform()") - - /* 0 <= u < 2^32 */ - - u = u_get_num_random(0); - - /* The magic number below is 1/(2^32 + 2). The result is strictly between 0 and 1 */ - - return (u + 1.0) * 2.328306435454494e-10; -} - /** * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. Compares a filename or pathname to a pattern */ diff --git a/src/ulib/debug/error_simulation.cpp b/src/ulib/debug/error_simulation.cpp index db01c519..2d4e5cc0 100644 --- a/src/ulib/debug/error_simulation.cpp +++ b/src/ulib/debug/error_simulation.cpp @@ -126,7 +126,7 @@ void* USimulationError::checkForMatch(const char* call_name) uint32_t range = (uint32_t) strtol(file_ptr, &file_ptr, 10); - if (range > 0) match = (u_get_num_random(range) == (range / 2)); + if (range > 0) match = (u_get_num_random_range1(range) == (range / 2)); break; } diff --git a/src/ulib/net/server/plugin/usp/db.usp b/src/ulib/net/server/plugin/usp/db.usp index d9b05f08..439db544 100644 --- a/src/ulib/net/server/plugin/usp/db.usp +++ b/src/ulib/net/server/plugin/usp/db.usp @@ -32,7 +32,7 @@ static void usp_fork_db() - + - +