Is there some better and simple way to implement this for BigFloat:
function rand_uniform(lo::F, hi::F, n::Signed) where {F <: AbstractFloat}
ret = Vector{F}(undef, n)
dist = Distributions.Uniform(lo, hi)
for i ∈ eachindex(ret)
ret[i] = rand(dist)
end
ret
end
This approach fails because of a Distributionsbug, it returns Vector{Float64} instead of Vector{BigFloat} even though lo and hi are BigFloat:
rand(Distributions.Uniform(lo, hi), n)
This, on the other hand, fails with a stack overflow because of recursion, for some reason:
Yeah, this is getting interesting. Both your and Steven’s function’s presented some opportunities for further optimization:
function rand_uniform_nsajko(lo::F, hi::F, n::Signed) where {F <: AbstractFloat}
ret = Vector{F}(undef, n)
dist = Distributions.Uniform(lo, hi)
for i ∈ eachindex(ret)
ret[i] = rand(dist)
end
ret
end
rand_uniform_barucden(lo::T, hi::T, n) where {T <: AbstractFloat} =
(hi - lo) * rand(T, n) .+ lo
rand_uniform_barucden_opt(lo::T, hi::T, n) where {T <: AbstractFloat} =
(hi - lo) .* rand(T, n) .+ lo
rand_uniform_stevengj(lo::F, hi::F, n::Integer) where {F <: AbstractFloat} =
[rand(F) * (hi - lo) + lo for _=1:n]
rand_uniform_stevengj_opt(lo::F, hi::F, n::Integer) where {F <: AbstractFloat} =
let d = hi - lo
[rand(F) * d + lo for _=1:n]
end
# Almost as fast as rand_uniform_barucden_opt
rand_uniform_map(lo::F, hi::F, n::Signed) where {F <: AbstractFloat} =
let v = rand(F, n)
map!(
let d = hi - lo, l = lo
x -> x*d + l
end,
v,
v,
)
end
The optimized version of your function, rand_uniform_barucden_opt, seems to be the fastest of all. I guess this could be because your approach uses rand(::Type, ::Int), which could be specially optimized in the Julia stdlib.