Skip to content

Commit

Permalink
seed PRNGs from System source instead of time.
Browse files Browse the repository at this point in the history
  • Loading branch information
konovod committed Aug 4, 2017
1 parent 890ab45 commit b3cdcf6
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 14 deletions.
17 changes: 6 additions & 11 deletions src/random.cr
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,14 @@ require "random/pcg32"
module Random
DEFAULT = PCG32.new

# Returns a `UInt32` read from a counter value generated by the cycle counter
# register, or the current time on ARM processors.
def self.new_seed : UInt32
{% if flag?(:arm) || flag?(:aarch64) %}
Time.now.ticks.to_u32
{% else %}
Intrinsics.read_cycle_counter.to_u32
{% end %}
# Initializes an instance with the given *seed* and *sequence*.
def self.new(seed, sequence = 0_u64)
PCG32.new(seed.to_u64, sequence)
end

# Initializes an instance with the given *seed*. (Default: `#new_seed`)
def self.new(seed = new_seed)
PCG32.new(seed)
# Initializes an instance seeded from a system source.
def self.new
PCG32.new
end

# Generates a random unsigned integer.
Expand Down
8 changes: 7 additions & 1 deletion src/random/isaac.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ class Random::ISAAC
init_by_array(seeds)
end

def new_seed(seeds = StaticArray(UInt32, 8).new { Random.new_seed })
private def self.random_seeds
(uninitialized StaticArray(UInt32, 8)).tap do |seeds|
System::Random.random_bytes(seeds.to_slice)
end
end

def new_seed(seeds = self.random_seeds)
@aa = @bb = @cc = 0_u32
init_by_array(seeds)
end
Expand Down
12 changes: 10 additions & 2 deletions src/random/pcg32.cr
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,22 @@ class Random::PCG32
@state : UInt64
@inc : UInt64

def initialize(initstate = UInt64.new(Random.new_seed), initseq = 0_u64)
def initialize
initialize(Random::System.rand(UInt64::MIN..UInt64::MAX), Random::System.rand(UInt64::MIN..UInt64::MAX))
end

def initialize(initstate : UInt64, initseq = 0_u64)
# initialize to zeros to prevent compiler complains
@state = 0_u64
@inc = 0_u64
new_seed(initstate, initseq)
end

def new_seed(initstate = UInt64.new(Random.new_seed), initseq = 0_u64)
def new_seed
initialize(Random::System.rand(UInt64::MIN..UInt64::MAX), Random::System.rand(UInt64::MIN..UInt64::MAX))
end

def new_seed(initstate : UInt64, initseq = 0_u64)
@state = 0_u64
@inc = (initseq << 1) | 1
next_u
Expand Down

0 comments on commit b3cdcf6

Please sign in to comment.