Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seed PRNGs from System source instead of time #4789

Merged
merged 1 commit into from Aug 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 6 additions & 11 deletions src/random.cr
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
12 changes: 10 additions & 2 deletions src/random/isaac.cr
@@ -1,3 +1,5 @@
require "crystal/system/random"

# (c) Bob Jenkins, March 1996, Public Domain
# You may use this code in any way you wish, and it is free. No warrantee.
# http://burtleburtle.net/bob/rand/isaacafa.html
Expand All @@ -10,15 +12,21 @@ class Random::ISAAC
private getter bb
private getter cc

def initialize(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 initialize(seeds = self.random_seeds)
@rsl = StaticArray(UInt32, 256).new { 0_u32 }
@mm = StaticArray(UInt32, 256).new { 0_u32 }
@counter = 0
@aa = @bb = @cc = 0_u32
init_by_array(seeds)
end

def new_seed(seeds = StaticArray(UInt32, 8).new { Random.new_seed })
def new_seed(seeds = self.random_seeds)
@aa = @bb = @cc = 0_u32
init_by_array(seeds)
end
Expand Down
14 changes: 12 additions & 2 deletions src/random/pcg32.cr
@@ -1,3 +1,5 @@
require "random/system"

# This is a Crystal conversion of basic C PCG implementation
#
# Original file notice:
Expand Down Expand Up @@ -37,14 +39,22 @@ class Random::PCG32
@state : UInt64
@inc : UInt64

def initialize(initstate = UInt64.new(Random.new_seed), initseq = 0_u64)
def self.new
new(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
new_seed(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