1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
module Backports
class Random
# Supplement the MT19937 class with methods to do
# conversions the same way as MRI.
# No argument checking is done here either.
class MT19937
FLOAT_FACTOR = 1.0/9007199254740992.0
# generates a random number on [0,1) with 53-bit resolution
def random_float
((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
end
# Returns an integer within 0...upto
def random_integer(upto)
n = upto - 1
nb_full_32 = 0
while n > PAD_32_BITS
n >>= 32
nb_full_32 += 1
end
mask = mask_32_bits(n)
begin
rand = random_32_bits & mask
nb_full_32.times do
rand <<= 32
rand |= random_32_bits
end
end until rand < upto
rand
end
def random_bytes(nb)
nb_32_bits = (nb + 3) / 4
random = nb_32_bits.times.map { random_32_bits }
random.pack("L" * nb_32_bits)[0, nb]
end
def state_as_bignum
b = 0
@state.each_with_index do |val, i|
b |= val << (32 * i)
end
b
end
def left # It's actually the number of words left + 1, as per MRI...
MT19937::STATE_SIZE - @last_read
end
def marshal_dump
[state_as_bignum, left]
end
def marshal_load(ary)
b, left = ary
@last_read = MT19937::STATE_SIZE - left
@state = Array.new(STATE_SIZE)
STATE_SIZE.times do |i|
@state[i] = b & PAD_32_BITS
b >>= 32
end
end
# Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers
def self.convert_seed(seed)
seed = seed.abs
long_values = []
begin
long_values << (seed & PAD_32_BITS)
seed >>= 32
end until seed == 0
long_values.pop if long_values[-1] == 1 && long_values.size > 1 # Done to allow any kind of sequence of integers
long_values.size > 1 ? long_values : long_values.first
end
def self.[](seed)
new(convert_seed(seed))
end
private
MASK_BY = [1,2,4,8,16]
def mask_32_bits(n)
MASK_BY.each do |shift|
n |= n >> shift
end
n
end
end
end
end
|