Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spec/xoshiro128plus_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe Random::XoShiRo128Plus do
original.next_u.should eq(0x472255cc_u32)

rng = original.split
rng.should_not be(original)
rng.next_u.should eq(0xbbc0480a_u32)
rng.should_not eq(original)
rng.next_u.should eq(0x16d92aa0_u32)
end
end
9 changes: 5 additions & 4 deletions spec/xoshiro128starstar_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ describe Random::XoShiRo128StarStar do
end

it "#split" do
rng = Random::XoShiRo128StarStar.new(0xdeadbeef_u64)
rng.next_u.should eq(0xa9c3d393_u32)
original = Random::XoShiRo128StarStar.new(0xdeadbeef_u64)
original.next_u.should eq(0xa9c3d393_u32)

rng = rng.split
rng.next_u.should eq(0x61800258_u32)
rng = original.split
rng.should_not eq(original)
rng.next_u.should eq(0x818871d8_u32)
end
end
4 changes: 2 additions & 2 deletions spec/xoshiro256plus_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe Random::XoShiRo256Plus do
original.next_u.should eq(0xbf468782e4ab532b_u64)

rng = original.split
rng.should_not be(original)
rng.next_u.should eq(0xef2817c89dfe32e1_u64)
rng.should_not eq(original)
rng.next_u.should eq(0x6ecba84e8c0ab44_u64)
end
end
4 changes: 2 additions & 2 deletions spec/xoshiro256starstar_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe Random::XoShiRo256StarStar do
original.next_u.should eq(0xc5555444a74d7e83_u64)

rng = original.split
rng.should_not be(original)
rng.next_u.should eq(0x228bb75bc497d835_u64)
rng.should_not eq(original)
rng.next_u.should eq(0x54f773200a4efa23_u64)
end
end
9 changes: 5 additions & 4 deletions src/splittable.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class Random::Splittable

private GOLDEN_GAMMA = 0x9e3779b97f4a7c15_u64 # odd

@seed : UInt64
@gamma : UInt64
protected setter seed : UInt64
protected setter gamma : UInt64

def initialize
s = default_gen.add(2_u64 &* GOLDEN_GAMMA)
Expand All @@ -38,8 +38,9 @@ class Random::Splittable
mix32(next_seed)
end

def split : self
self.class.new(next_u, mix_gamma(next_seed))
def split_internal(other : self) : Nil
other.seed = next_u
other.gamma = mix_gamma(next_seed)
end

private def next_seed : UInt64
Expand Down
17 changes: 13 additions & 4 deletions src/splittable128.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Random::Splittable128
GAMMA_PRIME = (1_u64 << 57) &- 13 # "Ginny"
GAMMA_GAMMA = 0x00281e2dba6606f3_u64

@seed_hi : UInt64
@seed_lo : UInt64
protected setter seed_hi : UInt64
protected setter seed_lo : UInt64
@gamma_hi : UInt64
@gamma_lo : UInt64
@next_split : UInt64
Expand All @@ -26,6 +26,13 @@ class Random::Splittable128
end

def initialize(@seed_hi = next_default_seed, @seed_lo = 0_u64, s : UInt64 = GAMMA_GAMMA)
@gamma_hi = 0_u64
@gamma_lo = 0_u64
@next_split = 0_u64
mix_gamma(s)
end

protected def mix_gamma(s)
# we require 0 <= s <= Ginny
s &+= GAMMA_GAMMA
s &-= GAMMA_PRIME if s >= GAMMA_PRIME
Expand All @@ -38,9 +45,11 @@ class Random::Splittable128
@next_split = s
end

def split : self
def split_internal(other : self) : Nil
next_raw64
Splittable128.new(@seed_hi, @seed_lo, @next_split)
other.seed_hi = @seed_hi
other.seed_lo = @seed_lo
other.mix_gamma(@next_split)
end

def next_u : UInt64
Expand Down
4 changes: 2 additions & 2 deletions src/xoshiro128.cr
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ abstract class Random::XoShiRo128
@state.to_unsafe[3] = s3
end

# Returns a new instance that shares no mutable state with this instance.
def split
def split_internal(other : self) : Nil
self.class.new(@state.map { |s| murmurhash3(s) })
other.next_u
end

@[AlwaysInline]
Expand Down
9 changes: 3 additions & 6 deletions src/xoshiro256.cr
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,9 @@ abstract class Random::XoShiRo256
@state.to_unsafe[3] = s3
end

# Returns a new instance that shares no mutable state with this instance. The
# sequence generated by the new instance depends deterministically from the
# state of this instance, but the probability that the sequence generated by
# this instance and by the new instance overlap is negligible.
def split
self.class.new(@state.map { |s| murmurhash3(s) })
def split_internal(other : self) : Nil
@state.map! { |s| murmurhash3(s) }
other.next_u
end

@[AlwaysInline]
Expand Down