class RSpec::Core::Backports::Random::MT19937
An implementation of Mersenne Twister MT19937 in Ruby.
@private
def self.[](seed)
def self.[](seed) new(convert_seed(seed)) end
def self.convert_seed(seed)
Convert an Integer seed of arbitrary size to either a single 32 bit
def self.convert_seed(seed) seed = seed.abs long_values = [] begin long_values << (seed & PAD_32_BITS) seed >>= 32 end until seed == 0 # Done to allow any kind of sequence of integers. long_values.pop if long_values[-1] == 1 && long_values.size > 1 long_values.size > 1 ? long_values : long_values.first end
def initialize(seed)
def initialize(seed) self.seed = seed end
def left # It's actually the number of words left + 1, as per MRI...
def left # It's actually the number of words left + 1, as per MRI... MT19937::STATE_SIZE - @last_read end
def marshal_dump
def marshal_dump [state_as_bignum, left] end
def marshal_load(ary)
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
def mask_32_bits(n)
def mask_32_bits(n) MASK_BY.each do |shift| n |= n >> shift end n end
def next_state
def next_state STATE_SIZE.times do |i| mix = @state[i] & 0x80000000 | @state[i+1 - STATE_SIZE] & 0x7fffffff @state[i] = @state[i+OFFSET - STATE_SIZE] ^ (mix >> 1) @state[i] ^= 0x9908b0df if mix.odd? end @last_read = -1 end
def random_32_bits
def random_32_bits next_state if @last_read >= LAST_STATE @last_read += 1 y = @state[@last_read] # Tempering y ^= (y >> 11) y ^= (y << 7) & 0x9d2c5680 y ^= (y << 15) & 0xefc60000 y ^= (y >> 18) end
def random_bytes(nb)
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 random_float
def random_float ((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR; end
def random_integer(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 seed=(seed)
used).
or an Array of Integers (of which only the first 32 bits will be
Seed must be either an Integer (only the first 32 bits will be used)
def seed=(seed) case seed when Integer @state = Array.new(STATE_SIZE) @state[0] = seed & PAD_32_BITS (1..LAST_STATE).each do |i| @state[i] = (1812433253 * (@state[i-1] ^ @state[i-1]>>30) + i)& PAD_32_BITS end @last_read = LAST_STATE when Array self.seed = 19650218 i=1 j=0 [STATE_SIZE, seed.size].max.times do @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1664525) + j + seed[j] & PAD_32_BITS if (i+=1) >= STATE_SIZE @state[0] = @state[-1] i = 1 end j = 0 if (j+=1) >= seed.size end (STATE_SIZE-1).times do @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1566083941) - i & PAD_32_BITS if (i+=1) >= STATE_SIZE @state[0] = @state[-1] i = 1 end end @state[0] = 0x80000000 else raise ArgumentError, "Seed must be an Integer or an Array" end end
def state_as_bignum
def state_as_bignum b = 0 @state.each_with_index do |val, i| b |= val << (32 * i) end b end