diff --git a/src/adjtrans.jl b/src/adjtrans.jl index c4de7dae..51f17be8 100644 --- a/src/adjtrans.jl +++ b/src/adjtrans.jl @@ -513,6 +513,10 @@ function _dot_nonrecursive(u, v) end end +# we use (n A^T) = (A n)^T, which holds if the product of n and the elements of A is commutative +rmul!(X::AdjOrTrans{<:Union{Real,Complex}}, s::Union{Real,Complex}) = (lmul!(wrapperop(X)(s), parent(X)); X) +lmul!(s::Union{Real,Complex}, X::AdjOrTrans{<:Union{Real,Complex}}) = (rmul!(parent(X), wrapperop(X)(s)); X) + # Adjoint/Transpose-vector * vector *(u::AdjointAbsVec{<:Number}, v::AbstractVector{<:Number}) = dot(u.parent, v) *(u::TransposeAbsVec{T}, v::AbstractVector{T}) where {T<:Real} = dot(u.parent, v) diff --git a/test/adjtrans.jl b/test/adjtrans.jl index 43868162..85a17b3d 100644 --- a/test/adjtrans.jl +++ b/test/adjtrans.jl @@ -12,6 +12,7 @@ isdefined(Main, :LinearAlgebraTestHelpers) || Base.include(Main, TESTHELPERS) using Main.LinearAlgebraTestHelpers.OffsetArrays using Main.LinearAlgebraTestHelpers.ImmutableArrays +using Main.LinearAlgebraTestHelpers.Quaternions @testset "Adjoint and Transpose inner constructor basics" begin intvec, intmat = [1, 2], [1 2; 3 4] @@ -809,4 +810,31 @@ end end end +@testset "lmul!/rmul! by numbers" begin + @testset "$(eltype(A))" for A in (rand(4, 4), rand(ComplexF64,4,4), + fill([1 2; 3 4], 4, 4), + fill(Quaternion(1,2,3,4), 4, 4)) + B = copy(A) + @testset for op in (transpose, adjoint) + A .= B + @test lmul!(2, op(A)) == 2 * op(B) + A .= B + @test rmul!(op(A), 2) == op(B) * 2 + if eltype(A) <: Complex + A .= B + @test lmul!(-2im, op(A)) == -2im * op(B) + A .= B + @test rmul!(op(A), -2im) == op(B) * -2im + end + if eltype(A) <: Quaternion + A .= B + q = Quaternion(0,1,4,7) + @test lmul!(q, op(A)) == q * op(B) + A .= B + @test rmul!(op(A), q) == op(B) * q + end + end + end +end + end # module TestAdjointTranspose