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

depth[R]

The depth of the Fibonacci array.

init[R]

The init value used by this generator.

seed[R]

The seed value used by this generator.

Public Class Methods

new(arg_a=nil, arg_b=nil, arg_c=nil) click to toggle source

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
rand(max=0) click to toggle source

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
srand(seed=FibonacciRng.new_seed, depth=8) click to toggle source

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

new_seed() click to toggle source

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

<<(data) click to toggle source

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
byte() click to toggle source

Get a pseudo random byte

# File lib/fibonacci_rng/generator.rb, line 33
def byte
  do_spin
  validate
  @buffer[0] & BYTE
end
bytes(length) click to toggle source

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
dice(sides) click to toggle source

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
double() click to toggle source

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
float() click to toggle source

Get a pseudo random float

# File lib/fibonacci_rng/generator.rb, line 54
def float
  do_spin
  validate
  raw_float / BASE
end
hash_string() click to toggle source

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
hash_value() click to toggle source

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
rand(max=0) click to toggle source

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
reseed(seed=FibonacciRng.new_seed)
Alias for: srand
spin(count=1) click to toggle source

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
srand(seed=FibonacciRng.new_seed) click to toggle source

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
Also aliased as: reseed
string(length, set=ASCII_7_BIT) click to toggle source

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() click to toggle source

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
word() click to toggle source

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_value(value) click to toggle source

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_reseed(indxsrc, seedsrc) click to toggle source

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
do_spin() click to toggle source

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
fudge(seed) click to toggle source

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
raw_float() click to toggle source

Get a float value.

# File lib/fibonacci_rng/generator.rb, line 85
def raw_float
  @buffer[0].to_f
end