Skip to content

mul! with two BandedMatrices that share data through a view throws an ArgumentError #474

@MikaelSlevinsky

Description

@MikaelSlevinsky

mul! can work with nonintersecting views of dense matrices:

julia> using LinearAlgebra

julia> A = zeros(10, 10); A[1:5, 1:5] .= randn(5, 5);

julia> B = randn(5,5);

julia> A1 = view(A, 1:5, 1:5);

julia> A2 = view(A, 1:5, 6:10);

julia> using LinearAlgebra

julia> A = zeros(5, 10); A[1:5, 1:5] .= randn(5, 5);

julia> B = randn(5,5);

julia> A1 = view(A, 1:5, 1:5);

julia> A2 = view(A, 1:5, 6:10);

julia> mul!(A2, B, A1)
5×5 view(::Matrix{Float64}, 1:5, 6:10) with eltype Float64:
 -2.65047   1.63847   -0.972346  -0.803627    2.03012
 -0.817101  1.09273   -1.04688    0.41023    -1.15711
 -3.21165   0.721003  -5.99989   -2.00797     7.1199
 -1.67402   1.31855   -4.07428   -0.0920713   1.73292
 -1.01159   2.77983    1.81222    0.589318   -2.18872

Success!

With banded matrices, this same kind of operation doesn't work:

julia> using BandedMatrices

julia> ADATA = randn(3, 10);

julia> A1 = BandedMatrices._BandedMatrix(view(ADATA, 1:3, 1:5), 5, 1, 1);

julia> A2 = BandedMatrices._BandedMatrix(view(ADATA, 1:3, 6:10), 5, 1, 1);

julia> mul!(A2, B, A1)
ERROR: ArgumentError: an array of type `BandedMatrix` shares memory with another argument
and must make a preventative copy of itself in order to maintain consistent semantics,
but `copy(::BandedMatrix{Float64, SubArray{Float64, 2, Matrix{Float64}, Tuple{UnitRange{Int64}, UnitRange{Int64}}, false}, Base.OneTo{Int64}})` returns a new array of type `BandedMatrix{Float64, Matrix{Float64}, Base.OneTo{Int64}}`.
To fix, implement:
    `Base.unaliascopy(A::BandedMatrix)::typeof(A)`
Stacktrace:
 [1] _unaliascopy(A::BandedMatrix{Float64, SubArray{…}, Base.OneTo{…}}, C::BandedMatrix{Float64, Matrix{…}, Base.OneTo{…}})
   @ Base ./abstractarray.jl:1500
 [2] unaliascopy(A::BandedMatrix{Float64, SubArray{Float64, 2, Matrix{Float64}, Tuple{UnitRange{}, UnitRange{}}, false}, Base.OneTo{Int64}})
   @ Base ./abstractarray.jl:1498
 [3] unalias
   @ ./abstractarray.jl:1481 [inlined]
 [4] copyto!
   @ ~/.julia/packages/ArrayLayouts/B2wRU/src/muladd.jl:82 [inlined]
 [5] copyto!
   @ ~/.julia/packages/ArrayLayouts/B2wRU/src/mul.jl:142 [inlined]
 [6] mul!(dest::BandedMatrix{Float64, SubArray{…}, Base.OneTo{…}}, A::Matrix{Float64}, B::BandedMatrix{Float64, SubArray{…}, Base.OneTo{…}})
   @ ArrayLayouts ~/.julia/packages/ArrayLayouts/B2wRU/src/mul.jl:143
 [7] mul!(dest::BandedMatrix{Float64, SubArray{…}, Base.OneTo{…}}, A::Matrix{Float64}, B::BandedMatrix{Float64, SubArray{…}, Base.OneTo{…}})
   @ ArrayLayouts ~/.julia/packages/ArrayLayouts/B2wRU/src/mul.jl:212
 [8] top-level scope
   @ REPL[31]:1
Some type information was truncated. Use `show(err)` to see complete types.

julia> 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions