Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating random StaticArrays works with SamplerTypes but not other Samplers #804

Closed
npbarnes opened this issue Jun 29, 2020 · 7 comments · Fixed by #1210
Closed

Generating random StaticArrays works with SamplerTypes but not other Samplers #804

npbarnes opened this issue Jun 29, 2020 · 7 comments · Fixed by #1210
Labels

Comments

@npbarnes
Copy link
Contributor

Here's an example taken from the Julia docs on random number generation here

struct Die
    nsides::Int
end
Random.rand(rng::AbstractRNG, ::Random.SamplerType{Die}) = Die(rand(rng, 4:20))
Random.rand(rng::AbstractRNG, d::Random.SamplerTrivial{Die}) = rand(rng, 1:d[].nsides)
Base.eltype(::type{Die}) = Int

This lets us conveniently generate arrays of random dice,

julia> rand(Die,3)
3-element Array{Die,1}:
 Die(11)
 Die(17)
 Die(4)

or arrays of random dice rolls

julia> rand(Die(6), 3)
3-element Array{Int64,1}:
 3
 1
 5

With StaticArrays we can generate random dice

julia> @SVector rand(Die, 3)
3-element SArray{Tuple{3},Die,1,3} with indices SOneTo{3}:
 Die(20)
 Die(10)
 Die(13)

but not random dice rolls

julia> @SVector rand(Die(6), 3)
ERROR: ArgumentError: Static Array parameter T must be a type, got Die(6)
Stacktrace:
...

The same error occurs when using the samplers from Distributions.jl, for example.

@c42f
Copy link
Member

c42f commented Jul 8, 2020

I'm not sure whether this is a feature request or a bug, but it seems like a problem we should address :-)

@c42f c42f added the bug label Jul 8, 2020
@fejfo
Copy link

fejfo commented Sep 6, 2022

An even simpler example of this bug is

using Distributions
@MVector rand(Uniform(-1.,1.), 2)

@fredcallaway
Copy link

Ran into this today! Any chance this might be addressed?

@hyrodium
Copy link
Collaborator

The most simple case is @SVector rand(1:5, 3). (without Distributions.jl)

julia> using StaticArrays

julia> rand(Float32, 3)
3-element Vector{Float32}:
 0.36981475
 0.018245816
 0.6316833

julia> @SVector rand(Float32, 3)
3-element SVector{3, Float32} with indices SOneTo(3):
 0.54274094
 0.22791529
 0.9776533

julia> rand(1:5, 3)
3-element Vector{Int64}:
 5
 3
 4

julia> @SVector rand(1:5, 3)
ERROR: ArgumentError: Static Array parameter T must be a type, got 1:5
Stacktrace:

The problem is that macros such as @SVector does not work with samplers.

julia> @macroexpand @SVector rand(Float32, 3)
:(StaticArrays.rand((SVector){3, Float32}))

julia> @macroexpand @SVector rand(1:5, 3)
:(StaticArrays.rand((SVector){3, 1:5}))

I think adding a new function named strand would be a solution. (strand is an abbreviation of "StaticArrays rand", just like SparseArrays.sprand.)

julia> @macroexpand @SVector rand(Float32, 3)  # How macro expands
:(StaticArrays.strand((SVector){3, Float32}))

julia> @macroexpand @SVector rand(1:5, 3)  # How macro expands
:(StaticArrays.strand((SVector){3, Int}, 1:5))

julia> strand(SVector{3}, 1:5)  # Use cases
julia> strand(SVector{3, Int}, 1:5)
julia> strand(SVector{3}, Float64)
julia> strand(SVector{3, Float64}, Float64)
julia> strand(SVector{3, Float64})
julia> strand(SMatrix{3, Float64}, 1:8)

@mateuszbaran
Copy link
Collaborator

I've looked into this issue yesterday and I think we can modify the macro without introducing a new function. I'll let you know when I make sure it works fine.

@mateuszbaran
Copy link
Collaborator

My solution seems to work as long as the array has at least one element, so I'd say it's good enough. There are also no regressions for 0-element arrays.

@stevengj
Copy link
Contributor

stevengj commented Nov 30, 2023

Similarly, it would be good to handle rng arguments, e.g.

julia> using Random

julia> rng = Xoshiro(3);

julia> @SVector rand(rng, 3)
ERROR: TypeError: in Type, in parameter, expected Type, got a value of type Xoshiro

What I would suggest is that @SVector rand(...., n) should rewrite to StaticArrays.sa_rand(....., Val{n}()), where sa_rand is an ordinary function that can dispatch on the different argument types, e.g. it can dispatch on whether the first argument is a type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants