davidavdav / NamedArrays.jl

Julia type that implements a drop-in replacement of Array with named dimensions
Other
120 stars 20 forks source link

BoundsError on broadcasting over `NamedArray` with abstract `eltype` #114

Open yha opened 3 years ago

yha commented 3 years ago

A simple reproducer:

julia> using NamedArrays

julia> identity.(NamedArray(AbstractMatrix{Int}[[1 2; 3 4]]))
ERROR: BoundsError: attempt to access Tuple{} at index [1]
Stacktrace:
 [1] getindex(t::Tuple, i::Int64)
   @ Base .\tuple.jl:29
 [2] find_namedarray(args::Tuple{})
   @ NamedArrays C:\Users\sternlab\.julia\packages\NamedArrays\TuJLn\src\keepnames.jl:61
 [3] find_namedarray(#unused#::Tuple{}, rest::Tuple{})
   @ NamedArrays C:\Users\sternlab\.julia\packages\NamedArrays\TuJLn\src\keepnames.jl:65
 [4] find_namedarray(args::Tuple{Base.Broadcast.Extruded{NamedVector{AbstractMatrix{Int64}, Vector{AbstractMatrix{Int64}}, Tuple{OrderedCollections.OrderedDict{String, Int64}}}, Tuple{Bool}, Tuple{Int64}}})
   @ NamedArrays C:\Users\sternlab\.julia\packages\NamedArrays\TuJLn\src\keepnames.jl:61
 [5] find_namedarray(bc::Base.Broadcast.Broadcasted{Base.Broadcast.ArrayStyle{NamedArray}, Tuple{Base.OneTo{Int64}}, typeof(identity), Tuple{Base.Broadcast.Extruded{NamedVector{AbstractMatrix{Int64}, Vector{AbstractMatrix{Int64}}, Tuple{OrderedCollections.OrderedDict{String, Int64}}}, Tuple{Bool}, Tuple{Int64}}}})
   @ NamedArrays C:\Users\sternlab\.julia\packages\NamedArrays\TuJLn\src\keepnames.jl:59
 [6] similar(bc::Base.Broadcast.Broadcasted{Base.Broadcast.ArrayStyle{NamedArray}, Tuple{Base.OneTo{Int64}}, typeof(identity), Tuple{Base.Broadcast.Extruded{NamedVector{AbstractMatrix{Int64}, Vector{AbstractMatrix{Int64}}, Tuple{OrderedCollections.OrderedDict{String, Int64}}}, Tuple{Bool}, Tuple{Int64}}}}, #unused#::Type{Matrix{Int64}})
   @ NamedArrays C:\Users\sternlab\.julia\packages\NamedArrays\TuJLn\src\keepnames.jl:55
 [7] copy
   @ .\broadcast.jl:923 [inlined]
 [8] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.ArrayStyle{NamedArray}, Nothing, typeof(identity), Tuple{NamedVector{AbstractMatrix{Int64}, Vector{AbstractMatrix{Int64}}, Tuple{OrderedCollections.OrderedDict{String, Int64}}}}})
   @ Base.Broadcast .\broadcast.jl:883
 [9] top-level scope
   @ REPL[31]:1

I encountered this when trying to work with block arrays with named blocks, roughly as follows:

using NamedArrays, BlockArrays
mn = mortar(NamedArray([rand(i,j) for i=2:4, j=3:5]))
eachblockrow(x) = (view(x,b,:) for b in blockaxes(x,1))
f(x) = x
processed_block_rows = reduce(vcat, blocks.(f.(eachblockrow(m))))
f.(processed_block_rows) # Fine
f.(NamedArray(processed_block_rows, names(blocks(mn)))) # BoundsError
f.(NamedArray(identity.(processed_block_rows), names(blocks(mn)))) # Workaround
davidavdav commented 3 years ago

Thanks for reporting this bug. At first it seemed pretty esoteric to me. I have to admit that I don't understand broadcasting very much. I looks like somehow broadcasting is throwing a Base.Broadcast.Extruded into the situation, I have no idea what that is supposed to do. Maybe @diegozea knows what is going on?

icweaver commented 2 years ago

Idk if this is related, but I think I was able to reproduce the error when I forgot to specify the type parameter for an array (any kind really) before operating on it. For example:

n = NamedArray(zeros(Complex, 2))
n .- 2

throws the BoundsError above, while:

n = NamedArray(zeros(Complex{Float64}, 2))
n .- 2

looks to behave as expected

davidavdav commented 2 years ago

Thanks, pretty esoteric indeed. Thanks for finding this one