Skip to content

Commit 23efecb

Browse files
authored
Broadcast a vector to a band (#367)
* Broadcast a vector to a band * copy non-data band to offset vector
1 parent 76a25db commit 23efecb

File tree

4 files changed

+84
-31
lines changed

4 files changed

+84
-31
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "BandedMatrices"
22
uuid = "aae01518-5342-5314-be14-df237901396f"
3-
version = "0.17.25"
3+
version = "0.17.26"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

src/banded/BandedMatrix.jl

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -448,18 +448,18 @@ function dataview(V::BandedMatrixBand)
448448
end
449449

450450
# B[band(i)]
451-
function copyto!(v::Vector, B::BandedMatrixBand)
451+
function copyto!(v::AbstractVector, B::BandedMatrixBand)
452452
A = parent(parent(B))
453453
if -A.l band(B) A.u
454454
copyto!(v, dataview(B))
455455
else
456456
Binds = axes(B,1)
457-
v[Binds] .= 0
457+
v[firstindex(v)-1 .+ Binds] .= 0
458458
end
459459
return v
460460
end
461461

462-
# B[band(i)] .= x
462+
# B[band(i)] .= x::Number
463463
function fill!(Bv::BandedMatrixBand, x)
464464
b = band(Bv)
465465
A = parent(parent(Bv))
@@ -472,6 +472,29 @@ function fill!(Bv::BandedMatrixBand, x)
472472
Bv
473473
end
474474

475+
# B[band(i)] .= V::AbstractVector
476+
function _copyto!(Bv::BandedMatrixBand, V::AbstractVector)
477+
isempty(V) && return Bv
478+
A = parent(parent(Bv))
479+
if -A.l band(Bv) A.u
480+
copyto!(dataview(Bv), V)
481+
else
482+
# bounds-checking to work around axis offset of V
483+
destinds, srcinds = LinearIndices(Bv), LinearIndices(V)
484+
idf, isf = first(destinds), first(srcinds)
485+
Δi = idf - isf
486+
(checkbounds(Bool, destinds, isf+Δi) &
487+
checkbounds(Bool, destinds, last(srcinds)+Δi)) ||
488+
throw(BoundsError(dest, srcinds))
489+
490+
all(iszero, V) || throw(BandError(A, band(Bv)))
491+
end
492+
return Bv
493+
end
494+
495+
copyto!(Bv::BandedMatrixBand, V::AbstractVector) = _copyto!(Bv, V)
496+
copyto!(Bv::BandedMatrixBand, V::BandedMatrixBand) = _copyto!(Bv, V)
497+
475498
# ~ indexing along a row
476499

477500

@@ -530,6 +553,7 @@ end
530553

531554
@propagate_inbounds function setindex!(A::BandedMatrix{T}, v::AbstractVector, ::Colon) where {T}
532555
A[:, :] = reshape(v,size(A))
556+
A
533557
end
534558

535559

@@ -542,10 +566,10 @@ end
542566
row = A.u - b.i + 1
543567
data, i = A.data, max(b.i + 1, 1)
544568
for v in V
545-
data[row, i] = convert(T, v)::T
569+
@inbounds data[row, i] = v
546570
i += 1
547571
end
548-
V
572+
A
549573
end
550574

551575

@@ -557,12 +581,14 @@ end
557581
@boundscheck checkbandmatch(A,V,:,j)
558582

559583
A.data[data_colrange(A,j)] = V[colrange(A,j)]
560-
V
584+
A
561585
end
562586

563587
# vector - BandRange - integer -- A[1, BandRange] = 2
564-
@propagate_inbounds setindex!(A::BandedMatrix, V::AbstractVector, ::BandRangeType, j::Integer) =
565-
(A[colrange(A, j), j] = V) # call range method
588+
@propagate_inbounds function setindex!(A::BandedMatrix, V::AbstractVector, ::BandRangeType, j::Integer)
589+
A[colrange(A, j), j] = V # call range method
590+
A
591+
end
566592

567593
# vector - range - integer -- A[1:3, 1] = [1, 2, 3]
568594
@propagate_inbounds function setindex!(A::BandedMatrix, V::AbstractVector, kr::AbstractRange, j::Integer)
@@ -580,7 +606,7 @@ end
580606
inbands_setindex!(data, u, v, k, j)
581607
end
582608
end
583-
V
609+
A
584610
end
585611

586612

@@ -607,12 +633,14 @@ end
607633
end
608634

609635
A.data[data_rowrange(A,k)] = V[rowrange(A,k)]
610-
V
636+
A
611637
end
612638

613639
# vector - integer - BandRange -- A[1, BandRange] = [1, 2, 3]
614-
@propagate_inbounds setindex!(A::BandedMatrix, V::AbstractVector, k::Integer, ::BandRangeType) =
615-
(A[k, rowstart(A, k):rowstop(A, k)] = V) # call range method
640+
@propagate_inbounds function setindex!(A::BandedMatrix, V::AbstractVector, k::Integer, ::BandRangeType)
641+
A[k, rowstart(A, k):rowstop(A, k)] = V # call range method
642+
A
643+
end
616644

617645
# vector - integer - range -- A[1, 2:3] = [3, 4]
618646
@propagate_inbounds function setindex!(A::BandedMatrix, V::AbstractVector, k::Integer, jr::AbstractRange)
@@ -630,7 +658,7 @@ end
630658
inbands_setindex!(data, u, v, k, j)
631659
end
632660
end
633-
V
661+
A
634662
end
635663

636664
# ~ indexing over a rectangular block
@@ -641,7 +669,7 @@ end
641669
@boundscheck checkdimensions(kr, jr, V)
642670
@boundscheck checkbandmatch(A, V, kr, jr)
643671
copyto!(view(A, kr, jr), V)
644-
V
672+
A
645673
end
646674

647675
# ~~ end setindex! ~~

test/test_banded.jl

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ Base.similar(::MyMatrix, ::Type{T}, m::Int, n::Int) where T = MyMatrix{T}(undef,
471471
end
472472

473473
@testset "setindex! with ranges (#348)" begin
474-
n = 10;
474+
n = 10;
475475
X1 = brand(n,n,1,1)
476476
B = BandedMatrix(Zeros(2n,2n), (3,3))
477477
B[1:2:end,1:2:end] = X1
@@ -480,20 +480,19 @@ Base.similar(::MyMatrix, ::Type{T}, m::Int, n::Int) where T = MyMatrix{T}(undef,
480480
@test A == B
481481
end
482482

483-
@testset "broadcasting to a band" begin
484-
B = brand(Int8, 6, 6, -2, 2)
485-
B[band(2)] .= 10
486-
@test all(==(10), diag(B, 2))
487-
@test all(==(10), B[band(2)])
488-
489-
B = brand(Int8, 2, 4, 1, 1)
490-
B[band(-1)] .= 2
491-
B[band(0)] .= 3
492-
B[band(1)] .= 4
493-
@test B == [3 4 0 0; 2 3 4 0]
494-
495-
@test_throws BandError B[band(100)] .= 10
496-
@test_throws BandError B[band(-100)] .= 10
483+
@testset "copy band to offset vector" begin
484+
B = BandedMatrix(2=>2:3)
485+
# test that a BandedMatrix and a Matrix behave identically
486+
p = zeros(3)
487+
v = view(p, Base.IdentityUnitRange(2:3))
488+
for M in (B, Matrix(B))
489+
p .= 0
490+
copyto!(v, diag(M, 2))
491+
@test p[1] == 0
492+
@test @view(p[2:3]) == 2:3
493+
copyto!(v, diag(M, 10))
494+
@test p[1] == 0
495+
@test @view(p[2:3]) == 2:3
496+
end
497497
end
498498
end
499-

test/test_broadcasting.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,4 +729,30 @@ import BandedMatrices: BandedStyle, BandedRows, BandError
729729
@test Z .* A Z
730730
@test A .* Z Z
731731
end
732+
733+
@testset "broadcasting to a band" begin
734+
B = brand(Int8, 6, 6, -2, 2)
735+
B[band(2)] .= 10
736+
@test all(==(10), diag(B, 2))
737+
@test all(==(10), B[band(2)])
738+
739+
B = brand(Int8, 2, 4, 1, 1)
740+
B[band(-1)] .= 2
741+
B[band(0)] .= 3
742+
B[band(1)] .= 4
743+
B[band(2)] .= 0
744+
@test B == [3 4 0 0; 2 3 4 0]
745+
746+
B[band(-1)] .= 3:3
747+
@test all(==(3), @view B[band(-1)])
748+
B[band(0)] .= 4:5
749+
@test (@view B[band(0)]) == 4:5
750+
B[band(1)] .= 3:4
751+
@test (@view B[band(1)]) == 3:4
752+
B[band(2)] .= [0,0]
753+
@test all(iszero, @view B[band(2)])
754+
755+
@test_throws BandError B[band(100)] .= 10
756+
@test_throws BandError B[band(-100)] .= 10
757+
end
732758
end

0 commit comments

Comments
 (0)