Hi,
The LinearIndices
type is defined in Base at line 382 of indices.jl as
struct LinearIndices{N,R<:NTuple{N,AbstractUnitRange{Int}}} <: AbstractArray{Int,N}
indices::R
end
I’m wondering why it’s defined to hold an NTuple{N,AbstractUnitRange{Int}}}
rather than being defined along the lines of:
struct MyLinearIndices{N,Tn,R<:NTuple{N,AbstractUnitRange{Tn}}} <: AbstractArray{Tn,N}
indices::R
end
The issue with the current implementation is that you can’t convert a Cartesian index to a linear index if the resulting linear index is too big to represented by an Int
. For example (with Int
=Int64
on my system, running on current master branch julia):
julia> l = Int128(10_000_000);
julia> sz = (l,l,l)
(10000000, 10000000, 10000000)
julia> LI = LinearIndices(sz);
julia> LI[l,l,l]
3875820019684212736
julia> l^3
1000000000000000000000
I do need to convert cartesian indices to such large linear indices in practice. It’s part of a sparse 3D array implementation. I was able to get what I was looking for by extending a few methods for the MyLinearIndices
type defined above:
MyLinearIndices(sz::NTuple{N,Tn}) where {N,Tn<:Integer} = MyLinearIndices(map(Base.OneTo, sz))
IndexStyle(::Type{<:MyLinearIndices}) = IndexLinear()
axes(iter::MyLinearIndices) = map(axes1, iter.indices)
size(iter::MyLinearIndices) = map(unsafe_length, iter.indices)
function getindex(iter::MyLinearIndices, i::Integer)
@_inline_meta
@boundscheck checkbounds(iter, i)
i
end
function getindex(iter::MyLinearIndices, i::AbstractRange{<:Integer})
@_inline_meta
@boundscheck checkbounds(iter, i)
@inbounds isa(iter, LinearIndices{1}) ? iter.indices[1][i] : (first(iter):last(iter))[i]
end
Using this new type gives me
julia> myLI = MyLinearIndices(sz);
julia> myLI[l,l,l]
1000000000000000000000
I don’t know the array indexing code very well so I don’t know whether or not there’s a good reason to force LinearIndices
to use Int
s rather than working with arbitrary integer types? Is there a good reason or was this just an oversight? If it was just an oversight then I can prepare a PR with a fix based on the MyLinearIndices
stuff in this post. I believe it could count as a bugfix and not as a breaking change. On the other hand, if the current behaviour is intended I would be grateful if someone could explain the reasoning behind it a little.
Thanks very much, Patrick