-
Notifications
You must be signed in to change notification settings - Fork 148
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
Adding n x 0 matrices results in Union{} eltype #528
Comments
I guess this is due to getting rid of julia> zeros(3, 0) + zeros(3, 0)
3×0 Array{Float64,2} |
Yes, this was a delibrate change. I wanted to gather feedback - does this cause any actual problems?
I'm also really curious - what do people want zero-sized static arrays for? Someone, somewhere knows the container has no elements... |
In my use cases, I just want things to be as similar as possible to the non-empty case, for the sake of genericity. I can of course handle the empty case more robustly in my packages (and maybe I should), but if a lot of other downstream packages would need to do the same kid of robustification, maybe it'd be better to handle it here. Not sure what I'd replace |
It definitely wouldn't be great if every generic package using |
For types such as julia> x = zero(SMatrix{3, 0})
3×0 SArray{Tuple{3,0},Union{},2,0}
julia> isapprox(x, x)
ERROR: MethodError: LinearAlgebra.promote_leaf_eltypes(::SArray{Tuple{3,0},Union{},2,0}) is ambiguous. Candidates:
promote_leaf_eltypes(x::Union{Tuple{Vararg{T,N} where N}, AbstractArray{T,N} where N}) where T<:(AbstractArray{T,N} where N where T<:Number) in LinearAlgebra at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/generic.jl:1328
promote_leaf_eltypes(x::Union{Tuple{Vararg{T,N} where N}, AbstractArray{T,N} where N}) where T<:Number in LinearAlgebra at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/generic.jl:1327
Possible fix, define
promote_leaf_eltypes(::Union{Tuple{}, AbstractArray{Union{},N} where N})
Stacktrace:
[1] isapprox(::SArray{Tuple{3,0},Union{},2,0}, ::SArray{Tuple{3,0},Union{},2,0}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/generic.jl:1339
[2] top-level scope at none:0 Errors would arise from e.g. this method, which would have to specifically handle the case where julia> eltype(zero(SMatrix{3, 3}) * zero(SMatrix{3, 0}))
Float64 Also note that in this case, So I would propose either something like StaticArrays.jl/src/matrix_multiply.jl Line 37 in 9368cba
for StaticArrays.jl/src/mapreduce.jl Lines 27 to 31 in 9368cba
|
Let me know if you'd be OK with trying the proposal at the end of my previous comment. I can put a PR together if you do. |
Great examples. Your solution using traits to map the eltype sounds kind of sensible to me for cases where the semantic of the operation is clearly numeric (eg, matrix multiply). For |
Good point. So the complete removal of
Taken strictly, I'd think this would be equivalent to 'don't use Were the inference issues / segfaults always because |
Yes, that comment is the reason. Honestly I'm not sure if this is a fundamental issue of asking counterfactuals inside of inference cycles (I mean, that's what inference does in these cycles, right?), or an issue of our implementation of how our compiler handles code explicitly asking counterfactuals inside inference cycles (that is, is it technically possible to plumb explicit usage of
I suspect he's saying you can never safely use
Umm... I dunno? Finally, @tkoolen, to understand the motivation behind all of this I'd still really love to see an example of a length-zero static array popping up in the wild (not a test suite - actual production code). I totally get the idea of genericity - empty containers shouldn't need special code to handle them. But the operations on a The alternatives seem to be use |
I decided to work around this in RigidBodyDynamics.jl for now, especially since I seem to be the only one running into this issue.
I don't see this distinction between test code and production code in this case. I think most test code is possible user code. |
In ACME.jl, I use a non-linear state-space model (but don't use StaticArrays; however, I want to change that eventually, and had a branch with a promising if unfinished implementation). Here, absence of non-linear elements or stateful elements (capacitors) leads to empty matrices/vectors, and even if these are relatively simple circuits, they are by no means irrelevant in practice. That said, when working with |
@tkoolen we still have this issue, and we still have no solution to it. But I'm also not sure how we can take action if we can't use How are you finding this in practice? Is it still a source of pain, or did it turn out to be fairly easy to deal with? |
Yeah, go ahead and close. It was somewhat annoying when I had to put the special cases in place in existing code, but since making those changes the number of times where this was a problem has been very low. |
On second thought we could still fix a few cases where we have insight into the operation. Like the original issue here of adding matrices. I guess that might possibly be worth pursuing, or possibly giving people a way to declare what they want to come out of an operation with zero elements? |
In general, even for
For By the way, So if the goal is to match Base's behavior, we're probably out of luck if we're not allowed to use |
All great points, thanks. I suppose our case here is closest to the line in Base here: which basically returns an empty array with eltype deduced from the first element of the iterator (or rather, the type thereof... given that the iterator is actually empty). Base broadcast also does something similar here and why It seems to me that we would be no worse than parts of Base and linear algebra if we used |
On 0.9.1:
while on 0.8.3:
The text was updated successfully, but these errors were encountered: