Skip to content

Commit

Permalink
implement randn!(::Array{Float32}) etc. (fix JuliaLang#9836)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Jan 27, 2016
1 parent 5ac7f75 commit 09639d7
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 62 deletions.
19 changes: 12 additions & 7 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -978,10 +978,12 @@ references in `r` are replaced with the corresponding matched text.
replace

"""
randexp([rng], [dims...])
randexp([rng], [F], [dims...])
Generate a random number of type `F` according to the exponential distribution with scale 1.
The type `F` can be `Float16`, `Float32` or `Float64` and defaults to the latter.
Optionally generate an array of such random numbers.
Generate a random number according to the exponential distribution with scale 1. Optionally
generate an array of such random numbers.
"""
randexp

Expand Down Expand Up @@ -2073,9 +2075,10 @@ Right bit shift operator, preserving the sign of `x`.
Base.(:(>>))

"""
randn([rng], [dims...])
randn([rng], [F], [dims...])
Generate a normally-distributed random number with mean 0 and standard deviation 1.
Generate a normally-distributed random number of type `F` with mean 0 and standard deviation 1.
The type `F` can be `Float16`, `Float32` or `Float64` and defaults to the latter.
Optionally generate an array of normally-distributed random numbers.
"""
randn
Expand Down Expand Up @@ -6830,9 +6833,10 @@ the topmost backend that does not throw a `MethodError`).
pushdisplay

"""
randexp!([rng], A::Array{Float64,N})
randexp!([rng], A::Array{F,N})
Fill the array `A` with random numbers following the exponential distribution (with scale 1).
The type `F` can be `Float16`, `Float32` or `Float64`.
"""
randexp!

Expand Down Expand Up @@ -10087,9 +10091,10 @@ no effect outside of compilation.
include_dependency

"""
randn!([rng], A::Array{Float64,N})
randn!([rng], A::Array{F,N})
Fill the array `A` with normally-distributed (mean 0, standard deviation 1) random numbers.
The type `F` can be `Float16`, `Float32` or `Float64`.
Also see the rand function.
"""
randn!
Expand Down
55 changes: 31 additions & 24 deletions base/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1126,19 +1126,6 @@ function randn_unlikely(rng, idx, rabs, x)
end
end

function randn!(rng::AbstractRNG, A::AbstractArray{Float64})
for i in eachindex(A)
@inbounds A[i] = randn(rng)
end
A
end

randn!(A::AbstractArray{Float64}) = randn!(GLOBAL_RNG, A)
randn(dims::Dims) = randn!(Array(Float64, dims))
randn(dims::Integer...) = randn!(Array(Float64, dims...))
randn(rng::AbstractRNG, dims::Dims) = randn!(rng, Array(Float64, dims))
randn(rng::AbstractRNG, dims::Integer...) = randn!(rng, Array(Float64, dims...))

@inline function randexp(rng::AbstractRNG=GLOBAL_RNG)
@inbounds begin
ri = rand_ui52(rng)
Expand All @@ -1159,20 +1146,40 @@ function randexp_unlikely(rng, idx, x)
end
end

function randexp!(rng::AbstractRNG, A::Array{Float64})
for i in eachindex(A)
@inbounds A[i] = randexp(rng)
end
A
end
let Floats = Union{Float16,Float32,Float64}
for randfun in [:randn, :randexp]
randfun! = symbol(randfun, :!)
@eval begin

# scalars

$randfun{F<:$Floats}(rng::AbstractRNG, ::Type{F}) = convert(F, $randfun(rng))
$randfun{F<:$Floats}(::Type{F}) = $randfun(GLOBAL_RNG, F)

# filling arrays

randexp!(A::Array{Float64}) = randexp!(GLOBAL_RNG, A)
randexp(dims::Dims) = randexp!(Array(Float64, dims))
randexp(dims::Int...) = randexp!(Array(Float64, dims))
randexp(rng::AbstractRNG, dims::Dims) = randexp!(rng, Array(Float64, dims))
randexp(rng::AbstractRNG, dims::Int...) = randexp!(rng, Array(Float64, dims))
function $randfun!{F<:$Floats}(rng::AbstractRNG, A::AbstractArray{F})
for i in eachindex(A)
@inbounds A[i] = $randfun(rng)
end
A
end

$randfun!{F<:$Floats}(A::AbstractArray{F}) = $randfun!(GLOBAL_RNG, A)

# generating arrays

$randfun{F<:$Floats}(rng::AbstractRNG, ::Type{F}, dims::Dims) = $randfun!(rng, Array(F, dims))
$randfun{F<:$Floats}(rng::AbstractRNG, ::Type{F}, dims::Integer...) = $randfun!(rng, Array(F, dims...))
$randfun{F<:$Floats}( ::Type{F}, dims::Dims) = $randfun(GLOBAL_RNG, F, dims)
$randfun{F<:$Floats}( ::Type{F}, dims::Integer...) = $randfun(GLOBAL_RNG, F, dims...)
$randfun( rng::AbstractRNG, dims::Dims) = $randfun(rng, Float64, dims)
$randfun( rng::AbstractRNG, dims::Integer...) = $randfun(rng, Float64, dims...)
$randfun( dims::Dims) = $randfun(GLOBAL_RNG, Float64, dims)
$randfun( dims::Integer...) = $randfun(GLOBAL_RNG, Float64, dims...)
end
end
end
## random UUID generation

immutable UUID
Expand Down
16 changes: 8 additions & 8 deletions doc/stdlib/numbers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -608,29 +608,29 @@ As ``BigInt`` represents unbounded integers, the interval must be specified (e.g
Generate a ``BitArray`` of random boolean values.

.. function:: randn([rng], [dims...])
.. function:: randn([rng], [F], [dims...])

.. Docstring generated from Julia source
Generate a normally-distributed random number with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers.
Generate a normally-distributed random number of type ``F`` with mean 0 and standard deviation 1. The type ``F`` can be ``Float16``\ , ``Float32`` or ``Float64`` and defaults to the latter. Optionally generate an array of normally-distributed random numbers.

.. function:: randn!([rng], A::Array{Float64,N})
.. function:: randn!([rng], A::Array{F,N})

.. Docstring generated from Julia source
Fill the array ``A`` with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the rand function.
Fill the array ``A`` with normally-distributed (mean 0, standard deviation 1) random numbers. The type ``F`` can be ``Float16``\ , ``Float32`` or ``Float64``\ . Also see the rand function.

.. function:: randexp([rng], [dims...])
.. function:: randexp([rng], [F], [dims...])

.. Docstring generated from Julia source
Generate a random number according to the exponential distribution with scale 1. Optionally generate an array of such random numbers.
Generate a random number of type ``F`` according to the exponential distribution with scale 1. The type ``F`` can be ``Float16``\ , ``Float32`` or ``Float64`` and defaults to the latter. Optionally generate an array of such random numbers.

.. function:: randexp!([rng], A::Array{Float64,N})
.. function:: randexp!([rng], A::Array{F,N})

.. Docstring generated from Julia source
Fill the array ``A`` with random numbers following the exponential distribution (with scale 1).
Fill the array ``A`` with random numbers following the exponential distribution (with scale 1). The type ``F`` can be ``Float16``\ , ``Float32`` or ``Float64``\ .

.. function:: randjump(r::MersenneTwister, jumps, [jumppoly]) -> Vector{MersenneTwister}

Expand Down
57 changes: 34 additions & 23 deletions test/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,39 +299,50 @@ let a = [rand(RandomDevice(), UInt128) for i=1:10]
end

# test all rand APIs

for rng in ([], [MersenneTwister()], [RandomDevice()])
types = [Base.BitInteger_types..., Bool, Char, Float16, Float32, Float64]
ftypes = [Float16, Float32, Float64]
b2 = big(2)
u3 = UInt(3)
for f in [rand, randn, randexp]
f(rng...) ::Float64
f(rng..., 5) ::Vector{Float64}
f(rng..., 2, 3) ::Array{Float64, 2}
f(rng...) ::Float64
f(rng..., 5) ::Vector{Float64}
f(rng..., 2, 3) ::Array{Float64, 2}
f(rng..., b2, u3) ::Array{Float64, 2}
f(rng..., (2, 3)) ::Array{Float64, 2}
for T in (f === rand ? types : ftypes)
a0 = f(rng..., T) ::T
a1 = f(rng..., T, 5) ::Vector{T}
a2 = f(rng..., T, 2, 3) ::Array{T, 2}
a3 = f(rng..., T, b2, u3) ::Array{T, 2}
a4 = f(rng..., T, (2, 3)) ::Array{T, 2}
if T <: AbstractFloat && f === rand
for a in [a0, a1..., a2..., a3..., a4...]
@test 0.0 <= a < 1.0
end
end
end
end
for f! in [randn!, randexp!]
f!(rng..., Array(Float64, 5)) ::Vector{Float64}
f!(rng..., Array(Float64, 2, 3)) ::Array{Float64, 2}
for f! in [rand!, randn!, randexp!]
for T in (f! === rand! ? types : ftypes)
X = T == Bool ? T[0,1] : T[0,1,2]
for A in (Array(T, 5), Array(T, 2, 3))
f!(rng..., A) ::typeof(A)
if f! === rand!
f!(rng..., A, X) ::typeof(A)
f!(rng..., sparse(A)) ::typeof(sparse(A))
f!(rng..., sparse(A), X) ::typeof(sparse(A))
end
end
end
end

bitrand(rng..., 5) ::BitArray{1}
bitrand(rng..., 2, 3) ::BitArray{2}
rand!(rng..., BitArray(5)) ::BitArray{1}
rand!(rng..., BitArray(2, 3)) ::BitArray{2}

for T in [Base.BitInteger_types..., Bool, Char, Float16, Float32, Float64]
a0 = rand(rng..., T) ::T
a1 = rand(rng..., T, 5) ::Vector{T}
a2 = rand(rng..., T, 2, 3) ::Array{T, 2}
if T <: AbstractFloat
for a in [a0, a1..., a2...]
@test 0.0 <= a < 1.0
end
end
for A in (Array(T, 5), Array(T, 2, 3))
X = T == Bool ? T[0,1] : T[0,1,2]
rand!(rng..., A) ::typeof(A)
rand!(rng..., A, X) ::typeof(A)
rand!(rng..., sparse(A)) ::typeof(sparse(A))
rand!(rng..., sparse(A), X) ::typeof(sparse(A))
end
end
end

# test uniform distribution of floats
Expand Down

0 comments on commit 09639d7

Please sign in to comment.