Class: Random::MT19937
- Defined in:
- lib/vendor/backports-3.3.5/lib/backports/extra/random/MT19937.rb,
lib/vendor/backports-3.3.5/lib/backports/extra/random/bits_and_bytes.rb
Overview
Supplement the MT19937 class with methods to do conversions the same way as MRI. No argument checking is done here either.
Constant Summary collapse
- STATE_SIZE =
624
- LAST_STATE =
STATE_SIZE - 1
- PAD_32_BITS =
0xffffffff
- LAST_31_BITS =
0x7fffffff
- OFFSET =
397
- FLOAT_FACTOR =
1.0/9007199254740992.0
Class Method Summary collapse
- .[](seed) ⇒ Object
-
.convert_seed(seed) ⇒ Object
Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers.
Instance Method Summary collapse
-
#initialize(seed) ⇒ MT19937
constructor
See seed=.
-
#left ⇒ Object
It’s actually the number of words left + 1, as per MRI…
- #marshal_dump ⇒ Object
- #marshal_load(ary) ⇒ Object
-
#next_state ⇒ Object
Generates a completely new state out of the previous one.
-
#random_32_bits ⇒ Object
Returns a random Integer from the range 0 …
- #random_bytes(nb) ⇒ Object
-
#random_float ⇒ Object
generates a random number on [0,1) with 53-bit resolution.
-
#random_integer(upto) ⇒ Object
Returns an integer within 0…upto.
-
#seed=(seed) ⇒ Object
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).
- #state_as_bignum ⇒ Object
Constructor Details
#initialize(seed) ⇒ MT19937
See seed=
9 10 11 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/random/MT19937.rb', line 9 def initialize(seed) self.seed = seed end |
Class Method Details
.[](seed) ⇒ Object
78 79 80 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/random/bits_and_bytes.rb', line 78 def self.[](seed) new(convert_seed(seed)) end |
.convert_seed(seed) ⇒ Object
Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers
65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 |
Instance Method Details
#left ⇒ Object
It’s actually the number of words left + 1, as per MRI…
46 47 48 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 ⇒ Object
50 51 52 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/random/bits_and_bytes.rb', line 50 def marshal_dump [state_as_bignum, left] end |
#marshal_load(ary) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 ⇒ Object
Generates a completely new state out of the previous one.
17 18 19 20 21 22 23 24 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 ⇒ Object
Returns a random Integer from the range 0 … (1 << 32)
65 66 67 68 69 70 71 72 73 74 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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) ⇒ Object
32 33 34 35 36 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 ⇒ Object
generates a random number on [0,1) with 53-bit resolution
9 10 11 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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) ⇒ Object
Returns an integer within 0…upto
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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) ⇒ Object
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
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 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 ⇒ Object
38 39 40 41 42 43 44 |
# File 'lib/vendor/backports-3.3.5/lib/backports/extra/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 |