Parent

Random::MT19937

An implementation of Mersenne Twister MT19937 in Ruby


Supplement the MT19937 class with methods to do conversions the same way as MRI. No argument checking is done here either.

Public Class Methods

[](seed) click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 78
def self.[](seed)
  new(convert_seed(seed))
end
convert_seed(seed) click to toggle source

Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers

# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 65
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
new(seed) click to toggle source

See seed=

# File lib/backports/1.9.2/random/MT19937.rb, line 9
def initialize(seed)
  self.seed = seed
end

Public Instance Methods

left() click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 46
def left # It's actually the number of words left + 1, as per MRI...
  MT19937::STATE_SIZE - @last_read
end
marshal_dump() click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 50
def marshal_dump
  [state_as_bignum, left]
end
marshal_load(ary) click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 54
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
next_state() click to toggle source

Generates a completely new state out of the previous one.

# File lib/backports/1.9.2/random/MT19937.rb, line 17
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
random_32_bits() click to toggle source

Returns a random Integer from the range 0 ... (1 << 32)

# File lib/backports/1.9.2/random/MT19937.rb, line 65
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
random_bytes(nb) click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 32
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
random_float() click to toggle source

generates a random number on [0,1) with 53-bit resolution

# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 9
def random_float
  ((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
end
random_integer(upto) click to toggle source

Returns an integer within 0...upto

# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 14
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
seed=(seed) click to toggle source

Seed must be either an Integer (only the first 32 bits will be used) or an Array of Integers (of which only the first 32 bits will be used)

No conversion or type checking is done at this level

# File lib/backports/1.9.2/random/MT19937.rb, line 30
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
state_as_bignum() click to toggle source
# File lib/backports/1.9.2/random/bits_and_bytes.rb, line 38
def state_as_bignum
  b = 0
  @state.each_with_index do |val, i|
    b |= val << (32 * i)
  end
  b
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.