jeudi 25 juin 2020

Implementing a sampler with array eltype

Hooking into rand has been easier in the old days... I think I followed the description in the docs, but it doesn't seem to like a sampler returning an array:

using Random

struct Shell{N}
    r0::Float64
    r1::Float64
end

Base.eltype(::Type{Shell{N}}) where {N} = Array{Float64, N}

function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
    # ignore the correctness of the sampling algorithm for now :)
    shell = d[]
    Δ = shell.r1 - shell.r0
    θ = Δ .* randn(N)
    r = shell.r0 .+ θ .* .√rand(N) 
end

Test:

julia> rand(Shell{2}(0, 1))
2-element Array{Float64,1}:
 0.5165139561555491  
 0.035180151872393726

julia> rand(Shell{2}(0, 1), 2)
ERROR: MethodError: no method matching Array{Float64,2}(::Array{Float64,1})
Closest candidates are:
  Array{Float64,2}(::AbstractArray{S,N}) where {T, N, S} at array.jl:498
  Array{Float64,2}(::UndefInitializer, ::Int64, ::Int64) where T at boot.jl:406
  Array{Float64,2}(::UndefInitializer, ::Int64...) where {T, N} at boot.jl:410
  ...
Stacktrace:
 [1] convert(::Type{Array{Float64,2}}, ::Array{Float64,1}) at ./array.jl:490
 [2] setindex!(::Array{Array{Float64,2},1}, ::Array{Float64,1}, ::Int64) at ./array.jl:782
 [3] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:271 [inlined]
 [4] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:266 [inlined]
 [5] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:279 [inlined]
 [6] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:280 [inlined]
 [7] rand(::Shell{2}, ::Int64) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:283
 [8] top-level scope at REPL[14]:1

What am I missing?




Aucun commentaire:

Enregistrer un commentaire