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

RFC: Restricts parameter type for randn & randexp to Float types for #17608. #17627

Merged
merged 3 commits into from
Jul 29, 2016
Merged

RFC: Restricts parameter type for randn & randexp to Float types for #17608. #17627

merged 3 commits into from
Jul 29, 2016

Conversation

NHDaly
Copy link
Member

@NHDaly NHDaly commented Jul 26, 2016

Fixes base/random.jl and adds tests to tests/random.jl to restrict parametrized type parameter to one of Float16,Float32,Float64.

These functions already worked only for those types, but erroneously allowed parameters outside those three, with unintended behavior (crashing and infinite-looping). Now, this throws a MethodError if provided a non-float type-parameter.

@tkelman tkelman added the randomness Random number generation and the Random stdlib label Jul 26, 2016
@tkelman
Copy link
Contributor

tkelman commented Jul 26, 2016

Very nice, thank you! cc @rfourquet
Same issue for BigFloat, right? May as well throw that into the tests?

@NHDaly
Copy link
Member Author

NHDaly commented Jul 26, 2016

Done. Although, would we want to consider just adding BigFloat to the list of supported types for randn and randexp? I.e., adding it to the Floats union?

I can leave that for another PR after this bug-fix though. Should I leave a TODO somewhere for it?

@tkelman
Copy link
Contributor

tkelman commented Jul 26, 2016

I imagine there's code somewhere in MPFR for those, but I don't know whether we have the ccall wrappers here yet. I think a TODO as an issue, a code/test comment, or an early WIP PR would be fine.

@NHDaly
Copy link
Member Author

NHDaly commented Jul 26, 2016

I've added code TODOs. Can you verify that I've formatted them in a reasonable way? (I'm new to JuliaLang contributing and don't know your conventions). :)

(Should I have written # TODO(17627): instead of # TODO(#17627):?)

@tkelman
Copy link
Contributor

tkelman commented Jul 26, 2016

3c91c92 looks fine to me, we're not super uniform in formatting of todo's and fixme's

@NHDaly
Copy link
Member Author

NHDaly commented Jul 26, 2016

S.g. Thanks for the review! :)


@test_throws MethodError r(rng..., Number, (2,3))
@test_throws MethodError r(rng..., Any, 1)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a second loop for concision:

for T in [Int, Int32, String, AbstractFloat, BigFloat, Number, Any]
    @test_throws MethodError r(rng..., T)
    @test_throws MethodError r(rng..., T, 1)
    @test_throws MethodError r(rng..., T, (2, 3))
end

(and, why not, a loop over the dimensions: for d in ([], [1], [(2, 3)])).

@rfourquet
Copy link
Member

Another possible fix would be to write a signature similar to what I used there to fix a similar problem, but I guess it makes sense to restrict those randn functions to AbstractFloat anyway (cf. my inline comment for using AbstractFloat instead of $Floats).
Also you may squash the commits when done.
Otherwise LGTM.

$randfun{T<:$Floats}(rng::AbstractRNG, ::Type{T}, dims::Dims) = $randfun!(rng, Array{T}(dims))
$randfun{T<:$Floats}(rng::AbstractRNG, ::Type{T}, dims::Integer...) = $randfun!(rng, Array{T}(dims...))
$randfun{T<:$Floats}( ::Type{T}, dims::Dims) = $randfun(GLOBAL_RNG, T, dims)
$randfun{T<:$Floats}( ::Type{T}, dims::Integer...) = $randfun(GLOBAL_RNG, T, dims...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like these restrictions either, for the same reason as above. It makes it significantly harder to define e.g. randn for new types.

@stevengj
Copy link
Member

stevengj commented Jul 26, 2016

It seems like a better solution is much simpler. Just change:

$randfun{T}(rng::AbstractRNG, ::Type{T}, dims::Integer...) = $randfun!(rng, Array{T}(dims...))

to

$randfun{T}(rng::AbstractRNG, ::Type{T}, dim0::Integer, dims::Integer...) = $randfun!(rng, Array{T}(dim0, dims...))

That will remove the circular fallback definition for $randfun{T}(rng::AbstractRNG, ::Type{T}), without making it harder to define randn for new types.

@rfourquet
Copy link
Member

Ah of course, I had already forgotten about randn for Complex. So I concur with your proposed solution (identical to what I linked to above).

@NHDaly
Copy link
Member Author

NHDaly commented Jul 28, 2016

Hi, yeah that makes a ton of sense. This is a great way to break the recursion, thanks. I wasn't sure what was the best way, so I just tried the first one that came to mind. :) Thanks!

I'll try this tomorrow and send the PR back to you. Sorry for the delay; i don't have my machine with me. Thanks!

@stevengj
Copy link
Member

@NHDaly, note that you should just push a new commit to this PR, rather than opening a brand-new PR.

The functions already only supported Float types
(Float16,Float32,Float64), but could be called with non-float types.
Calling with Non-Float types, e.g. `Int`, could cause an infinite loop.

Also adds tests verifying that randn throws a MethodError for types
besides Float types.
@NHDaly
Copy link
Member Author

NHDaly commented Jul 28, 2016

@stevengj Yep, thanks! I've synced, rebased, and squashed.

This solution definitely looks better, and the tests still pass on my client. Lmk what you think! Thanks

$randfun( dims::Dims) = $randfun(GLOBAL_RNG, Float64, dims)
$randfun( dims::Integer...) = $randfun(GLOBAL_RNG, Float64, dims...)
$randfun{T}(rng::AbstractRNG, ::Type{T}, dims::Dims ) = $randfun!(rng, Array{T}(dims))
$randfun{T}(rng::AbstractRNG, ::Type{T}, dim0::Integer, dims::Integer...) = $randfun!(rng, Array{T}(dim0, dims...))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably dim1 would be more Julian (1-based).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks!

@NHDaly
Copy link
Member Author

NHDaly commented Jul 29, 2016

I've left some inline comments. PTAL. thanks! :)

@stevengj
Copy link
Member

stevengj commented Jul 29, 2016

As noted above, I would strongly prefer that, to add randn for a new type, you should only have to define randn(rng::AbstractRNG, ::Type{T}). This means making the one-argument randn work for any type, not just Floats.

@NHDaly
Copy link
Member Author

NHDaly commented Jul 29, 2016

:) Okay I'm sold! I agree, you should only have to define randn(rng::AbstractRNG, ::Type{T}) for your type. So I've made the one-arg version work for any type. Thanks!

Let me know if this looks okay and I'll squash the commits.

@stevengj
Copy link
Member

LGTM.

@stevengj
Copy link
Member

(No need to squash the commits, the Github merge button can do that for us.)

@stevengj stevengj merged commit e70de21 into JuliaLang:master Jul 29, 2016
@NHDaly
Copy link
Member Author

NHDaly commented Jul 29, 2016

(No need to squash the commits, the Github merge button can do that for us.)

:O Woahh fancy! :) cool thanks!

@NHDaly NHDaly deleted the randn_domain_fix branch August 2, 2016 03:07
mfasi pushed a commit to mfasi/julia that referenced this pull request Sep 5, 2016
…uliaLang#17608. (JuliaLang#17627)

* Fixes infinite recursion in randn for non-floats; fixes JuliaLang#17608.

The functions already only supported Float types
(Float16,Float32,Float64), but could be called with non-float types.
Calling with Non-Float types, e.g. `Int`, could cause an infinite loop.

Also adds tests verifying that randn throws a MethodError for types
besides Float types.

* s/dim0/dim1/

* removed other dimensions, fixed randn(T), added comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
randomness Random number generation and the Random stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants