From 15fbd05e4e53798ee80cc21af22a53edc3c8229b Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 10 May 2016 06:46:09 +0000 Subject: [PATCH] random.c: reuse bits * random.c (random_ulong_limited): reduce calling bytes methods by reusing dropped bits. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54969 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- random.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/random.c b/random.c index 21d1ea0840..a3476d5203 100644 --- a/random.c +++ b/random.c @@ -991,9 +991,21 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit) { if (!limit) return 0; if (!rnd) { - unsigned long val, mask = make_mask(limit); + const int w = sizeof(limit) * CHAR_BIT - nlz_long(limit); + const int n = w > 32 ? sizeof(unsigned long) : sizeof(uint32_t); + const unsigned long mask = ~(~0UL << w); + const unsigned long full = ~(~0UL << n * CHAR_BIT); + unsigned long val, bits = 0, rest = 0; do { - obj_random_bytes(obj, &val, sizeof(unsigned long)); + if (mask & ~rest) { + union {uint32_t u32; unsigned long ul;} buf; + obj_random_bytes(obj, &buf, n); + rest = full; + bits = (n == sizeof(uint32_t)) ? buf.u32 : buf.ul; + } + val = bits; + bits >>= w; + rest >>= w; val &= mask; } while (limit < val); return val;