class FibonacciRng
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
The class of Fibonacci inspired random number generators.
Constants
- ASCII_7_BIT
The printable seven bit ASCII characters.
- BASE
- BYTE
- CHOP
- DEPTHS
- DOUBLE
- INITS
- TOP
- VERSION
- WORD
Attributes
The depth of the Fibonacci array.
The init value used by this generator.
The seed value used by this generator.
Public Class Methods
Initialize the PRN generator
# File lib/fibonacci_rng.rb, line 32 def initialize(arg_a=nil, arg_b=nil, arg_c=nil) #Extract the parameters. if arg_a.is_a?(Hash) seed = arg_a[:seed] @depth = arg_a[:depth] @init = arg_a[:init] else seed = arg_a @depth = arg_b @init = arg_c end #Set up the default parameters if needed. seed ||= FibonacciRng.new_seed @depth ||= 8 #Validate the depth. unless DEPTHS === @depth fail "Invalid depth value #{@depth}. Allowed values are #{DEPTHS}" end @init ||= 32 * @depth + 768 #Validate the depth. unless INITS === @init fail "Invalid init value #{@init}. Allowed values are #{INITS}" end #Build the generator. srand(seed) end
Get a random number from the class based generator. This exists only for compatibility purposes. It is far better to create instances of generators than to use a shared, global one.
Returns
-
The computed pseudo-random value.
# File lib/fibonacci_rng.rb, line 69 def self.rand(max=0) (@hidden ||= FibonacciRng.new).rand(max) end
Initialize the class based generator. This exists only for compatibility purposes. It is far better to create instances of generators than to use a shared, global one.
Returns
-
The old seed value.
# File lib/fibonacci_rng.rb, line 78 def self.srand(seed=FibonacciRng.new_seed, depth=8) old = (@hidden && @hidden.seed) @hidden = FibonacciRng.new(seed, depth) old end
Private Class Methods
Create the default seed string.
# File lib/fibonacci_rng/seeder.rb, line 41 def self.new_seed @sync.synchronize {Time.now.to_s + @tickle.succ!} end
Public Instance Methods
Append data to the generator
# File lib/fibonacci_rng/hasher.rb, line 19 def <<(data) (str = data.to_s).each_byte.each do |value| add_value(value) end do_spin if str.empty? validate end
Get a pseudo random byte
# File lib/fibonacci_rng/generator.rb, line 33 def byte do_spin validate @buffer[0] & BYTE end
Get a string of random bytes
# File lib/fibonacci_rng/generator.rb, line 40 def bytes(length) result = "" length.times {result << byte.chr} result end
Roll a dice.
# File lib/fibonacci_rng/generator.rb, line 21 def dice(sides) limit = ((CHOP+1) / sides) * sides begin do_spin end until (value = @buffer[0]) < limit validate value % sides end
Get a better pseudo random float
# File lib/fibonacci_rng/generator.rb, line 61 def double do_spin part_one = raw_float * BASE do_spin validate (part_one + raw_float) / DOUBLE end
Get a pseudo random float
# File lib/fibonacci_rng/generator.rb, line 54 def float do_spin validate raw_float / BASE end
Get the value of the rng state as a string.
# File lib/fibonacci_rng/hasher.rb, line 14 def hash_string hash_value.to_s(36) end
Get the value of the rng state as a number.
# File lib/fibonacci_rng/hasher.rb, line 7 def hash_value result = 0 @buffer[0...@depth].each {|value| result = (result << 29) + value } result end
A (mostly) compatible access point for random numbers.
Endemic Code Smells
-
:reek:FeatureEnvy
# File lib/fibonacci_rng/generator.rb, line 9 def rand(max=0) if max.is_a?(Range) min = max.min dice(1 + max.max - min) + min elsif max.zero? float else dice(max.to_i) end end
Cycle through the PRNG count times.
# File lib/fibonacci_rng/spinner.rb, line 7 def spin(count=1) count.times do do_spin end validate end
Set up a new seed value
# File lib/fibonacci_rng/seeder.rb, line 7 def srand(seed=FibonacciRng.new_seed) @seed = seed @buffer = Array.new(@depth+2, 0) seedsrc = (seed.to_s + fudge(seed) + 'Leonardo Pisano').each_byte.cycle indxsrc = (0...depth).cycle do_reseed(indxsrc, seedsrc) end
Create a random string
Endemic Code Smells.
-
:reek:FeatureEnvy
# File lib/fibonacci_rng/generator.rb, line 75 def string(length, set=ASCII_7_BIT) set_length = set.length result = "" length.times {result << set[dice(set_length)]} result end
Validate the sanity of the generator.
# File lib/fibonacci_rng/validate.rb, line 10 def validate @buffer.each do |element| return true unless element.zero? end fail InvalidFibonacciRngState end
Get a pseudo random word
# File lib/fibonacci_rng/generator.rb, line 47 def word do_spin validate @buffer[0] & WORD end
Private Instance Methods
Add a value to the generator.
# File lib/fibonacci_rng/hasher.rb, line 31 def add_value(value) index = @buffer[0] % @depth do_spin @buffer[index] += value do_spin validate end
Do the work of reseeding the PRNG
# File lib/fibonacci_rng/seeder.rb, line 46 def do_reseed(indxsrc, seedsrc) @init.times do @buffer[indxsrc.next] += seedsrc.next do_spin end end
Cycle through the PRNG once.
# File lib/fibonacci_rng/spinner.rb, line 18 def do_spin @buffer[-2] = @buffer[0] @buffer[-1] = @buffer[1] (0...@depth).each do |idx| tmp = @buffer[idx+2] @buffer[idx] = (@buffer[idx+1] + ((tmp >> 1)|(tmp.odd? ? TOP : 0))) & CHOP end end
A patch for the seeder class name bug.
Endemic Code Smells
-
:reek:UtilityFunction
# File lib/fibonacci_rng/seeder.rb, line 22 def fudge(seed) if seed.is_a?(Integer) if (-1073741824..1073741823) === seed "Fixnum" else "Bignum" end else seed.class.to_s end end
Get a float value.
# File lib/fibonacci_rng/generator.rb, line 85 def raw_float @buffer[0].to_f end