# Static Array With Random Numbers From a Uniform Distribution

I am trying to define a static array with numbers pulled from a uniform distribution (`using Distributions`) from -1 to 1. It is easy to generate a matrix:

``````pvec=rand(Uniform(-1, 1), 3,10)
``````

But I want to have a static array (`using StaticArrays`) for which I can write `rand(SVector{3,Float64},10)`, but I don’t know how to combine both. How can I define a static array and keep the uniform distribution information? I know I can do scaling and addition to get a distribution from -1 to 1 from the second command but it is not as fast as I would like.

It’s clumsy, but here’s a solution that relies on reinterpreting the vector of `SVector` as a “typical” array so that it can be filled by `rand!`:

``````julia> using Random, StaticArrays, Distributions

julia> z = Vector{SVector{3,Float32}}(undef, 10);

julia> rand!(Uniform(-1, 1), reinterpret(Float32, z))
30-element reinterpret(Float32, ::Vector{SVector{3, Float32}}):
-0.03727758
0.6890855
-0.91755855
0.25815475
⋮
0.48348153
-0.8701681
0.63198125
0.57068086

julia> z
10-element Vector{SVector{3, Float32}}:
[-0.03727758, 0.6890855, -0.91755855]
[0.25815475, 0.9596908, 0.95804846]
[0.4309975, 0.38259137, 0.5585474]
[0.16815412, 0.19676924, 0.5617609]
[0.9677615, -0.66337335, -0.17191088]
[-0.25808072, -0.2981007, -0.10571146]
[-0.87585616, -0.08150554, -0.4999045]
[-0.36705136, 0.9787103, 0.12711072]
[-0.85927045, 0.7996801, 0.48348153]
[-0.8701681, 0.63198125, 0.57068086]
``````

But there’s probably a more idiomatic way. Hopefully someone else can point you towards it. I haven’t really used `Distributions` so I’m not familiar with the interfaces it provides.

By the way, it’s good practice to mention the packages you’re using. If someone didn’t recognize `Uniform` and `SVector` then they wouldn’t know you were using `Distributions` and `StaticArrays` and it would be difficult to help you.

2 Likes

You can do

``````[2 .* rand(SVector{3, Float64}) .- 1 for _ in 1:10]
``````

but it doesn’t generalize very well to other distributions.

1 Like

Or `reinterpret` the other way:

``````julia> reinterpret(SVector{3, Float64},rand(Uniform(-1,1),prod((3,10))))
10-element reinterpret(SVector{3, Float64}, ::Vector{Float64}):
[0.342863141712473, 0.3758805838896866, 0.27241838039458677]
...
``````
1 Like
3 Likes

Yes but this seems to be adding significant computation cost in my case.

I will keep the suggestion in mind for future questions, thank you!

No, it should be much faster than the alternative:

``````foo(N) = [2 .* rand(SVector{3, Float64}) .- 1 for _ in 1:N]

function bar(N)
z = Vector{SVector{3,Float64}}(undef, N)
rand!(Uniform(-1, 1), reinterpret(Float64, z))
return z
end
``````

Timing:

``````julia> using BenchmarkTools

julia> @btime foo(10);
96.635 ns (1 allocation: 304 bytes)

julia> @btime bar(10);
414.141 ns (1 allocation: 304 bytes)
``````
1 Like

I think OP meant compared to the simple `rand(SVector..)` construct, although even then I don’t see a material slowdown:

``````julia> baz(N) = rand(SVector{3,Float64}, N)
baz (generic function with 1 method)

julia> @btime foo(10);
70.961 ns (1 allocation: 304 bytes)

julia> @btime bar(10);
297.378 ns (1 allocation: 304 bytes)

julia> @btime baz(10);
64.082 ns (1 allocation: 304 bytes)
``````
1 Like

I am new to Julia so I may be doing something wrong. I will try again and see