From e6a767c0e42f3577604c23bb5a4af00a2517a46f Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 27 Jan 2016 18:38:15 +0530 Subject: [PATCH] implement randn!(::Array{Float32}) etc. (fix #9836) --- base/docs/helpdb/Base.jl | 31 ---------------- base/random.jl | 79 ++++++++++++++++++++++++++++------------ doc/stdlib/numbers.rst | 14 +++---- test/random.jl | 57 +++++++++++++++++------------ 4 files changed, 96 insertions(+), 85 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 23aa66990e2747..72315464f81220 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -938,14 +938,6 @@ references in `r` are replaced with the corresponding matched text. """ replace -""" - randexp([rng], [dims...]) - -Generate a random number according to the exponential distribution with scale 1. Optionally -generate an array of such random numbers. -""" -randexp - """ chop(string) @@ -1964,14 +1956,6 @@ Kronecker tensor product of two vectors or two matrices. """ kron -""" - randn([rng], [dims...]) - -Generate a normally-distributed random number with mean 0 and standard deviation 1. -Optionally generate an array of normally-distributed random numbers. -""" -randn - """ process_exited(p::Process) @@ -6412,13 +6396,6 @@ the topmost backend that does not throw a `MethodError`). """ pushdisplay -""" - randexp!([rng], A::Array{Float64,N}) - -Fill the array `A` with random numbers following the exponential distribution (with scale 1). -""" -randexp! - """ prevind(str, i) @@ -9433,14 +9410,6 @@ no effect outside of compilation. """ include_dependency -""" - randn!([rng], A::Array{Float64,N}) - -Fill the array `A` with normally-distributed (mean 0, standard deviation 1) random numbers. -Also see the rand function. -""" -randn! - """ ldexp(x, n) diff --git a/base/random.jl b/base/random.jl index 9cb75cd203d87a..d71f209547fc54 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1096,7 +1096,14 @@ const ziggurat_nor_r = 3.6541528853610087963519472518 const ziggurat_nor_inv_r = inv(ziggurat_nor_r) const ziggurat_exp_r = 7.6971174701310497140446280481 +""" + randn([rng], [T=Float64], [dims...]) +Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. +Optionally generate an array of normally-distributed random numbers. +The `Base` module currently provides an implementation for the types +`Float16`, `Float32`, and `Float64` (the default). +""" @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin r = rand_ui52(rng) @@ -1123,19 +1130,14 @@ 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...)) +""" + randexp([rng], [T=Float64], [dims...]) +Generate a random number of type `T` according to the exponential distribution with scale 1. +Optionally generate an array of such random numbers. +The `Base` module currently provides an implementation for the types +`Float16`, `Float32`, and `Float64` (the default). +""" @inline function randexp(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin ri = rand_ui52(rng) @@ -1156,20 +1158,51 @@ 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 +""" + randn!([rng], A::AbstractArray) -> A -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)) +Fill the array `A` with normally-distributed (mean 0, standard deviation 1) random numbers. +Also see the `rand` function. +""" +function randn! end +""" + randexp!([rng], A::AbstractArray) -> A +Fill the array `A` with random numbers following the exponential distribution (with scale 1). +""" +function randexp! end + +let Floats = Union{Float16,Float32,Float64} + for randfun in [:randn, :randexp] + randfun! = Symbol(randfun, :!) + @eval begin + # scalars + $randfun{T<:$Floats}(rng::AbstractRNG, ::Type{T}) = convert(T, $randfun(rng)) + $randfun{T<:$Floats}(::Type{T}) = $randfun(GLOBAL_RNG, T) + + # filling arrays + function $randfun!{T}(rng::AbstractRNG, A::AbstractArray{T}) + for i in eachindex(A) + @inbounds A[i] = $randfun(rng, T) + end + A + end + + $randfun!(A::AbstractArray) = $randfun!(GLOBAL_RNG, A) + + # generating arrays + $randfun{T}(rng::AbstractRNG, ::Type{T}, dims::Dims) = $randfun!(rng, Array{T}(dims)) + $randfun{T}(rng::AbstractRNG, ::Type{T}, dims::Integer...) = $randfun!(rng, Array{T}(dims...)) + $randfun{T}( ::Type{T}, dims::Dims) = $randfun(GLOBAL_RNG, T, dims) + $randfun{T}( ::Type{T}, dims::Integer...) = $randfun(GLOBAL_RNG, T, 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 diff --git a/doc/stdlib/numbers.rst b/doc/stdlib/numbers.rst index e2464460f3bcbf..e9394a54f0dae4 100644 --- a/doc/stdlib/numbers.rst +++ b/doc/stdlib/numbers.rst @@ -568,25 +568,25 @@ 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], [T=Float64], [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 ``T`` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The ``Base`` module currently provides an implementation for the types ``Float16``\ , ``Float32``\ , and ``Float64`` (the default). -.. function:: randn!([rng], A::Array{Float64,N}) +.. function:: randn!([rng], A::AbstractArray) -> A .. 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. Also see the ``rand`` function. -.. function:: randexp([rng], [dims...]) +.. function:: randexp([rng], [T=Float64], [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 ``T`` according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The ``Base`` module currently provides an implementation for the types ``Float16``\ , ``Float32``\ , and ``Float64`` (the default). -.. function:: randexp!([rng], A::Array{Float64,N}) +.. function:: randexp!([rng], A::AbstractArray) -> A .. Docstring generated from Julia source diff --git a/test/random.jl b/test/random.jl index 2d619f99723715..64957fc82f6a21 100644 --- a/test/random.jl +++ b/test/random.jl @@ -300,38 +300,47 @@ end # test all rand APIs for rng in ([], [MersenneTwister()], [RandomDevice()]) + types = [Base.BitInteger_types..., Bool, 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, 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 function hist(X,n)