-
Notifications
You must be signed in to change notification settings - Fork 415
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
Uniform is not type stable + Bounds type should be independent of distribution type #1041
Comments
This isn't really what is usually called type stability. |
The current definition imposes some restrictions on the API that are not necessary. Removing In that case, all these redundant defenitions can be removed: |
It's usually beneficial to make these kinds of restrictions. It makes it easier when defining methods for the julia> Uniform2{Float32}("W", :fwe)
Uniform2{Float32}(
a: W
b: fwe
) |
You are right, I edited my proposal, so that a and b are |
Another thing, if the struct fields are abstract, as in you proposal, the compiler can't infer the return types for functions of the struct. This causes a big overhead and is the reason why the distributions initially used to be hard coded for I'm not completely sure about the role of the type parameter in your proposal. Is it so allow for different types for the parameters of the distribution and realized values of it? In theory that could make sense but we always have to balance generality with the overhead that more flexible struct impose on the methods defined for the struct. So far, I think it's been mostly sufficient to require the types of the parameters and realizations to be the same. Btw, in #1041 (comment) I was wrong about the Rmath part. I was fooled
where rand(rng::AbstractRNG, d::Uniform{T}) where T = d.a + (d.b - d.a) * convert(T, rand(rng)) might be sufficient to fix the issue here. |
From the mathematical point of view, My problem was that for example, for creating a simple Uniform(Float32(1), Float32(2)) while we can just simply write Uniform{Float32}(1,2) The latter seems more natural to me. |
As mentioned on the discourse, having probability The other points you mentioned are more to do with improving the syntax for construction and overloading |
If you think that we should keep the type of struct Uniform{T} <: ContinuousUnivariateDistribution
a::T
b::T
# Uniform{T}(a::T, b::T) constructor
function Uniform{T}(a::T, b::T; check_args=true) where {T <: Real}
check_args && @check_args(Uniform, a < b)
return new{T}(a, b)
end
# Abstract a,b - Uniform{T}(a, b) constructor
function Uniform{T}(a::Real, b::Real; check_args=true) where {T <: Real}
check_args && @check_args(Uniform, a < b)
return new{T}(T(a), T(b))
end
# Uniform{T}(a::T, b::T) constructor
function Uniform{T}(a::T, b::T) where {T <:Complex}
new{T}(a, b)
end
# Abstract a,b - Uniform{T}(a, b) constructor
function Uniform{T}(a, b) where {T <: Complex}
return new{T}(T(a), T(b))
end
end
# Real
# zeros() like constructor (Uniform(T, a::T, b::T))
function Uniform(::Type{T}, a::T, b::T; check_args=true) where {T <: Real}
return Uniform{T}(a, b, check_args = check_args)
end
# Abstract a,b - zeros() like constructor (Uniform(T, a, b))
function Uniform(::Type{T}, a, b; check_args=true) where {T <: Real}
return Uniform{T}(T(a), T(b), check_args = check_args)
end
# No type specified constructor:
function Uniform(a::Float64, b::Float64; check_args=true)
return Uniform{Float64}(a, b, check_args = check_args)
end
# Abstract a,b - no type specified constructor:
function Uniform(a, b; check_args=true)
return Uniform{Float64}(Float64(a), Float64(b), check_args = check_args)
end
# Complex
# zeros() like constructor (Uniform(T, a::T, b::T))
function Uniform(::Type{T}, a::T, b::T) where {T <: Complex}
return Uniform{T}(a, b)
end
# Abstract a,b - zeros() like constructor (Uniform(T, a, b))
function Uniform(::Type{T}, a, b) where {T <: Complex}
return Uniform{T}(T(a), T(b))
end
# No type specified constructor:
function Uniform(a::ComplexF64, b::ComplexF64)
return Uniform{ComplexF64}(a, b)
end
|
The current definition of
Uniform
is not type stable. I tried to make a method in #1035 to make it usable, but it doesn't help.The definition should not be dependent on the type of
a
andb
. From the mathematical point of view,a
andb
bounds may not be part of the distribution and so their type shouldn't matter. Actually their probability is equal to 0!https://github.com/JuliaStats/Distributions.jl/blob/master/src/univariate/continuous/uniform.jl#L26
Instead, the user should provide the type explicitly. It should use
Float64
if no type is provided.The following definition is my proposed definition:
for array like constructor
(Uniform{T}(a, b))
for zeros like constructor
(Uniform(T, a, b))
No type specified constructor:
API examples:
The text was updated successfully, but these errors were encountered: