From 2301129f711f29d9e47365e6eab5f668df6b1d9f Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Tue, 6 Feb 2018 13:18:44 -0500 Subject: [PATCH] Add support for dealiasing Adjoint and Transpose And fixup the assumption that `broadcast!(f, C, A)` is safe --- base/broadcast.jl | 5 ++++- stdlib/LinearAlgebra/src/adjtrans.jl | 4 ++++ stdlib/LinearAlgebra/test/adjtrans.jl | 13 +++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 4702088878b28..55c7f3bcf1cc4 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -484,10 +484,13 @@ end return C end -# In the one-argument case, we don't need to worry about aliasing as we only make one pass +# In the one-argument case, we can avoid de-aliasing `A` from `C` if +# `A === C`. Otherwise `A` might be something like `transpose(C)` or +# another such re-ordering that won't iterate the two safely. @inline function _broadcast!(f, C, A) shape = broadcast_indices(C) @boundscheck check_broadcast_indices(shape, A) + A !== C && (A = unalias(C, A)) keeps, Idefaults = map_newindexer(shape, A, ()) iter = CartesianIndices(shape) _broadcast!(f, C, keeps, Idefaults, A, (), Val(0), iter) diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 45063f983268a..1d428f4a9b597 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -47,6 +47,10 @@ end Adjoint(A) = Adjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A) Transpose(A) = Transpose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A) +using Base: unalias, mightalias, dataids +Base.unalias(dest, A::Union{Adjoint,Transpose}) = mightalias(dest, A) ? typeof(A)(unalias(dest, A.parent)) : A +Base.dataids(A::Union{Adjoint,Transpose}) = dataids(A.parent) + # wrapping lowercase quasi-constructors """ adjoint(A) diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 0d5f3362c4ee5..9dd5b068a5dcd 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -447,4 +447,17 @@ end @test adjoint!(b, a) === b end +@testset "aliasing with adjoint and transpose" begin + A = collect(reshape(1:25, 5, 5)) .+ rand.().*im + B = copy(A) + B .= B' + @test B == A' + B = copy(A) + B .= transpose(B) + @test B == transpose(A) + B = copy(A) + B .= B .* B' + @test B == A .* A' +end + end # module TestAdjointTranspose