Skip to content

Commit 8695b51

Browse files
authored
CartesianIndex constructor for BandIndex (#1304)
This allows easier conversion from a `BandIndex` to a `CartesianIndex` by using the `CartesianIndex` constructor. It also skips the intermediate conversion in `to_indices` where we need the `(row, column)` tuple directly. After this, the following is possible: ```julia julia> b = LinearAlgebra.BandIndex(0, 2) BandIndex(0, 2) julia> c = CartesianIndex(b) CartesianIndex(2, 2) julia> LinearAlgebra.BandIndex(c) BandIndex(0, 2) ``` I had not added the constructor earlier to avoid potential invalidations, but I don't think this is a factor, given that `Base` already defines four methods for `CartesianIndex`.
1 parent 6e8f9a1 commit 8695b51

File tree

3 files changed

+25
-11
lines changed

3 files changed

+25
-11
lines changed

src/LinearAlgebra.jl

+18-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Base: USE_BLAS64, abs, acos, acosh, acot, acoth, acsc, acsch, adjoint, as
1515
IndexStyle, kron, kron!, length, log, map, ndims, one, oneunit, parent, permutecols!,
1616
permutedims, permuterows!, power_by_squaring, promote_rule, real, isreal, sec, sech, setindex!,
1717
show, similar, sin, sincos, sinh, size, sqrt, strides, stride, tan, tanh, transpose, trunc,
18-
typed_hcat, vec, view, zero
18+
typed_hcat, vec, view, zero, CartesianIndex
1919
import Base: AbstractArray, AbstractMatrix, Array, Matrix
2020
using Base: IndexLinear, promote_eltype, promote_op, print_matrix,
2121
@propagate_inbounds, reduce, typed_hvcat, typed_vcat, require_one_based_indexing,
@@ -508,21 +508,29 @@ struct BandIndex
508508
band :: Int
509509
index :: Int
510510
end
511-
function _cartinds(b::BandIndex)
511+
function _torowcol(b::BandIndex)
512512
(; band, index) = b
513-
bandg0 = max(band,0)
514-
row = index - band + bandg0
515-
col = index + bandg0
516-
CartesianIndex(row, col)
513+
minband0, maxband0 = minmax(band,0)
514+
row = index - minband0
515+
col = index + maxband0
516+
row, col
517517
end
518-
function Base.to_indices(A, inds, t::Tuple{BandIndex, Vararg{Any}})
519-
to_indices(A, inds, (_cartinds(first(t)), Base.tail(t)...))
518+
CartesianIndex(b::BandIndex) = CartesianIndex{2}(b)
519+
CartesianIndex{2}(b::BandIndex) = CartesianIndex{2}(_torowcol(b))
520+
function BandIndex(c::CartesianIndex{2})
521+
row, col = Tuple(c)
522+
band = col - row
523+
index = min(row, col)
524+
BandIndex(band, index)
525+
end
526+
function Base.to_indices(A, inds, t::Tuple{BandIndex, Vararg})
527+
to_indices(A, inds, (_torowcol(first(t))..., Base.tail(t)...))
520528
end
521529
function Base.checkbounds(::Type{Bool}, A::AbstractMatrix, b::BandIndex)
522-
checkbounds(Bool, A, _cartinds(b))
530+
checkbounds(Bool, A, _torowcol(b)...)
523531
end
524532
function Base.checkbounds(A::Broadcasted, b::BandIndex)
525-
checkbounds(A, _cartinds(b))
533+
checkbounds(A, CartesianIndex(b))
526534
end
527535

528536
include("adjtrans.jl")

src/structuredbroadcast.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ isvalidstructbc(dest::Bidiagonal, bc::Broadcasted{StructuredMatrixStyle{Bidiagon
194194
@inbounds Broadcast._broadcast_getindex(bc, b)
195195
end
196196

197-
Broadcast.newindex(A, b::BandIndex) = Broadcast.newindex(A, _cartinds(b))
197+
Broadcast.newindex(A, b::BandIndex) = Broadcast.newindex(A, CartesianIndex(b))
198198
function Broadcast.newindex(A::StructuredMatrix, b::BandIndex)
199199
# we use the fact that a StructuredMatrix is square,
200200
# and we apply newindex to both the axes at once to obtain the result

test/special.jl

+6
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,12 @@ end
764764
end
765765
@test_throws BoundsError D[BandIndex(size(D,1),1)]
766766
end
767+
@testset "BandIndex to CartesianIndex" begin
768+
b = BandIndex(1, 2)
769+
c = CartesianIndex(b)
770+
@test c == CartesianIndex(2, 3)
771+
@test BandIndex(c) == b
772+
end
767773
end
768774

769775
@testset "Partly filled Hermitian and Diagonal algebra" begin

0 commit comments

Comments
 (0)