Class Random::MT19937
In: lib/backports/1.9.2/random/MT19937.rb
lib/backports/1.9.2/random/bits_and_bytes.rb
Parent: Object

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

Methods

Constants

STATE_SIZE = 624
LAST_STATE = STATE_SIZE - 1
PAD_32_BITS = 0xffffffff
LAST_31_BITS = 0x7fffffff
OFFSET = 397
FLOAT_FACTOR = 1.0/9007199254740992.0
MASK_BY = [1,2,4,8,16]

Public Class methods

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 78
78:     def self.[](seed)
79:       new(convert_seed(seed))
80:     end

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

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 65
65:     def self.convert_seed(seed)
66:       seed = seed.abs
67:       long_values = []
68:       begin
69:         long_values << (seed & PAD_32_BITS)
70:         seed >>= 32
71:       end until seed == 0
72: 
73:       long_values.pop if long_values[-1] == 1 && long_values.size > 1 # Done to allow any kind of sequence of integers
74: 
75:       long_values.size > 1 ? long_values : long_values.first
76:     end

See seed=

[Source]

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

Public Instance methods

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 46
46:     def left # It's actually the number of words left + 1, as per MRI...
47:       MT19937::STATE_SIZE - @last_read
48:     end

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 50
50:     def marshal_dump
51:       [state_as_bignum, left]
52:     end

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 54
54:     def marshal_load(ary)
55:       b, left = ary
56:       @last_read = MT19937::STATE_SIZE - left
57:       @state = Array.new(STATE_SIZE)
58:       STATE_SIZE.times do |i|
59:         @state[i] = b & PAD_32_BITS
60:         b >>= 32
61:       end
62:     end

Generates a completely new state out of the previous one.

[Source]

    # File lib/backports/1.9.2/random/MT19937.rb, line 17
17:     def next_state
18:       STATE_SIZE.times do |i|
19:         mix = @state[i] & 0x80000000 | @state[i+1 - STATE_SIZE] & 0x7fffffff
20:         @state[i] = @state[i+OFFSET - STATE_SIZE] ^ (mix >> 1)
21:         @state[i] ^= 0x9908b0df if mix.odd?
22:       end
23:       @last_read = -1
24:     end

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

[Source]

    # File lib/backports/1.9.2/random/MT19937.rb, line 65
65:     def random_32_bits
66:       next_state if @last_read >= LAST_STATE
67:       @last_read += 1
68:       y = @state[@last_read]
69:       # Tempering
70:       y ^= (y >> 11)
71:       y ^= (y << 7) & 0x9d2c5680
72:       y ^= (y << 15) & 0xefc60000
73:       y ^= (y >> 18)
74:     end

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 32
32:     def random_bytes(nb)
33:       nb_32_bits = (nb + 3) / 4
34:       random = nb_32_bits.times.map { random_32_bits }
35:       random.pack("L" * nb_32_bits)[0, nb]
36:     end

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

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 9
 9:     def random_float
10:       ((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
11:     end

Returns an integer within 0...upto

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 14
14:     def random_integer(upto)
15:       n = upto - 1
16:       nb_full_32 = 0
17:       while n > PAD_32_BITS
18:         n >>= 32
19:         nb_full_32 += 1
20:       end
21:       mask = mask_32_bits(n)
22:       begin
23:         rand = random_32_bits & mask
24:         nb_full_32.times do
25:           rand <<= 32
26:           rand |= random_32_bits
27:         end
28:       end until rand < upto
29:       rand
30:     end

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

[Source]

    # File lib/backports/1.9.2/random/MT19937.rb, line 30
30:     def seed=(seed)
31:       case seed
32:       when Integer
33:         @state = Array.new(STATE_SIZE)
34:         @state[0] = seed & PAD_32_BITS
35:         (1..LAST_STATE).each do |i|
36:           @state[i] = (1812433253 * (@state[i-1]  ^ @state[i-1]>>30) + i)& PAD_32_BITS
37:         end
38:         @last_read = LAST_STATE
39:       when Array
40:         self.seed = 19650218
41:         i=1
42:         j=0
43:         [STATE_SIZE, seed.size].max.times do
44:           @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1664525) + j + seed[j] & PAD_32_BITS
45:           if (i+=1) >= STATE_SIZE
46:             @state[0] = @state[-1]
47:             i = 1
48:           end
49:           j = 0 if (j+=1) >= seed.size
50:         end
51:         (STATE_SIZE-1).times do
52:           @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1566083941) - i & PAD_32_BITS
53:           if (i+=1) >= STATE_SIZE
54:             @state[0] = @state[-1]
55:             i = 1
56:           end
57:         end
58:         @state[0] = 0x80000000
59:       else
60:         raise ArgumentError, "Seed must be an Integer or an Array"
61:       end
62:     end

[Source]

    # File lib/backports/1.9.2/random/bits_and_bytes.rb, line 38
38:     def state_as_bignum
39:       b = 0
40:       @state.each_with_index do |val, i|
41:         b |= val << (32 * i)
42:       end
43:       b
44:     end

[Validate]