diff --git a/src/adjtrans.jl b/src/adjtrans.jl index b722e49b..f7caa9bc 100644 --- a/src/adjtrans.jl +++ b/src/adjtrans.jl @@ -382,6 +382,20 @@ parent(A::AdjOrTrans) = A.parent vec(v::TransposeAbsVec{<:Number}) = 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/test/adjtrans.jl b/test/adjtrans.jl index 6cf2ff9a..50565583 100644 --- a/test/adjtrans.jl +++ b/test/adjtrans.jl @@ -308,6 +308,35 @@ end @test vec(adjoint(mvec))[1] == adjoint(mvec[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