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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions