Skip to content

Commit 6177901

Browse files
committed
[WIP] Xoshiro: allow any non-negative integer as a seed, via SHA2_256
[ci skip]
1 parent e3a06c4 commit 6177901

File tree

3 files changed

+9
-42
lines changed

3 files changed

+9
-42
lines changed

stdlib/Random/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
33

44
[deps]
55
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
6+
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
67

78
[extras]
89
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

stdlib/Random/src/Random.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ include("DSFMT.jl")
1313
using .DSFMT
1414
using Base.GMP.MPZ
1515
using Base.GMP: Limb
16+
import SHA
1617

1718
using Base: BitInteger, BitInteger_types, BitUnsigned, require_one_based_indexing
1819

stdlib/Random/src/Xoshiro.jl

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -117,65 +117,30 @@ end
117117

118118
# Shared implementation between Xoshiro and TaskLocalRNG -- seeding
119119

120-
function seed!(x::Union{TaskLocalRNG,Xoshiro})
120+
function seed!(rng::Union{TaskLocalRNG,Xoshiro})
121121
# as we get good randomness from RandomDevice, we can skip hashing
122122
parent = RandomDevice()
123123
# Constants have nothing up their sleeve, see task.c
124124
# 0x02011ce34bce797f == hash(UInt(1))|0x01
125125
# 0x5a94851fb48a6e05 == hash(UInt(2))|0x01
126126
# 0x3688cf5d48899fa7 == hash(UInt(3))|0x01
127127
# 0x867b4bb4c42e5661 == hash(UInt(4))|0x01
128-
setstate!(x,
128+
setstate!(rng,
129129
0x02011ce34bce797f * rand(parent, UInt64),
130130
0x5a94851fb48a6e05 * rand(parent, UInt64),
131131
0x3688cf5d48899fa7 * rand(parent, UInt64),
132132
0x867b4bb4c42e5661 * rand(parent, UInt64))
133133
end
134134

135-
function seed!(rng::Union{TaskLocalRNG,Xoshiro}, seed::NTuple{4,UInt64})
136-
# TODO: Consider a less ad-hoc construction
137-
# We can afford burning a handful of cycles here, and we don't want any
138-
# surprises with respect to bad seeds / bad interactions.
139-
140-
s0 = s = Base.hash_64_64(seed[1])
141-
s1 = s += Base.hash_64_64(seed[2])
142-
s2 = s += Base.hash_64_64(seed[3])
143-
s3 = s += Base.hash_64_64(seed[4])
144-
135+
function seed!(rng::Union{TaskLocalRNG,Xoshiro}, seed::Vector{UInt32})
136+
c = SHA.SHA2_256_CTX()
137+
SHA.update!(c, reinterpret(UInt8, seed))
138+
s0, s1, s2, s3 = reinterpret(UInt64, SHA.digest!(c))
145139
setstate!(rng, s0, s1, s2, s3)
146-
147-
rand(rng, UInt64)
148-
rand(rng, UInt64)
149-
rand(rng, UInt64)
150-
rand(rng, UInt64)
151-
rng
152140
end
153141

154-
function seed!(rng::Union{TaskLocalRNG, Xoshiro}, seed::UInt128)
155-
seed0 = seed % UInt64
156-
seed1 = (seed>>>64) % UInt64
157-
seed!(rng, (seed0, seed1, zero(UInt64), zero(UInt64)))
158-
end
159-
seed!(rng::Union{TaskLocalRNG, Xoshiro}, seed::Integer) = seed!(rng, UInt128(seed))
160-
161-
function seed!(rng::Union{TaskLocalRNG, Xoshiro}, seed::AbstractVector{UInt64})
162-
if length(seed) > 4
163-
throw(ArgumentError("seed should have no more than 256 bits"))
164-
end
165-
seed0 = length(seed)>0 ? seed[1] : UInt64(0)
166-
seed1 = length(seed)>1 ? seed[2] : UInt64(0)
167-
seed2 = length(seed)>2 ? seed[3] : UInt64(0)
168-
seed3 = length(seed)>3 ? seed[4] : UInt64(0)
169-
seed!(rng, (seed0, seed1, seed2, seed3))
170-
end
142+
seed!(rng::Union{TaskLocalRNG, Xoshiro}, seed::Integer) = seed!(rng, make_seed(seed))
171143

172-
function seed!(rng::Union{TaskLocalRNG, Xoshiro}, seed::AbstractVector{UInt32})
173-
if iseven(length(seed))
174-
seed!(rng, reinterpret(UInt64, seed))
175-
else
176-
seed!(rng, UInt64[reinterpret(UInt64, @view(seed[begin:end-1])); seed[end] % UInt64])
177-
end
178-
end
179144

180145
@inline function rand(rng::Union{TaskLocalRNG, Xoshiro}, ::SamplerType{UInt128})
181146
first = rand(rng, UInt64)

0 commit comments

Comments
 (0)