diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 56942930d7aa7..44ceeb43ede2a 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -241,6 +241,20 @@ parent(A::AdjOrTrans) = A.parent vec(v::TransposeAbsVec) = parent(v) vec(v::AdjointAbsVec{<:Real}) = parent(v) +Base.reshape(v::TransposeAbsVec{<:Number}, ::Val{1}) = parent(v) +Base.reshape(v::AdjointAbsVec{<:Real}, ::Val{1}) = parent(v) + +# these make eachrow(A') produce simpler views +@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::Integer, j::AbstractArray) = + Base.unsafe_view(parent(A), j, i) +@inline Base.unsafe_view(A::Transpose{<:Number, <:AbstractMatrix}, i::AbstractArray, j::Integer) = + Base.unsafe_view(parent(A), j, i) + +@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::Integer, j::AbstractArray) = + Base.unsafe_view(parent(A), j, i) +@inline Base.unsafe_view(A::Adjoint{<:Real, <:AbstractMatrix}, i::AbstractArray, j::Integer) = + Base.unsafe_view(parent(A), j, i) + ### concatenation # preserve Adjoint/Transpose wrapper around vectors # to retain the associated semantics post-concatenation diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index bb2e54d306224..61c914d1a7f9e 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -277,6 +277,35 @@ end @test vec(cvec')[1] == cvec[1]' end +@testset "Adjoint and Transpose view methods" begin + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + # overload of reshape(v, Val(1)) simplifies views of row vectors: + @test view(adjoint(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} + @test view(transpose(intvec), 1:2) isa SubArray{Int, 1, Vector{Int}} + cvec = [1, 2im, 3, 4im] + @test view(transpose(cvec), 2:3) === view(cvec, 2:3) + @test view(adjoint(cvec), 2:3) == conj(view(cvec, 2:3)) + + # vector slices of transposed matrices are simplified: + @test view(adjoint(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} + @test view(transpose(intmat), 1, :) isa SubArray{Int, 1, Matrix{Int}} + @test view(adjoint(intmat), 1, :) == permutedims(intmat)[1, :] + @test view(transpose(intmat), 1:1, :) == permutedims(intmat)[1:1, :] # not simplified + @test view(adjoint(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} + @test view(transpose(intmat), :, 2) isa SubArray{Int, 1, Matrix{Int}} + @test view(adjoint(intmat), :, 2) == permutedims(intmat)[:, 2] + @test view(transpose(intmat), :, 2:2) == permutedims(intmat)[:, 2:2] # not simplified + cmat = [1 2im 3; 4im 5 6im] + @test view(transpose(cmat), 1, :) isa SubArray{Complex{Int}, 1, Matrix{Complex{Int}}} + @test view(transpose(cmat), :, 2) == cmat[2, :] + @test view(adjoint(cmat), :, 2) == conj(cmat[2, :]) # not simplified + + # bounds checks happen before this + @test_throws BoundsError view(adjoint(intvec), 0:3) + @test_throws BoundsError view(transpose(cvec), 0:3) + @test_throws BoundsError view(adjoint(intmat), :, 3) +end + @testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin # horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers # should preserve the Adjoint/Transpose-wrapper to preserve semantics downstream