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

Forward axes to the parent for a Diagonal #50514

Merged
merged 3 commits into from
Aug 28, 2023
Merged

Forward axes to the parent for a Diagonal #50514

merged 3 commits into from
Aug 28, 2023

Conversation

jishnub
Copy link
Contributor

@jishnub jishnub commented Jul 12, 2023

Given that quite a few packages define axes(d::Diagonal{T, CustomVector{T}}) as ax = parent(d); (ax,ax), perhaps it makes sense to have this defined in LinearAlgebra.

After this,

julia> using StaticArrays, StructArrays, LinearAlgebra

julia> D = Diagonal(StructArray{Complex{Int}}((SA[1,2], SA[1,2])))
2×2 Diagonal{Complex{Int64}, StructVector{Complex{Int64}, @NamedTuple{re::SVector{2, Int64}, im::SVector{2, Int64}}, Int64}} with indices SOneTo(2)×SOneTo(2):
 1+1im      
       2+2im

julia> axes(D)
(SOneTo(2), SOneTo(2))

The static sizes are preserved.

This is potentially breaking, as similar may be undefined/ambiguous for custom axis types (see JuliaArrays/StructArrays.jl#279), but this may be something to explore in the future. Packages should perhaps figure this out, as the specific method is broken anyway.

@jishnub jishnub marked this pull request as draft July 12, 2023 07:18
@stevengj
Copy link
Member

Seems fine to me.

(Note that Diagonal throws an error for non 1-based diag arrays, so this will still be 1-based axes.)

@brenhinkeller brenhinkeller added the linear algebra Linear algebra label Aug 4, 2023
@jishnub jishnub marked this pull request as ready for review August 28, 2023 08:40
@jishnub
Copy link
Contributor Author

jishnub commented Aug 28, 2023

I think this should be good. @dkarrasch could you take a look? Given the decision in #50530 to treat oneto as internal, we may need such specializations to avoid breaking InfiniteArrays.

In particular, currently

julia> D = Diagonal(1:∞); D[:,1:3]
ERROR: MethodError: no method matching Int64(::Infinities.InfiniteCardinal{0})

Closest candidates are:
  (::Type{T})(::T) where T<:Number
   @ Core boot.jl:791
  Int64(::Float64)
   @ Base float.jl:962
  Int64(::Float32)
   @ Base float.jl:962
  ...

Stacktrace:
 [1] to_shape(r::Base.OneTo{Infinities.InfiniteCardinal{0}})
   @ Base ./abstractarray.jl:847
 [2] map
   @ Base ./tuple.jl:292 [inlined]
 [3] to_shape(dims::Tuple{Base.OneTo{Infinities.InfiniteCardinal{0}}, Base.OneTo{Int64}})
   @ Base ./abstractarray.jl:843
 [4] similar(a::Diagonal{Int64, InfiniteArrays.InfUnitRange{Int64}}, dims::Tuple{Base.OneTo{Infinities.InfiniteCardinal{0}}, Base.OneTo{Int64}})
   @ Base ./abstractarray.jl:828
 [5] _unsafe_getindex(::IndexCartesian, ::Diagonal{Int64, InfiniteArrays.InfUnitRange{Int64}}, ::Base.Slice{Base.OneTo{Infinities.InfiniteCardinal{0}}}, ::UnitRange{Int64})
   @ Base ./multidimensional.jl:901
 [6] _getindex
   @ Base ./multidimensional.jl:889 [inlined]
 [7] getindex(::Diagonal{Int64, InfiniteArrays.InfUnitRange{Int64}}, ::Function, ::UnitRange{Int64})
   @ Base ./abstractarray.jl:1286
 [8] top-level scope
   @ REPL[5]:1

is broken on master, although this works on v1.9.3. This PR fixes it.

Co-authored-by: Daniel Karrasch <daniel.karrasch@posteo.de>
@jishnub jishnub merged commit b4052a5 into master Aug 28, 2023
@jishnub jishnub deleted the jishnub/diagaxes branch August 28, 2023 15:33
@jishnub
Copy link
Contributor Author

jishnub commented Aug 29, 2023

Unfortunately, this PR worsens the inferred type of axes, but hopefully union-splitting and constant-propagation should help with that.

julia> v = SVector(1,2,3,4);

julia> D = Diagonal(v)
4×4 Diagonal{Int64, SVector{4, Int64}} with indices SOneTo(4)×SOneTo(4):
 1      
   2    
     3  
       4

julia> @inferred axes(v,1) # not inferred concretely
ERROR: return type SOneTo{4} does not match inferred return type Union{SOneTo{4}, Base.OneTo{Int64}}
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] top-level scope
   @ REPL[32]:1

julia> @inferred (x -> axes(x,1))(v) # type-inferred
SOneTo(4)

julia> @inferred (x -> axes(x,3))(v)
Base.OneTo(1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linear algebra Linear algebra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants