Skip to content

Commit

Permalink
faster generation of few character generation from a string
Browse files Browse the repository at this point in the history
For generating few characters from a string `str`, it's more efficient
to use `Sampler(rng, str, Val(1))` rather than with `Val(Inf)`.
This change improves this use case, e.g.:

sp = Sampler(rng, str, Val(1);
C = (rand(rng, sp), rand(rng, sp), rand(rng, sp))
  • Loading branch information
rfourquet committed Nov 30, 2017
1 parent a0a5770 commit 007b640
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 5 deletions.
10 changes: 5 additions & 5 deletions base/random/generation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,22 +309,22 @@ rand(rng::AbstractRNG, sp::SamplerTrivial{<:Union{Associative,AbstractSet}}) =

# we use collect(str), which is most of the time more efficient than specialized methods
# (except maybe for very small arrays)
Sampler(rng::AbstractRNG, str::AbstractString, n::Repetition) = Sampler(rng, collect(str), n)
Sampler(rng::AbstractRNG, str::AbstractString, n::Val{Inf}) = Sampler(rng, collect(str), n)

# when generating only one char from a string, the specialized method below
# is usually more efficient
Sampler(::AbstractRNG, str::AbstractString, ::Val{1}) = SamplerTrivial(str)
Sampler(rng::AbstractRNG, str::AbstractString, ::Val{1}) =
SamplerSimple(str, Sampler(rng, 1:_endof(str), Val(Inf)))

isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(Base.@gc_preserve s unsafe_load(pointer(s), i))
isvalid_unsafe(s::AbstractString, i) = isvalid(s, i)
_endof(s::String) = sizeof(s)
_endof(s::AbstractString) = endof(s)

function rand(rng::AbstractRNG, sp::SamplerTrivial{<:AbstractString})::Char
function rand(rng::AbstractRNG, sp::SamplerSimple{<:AbstractString,<:Sampler})::Char
str = sp[]
sp_pos = Sampler(rng, 1:_endof(str))
while true
pos = rand(rng, sp_pos)
pos = rand(rng, sp.data)
isvalid_unsafe(str, pos) && return str[pos]
end
end
2 changes: 2 additions & 0 deletions test/random.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

Base.Random.Sampler(rng::AbstractRNG, str::AbstractString, ::Val{1}) =
Base.Random.SamplerSimple(str, Base.Random.Sampler(rng, 1:Base.Random._endof(str), Val(Inf)))


# Issue #6573
Expand Down

0 comments on commit 007b640

Please sign in to comment.