From e0af2ab86ba1b45fc647fd8b4e5c4fd03cbee6fb Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 26 Nov 2017 17:25:45 +0800 Subject: [PATCH 01/77] osutils: make static macro support `elseif` --- base/osutils.jl | 16 ++++++++++++---- test/osutils.jl | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/base/osutils.jl b/base/osutils.jl index 96b6434d7e0ab3..9d67675d3c2d86 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -13,13 +13,21 @@ such as a `ccall` to a non-existent function. """ macro static(ex) if isa(ex, Expr) - if ex.head === :if || ex.head === :&& || ex.head === :|| + @label loop + hd = ex.head + if hd ∈ (:if, :elseif, :&&, :||) cond = eval(__module__, ex.args[1]) - if xor(cond, ex.head === :||) + if xor(cond, hd === :||) return esc(ex.args[2]) elseif length(ex.args) == 3 - return esc(ex.args[3]) - elseif ex.head === :if + br = ex.args[3] + if br isa Expr && br.head === :elseif + ex = br + @goto loop + else + return esc(ex.args[3]) + end + elseif hd ∈ (:if, :elseif) return nothing else return cond diff --git a/test/osutils.jl b/test/osutils.jl index 40e42d57bbaff3..ebbd7c9084c3dd 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -29,6 +29,11 @@ end @test (@static false && 1) === false @test (@static true || 1) === true @test (@static false || 1) === 1 + @test (@static if false 1 elseif true 2 end) === 2 + @test (@static if false 1 elseif false 2 end) === nothing + @test (@static if false 1 elseif false 2 else 3 end) === 3 + @test (@static if false 1 elseif false 2 elseif true && false 3 else 4 end) === 4 + @test (@static if false 1 elseif false 2 elseif true && false 3 end) === nothing end if Sys.iswindows() From b0429ff20a40dd87738685d9a95a085344cfaf30 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 10:05:45 -0800 Subject: [PATCH 02/77] Basic definitions and tests for Adjoint and Transpose types. --- base/linalg/adjtrans.jl | 99 ++++++++++++++ base/linalg/linalg.jl | 1 + test/choosetests.jl | 2 +- test/linalg/adjtrans.jl | 288 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 base/linalg/adjtrans.jl create mode 100644 test/linalg/adjtrans.jl diff --git a/base/linalg/adjtrans.jl b/base/linalg/adjtrans.jl new file mode 100644 index 00000000000000..0044780922cf4e --- /dev/null +++ b/base/linalg/adjtrans.jl @@ -0,0 +1,99 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Base: @pure, @propagate_inbounds, _return_type, _default_type, _isleaftype, @_inline_meta +import Base: length, size, indices, IndexStyle, getindex, setindex!, parent, vec, convert, similar + +### basic definitions (types, aliases, constructors, abstractarray interface, sundry similar) + +# note that Adjoint and Transpose must be able to wrap not only vectors and matrices +# but also factorizations, rotations, and other linear algebra objects, including +# user-defined such objects. so do not restrict the wrapped type. +struct Adjoint{T,S} <: AbstractMatrix{T} + parent::S + function Adjoint{T,S}(A::S) where {T,S} + checkeltype(Adjoint, T, eltype(A)) + new(A) + end +end +struct Transpose{T,S} <: AbstractMatrix{T} + parent::S + function Transpose{T,S}(A::S) where {T,S} + checkeltype(Transpose, T, eltype(A)) + new(A) + end +end + +@pure function checkeltype(::Type{Transform}, ::Type{ResultEltype}, ::Type{ParentEltype}) where {Transform, ResultEltype, ParentEltype} + if ResultEltype !== transformtype(Transform, ParentEltype) + error(string("Element type mismatch. Tried to create an `$Transform{$ResultEltype}` ", + "from an object with eltype `$ParentEltype`, but the element type of the ", + "`$Transform` of an object with eltype `$ParentEltype` must be ", + "`$(transformtype(Transform, ParentEltype))`")) + end + return nothing +end +function transformtype(::Type{O}, ::Type{S}) where {O,S} + # similar to promote_op(::Any, ::Type) + @_inline_meta + T = _return_type(O, Tuple{_default_type(S)}) + _isleaftype(S) && return _isleaftype(T) ? T : Any + return typejoin(S, T) +end + +# basic outer constructors +Adjoint(A) = Adjoint{transformtype(Adjoint,eltype(A)),typeof(A)}(A) +Transpose(A) = Transpose{transformtype(Transpose,eltype(A)),typeof(A)}(A) + +# numbers are the end of the line +Adjoint(x::Number) = adjoint(x) +Transpose(x::Number) = transpose(x) + +# unwrapping constructors +# perhaps slightly odd, but necessary (at least till adjoint and transpose names are free) +Adjoint(A::Adjoint) = A.parent +Transpose(A::Transpose) = A.parent + +# some aliases for internal convenience use +const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S} +const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector} +const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractMatrix} + +# for internal use below +wrappertype(A::Adjoint) = Adjoint +wrappertype(A::Transpose) = Transpose +wrappertype(::Type{<:Adjoint}) = Adjoint +wrappertype(::Type{<:Transpose}) = Transpose + +# AbstractArray interface, basic definitions +length(A::AdjOrTrans) = length(A.parent) +size(v::AdjOrTransAbsVec) = (1, length(v.parent)) +size(A::AdjOrTransAbsMat) = reverse(size(A.parent)) +indices(v::AdjOrTransAbsVec) = (Base.OneTo(1), indices(v.parent)...) +indices(A::AdjOrTransAbsMat) = reverse(indices(A.parent)) +IndexStyle(::Type{<:AdjOrTransAbsVec}) = IndexLinear() +IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian() +@propagate_inbounds getindex(v::AdjOrTransAbsVec, i::Int) = wrappertype(v)(v.parent[i]) +@propagate_inbounds getindex(A::AdjOrTransAbsMat, i::Int, j::Int) = wrappertype(A)(A.parent[j, i]) +@propagate_inbounds setindex!(v::AdjOrTransAbsVec, x, i::Int) = (setindex!(v.parent, wrappertype(v)(x), i); v) +@propagate_inbounds setindex!(A::AdjOrTransAbsMat, x, i::Int, j::Int) = (setindex!(A.parent, wrappertype(A)(x), j, i); A) +# AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate +@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, is::AbstractArray{Int}) = wrappertype(v)(v.parent[is]) +@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrappertype(v)(v.parent[:]) + +# conversion of underlying storage +convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent)) +convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(convert(S, A.parent)) + +# for vectors, the semantics of the wrapped and unwrapped types differ +# so attempt to maintain both the parent and wrapper type insofar as possible +similar(A::AdjOrTransAbsVec) = wrappertype(A)(similar(A.parent)) +similar(A::AdjOrTransAbsVec, ::Type{T}) where {T} = wrappertype(A)(similar(A.parent, transformtype(wrappertype(A), T))) +# for matrices, the semantics of the wrapped and unwrapped types are generally the same +# and as you are allocating with similar anyway, you might as well get something unwrapped +similar(A::AdjOrTrans) = similar(A.parent, eltype(A), size(A)) +similar(A::AdjOrTrans, ::Type{T}) where {T} = similar(A.parent, T, size(A)) +similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, T, dims) + +# sundry basic definitions +parent(A::AdjOrTrans) = A.parent +vec(v::AdjOrTransAbsVec) = v.parent diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index ce75dd49c4fc74..3ecb8834f38fd6 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -240,6 +240,7 @@ end copy_oftype(A::AbstractArray{T}, ::Type{T}) where {T} = copy(A) copy_oftype(A::AbstractArray{T,N}, ::Type{S}) where {T,N,S} = convert(AbstractArray{S,N}, A) +include("adjtrans.jl") include("conjarray.jl") include("transpose.jl") include("rowvector.jl") diff --git a/test/choosetests.jl b/test/choosetests.jl index dd76d15ee24068..0279080578ad54 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -126,7 +126,7 @@ function choosetests(choices = []) "linalg/cholesky", "linalg/lu", "linalg/symmetric", "linalg/generic", "linalg/uniformscaling", "linalg/lq", "linalg/hessenberg", "linalg/rowvector", "linalg/conjarray", - "linalg/blas"] + "linalg/blas", "linalg/adjtrans"] if "linalg" in skip_tests filter!(x -> (x != "linalg" && !(x in linalgtests)), tests) diff --git a/test/linalg/adjtrans.jl b/test/linalg/adjtrans.jl new file mode 100644 index 00000000000000..b21c8ee31e529f --- /dev/null +++ b/test/linalg/adjtrans.jl @@ -0,0 +1,288 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test +using Base.LinAlg: Adjoint, Transpose + +@testset "Adjoint and Transpose inner constructor basics" begin + intvec, intmat = [1, 2], [1 2; 3 4] + # Adjoint/Transpose eltype must match the type of the Adjoint/Transpose of the input eltype + @test_throws ErrorException Adjoint{Float64,Vector{Int}}(intvec) + @test_throws ErrorException Adjoint{Float64,Matrix{Int}}(intmat) + @test_throws ErrorException Transpose{Float64,Vector{Int}}(intvec) + @test_throws ErrorException Transpose{Float64,Matrix{Int}}(intmat) + # Adjoint/Transpose wrapped array type must match the input array type + @test_throws MethodError Adjoint{Int,Vector{Float64}}(intvec) + @test_throws MethodError Adjoint{Int,Matrix{Float64}}(intmat) + @test_throws MethodError Transpose{Int,Vector{Float64}}(intvec) + @test_throws MethodError Transpose{Int,Matrix{Float64}}(intmat) + # Adjoint/Transpose inner constructor basic functionality, concrete scalar eltype + @test (Adjoint{Int,Vector{Int}}(intvec)::Adjoint{Int,Vector{Int}}).parent === intvec + @test (Adjoint{Int,Matrix{Int}}(intmat)::Adjoint{Int,Matrix{Int}}).parent === intmat + @test (Transpose{Int,Vector{Int}}(intvec)::Transpose{Int,Vector{Int}}).parent === intvec + @test (Transpose{Int,Matrix{Int}}(intmat)::Transpose{Int,Matrix{Int}}).parent === intmat + # Adjoint/Transpose inner constructor basic functionality, abstract scalar eltype + anyvec, anymat = Any[1, 2], Any[1 2; 3 4] + @test (Adjoint{Any,Vector{Any}}(anyvec)::Adjoint{Any,Vector{Any}}).parent === anyvec + @test (Adjoint{Any,Matrix{Any}}(anymat)::Adjoint{Any,Matrix{Any}}).parent === anymat + @test (Transpose{Any,Vector{Any}}(anyvec)::Transpose{Any,Vector{Any}}).parent === anyvec + @test (Transpose{Any,Matrix{Any}}(anymat)::Transpose{Any,Matrix{Any}}).parent === anymat + # Adjoint/Transpose inner constructor basic functionality, concrete array eltype + intvecvec = [[1, 2], [3, 4]] + intmatmat = [[[1 2]] [[3 4]] [[5 6]]; [[7 8]] [[9 10]] [[11 12]]] + @test (X = Adjoint{Adjoint{Int,Vector{Int}},Vector{Vector{Int}}}(intvecvec); + isa(X, Adjoint{Adjoint{Int,Vector{Int}},Vector{Vector{Int}}}) && X.parent === intvecvec) + @test (X = Adjoint{Adjoint{Int,Matrix{Int}},Matrix{Matrix{Int}}}(intmatmat); + isa(X, Adjoint{Adjoint{Int,Matrix{Int}},Matrix{Matrix{Int}}}) && X.parent === intmatmat) + @test (X = Transpose{Transpose{Int,Vector{Int}},Vector{Vector{Int}}}(intvecvec); + isa(X, Transpose{Transpose{Int,Vector{Int}},Vector{Vector{Int}}}) && X.parent === intvecvec) + @test (X = Transpose{Transpose{Int,Matrix{Int}},Matrix{Matrix{Int}}}(intmatmat); + isa(X, Transpose{Transpose{Int,Matrix{Int}},Matrix{Matrix{Int}}}) && X.parent === intmatmat) +end + +@testset "Adjoint and Transpose outer constructor basics" begin + intvec, intmat = [1, 2], [1 2; 3 4] + # the wrapped array's eltype strictly determines the Adjoint/Transpose eltype + # so Adjoint{T}/Transpose{T} constructors are somewhat unnecessary and error-prone + # so ascertain that such calls throw whether or not T and the input eltype are compatible + @test_throws MethodError Adjoint{Int}(intvec) + @test_throws MethodError Adjoint{Int}(intmat) + @test_throws MethodError Adjoint{Float64}(intvec) + @test_throws MethodError Adjoint{Float64}(intmat) + @test_throws MethodError Transpose{Int}(intvec) + @test_throws MethodError Transpose{Int}(intmat) + @test_throws MethodError Transpose{Float64}(intvec) + @test_throws MethodError Transpose{Float64}(intmat) + # Adjoint/Transpose outer constructor basic functionality, concrete scalar eltype + @test (Adjoint(intvec)::Adjoint{Int,Vector{Int}}).parent === intvec + @test (Adjoint(intmat)::Adjoint{Int,Matrix{Int}}).parent === intmat + @test (Transpose(intvec)::Transpose{Int,Vector{Int}}).parent === intvec + @test (Transpose(intmat)::Transpose{Int,Matrix{Int}}).parent === intmat + # the tests for the inner constructors exercise abstract scalar and concrete array eltype, forgoing here +end + +@testset "Adjoint and Transpose of Numbers" begin + @test Adjoint(1) == 1 + @test Adjoint(1.0) == 1.0 + @test Adjoint(1im) == -1im + @test Adjoint(1.0im) == -1.0im + @test Transpose(1) == 1 + @test Transpose(1.0) == 1.0 + @test Transpose(1im) == 1im + @test Transpose(1.0im) == 1.0im +end + +@testset "Adjoint and Transpose unwrapping" begin + intvec, intmat = [1, 2], [1 2; 3 4] + @test Adjoint(Adjoint(intvec)) === intvec + @test Adjoint(Adjoint(intmat)) === intmat + @test Transpose(Transpose(intvec)) === intvec + @test Transpose(Transpose(intmat)) === intmat +end + +@testset "Adjoint and Transpose basic AbstractArray functionality" begin + # vectors and matrices with real scalar eltype, and their adjoints/transposes + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + tintvec, tintmat = [1 2], [1 4; 2 5; 3 6] + @testset "length methods" begin + @test length(Adjoint(intvec)) == length(intvec) + @test length(Adjoint(intmat)) == length(intmat) + @test length(Transpose(intvec)) == length(intvec) + @test length(Transpose(intmat)) == length(intmat) + end + @testset "size methods" begin + @test size(Adjoint(intvec)) == (1, length(intvec)) + @test size(Adjoint(intmat)) == reverse(size(intmat)) + @test size(Transpose(intvec)) == (1, length(intvec)) + @test size(Transpose(intmat)) == reverse(size(intmat)) + end + @testset "indices methods" begin + @test indices(Adjoint(intvec)) == (Base.OneTo(1), Base.OneTo(length(intvec))) + @test indices(Adjoint(intmat)) == reverse(indices(intmat)) + @test indices(Transpose(intvec)) == (Base.OneTo(1), Base.OneTo(length(intvec))) + @test indices(Transpose(intmat)) == reverse(indices(intmat)) + end + @testset "IndexStyle methods" begin + @test IndexStyle(Adjoint(intvec)) == IndexLinear() + @test IndexStyle(Adjoint(intmat)) == IndexCartesian() + @test IndexStyle(Transpose(intvec)) == IndexLinear() + @test IndexStyle(Transpose(intmat)) == IndexCartesian() + end + # vectors and matrices with complex scalar eltype, and their adjoints/transposes + complexintvec, complexintmat = [1im, 2im], [1im 2im 3im; 4im 5im 6im] + tcomplexintvec, tcomplexintmat = [1im 2im], [1im 4im; 2im 5im; 3im 6im] + acomplexintvec, acomplexintmat = conj.(tcomplexintvec), conj.(tcomplexintmat) + # vectors and matrices with real-vector and real-matrix eltype, and their adjoints/transposes + intvecvec = [[1, 2], [3, 4]] + tintvecvec = [[[1 2]] [[3 4]]] + intmatmat = [[[1 2]] [[3 4]] [[ 5 6]]; + [[7 8]] [[9 10]] [[11 12]]] + tintmatmat = [[hcat([1, 2])] [hcat([7, 8])]; + [hcat([3, 4])] [hcat([9, 10])]; + [hcat([5, 6])] [hcat([11, 12])]] + # vectors and matrices with complex-vector and complex-matrix eltype, and their adjoints/transposes + complexintvecvec, complexintmatmat = im .* (intvecvec, intmatmat) + tcomplexintvecvec, tcomplexintmatmat = im .* (tintvecvec, tintmatmat) + acomplexintvecvec, acomplexintmatmat = conj.(tcomplexintvecvec), conj.(tcomplexintmatmat) + @testset "getindex methods, elementary" begin + # implicitly test elementary definitions, for arrays with concrete real scalar eltype + @test Adjoint(intvec) == tintvec + @test Adjoint(intmat) == tintmat + @test Transpose(intvec) == tintvec + @test Transpose(intmat) == tintmat + # implicitly test elementary definitions, for arrays with concrete complex scalar eltype + @test Adjoint(complexintvec) == acomplexintvec + @test Adjoint(complexintmat) == acomplexintmat + @test Transpose(complexintvec) == tcomplexintvec + @test Transpose(complexintmat) == tcomplexintmat + # implicitly test elementary definitions, for arrays with concrete real-array eltype + @test Adjoint(intvecvec) == tintvecvec + @test Adjoint(intmatmat) == tintmatmat + @test Transpose(intvecvec) == tintvecvec + @test Transpose(intmatmat) == tintmatmat + # implicitly test elementary definitions, for arrays with concrete complex-array type + @test Adjoint(complexintvecvec) == acomplexintvecvec + @test Adjoint(complexintmatmat) == acomplexintmatmat + @test Transpose(complexintvecvec) == tcomplexintvecvec + @test Transpose(complexintmatmat) == tcomplexintmatmat + end + @testset "getindex(::AdjOrTransVec, ::Colon, ::AbstractArray{Int}) methods that preserve wrapper type" begin + # for arrays with concrete scalar eltype + @test Adjoint(intvec)[:, [1, 2]] == Adjoint(intvec) + @test Transpose(intvec)[:, [1, 2]] == Transpose(intvec) + @test Adjoint(complexintvec)[:, [1, 2]] == Adjoint(complexintvec) + @test Transpose(complexintvec)[:, [1, 2]] == Transpose(complexintvec) + # for arrays with concrete array eltype + @test Adjoint(intvecvec)[:, [1, 2]] == Adjoint(intvecvec) + @test Transpose(intvecvec)[:, [1, 2]] == Transpose(intvecvec) + @test Adjoint(complexintvecvec)[:, [1, 2]] == Adjoint(complexintvecvec) + @test Transpose(complexintvecvec)[:, [1, 2]] == Transpose(complexintvecvec) + end + @testset "getindex(::AdjOrTransVec, ::Colon, ::Colon) methods that preserve wrapper type" begin + # for arrays with concrete scalar eltype + @test Adjoint(intvec)[:, :] == Adjoint(intvec) + @test Transpose(intvec)[:, :] == Transpose(intvec) + @test Adjoint(complexintvec)[:, :] == Adjoint(complexintvec) + @test Transpose(complexintvec)[:, :] == Transpose(complexintvec) + # for arrays with concrete array elype + @test Adjoint(intvecvec)[:, :] == Adjoint(intvecvec) + @test Transpose(intvecvec)[:, :] == Transpose(intvecvec) + @test Adjoint(complexintvecvec)[:, :] == Adjoint(complexintvecvec) + @test Transpose(complexintvecvec)[:, :] == Transpose(complexintvecvec) + end + @testset "getindex(::AdjOrTransVec, ::Colon, ::Int) should preserve wrapper type on result entries" begin + # for arrays with concrete scalar eltype + @test Adjoint(intvec)[:, 2] == intvec[2:2] + @test Transpose(intvec)[:, 2] == intvec[2:2] + @test Adjoint(complexintvec)[:, 2] == conj.(complexintvec[2:2]) + @test Transpose(complexintvec)[:, 2] == complexintvec[2:2] + # for arrays with concrete array eltype + @test Adjoint(intvecvec)[:, 2] == Adjoint.(intvecvec[2:2]) + @test Transpose(intvecvec)[:, 2] == Transpose.(intvecvec[2:2]) + @test Adjoint(complexintvecvec)[:, 2] == Adjoint.(complexintvecvec[2:2]) + @test Transpose(complexintvecvec)[:, 2] == Transpose.(complexintvecvec[2:2]) + end + @testset "setindex! methods" begin + # for vectors with real scalar eltype + @test (wv = Adjoint(copy(intvec)); + wv === setindex!(wv, 3, 2) && + wv == setindex!(copy(tintvec), 3, 1, 2) ) + @test (wv = Transpose(copy(intvec)); + wv === setindex!(wv, 4, 2) && + wv == setindex!(copy(tintvec), 4, 1, 2) ) + # for matrices with real scalar eltype + @test (wA = Adjoint(copy(intmat)); + wA === setindex!(wA, 7, 3, 1) && + wA == setindex!(copy(tintmat), 7, 3, 1) ) + @test (wA = Transpose(copy(intmat)); + wA === setindex!(wA, 7, 3, 1) && + wA == setindex!(copy(tintmat), 7, 3, 1) ) + # for vectors with complex scalar eltype + @test (wz = Adjoint(copy(complexintvec)); + wz === setindex!(wz, 3im, 2) && + wz == setindex!(copy(acomplexintvec), 3im, 1, 2) ) + @test (wz = Transpose(copy(complexintvec)); + wz === setindex!(wz, 4im, 2) && + wz == setindex!(copy(tcomplexintvec), 4im, 1, 2) ) + # for matrices with complex scalar eltype + @test (wZ = Adjoint(copy(complexintmat)); + wZ === setindex!(wZ, 7im, 3, 1) && + wZ == setindex!(copy(acomplexintmat), 7im, 3, 1) ) + @test (wZ = Transpose(copy(complexintmat)); + wZ === setindex!(wZ, 7im, 3, 1) && + wZ == setindex!(copy(tcomplexintmat), 7im, 3, 1) ) + # for vectors with concrete real-vector eltype + @test (wv = Adjoint(copy(intvecvec)); + wv === setindex!(wv, Adjoint([5, 6]), 2) && + wv == setindex!(copy(tintvecvec), [5 6], 2)) + @test (wv = Transpose(copy(intvecvec)); + wv === setindex!(wv, Transpose([5, 6]), 2) && + wv == setindex!(copy(tintvecvec), [5 6], 2)) + # for matrices with concrete real-matrix eltype + @test (wA = Adjoint(copy(intmatmat)); + wA === setindex!(wA, Adjoint([13 14]), 3, 1) && + wA == setindex!(copy(tintmatmat), hcat([13, 14]), 3, 1)) + @test (wA = Transpose(copy(intmatmat)); + wA === setindex!(wA, Transpose([13 14]), 3, 1) && + wA == setindex!(copy(tintmatmat), hcat([13, 14]), 3, 1)) + # for vectors with concrete complex-vector eltype + @test (wz = Adjoint(copy(complexintvecvec)); + wz === setindex!(wz, Adjoint([5im, 6im]), 2) && + wz == setindex!(copy(acomplexintvecvec), [-5im -6im], 2)) + @test (wz = Transpose(copy(complexintvecvec)); + wz === setindex!(wz, Transpose([5im, 6im]), 2) && + wz == setindex!(copy(tcomplexintvecvec), [5im 6im], 2)) + # for matrices with concrete complex-matrix eltype + @test (wZ = Adjoint(copy(complexintmatmat)); + wZ === setindex!(wZ, Adjoint([13im 14im]), 3, 1) && + wZ == setindex!(copy(acomplexintmatmat), hcat([-13im, -14im]), 3, 1)) + @test (wZ = Transpose(copy(complexintmatmat)); + wZ === setindex!(wZ, Transpose([13im 14im]), 3, 1) && + wZ == setindex!(copy(tcomplexintmatmat), hcat([13im, 14im]), 3, 1)) + end +end + +@testset "Adjoint and Transpose convert methods that convert underlying storage" begin + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + @test convert(Adjoint{Float64,Vector{Float64}}, Adjoint(intvec))::Adjoint{Float64,Vector{Float64}} == Adjoint(intvec) + @test convert(Adjoint{Float64,Matrix{Float64}}, Adjoint(intmat))::Adjoint{Float64,Matrix{Float64}} == Adjoint(intmat) + @test convert(Transpose{Float64,Vector{Float64}}, Transpose(intvec))::Transpose{Float64,Vector{Float64}} == Transpose(intvec) + @test convert(Transpose{Float64,Matrix{Float64}}, Transpose(intmat))::Transpose{Float64,Matrix{Float64}} == Transpose(intmat) +end + +@testset "Adjoint and Transpose similar methods" begin + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + # similar with no additional specifications, vector (rewrapping) semantics + @test size(similar(Adjoint(intvec))::Adjoint{Int,Vector{Int}}) == size(Adjoint(intvec)) + @test size(similar(Transpose(intvec))::Transpose{Int,Vector{Int}}) == size(Transpose(intvec)) + # similar with no additional specifications, matrix (no-rewrapping) semantics + @test size(similar(Adjoint(intmat))::Matrix{Int}) == size(Adjoint(intmat)) + @test size(similar(Transpose(intmat))::Matrix{Int}) == size(Transpose(intmat)) + # similar with element type specification, vector (rewrapping) semantics + @test size(similar(Adjoint(intvec), Float64)::Adjoint{Float64,Vector{Float64}}) == size(Adjoint(intvec)) + @test size(similar(Transpose(intvec), Float64)::Transpose{Float64,Vector{Float64}}) == size(Transpose(intvec)) + # similar with element type specification, matrix (no-rewrapping) semantics + @test size(similar(Adjoint(intmat), Float64)::Matrix{Float64}) == size(Adjoint(intmat)) + @test size(similar(Transpose(intmat), Float64)::Matrix{Float64}) == size(Transpose(intmat)) + # similar with element type and arbitrary dims specifications + shape = (2, 2, 2) + @test size(similar(Adjoint(intvec), Float64, shape)::Array{Float64,3}) == shape + @test size(similar(Adjoint(intmat), Float64, shape)::Array{Float64,3}) == shape + @test size(similar(Transpose(intvec), Float64, shape)::Array{Float64,3}) == shape + @test size(similar(Transpose(intmat), Float64, shape)::Array{Float64,3}) == shape +end + +@testset "Adjoint and Transpose parent methods" begin + intvec, intmat = [1, 2], [1 2 3; 4 5 6] + @test parent(Adjoint(intvec)) === intvec + @test parent(Adjoint(intmat)) === intmat + @test parent(Transpose(intvec)) === intvec + @test parent(Transpose(intmat)) === intmat +end + +@testset "Adjoint and Transpose vector vec methods" begin + intvec = [1, 2] + @test vec(Adjoint(intvec)) === intvec + @test vec(Transpose(intvec)) === intvec +end From 06bf4318a030c036f72606141714e90d8d6cfa27 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 11:28:55 -0800 Subject: [PATCH 03/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/bidiag with de-jazzed passthroughs. --- base/deprecated.jl | 30 +++++++++++ base/linalg/bidiag.jl | 119 +++++++++++++++++++++++++----------------- 2 files changed, 101 insertions(+), 48 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 44e83e07e72c78..47d9f4e9bbbdf4 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2159,6 +2159,36 @@ finalizer(f::Ptr{Void}, o::Function) = invoke(finalizer, Tuple{Ptr{Void}, Any}, Base.@deprecate_binding broadcast_t broadcast false ", broadcast_t(f, ::Type{ElType}, shape, iter, As...)` should become `broadcast(f, Broadcast.DefaultArrayStyle{N}(), ElType, shape, As...))` (see the manual chapter Interfaces)" end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/bidiag.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(C::AbstractMatrix, A::SymTridiagonal, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::BiTri, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::AbstractTriangular, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::Diagonal, B::BiTriSym) = mul!(C, A, B) + A_mul_B!(C::AbstractVector, A::BiTri, B::AbstractVector) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::BiTri, B::AbstractVecOrMat) = mul!(C, A, B) + A_mul_B!(C::AbstractVecOrMat, A::BiTri, B::AbstractVecOrMat) = mul!(C, A, B) + Ac_ldiv_B(A::Bidiagonal, v::RowVector) = \(Adjoint(A), v) + At_ldiv_B(A::Bidiagonal, v::RowVector) = \(Transpose(A), v) + Ac_ldiv_B(A::Bidiagonal{<:Number}, v::RowVector{<:Number}) = \(Adjoint(A), v) + At_ldiv_B(A::Bidiagonal{<:Number}, v::RowVector{<:Number}) = \(Transpose(A), v) + Ac_mul_B(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Adjoint(A), B) + A_mul_Bc(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(A, Adjoint(B)) + A_rdiv_Bc(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = /(A, Adjoint(B)) + A_ldiv_B!(A::Union{Bidiagonal, AbstractTriangular}, b::AbstractVector) = ldiv!(A, b) + At_ldiv_B!(A::Bidiagonal, b::AbstractVector) = ldiv!(Transpose(A), b) + Ac_ldiv_B!(A::Bidiagonal, b::AbstractVector) = ldiv!(Adjoint(A), b) + A_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) = ldiv!(A, B) + Ac_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) = ldiv!(Adjoint(A), B) + At_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) = ldiv!(Transpose(A), B) + At_ldiv_B(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} = \(Transpose(A), B) + At_ldiv_B(A::Bidiagonal, B::AbstractVecOrMat) = \(Transpose(A), B) + Ac_ldiv_B(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} = \(Adjoint(A), B) + Ac_ldiv_B(A::Bidiagonal, B::AbstractVecOrMat) = ldiv!(Adjoint(A), B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 305d914cc057e0..02f1baab392416 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -325,25 +325,24 @@ end const BiTriSym = Union{Bidiagonal,Tridiagonal,SymTridiagonal} const BiTri = Union{Bidiagonal,Tridiagonal} -A_mul_B!(C::AbstractMatrix, A::SymTridiagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::BiTri, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::AbstractTriangular, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::Diagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractVector, A::BiTri, B::AbstractVector) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractMatrix, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) -A_mul_B!(C::AbstractVecOrMat, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) - -\(::Diagonal, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -\(::Bidiagonal, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -\(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - -At_ldiv_B(::Bidiagonal, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -At_ldiv_B(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - -Ac_ldiv_B(::Bidiagonal, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -Ac_ldiv_B(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +mul!(C::AbstractMatrix, A::SymTridiagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::BiTri, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::AbstractTriangular, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Diagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractVector, A::BiTri, B::AbstractVector) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) +mul!(C::AbstractVecOrMat, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) + +\(::Diagonal, ::RowVector) = _mat_ldiv_rowvec_error() +\(::Bidiagonal, ::RowVector) = _mat_ldiv_rowvec_error() +\(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() +\(::Adjoint{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() +\(::Transpose{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() +\(::Adjoint{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() +\(::Transpose{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() +_mat_ldiv_rowvec_error() = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) function check_A_mul_B!_sizes(C, A, B) nA, mA = size(A) @@ -489,15 +488,17 @@ const SpecialMatrix = Union{Bidiagonal,SymTridiagonal,Tridiagonal} *(A::SpecialMatrix, B::SpecialMatrix) = Array(A) * Array(B) #Generic multiplication -for func in (:*, :Ac_mul_B, :A_mul_Bc, :/, :A_rdiv_Bc) - @eval ($func)(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = ($func)(Array(A), B) -end +*(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Array(A), B) +*(adjA::Adjoint{<:Any,<:Bidiagonal{T}}, B::AbstractVector{T}) where {T} = Ac_mul_B(Array(adjA.parent), B) +*(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = A_mul_Bc(Array(A), adjB.parent) +/(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = /(Array(A), B) +/(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = A_rdiv_Bc(Array(A), adjB.parent) #Linear solvers -A_ldiv_B!(A::Union{Bidiagonal, AbstractTriangular}, b::AbstractVector) = naivesub!(A, b) -At_ldiv_B!(A::Bidiagonal, b::AbstractVector) = A_ldiv_B!(transpose(A), b) -Ac_ldiv_B!(A::Bidiagonal, b::AbstractVector) = A_ldiv_B!(adjoint(A), b) -function A_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) +ldiv!(A::Union{Bidiagonal, AbstractTriangular}, b::AbstractVector) = naivesub!(A, b) +ldiv!(transA::Transpose{<:Any,<:Bidiagonal}, b::AbstractVector) = A_ldiv_B!(transpose(transA.parent), b) +ldiv!(adjA::Adjoint{<:Any,<:Bidiagonal}, b::AbstractVector) = A_ldiv_B!(adjoint(adjA.parent), b) +function ldiv!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) nA,mA = size(A) tmp = similar(B,size(B,1)) n = size(B, 1) @@ -511,21 +512,35 @@ function A_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) end B end -for func in (:Ac_ldiv_B!, :At_ldiv_B!) - @eval function ($func)(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) - nA,mA = size(A) - tmp = similar(B,size(B,1)) - n = size(B, 1) - if mA != n - throw(DimensionMismatch("size of A' is ($mA,$nA), corresponding dimension of B is $n")) - end - for i = 1:size(B,2) - copy!(tmp, 1, B, (i - 1)*n + 1, n) - ($func)(A, tmp) - copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. - end - B +function ldiv!(adjA::Adjoint{<:Any,<:Union{Bidiagonal,AbstractTriangular}}, B::AbstractMatrix) + A = adjA.parent + nA,mA = size(A) + tmp = similar(B,size(B,1)) + n = size(B, 1) + if mA != n + throw(DimensionMismatch("size of A' is ($mA,$nA), corresponding dimension of B is $n")) end + for i = 1:size(B,2) + copy!(tmp, 1, B, (i - 1)*n + 1, n) + Ac_ldiv_B!(A, tmp) + copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. + end + B +end +function ldiv!(transA::Transpose{<:Any,<:Union{Bidiagonal,AbstractTriangular}}, B::AbstractMatrix) + A = transA.parent + nA,mA = size(A) + tmp = similar(B,size(B,1)) + n = size(B, 1) + if mA != n + throw(DimensionMismatch("size of A' is ($mA,$nA), corresponding dimension of B is $n")) + end + for i = 1:size(B,2) + copy!(tmp, 1, B, (i - 1)*n + 1, n) + At_ldiv_B!(A, tmp) + copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. + end + B end #Generic solver using naive substitution function naivesub!(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) where T @@ -550,15 +565,23 @@ function naivesub!(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) w end ### Generic promotion methods and fallbacks -for (f,g) in ((:\, :A_ldiv_B!), (:At_ldiv_B, :At_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!)) - @eval begin - function ($f)(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} - TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) - ($g)(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) - end - ($f)(A::Bidiagonal, B::AbstractVecOrMat) = ($g)(A, copy(B)) - end +function \(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} + TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) + A_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) +end +\(A::Bidiagonal, B::AbstractVecOrMat) = A_ldiv_B!(A, copy(B)) +function \(transA::Transpose{<:Any,<:Bidiagonal{TA}}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} + A = transA.parent + TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) + At_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) +end +\(transA::Transpose{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = At_ldiv_B!(transA.parent, copy(B)) +function \(adjA::Adjoint{<:Any,<:Bidiagonal{TA}}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} + A = adjA.parent + TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) + Ac_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end +\(adjA::Adjoint{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = Ac_ldiv_B!(adjA.parent, copy(B)) factorize(A::Bidiagonal) = A From 220876241735e82397cd0e2886a8754f51e70f76 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 11:37:14 -0800 Subject: [PATCH 04/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/tridiag.jl with de-jazzed passthroughs. --- base/deprecated.jl | 5 +++++ base/linalg/tridiag.jl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 47d9f4e9bbbdf4..e5e342687cdbb1 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2189,6 +2189,11 @@ end Ac_ldiv_B(A::Bidiagonal, B::AbstractVecOrMat) = ldiv!(Adjoint(A), B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/tridiag.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) = mul!(C, S, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index dbd6a56b4f6876..fb1a77f5d5daa0 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -153,7 +153,7 @@ end /(A::SymTridiagonal, B::Number) = SymTridiagonal(A.dv/B, A.ev/B) ==(A::SymTridiagonal, B::SymTridiagonal) = (A.dv==B.dv) && (A.ev==B.ev) -function A_mul_B!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) +function mul!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if !(m == size(S, 1) == size(C, 1)) throw(DimensionMismatch("A has first dimension $(size(S,1)), B has $(size(B,1)), C has $(size(C,1)) but all must match")) From 39cc5ccbe07b1ae088c71a26c36c29a6a8d305fc Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 13:53:24 -0800 Subject: [PATCH 05/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/diagonal.jl with de-jazzed passthroughs. --- base/deprecated.jl | 55 ++++++++++++++++++ base/linalg/diagonal.jl | 125 ++++++++++++++++++++++------------------ 2 files changed, 125 insertions(+), 55 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index e5e342687cdbb1..4996f0f484360f 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2194,6 +2194,61 @@ end A_mul_B!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) = mul!(C, S, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/diagonal.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal) = mul!(A, D) + A_mul_B!(A::UnitLowerTriangular, D::Diagonal) = mul!(A, D) + A_mul_B!(A::UnitUpperTriangular, D::Diagonal) = mul!(A, D) + A_mul_B!(D::Diagonal, B::UnitLowerTriangular) = mul!(D, B) + A_mul_B!(D::Diagonal, B::UnitUpperTriangular) = mul!(D, B) + Ac_mul_B(D::Diagonal, B::Diagonal) = *(Adjoint(D), B) + Ac_mul_B(A::AbstractTriangular, D::Diagonal) = *(Adjoint(A), D) + Ac_mul_B(A::AbstractMatrix, D::Diagonal) = *(Adjoint(A), D) + At_mul_B(D::Diagonal, B::Diagonal) = *(Transpose(D), B) + At_mul_B(A::AbstractTriangular, D::Diagonal) = *(Transpose(A), D) + At_mul_B(A::AbstractMatrix, D::Diagonal) = *(Transpose(A), D) + A_mul_Bc(D::Diagonal, B::Diagonal) = *(D, Adjoint(B)) + A_mul_Bc(D::Diagonal, B::AbstractTriangular) = *(D, Adjoint(B)) + A_mul_Bc(D::Diagonal, Q::Union{QRCompactWYQ,QRPackedQ}) = *(D, Adjoint(Q)) + A_mul_Bc(D::Diagonal, A::AbstractMatrix) = *(D, Adjoint(A)) + A_mul_Bt(D::Diagonal, B::Diagonal) = *(D, Transpose(B)) + A_mul_Bt(D::Diagonal, B::AbstractTriangular) = *(D, Transpose(B)) + A_mul_Bt(D::Diagonal, A::AbstractMatrix) = *(D, Transpose(A)) + Ac_mul_Bc(D::Diagonal, B::Diagonal) = *(Adjoint(D), Adjoint(B)) + At_mul_Bt(D::Diagonal, B::Diagonal) = *(Transpose(D), Transpose(B)) + A_mul_B!(A::Diagonal,B::Diagonal) = mul!(A, B) + At_mul_B!(A::Diagonal,B::Diagonal) = mul!(Transpose(A), B) + Ac_mul_B!(A::Diagonal,B::Diagonal) = mul!(Adjoint(A), B) + A_mul_B!(A::QRPackedQ, D::Diagonal) = mul!(A, D) + A_mul_B!(A::Diagonal,B::AbstractMatrix) = mul!(A, B) + At_mul_B!(A::Diagonal,B::AbstractMatrix) = mul!(Transpose(A), B) + Ac_mul_B!(A::Diagonal,B::AbstractMatrix) = mul!(Adjoint(A), B) + A_mul_B!(A::AbstractMatrix,B::Diagonal) = mul!(A, B) + A_mul_Bt!(A::AbstractMatrix,B::Diagonal) = mul!(A, Transpose(B)) + A_mul_Bc!(A::AbstractMatrix,B::Diagonal) = mul!(A, Adjoint(B)) + A_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = mul!(out, A, in) + Ac_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = mul!(out, Adjoint(A), in) + At_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = mul!(out, Transpose(A), in) + A_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = mul!(out, A, in) + Ac_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = mul!(out, Adjoint(A), in) + At_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = mul!(out, Transpose(A), in) + A_mul_Bt(A::Diagonal, B::RealHermSymComplexSym) = *(A, Transpose(B)) + At_mul_B(A::RealHermSymComplexSym, B::Diagonal) = *(Transpose(A), B) + A_mul_Bc(A::Diagonal, B::RealHermSymComplexHerm) = *(A, Adjoint(B)) + Ac_mul_B(A::RealHermSymComplexHerm, B::Diagonal) = *(Adjoint(A), B) + A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where {T} = ldiv!(D, v) + A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} = ldiv!(D, V) + Ac_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = ldiv!(Adjoint(D), B) + At_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = ldiv!(Transpose(D), B) + A_rdiv_B!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = rdiv!(A, D) + A_rdiv_Bc!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = rdiv!(A, Adjoint(D)) + A_rdiv_Bt!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = rdiv!(A, Transpose(D)) + Ac_ldiv_B(F::Factorization, D::Diagonal) = \(Adjoint(F), D) + A_mul_Bt(D::Diagonal, rowvec::RowVector) = *(D, Transpose(rowvec)) + A_mul_Bc(D::Diagonal, rowvec::RowVector) = *(D, Adjoint(rowvec)) + A_ldiv_B!(D::Diagonal, B::StridedVecOrMat) = ldiv!(D, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 31032e5b59c616..7571f7cccaf89d 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -158,30 +158,29 @@ end (*)(D::Diagonal, A::AbstractMatrix) = scale!(similar(A, promote_op(*, eltype(A), eltype(D.diag)), size(A)), D.diag, A) -A_mul_B!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal) = - typeof(A)(A_mul_B!(A.data, D)) -function A_mul_B!(A::UnitLowerTriangular, D::Diagonal) +mul!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal) = typeof(A)(A_mul_B!(A.data, D)) +function mul!(A::UnitLowerTriangular, D::Diagonal) A_mul_B!(A.data, D) for i = 1:size(A, 1) A.data[i,i] = D.diag[i] end LowerTriangular(A.data) end -function A_mul_B!(A::UnitUpperTriangular, D::Diagonal) +function mul!(A::UnitUpperTriangular, D::Diagonal) A_mul_B!(A.data, D) for i = 1:size(A, 1) A.data[i,i] = D.diag[i] end UpperTriangular(A.data) end -function A_mul_B!(D::Diagonal, B::UnitLowerTriangular) +function mul!(D::Diagonal, B::UnitLowerTriangular) A_mul_B!(D, B.data) for i = 1:size(B, 1) B.data[i,i] = D.diag[i] end LowerTriangular(B.data) end -function A_mul_B!(D::Diagonal, B::UnitUpperTriangular) +function mul!(D::Diagonal, B::UnitUpperTriangular) A_mul_B!(D, B.data) for i = 1:size(B, 1) B.data[i,i] = D.diag[i] @@ -189,71 +188,83 @@ function A_mul_B!(D::Diagonal, B::UnitUpperTriangular) UpperTriangular(B.data) end -Ac_mul_B(D::Diagonal, B::Diagonal) = Diagonal(adjoint.(D.diag) .* B.diag) -Ac_mul_B(A::AbstractTriangular, D::Diagonal) = A_mul_B!(adjoint(A), D) -function Ac_mul_B(A::AbstractMatrix, D::Diagonal) +*(adjD::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = (D = adjD.parent; Diagonal(adjoint.(D.diag) .* B.diag)) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = adjA.parent; A_mul_B!(adjoint(A), D)) +function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, D::Diagonal) + A = adjA.parent Ac = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) adjoint!(Ac, A) A_mul_B!(Ac, D) end -At_mul_B(D::Diagonal, B::Diagonal) = Diagonal(transpose.(D.diag) .* B.diag) -At_mul_B(A::AbstractTriangular, D::Diagonal) = A_mul_B!(transpose(A), D) -function At_mul_B(A::AbstractMatrix, D::Diagonal) +*(transD::Transpose{<:Any,<:Diagonal}, B::Diagonal) = (D = transD.parent; Diagonal(transpose.(D.diag) .* B.diag)) +*(transA::Transpose{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = transA.parent; A_mul_B!(transpose(A), D)) +function *(transA::Transpose{<:Any,<:AbstractMatrix}, D::Diagonal) + A = transA.parent At = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) transpose!(At, A) A_mul_B!(At, D) end -A_mul_Bc(D::Diagonal, B::Diagonal) = Diagonal(D.diag .* adjoint.(B.diag)) -A_mul_Bc(D::Diagonal, B::AbstractTriangular) = A_mul_B!(D, adjoint(B)) -A_mul_Bc(D::Diagonal, Q::Union{Base.LinAlg.QRCompactWYQ,Base.LinAlg.QRPackedQ}) = A_mul_Bc!(Array(D), Q) -function A_mul_Bc(D::Diagonal, A::AbstractMatrix) +*(D::Diagonal, adjB::Adjoint{<:Any,<:Diagonal}) = (B = adjB.parent; Diagonal(D.diag .* adjoint.(B.diag))) +*(D::Diagonal, adjB::Adjoint{<:Any,<:AbstractTriangular}) = (B = adjB.parent; A_mul_B!(D, adjoint(B))) +*(D::Diagonal, adjQ::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (Q = adjQ.parent; A_mul_Bc!(Array(D), Q)) +function *(D::Diagonal, adjA::Adjoint{<:Any,<:AbstractMatrix}) + A = adjA.parent Ac = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) adjoint!(Ac, A) A_mul_B!(D, Ac) end -A_mul_Bt(D::Diagonal, B::Diagonal) = Diagonal(D.diag .* transpose.(B.diag)) -A_mul_Bt(D::Diagonal, B::AbstractTriangular) = A_mul_B!(D, transpose(B)) -function A_mul_Bt(D::Diagonal, A::AbstractMatrix) +*(D::Diagonal, transB::Transpose{<:Any,<:Diagonal}) = (B = transB.parent; Diagonal(D.diag .* transpose.(B.diag))) +*(D::Diagonal, transB::Transpose{<:Any,<:AbstractTriangular}) = (B = transB.parent; A_mul_B!(D, transpose(B))) +function *(D::Diagonal, transA::Transpose{<:Any,<:AbstractMatrix}) + A = transA.parent At = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) transpose!(At, A) A_mul_B!(D, At) end -Ac_mul_Bc(D::Diagonal, B::Diagonal) = Diagonal(adjoint.(D.diag) .* adjoint.(B.diag)) -At_mul_Bt(D::Diagonal, B::Diagonal) = Diagonal(transpose.(D.diag) .* transpose.(B.diag)) - -A_mul_B!(A::Diagonal,B::Diagonal) = throw(MethodError(A_mul_B!, Tuple{Diagonal,Diagonal})) -At_mul_B!(A::Diagonal,B::Diagonal) = throw(MethodError(At_mul_B!, Tuple{Diagonal,Diagonal})) -Ac_mul_B!(A::Diagonal,B::Diagonal) = throw(MethodError(Ac_mul_B!, Tuple{Diagonal,Diagonal})) -A_mul_B!(A::Base.LinAlg.QRPackedQ, D::Diagonal) = throw(MethodError(A_mul_B!, Tuple{Diagonal,Diagonal})) -A_mul_B!(A::Diagonal,B::AbstractMatrix) = scale!(A.diag,B) -At_mul_B!(A::Diagonal,B::AbstractMatrix) = scale!(A.diag,B) -Ac_mul_B!(A::Diagonal,B::AbstractMatrix) = scale!(conj(A.diag),B) -A_mul_B!(A::AbstractMatrix,B::Diagonal) = scale!(A,B.diag) -A_mul_Bt!(A::AbstractMatrix,B::Diagonal) = scale!(A,B.diag) -A_mul_Bc!(A::AbstractMatrix,B::Diagonal) = scale!(A,conj(B.diag)) +*(adjD::Adjoint{<:Any,<:Diagonal}, adjB::Adjoint{<:Any,<:Diagonal}) = + (D = adjD.parent; B = adjB.parent; Diagonal(adjoint.(D.diag) .* adjoint.(B.diag))) +*(transD::Transpose{<:Any,<:Diagonal}, transB::Transpose{<:Any,<:Diagonal}) = + (D = transD.parent; B = transB.parent; Diagonal(transpose.(D.diag) .* transpose.(B.diag))) + +mul!(A::Diagonal, B::Diagonal) = throw(MethodError(mul!, Tuple{Diagonal,Diagonal})) +mul!(A::QRPackedQ, D::Diagonal) = throw(MethodError(mul!, Tuple{Diagonal,Diagonal})) +mul!(transA::Transpose{<:Any,<:Diagonal}, B::Diagonal) = + throw(MethodError(mul!, Tuple{Transpose{<:Any,<:Diagonal},Diagonal})) +mul!(adjA::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = + throw(MethodError(mul!, Tuple{Adjoint{<:Any,<:Diagonal},Diagonal})) +mul!(A::Diagonal, B::AbstractMatrix) = scale!(A.diag, B) +mul!(adjA::Adjoint{<:Any,<:Diagonal}, B::AbstractMatrix) = (A = adjA.parent; scale!(conj(A.diag),B)) +mul!(transA::Transpose{<:Any,<:Diagonal}, B::AbstractMatrix) = (A = transA.parent; scale!(A.diag,B)) +mul!(A::AbstractMatrix, B::Diagonal) = scale!(A,B.diag) +mul!(A::AbstractMatrix, adjB::Adjoint{<:Any,<:Diagonal}) = (B = adjB.parent; scale!(A,conj(B.diag))) +mul!(A::AbstractMatrix, transB::Transpose{<:Any,<:Diagonal}) = (B = transB.parent; scale!(A,B.diag)) # Get ambiguous method if try to unify AbstractVector/AbstractMatrix here using AbstractVecOrMat -A_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in -Ac_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= adjoint.(A.diag) .* in -At_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= transpose.(A.diag) .* in - -A_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in -Ac_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= adjoint.(A.diag) .* in -At_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= transpose.(A.diag) .* in +mul!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in +mul!(out::AbstractVector, adjA::Adjoint{<:Any,<:Diagonal}, in::AbstractVector) = + (A = adjA.parent; out .= adjoint.(A.diag) .* in) +mul!(out::AbstractVector, transA::Transpose{<:Any,<:Diagonal}, in::AbstractVector) = + (A = transA.parent; out .= transpose.(A.diag) .* in) + +mul!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in +mul!(out::AbstractMatrix, adjA::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = + (A = adjA.parent; out .= adjoint.(A.diag) .* in) +mul!(out::AbstractMatrix, transA::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = + (A = transA.parent; out .= transpose.(A.diag) .* in) # ambiguities with Symmetric/Hermitian # RealHermSymComplex[Sym]/[Herm] only include Number; invariant to [c]transpose -A_mul_Bt(A::Diagonal, B::RealHermSymComplexSym) = A*B -At_mul_B(A::RealHermSymComplexSym, B::Diagonal) = A*B -A_mul_Bc(A::Diagonal, B::RealHermSymComplexHerm) = A*B -Ac_mul_B(A::RealHermSymComplexHerm, B::Diagonal) = A*B +*(A::Diagonal, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::Diagonal) = transA.parent * B +*(A::Diagonal, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Diagonal) = adjA.parent * B (/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) -function A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where {T} +function ldiv!(D::Diagonal{T}, v::AbstractVector{T}) where {T} if length(v) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(length(v)) rows")) end @@ -266,7 +277,7 @@ function A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where {T} end v end -function A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} +function ldiv!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} if size(V,1) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(size(V,1)) rows")) end @@ -282,10 +293,12 @@ function A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} V end -Ac_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = A_ldiv_B!(conj(D), B) -At_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = A_ldiv_B!(D, B) +ldiv!(adjD::Adjoint{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} = + (D = adjD.parent; A_ldiv_B!(conj(D), B)) +ldiv!(transD::Transpose{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} = + (D = transD.parent; A_ldiv_B!(D, B)) -function A_rdiv_B!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} +function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} dd = D.diag m, n = size(A) if (k = length(dd)) ≠ n @@ -303,18 +316,20 @@ function A_rdiv_B!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} A end -A_rdiv_Bc!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, conj(D)) -A_rdiv_Bt!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, D) +rdiv!(A::AbstractMatrix{T}, adjD::Adjoint{<:Any,<:Diagonal{T}}) where {T} = + (D = adjD.parent; A_rdiv_B!(A, conj(D))) +rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = + (D = transD.parent; A_rdiv_B!(A, D)) (\)(F::Factorization, D::Diagonal) = A_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D)) -Ac_ldiv_B(F::Factorization, D::Diagonal) = - Ac_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D)) +\(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) = + (F = adjF.parent; Ac_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))) # Methods to resolve ambiguities with `Diagonal` @inline *(rowvec::RowVector, D::Diagonal) = transpose(D * transpose(rowvec)) -@inline A_mul_Bt(D::Diagonal, rowvec::RowVector) = D*transpose(rowvec) -@inline A_mul_Bc(D::Diagonal, rowvec::RowVector) = D*adjoint(rowvec) +*(D::Diagonal, transrowvec::Transpose{<:Any,<:RowVector}) = (rowvec = transrowvec.parent; D*transpose(rowvec)) +*(D::Diagonal, adjrowvec::Adjoint{<:Any,<:RowVector}) = (rowvec = adjrowvec.parent; D*adjoint(rowvec)) conj(D::Diagonal) = Diagonal(conj(D.diag)) transpose(D::Diagonal{<:Number}) = D @@ -352,7 +367,7 @@ for f in (:exp, :log, :sqrt, end #Linear solver -function A_ldiv_B!(D::Diagonal, B::StridedVecOrMat) +function ldiv!(D::Diagonal, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if m != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $m rows")) From badadbf6e06e6e7ed8007e0547fac4118fb848b4 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 14:28:31 -0800 Subject: [PATCH 06/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/special.jl with de-jazzed passthroughs. --- base/deprecated.jl | 6 ++++++ base/linalg/special.jl | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 4996f0f484360f..1a08e2ab39f2c8 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2249,6 +2249,12 @@ end A_ldiv_B!(D::Diagonal, B::StridedVecOrMat) = ldiv!(D, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/special.jl, to deprecate +@eval Base.LinAlg begin + A_mul_Bc!(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = mul!(A, Adjoint(B)) + A_mul_Bc(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = *(A, Adjoint(B)) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/special.jl b/base/linalg/special.jl index 48a8053653d3db..f9fb09da2cd381 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -122,5 +122,7 @@ for op in (:+, :-) end end -A_mul_Bc!(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = A_mul_Bc!(full!(A), B) -A_mul_Bc(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = A_mul_Bc(copy!(similar(parent(A)), A), B) +mul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = + (B = adjB.parent; A_mul_Bc!(full!(A), B)) +*(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = + (B = adjB.parent; A_mul_Bc(copy!(similar(parent(A)), A), B)) From 03057a96cc6c82a6a2392b3912119b4fe68e2fba Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 14:36:08 -0800 Subject: [PATCH 07/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/bunchkaufman.jl with de-jazzed passthroughs. --- base/deprecated.jl | 7 +++++++ base/linalg/bunchkaufman.jl | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 1a08e2ab39f2c8..120ea1a2f670d0 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2255,6 +2255,13 @@ end A_mul_Bc(A::AbstractTriangular, B::Union{QRCompactWYQ,QRPackedQ}) = *(A, Adjoint(B)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/bunchkaufman.jl, to deprecate +@eval Base.LinAlg begin + A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where {T<:BlasReal} = ldiv!(B, R) + A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where {T<:BlasComplex} = ldiv!(B, R) + A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} = ldiv!(B, R) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index cc1d4f32011d38..d812f603548cf6 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -254,7 +254,7 @@ function inv(B::BunchKaufman{<:BlasComplex}) end end -function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasReal +function ldiv!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasReal if !issuccess(B) throw(SingularException(B.info)) end @@ -265,7 +265,7 @@ function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasReal LAPACK.sytrs!(B.uplo, B.LD, B.ipiv, R) end end -function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasComplex +function ldiv!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasComplex if !issuccess(B) throw(SingularException(B.info)) end @@ -285,7 +285,7 @@ function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasCompl end end # There is no fallback solver for Bunch-Kaufman so we'll have to promote to same element type -function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} +function ldiv!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} TS = promote_type(T,S) return A_ldiv_B!(convert(BunchKaufman{TS}, B), convert(AbstractArray{TS}, R)) end From 89cc4e7549c55853a12fc67b99c975a5da87701d Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 14:42:53 -0800 Subject: [PATCH 08/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/cholesky.jl with de-jazzed passthroughs. --- base/deprecated.jl | 10 ++++++++++ base/linalg/cholesky.jl | 12 ++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 120ea1a2f670d0..77149fcf172d2e 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2262,6 +2262,16 @@ end A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} = ldiv!(B, R) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/cholesky.jl, to deprecate +@eval Base.LinAlg begin + A_ldiv_B!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(C, B) + A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) = ldiv!(C, B) + A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = ldiv!(C, B) + A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = ldiv!(C, B) + A_ldiv_B!(C::CholeskyPivoted, B::StridedVector) = ldiv!(C, B) + A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) = ldiv!(C, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 938a066027c13c..cc122aededd796 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -419,10 +419,10 @@ function show(io::IO, mime::MIME{Symbol("text/plain")}, C::CholeskyPivoted{<:Any show(io, mime, C[:p]) end -A_ldiv_B!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +ldiv!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @assertposdef LAPACK.potrs!(C.uplo, C.factors, B) C.info -function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) +function ldiv!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) if C.uplo == 'L' return Ac_ldiv_B!(LowerTriangular(C.factors), A_ldiv_B!(LowerTriangular(C.factors), B)) else @@ -430,11 +430,11 @@ function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) end end -function A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedVector{T}) where T<:BlasFloat +function ldiv!(C::CholeskyPivoted{T}, B::StridedVector{T}) where T<:BlasFloat chkfullrank(C) ipermute!(LAPACK.potrs!(C.uplo, C.factors, permute!(B, C.piv)), C.piv) end -function A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedMatrix{T}) where T<:BlasFloat +function ldiv!(C::CholeskyPivoted{T}, B::StridedMatrix{T}) where T<:BlasFloat chkfullrank(C) n = size(C, 1) for i=1:size(B, 2) @@ -447,7 +447,7 @@ function A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedMatrix{T}) where T<:BlasFloa B end -function A_ldiv_B!(C::CholeskyPivoted, B::StridedVector) +function ldiv!(C::CholeskyPivoted, B::StridedVector) if C.uplo == 'L' Ac_ldiv_B!(LowerTriangular(C.factors), A_ldiv_B!(LowerTriangular(C.factors), B[C.piv]))[invperm(C.piv)] @@ -457,7 +457,7 @@ function A_ldiv_B!(C::CholeskyPivoted, B::StridedVector) end end -function A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) +function ldiv!(C::CholeskyPivoted, B::StridedMatrix) if C.uplo == 'L' Ac_ldiv_B!(LowerTriangular(C.factors), A_ldiv_B!(LowerTriangular(C.factors), B[C.piv,:]))[invperm(C.piv),:] From c138fdc969178a4df23e1770b9ab2c84d53d1f74 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 17:23:16 -0800 Subject: [PATCH 09/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/factorization.jl with de-jazzed passthroughs. --- base/deprecated.jl | 11 +++++++++++ base/linalg/factorization.jl | 35 +++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 77149fcf172d2e..701cbf41212966 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2272,6 +2272,17 @@ end A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) = ldiv!(C, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/factorization.jl, to deprecate +@eval Base.LinAlg begin + Ac_ldiv_B(F::Factorization, B::AbstractVecOrMat) = \(Adjoint(F), B) + A_ldiv_B!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = ldiv!(Y, A, B) + Ac_ldiv_B!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = ldiv!(Y, Adjoint(A), B) + At_ldiv_B!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = ldiv!(Y, Transpose(A), B) + At_ldiv_B(F::Factorization{<:Real}, B::AbstractVecOrMat) = \(Transpose(F), B) + At_ldiv_B(F::Factorization, B) = \(Transpose(F), B) +end + + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 487221a20acac8..8003e5aca721e5 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -61,27 +61,30 @@ function (\)(F::Factorization{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal return reshape(collect(reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)))), _ret_size(F, B)) end -for (f1, f2) in ((:\, :A_ldiv_B!), - (:Ac_ldiv_B, :Ac_ldiv_B!)) - @eval begin - function $f1(F::Factorization, B::AbstractVecOrMat) - TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) - BB = similar(B, TFB, size(B)) - copy!(BB, B) - $f2(F, BB) - end - end +function \(F::Factorization, B::AbstractVecOrMat) + TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) + BB = similar(B, TFB, size(B)) + copy!(BB, B) + A_ldiv_B!(F, BB) +end +function \(adjF::Adjoint{<:Any,<:Factorization}, B::AbstractVecOrMat) + F = adjF.parent + TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) + BB = similar(B, TFB, size(B)) + copy!(BB, B) + Ac_ldiv_B!(F, BB) end # support the same 3-arg idiom as in our other in-place A_*_B functions: -for f in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) - @eval $f(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = - $f(A, copy!(Y, B)) -end +ldiv!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = A_ldiv_B!(A, copy!(Y, B)) +ldiv!(Y::AbstractVecOrMat, adjA::Adjoint{<:Any,<:Factorization}, B::AbstractVecOrMat) = + (A = adjA.parent; Ac_ldiv_B!(A, copy!(Y, B))) +ldiv!(Y::AbstractVecOrMat, transA::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = + (A = transA.parent; At_ldiv_B!(A, copy!(Y, B))) # fallback methods for transposed solves -At_ldiv_B(F::Factorization{<:Real}, B::AbstractVecOrMat) = Ac_ldiv_B(F, B) -At_ldiv_B(F::Factorization, B) = conj.(Ac_ldiv_B(F, conj.(B))) +\(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; Ac_ldiv_B(F, B)) +\(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(Ac_ldiv_B(F, conj.(B)))) """ A_ldiv_B!([Y,] A, B) -> Y From 4642c3e01637b2ccd2f9b48da6cbd102cc6ac81c Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 20:06:18 -0800 Subject: [PATCH 10/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/hessenberg.jl with de-jazzed passthroughs. --- base/deprecated.jl | 9 +++++++++ base/linalg/hessenberg.jl | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 701cbf41212966..c6bd55f64a749b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2282,6 +2282,15 @@ end At_ldiv_B(F::Factorization, B) = \(Transpose(F), B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/hessenberg.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(Q, X) + A_mul_B!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = mul!(X, Q) + Ac_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(Adjoint(Q), X) + A_mul_Bc!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = mul!(X, Adjoint(Q)) + Ac_mul_B(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} = *(Adjoint(Q), X) + A_mul_Bc(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} = *(X, Adjoint(Q)) +end # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index fc4d44ddd9c3e2..3be7b7fb18326a 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -84,14 +84,14 @@ convert(::Type{AbstractArray}, F::Hessenberg) = convert(AbstractMatrix, F) convert(::Type{Matrix}, F::Hessenberg) = convert(Array, convert(AbstractArray, F)) convert(::Type{Array}, F::Hessenberg) = convert(Matrix, F) -A_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = +mul!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) -A_mul_B!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = +mul!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = LAPACK.ormhr!('R', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) -Ac_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = - LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X) -A_mul_Bc!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = - LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X) +mul!(adjQ::Adjoint{<:Any,<:HessenbergQ{T}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = + (Q = adjQ.parent; LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)) +mul!(X::StridedMatrix{T}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T<:BlasFloat} = + (Q = adjQ.parent; LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)) function (*)(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} @@ -102,11 +102,13 @@ function (*)(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return A_mul_B!(copy_oftype(X, TT), Q) end -function Ac_mul_B(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} +function *(adjQ::Adjoint{<:Any,<:HessenbergQ{T}}, X::StridedVecOrMat{S}) where {T,S} + Q = adjQ.parent TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return Ac_mul_B!(Q, copy_oftype(X, TT)) end -function A_mul_Bc(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} +function *(X::StridedVecOrMat{S}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T,S} + Q = adjQ.parent TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return A_mul_Bc!(copy_oftype(X, TT), Q) end From e7f21251e18be1e26ad08771fdc119ec167db343 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 20:09:02 -0800 Subject: [PATCH 11/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/ldlt.jl with de-jazzed passthroughs. --- base/deprecated.jl | 5 +++++ base/linalg/ldlt.jl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index c6bd55f64a749b..ae6390f3245fff 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2292,6 +2292,11 @@ end A_mul_Bc(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} = *(X, Adjoint(Q)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/ldlt.jl, to deprecate +@eval Base.LinAlg begin + A_ldiv_B!(S::LDLt{T,M}, B::AbstractVecOrMat{T}) where {T,M<:SymTridiagonal{T}} = ldiv!(S, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index a2d65971ce78d7..d8bc1f38c979a4 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -91,7 +91,7 @@ end factorize(S::SymTridiagonal) = ldltfact(S) -function A_ldiv_B!(S::LDLt{T,M}, B::AbstractVecOrMat{T}) where {T,M<:SymTridiagonal{T}} +function ldiv!(S::LDLt{T,M}, B::AbstractVecOrMat{T}) where {T,M<:SymTridiagonal{T}} n, nrhs = size(B, 1), size(B, 2) if size(S,1) != n throw(DimensionMismatch("Matrix has dimensions $(size(S)) but right hand side has first dimension $n")) From 5c45fef0a315d9a80c3240a934ac2d6a9731fea7 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 20:12:01 -0800 Subject: [PATCH 12/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/svd.jl with de-jazzed passthroughs. --- base/deprecated.jl | 5 +++++ base/linalg/svd.jl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index ae6390f3245fff..81dab73a0bda16 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2297,6 +2297,11 @@ end A_ldiv_B!(S::LDLt{T,M}, B::AbstractVecOrMat{T}) where {T,M<:SymTridiagonal{T}} = ldiv!(S, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/svd.jl, to deprecate +@eval Base.LinAlg begin + A_ldiv_B!(A::SVD{T}, B::StridedVecOrMat) where {T} = ldiv!(A, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 2672a432bd27cf..e25b921fc21411 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -256,7 +256,7 @@ svdvals(x::Number) = abs(x) svdvals(S::SVD{<:Any,T}) where {T} = (S[:S])::Vector{T} # SVD least squares -function A_ldiv_B!(A::SVD{T}, B::StridedVecOrMat) where T +function ldiv!(A::SVD{T}, B::StridedVecOrMat) where T k = searchsortedlast(A.S, eps(real(T))*A.S[1], rev=true) view(A.Vt,1:k,:)' * (view(A.S,1:k) .\ (view(A.U,:,1:k)' * B)) end From f5f77a523402519a32317b70c8f95f31f4d86872 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 20:33:24 -0800 Subject: [PATCH 13/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/symmetric.jl with de-jazzed passthroughs. --- base/deprecated.jl | 25 ++++++++++++++++++++++++ base/linalg/symmetric.jl | 42 ++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 81dab73a0bda16..f254200d6c6642 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2302,6 +2302,31 @@ end A_ldiv_B!(A::SVD{T}, B::StridedVecOrMat) where {T} = ldiv!(A, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/symmetric.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = mul!(y, A, x) + A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasReal} = mul!(y, A, x) + A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasComplex} = mul!(y, A, x) + A_mul_B!(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) where {T<:BlasFloat} = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasReal} = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasComplex} = mul!(C, A, B) + At_mul_B(A::RealHermSymComplexSym, B::AbstractVector) = *(Transpose(A), B) + At_mul_B(A::RealHermSymComplexSym, B::AbstractMatrix) = *(Transpose(A), B) + A_mul_Bt(A::AbstractMatrix, B::RealHermSymComplexSym) = *(A, Transpose(B)) + Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractVector) = *(Adjoint(A), B) + Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractMatrix) = *(Adjoint(A), B) + A_mul_Bc(A::AbstractMatrix, B::RealHermSymComplexHerm) = *(A, Adjoint(B)) + A_mul_Bt(A::RowVector, B::RealHermSymComplexSym) = *(A, Transpose(B)) + A_mul_Bc(A::RowVector, B::RealHermSymComplexHerm) = *(A, Adjoint(B)) + At_mul_B(A::RealHermSymComplexSym, B::AbstractTriangular) = *(Transpose(A), B) + A_mul_Bt(A::AbstractTriangular, B::RealHermSymComplexSym) = *(A, Transpose(B)) + Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractTriangular) = *(Adjoint(A), B) + A_mul_Bc(A::AbstractTriangular, B::RealHermSymComplexHerm) = *(A, Adjoint(B)) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 20d587a6a1bc81..cb3acee4804707 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -299,46 +299,46 @@ end (-)(A::Hermitian{Tv,S}) where {Tv,S} = Hermitian{Tv,S}(-A.data, A.uplo) ## Matvec -A_mul_B!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = +mul!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) -A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasReal} = +mul!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasReal} = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) -A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasComplex} = +mul!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasComplex} = BLAS.hemv!(A.uplo, one(T), A.data, x, zero(T), y) ## Matmat -A_mul_B!(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = +mul!(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) -A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) where {T<:BlasFloat} = +mul!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) -A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = +mul!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) -A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasReal} = +mul!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasReal} = BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) -A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = +mul!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = BLAS.hemm!('L', A.uplo, one(T), A.data, B, zero(T), C) -A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasComplex} = +mul!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasComplex} = BLAS.hemm!('R', B.uplo, one(T), B.data, A, zero(T), C) *(A::HermOrSym, B::HermOrSym) = A * copy!(similar(parent(B)), B) # Fallbacks to avoid generic_matvecmul!/generic_matmatmul! ## Symmetric{<:Number} and Hermitian{<:Real} are invariant to transpose; peel off the t -At_mul_B(A::RealHermSymComplexSym, B::AbstractVector) = A*B -At_mul_B(A::RealHermSymComplexSym, B::AbstractMatrix) = A*B -A_mul_Bt(A::AbstractMatrix, B::RealHermSymComplexSym) = A*B +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::AbstractVector) = transA.parent * B +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::AbstractMatrix) = transA.parent * B +*(A::AbstractMatrix, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent ## Hermitian{<:Number} and Symmetric{<:Real} are invariant to adjoint; peel off the c -Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractVector) = A*B -Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractMatrix) = A*B -A_mul_Bc(A::AbstractMatrix, B::RealHermSymComplexHerm) = A*B +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::AbstractVector) = adjA.parent * B +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::AbstractMatrix) = adjA.parent * B +*(A::AbstractMatrix, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent # ambiguities with RowVector -A_mul_Bt(A::RowVector, B::RealHermSymComplexSym) = A*B -A_mul_Bc(A::RowVector, B::RealHermSymComplexHerm) = A*B +*(A::RowVector, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent +*(A::RowVector, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent # ambiguities with AbstractTriangular -At_mul_B(A::RealHermSymComplexSym, B::AbstractTriangular) = A*B -A_mul_Bt(A::AbstractTriangular, B::RealHermSymComplexSym) = A*B -Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractTriangular) = A*B -A_mul_Bc(A::AbstractTriangular, B::RealHermSymComplexHerm) = A*B +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::AbstractTriangular) = transA.parent * B +*(A::AbstractTriangular, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::AbstractTriangular) = adjA.parent * B +*(A::AbstractTriangular, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent for T in (:Symmetric, :Hermitian), op in (:*, :/) # Deal with an ambiguous case From 6fdb961888b77bb42f121a14f6a3a9e8f442af15 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 20:58:04 -0800 Subject: [PATCH 14/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/lu.jl with de-jazzed passthroughs. --- base/deprecated.jl | 18 ++++++++++++++++++ base/linalg/lu.jl | 46 +++++++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index f254200d6c6642..1b1f44c6133460 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2327,6 +2327,24 @@ end A_mul_Bc(A::AbstractTriangular, B::RealHermSymComplexHerm) = *(A, Adjoint(B)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/lu.jl, to deprecate +@eval Base.LinAlg begin + A_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(A, B) + A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) = ldiv!(A, B) + At_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(Transpose(A), B) + At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) = ldiv!(Transpose(A), B) + Ac_ldiv_B!(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:Real} = ldiv!(Adjoint(F), B) + Ac_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = ldiv!(Adjoint(A), B) + Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) = ldiv!(Adjoint(A), B) + At_ldiv_Bt(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = \(Transpose(A), Transpose(B)) + At_ldiv_Bt(A::LU, B::StridedVecOrMat) = \(Transpose(A), Transpose(B)) + Ac_ldiv_Bc(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = \(Adjoint(A), Adjoint(B)) + Ac_ldiv_Bc(A::LU, B::StridedVecOrMat) = \(Adjoint(A), Adjoint(B)) + A_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} = ldiv!(A, B) + At_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} = \(Transpose(A), B) + Ac_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} = ldiv!(Adjoint(A), B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 873a889f91f351..ed7f86b514d3e4 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -302,39 +302,49 @@ function _swap_rows!(B::StridedMatrix, i::Integer, j::Integer) B end -A_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +ldiv!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info -function A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) +function ldiv!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) _apply_ipiv!(A, B) A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B)) end -At_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = - @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, B) A.info +ldiv!(transA::Transpose{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = + (A = transA.parent; @assertnonsingular(LAPACK.getrs!('T', A.factors, A.ipiv, B), A.info)) -function At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) +function ldiv!(transA::Transpose{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) + A = transA.parent At_ldiv_B!(UnitLowerTriangular(A.factors), At_ldiv_B!(UpperTriangular(A.factors), B)) _apply_inverse_ipiv!(A, B) end -Ac_ldiv_B!(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:Real} = - At_ldiv_B!(F, B) -Ac_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = - @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, B) A.info +ldiv!(adjF::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:Real} = + (F = adjF.parent; At_ldiv_B!(F, B)) +ldiv!(adjA::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = + (A = adjA.parent; @assertnonsingular(LAPACK.getrs!('C', A.factors, A.ipiv, B), A.info)) -function Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) +function ldiv!(adjA::Adjoint{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) + A = adjA.parent Ac_ldiv_B!(UnitLowerTriangular(A.factors), Ac_ldiv_B!(UpperTriangular(A.factors), B)) _apply_inverse_ipiv!(A, B) end -At_ldiv_Bt(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +function \(transA::Transpose{<:Any,<:LU{T,<:StridedMatrix}}, + transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} + A, B = transA.parent, transB.parent @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info -At_ldiv_Bt(A::LU, B::StridedVecOrMat) = At_ldiv_B(A, transpose(B)) +end +\(transA::Transpose{<:Any,<:LU}, transB::Transpose{<:Any,<:StridedVecOrMat}) = + (A = transA.parent; B = transB.parent; At_ldiv_B(A, transpose(B))) -Ac_ldiv_Bc(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = +function \(adjA::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, + adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasComplex} + A, B = adjA.parent, adjB.parent @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, adjoint(B)) A.info -Ac_ldiv_Bc(A::LU, B::StridedVecOrMat) = Ac_ldiv_B(A, adjoint(B)) +end +\(adjA::Adjoint{<:Any,<:LU}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) = + (A = adjA.parent; B = adjB.parent; Ac_ldiv_B(A, adjoint(B))) function det(F::LU{T}) where T n = checksquare(F) @@ -478,7 +488,7 @@ function getindex(F::LU{T,Tridiagonal{T,V}}, d::Symbol) where {T,V} end # See dgtts2.f -function A_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} +function ldiv!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) @@ -509,7 +519,8 @@ function A_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} return B end -function At_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} +function ldiv!(transA::Transpose{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V} + A = transA.parent n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) @@ -544,7 +555,8 @@ function At_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} end # Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where {T<:Real} = At_ldiv_B!(A,B) -function Ac_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} +function ldiv!(adjA::Adjoint{<:Any,LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V} + A = adjA.parent n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) From 79a2ce2a01bfb81e0b446d4adf9026f566ecc052 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 4 Dec 2017 21:21:07 -0800 Subject: [PATCH 15/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/lq.jl with de-jazzed passthroughs. --- base/deprecated.jl | 20 +++++++++++++++ base/linalg/lq.jl | 61 ++++++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 1b1f44c6133460..fccf28877af134 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2345,6 +2345,26 @@ end Ac_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} = ldiv!(Adjoint(A), B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/lq.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(A, B) + A_mul_B!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = mul!(A, B) + A_mul_B!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = mul!(A, B) + A_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(A, B) + Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = mul!(Adjoint(A), B) + Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = mul!(Adjoint(A), B) + Ac_mul_B(A::LQPackedQ, B::StridedVecOrMat) = *(Adjoint(A), B) + A_mul_Bc(A::LQPackedQ, B::StridedVecOrMat) = *(A, Adjoint(B)) + Ac_mul_Bc(A::LQPackedQ, B::StridedVecOrMat) = *(Adjoint(A), Adjoint(B)) + A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = mul!(A, B) + A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = mul!(A, Adjoint(B)) + A_mul_Bc(A::StridedVecOrMat, Q::LQPackedQ) = *(A, Adjoint(Q)) + Ac_mul_Bc(A::StridedMatrix, Q::LQPackedQ) = *(Adjoint(A), Adjoint(Q)) + Ac_mul_B(A::StridedMatrix, Q::LQPackedQ) = *(Adjoint(A), Q) + A_ldiv_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T} = ldiv!(A, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 01966e41dd0690..5717e6fda52841 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -120,11 +120,11 @@ end ## Multiplication by LQ -A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +mul!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A[:L] * LAPACK.ormlq!('L', 'N', A.factors, A.τ, B) -A_mul_B!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = +mul!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = A[:L] * LAPACK.ormlq!('L', 'N', A.factors, A.τ, Matrix(B)) -A_mul_B!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = +mul!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = A_mul_B!(zeros(eltype(A), size(A)), Matrix(A), Matrix(B)) function *(A::LQ{TA}, B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) @@ -141,16 +141,19 @@ end ## Multiplication by Q ### QB -A_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) +mul!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) function (*)(A::LQPackedQ, B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) A_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) end ### QcB -Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = LAPACK.ormlq!('L','T',A.factors,A.τ,B) -Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = LAPACK.ormlq!('L','C',A.factors,A.τ,B) -function Ac_mul_B(A::LQPackedQ, B::StridedVecOrMat) +mul!(adjA::Adjoint{<:Any,<:LQPackedQ{T}}, B::StridedVecOrMat{T}) where {T<:BlasReal} = + (A = adjA.parent; LAPACK.ormlq!('L','T',A.factors,A.τ,B)) +mul!(adjA::Adjoint{<:Any,<:LQPackedQ{T}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = + (A = adjA.parent; LAPACK.ormlq!('L','C',A.factors,A.τ,B)) +function *(adjA::Adjoint{<:Any,<:LQPackedQ}, B::StridedVecOrMat) + A = adjA.parent TAB = promote_type(eltype(A), eltype(B)) if size(B,1) == size(A.factors,2) Ac_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) @@ -162,16 +165,19 @@ function Ac_mul_B(A::LQPackedQ, B::StridedVecOrMat) end ### QBc/QcBc -for (f1, f2) in ((:A_mul_Bc, :A_mul_B!), - (:Ac_mul_Bc, :Ac_mul_B!)) - @eval begin - function ($f1)(A::LQPackedQ, B::StridedVecOrMat) - TAB = promote_type(eltype(A), eltype(B)) - BB = similar(B, TAB, (size(B, 2), size(B, 1))) - adjoint!(BB, B) - return ($f2)(A, BB) - end - end +function *(A::LQPackedQ, adjB::Adjoint{<:Any,<:StridedVecOrMat}) + B = adjB.parent + TAB = promote_type(eltype(A), eltype(B)) + BB = similar(B, TAB, (size(B, 2), size(B, 1))) + adjoint!(BB, B) + return A_mul_B!(A, BB) +end +function *(adjA::Adjoint{<:Any,<:LQPackedQ}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) + A, B = adjA.parent, adjB.parent + TAB = promote_type(eltype(A), eltype(B)) + BB = similar(B, TAB, (size(B, 2), size(B, 1))) + adjoint!(BB, B) + return Ac_mul_B!(A, BB) end # in-place right-application of LQPackedQs @@ -179,12 +185,12 @@ end # match the number of columns (nQ) of the LQPackedQ (Q) (necessary for in-place # operation, and the underlying LAPACK routine (ormlq) treats the implicit Q # as its (nQ-by-nQ) square form) -A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = +mul!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = LAPACK.ormlq!('R', 'N', B.factors, B.τ, A) -A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} = - LAPACK.ormlq!('R', 'T', B.factors, B.τ, A) -A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = - LAPACK.ormlq!('R', 'C', B.factors, B.τ, A) +mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:LQPackedQ{T}}) where {T<:BlasReal} = + (B = adjB.parent; LAPACK.ormlq!('R', 'T', B.factors, B.τ, A)) +mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:LQPackedQ{T}}) where {T<:BlasComplex} = + (B = adjB.parent; LAPACK.ormlq!('R', 'C', B.factors, B.τ, A)) # out-of-place right application of LQPackedQs # @@ -198,11 +204,13 @@ A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = # (1) the inner dimension in the multiplication is the LQPackedQ's second dimension. # in this case, the LQPackedQ behaves like its square form. # -function A_mul_Bc(A::StridedVecOrMat, Q::LQPackedQ) +function *(A::StridedVecOrMat, adjQ::Adjoint{<:Any,<:LQPackedQ}) + Q = adjQ.parent TR = promote_type(eltype(A), eltype(Q)) return A_mul_Bc!(copy_oftype(A, TR), convert(AbstractMatrix{TR}, Q)) end -function Ac_mul_Bc(A::StridedMatrix, Q::LQPackedQ) +function *(adjA::Adjoint{<:Any,<:StridedMatrix}, adjQ::Adjoint{<:Any,<:LQPackedQ}) + A, Q = adjA.parent, adjQ.parent TR = promote_type(eltype(A), eltype(Q)) C = adjoint!(similar(A, TR, reverse(size(A))), A) return A_mul_Bc!(C, convert(AbstractMatrix{TR}, Q)) @@ -232,7 +240,8 @@ function *(A::StridedVecOrMat, Q::LQPackedQ) end return A_mul_B!(C, convert(AbstractMatrix{TR}, Q)) end -function Ac_mul_B(A::StridedMatrix, Q::LQPackedQ) +function *(adjA::Adjoint{<:Any,<:StridedMatrix}, Q::LQPackedQ) + A = adjA.parent TR = promote_type(eltype(A), eltype(Q)) if size(A, 1) == size(Q.factors, 2) C = adjoint!(similar(A, TR, reverse(size(A))), A) @@ -277,7 +286,7 @@ function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal end -function A_ldiv_B!(A::LQ{T}, B::StridedVecOrMat{T}) where T +function ldiv!(A::LQ{T}, B::StridedVecOrMat{T}) where T Ac_mul_B!(A[:Q], A_ldiv_B!(LowerTriangular(A[:L]),B)) return B end From 096fc6761570f4e50e79702d0e34a312f140b5bb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 5 Dec 2017 09:54:47 -0800 Subject: [PATCH 16/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/qr.jl with de-jazzed passthroughs. --- base/deprecated.jl | 36 ++++++++++++++ base/linalg/qr.jl | 120 +++++++++++++++++++++++++-------------------- 2 files changed, 104 insertions(+), 52 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index fccf28877af134..0fb4f02e318c66 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2365,6 +2365,42 @@ end A_ldiv_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T} = ldiv!(A, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/qr.jl, to deprecate +@eval Base.LinAlg begin + A_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = mul!(A, B) + A_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = mul!(A, B) + A_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) = mul!(A, B) + Ac_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = mul!(Adjoint(A), B) + Ac_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = mul!(Adjoint(A), B) + Ac_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = mul!(Adjoint(A), B) + Ac_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = mul!(Adjoint(A), B) + Ac_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) = mul!(Adjoint(A), B) + Ac_mul_B(Q::AbstractQ, B::StridedVecOrMat) = *(Adjoint(Q), B) + A_mul_Bc(Q::AbstractQ, B::StridedVecOrMat) = *(Q, Adjoint(B)) + Ac_mul_Bc(Q::AbstractQ, B::StridedVecOrMat) = *(Adjoint(Q), Adjoint(B)) + A_mul_B!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = mul!(A, B) + A_mul_B!(A::StridedVecOrMat{T}, B::QRPackedQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = mul!(A, B) + A_mul_B!(A::StridedMatrix,Q::QRPackedQ) = mul!(A, Q) + A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasReal} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasComplex} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasReal} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasComplex} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix,Q::QRPackedQ) = mul!(A, Adjoint(Q)) + A_mul_Bc(A::StridedMatrix, B::AbstractQ) = *(A, Adjoint(B)) + A_mul_Bc(rowvec::RowVector, B::AbstractQ) = *(rowvec, Adjoint(B)) + Ac_mul_B(A::StridedVecOrMat, Q::AbstractQ) = *(Adjoint(A), Q) + Ac_mul_Bc(A::StridedVecOrMat, Q::AbstractQ) = *(Adjoint(A), Adjoint(Q)) + A_ldiv_B!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat} = ldiv!(A, b) + A_ldiv_B!(A::QRCompactWY{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = ldiv!(A, B) + A_ldiv_B!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where {T<:BlasFloat} = ldiv!(A, B, rcond) + A_ldiv_B!(A::QRPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = ldiv!(A, B) + A_ldiv_B!(A::QRPivoted{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(A, B) + A_ldiv_B!(A::QR{T}, B::StridedMatrix{T}) where {T} = ldiv!(A, B) + A_ldiv_B!(A::QR, B::StridedVector) = ldiv!(A, B) + A_ldiv_B!(A::QRPivoted, b::StridedVector) = ldiv!(A, b) + A_ldiv_B!(A::QRPivoted, B::StridedMatrix) = ldiv!(A, B) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index dcdbc64e8c9960..8adc91052cf2b7 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -527,11 +527,11 @@ end ## Multiplication by Q ### QB -A_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = +mul!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = LAPACK.gemqrt!('L','N',A.factors,A.T,B) -A_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = +mul!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasFloat, S<:StridedMatrix} = LAPACK.ormqr!('L','N',A.factors,A.τ,B) -function A_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) +function mul!(A::QRPackedQ, B::AbstractVecOrMat) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) if mA != mB @@ -582,15 +582,16 @@ function (*)(A::AbstractQ, B::StridedMatrix) end ### QcB -Ac_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = - LAPACK.gemqrt!('L','T',A.factors,A.T,B) -Ac_mul_B!(A::QRCompactWYQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = - LAPACK.gemqrt!('L','C',A.factors,A.T,B) -Ac_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = - LAPACK.ormqr!('L','T',A.factors,A.τ,B) -Ac_mul_B!(A::QRPackedQ{T,S}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = - LAPACK.ormqr!('L','C',A.factors,A.τ,B) -function Ac_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) +mul!(adjA::Adjoint{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = + (A = adjA.parent; LAPACK.gemqrt!('L','T',A.factors,A.T,B)) +mul!(adjA::Adjoint{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = + (A = adjA.parent; LAPACK.gemqrt!('L','C',A.factors,A.T,B)) +mul!(adjA::Adjoint{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} = + (A = adjA.parent; LAPACK.ormqr!('L','T',A.factors,A.τ,B)) +mul!(adjA::Adjoint{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} = + (A = adjA.parent; LAPACK.ormqr!('L','C',A.factors,A.τ,B)) +function mul!(adjA::Adjoint{<:Any,<:QRPackedQ}, B::AbstractVecOrMat) + A = adjA.parent mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) if mA != mB @@ -614,30 +615,34 @@ function Ac_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) end B end -function Ac_mul_B(Q::AbstractQ, B::StridedVecOrMat) +function *(adjQ::Adjoint{<:Any,<:AbstractQ}, B::StridedVecOrMat) + Q = adjQ.parent TQB = promote_type(eltype(Q), eltype(B)) return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), copy_oftype(B, TQB)) end ### QBc/QcBc -for (f1, f2) in ((:A_mul_Bc, :A_mul_B!), - (:Ac_mul_Bc, :Ac_mul_B!)) - @eval begin - function ($f1)(Q::AbstractQ, B::StridedVecOrMat) - TQB = promote_type(eltype(Q), eltype(B)) - Bc = similar(B, TQB, (size(B, 2), size(B, 1))) - adjoint!(Bc, B) - return ($f2)(convert(AbstractMatrix{TQB}, Q), Bc) - end - end +function *(Q::AbstractQ, adjB::Adjoint{<:Any,<:StridedVecOrMat}) + B = adjB.parent + TQB = promote_type(eltype(Q), eltype(B)) + Bc = similar(B, TQB, (size(B, 2), size(B, 1))) + adjoint!(Bc, B) + return A_mul_B!(convert(AbstractMatrix{TQB}, Q), Bc) +end +function *(adjQ::Adjoint{<:Any,<:AbstractQ}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) + Q, B = adjQ.parent, adjB.parent + TQB = promote_type(eltype(Q), eltype(B)) + Bc = similar(B, TQB, (size(B, 2), size(B, 1))) + adjoint!(Bc, B) + return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), Bc) end ### AQ -A_mul_B!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = +mul!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = LAPACK.gemqrt!('R','N', B.factors, B.T, A) -A_mul_B!(A::StridedVecOrMat{T}, B::QRPackedQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = +mul!(A::StridedVecOrMat{T}, B::QRPackedQ{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = LAPACK.ormqr!('R', 'N', B.factors, B.τ, A) -function A_mul_B!(A::StridedMatrix,Q::QRPackedQ) +function mul!(A::StridedMatrix,Q::QRPackedQ) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) if nA != mQ @@ -668,11 +673,16 @@ function (*)(A::StridedMatrix, Q::AbstractQ) end ### AQc -A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasReal} = LAPACK.gemqrt!('R','T',B.factors,B.T,A) -A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasComplex} = LAPACK.gemqrt!('R','C',B.factors,B.T,A) -A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasReal} = LAPACK.ormqr!('R','T',B.factors,B.τ,A) -A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasComplex} = LAPACK.ormqr!('R','C',B.factors,B.τ,A) -function A_mul_Bc!(A::StridedMatrix,Q::QRPackedQ) +mul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasReal} = + (B = adjB.parent; LAPACK.gemqrt!('R','T',B.factors,B.T,A)) +mul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasComplex} = + (B = adjB.parent; LAPACK.gemqrt!('R','C',B.factors,B.T,A)) +mul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRPackedQ{T}}) where {T<:BlasReal} = + (B = adjB.parent; LAPACK.ormqr!('R','T',B.factors,B.τ,A)) +mul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRPackedQ{T}}) where {T<:BlasComplex} = + (B = adjB.parent; LAPACK.ormqr!('R','C',B.factors,B.τ,A)) +function mul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRPackedQ}) + Q = adjQ.parent mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) if nA != mQ @@ -696,7 +706,8 @@ function A_mul_Bc!(A::StridedMatrix,Q::QRPackedQ) end A end -function A_mul_Bc(A::StridedMatrix, B::AbstractQ) +function *(A::StridedMatrix, adjB::Adjoint{<:Any,<:AbstractQ}) + B = adjB.parent TAB = promote_type(eltype(A),eltype(B)) BB = convert(AbstractMatrix{TAB}, B) if size(A,2) == size(B.factors, 1) @@ -709,27 +720,32 @@ function A_mul_Bc(A::StridedMatrix, B::AbstractQ) throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(B))")) end end -@inline A_mul_Bc(rowvec::RowVector, B::AbstractQ) = adjoint(B*adjoint(rowvec)) +@inline *(rowvec::RowVector, adjB::Adjoint{<:Any,<:AbstractQ}) = (B = adjB.parent; adjoint(B*adjoint(rowvec))) ### AcQ/AcQc -for (f1, f2) in ((:Ac_mul_B, :A_mul_B!), - (:Ac_mul_Bc, :A_mul_Bc!)) - @eval begin - function ($f1)(A::StridedVecOrMat, Q::AbstractQ) - TAQ = promote_type(eltype(A), eltype(Q)) - Ac = similar(A, TAQ, (size(A, 2), size(A, 1))) - adjoint!(Ac, A) - return ($f2)(Ac, convert(AbstractMatrix{TAQ}, Q)) - end - end +function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, Q::AbstractQ) + A = adjA.parent + TAQ = promote_type(eltype(A), eltype(Q)) + Ac = similar(A, TAQ, (size(A, 2), size(A, 1))) + adjoint!(Ac, A) + return A_mul_B!(Ac, convert(AbstractMatrix{TAQ}, Q)) +end +function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, adjQ::Adjoint{<:Any,<:AbstractQ}) + A, Q = adjA.parent, adjQ.parent + TAQ = promote_type(eltype(A), eltype(Q)) + Ac = similar(A, TAQ, (size(A, 2), size(A, 1))) + adjoint!(Ac, A) + return A_mul_Bc!(Ac, convert(AbstractMatrix{TAQ}, Q)) end -A_ldiv_B!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat} = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) -A_ldiv_B!(A::QRCompactWY{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) +ldiv!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat} = + (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) +ldiv!(A::QRCompactWY{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = + (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) # Julia implementation similar to xgelsy -function A_ldiv_B!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:BlasFloat +function ldiv!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:BlasFloat mA, nA = size(A.factors) nr = min(mA,nA) nrhs = size(B, 2) @@ -764,11 +780,11 @@ function A_ldiv_B!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:B B[1:nA,:] = view(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:] return B, rnk end -A_ldiv_B!(A::QRPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = +ldiv!(A::QRPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = vec(A_ldiv_B!(A,reshape(B,length(B),1))) -A_ldiv_B!(A::QRPivoted{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +ldiv!(A::QRPivoted{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A_ldiv_B!(A, B, min(size(A)...)*eps(real(float(one(eltype(B))))))[1] -function A_ldiv_B!(A::QR{T}, B::StridedMatrix{T}) where T +function ldiv!(A::QR{T}, B::StridedMatrix{T}) where T m, n = size(A) minmn = min(m,n) mB, nB = size(B) @@ -814,13 +830,13 @@ function A_ldiv_B!(A::QR{T}, B::StridedMatrix{T}) where T end return B end -A_ldiv_B!(A::QR, B::StridedVector) = A_ldiv_B!(A, reshape(B, length(B), 1))[:] -function A_ldiv_B!(A::QRPivoted, b::StridedVector) +ldiv!(A::QR, B::StridedVector) = A_ldiv_B!(A, reshape(B, length(B), 1))[:] +function ldiv!(A::QRPivoted, b::StridedVector) A_ldiv_B!(QR(A.factors,A.τ), b) b[1:size(A.factors, 2)] = view(b, 1:size(A.factors, 2))[invperm(A.jpvt)] b end -function A_ldiv_B!(A::QRPivoted, B::StridedMatrix) +function ldiv!(A::QRPivoted, B::StridedMatrix) A_ldiv_B!(QR(A.factors, A.τ), B) B[1:size(A.factors, 2),:] = view(B, 1:size(A.factors, 2), :)[invperm(A.jpvt),:] B From 2a29a50c28788b788d29e71ed595fd03aa983076 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 5 Dec 2017 12:25:09 -0800 Subject: [PATCH 17/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/matmul.jl with de-jazzed passthroughs. --- base/deprecated.jl | 75 ++++++++++++++++++ base/linalg/diagonal.jl | 13 ++++ base/linalg/matmul.jl | 161 +++++++++++++++++++++++++-------------- base/linalg/symmetric.jl | 8 ++ 4 files changed, 200 insertions(+), 57 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 0fb4f02e318c66..ee4a0d9163f87b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2401,6 +2401,81 @@ end A_ldiv_B!(A::QRPivoted, B::StridedMatrix) = ldiv!(A, B) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/matmul.jl, to deprecate +@eval Base.LinAlg begin + Ac_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = *(Adjoint(A), Adjoint(B)) + Ac_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(C, Adjoint(A), Adjoint(B)) + Ac_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, Adjoint(A), Adjoint(B)) + Ac_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, Adjoint(A), Transpose(B)) + A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = mul!(C, A, Adjoint(B)) + A_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, A, Adjoint(B)) + A_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = *(A, Adjoint(B)) + A_mul_Bc(A::StridedMatrix{<:BlasFloat}, B::StridedMatrix{<:BlasReal}) = *(A, Adjoint(B)) + A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{<:BlasReal}) where {T<:BlasFloat} = mul!(C, A, Adjoint(B)) + Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = mul!(C, Adjoint(A), B) + Ac_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, Adjoint(A), B) + Ac_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = *(Adjoint(A), B) + Ac_mul_B(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:BlasReal} = *(Adjoint(A), B) + Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = mul!(C, Adjoint(A), B) + At_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(C, Transpose(A), Transpose(B)) + At_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, Transpose(A), Transpose(B)) + At_mul_Bt(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) where {T,S} = *(Transpose(A), Transpose(B)) + A_mul_Bt!(C::AbstractVecOrMat, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, A, Transpose(B)) + A_mul_Bt!(C::StridedMatrix{Complex{Float32}}, A::StridedVecOrMat{Complex{Float32}}, B::StridedVecOrMat{Float32}) = mul!(C, A, Transpose(B)) + A_mul_Bt!(C::StridedMatrix{Complex{Float64}}, A::StridedVecOrMat{Complex{Float64}}, B::StridedVecOrMat{Float64}) = mul!(C, A, Transpose(B)) + A_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(C, A, Transpose(B)) + A_mul_Bt(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = *(A, Transpose(B)) + At_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(C, Transpose(A), B) + At_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, Transpose(A), B) + At_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = *(Transpose(A), B) + """ + A_mul_B!(A, B) + + Calculate the matrix-matrix product ``AB``, overwriting one of `A` or `B` (but not both), + and return the result (the overwritten argument). + """ + A_mul_B!(A, B) + """ + A_mul_B!(Y, A, B) -> Y + + Calculates the matrix-matrix or matrix-vector product ``AB`` and stores the result in `Y`, + overwriting the existing value of `Y`. Note that `Y` must not be aliased with either `A` or + `B`. + + # Examples + ```jldoctest + julia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); A_mul_B!(Y, A, B); + + julia> Y + 2×2 Array{Float64,2}: + 3.0 3.0 + 7.0 7.0 + ``` + """ + A_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{Complex{Float32}}, A::StridedVecOrMat{Complex{Float32}}, B::StridedVecOrMat{Float32}) = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{Complex{Float64}}, A::StridedVecOrMat{Complex{Float64}}, B::StridedVecOrMat{Float64}) = mul!(C, A, B) + A_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(C, A, B) + Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasReal} = mul!(y, Adjoint(A), x) + Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasComplex} = mul!(y, Adjoint(A), x) + Ac_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = mul!(y, Adjoint(A), x) + Ac_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} = *(Adjoint(A), x) + Ac_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} = *(Adjoint(A), x) + At_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} = *(Transpose(A), x) + At_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} = *(Transpose(A), x) + At_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = mul!(y, Transpose(A), x) + At_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = mul!(y, Transpose(A), x) + A_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = mul!(y, A, x) + A_mul_B!(y::StridedVector{Complex{Float32}}, A::StridedVecOrMat{Complex{Float32}}, x::StridedVector{Float32}) = mul!(y, A, x) + A_mul_B!(y::StridedVector{Complex{Float64}}, A::StridedVecOrMat{Complex{Float64}}, x::StridedVector{Float64}) = mul!(y, A, x) + A_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = mul!(y, A, x) + A_mul_Bt(a::AbstractVector, B::AbstractMatrix) = *(a, Transpose(B)) + A_mul_Bt(A::AbstractMatrix, b::AbstractVector) = *(A, Transpose(b)) + A_mul_Bc(a::AbstractVector, B::AbstractMatrix) = *(a, Adjoint(B)) + A_mul_Bc(A::AbstractMatrix, b::AbstractVector) = *(A, Adjoint(b)) + At_mul_B(x::StridedVector{T}, y::StridedVector{T}) where {T<:BlasComplex} = *(Transpose(x), y) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 7571f7cccaf89d..9f817a74828bc5 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -262,6 +262,19 @@ mul!(out::AbstractMatrix, transA::Transpose{<:Any,<:Diagonal}, in::AbstractMatri *(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::Diagonal) = transA.parent * B *(A::Diagonal, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent *(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Diagonal) = adjA.parent * B +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, transD::Transpose{<:Any,<:Diagonal}) = transA.parent * transD +*(transD::Transpose{<:Any,<:Diagonal}, transA::Transpose{<:Any,<:RealHermSymComplexSym}) = transD * transA.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, adjD::Adjoint{<:Any,<:Diagonal}) = adjA.parent * adjD +*(adjD::Adjoint{<:Any,<:Diagonal}, adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}) = adjD * adjA.parent +mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:Diagonal}, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = + mul!(C, adjA, adjB.parent) +mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:Diagonal}, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = + mul!(C, transA, transB.parent) +mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:Diagonal}, adjB::Adjoint{<:Any,<:RealHermSymComplexSym}) = + (A = adjA.parent; C .= adjoint.(A.diag) .* adjB) +mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:Diagonal}, transB::Transpose{<:Any,<:RealHermSymComplexHerm}) = + (A = transA.parent; C .= transpose.(A.diag) .* transB) + (/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) function ldiv!(D::Diagonal{T}, v::AbstractVector{T}) where {T} diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index bf0fbd8283d183..15f96dcfa690bf 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -67,7 +67,8 @@ function dot(x::Vector{T}, rx::Union{UnitRange{TI},AbstractRange{TI}}, y::Vector Base.@gc_preserve x y BLAS.dotc(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end -At_mul_B(x::StridedVector{T}, y::StridedVector{T}) where {T<:BlasComplex} = BLAS.dotu(x, y) +*(transx::Transpose{<:Any,<:StridedVector{T}}, y::StridedVector{T}) where {T<:BlasComplex} = + (x = transx.parent; BLAS.dotu(x, y)) # Matrix-vector multiplication function (*)(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} @@ -80,16 +81,20 @@ function (*)(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} end # these will throw a DimensionMismatch unless B has 1 row (or 1 col for transposed case): -A_mul_Bt(a::AbstractVector, B::AbstractMatrix) = A_mul_Bt(reshape(a,length(a),1),B) -A_mul_Bt(A::AbstractMatrix, b::AbstractVector) = A_mul_Bt(A,reshape(b,length(b),1)) -A_mul_Bc(a::AbstractVector, B::AbstractMatrix) = A_mul_Bc(reshape(a,length(a),1),B) -A_mul_Bc(A::AbstractMatrix, b::AbstractVector) = A_mul_Bc(A,reshape(b,length(b),1)) +*(a::AbstractVector, transB::Transpose{<:Any,<:AbstractMatrix}) = + (B = transB.parent; A_mul_Bt(reshape(a,length(a),1),B)) +*(A::AbstractMatrix, transb::Transpose{<:Any,<:AbstractVector}) = + (b = transb.parent; A_mul_Bt(A,reshape(b,length(b),1))) +*(a::AbstractVector, adjB::Adjoint{<:Any,<:AbstractMatrix}) = + (B = adjB.parent; A_mul_Bc(reshape(a,length(a),1),B)) +*(A::AbstractMatrix, adjb::Adjoint{<:Any,<:AbstractVector}) = + (b = adjb.parent; A_mul_Bc(A,reshape(b,length(b),1))) (*)(a::AbstractVector, B::AbstractMatrix) = reshape(a,length(a),1)*B -A_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'N', A, x) +mul!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'N', A, x) for elty in (Float32,Float64) @eval begin - function A_mul_B!(y::StridedVector{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, x::StridedVector{$elty}) + function mul!(y::StridedVector{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, x::StridedVector{$elty}) Afl = reinterpret($elty,A) yfl = reinterpret($elty,y) gemv!(yfl,'N',Afl,x) @@ -97,31 +102,40 @@ for elty in (Float32,Float64) end end end -A_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'N', A, x) +mul!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'N', A, x) -function At_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} +function *(transA::Transpose{<:Any,<:StridedMatrix{T}}, x::StridedVector{S}) where {T<:BlasFloat,S} + A = transA.parent TS = promote_op(matprod, T, S) At_mul_B!(similar(x,TS,size(A,2)), A, convert(AbstractVector{TS}, x)) end -function At_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} +function *(transA::Transpose{<:Any,<:AbstractMatrix{T}}, x::AbstractVector{S}) where {T,S} + A = transA.parent TS = promote_op(matprod, T, S) At_mul_B!(similar(x,TS,size(A,2)), A, x) end -At_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'T', A, x) -At_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'T', A, x) +mul!(y::StridedVector{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasFloat} = + (A = transA.parent; gemv!(y, 'T', A, x)) +mul!(y::AbstractVector, transA::Transpose{<:Any,<:AbstractVecOrMat}, x::AbstractVector) = + (A = transA.parent; generic_matvecmul!(y, 'T', A, x)) -function Ac_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} +function *(adjA::Adjoint{<:Any,<:StridedMatrix{T}}, x::StridedVector{S}) where {T<:BlasFloat,S} + A = adjA.parent TS = promote_op(matprod, T, S) Ac_mul_B!(similar(x,TS,size(A,2)),A,convert(AbstractVector{TS},x)) end -function Ac_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} +function *(adjA::Adjoint{<:Any,<:AbstractMatrix{T}}, x::AbstractVector{S}) where {T,S} + A = adjA.parent TS = promote_op(matprod, T, S) Ac_mul_B!(similar(x,TS,size(A,2)), A, x) end -Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasReal} = At_mul_B!(y, A, x) -Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasComplex} = gemv!(y, 'C', A, x) -Ac_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'C', A, x) +mul!(y::StridedVector{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasReal} = + (A = adjA.parent; At_mul_B!(y, A, x)) +mul!(y::StridedVector{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasComplex} = + (A = adjA.parent; gemv!(y, 'C', A, x)) +mul!(y::AbstractVector, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, x::AbstractVector) = + (A = adjA.parent; generic_matvecmul!(y, 'C', A, x)) # Matrix-matrix multiplication @@ -144,10 +158,10 @@ function (*)(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end -A_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'N', 'N', A, B) +mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'N', 'N', A, B) for elty in (Float32,Float64) @eval begin - function A_mul_B!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, B::StridedVecOrMat{$elty}) + function mul!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, B::StridedVecOrMat{$elty}) Afl = reinterpret($elty, A) Cfl = reinterpret($elty, C) gemm_wrapper!(Cfl, 'N', 'N', Afl, B) @@ -157,7 +171,7 @@ for elty in (Float32,Float64) end """ - A_mul_B!(Y, A, B) -> Y + mul!(Y, A, B) -> Y Calculates the matrix-matrix or matrix-vector product ``AB`` and stores the result in `Y`, overwriting the existing value of `Y`. Note that `Y` must not be aliased with either `A` or @@ -165,7 +179,7 @@ overwriting the existing value of `Y`. Note that `Y` must not be aliased with ei # Examples ```jldoctest -julia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); A_mul_B!(Y, A, B); +julia> A=[1.0 2.0; 3.0 4.0]; B=[1.0 1.0; 1.0 1.0]; Y = similar(B); mul!(Y, A, B); julia> Y 2×2 Array{Float64,2}: @@ -173,31 +187,37 @@ julia> Y 7.0 7.0 ``` """ -A_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) +mul!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) """ - A_mul_B!(A, B) + mul!(A, B) Calculate the matrix-matrix product ``AB``, overwriting one of `A` or `B` (but not both), and return the result (the overwritten argument). """ -A_mul_B!(A, B) +mul!(A, B) -function At_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} - TS = promote_op(matprod, T, S) +function *(transA::Transpose{<:Any,<:AbstractMatrix}, B::AbstractMatrix) + A = transA.parent + TS = promote_op(matprod, eltype(A), eltype(B)) At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end -At_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A===B ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) -At_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'T', 'N', A, B) +mul!(C::StridedMatrix{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = + (A = transA.parent; A===B ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B)) +mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:AbstractVecOrMat}, B::AbstractVecOrMat) = + (A = transA.parent; generic_matmatmul!(C, 'T', 'N', A, B)) -function A_mul_Bt(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} - TS = promote_op(matprod, T, S) +function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractMatrix}) + B = transB.parent + TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end -A_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A===B ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) +mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = + (B = transB.parent; A===B ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B)) for elty in (Float32,Float64) @eval begin - function A_mul_Bt!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, B::StridedVecOrMat{$elty}) + function mul!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, transB::Transpose{<:Any,<:StridedVecOrMat{$elty}}) + B = transB.parent Afl = reinterpret($elty, A) Cfl = reinterpret($elty, C) gemm_wrapper!(Cfl, 'N', 'T', Afl, B) @@ -205,38 +225,65 @@ for elty in (Float32,Float64) end end end -A_mul_Bt!(C::AbstractVecOrMat, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'T', A, B) - -function At_mul_Bt(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) where {T,S} +# collapsing the following two defs with C::AbstractVecOrMat yields ambiguities +mul!(C::AbstractVector, A::AbstractVecOrMat, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + _disambigmul!(C, A, transB) +mul!(C::AbstractMatrix, A::AbstractVecOrMat, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + _disambigmul!(C, A, transB) +_disambigmul!(C::AbstractVecOrMat, A::AbstractVecOrMat, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + (B = transB.parent; generic_matmatmul!(C, 'N', 'T', A, B)) + +# collapsing the following two defs with transB::Transpose{<:Any,<:AbstractVecOrMat{S}} yields ambiguities +*(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractMatrix}) = + _disambigmul(transA, transB) +*(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractVector}) = + _disambigmul(transA, transB) +function _disambigmul(transA::Transpose{<:Any,<:AbstractMatrix{T}}, transB::Transpose{<:Any,<:AbstractVecOrMat{S}}) where {T,S} + A, B = transA.parent, transB.parent TS = promote_op(matprod, T, S) At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end -At_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'T', 'T', A, B) -At_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'T', 'T', A, B) - -Ac_mul_B(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:BlasReal} = At_mul_B(A, B) -Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = At_mul_B!(C, A, B) -function Ac_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} - TS = promote_op(matprod, T, S) +mul!(C::StridedMatrix{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = + (A = transA.parent; B = transB.parent; gemm_wrapper!(C, 'T', 'T', A, B)) +mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:AbstractVecOrMat}, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + (A = transA.parent; B = transB.parent; generic_matmatmul!(C, 'T', 'T', A, B)) + +*(adjA::Adjoint{<:Any,<:StridedMatrix{T}}, B::StridedMatrix{T}) where {T<:BlasReal} = + (A = adjA.parent; At_mul_B(A, B)) +mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasReal} = + (A = adjA.parent; At_mul_B!(C, A, B)) +function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, B::AbstractMatrix) + A = adjA.parent + TS = promote_op(matprod, eltype(A), eltype(B)) Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end -Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = A===B ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) -Ac_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'N', A, B) - -A_mul_Bc(A::StridedMatrix{<:BlasFloat}, B::StridedMatrix{<:BlasReal}) = A_mul_Bt(A, B) -A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{<:BlasReal}) where {T<:BlasFloat} = A_mul_Bt!(C, A, B) -function A_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} - TS = promote_op(matprod, T, S) +mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = + (A = adjA.parent; A===B ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B)) +mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, B::AbstractVecOrMat) = + (A = adjA.parent; generic_matmatmul!(C, 'C', 'N', A, B)) + +*(A::StridedMatrix{<:BlasFloat}, adjB::Adjoint{<:Any,<:StridedMatrix{<:BlasReal}}) = + (B = adjB.parent; A_mul_Bt(A, B)) +mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:StridedVecOrMat{<:BlasReal}}) where {T<:BlasFloat} = + (B = adjB.parent; A_mul_Bt!(C, A, B)) +function *(A::AbstractMatrix, adjB::Adjoint{<:Any,<:AbstractMatrix}) + B = adjB.parent + TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_Bc!(similar(B,TS,(size(A,1),size(B,1))),A,B) end -A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = A===B ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) -A_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'C', A, B) - -Ac_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = - Ac_mul_Bc!(similar(B, promote_op(matprod, T, S), (size(A,2), size(B,1))), A, B) -Ac_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'C', 'C', A, B) -Ac_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'T', A, B) +mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasComplex} = + (B = adjB.parent; A===B ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B)) +mul!(C::AbstractMatrix, A::AbstractVecOrMat, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = + (B = adjB.parent; generic_matmatmul!(C, 'N', 'C', A, B)) + +*(adjA::Adjoint{<:Any,<:AbstractMatrix}, adjB::Adjoint{<:Any,<:AbstractMatrix}) = + (A = adjA.parent; B = adjB.parent; Ac_mul_Bc!(similar(B, promote_op(matprod, eltype(A), eltype(B)), (size(A,2), size(B,1))), A, B)) +mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = + (A = adjA.parent; B = adjB.parent; gemm_wrapper!(C, 'C', 'C', A, B)) +mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = + (A = adjA.parent; B = adjB.parent; generic_matmatmul!(C, 'C', 'C', A, B)) +mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + (A = adjA.parent; B = transB.parent; generic_matmatmul!(C, 'C', 'T', A, B)) # Supporting functions for matrix multiplication function copytri!(A::AbstractMatrix, uplo::Char, conjugate::Bool=false) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index cb3acee4804707..6f544a9bb545de 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -331,6 +331,14 @@ mul!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) *(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::AbstractMatrix) = adjA.parent * B *(A::AbstractMatrix, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent +# ambiguities with transposed AbstractMatrix methods in linalg/matmul.jl +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = transA.parent * transB.parent +*(transA::Transpose{<:Any,<:RealHermSymComplexSym}, transB::Transpose{<:Any,<:RealHermSymComplexHerm}) = transA.parent * transB +*(transA::Transpose{<:Any,<:RealHermSymComplexHerm}, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = transA * transB.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = adjA.parent * adjB.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexSym}, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = adjA * adjB.parent +*(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, adjB::Adjoint{<:Any,<:RealHermSymComplexSym}) = adjA.parent * adjB + # ambiguities with RowVector *(A::RowVector, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent *(A::RowVector, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent From e41efab2ef811dd960321542fa9cd6e3d38064f3 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 6 Dec 2017 09:46:21 -0800 Subject: [PATCH 18/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/triangular.jl with de-jazzed passthroughs. --- base/deprecated.jl | 220 ++++++++++++++ base/linalg/factorization.jl | 32 -- base/linalg/linalg.jl | 10 + base/linalg/triangular.jl | 568 +++++++++++++++++++++++------------ 4 files changed, 598 insertions(+), 232 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index ee4a0d9163f87b..fb82ee30f68b4c 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2476,6 +2476,226 @@ end At_mul_B(x::StridedVector{T}, y::StridedVector{T}) where {T<:BlasComplex} = *(Transpose(x), y) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/triangular.jl, to deprecate +@eval Base.LinAlg begin + A_mul_Bc(A::AbstractTriangular, B::AbstractTriangular) = *(A, Adjoint(B)) + A_mul_Bt(A::AbstractTriangular, B::AbstractTriangular) = *(A, Transpose(B)) + Ac_mul_B(A::AbstractTriangular, B::AbstractTriangular) = *(Adjoint(A), B) + At_mul_B(A::AbstractTriangular, B::AbstractTriangular) = *(Transpose(A), B) + Ac_ldiv_B(A::Union{UpperTriangular,LowerTriangular}, B::RowVector) = \(Adjoint(A), B) + Ac_ldiv_B(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::RowVector) = \(Adjoint(A), B) + At_ldiv_B(A::Union{UpperTriangular,LowerTriangular}, B::RowVector) = \(Transpose(A), B) + At_ldiv_B(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::RowVector) = \(Transpose(A), B) + A_rdiv_Bc(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = /(rowvec, Adjoint(A)) + A_rdiv_Bc(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = /(rowvec, Adjoint(A)) + A_rdiv_Bt(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = /(rowvec, Transpose(A)) + A_rdiv_Bt(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = /(rowvec, Transpose(A)) + A_mul_Bt(rowvec::RowVector, A::AbstractTriangular) = *(rowvec, Transpose(A)) + A_mul_Bt(A::AbstractTriangular, rowvec::RowVector) = *(A, Transpose(rowvec)) + At_mul_Bt(A::AbstractTriangular, rowvec::RowVector) = *(Transpose(A), Transpose(rowvec)) + A_mul_Bc(rowvec::RowVector, A::AbstractTriangular) = *(rowvec, Adjoint(A)) + A_mul_Bc(A::AbstractTriangular, rowvec::RowVector) = *(A, Adjoint(rowvec)) + Ac_mul_Bc(A::AbstractTriangular, rowvec::RowVector) = *(Adjoint(A), Adjoint(rowvec)) + Ac_mul_B(A::AbstractMatrix, B::AbstractTriangular) = *(Adjoint(A), B) + At_mul_B(A::AbstractMatrix, B::AbstractTriangular) = *(Transpose(A), B) + A_mul_Bc(A::AbstractTriangular, B::AbstractMatrix) = *(A, Adjoint(B)) + A_mul_Bt(A::AbstractTriangular, B::AbstractMatrix) = *(A, Transpose(B)) + Ac_mul_Bc(A::AbstractTriangular, B::AbstractTriangular) = *(Adjoint(A), Adjoint(B)) + Ac_mul_Bc(A::AbstractTriangular, B::AbstractMatrix) = *(Adjoint(A), Adjoint(B)) + Ac_mul_Bc(A::AbstractMatrix, B::AbstractTriangular) = *(Adjoint(A), Adjoint(B)) + At_mul_Bt(A::AbstractTriangular, B::AbstractTriangular) = *(Transpose(A), Transpose(B)) + At_mul_Bt(A::AbstractTriangular, B::AbstractMatrix) = *(Transpose(A), Transpose(B)) + At_mul_Bt(A::AbstractMatrix, B::AbstractTriangular) = *(Transpose(A), Transpose(B)) + A_mul_Bc!(A::UpperTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = mul!(A, Adjoint(B)) + A_mul_Bc!(A::LowerTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = mul!(A, Adjoint(B)) + A_mul_Bt!(A::UpperTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = mul!(A, Transpose(B)) + A_mul_Bt!(A::LowerTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = mul!(A, Transpose(B)) + A_rdiv_Bc!(A::UpperTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = rdiv!(A, Adjoint(B)) + A_rdiv_Bc!(A::LowerTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = rdiv!(A, Adjoint(B)) + A_rdiv_Bt!(A::UpperTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = rdiv!(A, Transpose(B)) + A_rdiv_Bt!(A::LowerTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = rdiv!(A, Transpose(B)) + A_rdiv_B!(A::UpperTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = rdiv!(A, B) + A_rdiv_B!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = rdiv!(A, B) + Ac_mul_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) = mul!(Adjoint(A), B) + Ac_mul_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) = mul!(Adjoint(A), B) + At_mul_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) = mul!(Transpose(A), B) + At_mul_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) = mul!(Transpose(A), B) + Ac_ldiv_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) = ldiv!(Adjoint(A), B) + Ac_ldiv_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) = ldiv!(Adjoint(A), B) + At_ldiv_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) = ldiv!(Transpose(A), B) + At_ldiv_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) = ldiv!(Transpose(A), B) + A_rdiv_Bt!(A::StridedMatrix, B::UnitLowerTriangular) = rdiv!(A, Transpose(B)) + A_rdiv_Bt!(A::StridedMatrix, B::LowerTriangular) = rdiv!(A, Transpose(B)) + A_rdiv_Bt!(A::StridedMatrix, B::UnitUpperTriangular) = rdiv!(A, Transpose(B)) + A_rdiv_Bt!(A::StridedMatrix, B::UpperTriangular) = rdiv!(A, Transpose(B)) + A_rdiv_Bc!(A::StridedMatrix, B::UnitLowerTriangular) = rdiv!(A, Adjoint(B)) + A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) = rdiv!(A, Adjoint(B)) + A_rdiv_Bc!(A::StridedMatrix, B::UnitUpperTriangular) = rdiv!(A, Adjoint(B)) + A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) = rdiv!(A, Adjoint(B)) + A_rdiv_B!(A::StridedMatrix, B::UnitLowerTriangular) = rdiv!(A, B) + A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) = rdiv!(A, B) + A_rdiv_B!(A::StridedMatrix, B::UnitUpperTriangular) = rdiv!(A, B) + A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) = rdiv!(A, B) + Ac_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Adjoint(A), b, x) + Ac_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Adjoint(A), b, x) + Ac_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Adjoint(A), b, x) + Ac_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Adjoint(A), b, x) + At_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Transpose(A), b, x) + At_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Transpose(A), b, x) + At_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Transpose(A), b, x) + At_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b) = ldiv!(Transpose(A), b, x) + A_mul_Bt!(A::StridedMatrix, B::UnitLowerTriangular) = mul!(A, Transpose(B)) + A_mul_Bt!(A::StridedMatrix, B::LowerTriangular) = mul!(A, Transpose(B)) + A_mul_Bt!(A::StridedMatrix, B::UnitUpperTriangular) = mul!(A, Transpose(B)) + A_mul_Bt!(A::StridedMatrix, B::UpperTriangular) = mul!(A, Transpose(B)) + A_mul_Bc!(A::StridedMatrix, B::UnitLowerTriangular) = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix, B::UnitUpperTriangular) = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) = mul!(A, Adjoint(B)) + A_mul_B!(A::StridedMatrix, B::UnitLowerTriangular) = mul!(A, B) + A_mul_B!(A::StridedMatrix, B::LowerTriangular) = mul!(A, B) + A_mul_B!(A::StridedMatrix, B::UnitUpperTriangular) = mul!(A, B) + A_mul_B!(A::StridedMatrix, B::UpperTriangular) = mul!(A, B) + At_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) = mul!(Transpose(A), B) + At_mul_B!(A::LowerTriangular, B::StridedVecOrMat) = mul!(Transpose(A), B) + At_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) = mul!(Transpose(A), B) + At_mul_B!(A::UpperTriangular, B::StridedVecOrMat) = mul!(Transpose(A), B) + Ac_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) = mul!(Adjoint(A), B) + Ac_mul_B!(A::LowerTriangular, B::StridedVecOrMat) = mul!(Adjoint(A), B) + Ac_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) = mul!(Adjoint(A), B) + Ac_mul_B!(A::UpperTriangular, B::StridedVecOrMat) = mul!(Adjoint(A), B) + A_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) = mul!(A, B) + A_mul_B!(A::LowerTriangular, B::StridedVecOrMat) = mul!(A, B) + A_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) = mul!(A, B) + A_mul_B!(A::UpperTriangular, B::StridedVecOrMat) = mul!(A, B) + A_mul_B!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, A, B) + A_mul_B!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, A, B) + Ac_mul_B!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = mul!(C, Adjoint(A), B) + Ac_mul_B!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, Adjoint(A), B) + Ac_mul_B!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, Adjoint(A), B) + At_mul_B!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = mul!(C, Transpose(A), B) + At_mul_B!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, Transpose(A), B) + At_mul_B!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, Transpose(A), B) + A_mul_B!(A::Tridiagonal, B::AbstractTriangular) = mul!(A, B) + A_mul_B!(C::AbstractMatrix, A::AbstractTriangular, B::Tridiagonal) = mul!(C, A, B) + A_mul_B!(C::AbstractMatrix, A::Tridiagonal, B::AbstractTriangular) = mul!(C, A, B) + A_mul_Bt!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, A, Transpose(B)) + A_mul_Bc!(C::AbstractMatrix, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, A, Adjoint(B)) + A_mul_Bc!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(C, A, Adjoint(B)) +end +for mat in (:AbstractVector, :AbstractMatrix) + @eval Base.LinAlg begin + Ac_mul_B(A::AbstractTriangular, B::$mat) = *(Adjoint(A), B) + At_mul_B(A::AbstractTriangular, B::$mat) = *(Transpose(A), B) + Ac_ldiv_B(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::$mat) = \(Adjoint(A), B) + At_ldiv_B(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::$mat) = \(Transpose(A), B) + Ac_ldiv_B(A::Union{UpperTriangular,LowerTriangular}, B::$mat) = \(Adjoint(A), B) + At_ldiv_B(A::Union{UpperTriangular,LowerTriangular}, B::$mat) = \(Transpose(A), B) + A_rdiv_Bc(A::$mat, B::Union{UnitUpperTriangular, UnitLowerTriangular}) = /(A, Adjoint(B)) + A_rdiv_Bt(A::$mat, B::Union{UnitUpperTriangular, UnitLowerTriangular}) = /(A, Transpose(B)) + A_rdiv_Bc(A::$mat, B::Union{UpperTriangular,LowerTriangular}) = /(A, Adjoint(B)) + A_rdiv_Bt(A::$mat, B::Union{UpperTriangular,LowerTriangular}) = /(A, Transpose(B)) + end +end +@eval Base.LinAlg begin + A_mul_Bc(A::AbstractMatrix, B::AbstractTriangular) = *(A, Adjoint(B)) + A_mul_Bt(A::AbstractMatrix, B::AbstractTriangular) = *(A, Transpose(B)) +end +for (f, op, transform) in ( + (:A_mul_Bc, :*, :Adjoint), + (:A_mul_Bt, :*, :Transpose), + (:A_rdiv_Bc, :/, :Adjoint), + (:A_rdiv_Bt, :/, :Transpose)) + @eval Base.LinAlg begin + $f(A::LowerTriangular, B::UpperTriangular) = ($op)(A, ($transform)(B)) + $f(A::LowerTriangular, B::UnitUpperTriangular) = ($op)(A, ($transform)(B)) + $f(A::UpperTriangular, B::LowerTriangular) = ($op)(A, ($transform)(B)) + $f(A::UpperTriangular, B::UnitLowerTriangular) = ($op)(A, ($transform)(B)) + end +end +for (f, op, transform) in ( + (:Ac_mul_B, :*, :Adjoint), + (:At_mul_B, :*, :Transpose), + (:Ac_ldiv_B, :\, :Adjoint), + (:At_ldiv_B, :\, :Transpose)) + @eval Base.LinAlg begin + ($f)(A::UpperTriangular, B::LowerTriangular) = ($op)(($transform)(A), B) + ($f)(A::UnitUpperTriangular, B::LowerTriangular) = ($op)(($transform)(A), B) + ($f)(A::LowerTriangular, B::UpperTriangular) = ($op)(($transform)(A), B) + ($f)(A::UnitLowerTriangular, B::UpperTriangular) = ($op)(($transform)(A), B) + end +end +for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), + (:UnitLowerTriangular, 'L', 'U'), + (:UpperTriangular, 'U', 'N'), + (:UnitUpperTriangular, 'U', 'U')) + @eval Base.LinAlg begin + # Vector multiplication + A_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = mul!(A, b) + At_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = mul!(Transpose(A), b) + Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasReal} = mul!(Adjoint(A), b) + Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasComplex} = mul!(Adjoint(A), b) + + # Matrix multiplication + A_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = mul!(A, B) + A_mul_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = mul!(A, B) + + At_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = mul!(Transpose(A), B) + Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = mul!(Adjoint(A), B) + Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = mul!(Adjoint(A), B) + + A_mul_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = mul!(A, Transpose(B)) + A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = mul!(A, Adjoint(B)) + A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = mul!(A, Adjoint(B)) + + # Left division + A_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(A, B) + At_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = ldiv!(Transpose(A), B) + Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasReal} = ldiv!(Adjoint(A), B) + Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = ldiv!(Adjoint(A), B) + + # Right division + A_rdiv_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = rdiv!(A, B) + A_rdiv_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = rdiv!(A, Transpose(B)) + A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = rdiv!(A, Adjoint(B)) + A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = rdiv!(A, Adjoint(B)) + end +end +@eval Base.LinAlg begin + """ + A_ldiv_B!([Y,] A, B) -> Y + + Compute `A \\ B` in-place and store the result in `Y`, returning the result. + If only two arguments are passed, then `A_ldiv_B!(A, B)` overwrites `B` with + the result. + + The argument `A` should *not* be a matrix. Rather, instead of matrices it should be a + factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). + The reason for this is that factorization itself is both expensive and typically allocates memory + (although it can also be done in-place via, e.g., [`lufact!`](@ref)), + and performance-critical situations requiring `A_ldiv_B!` usually also require fine-grained + control over the factorization of `A`. + """ + A_ldiv_B! + + """ + Ac_ldiv_B!([Y,] A, B) -> Y + + Similar to [`A_ldiv_B!`](@ref), but return ``Aᴴ`` \\ ``B``, + computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). + """ + Ac_ldiv_B! + + """ + At_ldiv_B!([Y,] A, B) -> Y + + Similar to [`A_ldiv_B!`](@ref), but return ``Aᵀ`` \\ ``B``, + computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). + """ + At_ldiv_B! +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 8003e5aca721e5..1e7e070bc8e3fc 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -85,35 +85,3 @@ ldiv!(Y::AbstractVecOrMat, transA::Transpose{<:Any,<:Factorization}, B::Abstract # fallback methods for transposed solves \(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; Ac_ldiv_B(F, B)) \(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(Ac_ldiv_B(F, conj.(B)))) - -""" - A_ldiv_B!([Y,] A, B) -> Y - -Compute `A \\ B` in-place and store the result in `Y`, returning the result. -If only two arguments are passed, then `A_ldiv_B!(A, B)` overwrites `B` with -the result. - -The argument `A` should *not* be a matrix. Rather, instead of matrices it should be a -factorization object (e.g. produced by [`factorize`](@ref) or [`cholfact`](@ref)). -The reason for this is that factorization itself is both expensive and typically allocates memory -(although it can also be done in-place via, e.g., [`lufact!`](@ref)), -and performance-critical situations requiring `A_ldiv_B!` usually also require fine-grained -control over the factorization of `A`. -""" -A_ldiv_B! - -""" - Ac_ldiv_B!([Y,] A, B) -> Y - -Similar to [`A_ldiv_B!`](@ref), but return ``Aᴴ`` \\ ``B``, -computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). -""" -Ac_ldiv_B! - -""" - At_ldiv_B!([Y,] A, B) -> Y - -Similar to [`A_ldiv_B!`](@ref), but return ``Aᵀ`` \\ ``B``, -computing the result in-place in `Y` (or overwriting `B` if `Y` is not supplied). -""" -At_ldiv_B! diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 3ecb8834f38fd6..fb01e70f3c3fc4 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -237,6 +237,16 @@ function char_uplo(uplo::Symbol) end end +# shims to maintain existence of names in A_mul_B deprecation process +function Ac_mul_B! end +function Ac_mul_B! end +function At_mul_B! end +function A_ldiv_B! end +function At_ldiv_B! end +function Ac_ldiv_B! end +function A_rdiv_B! end +function A_rdiv_Bc! end + copy_oftype(A::AbstractArray{T}, ::Type{T}) where {T} = copy(A) copy_oftype(A::AbstractArray{T,N}, ::Type{S}) where {T,N,S} = convert(AbstractArray{S,N}, A) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index e1b62b6e61c1c7..9fb50091cffa7c 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -443,20 +443,33 @@ scale!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = scale!(A,c) # BlasFloat routines # ###################### -A_mul_B!(A::Tridiagonal, B::AbstractTriangular) = A*full!(B) -A_mul_B!(C::AbstractMatrix, A::AbstractTriangular, B::Tridiagonal) = A_mul_B!(C, copy!(similar(parent(A)), A), B) -A_mul_B!(C::AbstractMatrix, A::Tridiagonal, B::AbstractTriangular) = A_mul_B!(C, A, copy!(similar(parent(B)), B)) -A_mul_Bt!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, transpose!(C, B)) -A_mul_Bc!(C::AbstractMatrix, A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, adjoint!(C, B)) -A_mul_Bc!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, adjoint!(C, B)) -# The three methods are neceesary to avoid ambiguities with definitions in matmul.jl -for f in (:A_mul_B!, :Ac_mul_B!, :At_mul_B!) - @eval begin - ($f)(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = ($f)(A, copy!(C, B)) - ($f)(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = ($f)(A, copy!(C, B)) - ($f)(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = ($f)(A, copy!(C, B)) - end -end +mul!(A::Tridiagonal, B::AbstractTriangular) = A*full!(B) +mul!(C::AbstractMatrix, A::AbstractTriangular, B::Tridiagonal) = A_mul_B!(C, copy!(similar(parent(A)), A), B) +mul!(C::AbstractMatrix, A::Tridiagonal, B::AbstractTriangular) = A_mul_B!(C, A, copy!(similar(parent(B)), B)) +mul!(C::AbstractVector, A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + (B = transB.parent; A_mul_B!(A, transpose!(C, B))) +mul!(C::AbstractMatrix, A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractVecOrMat}) = + (B = transB.parent; A_mul_B!(A, transpose!(C, B))) +mul!(C::AbstractMatrix, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = + (B = adjB.parent; A_mul_B!(A, adjoint!(C, B))) +mul!(C::AbstractVecOrMat, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = + (B = adjB.parent; A_mul_B!(A, adjoint!(C, B))) +# The three methods for each op are neceesary to avoid ambiguities with definitions in matmul.jl +mul!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = A_mul_B!(A, copy!(C, B)) +mul!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, copy!(C, B)) +mul!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, copy!(C, B)) +mul!(C::AbstractVector , adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVector) = + (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) +mul!(C::AbstractMatrix , adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = + (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) +mul!(C::AbstractVecOrMat, adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = + (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) +mul!(C::AbstractVector , transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVector) = + (A = transA.parent; At_mul_B!(A, copy!(C, B))) +mul!(C::AbstractMatrix , transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = + (A = transA.parent; At_mul_B!(A, copy!(C, B))) +mul!(C::AbstractVecOrMat, transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = + (A = transA.parent; At_mul_B!(A, copy!(C, B))) for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), (:UnitLowerTriangular, 'L', 'U'), @@ -464,54 +477,54 @@ for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), (:UnitUpperTriangular, 'U', 'U')) @eval begin # Vector multiplication - A_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = + mul!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = BLAS.trmv!($uploc, 'N', $isunitc, A.data, b) - At_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = - BLAS.trmv!($uploc, 'T', $isunitc, A.data, b) - Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasReal} = - BLAS.trmv!($uploc, 'T', $isunitc, A.data, b) - Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasComplex} = - BLAS.trmv!($uploc, 'C', $isunitc, A.data, b) + mul!(transA::Transpose{<:Any,<:$t{T,<:StridedMatrix}}, b::StridedVector{T}) where {T<:BlasFloat} = + (A = transA.parent; BLAS.trmv!($uploc, 'T', $isunitc, A.data, b)) + mul!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, b::StridedVector{T}) where {T<:BlasReal} = + (A = adjA.parent; BLAS.trmv!($uploc, 'T', $isunitc, A.data, b)) + mul!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, b::StridedVector{T}) where {T<:BlasComplex} = + (A = adjA.parent; BLAS.trmv!($uploc, 'C', $isunitc, A.data, b)) # Matrix multiplication - A_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = + mul!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = BLAS.trmm!('L', $uploc, 'N', $isunitc, one(T), A.data, B) - A_mul_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = + mul!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trmm!('R', $uploc, 'N', $isunitc, one(T), B.data, A) - At_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = - BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B) - Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = - BLAS.trmm!('L', $uploc, 'C', $isunitc, one(T), A.data, B) - Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = - BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B) + mul!(transA::Transpose{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedMatrix{T}) where {T<:BlasFloat} = + (A = transA.parent; BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B)) + mul!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedMatrix{T}) where {T<:BlasComplex} = + (A = adjA.parent; BLAS.trmm!('L', $uploc, 'C', $isunitc, one(T), A.data, B)) + mul!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedMatrix{T}) where {T<:BlasReal} = + (A = adjA.parent; BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B)) - A_mul_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = - BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = - BLAS.trmm!('R', $uploc, 'C', $isunitc, one(T), B.data, A) - A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = - BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) + mul!(A::StridedMatrix{T}, transB::Transpose{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasFloat} = + (B = transB.parent; BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A)) + mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasComplex} = + (B = adjB.parent; BLAS.trmm!('R', $uploc, 'C', $isunitc, one(T), B.data, A)) + mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasReal} = + (B = adjB.parent; BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A)) # Left division - A_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = + ldiv!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.trtrs!($uploc, 'N', $isunitc, A.data, B) - At_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = - LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B) - Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasReal} = - LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B) - Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = - LAPACK.trtrs!($uploc, 'C', $isunitc, A.data, B) + ldiv!(transA::Transpose{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = + (A = transA.parent; LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B)) + ldiv!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasReal} = + (A = adjA.parent; LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B)) + ldiv!(adjA::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = + (A = adjA.parent; LAPACK.trtrs!($uploc, 'C', $isunitc, A.data, B)) # Right division - A_rdiv_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = + rdiv!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trsm!('R', $uploc, 'N', $isunitc, one(T), B.data, A) - A_rdiv_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = - BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = - BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = - BLAS.trsm!('R', $uploc, 'C', $isunitc, one(T), B.data, A) + rdiv!(A::StridedMatrix{T}, transB::Transpose{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasFloat} = + (B = transB.parent; BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A)) + rdiv!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasReal} = + (B = adjB.parent; BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A)) + rdiv!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:$t{T,<:StridedMatrix}}) where {T<:BlasComplex} = + (B = adjB.parent; BLAS.trsm!('R', $uploc, 'C', $isunitc, one(T), B.data, A)) # Matrix inverse inv!(A::$t{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = @@ -626,7 +639,7 @@ for (t, unitt) in ((UpperTriangular, UnitUpperTriangular), end ## Generic triangular multiplication -function A_mul_B!(A::UpperTriangular, B::StridedVecOrMat) +function mul!(A::UpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -642,7 +655,7 @@ function A_mul_B!(A::UpperTriangular, B::StridedVecOrMat) end B end -function A_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) +function mul!(A::UnitUpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -659,7 +672,7 @@ function A_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) B end -function A_mul_B!(A::LowerTriangular, B::StridedVecOrMat) +function mul!(A::LowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -675,7 +688,7 @@ function A_mul_B!(A::LowerTriangular, B::StridedVecOrMat) end B end -function A_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) +function mul!(A::UnitLowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -692,7 +705,8 @@ function A_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) B end -function Ac_mul_B!(A::UpperTriangular, B::StridedVecOrMat) +function mul!(adjA::Adjoint{<:Any,<:UpperTriangular}, B::StridedVecOrMat) + A = adjA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -708,7 +722,8 @@ function Ac_mul_B!(A::UpperTriangular, B::StridedVecOrMat) end B end -function Ac_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) +function mul!(adjA::Adjoint{<:Any,<:UnitUpperTriangular}, B::StridedVecOrMat) + A = adjA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -725,7 +740,8 @@ function Ac_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) B end -function Ac_mul_B!(A::LowerTriangular, B::StridedVecOrMat) +function mul!(adjA::Adjoint{<:Any,<:LowerTriangular}, B::StridedVecOrMat) + A = adjA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -741,7 +757,8 @@ function Ac_mul_B!(A::LowerTriangular, B::StridedVecOrMat) end B end -function Ac_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) +function mul!(adjA::Adjoint{<:Any,<:UnitLowerTriangular}, B::StridedVecOrMat) + A = adjA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -758,7 +775,8 @@ function Ac_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) B end -function At_mul_B!(A::UpperTriangular, B::StridedVecOrMat) +function mul!(transA::Transpose{<:Any,<:UpperTriangular}, B::StridedVecOrMat) + A = transA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -774,7 +792,8 @@ function At_mul_B!(A::UpperTriangular, B::StridedVecOrMat) end B end -function At_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) +function mul!(transA::Transpose{<:Any,<:UnitUpperTriangular}, B::StridedVecOrMat) + A = transA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -791,7 +810,8 @@ function At_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) B end -function At_mul_B!(A::LowerTriangular, B::StridedVecOrMat) +function mul!(transA::Transpose{<:Any,<:LowerTriangular}, B::StridedVecOrMat) + A = transA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -807,7 +827,8 @@ function At_mul_B!(A::LowerTriangular, B::StridedVecOrMat) end B end -function At_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) +function mul!(transA::Transpose{<:Any,<:UnitLowerTriangular}, B::StridedVecOrMat) + A = transA.parent m, n = size(B, 1), size(B, 2) if m != size(A, 1) throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) @@ -824,7 +845,7 @@ function At_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) B end -function A_mul_B!(A::StridedMatrix, B::UpperTriangular) +function mul!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -840,7 +861,7 @@ function A_mul_B!(A::StridedMatrix, B::UpperTriangular) end A end -function A_mul_B!(A::StridedMatrix, B::UnitUpperTriangular) +function mul!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -857,7 +878,7 @@ function A_mul_B!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_mul_B!(A::StridedMatrix, B::LowerTriangular) +function mul!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -873,7 +894,7 @@ function A_mul_B!(A::StridedMatrix, B::LowerTriangular) end A end -function A_mul_B!(A::StridedMatrix, B::UnitLowerTriangular) +function mul!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -890,7 +911,8 @@ function A_mul_B!(A::StridedMatrix, B::UnitLowerTriangular) A end -function A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) +function mul!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UpperTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -906,7 +928,8 @@ function A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) end A end -function A_mul_Bc!(A::StridedMatrix, B::UnitUpperTriangular) +function mul!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UnitUpperTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -923,7 +946,8 @@ function A_mul_Bc!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) +function mul!(A::StridedMatrix, adjB::Adjoint{<:Any,<:LowerTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -939,7 +963,8 @@ function A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) end A end -function A_mul_Bc!(A::StridedMatrix, B::UnitLowerTriangular) +function mul!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UnitLowerTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -956,7 +981,8 @@ function A_mul_Bc!(A::StridedMatrix, B::UnitLowerTriangular) A end -function A_mul_Bt!(A::StridedMatrix, B::UpperTriangular) +function mul!(A::StridedMatrix, transB::Transpose{<:Any,<:UpperTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -972,7 +998,8 @@ function A_mul_Bt!(A::StridedMatrix, B::UpperTriangular) end A end -function A_mul_Bt!(A::StridedMatrix, B::UnitUpperTriangular) +function mul!(A::StridedMatrix, transB::Transpose{<:Any,<:UnitUpperTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -989,7 +1016,8 @@ function A_mul_Bt!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_mul_Bt!(A::StridedMatrix, B::LowerTriangular) +function mul!(A::StridedMatrix, transB::Transpose{<:Any,<:LowerTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1005,7 +1033,8 @@ function A_mul_Bt!(A::StridedMatrix, B::LowerTriangular) end A end -function A_mul_Bt!(A::StridedMatrix, B::UnitLowerTriangular) +function mul!(A::StridedMatrix, transB::Transpose{<:Any,<:UnitLowerTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1086,7 +1115,8 @@ function naivesub!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector end # in the following transpose and conjugate transpose naive substitution variants, # accumulating in z rather than b[j] significantly improves performance as of Dec 2015 -function At_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(transA::Transpose{<:Any,<:LowerTriangular}, b::AbstractVector, x::AbstractVector = b) + A = transA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1101,7 +1131,8 @@ function At_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b end x end -function At_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(transA::Transpose{<:Any,<:UnitLowerTriangular}, b::AbstractVector, x::AbstractVector = b) + A = transA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1115,7 +1146,8 @@ function At_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector end x end -function At_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(transA::Transpose{<:Any,<:UpperTriangular}, b::AbstractVector, x::AbstractVector = b) + A = transA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1130,7 +1162,8 @@ function At_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b end x end -function At_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(transA::Transpose{<:Any,<:UnitUpperTriangular}, b::AbstractVector, x::AbstractVector = b) + A = transA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1144,7 +1177,8 @@ function At_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector end x end -function Ac_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(adjA::Adjoint{<:Any,<:LowerTriangular}, b::AbstractVector, x::AbstractVector = b) + A = adjA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1159,7 +1193,8 @@ function Ac_ldiv_B!(A::LowerTriangular, b::AbstractVector, x::AbstractVector = b end x end -function Ac_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(adjA::Adjoint{<:Any,<:UnitLowerTriangular}, b::AbstractVector, x::AbstractVector = b) + A = adjA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1173,7 +1208,8 @@ function Ac_ldiv_B!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector end x end -function Ac_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(adjA::Adjoint{<:Any,<:UpperTriangular}, b::AbstractVector, x::AbstractVector = b) + A = adjA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1188,7 +1224,8 @@ function Ac_ldiv_B!(A::UpperTriangular, b::AbstractVector, x::AbstractVector = b end x end -function Ac_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector = b) +function ldiv!(adjA::Adjoint{<:Any,<:UnitUpperTriangular}, b::AbstractVector, x::AbstractVector = b) + A = adjA.parent n = size(A, 1) if !(n == length(b) == length(x)) throw(DimensionMismatch("first dimension of left hand side A, $n, length of output x, $(length(x)), and length of right hand side b, $(length(b)), must be equal")) @@ -1203,7 +1240,7 @@ function Ac_ldiv_B!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector x end -function A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) +function rdiv!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1219,7 +1256,7 @@ function A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) end A end -function A_rdiv_B!(A::StridedMatrix, B::UnitUpperTriangular) +function rdiv!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1236,7 +1273,7 @@ function A_rdiv_B!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) +function rdiv!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1252,7 +1289,7 @@ function A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) end A end -function A_rdiv_B!(A::StridedMatrix, B::UnitLowerTriangular) +function rdiv!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1269,7 +1306,8 @@ function A_rdiv_B!(A::StridedMatrix, B::UnitLowerTriangular) A end -function A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) +function rdiv!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UpperTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1285,7 +1323,8 @@ function A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) end A end -function A_rdiv_Bc!(A::StridedMatrix, B::UnitUpperTriangular) +function rdiv!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UnitUpperTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1302,7 +1341,8 @@ function A_rdiv_Bc!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) +function rdiv!(A::StridedMatrix, adjB::Adjoint{<:Any,<:LowerTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1318,7 +1358,8 @@ function A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) end A end -function A_rdiv_Bc!(A::StridedMatrix, B::UnitLowerTriangular) +function rdiv!(A::StridedMatrix, adjB::Adjoint{<:Any,<:UnitLowerTriangular}) + B = adjB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1335,7 +1376,8 @@ function A_rdiv_Bc!(A::StridedMatrix, B::UnitLowerTriangular) A end -function A_rdiv_Bt!(A::StridedMatrix, B::UpperTriangular) +function rdiv!(A::StridedMatrix, transB::Transpose{<:Any,<:UpperTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1351,7 +1393,8 @@ function A_rdiv_Bt!(A::StridedMatrix, B::UpperTriangular) end A end -function A_rdiv_Bt!(A::StridedMatrix, B::UnitUpperTriangular) +function rdiv!(A::StridedMatrix, transB::Transpose{<:Any,<:UnitUpperTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1368,7 +1411,8 @@ function A_rdiv_Bt!(A::StridedMatrix, B::UnitUpperTriangular) A end -function A_rdiv_Bt!(A::StridedMatrix, B::LowerTriangular) +function rdiv!(A::StridedMatrix, transB::Transpose{<:Any,<:LowerTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1384,7 +1428,8 @@ function A_rdiv_Bt!(A::StridedMatrix, B::LowerTriangular) end A end -function A_rdiv_Bt!(A::StridedMatrix, B::UnitLowerTriangular) +function rdiv!(A::StridedMatrix, transB::Transpose{<:Any,<:UnitLowerTriangular}) + B = transB.parent m, n = size(A) if size(B, 1) != n throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) @@ -1401,28 +1446,44 @@ function A_rdiv_Bt!(A::StridedMatrix, B::UnitLowerTriangular) A end -for f in (:Ac_mul_B!, :At_mul_B!, :Ac_ldiv_B!, :At_ldiv_B!) - @eval begin - $f(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) = - UpperTriangular($f(A, triu!(B.data))) - $f(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) = - LowerTriangular($f(A, tril!(B.data))) - end -end - -A_rdiv_B!(A::UpperTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = +mul!(adjA::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = + (A = adjA.parent; UpperTriangular(Ac_mul_B!(A, triu!(B.data)))) +mul!(adjA::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = + (A = adjA.parent; LowerTriangular(Ac_mul_B!(A, tril!(B.data)))) +mul!(transA::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = + (A = transA.parent; UpperTriangular(At_mul_B!(A, triu!(B.data)))) +mul!(transA::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = + (A = transA.parent; LowerTriangular(At_mul_B!(A, tril!(B.data)))) +ldiv!(adjA::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = + (A = adjA.parent; UpperTriangular(Ac_ldiv_B!(A, triu!(B.data)))) +ldiv!(adjA::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = + (A = adjA.parent; LowerTriangular(Ac_ldiv_B!(A, tril!(B.data)))) +ldiv!(transA::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = + (A = transA.parent; UpperTriangular(At_ldiv_B!(A, triu!(B.data)))) +ldiv!(transA::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = + (A = transA.parent; LowerTriangular(At_ldiv_B!(A, tril!(B.data)))) + +rdiv!(A::UpperTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = UpperTriangular(A_rdiv_B!(triu!(A.data), B)) -A_rdiv_B!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = +rdiv!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = LowerTriangular(A_rdiv_B!(tril!(A.data), B)) -for f in (:A_mul_Bc!, :A_mul_Bt!, :A_rdiv_Bc!, :A_rdiv_Bt!) - @eval begin - $f(A::UpperTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = - UpperTriangular($f(triu!(A.data), B)) - $f(A::LowerTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = - LowerTriangular($f(tril!(A.data), B)) - end -end +mul!(A::UpperTriangular, adjB::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = + (B = adjB.parent; UpperTriangular(A_mul_Bc!(triu!(A.data), B))) +mul!(A::LowerTriangular, adjB::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = + (B = adjB.parent; LowerTriangular(A_mul_Bc!(tril!(A.data), B))) +mul!(A::UpperTriangular, transB::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = + (B = transB.parent; UpperTriangular(A_mul_Bt!(triu!(A.data), B))) +mul!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = + (B = transB.parent; LowerTriangular(A_mul_Bt!(tril!(A.data), B))) +rdiv!(A::UpperTriangular, adjB::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = + (B = adjB.parent; UpperTriangular(A_rdiv_Bc!(triu!(A.data), B))) +rdiv!(A::LowerTriangular, adjB::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = + (B = adjB.parent; LowerTriangular(A_rdiv_Bc!(tril!(A.data), B))) +rdiv!(A::UpperTriangular, transB::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = + (B = transB.parent; UpperTriangular(A_rdiv_Bt!(triu!(A.data), B))) +rdiv!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = + (B = transB.parent; LowerTriangular(A_rdiv_Bt!(tril!(A.data), B))) # Promotion ## Promotion methods in matmul don't apply to triangular multiplication since @@ -1471,18 +1532,23 @@ for (f1, f2) in ((:*, :A_mul_B!), (:\, :A_ldiv_B!)) end end -for (f1, f2) in ((:Ac_mul_B, :Ac_mul_B!), (:At_mul_B, :At_mul_B!), - (:Ac_ldiv_B, Ac_ldiv_B!), (:At_ldiv_B, :At_ldiv_B!)) +for (f1, f2, op, xform) in ( + (:Ac_mul_B, :Ac_mul_B!, :*, :Adjoint), + (:At_mul_B, :At_mul_B!, :*, :Transpose), + (:Ac_ldiv_B, :Ac_ldiv_B!, :\, :Adjoint), + (:At_ldiv_B, :At_ldiv_B!, :\, :Transpose)) @eval begin - function ($f1)(A::UpperTriangular, B::LowerTriangular) + function ($op)(xformA::($xform){<:Any,<:UpperTriangular}, B::LowerTriangular) + A = xformA.parent TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + ($f1)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copy!(BB, B) - return LowerTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) + return LowerTriangular(($f2)(convert(AbstractMatrix{TAB}, A), BB)) end - function ($f1)(A::UnitUpperTriangular, B::LowerTriangular) + function ($op)(xformA::($xform){<:Any,<:UnitUpperTriangular}, B::LowerTriangular) + A = xformA.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) @@ -1490,7 +1556,8 @@ for (f1, f2) in ((:Ac_mul_B, :Ac_mul_B!), (:At_mul_B, :At_mul_B!), return LowerTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) end - function ($f1)(A::LowerTriangular, B::UpperTriangular) + function ($op)(xformA::($xform){<:Any,<:LowerTriangular}, B::UpperTriangular) + A = xformA.parent TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + ($f1)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) @@ -1498,7 +1565,8 @@ for (f1, f2) in ((:Ac_mul_B, :Ac_mul_B!), (:At_mul_B, :At_mul_B!), return UpperTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) end - function ($f1)(A::UnitLowerTriangular, B::UpperTriangular) + function ($op)(xformA::($xform){<:Any,<:UnitLowerTriangular}, B::UpperTriangular) + A = xformA.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) @@ -1537,10 +1605,14 @@ function (/)(A::UpperTriangular, B::UnitUpperTriangular) return UpperTriangular(A_rdiv_B!(AA, convert(AbstractMatrix{TAB}, B))) end -for (f1, f2) in ((:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!), - (:A_rdiv_Bc, :A_rdiv_Bc!), (:A_rdiv_Bt, :A_rdiv_Bt!)) +for (f1, f2, op, xform) in ( + (:A_mul_Bc, :A_mul_Bc!, :*, :Adjoint), + (:A_mul_Bt, :A_mul_Bt!, :*, :Transpose), + (:A_rdiv_Bc, :A_rdiv_Bc!, :/, :Adjoint), + (:A_rdiv_Bt, :A_rdiv_Bt!, :/, :Transpose)) @eval begin - function $f1(A::LowerTriangular, B::UpperTriangular) + function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UpperTriangular}) + B = xformB.parent TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + ($f1)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) @@ -1548,7 +1620,8 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!), return LowerTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) end - function $f1(A::LowerTriangular, B::UnitUpperTriangular) + function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UnitUpperTriangular}) + B = xformB.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) @@ -1556,7 +1629,8 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!), return LowerTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) end - function $f1(A::UpperTriangular, B::LowerTriangular) + function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:LowerTriangular}) + B = xformB.parent TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + ($f1)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) @@ -1564,7 +1638,8 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!), return UpperTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) end - function $f1(A::UpperTriangular, B::UnitLowerTriangular) + function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:UnitLowerTriangular}) + B = xformB.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) @@ -1576,96 +1651,180 @@ end ## The general promotion methods -for (f, g) in ((:*, :A_mul_B!), (:Ac_mul_B, :Ac_mul_B!), (:At_mul_B, :At_mul_B!)) +function *(A::AbstractTriangular, B::AbstractTriangular) + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + A_mul_B!(convert(AbstractArray{TAB}, A), BB) +end +function *(adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractTriangular) + A = adjA.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + Ac_mul_B!(convert(AbstractArray{TAB}, A), BB) +end +function *(transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractTriangular) + A = transA.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + At_mul_B!(convert(AbstractArray{TAB}, A), BB) +end + +function *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractTriangular}) + B = adjB.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_mul_Bc!(AA, convert(AbstractArray{TAB}, B)) +end +function *(A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractTriangular}) + B = transB.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_mul_Bt!(AA, convert(AbstractArray{TAB}, B)) +end + +for mat in (:AbstractVector, :AbstractMatrix) + ### Multiplication with triangle to the left and hence rhs cannot be transposed. @eval begin - function ($f)(A::AbstractTriangular, B::AbstractTriangular) + function *(A::AbstractTriangular, B::$mat) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - ($g)(convert(AbstractArray{TAB}, A), BB) + A_mul_B!(convert(AbstractArray{TAB}, A), BB) end - end -end -for (f, g) in ((:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!)) - @eval begin - function ($f)(A::AbstractTriangular, B::AbstractTriangular) + function *(adjA::Adjoint{<:Any,<:AbstractTriangular}, B::$mat) + A = adjA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) - AA = similar(A, TAB, size(A)) - copy!(AA, A) - ($g)(AA, convert(AbstractArray{TAB}, B)) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + Ac_mul_B!(convert(AbstractArray{TAB}, A), BB) end - end -end - -for mat in (:AbstractVector, :AbstractMatrix) - -### Multiplication with triangle to the left and hence rhs cannot be transposed. -for (f, g) in ((:*, :A_mul_B!), (:Ac_mul_B, :Ac_mul_B!), (:At_mul_B, :At_mul_B!)) - @eval begin - function ($f)(A::AbstractTriangular, B::$mat) + function *(transA::Transpose{<:Any,<:AbstractTriangular}, B::$mat) + A = transA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - ($g)(convert(AbstractArray{TAB}, A), BB) + At_mul_B!(convert(AbstractArray{TAB}, A), BB) end end -end -### Left division with triangle to the left hence rhs cannot be transposed. No quotients. -for (f, g) in ((:\, :A_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!), (:At_ldiv_B, :At_ldiv_B!)) + ### Left division with triangle to the left hence rhs cannot be transposed. No quotients. @eval begin - function ($f)(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::$mat) + function \(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::$mat) + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + A_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + end + function \(adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, B::$mat) + A = adjA.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + Ac_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + end + function \(transA::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, B::$mat) + A = transA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - ($g)(convert(AbstractArray{TAB}, A), BB) + At_ldiv_B!(convert(AbstractArray{TAB}, A), BB) end end -end -### Left division with triangle to the left hence rhs cannot be transposed. Quotients. -for (f, g) in ((:\, :A_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!), (:At_ldiv_B, :At_ldiv_B!)) + ### Left division with triangle to the left hence rhs cannot be transposed. Quotients. @eval begin - function ($f)(A::Union{UpperTriangular,LowerTriangular}, B::$mat) + function \(A::Union{UpperTriangular,LowerTriangular}, B::$mat) + TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + A_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + end + function \(adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}, B::$mat) + A = adjA.parent + TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) + BB = similar(B, TAB, size(B)) + copy!(BB, B) + Ac_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + end + function \(transA::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}, B::$mat) + A = transA.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) BB = similar(B, TAB, size(B)) copy!(BB, B) - ($g)(convert(AbstractArray{TAB}, A), BB) + At_ldiv_B!(convert(AbstractArray{TAB}, A), BB) end end -end -### Multiplication with triangle to the right and hence lhs cannot be transposed. -for (f, g) in ((:*, :A_mul_B!), (:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!)) - mat != :AbstractVector && @eval begin - function ($f)(A::$mat, B::AbstractTriangular) + ### Right division with triangle to the right hence lhs cannot be transposed. No quotients. + @eval begin + function /(A::$mat, B::Union{UnitUpperTriangular, UnitLowerTriangular}) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - ($g)(AA, convert(AbstractArray{TAB}, B)) + A_rdiv_B!(AA, convert(AbstractArray{TAB}, B)) end - end -end -### Right division with triangle to the right hence lhs cannot be transposed. No quotients. -for (f, g) in ((:/, :A_rdiv_B!), (:A_rdiv_Bc, :A_rdiv_Bc!), (:A_rdiv_Bt, :A_rdiv_Bt!)) - @eval begin - function ($f)(A::$mat, B::Union{UnitUpperTriangular, UnitLowerTriangular}) + function /(A::$mat, adjB::Adjoint{<:Any,<:Union{UnitUpperTriangular, UnitLowerTriangular}}) + B = adjB.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_rdiv_Bc!(AA, convert(AbstractArray{TAB}, B)) + end + function /(A::$mat, transB::Transpose{<:Any,<:Union{UnitUpperTriangular, UnitLowerTriangular}}) + B = transB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - ($g)(AA, convert(AbstractArray{TAB}, B)) + A_rdiv_Bt!(AA, convert(AbstractArray{TAB}, B)) end end -end - -### Right division with triangle to the right hence lhs cannot be transposed. Quotients. -for (f, g) in ((:/, :A_rdiv_B!), (:A_rdiv_Bc, :A_rdiv_Bc!), (:A_rdiv_Bt, :A_rdiv_Bt!)) + ### Right division with triangle to the right hence lhs cannot be transposed. Quotients. @eval begin - function ($f)(A::$mat, B::Union{UpperTriangular,LowerTriangular}) + function /(A::$mat, B::Union{UpperTriangular,LowerTriangular}) + TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_rdiv_B!(AA, convert(AbstractArray{TAB}, B)) + end + function /(A::$mat, adjB::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) + B = adjB.parent + TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_rdiv_Bc!(AA, convert(AbstractArray{TAB}, B)) + end + function /(A::$mat, transB::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}) + B = transB.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) AA = similar(A, TAB, size(A)) copy!(AA, A) - ($g)(AA, convert(AbstractArray{TAB}, B)) + A_rdiv_Bt!(AA, convert(AbstractArray{TAB}, B)) end end end +### Multiplication with triangle to the right and hence lhs cannot be transposed. +# Only for AbstractMatrix, hence outside the above loop. +function *(A::AbstractMatrix, B::AbstractTriangular) + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_mul_B!(AA, convert(AbstractArray{TAB}, B)) +end +function *(A::AbstractMatrix, adjB::Adjoint{<:Any,<:AbstractTriangular}) + B = adjB.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_mul_Bc!(AA, convert(AbstractArray{TAB}, B)) +end +function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractTriangular}) + B = transB.parent + TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + A_mul_Bt!(AA, convert(AbstractArray{TAB}, B)) end # If these are not defined, they will fallback to the versions in matmul.jl @@ -1673,43 +1832,52 @@ end # below might compute an unnecessary copy. Eliminating the copy requires adding # all the promotion logic here once again. Since these methods are probably relatively # rare, we chose not to bother for now. -Ac_mul_B(A::AbstractMatrix, B::AbstractTriangular) = (*)(adjoint(A), B) -At_mul_B(A::AbstractMatrix, B::AbstractTriangular) = (*)(transpose(A), B) -A_mul_Bc(A::AbstractTriangular, B::AbstractMatrix) = (*)(A, adjoint(B)) -A_mul_Bt(A::AbstractTriangular, B::AbstractMatrix) = (*)(A, transpose(B)) -Ac_mul_Bc(A::AbstractTriangular, B::AbstractTriangular) = Ac_mul_B(A, B') -Ac_mul_Bc(A::AbstractTriangular, B::AbstractMatrix) = Ac_mul_B(A, B') -Ac_mul_Bc(A::AbstractMatrix, B::AbstractTriangular) = A_mul_Bc(A', B) -At_mul_Bt(A::AbstractTriangular, B::AbstractTriangular) = At_mul_B(A, B.') -At_mul_Bt(A::AbstractTriangular, B::AbstractMatrix) = At_mul_B(A, B.') -At_mul_Bt(A::AbstractMatrix, B::AbstractTriangular) = A_mul_Bt(A.', B) +*(adjA::Adjoint{<:Any,<:AbstractMatrix}, B::AbstractTriangular) = (*)(adjoint(adjA.parent), B) +*(transA::Transpose{<:Any,<:AbstractMatrix}, B::AbstractTriangular) = (*)(transpose(transA.parent), B) +*(A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractMatrix}) = (*)(A, adjoint(adjB.parent)) +*(A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractMatrix}) = (*)(A, transpose(transB.parent)) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractTriangular}) =Ac_mul_B(adjA.parent, adjB.parent') +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractMatrix}) = Ac_mul_B(adjA.parent, adjB.parent') +*(adjA::Adjoint{<:Any,<:AbstractMatrix}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = A_mul_Bc(adjA.parent', adjB.parent) +*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractTriangular}) = At_mul_B(transA.parent, transB.parent.') +*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractMatrix}) = At_mul_B(transA.parent, transB.parent.') +*(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractTriangular}) = A_mul_Bt(transA.parent.', transB.parent) # Specializations for RowVector @inline *(rowvec::RowVector, A::AbstractTriangular) = transpose(A * transpose(rowvec)) -@inline A_mul_Bt(rowvec::RowVector, A::AbstractTriangular) = transpose(A * transpose(rowvec)) -@inline A_mul_Bt(A::AbstractTriangular, rowvec::RowVector) = A * transpose(rowvec) -@inline At_mul_Bt(A::AbstractTriangular, rowvec::RowVector) = A.' * transpose(rowvec) -@inline A_mul_Bc(rowvec::RowVector, A::AbstractTriangular) = adjoint(A * adjoint(rowvec)) -@inline A_mul_Bc(A::AbstractTriangular, rowvec::RowVector) = A * adjoint(rowvec) -@inline Ac_mul_Bc(A::AbstractTriangular, rowvec::RowVector) = A' * adjoint(rowvec) +*(rowvec::RowVector, transA::Transpose{<:Any,<:AbstractTriangular}) = transpose(transA.parent * transpose(rowvec)) +*(A::AbstractTriangular, transrowvec::Transpose{<:Any,<:RowVector}) = A * transpose(transrowvec.parent) +*(transA::Transpose{<:Any,<:AbstractTriangular}, transrowvec::Transpose{<:Any,<:RowVector}) = transA.parent.' * transpose(transrowvec.parent) +*(rowvec::RowVector, adjA::Adjoint{<:Any,<:AbstractTriangular}) = adjoint(adjA.parent * adjoint(rowvec)) +*(A::AbstractTriangular, adjrowvec::Adjoint{<:Any,<:RowVector}) = A * adjoint(adjrowvec.parent) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjrowvec::Adjoint{<:Any,<:RowVector}) = adjA.parent' * adjoint(adjrowvec.parent) @inline /(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = transpose(transpose(A) \ transpose(rowvec)) @inline /(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = transpose(transpose(A) \ transpose(rowvec)) -@inline A_rdiv_Bt(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = transpose(A \ transpose(rowvec)) -@inline A_rdiv_Bt(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = transpose(A \ transpose(rowvec)) - -@inline A_rdiv_Bc(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = adjoint(A \ adjoint(rowvec)) -@inline A_rdiv_Bc(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = adjoint(A \ adjoint(rowvec)) +/(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = + transpose(transA.parent \ transpose(rowvec)) +/(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = + transpose(transA.parent \ transpose(rowvec)) +# ambiguity resolution with definitions in linalg/rowvector.jl +/(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = + /(rowvec, adjoint(adjA.parent)) +/(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = + /(rowvec, adjoint(adjA.parent)) + +rdiv(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = + adjoint(adjA.parent \ adjoint(rowvec)) +rdiv(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = + adjoint(adjA.parent \ adjoint(rowvec)) \(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) \(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -At_ldiv_B(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -At_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +\(::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +\(::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -Ac_ldiv_B(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -Ac_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +\(::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +\(::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) # Complex matrix power for upper triangular factor, see: # Higham and Lin, "A Schur-Padé algorithm for fractional powers of a Matrix", From 57183d2d4dde6bde5ec0075e75d6893b172280f5 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 6 Dec 2017 13:07:05 -0800 Subject: [PATCH 19/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/sparse/linalg.jl with de-jazzed passthroughs. --- base/deprecated.jl | 38 ++++++++ base/sparse/linalg.jl | 211 +++++++++++++++++++++++++++--------------- 2 files changed, 172 insertions(+), 77 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index fb82ee30f68b4c..ec7ff0a8035300 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2696,6 +2696,44 @@ end At_ldiv_B! end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/sparse/linalg.jl, to deprecate +@eval Base.SparseArrays begin + using Base.LinAlg: Adjoint, Transpose + Ac_ldiv_B(A::SparseMatrixCSC, B::RowVector) = \(Adjoint(A), B) + At_ldiv_B(A::SparseMatrixCSC, B::RowVector) = \(Transpose(A), B) + Ac_ldiv_B(A::SparseMatrixCSC, B::AbstractVecOrMat) = \(Adjoint(A), B) + At_ldiv_B(A::SparseMatrixCSC, B::AbstractVecOrMat) = \(Transpose(A), B) + A_rdiv_Bc!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where {T} = rdiv!(A, Adjoint(D)) + A_rdiv_Bt!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where {T} = rdiv!(A, Transpose(D)) + A_rdiv_B!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where {T} = rdiv!(A, D) + A_ldiv_B!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = ldiv!(L, B) + A_ldiv_B!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = ldiv!(U, B) + A_mul_Bt(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(A, Transpose(B)) + A_mul_Bc(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(A, Adjoint(B)) + At_mul_B(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(Transpose(A), B) + Ac_mul_B(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(Adjoint(A), B) + At_mul_Bt(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(Transpose(A), Transpose(B)) + Ac_mul_Bc(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = *(Adjoint(A), Adjoint(B)) + A_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = mul!(C, A, B) + Ac_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = mul!(C, Adjoint(A), B) + At_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = mul!(C, Transpose(A), B) + A_mul_B!(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) = mul!(α, A, B, β, C) + A_mul_B(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = *(A, x) + A_mul_B(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = *(A, B) + Ac_mul_B!(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) = mul!(α, Adjoint(A), B, β, C) + Ac_mul_B(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = *(Adjoint(A), x) + Ac_mul_B(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = *(Adjoint(A), B) + At_mul_B!(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) = mul!(α, Transpose(A), B, β, C) + At_mul_B(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = *(Transpose(A), x) + At_mul_B(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = *(Transpose(A), B) + A_mul_Bt(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(A, Transpose(B)) + A_mul_Bc(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(A, Adjoint(B)) + At_mul_B(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(Transpose(A), B) + Ac_mul_B(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(Adjoint(A),B) + At_mul_Bt(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(Transpose(A), Transpose(B)) + Ac_mul_Bc(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(Adjoint(A), Adjoint(B)) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 388a8f63f49229..a816e9d2a00eea 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -1,21 +1,24 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base.LinAlg: Adjoint, Transpose import Base.LinAlg: checksquare ## sparse matrix multiplication -function (*)(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} - (*)(sppromote(A, B)...) -end -for f in (:A_mul_Bt, :A_mul_Bc, - :At_mul_B, :Ac_mul_B, - :At_mul_Bt, :Ac_mul_Bc) - @eval begin - function ($f)(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} - ($f)(sppromote(A, B)...) - end - end -end +*(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = + *(sppromote(A, B)...) +*(A::SparseMatrixCSC{TvA,TiA}, transB::Transpose{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = + (B = transB.parent; A_mul_Bt(sppromote(A, B)...)) +*(A::SparseMatrixCSC{TvA,TiA}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = + (B = adjB.parent; A_mul_Bc(sppromote(A, B)...)) +*(transA::Transpose{<:Any,<:SparseMatrixCSC{TvA,TiA}}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = + (A = transA.parent; At_mul_B(sppromote(A, B)...)) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TvA,TiA}}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = + (A = adjA.parent; Ac_mul_B(sppromote(A, B)...)) +*(transA::Transpose{<:Any,<:SparseMatrixCSC{TvA,TiA}}, transB::Transpose{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = + (A = transA.parent; B = transB.parent; At_mul_Bt(sppromote(A, B)...)) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TvA,TiA}}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = + (A = adjA.parent; B = adjB.parent; Ac_mul_Bc(sppromote(A, B)...)) function sppromote(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} Tv = promote_type(TvA, TvB) @@ -27,60 +30,90 @@ end # In matrix-vector multiplication, the correct orientation of the vector is assumed. -for (f, op, transp) in ((:A_mul_B, :identity, false), - (:Ac_mul_B, :adjoint, true), - (:At_mul_B, :transpose, true)) - @eval begin - function $(Symbol(f,:!))(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) - if $transp - A.n == size(C, 1) || throw(DimensionMismatch()) - A.m == size(B, 1) || throw(DimensionMismatch()) - else - A.n == size(B, 1) || throw(DimensionMismatch()) - A.m == size(C, 1) || throw(DimensionMismatch()) - end - size(B, 2) == size(C, 2) || throw(DimensionMismatch()) - nzv = A.nzval - rv = A.rowval - if β != 1 - β != 0 ? scale!(C, β) : fill!(C, zero(eltype(C))) - end - for k = 1:size(C, 2) - for col = 1:A.n - if $transp - tmp = zero(eltype(C)) - @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) - tmp += $(op)(nzv[j])*B[rv[j],k] - end - C[col,k] += α*tmp - else - αxj = α*B[col,k] - @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) - C[rv[j], k] += nzv[j]*αxj - end - end - end +function mul!(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) + A.n == size(B, 1) || throw(DimensionMismatch()) + A.m == size(C, 1) || throw(DimensionMismatch()) + size(B, 2) == size(C, 2) || throw(DimensionMismatch()) + nzv = A.nzval + rv = A.rowval + if β != 1 + β != 0 ? scale!(C, β) : fill!(C, zero(eltype(C))) + end + for k = 1:size(C, 2) + for col = 1:A.n + αxj = α*B[col,k] + @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) + C[rv[j], k] += nzv[j]*αxj end - C end - - function $(f)(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} - T = promote_type(TA, Tx) - $(Symbol(f,:!))(one(T), A, x, zero(T), similar(x, T, A.n)) + end + C +end +*(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = + (T = promote_type(TA, Tx); A_mul_B!(one(T), A, x, zero(T), similar(x, T, A.m))) +*(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = + (T = promote_type(TA, Tx); A_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.m, size(B, 2))))) + +function mul!(α::Number, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) + A = adjA.parent + A.n == size(C, 1) || throw(DimensionMismatch()) + A.m == size(B, 1) || throw(DimensionMismatch()) + size(B, 2) == size(C, 2) || throw(DimensionMismatch()) + nzv = A.nzval + rv = A.rowval + if β != 1 + β != 0 ? scale!(C, β) : fill!(C, zero(eltype(C))) + end + for k = 1:size(C, 2) + for col = 1:A.n + tmp = zero(eltype(C)) + @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) + tmp += adjoint(nzv[j])*B[rv[j],k] + end + C[col,k] += α*tmp end - function $(f)(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} - T = promote_type(TA, Tx) - $(Symbol(f,:!))(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2)))) + end + C +end +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = + (A = adjA.parent; T = promote_type(TA, Tx); Ac_mul_B!(one(T), A, x, zero(T), similar(x, T, A.n))) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = + (A = adjA.parent; T = promote_type(TA, Tx); Ac_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2))))) + +function mul!(α::Number, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) + A = transA.parent + A.n == size(C, 1) || throw(DimensionMismatch()) + A.m == size(B, 1) || throw(DimensionMismatch()) + size(B, 2) == size(C, 2) || throw(DimensionMismatch()) + nzv = A.nzval + rv = A.rowval + if β != 1 + β != 0 ? scale!(C, β) : fill!(C, zero(eltype(C))) + end + for k = 1:size(C, 2) + for col = 1:A.n + tmp = zero(eltype(C)) + @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) + tmp += transpose(nzv[j])*B[rv[j],k] + end + C[col,k] += α*tmp end end + C end +*(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = + (A = transA.parent; T = promote_type(TA, Tx); At_mul_B!(one(T), A, x, zero(T), similar(x, T, A.n))) +*(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = + (A = transA.parent; T = promote_type(TA, Tx); At_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2))))) # For compatibility with dense multiplication API. Should be deleted when dense multiplication # API is updated to follow BLAS API. -A_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = A_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) -Ac_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = Ac_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) -At_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = At_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) - +mul!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = + A_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) +mul!(C::StridedVecOrMat, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat) = + (A = adjA.parent; Ac_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C)) +mul!(C::StridedVecOrMat, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat) = + (A = transA.parent; At_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C)) function (*)(X::StridedMatrix{TX}, A::SparseMatrixCSC{TvA,TiA}) where {TX,TvA,TiA} mX, nX = size(X) @@ -107,18 +140,18 @@ end # http://dl.acm.org/citation.cfm?id=355796 (*)(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = spmatmul(A,B) -for (f, opA, opB) in ((:A_mul_Bt, :identity, :transpose), - (:A_mul_Bc, :identity, :adjoint), - (:At_mul_B, :transpose, :identity), - (:Ac_mul_B, :adjoint, :identity), - (:At_mul_Bt, :transpose, :transpose), - (:Ac_mul_Bc, :adjoint, :adjoint)) - @eval begin - function ($f)(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} - spmatmul(($opA)(A), ($opB)(B)) - end - end -end +*(A::SparseMatrixCSC{Tv,Ti}, transB::Transpose{<:Any,<:SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = + (B = transB.parent; spmatmul(A, transpose(B))) +*(A::SparseMatrixCSC{Tv,Ti}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = + (B = adjB.parent; spmatmul(A, adjoint(B))) +*(transA::Transpose{<:Any,<:SparseMatrixCSC{Tv,Ti}}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = + (A = transA.parent; spmatmul(tranpsose(A), B)) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{Tv,Ti}}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = + (A = adjA.parent; spmatmul(adjoint(A), B)) +*(transA::Transpose{<:Any,<:SparseMatrixCSC{Tv,Ti}}, transB::Transpose{<:Any,<:SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = + (A = transA.parent; B = transB.parent; spmatmul(transpose(A), transpose(B))) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC{Tv,Ti}}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{Tv,Ti}}) where {Tv,Ti} = + (A = adjA.parent; B = adjB.parent; spmatmul(adjoint(A), adjoint(B))) function spmatmul(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}; sortindices::Symbol = :sortcols) where {Tv,Ti} @@ -268,13 +301,13 @@ function bwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat) B end -A_ldiv_B!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) -A_ldiv_B!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) +ldiv!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) +ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) (\)(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(L, Array(B)) (\)(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(U, Array(B)) -function A_rdiv_B!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T +function rdiv!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T dd = D.diag if (k = length(dd)) ≠ A.n throw(DimensionMismatch("size(A, 2)=$(A.n) should be size(D, 1)=$k")) @@ -292,8 +325,10 @@ function A_rdiv_B!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T A end -A_rdiv_Bc!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, conj(D)) -A_rdiv_Bt!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, D) +rdiv!(A::SparseMatrixCSC{T}, adjD::Adjoint{<:Any,<:Diagonal{T}}) where {T} = + (D = adjD.parent; A_rdiv_B!(A, conj(D))) +rdiv!(A::SparseMatrixCSC{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = + (D = transD.parent; A_rdiv_B!(A, D)) ## triu, tril @@ -883,9 +918,31 @@ end scale!(A::SparseMatrixCSC, b::Number) = (scale!(A.nzval, b); A) scale!(b::Number, A::SparseMatrixCSC) = (scale!(b, A.nzval); A) -for f in (:\, :Ac_ldiv_B, :At_ldiv_B) +function \(A::SparseMatrixCSC, B::AbstractVecOrMat) + m, n = size(A) + if m == n + if istril(A) + if istriu(A) + return \(Diagonal(Vector(diag(A))), B) + else + return \(LowerTriangular(A), B) + end + elseif istriu(A) + return \(UpperTriangular(A), B) + end + if ishermitian(A) + return \(Hermitian(A), B) + end + return \(lufact(A), B) + else + return \(qrfact(A), B) + end +end +\(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +for (xform, f) in ((:Adjoint, :Ac_ldiv_B), (:Transpose, :At_ldiv_B)) @eval begin - function ($f)(A::SparseMatrixCSC, B::AbstractVecOrMat) + function \(xformA::($xform){<:Any,<:SparseMatrixCSC}, B::AbstractVecOrMat) + A = xformA.parent m, n = size(A) if m == n if istril(A) @@ -905,7 +962,7 @@ for f in (:\, :Ac_ldiv_B, :At_ldiv_B) return ($f)(qrfact(A), B) end end - ($f)(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::($xform){<:Any,<:SparseMatrixCSC}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) end end From ae76f0d3ba8e99c59ed8fc3da8d781d4f5fb3eda Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 6 Dec 2017 14:36:57 -0800 Subject: [PATCH 20/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/sparse/sparsevector.jl with de-jazzed passthroughs. --- base/deprecated.jl | 35 ++++++++++++++++ base/sparse/sparsevector.jl | 81 ++++++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 33 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index ec7ff0a8035300..92ba401eb48041 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2734,6 +2734,41 @@ end Ac_mul_Bc(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(Adjoint(A), Adjoint(B)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/sparse/sparsevector.jl, to deprecate +for isunittri in (true, false), islowertri in (true, false) + unitstr = isunittri ? "Unit" : "" + halfstr = islowertri ? "Lower" : "Upper" + tritype = :(Base.LinAlg.$(Symbol(unitstr, halfstr, "Triangular"))) + @eval Base.SparseArrays begin + using Base.LinAlg: Adjoint, Transpose + At_ldiv_B(A::$tritype{TA,<:AbstractMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} = \(Transpose(A), b) + At_ldiv_B(A::$tritype{TA,<:StridedMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} = \(Transpose(A), b) + At_ldiv_B(A::$tritype, b::SparseVector) = \(Transpose(A), b) + Ac_ldiv_B(A::$tritype{TA,<:AbstractMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} = \(Adjoint(A), b) + Ac_ldiv_B(A::$tritype{TA,<:StridedMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} = \(Adjoint(A), b) + Ac_ldiv_B(A::$tritype, b::SparseVector) = \(Adjoint(A), b) + A_ldiv_B!(A::$tritype{<:Any,<:StridedMatrix}, b::SparseVector) = ldiv!(A, b) + At_ldiv_B!(A::$tritype{<:Any,<:StridedMatrix}, b::SparseVector) = ldiv!(Transpose(A), b) + Ac_ldiv_B!(A::$tritype{<:Any,<:StridedMatrix}, b::SparseVector) = ldiv!(Adjoint(A), b) + end +end +@eval Base.SparseArrays begin + using Base.LinAlg: Adjoint, Transpose + Ac_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = *(Adjoint(A), x) + At_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = *(Transpose(A), x) + Ac_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = mul!(α, Adjoint(A), x, β, y) + Ac_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, Adjoint(A), x) + At_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = mul!(α, Transpose(A), x, β, y) + At_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, Transpose(A), x) + A_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = mul!(α, A, x, β, y) + A_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, A, x) + At_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) = mul!(α, Transpose(A), x, β, y) + At_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, Transpose(A), x) + At_mul_B(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} = *(Transpose(A), x) + A_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) = mul!(α, A, x, β, y) + A_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, A, x) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 76e09d34ce39a4..74b8ed30c0bf67 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -2,6 +2,7 @@ ### Common definitions +using Base.LinAlg: Adjoint, Transpose import Base: scalarmax, scalarmin, sort, find, findnz import Base.LinAlg: promote_to_array_type, promote_to_arrays_ @@ -1571,10 +1572,10 @@ function (*)(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} A_mul_B!(y, A, x) end -A_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = +mul!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = A_mul_B!(one(Tx), A, x, zero(Ty), y) -function A_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) +function mul!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) m, n = size(A) length(x) == n && length(y) == m || throw(DimensionMismatch()) m == 0 && return y @@ -1600,7 +1601,8 @@ end # At_mul_B -function At_mul_B(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} +function *(transA::Transpose{<:Any,<:StridedMatrix{Ta}}, x::AbstractSparseVector{Tx}) where {Ta,Tx} + A = transA.parent m, n = size(A) length(x) == m || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) @@ -1608,10 +1610,11 @@ function At_mul_B(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,T At_mul_B!(y, A, x) end -At_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - At_mul_B!(one(Tx), A, x, zero(Ty), y) +mul!(y::StridedVector{Ty}, transA::Transpose{<:Any,<:StridedMatrix}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = + (A = transA.parent; At_mul_B!(one(Tx), A, x, zero(Ty), y)) -function At_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) +function mul!(α::Number, transA::Transpose{<:Any,<:StridedMatrix}, x::AbstractSparseVector, β::Number, y::StridedVector) + A = transA.parent m, n = size(A) length(x) == m && length(y) == n || throw(DimensionMismatch()) n == 0 && return y @@ -1666,10 +1669,10 @@ end # A_mul_B -A_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = +mul!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = A_mul_B!(one(Tx), A, x, zero(Ty), y) -function A_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) +function mul!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) m, n = size(A) length(x) == n && length(y) == m || throw(DimensionMismatch()) m == 0 && return y @@ -1699,17 +1702,17 @@ end # At_mul_B -At_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - At_mul_B!(one(Tx), A, x, zero(Ty), y) +mul!(y::StridedVector{Ty}, transA::Transpose{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = + (A = transA.parent; At_mul_B!(one(Tx), A, x, zero(Ty), y)) -At_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = - _At_or_Ac_mul_B!(*, α, A, x, β, y) +mul!(α::Number, transA::Transpose{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector, β::Number, y::StridedVector) = + (A = transA.parent; _At_or_Ac_mul_B!(*, α, A, x, β, y)) -Ac_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - Ac_mul_B!(one(Tx), A, x, zero(Ty), y) +mul!(y::StridedVector{Ty}, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = + (A = adjA.parent; Ac_mul_B!(one(Tx), A, x, zero(Ty), y)) -Ac_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = - _At_or_Ac_mul_B!(dot, α, A, x, β, y) +mul!(α::Number, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector, β::Number, y::StridedVector) = + (A = adjA.parent; _At_or_Ac_mul_B!(dot, α, A, x, β, y)) function _At_or_Ac_mul_B!(tfun::Function, α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, @@ -1747,11 +1750,11 @@ function *(A::SparseMatrixCSC, x::AbstractSparseVector) _dense2sparsevec(y, initcap) end -At_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = - _At_or_Ac_mul_B(*, A, x) +*(transA::Transpose{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector) = + (A = transA.parent; _At_or_Ac_mul_B(*, A, x)) -Ac_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = - _At_or_Ac_mul_B(dot, A, x) +*(adjA::Adjoint{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector) = + (A = adjA.parent; _At_or_Ac_mul_B(dot, A, x)) function _At_or_Ac_mul_B(tfun::Function, A::SparseMatrixCSC{TvA,TiA}, x::AbstractSparseVector{TvX,TiX}) where {TvA,TiA,TvX,TiX} m, n = size(A) @@ -1797,13 +1800,16 @@ for isunittri in (true, false), islowertri in (true, false) tritype = :(Base.LinAlg.$(Symbol(unitstr, halfstr, "Triangular"))) # build out-of-place left-division operations - for (istrans, func, ipfunc) in ( - (false, :(\), :(A_ldiv_B!)), - (true, :(At_ldiv_B), :(At_ldiv_B!)), - (true, :(Ac_ldiv_B), :(Ac_ldiv_B!)) ) + for (istrans, func, ipfunc, applyxform, xform) in ( + (false, :(\), :(A_ldiv_B!), false, :None), + (true, :(At_ldiv_B), :(At_ldiv_B!), true, :Transpose), + (true, :(Ac_ldiv_B), :(Ac_ldiv_B!), true, :Adjoint) ) # broad method where elements are Numbers - @eval function ($func)(A::$tritype{TA,<:AbstractMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} + xformtritype = applyxform ? :($xform{<:TA,<:$tritype{<:Any,<:AbstractMatrix}}) : + :($tritype{<:TA,<:AbstractMatrix}) + @eval function \(xformA::$xformtritype, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} + A = $(applyxform ? :(xformA.parent) : :(xformA) ) TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) @@ -1812,7 +1818,10 @@ for isunittri in (true, false), islowertri in (true, false) # faster method requiring good view support of the # triangular matrix type. hence the StridedMatrix restriction. - @eval function ($func)(A::$tritype{TA,<:StridedMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} + xformtritype = applyxform ? :($xform{<:TA,<:$tritype{<:Any,<:StridedMatrix}}) : + :($tritype{<:TA,<:StridedMatrix}) + @eval function \(xformA::$xformtritype, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} + A = $(applyxform ? :(xformA.parent) : :(xformA) ) TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) @@ -1832,19 +1841,26 @@ for isunittri in (true, false), islowertri in (true, false) end # fallback where elements are not Numbers - @eval ($func)(A::$tritype, b::SparseVector) = ($ipfunc)(A, copy(b)) + xformtritype = applyxform ? :($xform{<:Any,<:$tritype}) : :($tritype) + @eval function \(xformA::$xformtritype, b::SparseVector) + A = $(applyxform ? :(xformA.parent) : :(xformA) ) + ($ipfunc)(A, copy(b)) + end end # build in-place left-division operations - for (istrans, func) in ( - (false, :(A_ldiv_B!)), - (true, :(At_ldiv_B!)), - (true, :(Ac_ldiv_B!)) ) + for (istrans, func, applyxform, xform) in ( + (false, :(A_ldiv_B!), false, :None), + (true, :(At_ldiv_B!), true, :Transpose), + (true, :(Ac_ldiv_B!), true, :Adjoint) ) + xformtritype = applyxform ? :($xform{<:Any,<:$tritype{<:Any,<:StridedMatrix}}) : + :($tritype{<:Any,<:StridedMatrix}) # the generic in-place left-division methods handle these cases, but # we can achieve greater efficiency where the triangular matrix provides # good view support. hence the StridedMatrix restriction. - @eval function ($func)(A::$tritype{<:Any,<:StridedMatrix}, b::SparseVector) + @eval function ldiv!(xformA::$xformtritype, b::SparseVector) + A = $(applyxform ? :(xformA.parent) : :(xformA) ) # If b has no nonzero entries, the result is necessarily zero and this call # reduces to a no-op. If b has nonzero entries, then... if nnz(b) != 0 @@ -1863,7 +1879,6 @@ for isunittri in (true, false), islowertri in (true, false) nzrangeviewbnz = view(b.nzval, nzrange .- (b.nzind[1] - 1)) nzrangeviewA = $tritype(view(A.data, nzrange, nzrange)) ($func)(nzrangeviewA, nzrangeviewbnz) - # could strip any miraculous zeros here perhaps end b end From 2edbb1cc6661711f66c8425d1246c1e8ebdab1cf Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 6 Dec 2017 15:30:19 -0800 Subject: [PATCH 21/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/rowvector.jl with de-jazzed passthroughs. --- base/deprecated.jl | 43 ++++++++++++++ base/linalg/rowvector.jl | 121 +++++++++++++++++++++++--------------- base/linalg/triangular.jl | 8 ++- 3 files changed, 125 insertions(+), 47 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 92ba401eb48041..b9faeb025e9bd1 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2769,6 +2769,49 @@ end A_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = mul!(y, A, x) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/rowvector.jl, to deprecate +@eval Base.LinAlg begin + A_rdiv_Bt(rowvec::RowVector, mat::AbstractMatrix) = /(rowvec, Transpose(mat)) + A_rdiv_Bc(rowvec::RowVector, mat::AbstractMatrix) = /(rowvec, Adjoint(mat)) + At_ldiv_B(mat::AbstractMatrix, rowvec::RowVector) = \(Transpose(mat), rowvec) + Ac_ldiv_B(mat::AbstractMatrix, rowvec::RowVector) = \(Adjoint(mat), rowvec) + Ac_mul_B(u::RowVector, v::AbstractVector) = *(Adjoint(u), v) + Ac_mul_B(vec::AbstractVector, mat::AbstractMatrix) = *(Adjoint(vec), mat) + Ac_mul_B(rowvec1::RowVector, rowvec2::RowVector) = *(Adjoint(rowvec1), rowvec2) + Ac_mul_B(vec::AbstractVector, rowvec::RowVector) = *(Adjoint(vec), rowvec) + Ac_mul_B(vec1::AbstractVector, vec2::AbstractVector) = *(Adjoint(vec1), vec2) + Ac_mul_Bc(rowvec::RowVector, vec::AbstractVector) = *(Adjoint(rowvec), Adjoint(vec)) + Ac_mul_Bc(vec::AbstractVector, mat::AbstractMatrix) = *(Adjoint(vec), Adjoint(mat)) + Ac_mul_Bc(rowvec1::RowVector, rowvec2::RowVector) = *(Adjoint(rowvec1), Adjoint(rowvec2)) + Ac_mul_Bc(vec::AbstractVector, rowvec::RowVector) = *(Adjoint(vec), Adjoint(rowvec)) + Ac_mul_Bc(vec::AbstractVector, rowvec::AbstractVector) = *(Adjoint(vec), Adjoint(rowvec)) + Ac_mul_Bc(mat::AbstractMatrix, rowvec::RowVector) = *(Adjoint(mat), Adjoint(rowvec)) + A_mul_Bc(u::RowVector, v::AbstractVector) = *(u, Adjoint(v)) + A_mul_Bc(rowvec::RowVector, mat::AbstractMatrix) = *(rowvec, Adjoint(mat)) + A_mul_Bc(rowvec1::RowVector, rowvec2::RowVector) = *(rowvec1, Adjoint(rowvec2)) + A_mul_Bc(vec::AbstractVector, rowvec::RowVector) = *(vec, Adjoint(rowvec)) + A_mul_Bc(vec1::AbstractVector, vec2::AbstractVector) = *(vec1, Adjoint(vec2)) + A_mul_Bc(mat::AbstractMatrix, rowvec::RowVector) = *(mat, Adjoint(rowvec)) + At_mul_B(v::RowVector, u::AbstractVector) = *(Transpose(v), u) + At_mul_B(vec::AbstractVector, mat::AbstractMatrix) = *(Transpose(vec), mat) + At_mul_B(rowvec1::RowVector, rowvec2::RowVector) = *(Transpose(rowvec1), rowvec2) + At_mul_B(vec::AbstractVector, rowvec::RowVector) = *(Transpose(vec), rowvec) + At_mul_B(vec1::AbstractVector{T}, vec2::AbstractVector{T}) where {T<:Real} = *(Transpose(vec1), vec2) + At_mul_B(vec1::AbstractVector, vec2::AbstractVector) = *(Transpose(vec1), vec2) + At_mul_Bt(rowvec::RowVector, vec::AbstractVector) = *(Transpose(rowvec), Transpose(vec)) + At_mul_Bt(vec::AbstractVector, mat::AbstractMatrix) = *(Transpose(vec), Transpose(mat)) + At_mul_Bt(rowvec1::RowVector, rowvec2::RowVector) = *(Transpose(rowvec1), Transpose(rowvec2)) + At_mul_Bt(vec::AbstractVector, rowvec::RowVector) = *(Transpose(vec), Transpose(rowvec)) + At_mul_Bt(vec::AbstractVector, rowvec::AbstractVector) = *(Transpose(vec), Transpose(rowvec)) + At_mul_Bt(mat::AbstractMatrix, rowvec::RowVector) = *(Transpose(mat), Transpose(rowvec)) + A_mul_Bt(v::RowVector, A::AbstractVector) = *(v, Transpose(A)) + A_mul_Bt(rowvec::RowVector, mat::AbstractMatrix) = *(rowvec, Transpose(mat)) + A_mul_Bt(rowvec1::RowVector, rowvec2::RowVector) = *(rowvec1, Transpose(rowvec2)) + A_mul_Bt(vec::AbstractVector, rowvec::RowVector) = *(vec, Transpose(rowvec)) + A_mul_Bt(vec1::AbstractVector, vec2::AbstractVector) = *(vec1, Transpose(vec2)) + A_mul_Bt(mat::AbstractMatrix, rowvec::RowVector) = *(mat, Transpose(rowvec)) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 8f7084f9cf6504..5f745d942a70c9 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -208,50 +208,77 @@ end *(vec::AbstractVector, rowvec::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) # Transposed forms -A_mul_Bt(::RowVector, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -@inline A_mul_Bt(rowvec::RowVector, mat::AbstractMatrix) = transpose(mat * transpose(rowvec)) -@inline A_mul_Bt(rowvec1::RowVector, rowvec2::RowVector) = rowvec1*transpose(rowvec2) -A_mul_Bt(vec::AbstractVector, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline A_mul_Bt(vec1::AbstractVector, vec2::AbstractVector) = vec1 * transpose(vec2) -@inline A_mul_Bt(mat::AbstractMatrix, rowvec::RowVector) = mat * transpose(rowvec) - -@inline At_mul_Bt(rowvec::RowVector, vec::AbstractVector) = transpose(rowvec) * transpose(vec) -@inline At_mul_Bt(vec::AbstractVector, mat::AbstractMatrix) = transpose(mat * vec) -At_mul_Bt(rowvec1::RowVector, rowvec2::RowVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline At_mul_Bt(vec::AbstractVector, rowvec::RowVector) = transpose(vec)*transpose(rowvec) -At_mul_Bt(vec::AbstractVector, rowvec::AbstractVector) = throw(DimensionMismatch( - "Cannot multiply two transposed vectors")) -@inline At_mul_Bt(mat::AbstractMatrix, rowvec::RowVector) = mat.' * transpose(rowvec) - -At_mul_B(::RowVector, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline At_mul_B(vec::AbstractVector, mat::AbstractMatrix) = transpose(At_mul_B(mat,vec)) -@inline At_mul_B(rowvec1::RowVector, rowvec2::RowVector) = transpose(rowvec1) * rowvec2 -At_mul_B(vec::AbstractVector, rowvec::RowVector) = throw(DimensionMismatch( - "Cannot multiply two transposed vectors")) -@inline At_mul_B(vec1::AbstractVector{T}, vec2::AbstractVector{T}) where {T<:Real} = - reduce(+, map(At_mul_B, vec1, vec2)) # Seems to be overloaded... -@inline At_mul_B(vec1::AbstractVector, vec2::AbstractVector) = transpose(vec1) * vec2 +*(::RowVector, ::Transpose{<:Any,<:AbstractVector}) = + throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = + (mat = transmat.parent; transpose(mat * transpose(rowvec))) +*(rowvec1::RowVector, transrowvec2::Transpose{<:Any,<:RowVector}) = + (rowvec2 = transrowvec2.parent; rowvec1*transpose(rowvec2)) +*(::AbstractVector, ::Transpose{<:Any,<:RowVector}) = + throw(DimensionMismatch("Cannot multiply two vectors")) +*(vec1::AbstractVector, transvec2::Transpose{<:Any,<:AbstractVector}) = + (vec2 = transvec2.parent; vec1 * transpose(vec2)) +*(mat::AbstractMatrix, transrowvec::Transpose{<:Any,<:RowVector}) = + (rowvec = transrowvec.parent; mat * transpose(rowvec)) + +*(transrowvec::Transpose{<:Any,<:RowVector}, transvec::Transpose{<:Any,<:AbstractVector}) = + transpose(transrowvec.parent) * transpose(transvec.parent) +*(transvec::Transpose{<:Any,<:AbstractVector}, transmat::Transpose{<:Any,<:AbstractMatrix}) = + transpose(transmat.parent * transvec.parent) +*(transrowvec1::Transpose{<:Any,<:RowVector}, transrowvec2::Transpose{<:Any,<:RowVector}) = + throw(DimensionMismatch("Cannot multiply two vectors")) +*(transvec::Transpose{<:Any,<:AbstractVector}, transrowvec::Transpose{<:Any,<:RowVector}) = + transpose(transvec.parent)*transpose(transrowvec.parent) +*(transvec::Transpose{<:Any,<:AbstractVector}, transrowvec::Transpose{<:Any,<:AbstractVector}) = + throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(transmat::Transpose{<:Any,<:AbstractMatrix}, transrowvec::Transpose{<:Any,<:RowVector}) = + (transmat.parent).' * transpose(transrowvec.parent) + +*(::Transpose{<:Any,<:RowVector}, ::AbstractVector) = + throw(DimensionMismatch("Cannot multiply two vectors")) +*(transvec::Transpose{<:Any,<:AbstractVector}, mat::AbstractMatrix) = + transpose(At_mul_B(mat,transvec.parent)) +*(transrowvec1::Transpose{<:Any,<:RowVector}, rowvec2::RowVector) = + transpose(transrowvec1.parent) * rowvec2 +*(transvec::Transpose{<:Any,<:AbstractVector}, rowvec::RowVector) = + throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(transvec1::Transpose{<:Any,<:AbstractVector{T}}, vec2::AbstractVector{T}) where {T<:Real} = + reduce(+, map(At_mul_B, transvec1.parent, vec2)) # Seems to be overloaded... +*(transvec1::Transpose{<:Any,<:AbstractVector}, vec2::AbstractVector) = + transpose(transvec1.parent) * vec2 # Conjugated forms -A_mul_Bc(::RowVector, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -@inline A_mul_Bc(rowvec::RowVector, mat::AbstractMatrix) = adjoint(mat * adjoint(rowvec)) -@inline A_mul_Bc(rowvec1::RowVector, rowvec2::RowVector) = rowvec1 * adjoint(rowvec2) -A_mul_Bc(vec::AbstractVector, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline A_mul_Bc(vec1::AbstractVector, vec2::AbstractVector) = vec1 * adjoint(vec2) -@inline A_mul_Bc(mat::AbstractMatrix, rowvec::RowVector) = mat * adjoint(rowvec) - -@inline Ac_mul_Bc(rowvec::RowVector, vec::AbstractVector) = adjoint(rowvec) * adjoint(vec) -@inline Ac_mul_Bc(vec::AbstractVector, mat::AbstractMatrix) = adjoint(mat * vec) -Ac_mul_Bc(rowvec1::RowVector, rowvec2::RowVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline Ac_mul_Bc(vec::AbstractVector, rowvec::RowVector) = adjoint(vec)*adjoint(rowvec) -Ac_mul_Bc(vec::AbstractVector, rowvec::AbstractVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -@inline Ac_mul_Bc(mat::AbstractMatrix, rowvec::RowVector) = mat' * adjoint(rowvec) - -Ac_mul_B(::RowVector, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -@inline Ac_mul_B(vec::AbstractVector, mat::AbstractMatrix) = adjoint(Ac_mul_B(mat,vec)) -@inline Ac_mul_B(rowvec1::RowVector, rowvec2::RowVector) = adjoint(rowvec1) * rowvec2 -Ac_mul_B(vec::AbstractVector, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -@inline Ac_mul_B(vec1::AbstractVector, vec2::AbstractVector) = adjoint(vec1)*vec2 +*(::RowVector, ::Adjoint{<:Any,<:AbstractVector}) = + throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = + adjoint(adjmat.parent * adjoint(rowvec)) +*(rowvec1::RowVector, adjrowvec2::Adjoint{<:Any,<:RowVector}) = + rowvec1 * adjoint(adjrowvec2.parent) +*(vec::AbstractVector, adjrowvec::Adjoint{<:Any,<:RowVector}) = + throw(DimensionMismatch("Cannot multiply two vectors")) +*(vec1::AbstractVector, adjvec2::Adjoint{<:Any,<:AbstractVector}) = + vec1 * adjoint(adjvec2.parent) +*(mat::AbstractMatrix, adjrowvec::Adjoint{<:Any,<:RowVector}) = + mat * adjoint(adjrowvec.parent) + +*(adjrowvec::Adjoint{<:Any,<:RowVector}, adjvec::Adjoint{<:Any,<:AbstractVector}) = + adjoint(adjrowvec.parent) * adjoint(adjvec.parent) +*(adjvec::Adjoint{<:Any,<:AbstractVector}, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = + adjoint(adjmat.parent * adjvec.parent) +*(adjrowvec1::Adjoint{<:Any,<:RowVector}, adjrowvec2::Adjoint{<:Any,<:RowVector}) = + throw(DimensionMismatch("Cannot multiply two vectors")) +*(adjvec::Adjoint{<:Any,<:AbstractVector}, adjrowvec::Adjoint{<:Any,<:RowVector}) = + adjoint(adjvec.parent)*adjoint(adjrowvec.parent) +*(adjvec::Adjoint{<:Any,<:AbstractVector}, adjrowvec::Adjoint{<:Any,<:AbstractVector}) = + throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(adjmat::Adjoint{<:Any,<:AbstractMatrix}, adjrowvec::Adjoint{<:Any,<:RowVector}) = + (adjmat.parent)' * adjoint(adjrowvec.parent) + +*(::Adjoint{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) +*(adjvec::Adjoint{<:Any,<:AbstractVector}, mat::AbstractMatrix) = adjoint(Ac_mul_B(mat,adjvec.parent)) +*(adjrowvec1::Adjoint{<:Any,<:RowVector}, rowvec2::RowVector) = adjoint(adjrowvec1.parent) * rowvec2 +*(adjvec::Adjoint{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) +*(adjvec1::Adjoint{<:Any,<:AbstractVector}, vec2::AbstractVector) = adjoint(adjvec1.parent)*vec2 # Pseudo-inverse pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' @@ -260,11 +287,13 @@ pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' \(rowvec1::RowVector, rowvec2::RowVector) = pinv(rowvec1) * rowvec2 \(mat::AbstractMatrix, rowvec::RowVector) = throw(DimensionMismatch("Cannot left-divide transposed vector by matrix")) -At_ldiv_B(mat::AbstractMatrix, rowvec::RowVector) = throw(DimensionMismatch("Cannot left-divide transposed vector by matrix")) -Ac_ldiv_B(mat::AbstractMatrix, rowvec::RowVector) = throw(DimensionMismatch("Cannot left-divide transposed vector by matrix")) +\(transmat::Transpose{<:Any,<:AbstractMatrix}, rowvec::RowVector) = + throw(DimensionMismatch("Cannot left-divide transposed vector by matrix")) +\(adjmat::Adjoint{<:Any,<:AbstractMatrix}, rowvec::RowVector) = + throw(DimensionMismatch("Cannot left-divide transposed vector by matrix")) # Right Division # @inline /(rowvec::RowVector, mat::AbstractMatrix) = transpose(transpose(mat) \ transpose(rowvec)) -@inline A_rdiv_Bt(rowvec::RowVector, mat::AbstractMatrix) = transpose(mat \ transpose(rowvec)) -@inline A_rdiv_Bc(rowvec::RowVector, mat::AbstractMatrix) = adjoint(mat \ adjoint(rowvec)) +/(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = transpose(transmat.parent \ transpose(rowvec)) +/(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(adjmat.parent \ adjoint(rowvec)) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 9fb50091cffa7c..aa9cb4d522c144 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1826,6 +1826,12 @@ function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractTriangular}) copy!(AA, A) A_mul_Bt!(AA, convert(AbstractArray{TAB}, B)) end +# ambiguity resolution with definitions in linalg/rowvector.jl +*(transA::Transpose{<:Any,<:AbstractVector}, B::AbstractTriangular) = *(transpose(transA.parent), B) +*(adjA::Adjoint{<:Any,<:AbstractVector}, B::AbstractTriangular) = *(adjoint(adjA.parent), B) +*(transA::Transpose{<:Any,<:AbstractVector}, transB::Transpose{<:Any,<:AbstractTriangular}) = *(transpose(transA.parent), transB) +*(adjA::Adjoint{<:Any,<:AbstractVector}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = *(adjoint(adjA.parent), adjB) + # If these are not defined, they will fallback to the versions in matmul.jl # and dispatch to generic_matmatmul! which is very costly to compile. The methods @@ -1844,7 +1850,7 @@ end *(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractTriangular}) = A_mul_Bt(transA.parent.', transB.parent) # Specializations for RowVector -@inline *(rowvec::RowVector, A::AbstractTriangular) = transpose(A * transpose(rowvec)) +*(rowvec::RowVector, A::AbstractTriangular) = transpose(transpose(A) * transpose(rowvec)) *(rowvec::RowVector, transA::Transpose{<:Any,<:AbstractTriangular}) = transpose(transA.parent * transpose(rowvec)) *(A::AbstractTriangular, transrowvec::Transpose{<:Any,<:RowVector}) = A * transpose(transrowvec.parent) *(transA::Transpose{<:Any,<:AbstractTriangular}, transrowvec::Transpose{<:Any,<:RowVector}) = transA.parent.' * transpose(transrowvec.parent) From 51633632cf026195a94bfd3214fadc901f02bd74 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 6 Dec 2017 17:11:20 -0800 Subject: [PATCH 22/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/linalg/givens.jl with de-jazzed passthroughs. --- base/deprecated.jl | 11 +++++++++++ base/linalg/givens.jl | 17 ++++++++++------- base/linalg/linalg.jl | 1 + 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index b9faeb025e9bd1..48d17812143ff4 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2812,6 +2812,17 @@ end A_mul_Bt(mat::AbstractMatrix, rowvec::RowVector) = *(mat, Transpose(rowvec)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/linalg/givens.jl, to deprecate +@eval Base.LinAlg begin + A_mul_Bc!(A::AbstractMatrix, R::Rotation) = mul!(A, Adjoint(R)) + A_mul_B!(R::Rotation, A::AbstractMatrix) = mul!(R, A) + A_mul_B!(G::Givens, R::Rotation) = mul!(G, R) + A_mul_Bc!(A::AbstractMatrix, G::Givens) = mul!(A, Adjoint(G)) + A_mul_B!(G::Givens, A::AbstractVecOrMat) = mul!(G, A) + A_mul_B!(G1::Givens, G2::Givens) = mul!(G1, G2) + A_mul_Bc(A::AbstractVecOrMat{T}, R::AbstractRotation{S}) where {T,S} = *(A, Adjoint(R)) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index de621983494d42..ddd637df842b06 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -9,7 +9,8 @@ function *(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_B!(convert(AbstractRotation{TS}, R), TS == S ? copy(A) : convert(AbstractArray{TS}, A)) end -function A_mul_Bc(A::AbstractVecOrMat{T}, R::AbstractRotation{S}) where {T,S} +function *(A::AbstractVecOrMat{T}, adjR::Adjoint{<:Any,<:AbstractRotation{S}}) where {T,S} + R = adjR.parent TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_Bc!(TS == T ? copy(A) : convert(AbstractArray{TS}, A), convert(AbstractRotation{TS}, R)) end @@ -318,9 +319,9 @@ function getindex(G::Givens, i::Integer, j::Integer) end -A_mul_B!(G1::Givens, G2::Givens) = error("Operation not supported. Consider *") +mul!(G1::Givens, G2::Givens) = error("Operation not supported. Consider *") -function A_mul_B!(G::Givens, A::AbstractVecOrMat) +function mul!(G::Givens, A::AbstractVecOrMat) m, n = size(A, 1), size(A, 2) if G.i2 > m throw(DimensionMismatch("column indices for rotation are outside the matrix")) @@ -332,7 +333,8 @@ function A_mul_B!(G::Givens, A::AbstractVecOrMat) end return A end -function A_mul_Bc!(A::AbstractMatrix, G::Givens) +function mul!(A::AbstractMatrix, adjG::Adjoint{<:Any,<:Givens}) + G = adjG.parent m, n = size(A, 1), size(A, 2) if G.i2 > n throw(DimensionMismatch("column indices for rotation are outside the matrix")) @@ -344,17 +346,18 @@ function A_mul_Bc!(A::AbstractMatrix, G::Givens) end return A end -function A_mul_B!(G::Givens, R::Rotation) +function mul!(G::Givens, R::Rotation) push!(R.rotations, G) return R end -function A_mul_B!(R::Rotation, A::AbstractMatrix) +function mul!(R::Rotation, A::AbstractMatrix) @inbounds for i = 1:length(R.rotations) A_mul_B!(R.rotations[i], A) end return A end -function A_mul_Bc!(A::AbstractMatrix, R::Rotation) +function mul!(A::AbstractMatrix, adjR::Adjoint{<:Any,<:Rotation}) + R = adjR.parent @inbounds for i = 1:length(R.rotations) A_mul_Bc!(A, R.rotations[i]) end diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index fb01e70f3c3fc4..3482798b52295b 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -238,6 +238,7 @@ function char_uplo(uplo::Symbol) end # shims to maintain existence of names in A_mul_B deprecation process +function A_mul_B! end function Ac_mul_B! end function Ac_mul_B! end function At_mul_B! end From e524a3236a08844c771f9a5a204b11814fbeccb0 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 9 Dec 2017 15:41:06 -0800 Subject: [PATCH 23/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in stdlib/IterativeEigenSolvers with de-jazzed passthroughs. --- stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl | 6 ++++-- stdlib/IterativeEigenSolvers/src/deprecated.jl | 6 ++++++ stdlib/IterativeEigenSolvers/test/runtests.jl | 7 ++++--- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 stdlib/IterativeEigenSolvers/src/deprecated.jl diff --git a/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl b/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl index 780c7c19940eed..a5912d8909cd43 100644 --- a/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl +++ b/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl @@ -205,7 +205,7 @@ function SVDAugmented(A::AbstractMatrix{T}) where T SVDAugmented{Tnew,typeof(Anew)}(Anew) end -function Base.A_mul_B!(y::StridedVector{T}, A::SVDAugmented{T}, x::StridedVector{T}) where T +function Base.LinAlg.mul!(y::StridedVector{T}, A::SVDAugmented{T}, x::StridedVector{T}) where T m, mn = size(A.X, 1), length(x) A_mul_B!( view(y, 1:m), A.X, view(x, m + 1:mn)) # left singular vector Ac_mul_B!(view(y, m + 1:mn), A.X, view(x, 1:m)) # right singular vector @@ -225,7 +225,7 @@ function AtA_or_AAt(A::AbstractMatrix{T}) where T AtA_or_AAt{Tnew,typeof(Anew)}(Anew, Vector{Tnew}(uninitialized, max(size(A)...))) end -function Base.A_mul_B!(y::StridedVector{T}, A::AtA_or_AAt{T}, x::StridedVector{T}) where T +function Base.LinAlg.mul!(y::StridedVector{T}, A::AtA_or_AAt{T}, x::StridedVector{T}) where T if size(A.A, 1) >= size(A.A, 2) A_mul_B!(A.buffer, A.A, x) return Ac_mul_B!(y, A.A, A.buffer) @@ -331,4 +331,6 @@ function _svds(X; nsv::Int = 6, ritzvec::Bool = true, tol::Float64 = 0.0, maxite end end +include("deprecated.jl") + end # module diff --git a/stdlib/IterativeEigenSolvers/src/deprecated.jl b/stdlib/IterativeEigenSolvers/src/deprecated.jl new file mode 100644 index 00000000000000..2d83f5d4e260e1 --- /dev/null +++ b/stdlib/IterativeEigenSolvers/src/deprecated.jl @@ -0,0 +1,6 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +@eval IterativeEigenSolvers begin + Base.A_mul_B!(y::StridedVector{T}, A::AtA_or_AAt{T}, x::StridedVector{T}) where {T} = Base.LinAlg.mul!(y, A, x) + Base.A_mul_B!(y::StridedVector{T}, A::SVDAugmented{T}, x::StridedVector{T}) where {T} = Base.LinAlg.mul!(y, A, x) +end diff --git a/stdlib/IterativeEigenSolvers/test/runtests.jl b/stdlib/IterativeEigenSolvers/test/runtests.jl index 9c56af6a26b528..7f6392ce10bd7e 100644 --- a/stdlib/IterativeEigenSolvers/test/runtests.jl +++ b/stdlib/IterativeEigenSolvers/test/runtests.jl @@ -105,7 +105,7 @@ using Test end end -# Problematic example from #6965 +# Problematic example from #6965A let A6965 = [ 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 -1.0 2.0 0.0 0.0 0.0 0.0 0.0 1.0 @@ -138,8 +138,7 @@ end size(Phi::CPM) = (size(Phi.kraus,1)^2,size(Phi.kraus,3)^2) issymmetric(Phi::CPM) = false ishermitian(Phi::CPM) = false -import Base: A_mul_B! -function A_mul_B!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) where {T<:Base.LinAlg.BlasFloat} +function Base.LinAlg.mul!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) where {T<:Base.LinAlg.BlasFloat} rho = reshape(rho,(size(Phi.kraus,3),size(Phi.kraus,3))) rho1 = zeros(T,(size(Phi.kraus,1),size(Phi.kraus,1))) for s = 1:size(Phi.kraus,2) @@ -148,6 +147,8 @@ function A_mul_B!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) wher end return copy!(rho2,rho1) end +Base.LinAlg.A_mul_B!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) where {T<:Base.LinAlg.BlasFloat} = Base.LinAlg.mul!(rho2, Phi, rho) +# after the A_mul_B! deprecation, remove this A_mul_B! def and the import above let # Generate random isometry From 8d20c31b2cc50b9736ae3586c7ef35ef92d96ef8 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 9 Dec 2017 16:43:31 -0800 Subject: [PATCH 24/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in stdlib/SuiteSparse/CHOLMOD with de-jazzed passthroughs. --- stdlib/SuiteSparse/src/SuiteSparse.jl | 3 +- stdlib/SuiteSparse/src/cholmod.jl | 67 +++++++++++++++++---------- stdlib/SuiteSparse/src/deprecated.jl | 17 +++++++ 3 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 stdlib/SuiteSparse/src/deprecated.jl diff --git a/stdlib/SuiteSparse/src/SuiteSparse.jl b/stdlib/SuiteSparse/src/SuiteSparse.jl index 87073f010de7cf..ef3e63b4d3b09c 100644 --- a/stdlib/SuiteSparse/src/SuiteSparse.jl +++ b/stdlib/SuiteSparse/src/SuiteSparse.jl @@ -5,7 +5,7 @@ __precompile__(true) module SuiteSparse import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B! -import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc! +import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc!, ldiv!, rdiv! ## Functions to switch to 0-based indexing to call external sparse solvers @@ -27,6 +27,7 @@ if Base.USE_GPL_LIBS include("umfpack.jl") include("cholmod.jl") include("spqr.jl") + include("deprecated.jl") end end # module SuiteSparse diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index b0d535d6dd8937..76bda374933fdb 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -7,7 +7,8 @@ import Base: (*), convert, copy, eltype, getindex, show, size, import Base.LinAlg: (\), A_mul_Bc, A_mul_Bt, Ac_ldiv_B, Ac_mul_B, At_ldiv_B, At_mul_B, cholfact, cholfact!, det, diag, ishermitian, isposdef, - issuccess, issymmetric, ldltfact, ldltfact!, logdet + issuccess, issymmetric, ldltfact, ldltfact!, logdet, + Adjoint, Transpose using ..SparseArrays @@ -1293,7 +1294,8 @@ end (*)(A::Sparse, B::Dense) = sdmult!(A, false, 1., 0., B, zeros(size(A, 1), size(B, 2))) (*)(A::Sparse, B::VecOrMat) = (*)(A, Dense(B)) -function A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where Tv<:VRealTypes +function *(A::Sparse{Tv}, adjB::Adjoint{Tv,Sparse{Tv}}) where Tv<:VRealTypes + B = adjB.parent if A !== B aa1 = transpose_(B, 2) ## result of ssmult will have stype==0, contain numerical values and be sorted @@ -1312,7 +1314,8 @@ function A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where Tv<:VRealTypes end end -function Ac_mul_B(A::Sparse, B::Sparse) +function *(adjA::Adjoint{<:Any,<:Sparse}, B::Sparse) + A = adjA.parent aa1 = transpose_(A, 2) if A === B return A_mul_Bc(aa1, aa1) @@ -1321,8 +1324,10 @@ function Ac_mul_B(A::Sparse, B::Sparse) return ssmult(aa1, B, 0, true, true) end -Ac_mul_B(A::Sparse, B::Dense) = sdmult!(A, true, 1., 0., B, zeros(size(A, 2), size(B, 2))) -Ac_mul_B(A::Sparse, B::VecOrMat) = Ac_mul_B(A, Dense(B)) +*(adjA::Adjoint{<:Any,<:Sparse}, B::Dense) = + (A = adjA.parent; sdmult!(A, true, 1., 0., B, zeros(size(A, 2), size(B, 2)))) +*(adjA::Adjoint{<:Any,<:Sparse}, B::VecOrMat) = + (A = adjA.parent; Ac_mul_B(A, Dense(B))) ## Factorization methods @@ -1672,8 +1677,8 @@ function (\)(L::FactorComponent, B::SparseVecOrMat) sparse(L\Sparse(B,0)) end -Ac_ldiv_B(L::FactorComponent, B) = adjoint(L)\B -Ac_ldiv_B(L::FactorComponent, B::RowVector) = adjoint(L)\B # ambiguity +\(adjL::Adjoint{<:Any,<:FactorComponent}, B::Union{VecOrMat,SparseVecOrMat}) = (L = adjL.parent; adjoint(L)\B) +\(adjL::Adjoint{<:Any,<:FactorComponent}, B::RowVector) = (L = adjL.parent; adjoint(L)\B) # ambiguity (\)(L::Factor{T}, B::Dense{T}) where {T<:VTypes} = solve(CHOLMOD_A, L, B) # Explicit typevars are necessary to avoid ambiguities with defs in linalg/factorizations.jl @@ -1686,25 +1691,39 @@ Ac_ldiv_B(L::FactorComponent, B::RowVector) = adjoint(L)\B # ambiguity # When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric. (\)(L::Factor, B::SparseVecOrMat) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0))) -Ac_ldiv_B(L::Factor, B::Dense) = solve(CHOLMOD_A, L, B) -Ac_ldiv_B(L::Factor, B::VecOrMat) = convert(Matrix, solve(CHOLMOD_A, L, Dense(B))) -Ac_ldiv_B(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B) -Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = Ac_ldiv_B(L, Sparse(B)) - -for f in (:\, :Ac_ldiv_B) - @eval function ($f)(A::Union{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, - Hermitian{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, - Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}}, B::StridedVecOrMat) - F = cholfact(A) +\(adjL::Adjoint{<:Any,<:Factor}, B::Dense) = (L = adjL.parent; solve(CHOLMOD_A, L, B)) +\(adjL::Adjoint{<:Any,<:Factor}, B::VecOrMat) = (L = adjL.parent; convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))) +\(adjL::Adjoint{<:Any,<:Factor}, B::Sparse) = (L = adjL.parent; spsolve(CHOLMOD_A, L, B)) +\(adjL::Adjoint{<:Any,<:Factor}, B::SparseVecOrMat) = (L = adjL.parent; Ac_ldiv_B(L, Sparse(B))) + +const RealHermSymComplexHermF64SSL = Union{ + Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, + Hermitian{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, + Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}} +function \(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) + F = cholfact(A) + if issuccess(F) + return \(F, B) + else + ldltfact!(F, A) if issuccess(F) - return ($f)(F, B) + return \(F, B) else - ldltfact!(F, A) - if issuccess(F) - return ($f)(F, B) - else - return ($f)(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A)), B) - end + return \(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A)), B) + end + end +end +function \(adjA::Adjoint{<:Any,<:RealHermSymComplexHermF64SSL}, B::StridedVecOrMat) + A = adjA.parent + F = cholfact(A) + if issuccess(F) + return Ac_ldiv_B(F, B) + else + ldltfact!(F, A) + if issuccess(F) + return Ac_ldiv_B(F, B) + else + return Ac_ldiv_B(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A)), B) end end end diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl new file mode 100644 index 00000000000000..52a6883892fdef --- /dev/null +++ b/stdlib/SuiteSparse/src/deprecated.jl @@ -0,0 +1,17 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/cholmod.jl, to deprecate +@eval SuiteSparse.CHOLMOD begin + using Base.LinAlg: Adjoint, Transpose + Ac_ldiv_B(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) = \(Adjoint(A), B) + Ac_ldiv_B(L::Factor, B::Dense) = \(Adjoint(L), B) + Ac_ldiv_B(L::Factor, B::VecOrMat) = \(Adjoint(L), B) + Ac_ldiv_B(L::Factor, B::Sparse) = \(Adjoint(L), B) + Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = \(Adjoint(L), B) + Ac_ldiv_B(L::FactorComponent, B) = \(Adjoint(L), B) + Ac_ldiv_B(L::FactorComponent, B::RowVector) = \(Adjoint(L), B) + Ac_mul_B(A::Sparse, B::Dense) = *(Adjoint(A), B) + Ac_mul_B(A::Sparse, B::VecOrMat) = *(Adjoint(A), B) + Ac_mul_B(A::Sparse, B::Sparse) = *(Adjoint(A), B) + A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where {Tv<:VRealTypes} = *(A, Adjoint(B)) +end From 0d4f1969e919d7a71dc03d9f63c758e04a644f42 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 9 Dec 2017 18:29:30 -0800 Subject: [PATCH 25/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in stdlib/SuiteSparse/UMFPACK with de-jazzed passthroughs. --- stdlib/SuiteSparse/src/deprecated.jl | 23 +++++++++++++++ stdlib/SuiteSparse/src/umfpack.jl | 43 ++++++++++++++++------------ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl index 52a6883892fdef..b210fd13333504 100644 --- a/stdlib/SuiteSparse/src/deprecated.jl +++ b/stdlib/SuiteSparse/src/deprecated.jl @@ -15,3 +15,26 @@ Ac_mul_B(A::Sparse, B::Sparse) = *(Adjoint(A), B) A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where {Tv<:VRealTypes} = *(A, Adjoint(B)) end + +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/umfpack.jl, to deprecate +@eval SuiteSparse.UMFPACK begin + using Base.LinAlg: Adjoint, Transpose + A_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.LinAlg.ldiv!(X, lu, B) + At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.LinAlg.ldiv!(X, Transpose(lu), B) + Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.LinAlg.ldiv!(X, Adjoint(lu), B) + A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.LinAlg.ldiv!(X, lu, B) + At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.LinAlg.ldiv!(X, Transpose(lu), B) + Ac_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.LinAlg.ldiv!(X, Adjoint(lu), B) + A_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(lu, B) + At_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Transpose(lu), B) + Ac_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Adjoint(lu), B) + A_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(lu, B) + At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Transpose(lu), B) + Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Adjoint(lu), B) +end diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl index fad1158d178b96..e766f5ef32f55b 100644 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -5,7 +5,8 @@ module UMFPACK export UmfpackLU import Base: (\), Ac_ldiv_B, At_ldiv_B, findnz, getindex, show, size -import Base.LinAlg: A_ldiv_B!, Ac_ldiv_B!, At_ldiv_B!, Factorization, det, lufact +import Base.LinAlg: A_ldiv_B!, Ac_ldiv_B!, At_ldiv_B!, Factorization, det, lufact, ldiv! +using Base.LinAlg: Adjoint, Transpose using ..SparseArrays import ..SparseArrays: nnz @@ -384,25 +385,31 @@ function nnz(lu::UmfpackLU) end ### Solve with Factorization -A_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = A_ldiv_B!(B, lu, copy(B)) -At_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = At_ldiv_B!(B, lu, copy(B)) -Ac_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Ac_ldiv_B!(B, lu, copy(B)) -A_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = A_ldiv_B!(B, lu, copy(B)) -At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = At_ldiv_B!(B, lu, copy(B)) -Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Ac_ldiv_B!(B, lu, copy(B)) - -A_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = +ldiv!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + A_ldiv_B!(B, lu, copy(B)) +ldiv!(translu::Transpose{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + (lu = translu.parent; At_ldiv_B!(B, lu, copy(B))) +ldiv!(adjlu::Adjoint{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + (lu = adjlu.parent; Ac_ldiv_B!(B, lu, copy(B))) +ldiv!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = + A_ldiv_B!(B, lu, copy(B)) +ldiv!(translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = + (lu = translu.parent; At_ldiv_B!(B, lu, copy(B))) +ldiv!(adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = + (lu = adjlu.parent; Ac_ldiv_B!(B, lu, copy(B))) + +ldiv!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) -Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = +ldiv!(X::StridedVecOrMat{T}, translu::Transpose{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + (lu = translu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat)) +ldiv!(X::StridedVecOrMat{T}, adjlu::Adjoint{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + (lu = adjlu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_At)) +ldiv!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) -Ac_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = - _Aq_ldiv_B!(X, lu, B, UMFPACK_At) +ldiv!(X::StridedVecOrMat{Tb}, translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + (lu = translu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat)) +ldiv!(X::StridedVecOrMat{Tb}, adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + (lu = adjlu.parent; _Aq_ldiv_B!(X, lu, B, UMFPACK_At)) function _Aq_ldiv_B!(X::StridedVecOrMat, lu::UmfpackLU, B::StridedVecOrMat, transposeoptype) if size(X, 2) != size(B, 2) From d062298a917ff256fb9892a7c48d1e7f4934132b Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 9 Dec 2017 18:47:07 -0800 Subject: [PATCH 26/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in stdlib/SuiteSparse/SPQR with de-jazzed passthroughs. --- stdlib/SuiteSparse/src/deprecated.jl | 9 +++++++++ stdlib/SuiteSparse/src/spqr.jl | 11 +++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl index b210fd13333504..29b7cd6913ab9c 100644 --- a/stdlib/SuiteSparse/src/deprecated.jl +++ b/stdlib/SuiteSparse/src/deprecated.jl @@ -38,3 +38,12 @@ end At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Transpose(lu), B) Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Adjoint(lu), B) end + +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/spqr.jl, to deprecate +@eval SuiteSparse.SPQR begin + using Base.LinAlg: Adjoint, Transpose + Base.A_mul_Bc!(A::StridedMatrix, Q::QRSparseQ) = Base.LinAlg.mul!(A, Adjoint(Q)) + Base.Ac_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) = Base.LinAlg.mul!(Adjoint(Q), A) + Base.A_mul_B!(A::StridedMatrix, Q::QRSparseQ) = Base.LinAlg.mul!(A, Q) + Base.A_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) = Base.LinAlg.mul!(Q, A) +end diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl index fe6237b80854a0..81d196c5ebf069 100644 --- a/stdlib/SuiteSparse/src/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -3,6 +3,7 @@ module SPQR import Base: \ +using Base.LinAlg: Adjoint, Transpose # ordering options */ const ORDERING_FIXED = Int32(0) @@ -197,7 +198,7 @@ Base.LinAlg.qrfact(A::SparseMatrixCSC; tol = _default_tol(A)) = qrfact(A, Val{tr Base.LinAlg.qr(A::SparseMatrixCSC; tol = _default_tol(A)) = qr(A, Val{true}, tol = tol) -function Base.A_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) +function Base.LinAlg.mul!(Q::QRSparseQ, A::StridedVecOrMat) if size(A, 1) != size(Q, 1) throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) end @@ -212,7 +213,7 @@ function Base.A_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) return A end -function Base.A_mul_B!(A::StridedMatrix, Q::QRSparseQ) +function Base.LinAlg.mul!(A::StridedMatrix, Q::QRSparseQ) if size(A, 2) != size(Q, 1) throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) end @@ -226,7 +227,8 @@ function Base.A_mul_B!(A::StridedMatrix, Q::QRSparseQ) return A end -function Base.Ac_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) +function Base.LinAlg.mul!(adjQ::Adjoint{<:Any,<:QRSparseQ}, A::StridedVecOrMat) + Q = adjQ.parent if size(A, 1) != size(Q, 1) throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) end @@ -241,7 +243,8 @@ function Base.Ac_mul_B!(Q::QRSparseQ, A::StridedVecOrMat) return A end -function Base.A_mul_Bc!(A::StridedMatrix, Q::QRSparseQ) +function Base.LinAlg.mul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRSparseQ}) + Q = adjQ.parent if size(A, 2) != size(Q, 1) throw(DimensionMismatch("size(Q) = $(size(Q)) but size(A) = $(size(A))")) end From ce5ee65305889d2690f3ab8d96daa894622c4ab3 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 9 Dec 2017 10:26:14 -0800 Subject: [PATCH 27/77] Disambiguate *, /, and \ methods. --- base/linalg/adjtrans.jl | 11 +++++++++++ base/linalg/bidiag.jl | 9 ++++++--- base/linalg/diagonal.jl | 6 ++++++ base/linalg/factorization.jl | 5 +++++ base/linalg/givens.jl | 19 +++++++++++++++++- base/linalg/lu.jl | 14 +++++++------- base/linalg/matmul.jl | 4 ++-- base/linalg/rowvector.jl | 6 ++++++ base/linalg/symmetric.jl | 37 ++++++++++++++++++++++++++++++++++++ base/linalg/triangular.jl | 22 +++++++++++++++++++++ 10 files changed, 120 insertions(+), 13 deletions(-) diff --git a/base/linalg/adjtrans.jl b/base/linalg/adjtrans.jl index 0044780922cf4e..e22642a8c2261f 100644 --- a/base/linalg/adjtrans.jl +++ b/base/linalg/adjtrans.jl @@ -97,3 +97,14 @@ similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, # sundry basic definitions parent(A::AdjOrTrans) = A.parent vec(v::AdjOrTransAbsVec) = v.parent + +# dismabiguation methods +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractVector}) = transpose(A.parent) * B +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractVector}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 02f1baab392416..5ef3871c96a0ba 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -565,19 +565,22 @@ function naivesub!(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) w end ### Generic promotion methods and fallbacks -function \(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} +function \(A::Bidiagonal{<:Number}, B::AbstractVecOrMat{<:Number}) + TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) A_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end \(A::Bidiagonal, B::AbstractVecOrMat) = A_ldiv_B!(A, copy(B)) -function \(transA::Transpose{<:Any,<:Bidiagonal{TA}}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} +function \(transA::Transpose{<:Number,<:Bidiagonal{<:Number}}, B::AbstractVecOrMat{<:Number}) A = transA.parent + TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) At_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end \(transA::Transpose{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = At_ldiv_B!(transA.parent, copy(B)) -function \(adjA::Adjoint{<:Any,<:Bidiagonal{TA}}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} +function \(adjA::Adjoint{<:Number,<:Bidiagonal{<:Number}}, B::AbstractVecOrMat{<:Number}) A = adjA.parent + TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) Ac_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 9f817a74828bc5..0d7bdba4b04f50 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -459,3 +459,9 @@ function svdfact(D::Diagonal) U, s, V = svd(D) SVD(U, s, V') end + +# dismabiguation methods: * of Diagonal and Adj/Trans AbsVec +*(A::Diagonal, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::Diagonal, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) +*(A::Adjoint{<:Any,<:AbstractVector}, B::Diagonal) = adjoint(A.parent) * B +*(A::Transpose{<:Any,<:AbstractVector}, B::Diagonal) = transpose(A.parent) * B diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 1e7e070bc8e3fc..9d498fe2692762 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -85,3 +85,8 @@ ldiv!(Y::AbstractVecOrMat, transA::Transpose{<:Any,<:Factorization}, B::Abstract # fallback methods for transposed solves \(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; Ac_ldiv_B(F, B)) \(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(Ac_ldiv_B(F, conj.(B)))) + +# dismabiguation methods +\(A::Adjoint{<:Any,<:Factorization}, B::RowVector) = adjoint(A.parent) \ B +\(A::Transpose{<:Any,<:Factorization}, B::RowVector) = transpose(A.parent) \ B +\(A::Transpose{<:Any,<:Factorization{<:Real}}, B::RowVector) = transpose(A.parent) \ B diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index ddd637df842b06..ccac4f5dca3a88 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -9,7 +9,9 @@ function *(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_B!(convert(AbstractRotation{TS}, R), TS == S ? copy(A) : convert(AbstractArray{TS}, A)) end -function *(A::AbstractVecOrMat{T}, adjR::Adjoint{<:Any,<:AbstractRotation{S}}) where {T,S} +*(A::AbstractVector, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) +*(A::AbstractMatrix, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) +function _absvecormat_mul_adjrot(A::AbstractVecOrMat{T}, adjR::Adjoint{<:Any,<:AbstractRotation{S}}) where {T,S} R = adjR.parent TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_Bc!(TS == T ? copy(A) : convert(AbstractArray{TS}, A), convert(AbstractRotation{TS}, R)) @@ -364,3 +366,18 @@ function mul!(A::AbstractMatrix, adjR::Adjoint{<:Any,<:Rotation}) return A end *(G1::Givens{T}, G2::Givens{T}) where {T} = Rotation(push!(push!(Givens{T}[], G2), G1)) + +# dismabiguation methods: *(Adj/Trans of AbsVec or AbsMat, Adj of AbstractRotation) +*(A::Adjoint{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractRotation}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractRotation}) = adjoint(A.parent) * B +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractRotation}) = transpose(A.parent) * B +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractRotation}) = transpose(A.parent) * B +# dismabiguation methods: *(Adj/Trans of AbsTri or RealHermSymComplex{Herm|Sym}, Adj of AbstractRotation) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractRotation}) = adjoint(A.parent) * B +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractRotation}) = transpose(A.parent) * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:AbstractRotation}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractRotation}) = A.parent * B +# dismabiguation methods: *(Diag/RowVec/AbsTri, Adj of AbstractRotation) +*(A::Diagonal, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) +*(A::RowVector, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) +*(A::AbstractTriangular, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index ed7f86b514d3e4..9e3ef416d708fb 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -310,7 +310,7 @@ function ldiv!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B)) end -ldiv!(transA::Transpose{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = +ldiv!(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = (A = transA.parent; @assertnonsingular(LAPACK.getrs!('T', A.factors, A.ipiv, B), A.info)) function ldiv!(transA::Transpose{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) @@ -319,9 +319,9 @@ function ldiv!(transA::Transpose{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedV _apply_inverse_ipiv!(A, B) end -ldiv!(adjF::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:Real} = +ldiv!(adjF::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:Real} = (F = adjF.parent; At_ldiv_B!(F, B)) -ldiv!(adjA::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = +ldiv!(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = (A = adjA.parent; @assertnonsingular(LAPACK.getrs!('C', A.factors, A.ipiv, B), A.info)) function ldiv!(adjA::Adjoint{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) @@ -330,16 +330,16 @@ function ldiv!(adjA::Adjoint{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOr _apply_inverse_ipiv!(A, B) end -function \(transA::Transpose{<:Any,<:LU{T,<:StridedMatrix}}, - transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} +function \(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, + transB::Transpose{T,<:StridedVecOrMat{T}}) where {T<:BlasFloat} A, B = transA.parent, transB.parent @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info end \(transA::Transpose{<:Any,<:LU}, transB::Transpose{<:Any,<:StridedVecOrMat}) = (A = transA.parent; B = transB.parent; At_ldiv_B(A, transpose(B))) -function \(adjA::Adjoint{<:Any,<:LU{T,<:StridedMatrix}}, - adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasComplex} +function \(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, + adjB::Adjoint{T,<:StridedVecOrMat{T}}) where {T<:BlasComplex} A, B = adjA.parent, adjB.parent @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, adjoint(B)) A.info end diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 15f96dcfa690bf..4bbab0145bb975 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -154,8 +154,8 @@ julia> [1 1; 0 1] * [1 0; 1 1] 1 1 ``` """ -function (*)(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} - TS = promote_op(matprod, T, S) +function (*)(A::AbstractMatrix, B::AbstractMatrix) + TS = promote_op(matprod, eltype(A), eltype(B)) A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'N', 'N', A, B) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 5f745d942a70c9..2e231f4d764bbc 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -297,3 +297,9 @@ pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' @inline /(rowvec::RowVector, mat::AbstractMatrix) = transpose(transpose(mat) \ transpose(rowvec)) /(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = transpose(transmat.parent \ transpose(rowvec)) /(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(adjmat.parent \ adjoint(rowvec)) + +# dismabiguation methods +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:RowVector}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RowVector}) = A * transpose(B.parent) +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:RowVector}) = transpose(A.parent) * B +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RowVector}) = A * adjoint(B.parent) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 6f544a9bb545de..503781d046a086 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -737,3 +737,40 @@ for func in (:log, :sqrt) end end end + +# dismabiguation methods: *(Adj of RealHermSymComplexHerm, Trans of RealHermSymComplexSym) and symmetric partner +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A.parent * B.parent +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A.parent * B.parent +# dismabiguation methods: *(Adj/Trans of AbsVec/AbsMat, Adj/Trans of RealHermSymComplex{Herm|Sym}) +*(A::Adjoint{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +# dismabiguation methods: *(Adj/Trans of RealHermSymComplex{Herm|Sym}, Adj/Trans of AbsVec/AbsMat) +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:AbstractVector}) = A.parent * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:AbstractMatrix}) = A.parent * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:AbstractVector}) = A.parent * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:AbstractMatrix}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractVector}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractMatrix}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:AbstractVector}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:AbstractMatrix}) = A.parent * B +# dismabiguation methods: *(Adj/Trans of RealHermSymComplex{Herm|Sym}, Adj/Trans of RowVector) +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:RowVector}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:RowVector}) = A.parent * B + +# dismabiguation methods: *(Adj/Trans of AbsTri or RealHermSymComplex{Herm|Sym}, Adj/Trans of other) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = A * B.parent +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:AbstractTriangular}) = A.parent * B +*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:AbstractTriangular}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractTriangular}) = A.parent * B +*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:AbstractTriangular}) = A.parent * B diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index aa9cb4d522c144..29d52ab7344594 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -2386,3 +2386,25 @@ for func in (:svd, :svdfact, :svdfact!, :svdvals) end factorize(A::AbstractTriangular) = A + +# dismabiguation methods: *(AbstractTriangular, Adj/Trans of AbstractVector) +*(A::AbstractTriangular, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::AbstractTriangular, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) +# dismabiguation methods: *(Adj/Trans of AbstractTriangular, Trans/Ajd of AbstractTriangular) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractTriangular}) = adjoint(A.parent) * B +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractTriangular}) = transpose(A.parent) * B +# dismabiguation methods: *(Adj/Trans of AbstractTriangular, Adj/Trans of AbsVec or AbsMat) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractMatrix}) = A * transpose(B.parent) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractMatrix}) = A * adjoint(B.parent) +# dismabiguation methods: *(Adj/Trans of AbsVec or AbsMat, Adj/Trans of AbstractTriangular) +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractTriangular}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractTriangular}) = adjoint(A.parent) * B +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractTriangular}) = transpose(A.parent) * B +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractTriangular}) = transpose(A.parent) * B +# dismabiguation methods: *(Adj/Trans of AbstractTriangular, Trans/Adj of RowVector) +*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:RowVector}) = A * transpose(B.parent) +*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RowVector}) = A * adjoint(B.parent) From 6fb85f07415c953ea3052b8118598619b3a67500 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 13:40:31 -0800 Subject: [PATCH 28/77] Disambiguate mul!, ldiv!, and rdiv! methods. --- base/linalg/bidiag.jl | 9 +++++++++ base/linalg/diagonal.jl | 19 +++++++++++++++++++ base/linalg/givens.jl | 11 +++++++++++ base/linalg/matmul.jl | 1 + base/linalg/triangular.jl | 7 +++++++ 5 files changed, 47 insertions(+) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 5ef3871c96a0ba..0fb9141711d916 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -331,9 +331,18 @@ mul!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) = A_mul_B_td!(C, A mul!(C::AbstractMatrix, A::AbstractTriangular, B::BiTriSym) = A_mul_B_td!(C, A, B) mul!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) = A_mul_B_td!(C, A, B) mul!(C::AbstractMatrix, A::Diagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractTriangular}, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractVecOrMat}, B::BiTriSym) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractVecOrMat}, B::BiTriSym) = A_mul_B_td!(C, A, B) mul!(C::AbstractVector, A::BiTri, B::AbstractVector) = A_mul_B_td!(C, A, B) mul!(C::AbstractMatrix, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) mul!(C::AbstractVecOrMat, A::BiTri, B::AbstractVecOrMat) = A_mul_B_td!(C, A, B) +mul!(C::AbstractMatrix, A::BiTri, B::Transpose{<:Any,<:AbstractVecOrMat}) = A_mul_B_td!(C, A, B) # around bidiag line 330 +mul!(C::AbstractMatrix, A::BiTri, B::Adjoint{<:Any,<:AbstractVecOrMat}) = A_mul_B_td!(C, A, B) +mul!(C::AbstractVector, A::BiTri, B::Transpose{<:Any,<:AbstractVecOrMat}) = throw(MethodError(mul!, (C, A, B))) \(::Diagonal, ::RowVector) = _mat_ldiv_rowvec_error() \(::Bidiagonal, ::RowVector) = _mat_ldiv_rowvec_error() diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 0d7bdba4b04f50..daa61a50fd4ae5 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -232,6 +232,17 @@ end mul!(A::Diagonal, B::Diagonal) = throw(MethodError(mul!, Tuple{Diagonal,Diagonal})) mul!(A::QRPackedQ, D::Diagonal) = throw(MethodError(mul!, Tuple{Diagonal,Diagonal})) +mul!(A::QRPackedQ, B::Adjoint{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::QRPackedQ, B::Transpose{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:QRPackedQ}, B::Diagonal) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:QRPackedQ}, B::Adjoint{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:QRPackedQ}, B::Transpose{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Diagonal, B::Adjoint{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Diagonal, B::Transpose{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:Diagonal}, B::Transpose{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Transpose{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) +mul!(A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:Diagonal}) = throw(MethodError(mul!, (A, B))) mul!(transA::Transpose{<:Any,<:Diagonal}, B::Diagonal) = throw(MethodError(mul!, Tuple{Transpose{<:Any,<:Diagonal},Diagonal})) mul!(adjA::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = @@ -256,6 +267,14 @@ mul!(out::AbstractMatrix, adjA::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = mul!(out::AbstractMatrix, transA::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = (A = transA.parent; out .= transpose.(A.diag) .* in) +mul!(C::AbstractMatrix, A::Diagonal, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Diagonal, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, transpose(B.parent)) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, transpose(B.parent)) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, transpose(B.parent)) + + # ambiguities with Symmetric/Hermitian # RealHermSymComplex[Sym]/[Herm] only include Number; invariant to [c]transpose *(A::Diagonal, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index ccac4f5dca3a88..d953dafcfc2c9b 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -381,3 +381,14 @@ end *(A::Diagonal, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) *(A::RowVector, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) *(A::AbstractTriangular, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) +# moar disambiguation +mul!(A::QRPackedQ, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) +mul!(A::QRPackedQ, B::Adjoint{<:Any,<:Rotation}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:QRPackedQ}, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:QRPackedQ}, B::Adjoint{<:Any,<:Rotation}) = throw(MethodError(mul!, (A, B))) +mul!(A::Diagonal, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) +mul!(A::Diagonal, B::Adjoint{<:Any,<:Rotation}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) +mul!(A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Rotation}) = throw(MethodError(mul!, (A, B))) +mul!(A::Transpose{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Rotation}) = throw(MethodError(mul!, (A, B))) +mul!(A::Transpose{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 4bbab0145bb975..090e37d6b51d7b 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -247,6 +247,7 @@ mul!(C::StridedMatrix{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, transB: (A = transA.parent; B = transB.parent; gemm_wrapper!(C, 'T', 'T', A, B)) mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:AbstractVecOrMat}, transB::Transpose{<:Any,<:AbstractVecOrMat}) = (A = transA.parent; B = transB.parent; generic_matmatmul!(C, 'T', 'T', A, B)) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractVecOrMat}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) *(adjA::Adjoint{<:Any,<:StridedMatrix{T}}, B::StridedMatrix{T}) where {T<:BlasReal} = (A = adjA.parent; At_mul_B(A, B)) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 29d52ab7344594..e3ef1f6242749f 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -470,6 +470,13 @@ mul!(C::AbstractMatrix , transA::Transpose{<:Any,<:AbstractTriangular}, B::Abst (A = transA.parent; At_mul_B!(A, copy!(C, B))) mul!(C::AbstractVecOrMat, transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = (A = transA.parent; At_mul_B!(A, copy!(C, B))) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, transpose(B.parent)) +mul!(C::AbstractVector, A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVecOrMat}) = throw(MethodError(mul!, (C, A, B))) +mul!(C::AbstractVector, A::Transpose{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVecOrMat}) = throw(MethodError(mul!, (C, A, B))) + for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), (:UnitLowerTriangular, 'L', 'U'), From e80697dfc5cf4748f50b727361c40d781149341a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 8 Dec 2017 09:27:18 -0800 Subject: [PATCH 29/77] Replace A[ct]_(mul|ldiv|rdiv)_B[ct][!] defs in base/operators.jl with shims to lazy calls in base/deprecated.jl, w/o transferring methods. --- base/deprecated.jl | 122 ++++++++++++++++++++++++++++++ base/linalg/adjtrans.jl | 12 ++- base/linalg/linalg.jl | 23 +++++- base/linalg/lq.jl | 2 + base/linalg/rowvector.jl | 7 ++ base/linalg/tridiag.jl | 2 + base/linalg/uniformscaling.jl | 2 + base/operators.jl | 136 ---------------------------------- base/sparse/linalg.jl | 3 + test/linalg/generic.jl | 3 + 10 files changed, 174 insertions(+), 138 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 48d17812143ff4..23b5d403c96c24 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2823,6 +2823,128 @@ end A_mul_Bc(A::AbstractVecOrMat{T}, R::AbstractRotation{S}) where {T,S} = *(A, Adjoint(R)) end +# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/operators.jl, to deprecate +@eval Base begin + using Base.LinAlg: Adjoint, Transpose + """ + Ac_ldiv_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``Bᵀ``. + """ + Ac_ldiv_Bt(a,b) = \(Adjoint(a), Transpose(b)) + """ + At_ldiv_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ`` \\ ``Bᵀ``. + """ + At_ldiv_Bt(a,b) = \(Transpose(a), Transpose(b)) + """ + A_ldiv_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A`` \\ ``Bᵀ``. + """ + A_ldiv_Bt(a,b) = \(a, Transpose(b)) + """ + At_ldiv_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ`` \\ ``B``. + """ + At_ldiv_B(a,b) = \(Transpose(a), b) + """ + Ac_ldiv_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``Bᴴ``. + """ + Ac_ldiv_Bc(a,b) = \(Adjoint(a), Adjoint(b)) + """ + A_ldiv_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A`` \\ ``Bᴴ``. + """ + A_ldiv_Bc(a,b) = \(a, Adjoint(b)) + """ + Ac_ldiv_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``B``. + """ + Ac_ldiv_B(a,b) = \(Adjoint(a), b) + """ + At_rdiv_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ / Bᵀ``. + """ + At_rdiv_Bt(a,b) = /(Transpose(a), Transpose(b)) + """ + A_rdiv_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A / Bᵀ``. + """ + A_rdiv_Bt(a,b) = /(a, Transpose(b)) + """ + At_rdiv_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ / B``. + """ + At_rdiv_B(a,b) = /(Transpose(a), b) + """ + Ac_rdiv_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ / Bᴴ``. + """ + Ac_rdiv_Bc(a,b) = /(Adjoint(a), Adjoint(b)) + """ + A_rdiv_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A / Bᴴ``. + """ + A_rdiv_Bc(a,b) = /(a, Adjoint(b)) + """ + Ac_rdiv_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ / B``. + """ + Ac_rdiv_B(a,b) = /(Adjoint(a), b) + """ + At_mul_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ⋅Bᵀ``. + """ + At_mul_Bt(a,b) = *(Transpose(a), Transpose(b)) + """ + A_mul_Bt(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A⋅Bᵀ``. + """ + A_mul_Bt(a,b) = *(a, Transpose(b)) + """ + At_mul_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ⋅B``. + """ + At_mul_B(a,b) = *(Transpose(a), b) + """ + Ac_mul_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ Bᴴ``. + """ + Ac_mul_Bc(a,b) = *(Adjoint(a), Adjoint(b)) + """ + A_mul_Bc(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``A⋅Bᴴ``. + """ + A_mul_Bc(a,b) = *(a, Adjoint(b)) + """ + Ac_mul_B(A, B) + + For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ⋅B``. + """ + Ac_mul_B(a,b) = *(Adjoint(a), b) +end + +# re. A_mul_B deprecation, don't forget to: +# 1) delete function shims in base/linalg/linalg.jl + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/linalg/adjtrans.jl b/base/linalg/adjtrans.jl index e22642a8c2261f..d9e931d278fa64 100644 --- a/base/linalg/adjtrans.jl +++ b/base/linalg/adjtrans.jl @@ -98,6 +98,16 @@ similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, parent(A::AdjOrTrans) = A.parent vec(v::AdjOrTransAbsVec) = v.parent + +### linear algebra + +# definitions necessary for test/linalg/rowvector.jl to pass +# should be cleaned up / revised as necessary in the future +/(A::Transpose{<:Any,<:Vector}, B::Matrix) = /(transpose(A.parent), B) +/(A::Transpose{<:Any,<:Vector}, B::Transpose{<:Any,<:Matrix}) = /(transpose(A.parent), B) +*(A::Adjoint{<:Any,<:Matrix}, B::Adjoint{<:Any,<:Vector}) = *(adjoint(A.parent), adjoint(B.parent)) + + # dismabiguation methods *(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractVector}) = transpose(A.parent) * B *(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B @@ -107,4 +117,4 @@ vec(v::AdjOrTransAbsVec) = v.parent *(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B *(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) *(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B \ No newline at end of file diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 3482798b52295b..8c21dd20761912 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -1,5 +1,26 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +# shims to maintain existence of names in Base module in A_mul_B deprecation process +function Ac_ldiv_Bt end +function At_ldiv_Bt end +function A_ldiv_Bt end +function At_ldiv_B end +function Ac_ldiv_Bc end +function A_ldiv_Bc end +function Ac_ldiv_B end +function At_rdiv_Bt end +function A_rdiv_Bt end +function At_rdiv_B end +function Ac_rdiv_Bc end +function A_rdiv_Bc end +function Ac_rdiv_B end +function At_mul_Bt end +function A_mul_Bt end +function At_mul_B end +function Ac_mul_Bc end +function A_mul_Bc end +function Ac_mul_B end + """ Linear algebra module. Provides array arithmetic, matrix factorizations and other linear algebra related @@ -237,7 +258,7 @@ function char_uplo(uplo::Symbol) end end -# shims to maintain existence of names in A_mul_B deprecation process +# shims to maintain existence of names in LinAlg module in A_mul_B deprecation process function A_mul_B! end function Ac_mul_B! end function Ac_mul_B! end diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 5717e6fda52841..04c11425fb2554 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -138,6 +138,8 @@ function *(A::QR{TA},B::LQ{TB}) where {TA,TB} TAB = promote_type(TA, TB) A_mul_B!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) end +*(A::Adjoint{<:Any,<:LQ}, B::LQ) = adjoint(A.parent) * B +*(A::LQ, B::Adjoint{<:Any,<:LQ}) = A * adjoint(B.parent) ## Multiplication by Q ### QB diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 2e231f4d764bbc..5ccb5d820f3bac 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -298,6 +298,13 @@ pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' /(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = transpose(transmat.parent \ transpose(rowvec)) /(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(adjmat.parent \ adjoint(rowvec)) + +# definitions necessary for test/linalg/dense.jl to pass +# should be cleaned up / revised as necessary in the future +/(A::Number, B::Adjoint{<:Any,<:RowVector}) = /(A, adjoint(B.parent)) +/(A::Matrix, B::RowVector) = adjoint(adjoint(B) \ adjoint(A)) + + # dismabiguation methods *(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:RowVector}) = adjoint(A.parent) * B *(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RowVector}) = A * transpose(B.parent) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index fb1a77f5d5daa0..53d2e1d4ed8b6b 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -536,6 +536,8 @@ broadcast(::typeof(ceil), ::Type{T}, M::Tridiagonal) where {T<:Integer} = transpose(M::Tridiagonal) = Tridiagonal(M.du, M.d, M.dl) adjoint(M::Tridiagonal) = conj(transpose(M)) +\(A::Adjoint{<:Any,<:Tridiagonal}, B::Adjoint{<:Any,<:StridedVecOrMat}) = adjoint(A.parent) \ adjoint(B.parent) + function diag(M::Tridiagonal{T}, n::Integer=0) where T # every branch call similar(..., ::Int) to make sure the # same vector type is returned independent of n diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index d87e42b4a2e78b..e159b647d9fe83 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -63,7 +63,9 @@ end copy(J::UniformScaling) = UniformScaling(J.λ) transpose(J::UniformScaling) = J +Transpose(S::UniformScaling) = transpose(S) adjoint(J::UniformScaling) = UniformScaling(conj(J.λ)) +Adjoint(S::UniformScaling) = adjoint(S) one(::Type{UniformScaling{T}}) where {T} = UniformScaling(one(T)) one(J::UniformScaling{T}) where {T} = one(UniformScaling{T}) diff --git a/base/operators.jl b/base/operators.jl index d40cf227410e18..c6eb8c3ccaef36 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -762,142 +762,6 @@ julia> adjoint(A) adjoint(x) = conj(transpose(x)) conj(x) = x -# transposed multiply - -""" - Ac_mul_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ⋅B``. -""" -Ac_mul_B(a,b) = adjoint(a)*b - -""" - A_mul_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A⋅Bᴴ``. -""" -A_mul_Bc(a,b) = a*adjoint(b) - -""" - Ac_mul_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ Bᴴ``. -""" -Ac_mul_Bc(a,b) = adjoint(a)*adjoint(b) - -""" - At_mul_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ⋅B``. -""" -At_mul_B(a,b) = transpose(a)*b - -""" - A_mul_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A⋅Bᵀ``. -""" -A_mul_Bt(a,b) = a*transpose(b) - -""" - At_mul_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ⋅Bᵀ``. -""" -At_mul_Bt(a,b) = transpose(a)*transpose(b) - -# transposed divide - -""" - Ac_rdiv_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ / B``. -""" -Ac_rdiv_B(a,b) = adjoint(a)/b - -""" - A_rdiv_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A / Bᴴ``. -""" -A_rdiv_Bc(a,b) = a/adjoint(b) - -""" - Ac_rdiv_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ / Bᴴ``. -""" -Ac_rdiv_Bc(a,b) = adjoint(a)/adjoint(b) - -""" - At_rdiv_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ / B``. -""" -At_rdiv_B(a,b) = transpose(a)/b - -""" - A_rdiv_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A / Bᵀ``. -""" -A_rdiv_Bt(a,b) = a/transpose(b) - -""" - At_rdiv_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ / Bᵀ``. -""" -At_rdiv_Bt(a,b) = transpose(a)/transpose(b) - -""" - Ac_ldiv_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``B``. -""" -Ac_ldiv_B(a,b) = adjoint(a)\b - -""" - A_ldiv_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A`` \\ ``Bᴴ``. -""" -A_ldiv_Bc(a,b) = a\adjoint(b) - -""" - Ac_ldiv_Bc(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``Bᴴ``. -""" -Ac_ldiv_Bc(a,b) = adjoint(a)\adjoint(b) - -""" - At_ldiv_B(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ`` \\ ``B``. -""" -At_ldiv_B(a,b) = transpose(a)\b - -""" - A_ldiv_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``A`` \\ ``Bᵀ``. -""" -A_ldiv_Bt(a,b) = a\transpose(b) - -""" - At_ldiv_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᵀ`` \\ ``Bᵀ``. -""" -At_ldiv_Bt(a,b) = At_ldiv_B(a,transpose(b)) - -""" - Ac_ldiv_Bt(A, B) - -For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``Bᵀ``. -""" -Ac_ldiv_Bt(a,b) = Ac_ldiv_B(a,transpose(b)) """ widen(x) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index a816e9d2a00eea..8dbc89eec8b922 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -306,6 +306,9 @@ ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where (\)(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(L, Array(B)) (\)(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(U, Array(B)) +\(A::Transpose{<:Real,<:Hermitian{<:Real,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B +\(A::Transpose{<:Complex,<:Hermitian{<:Complex,<:SparseMatrixCSC}}, B::Vector) = transpose(A.parent) \ B +\(A::Transpose{<:Number,<:Symmetric{<:Number,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B function rdiv!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T dd = D.diag diff --git a/test/linalg/generic.jl b/test/linalg/generic.jl index b6a670d1a116f3..a53168789395ee 100644 --- a/test/linalg/generic.jl +++ b/test/linalg/generic.jl @@ -361,7 +361,10 @@ Base.zero(::Type{ModInt{n}}) where {n} = ModInt{n}(0) Base.zero(::ModInt{n}) where {n} = ModInt{n}(0) Base.one(::Type{ModInt{n}}) where {n} = ModInt{n}(1) Base.one(::ModInt{n}) where {n} = ModInt{n}(1) +Base.adjoint(a::ModInt{n}) where {n} = ModInt{n}(conj(a)) Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 +Base.LinAlg.Adjoint(a::ModInt{n}) where {n} = adjoint(a) +Base.LinAlg.Transpose(a::ModInt{n}) where {n} = transpose(a) @testset "Issue 22042" begin A = [ModInt{2}(1) ModInt{2}(0); ModInt{2}(1) ModInt{2}(1)] From 3f2d810696968c2895fa94b15b480979bcc5af40 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 16:29:12 -0800 Subject: [PATCH 30/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/deprecated.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/deprecated.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 23b5d403c96c24..7b3f7c427750d9 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1956,8 +1956,8 @@ function full(Q::LinAlg.LQPackedQ; thin::Bool = true) "`full(Q::LQPackedQ; thin::Bool = true)` (and `full` in general) ", "has been deprecated. To replace `full(Q::LQPackedQ, true)`, ", "consider `Matrix(Q)` or `Array(Q)`. To replace `full(Q::LQPackedQ, false)`, ", - "consider `Base.LinAlg.A_mul_B!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2)))`."), :full) - return thin ? Array(Q) : A_mul_B!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2))) + "consider `Base.LinAlg.mul!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2)))`."), :full) + return thin ? Array(Q) : Base.LinAlg.mul!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2))) end function full(Q::Union{LinAlg.QRPackedQ,LinAlg.QRCompactWYQ}; thin::Bool = true) qtypestr = isa(Q, LinAlg.QRPackedQ) ? "QRPackedQ" : @@ -1967,8 +1967,8 @@ function full(Q::Union{LinAlg.QRPackedQ,LinAlg.QRCompactWYQ}; thin::Bool = true) "`full(Q::$(qtypestr); thin::Bool = true)` (and `full` in general) ", "has been deprecated. To replace `full(Q::$(qtypestr), true)`, ", "consider `Matrix(Q)` or `Array(Q)`. To replace `full(Q::$(qtypestr), false)`, ", - "consider `Base.LinAlg.A_mul_B!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 1), size(Q.factors, 1)))`."), :full) - return thin ? Array(Q) : A_mul_B!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 1), size(Q.factors, 1))) + "consider `Base.LinAlg.mul!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 1), size(Q.factors, 1)))`."), :full) + return thin ? Array(Q) : Base.LinAlg.mul!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 1), size(Q.factors, 1))) end # full for symmetric / hermitian / triangular wrappers From 233175d8a5c9c9b758cef6d1569e676fa8526598 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 17:04:38 -0800 Subject: [PATCH 31/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/bidiag.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/bidiag.jl | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 0fb9141711d916..f9f173c7e4ac05 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -383,7 +383,7 @@ end function A_mul_B_td!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) check_A_mul_B!_sizes(C, A, B) n = size(A,1) - n <= 3 && return A_mul_B!(C, Array(A), Array(B)) + n <= 3 && return mul!(C, Array(A), Array(B)) fill!(C, zero(eltype(C))) Al = _diag(A, -1) Ad = _diag(A, 0) @@ -442,7 +442,7 @@ function A_mul_B_td!(C::AbstractVecOrMat, A::BiTriSym, B::AbstractVecOrMat) if size(C,2) != nB throw(DimensionMismatch("A has second dimension $nA, B has $(size(B,2)), C has $(size(C,2)) but all must match")) end - nA <= 3 && return A_mul_B!(C, Array(A), Array(B)) + nA <= 3 && return mul!(C, Array(A), Array(B)) l = _diag(A, -1) d = _diag(A, 0) u = _diag(A, 1) @@ -463,7 +463,7 @@ end function A_mul_B_td!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) check_A_mul_B!_sizes(C, A, B) n = size(A,1) - n <= 3 && return A_mul_B!(C, Array(A), Array(B)) + n <= 3 && return mul!(C, Array(A), Array(B)) m = size(B,2) Bl = _diag(B, -1) Bd = _diag(B, 0) @@ -498,15 +498,15 @@ const SpecialMatrix = Union{Bidiagonal,SymTridiagonal,Tridiagonal} #Generic multiplication *(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = *(Array(A), B) -*(adjA::Adjoint{<:Any,<:Bidiagonal{T}}, B::AbstractVector{T}) where {T} = Ac_mul_B(Array(adjA.parent), B) -*(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = A_mul_Bc(Array(A), adjB.parent) +*(adjA::Adjoint{<:Any,<:Bidiagonal{T}}, B::AbstractVector{T}) where {T} = *(Adjoint(Array(adjA.parent)), B) +*(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = *(Array(A), Adjoint(adjB.parent)) /(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = /(Array(A), B) -/(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = A_rdiv_Bc(Array(A), adjB.parent) +/(A::Bidiagonal{T}, adjB::Adjoint{<:Any,<:AbstractVector{T}}) where {T} = /(Array(A), Adjoint(adjB.parent)) #Linear solvers ldiv!(A::Union{Bidiagonal, AbstractTriangular}, b::AbstractVector) = naivesub!(A, b) -ldiv!(transA::Transpose{<:Any,<:Bidiagonal}, b::AbstractVector) = A_ldiv_B!(transpose(transA.parent), b) -ldiv!(adjA::Adjoint{<:Any,<:Bidiagonal}, b::AbstractVector) = A_ldiv_B!(adjoint(adjA.parent), b) +ldiv!(transA::Transpose{<:Any,<:Bidiagonal}, b::AbstractVector) = ldiv!(transpose(transA.parent), b) +ldiv!(adjA::Adjoint{<:Any,<:Bidiagonal}, b::AbstractVector) = ldiv!(adjoint(adjA.parent), b) function ldiv!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) nA,mA = size(A) tmp = similar(B,size(B,1)) @@ -516,7 +516,7 @@ function ldiv!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) end for i = 1:size(B,2) copy!(tmp, 1, B, (i - 1)*n + 1, n) - A_ldiv_B!(A, tmp) + ldiv!(A, tmp) copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. end B @@ -531,7 +531,7 @@ function ldiv!(adjA::Adjoint{<:Any,<:Union{Bidiagonal,AbstractTriangular}}, B::A end for i = 1:size(B,2) copy!(tmp, 1, B, (i - 1)*n + 1, n) - Ac_ldiv_B!(A, tmp) + ldiv!(Adjoint(A), tmp) copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. end B @@ -546,7 +546,7 @@ function ldiv!(transA::Transpose{<:Any,<:Union{Bidiagonal,AbstractTriangular}}, end for i = 1:size(B,2) copy!(tmp, 1, B, (i - 1)*n + 1, n) - At_ldiv_B!(A, tmp) + ldiv!(Transpose(A), tmp) copy!(B, (i - 1)*n + 1, tmp, 1, n) # Modify this when array view are implemented. end B @@ -577,23 +577,23 @@ end function \(A::Bidiagonal{<:Number}, B::AbstractVecOrMat{<:Number}) TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) - A_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) + ldiv!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end -\(A::Bidiagonal, B::AbstractVecOrMat) = A_ldiv_B!(A, copy(B)) +\(A::Bidiagonal, B::AbstractVecOrMat) = ldiv!(A, copy(B)) function \(transA::Transpose{<:Number,<:Bidiagonal{<:Number}}, B::AbstractVecOrMat{<:Number}) A = transA.parent TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) - At_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) + ldiv!(Transpose(convert(AbstractArray{TAB}, A)), copy_oftype(B, TAB)) end -\(transA::Transpose{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = At_ldiv_B!(transA.parent, copy(B)) +\(transA::Transpose{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = ldiv!(Transpose(transA.parent), copy(B)) function \(adjA::Adjoint{<:Number,<:Bidiagonal{<:Number}}, B::AbstractVecOrMat{<:Number}) A = adjA.parent TA, TB = eltype(A), eltype(B) TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) - Ac_ldiv_B!(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) + ldiv!(Adjoint(convert(AbstractArray{TAB}, A)), copy_oftype(B, TAB)) end -\(adjA::Adjoint{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = Ac_ldiv_B!(adjA.parent, copy(B)) +\(adjA::Adjoint{<:Any,<:Bidiagonal}, B::AbstractVecOrMat) = ldiv!(Adjoint(adjA.parent), copy(B)) factorize(A::Bidiagonal) = A From c1aa72cbf98dc79b9a535d2b4fb985281925e9b2 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 17:09:11 -0800 Subject: [PATCH 32/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/bunchkaufman.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/bunchkaufman.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index d812f603548cf6..e856d6b742e06c 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -287,7 +287,7 @@ end # There is no fallback solver for Bunch-Kaufman so we'll have to promote to same element type function ldiv!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} TS = promote_type(T,S) - return A_ldiv_B!(convert(BunchKaufman{TS}, B), convert(AbstractArray{TS}, R)) + return ldiv!(convert(BunchKaufman{TS}, B), convert(AbstractArray{TS}, R)) end function logabsdet(F::BunchKaufman) From ecd02530a0352013b755472b8e97363a4682dcb2 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 17:11:35 -0800 Subject: [PATCH 33/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/cholesky.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/cholesky.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index cc122aededd796..bfaec7a83476b9 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -424,9 +424,9 @@ ldiv!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloa function ldiv!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) if C.uplo == 'L' - return Ac_ldiv_B!(LowerTriangular(C.factors), A_ldiv_B!(LowerTriangular(C.factors), B)) + return ldiv!(Adjoint(LowerTriangular(C.factors)), ldiv!(LowerTriangular(C.factors), B)) else - return A_ldiv_B!(UpperTriangular(C.factors), Ac_ldiv_B!(UpperTriangular(C.factors), B)) + return ldiv!(UpperTriangular(C.factors), ldiv!(Adjoint(UpperTriangular(C.factors)), B)) end end @@ -449,21 +449,21 @@ end function ldiv!(C::CholeskyPivoted, B::StridedVector) if C.uplo == 'L' - Ac_ldiv_B!(LowerTriangular(C.factors), - A_ldiv_B!(LowerTriangular(C.factors), B[C.piv]))[invperm(C.piv)] + ldiv!(Adjoint(LowerTriangular(C.factors)), + ldiv!(LowerTriangular(C.factors), B[C.piv]))[invperm(C.piv)] else - A_ldiv_B!(UpperTriangular(C.factors), - Ac_ldiv_B!(UpperTriangular(C.factors), B[C.piv]))[invperm(C.piv)] + ldiv!(UpperTriangular(C.factors), + ldiv!(Adjoint(UpperTriangular(C.factors)), B[C.piv]))[invperm(C.piv)] end end function ldiv!(C::CholeskyPivoted, B::StridedMatrix) if C.uplo == 'L' - Ac_ldiv_B!(LowerTriangular(C.factors), - A_ldiv_B!(LowerTriangular(C.factors), B[C.piv,:]))[invperm(C.piv),:] + ldiv!(Adjoint(LowerTriangular(C.factors)), + ldiv!(LowerTriangular(C.factors), B[C.piv,:]))[invperm(C.piv),:] else - A_ldiv_B!(UpperTriangular(C.factors), - Ac_ldiv_B!(UpperTriangular(C.factors), B[C.piv,:]))[invperm(C.piv),:] + ldiv!(UpperTriangular(C.factors), + ldiv!(Adjoint(UpperTriangular(C.factors)), B[C.piv,:]))[invperm(C.piv),:] end end From fc0accde1f3413eaba59c1b4fdc665490016ffeb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 17:15:16 -0800 Subject: [PATCH 34/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/dense.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/dense.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index aafe437d80a20d..1adbfc683ce784 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -1400,9 +1400,9 @@ function sylvester(A::StridedMatrix{T},B::StridedMatrix{T},C::StridedMatrix{T}) RA, QA = schur(A) RB, QB = schur(B) - D = -Ac_mul_B(QA,C*QB) + D = -(Adjoint(QA) * (C*QB)) Y, scale = LAPACK.trsyl!('N','N', RA, RB, D) - scale!(QA*A_mul_Bc(Y,QB), inv(scale)) + scale!(QA*(Y * Adjoint(QB)), inv(scale)) end sylvester(A::StridedMatrix{T}, B::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:Integer} = sylvester(float(A), float(B), float(C)) @@ -1443,9 +1443,9 @@ julia> A*X + X*A' + B function lyap(A::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:BlasFloat} R, Q = schur(A) - D = -Ac_mul_B(Q,C*Q) + D = -(Adjoint(Q) * (C*Q)) Y, scale = LAPACK.trsyl!('N', T <: Complex ? 'C' : 'T', R, R, D) - scale!(Q*A_mul_Bc(Y,Q), inv(scale)) + scale!(Q*(Y * Adjoint(Q)), inv(scale)) end lyap(A::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:Integer} = lyap(float(A), float(C)) lyap(a::T, c::T) where {T<:Number} = -c/(2a) From 5673e1add1287212071c7a66e2232c61fe4705df Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:04:17 -0800 Subject: [PATCH 35/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/diagonal.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/diagonal.jl | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index daa61a50fd4ae5..a6f70e68dc252f 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -150,38 +150,38 @@ end (*)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .* Db.diag) (*)(D::Diagonal, V::AbstractVector) = D.diag .* V -(*)(A::AbstractTriangular, D::Diagonal) = A_mul_B!(copy(A), D) -(*)(D::Diagonal, B::AbstractTriangular) = A_mul_B!(D, copy(B)) +(*)(A::AbstractTriangular, D::Diagonal) = mul!(copy(A), D) +(*)(D::Diagonal, B::AbstractTriangular) = mul!(D, copy(B)) (*)(A::AbstractMatrix, D::Diagonal) = scale!(similar(A, promote_op(*, eltype(A), eltype(D.diag)), size(A)), A, D.diag) (*)(D::Diagonal, A::AbstractMatrix) = scale!(similar(A, promote_op(*, eltype(A), eltype(D.diag)), size(A)), D.diag, A) -mul!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal) = typeof(A)(A_mul_B!(A.data, D)) +mul!(A::Union{LowerTriangular,UpperTriangular}, D::Diagonal) = typeof(A)(mul!(A.data, D)) function mul!(A::UnitLowerTriangular, D::Diagonal) - A_mul_B!(A.data, D) + mul!(A.data, D) for i = 1:size(A, 1) A.data[i,i] = D.diag[i] end LowerTriangular(A.data) end function mul!(A::UnitUpperTriangular, D::Diagonal) - A_mul_B!(A.data, D) + mul!(A.data, D) for i = 1:size(A, 1) A.data[i,i] = D.diag[i] end UpperTriangular(A.data) end function mul!(D::Diagonal, B::UnitLowerTriangular) - A_mul_B!(D, B.data) + mul!(D, B.data) for i = 1:size(B, 1) B.data[i,i] = D.diag[i] end LowerTriangular(B.data) end function mul!(D::Diagonal, B::UnitUpperTriangular) - A_mul_B!(D, B.data) + mul!(D, B.data) for i = 1:size(B, 1) B.data[i,i] = D.diag[i] end @@ -189,40 +189,40 @@ function mul!(D::Diagonal, B::UnitUpperTriangular) end *(adjD::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = (D = adjD.parent; Diagonal(adjoint.(D.diag) .* B.diag)) -*(adjA::Adjoint{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = adjA.parent; A_mul_B!(adjoint(A), D)) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = adjA.parent; mul!(adjoint(A), D)) function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, D::Diagonal) A = adjA.parent Ac = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) adjoint!(Ac, A) - A_mul_B!(Ac, D) + mul!(Ac, D) end *(transD::Transpose{<:Any,<:Diagonal}, B::Diagonal) = (D = transD.parent; Diagonal(transpose.(D.diag) .* B.diag)) -*(transA::Transpose{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = transA.parent; A_mul_B!(transpose(A), D)) +*(transA::Transpose{<:Any,<:AbstractTriangular}, D::Diagonal) = (A = transA.parent; mul!(transpose(A), D)) function *(transA::Transpose{<:Any,<:AbstractMatrix}, D::Diagonal) A = transA.parent At = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) transpose!(At, A) - A_mul_B!(At, D) + mul!(At, D) end *(D::Diagonal, adjB::Adjoint{<:Any,<:Diagonal}) = (B = adjB.parent; Diagonal(D.diag .* adjoint.(B.diag))) -*(D::Diagonal, adjB::Adjoint{<:Any,<:AbstractTriangular}) = (B = adjB.parent; A_mul_B!(D, adjoint(B))) -*(D::Diagonal, adjQ::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (Q = adjQ.parent; A_mul_Bc!(Array(D), Q)) +*(D::Diagonal, adjB::Adjoint{<:Any,<:AbstractTriangular}) = (B = adjB.parent; mul!(D, adjoint(B))) +*(D::Diagonal, adjQ::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (Q = adjQ.parent; mul!(Array(D), Adjoint(Q))) function *(D::Diagonal, adjA::Adjoint{<:Any,<:AbstractMatrix}) A = adjA.parent Ac = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) adjoint!(Ac, A) - A_mul_B!(D, Ac) + mul!(D, Ac) end *(D::Diagonal, transB::Transpose{<:Any,<:Diagonal}) = (B = transB.parent; Diagonal(D.diag .* transpose.(B.diag))) -*(D::Diagonal, transB::Transpose{<:Any,<:AbstractTriangular}) = (B = transB.parent; A_mul_B!(D, transpose(B))) +*(D::Diagonal, transB::Transpose{<:Any,<:AbstractTriangular}) = (B = transB.parent; mul!(D, transpose(B))) function *(D::Diagonal, transA::Transpose{<:Any,<:AbstractMatrix}) A = transA.parent At = similar(A, promote_op(*, eltype(A), eltype(D.diag)), (size(A, 2), size(A, 1))) transpose!(At, A) - A_mul_B!(D, At) + mul!(D, At) end *(adjD::Adjoint{<:Any,<:Diagonal}, adjB::Adjoint{<:Any,<:Diagonal}) = @@ -326,9 +326,9 @@ function ldiv!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} end ldiv!(adjD::Adjoint{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} = - (D = adjD.parent; A_ldiv_B!(conj(D), B)) + (D = adjD.parent; ldiv!(conj(D), B)) ldiv!(transD::Transpose{<:Any,<:Diagonal{T}}, B::AbstractVecOrMat{T}) where {T} = - (D = transD.parent; A_ldiv_B!(D, B)) + (D = transD.parent; ldiv!(D, B)) function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} dd = D.diag @@ -349,14 +349,14 @@ function rdiv!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} end rdiv!(A::AbstractMatrix{T}, adjD::Adjoint{<:Any,<:Diagonal{T}}) where {T} = - (D = adjD.parent; A_rdiv_B!(A, conj(D))) + (D = adjD.parent; rdiv!(A, conj(D))) rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = - (D = transD.parent; A_rdiv_B!(A, D)) + (D = transD.parent; rdiv!(A, D)) (\)(F::Factorization, D::Diagonal) = - A_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D)) + ldiv!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D)) \(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) = - (F = adjF.parent; Ac_ldiv_B!(F, Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))) + (F = adjF.parent; ldiv!(Adjoint(F), Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))) # Methods to resolve ambiguities with `Diagonal` @inline *(rowvec::RowVector, D::Diagonal) = transpose(D * transpose(rowvec)) From c98439dc88de461cb68c5f54dc9a7019fefded6f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:06:38 -0800 Subject: [PATCH 36/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/factorization.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/factorization.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 9d498fe2692762..d99c0717992444 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -47,7 +47,7 @@ end ### General promotion rules convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F -inv(F::Factorization{T}) where {T} = (n = size(F, 1); A_ldiv_B!(F, Matrix{T}(I, n, n))) +inv(F::Factorization{T}) where {T} = (n = size(F, 1); ldiv!(F, Matrix{T}(I, n, n))) Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, h, 1:nfields(F)) Base.:(==)( F::T, G::T) where {T<:Factorization} = all(f -> getfield(F, f) == getfield(G, f), 1:nfields(F)) @@ -57,7 +57,7 @@ Base.isequal(F::T, G::T) where {T<:Factorization} = all(f -> isequal(getfield(F, # the complex rhs as a real rhs with twice the number of columns function (\)(F::Factorization{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal c2r = reshape(transpose(reinterpret(T, reshape(B, (1, length(B))))), size(B, 1), 2*size(B, 2)) - x = A_ldiv_B!(F, c2r) + x = ldiv!(F, c2r) return reshape(collect(reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)))), _ret_size(F, B)) end @@ -65,26 +65,26 @@ function \(F::Factorization, B::AbstractVecOrMat) TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copy!(BB, B) - A_ldiv_B!(F, BB) + ldiv!(F, BB) end function \(adjF::Adjoint{<:Any,<:Factorization}, B::AbstractVecOrMat) F = adjF.parent TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copy!(BB, B) - Ac_ldiv_B!(F, BB) + ldiv!(Adjoint(F), BB) end # support the same 3-arg idiom as in our other in-place A_*_B functions: -ldiv!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = A_ldiv_B!(A, copy!(Y, B)) +ldiv!(Y::AbstractVecOrMat, A::Factorization, B::AbstractVecOrMat) = ldiv!(A, copy!(Y, B)) ldiv!(Y::AbstractVecOrMat, adjA::Adjoint{<:Any,<:Factorization}, B::AbstractVecOrMat) = - (A = adjA.parent; Ac_ldiv_B!(A, copy!(Y, B))) + (A = adjA.parent; ldiv!(Adjoint(A), copy!(Y, B))) ldiv!(Y::AbstractVecOrMat, transA::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = - (A = transA.parent; At_ldiv_B!(A, copy!(Y, B))) + (A = transA.parent; ldiv!(Transpose(A), copy!(Y, B))) # fallback methods for transposed solves -\(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; Ac_ldiv_B(F, B)) -\(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(Ac_ldiv_B(F, conj.(B)))) +\(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; \(Adjoint(F), B)) +\(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(\(Adjoint(F), conj.(B)))) # dismabiguation methods \(A::Adjoint{<:Any,<:Factorization}, B::RowVector) = adjoint(A.parent) \ B From a12f57e984404f7dcb540a4cb76dcc9ff202cde4 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:12:22 -0800 Subject: [PATCH 37/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/generic.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/generic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index a88d7e886201ab..8ec784332a418d 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -811,7 +811,7 @@ function inv(A::AbstractMatrix{T}) where T S = typeof(zero(T)/one(T)) # dimensionful S0 = typeof(zero(T)/oneunit(T)) # dimensionless dest = Matrix{S0}(I, n, n) - A_ldiv_B!(factorize(convert(AbstractMatrix{S}, A)), dest) + ldiv!(factorize(convert(AbstractMatrix{S}, A)), dest) end function pinv(v::AbstractVector{T}, tol::Real=real(zero(T))) where T From 16c5ce70c31fc8ed07da321932c230bcb391c0bb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:13:40 -0800 Subject: [PATCH 38/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/givens.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/givens.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index d953dafcfc2c9b..27dc2a99790296 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -7,14 +7,14 @@ transpose(R::AbstractRotation) = error("transpose not implemented for $(typeof(R function *(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - A_mul_B!(convert(AbstractRotation{TS}, R), TS == S ? copy(A) : convert(AbstractArray{TS}, A)) + mul!(convert(AbstractRotation{TS}, R), TS == S ? copy(A) : convert(AbstractArray{TS}, A)) end *(A::AbstractVector, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) *(A::AbstractMatrix, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) function _absvecormat_mul_adjrot(A::AbstractVecOrMat{T}, adjR::Adjoint{<:Any,<:AbstractRotation{S}}) where {T,S} R = adjR.parent TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - A_mul_Bc!(TS == T ? copy(A) : convert(AbstractArray{TS}, A), convert(AbstractRotation{TS}, R)) + mul!(TS == T ? copy(A) : convert(AbstractArray{TS}, A), Adjoint(convert(AbstractRotation{TS}, R))) end """ LinAlg.Givens(i1,i2,c,s) -> G @@ -354,14 +354,14 @@ function mul!(G::Givens, R::Rotation) end function mul!(R::Rotation, A::AbstractMatrix) @inbounds for i = 1:length(R.rotations) - A_mul_B!(R.rotations[i], A) + mul!(R.rotations[i], A) end return A end function mul!(A::AbstractMatrix, adjR::Adjoint{<:Any,<:Rotation}) R = adjR.parent @inbounds for i = 1:length(R.rotations) - A_mul_Bc!(A, R.rotations[i]) + mul!(A, Adjoint(R.rotations[i])) end return A end From 9e9afcf041613da34f9e9eda4cf6af414d908a7b Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:14:46 -0800 Subject: [PATCH 39/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/hessenberg.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/hessenberg.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 3be7b7fb18326a..ca64cb8259b4e3 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -73,7 +73,7 @@ function getindex(A::HessenbergQ, i::Integer, j::Integer) x[i] = 1 y = zeros(eltype(A), size(A, 2)) y[j] = 1 - return dot(x, A_mul_B!(A, y)) + return dot(x, mul!(A, y)) end ## reconstruct the original matrix @@ -96,19 +96,19 @@ mul!(X::StridedMatrix{T}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T<:BlasF function (*)(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - return A_mul_B!(Q, copy_oftype(X, TT)) + return mul!(Q, copy_oftype(X, TT)) end function (*)(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - return A_mul_B!(copy_oftype(X, TT), Q) + return mul!(copy_oftype(X, TT), Q) end function *(adjQ::Adjoint{<:Any,<:HessenbergQ{T}}, X::StridedVecOrMat{S}) where {T,S} Q = adjQ.parent TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - return Ac_mul_B!(Q, copy_oftype(X, TT)) + return mul!(Adjoint(Q), copy_oftype(X, TT)) end function *(X::StridedVecOrMat{S}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T,S} Q = adjQ.parent TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - return A_mul_Bc!(copy_oftype(X, TT), Q) + return mul!(copy_oftype(X, TT), Adjoint(Q)) end From aa56327d9f54f95f79e712786282d01a1f68b72d Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:17:54 -0800 Subject: [PATCH 40/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/lq.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/lq.jl | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 04c11425fb2554..005a6760872857 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -57,7 +57,7 @@ function lq(A::Union{Number,AbstractMatrix}; full::Bool = false, thin::Union{Boo end F = lqfact(A) L, Q = F[:L], F[:Q] - return L, !full ? Array(Q) : A_mul_B!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2))) + return L, !full ? Array(Q) : mul!(Q, Matrix{eltype(Q)}(I, size(Q.factors, 2), size(Q.factors, 2))) end copy(A::LQ) = LQ(copy(A.factors), copy(A.τ)) @@ -84,7 +84,7 @@ function getindex(A::LQ, d::Symbol) end getindex(A::LQPackedQ, i::Integer, j::Integer) = - A_mul_B!(A, setindex!(zeros(eltype(A), size(A, 2)), 1, j))[i] + mul!(A, setindex!(zeros(eltype(A), size(A, 2)), 1, j))[i] getq(A::LQ) = LQPackedQ(A.factors, A.τ) @@ -125,18 +125,18 @@ mul!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = mul!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = A[:L] * LAPACK.ormlq!('L', 'N', A.factors, A.τ, Matrix(B)) mul!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = - A_mul_B!(zeros(eltype(A), size(A)), Matrix(A), Matrix(B)) + mul!(zeros(eltype(A), size(A)), Matrix(A), Matrix(B)) function *(A::LQ{TA}, B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) - A_mul_B!(convert(Factorization{TAB},A), copy_oftype(B, TAB)) + mul!(convert(Factorization{TAB},A), copy_oftype(B, TAB)) end function *(A::LQ{TA},B::QR{TB}) where {TA,TB} TAB = promote_type(TA, TB) - A_mul_B!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) + mul!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) end function *(A::QR{TA},B::LQ{TB}) where {TA,TB} TAB = promote_type(TA, TB) - A_mul_B!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) + mul!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) end *(A::Adjoint{<:Any,<:LQ}, B::LQ) = adjoint(A.parent) * B *(A::LQ, B::Adjoint{<:Any,<:LQ}) = A * adjoint(B.parent) @@ -146,7 +146,7 @@ end mul!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) function (*)(A::LQPackedQ, B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) - A_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) + mul!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) end ### QcB @@ -158,9 +158,9 @@ function *(adjA::Adjoint{<:Any,<:LQPackedQ}, B::StridedVecOrMat) A = adjA.parent TAB = promote_type(eltype(A), eltype(B)) if size(B,1) == size(A.factors,2) - Ac_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) + mul!(Adjoint(convert(AbstractMatrix{TAB}, A)), copy_oftype(B, TAB)) elseif size(B,1) == size(A.factors,1) - Ac_mul_B!(convert(AbstractMatrix{TAB}, A), [B; zeros(TAB, size(A.factors, 2) - size(A.factors, 1), size(B, 2))]) + mul!(Adjoint(convert(AbstractMatrix{TAB}, A)), [B; zeros(TAB, size(A.factors, 2) - size(A.factors, 1), size(B, 2))]) else throw(DimensionMismatch("first dimension of B, $(size(B,1)), must equal one of the dimensions of A, $(size(A))")) end @@ -172,14 +172,14 @@ function *(A::LQPackedQ, adjB::Adjoint{<:Any,<:StridedVecOrMat}) TAB = promote_type(eltype(A), eltype(B)) BB = similar(B, TAB, (size(B, 2), size(B, 1))) adjoint!(BB, B) - return A_mul_B!(A, BB) + return mul!(A, BB) end function *(adjA::Adjoint{<:Any,<:LQPackedQ}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) A, B = adjA.parent, adjB.parent TAB = promote_type(eltype(A), eltype(B)) BB = similar(B, TAB, (size(B, 2), size(B, 1))) adjoint!(BB, B) - return Ac_mul_B!(A, BB) + return mul!(Adjoint(A), BB) end # in-place right-application of LQPackedQs @@ -209,13 +209,13 @@ mul!(A::StridedMatrix{T}, adjB::Adjoint{<:Any,<:LQPackedQ{T}}) where {T<:BlasCom function *(A::StridedVecOrMat, adjQ::Adjoint{<:Any,<:LQPackedQ}) Q = adjQ.parent TR = promote_type(eltype(A), eltype(Q)) - return A_mul_Bc!(copy_oftype(A, TR), convert(AbstractMatrix{TR}, Q)) + return mul!(copy_oftype(A, TR), Adjoint(convert(AbstractMatrix{TR}, Q))) end function *(adjA::Adjoint{<:Any,<:StridedMatrix}, adjQ::Adjoint{<:Any,<:LQPackedQ}) A, Q = adjA.parent, adjQ.parent TR = promote_type(eltype(A), eltype(Q)) C = adjoint!(similar(A, TR, reverse(size(A))), A) - return A_mul_Bc!(C, convert(AbstractMatrix{TR}, Q)) + return mul!(C, Adjoint(convert(AbstractMatrix{TR}, Q))) end # # (2) the inner dimension in the multiplication is the LQPackedQ's first dimension. @@ -240,7 +240,7 @@ function *(A::StridedVecOrMat, Q::LQPackedQ) else _rightappdimmismatch("columns") end - return A_mul_B!(C, convert(AbstractMatrix{TR}, Q)) + return mul!(C, convert(AbstractMatrix{TR}, Q)) end function *(adjA::Adjoint{<:Any,<:StridedMatrix}, Q::LQPackedQ) A = adjA.parent @@ -253,7 +253,7 @@ function *(adjA::Adjoint{<:Any,<:StridedMatrix}, Q::LQPackedQ) else _rightappdimmismatch("rows") end - return A_mul_B!(C, convert(AbstractMatrix{TR}, Q)) + return mul!(C, convert(AbstractMatrix{TR}, Q)) end _rightappdimmismatch(rowsorcols) = throw(DimensionMismatch(string("the number of $(rowsorcols) of the matrix on the left ", @@ -267,7 +267,7 @@ function (\)(A::LQ{TA}, b::StridedVector{Tb}) where {TA,Tb} m = checksquare(A) m == length(b) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has length $(length(b))")) AA = convert(Factorization{S}, A) - x = A_ldiv_B!(AA, copy_oftype(b, S)) + x = ldiv!(AA, copy_oftype(b, S)) return x end function (\)(A::LQ{TA},B::StridedMatrix{TB}) where {TA,TB} @@ -275,20 +275,20 @@ function (\)(A::LQ{TA},B::StridedMatrix{TB}) where {TA,TB} m = checksquare(A) m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) AA = convert(Factorization{S}, A) - X = A_ldiv_B!(AA, copy_oftype(B, S)) + X = ldiv!(AA, copy_oftype(B, S)) return X end # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal c2r = reshape(transpose(reinterpret(T, reshape(B, (1, length(B))))), size(B, 1), 2*size(B, 2)) - x = A_ldiv_B!(F, c2r) + x = ldiv!(F, c2r) return reshape(collect(reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)))), isa(B, AbstractVector) ? (size(F,2),) : (size(F,2), size(B,2))) end function ldiv!(A::LQ{T}, B::StridedVecOrMat{T}) where T - Ac_mul_B!(A[:Q], A_ldiv_B!(LowerTriangular(A[:L]),B)) + mul!(Adjoint(A[:Q]), ldiv!(LowerTriangular(A[:L]),B)) return B end From 2883770c4259d0470a9d8ec9ad9503441cfa5edf Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:20:32 -0800 Subject: [PATCH 41/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/lu.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/lu.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 9e3ef416d708fb..b25a8aee89c0f5 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -307,7 +307,7 @@ ldiv!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = function ldiv!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat) _apply_ipiv!(A, B) - A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B)) + ldiv!(UpperTriangular(A.factors), ldiv!(UnitLowerTriangular(A.factors), B)) end ldiv!(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @@ -315,18 +315,18 @@ ldiv!(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where function ldiv!(transA::Transpose{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) A = transA.parent - At_ldiv_B!(UnitLowerTriangular(A.factors), At_ldiv_B!(UpperTriangular(A.factors), B)) + ldiv!(Transpose(UnitLowerTriangular(A.factors)), ldiv!(Transpose(UpperTriangular(A.factors)), B)) _apply_inverse_ipiv!(A, B) end ldiv!(adjF::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:Real} = - (F = adjF.parent; At_ldiv_B!(F, B)) + (F = adjF.parent; ldiv!(Transpose(F), B)) ldiv!(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = (A = adjA.parent; @assertnonsingular(LAPACK.getrs!('C', A.factors, A.ipiv, B), A.info)) function ldiv!(adjA::Adjoint{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat) A = adjA.parent - Ac_ldiv_B!(UnitLowerTriangular(A.factors), Ac_ldiv_B!(UpperTriangular(A.factors), B)) + ldiv!(Adjoint(UnitLowerTriangular(A.factors)), ldiv!(Adjoint(UpperTriangular(A.factors)), B)) _apply_inverse_ipiv!(A, B) end @@ -336,7 +336,7 @@ function \(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info end \(transA::Transpose{<:Any,<:LU}, transB::Transpose{<:Any,<:StridedVecOrMat}) = - (A = transA.parent; B = transB.parent; At_ldiv_B(A, transpose(B))) + (A = transA.parent; B = transB.parent; \(Transpose(A), transpose(B))) function \(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, adjB::Adjoint{T,<:StridedVecOrMat{T}}) where {T<:BlasComplex} @@ -344,7 +344,7 @@ function \(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, adjoint(B)) A.info end \(adjA::Adjoint{<:Any,<:LU}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) = - (A = adjA.parent; B = adjB.parent; Ac_ldiv_B(A, adjoint(B))) + (A = adjA.parent; B = adjB.parent; \(Adjoint(A), adjoint(B))) function det(F::LU{T}) where T n = checksquare(F) @@ -382,7 +382,7 @@ end inv!(A::LU{<:BlasFloat,<:StridedMatrix}) = @assertnonsingular LAPACK.getri!(A.factors, A.ipiv) A.info inv!(A::LU{T,<:StridedMatrix}) where {T} = - @assertnonsingular A_ldiv_B!(A.factors, copy(A), Matrix{T}(I, size(A, 1), size(A, 1))) A.info + @assertnonsingular ldiv!(A.factors, copy(A), Matrix{T}(I, size(A, 1), size(A, 1))) A.info inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(copy(A)) function _cond1Inf(A::LU{<:BlasFloat,<:StridedMatrix}, p::Number, normA::Real) @@ -590,7 +590,7 @@ function ldiv!(adjA::Adjoint{<:Any,LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) return B end -/(B::AbstractMatrix,A::LU) = At_ldiv_Bt(A,B).' +/(B::AbstractMatrix,A::LU) = \(Transpose(A),Transpose(B)).' # Conversions convert(::Type{AbstractMatrix}, F::LU) = (F[:L] * F[:U])[invperm(F[:p]),:] From 5226436d69a27a1689b951b669962de5d25b3a88 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:53:42 -0800 Subject: [PATCH 42/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/matmul.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/matmul.jl | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 090e37d6b51d7b..abcc734a70bf34 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -73,22 +73,22 @@ end # Matrix-vector multiplication function (*)(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} TS = promote_op(matprod, T, S) - A_mul_B!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) + mul!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) end function (*)(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} TS = promote_op(matprod, T, S) - A_mul_B!(similar(x,TS,size(A,1)),A,x) + mul!(similar(x,TS,size(A,1)),A,x) end # these will throw a DimensionMismatch unless B has 1 row (or 1 col for transposed case): *(a::AbstractVector, transB::Transpose{<:Any,<:AbstractMatrix}) = - (B = transB.parent; A_mul_Bt(reshape(a,length(a),1),B)) + (B = transB.parent; *(reshape(a,length(a),1), Transpose(B))) *(A::AbstractMatrix, transb::Transpose{<:Any,<:AbstractVector}) = - (b = transb.parent; A_mul_Bt(A,reshape(b,length(b),1))) + (b = transb.parent; *(A, Transpose(reshape(b,length(b),1)))) *(a::AbstractVector, adjB::Adjoint{<:Any,<:AbstractMatrix}) = - (B = adjB.parent; A_mul_Bc(reshape(a,length(a),1),B)) + (B = adjB.parent; *(reshape(a,length(a),1), Adjoint(B))) *(A::AbstractMatrix, adjb::Adjoint{<:Any,<:AbstractVector}) = - (b = adjb.parent; A_mul_Bc(A,reshape(b,length(b),1))) + (b = adjb.parent; *(A, Adjoint(reshape(b,length(b),1)))) (*)(a::AbstractVector, B::AbstractMatrix) = reshape(a,length(a),1)*B mul!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'N', A, x) @@ -107,12 +107,12 @@ mul!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvec function *(transA::Transpose{<:Any,<:StridedMatrix{T}}, x::StridedVector{S}) where {T<:BlasFloat,S} A = transA.parent TS = promote_op(matprod, T, S) - At_mul_B!(similar(x,TS,size(A,2)), A, convert(AbstractVector{TS}, x)) + mul!(similar(x,TS,size(A,2)), Transpose(A), convert(AbstractVector{TS}, x)) end function *(transA::Transpose{<:Any,<:AbstractMatrix{T}}, x::AbstractVector{S}) where {T,S} A = transA.parent TS = promote_op(matprod, T, S) - At_mul_B!(similar(x,TS,size(A,2)), A, x) + mul!(similar(x,TS,size(A,2)), Transpose(A), x) end mul!(y::StridedVector{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasFloat} = (A = transA.parent; gemv!(y, 'T', A, x)) @@ -122,16 +122,16 @@ mul!(y::AbstractVector, transA::Transpose{<:Any,<:AbstractVecOrMat}, x::Abstract function *(adjA::Adjoint{<:Any,<:StridedMatrix{T}}, x::StridedVector{S}) where {T<:BlasFloat,S} A = adjA.parent TS = promote_op(matprod, T, S) - Ac_mul_B!(similar(x,TS,size(A,2)),A,convert(AbstractVector{TS},x)) + mul!(similar(x,TS,size(A,2)), Adjoint(A) ,convert(AbstractVector{TS},x)) end function *(adjA::Adjoint{<:Any,<:AbstractMatrix{T}}, x::AbstractVector{S}) where {T,S} A = adjA.parent TS = promote_op(matprod, T, S) - Ac_mul_B!(similar(x,TS,size(A,2)), A, x) + mul!(similar(x,TS,size(A,2)), Adjoint(A), x) end mul!(y::StridedVector{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasReal} = - (A = adjA.parent; At_mul_B!(y, A, x)) + (A = adjA.parent; mul!(y, Transpose(A), x)) mul!(y::StridedVector{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, x::StridedVector{T}) where {T<:BlasComplex} = (A = adjA.parent; gemv!(y, 'C', A, x)) mul!(y::AbstractVector, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, x::AbstractVector) = @@ -156,7 +156,7 @@ julia> [1 1; 0 1] * [1 0; 1 1] """ function (*)(A::AbstractMatrix, B::AbstractMatrix) TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) + mul!(similar(B, TS, (size(A,1), size(B,2))), A, B) end mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'N', 'N', A, B) for elty in (Float32,Float64) @@ -200,7 +200,7 @@ mul!(A, B) function *(transA::Transpose{<:Any,<:AbstractMatrix}, B::AbstractMatrix) A = transA.parent TS = promote_op(matprod, eltype(A), eltype(B)) - At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) + mul!(similar(B, TS, (size(A,2), size(B,2))), Transpose(A), B) end mul!(C::StridedMatrix{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = (A = transA.parent; A===B ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B)) @@ -210,7 +210,7 @@ mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:AbstractVecOrMat}, B::Abstract function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractMatrix}) B = transB.parent TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) + mul!(similar(B, TS, (size(A,1), size(B,1))), A, Transpose(B)) end mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = (B = transB.parent; A===B ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B)) @@ -241,7 +241,7 @@ _disambigmul!(C::AbstractVecOrMat, A::AbstractVecOrMat, transB::Transpose{<:Any, function _disambigmul(transA::Transpose{<:Any,<:AbstractMatrix{T}}, transB::Transpose{<:Any,<:AbstractVecOrMat{S}}) where {T,S} A, B = transA.parent, transB.parent TS = promote_op(matprod, T, S) - At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) + mul!(similar(B, TS, (size(A,2), size(B,1))), Transpose(A), Transpose(B)) end mul!(C::StridedMatrix{T}, transA::Transpose{<:Any,<:StridedVecOrMat{T}}, transB::Transpose{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = (A = transA.parent; B = transB.parent; gemm_wrapper!(C, 'T', 'T', A, B)) @@ -250,13 +250,13 @@ mul!(C::AbstractMatrix, transA::Transpose{<:Any,<:AbstractVecOrMat}, transB::Tra mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractVecOrMat}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) *(adjA::Adjoint{<:Any,<:StridedMatrix{T}}, B::StridedMatrix{T}) where {T<:BlasReal} = - (A = adjA.parent; At_mul_B(A, B)) + (A = adjA.parent; *(Transpose(A), B)) mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasReal} = - (A = adjA.parent; At_mul_B!(C, A, B)) + (A = adjA.parent; mul!(C, Transpose(A), B)) function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, B::AbstractMatrix) A = adjA.parent TS = promote_op(matprod, eltype(A), eltype(B)) - Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) + mul!(similar(B, TS, (size(A,2), size(B,2))), Adjoint(A), B) end mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = (A = adjA.parent; A===B ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B)) @@ -264,13 +264,13 @@ mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, B::AbstractVecO (A = adjA.parent; generic_matmatmul!(C, 'C', 'N', A, B)) *(A::StridedMatrix{<:BlasFloat}, adjB::Adjoint{<:Any,<:StridedMatrix{<:BlasReal}}) = - (B = adjB.parent; A_mul_Bt(A, B)) + (B = adjB.parent; *(A, Transpose(B))) mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:StridedVecOrMat{<:BlasReal}}) where {T<:BlasFloat} = - (B = adjB.parent; A_mul_Bt!(C, A, B)) + (B = adjB.parent; mul!(C, A, Transpose(B))) function *(A::AbstractMatrix, adjB::Adjoint{<:Any,<:AbstractMatrix}) B = adjB.parent TS = promote_op(matprod, eltype(A), eltype(B)) - A_mul_Bc!(similar(B,TS,(size(A,1),size(B,1))),A,B) + mul!(similar(B,TS,(size(A,1),size(B,1))), A, Adjoint(B)) end mul!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasComplex} = (B = adjB.parent; A===B ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B)) @@ -278,7 +278,7 @@ mul!(C::AbstractMatrix, A::AbstractVecOrMat, adjB::Adjoint{<:Any,<:AbstractVecOr (B = adjB.parent; generic_matmatmul!(C, 'N', 'C', A, B)) *(adjA::Adjoint{<:Any,<:AbstractMatrix}, adjB::Adjoint{<:Any,<:AbstractMatrix}) = - (A = adjA.parent; B = adjB.parent; Ac_mul_Bc!(similar(B, promote_op(matprod, eltype(A), eltype(B)), (size(A,2), size(B,1))), A, B)) + (A = adjA.parent; B = adjB.parent; mul!(similar(B, promote_op(matprod, eltype(A), eltype(B)), (size(A,2), size(B,1))), Adjoint(A), Adjoint(B))) mul!(C::StridedMatrix{T}, adjA::Adjoint{<:Any,<:StridedVecOrMat{T}}, adjB::Adjoint{<:Any,<:StridedVecOrMat{T}}) where {T<:BlasFloat} = (A = adjA.parent; B = adjB.parent; gemm_wrapper!(C, 'C', 'C', A, B)) mul!(C::AbstractMatrix, adjA::Adjoint{<:Any,<:AbstractVecOrMat}, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = From e1db456e084c322cf62b485a5ce140988abd923e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 18:57:19 -0800 Subject: [PATCH 43/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/qr.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/qr.jl | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 8adc91052cf2b7..db28f03980f522 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -329,13 +329,13 @@ function _qr(A::Union{Number,AbstractMatrix}, ::Val{false}; full::Bool = false) F = qrfact(A, Val(false)) Q, R = getq(F), F[:R]::Matrix{eltype(F)} sQf1 = size(Q.factors, 1) - return (!full ? Array(Q) : A_mul_B!(Q, Matrix{eltype(Q)}(I, sQf1, sQf1))), R + return (!full ? Array(Q) : mul!(Q, Matrix{eltype(Q)}(I, sQf1, sQf1))), R end function _qr(A::Union{Number, AbstractMatrix}, ::Val{true}; full::Bool = false) F = qrfact(A, Val(true)) Q, R, p = getq(F), F[:R]::Matrix{eltype(F)}, F[:p]::Vector{BlasInt} sQf1 = size(Q.factors, 1) - return (!full ? Array(Q) : A_mul_B!(Q, Matrix{eltype(Q)}(I, sQf1, sQf1))), R, p + return (!full ? Array(Q) : mul!(Q, Matrix{eltype(Q)}(I, sQf1, sQf1))), R, p end """ @@ -508,7 +508,7 @@ convert(::Type{AbstractMatrix{T}}, Q::QRPackedQ) where {T} = convert(QRPackedQ{T convert(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ{S}) where {S} = Q convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) where {S} = convert(QRCompactWYQ{S}, Q) -convert(::Type{Matrix}, A::AbstractQ{T}) where {T} = A_mul_B!(A, Matrix{T}(I, size(A.factors, 1), min(size(A.factors)...))) +convert(::Type{Matrix}, A::AbstractQ{T}) where {T} = mul!(A, Matrix{T}(I, size(A.factors, 1), min(size(A.factors)...))) convert(::Type{Array}, A::AbstractQ) = convert(Matrix, A) size(A::Union{QR,QRCompactWY,QRPivoted}, dim::Integer) = size(A.factors, dim) @@ -522,7 +522,7 @@ function getindex(A::AbstractQ, i::Integer, j::Integer) x[i] = 1 y = zeros(eltype(A), size(A, 2)) y[j] = 1 - return dot(x, A_mul_B!(A, y)) + return dot(x, mul!(A, y)) end ## Multiplication by Q @@ -566,7 +566,7 @@ function (*)(A::AbstractQ, b::StridedVector) else throw(DimensionMismatch("vector must have length either $(size(A.factors, 1)) or $(size(A.factors, 2))")) end - A_mul_B!(Anew, bnew) + mul!(Anew, bnew) end function (*)(A::AbstractQ, B::StridedMatrix) TAB = promote_type(eltype(A), eltype(B)) @@ -578,7 +578,7 @@ function (*)(A::AbstractQ, B::StridedMatrix) else throw(DimensionMismatch("first dimension of matrix must have size either $(size(A.factors, 1)) or $(size(A.factors, 2))")) end - A_mul_B!(Anew, Bnew) + mul!(Anew, Bnew) end ### QcB @@ -618,7 +618,7 @@ end function *(adjQ::Adjoint{<:Any,<:AbstractQ}, B::StridedVecOrMat) Q = adjQ.parent TQB = promote_type(eltype(Q), eltype(B)) - return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), copy_oftype(B, TQB)) + return mul!(Adjoint(convert(AbstractMatrix{TQB}, Q)), copy_oftype(B, TQB)) end ### QBc/QcBc @@ -627,14 +627,14 @@ function *(Q::AbstractQ, adjB::Adjoint{<:Any,<:StridedVecOrMat}) TQB = promote_type(eltype(Q), eltype(B)) Bc = similar(B, TQB, (size(B, 2), size(B, 1))) adjoint!(Bc, B) - return A_mul_B!(convert(AbstractMatrix{TQB}, Q), Bc) + return mul!(convert(AbstractMatrix{TQB}, Q), Bc) end function *(adjQ::Adjoint{<:Any,<:AbstractQ}, adjB::Adjoint{<:Any,<:StridedVecOrMat}) Q, B = adjQ.parent, adjB.parent TQB = promote_type(eltype(Q), eltype(B)) Bc = similar(B, TQB, (size(B, 2), size(B, 1))) adjoint!(Bc, B) - return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), Bc) + return mul!(Adjoint(convert(AbstractMatrix{TQB}, Q)), Bc) end ### AQ @@ -669,7 +669,7 @@ end function (*)(A::StridedMatrix, Q::AbstractQ) TAQ = promote_type(eltype(A), eltype(Q)) - return A_mul_B!(copy_oftype(A, TAQ), convert(AbstractMatrix{TAQ}, Q)) + return mul!(copy_oftype(A, TAQ), convert(AbstractMatrix{TAQ}, Q)) end ### AQc @@ -713,9 +713,9 @@ function *(A::StridedMatrix, adjB::Adjoint{<:Any,<:AbstractQ}) if size(A,2) == size(B.factors, 1) AA = similar(A, TAB, size(A)) copy!(AA, A) - return A_mul_Bc!(AA, BB) + return mul!(AA, Adjoint(BB)) elseif size(A,2) == size(B.factors,2) - return A_mul_Bc!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], BB) + return mul!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], Adjoint(BB)) else throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(B))")) end @@ -729,20 +729,20 @@ function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, Q::AbstractQ) TAQ = promote_type(eltype(A), eltype(Q)) Ac = similar(A, TAQ, (size(A, 2), size(A, 1))) adjoint!(Ac, A) - return A_mul_B!(Ac, convert(AbstractMatrix{TAQ}, Q)) + return mul!(Ac, convert(AbstractMatrix{TAQ}, Q)) end function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, adjQ::Adjoint{<:Any,<:AbstractQ}) A, Q = adjA.parent, adjQ.parent TAQ = promote_type(eltype(A), eltype(Q)) Ac = similar(A, TAQ, (size(A, 2), size(A, 1))) adjoint!(Ac, A) - return A_mul_Bc!(Ac, convert(AbstractMatrix{TAQ}, Q)) + return mul!(Ac, Adjoint(convert(AbstractMatrix{TAQ}, Q))) end ldiv!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat} = - (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) + (ldiv!(UpperTriangular(A[:R]), view(mul!(Adjoint(A[:Q]), b), 1:size(A, 2))); b) ldiv!(A::QRCompactWY{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = - (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) + (ldiv!(UpperTriangular(A[:R]), view(mul!(Adjoint(A[:Q]), B), 1:size(A, 2), 1:size(B, 2))); B) # Julia implementation similar to xgelsy function ldiv!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:BlasFloat @@ -774,21 +774,21 @@ function ldiv!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:BlasF rnk += 1 end C, τ = LAPACK.tzrzf!(A.factors[1:rnk,:]) - A_ldiv_B!(UpperTriangular(C[1:rnk,1:rnk]),view(Ac_mul_B!(getq(A),view(B, 1:mA, 1:nrhs)),1:rnk,1:nrhs)) + ldiv!(UpperTriangular(C[1:rnk,1:rnk]),view(mul!(Adjoint(getq(A)), view(B, 1:mA, 1:nrhs)), 1:rnk, 1:nrhs)) B[rnk+1:end,:] = zero(T) LAPACK.ormrz!('L', eltype(B)<:Complex ? 'C' : 'T', C, τ, view(B,1:nA,1:nrhs)) B[1:nA,:] = view(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:] return B, rnk end ldiv!(A::QRPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = - vec(A_ldiv_B!(A,reshape(B,length(B),1))) + vec(ldiv!(A,reshape(B,length(B),1))) ldiv!(A::QRPivoted{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = - A_ldiv_B!(A, B, min(size(A)...)*eps(real(float(one(eltype(B))))))[1] + ldiv!(A, B, min(size(A)...)*eps(real(float(one(eltype(B))))))[1] function ldiv!(A::QR{T}, B::StridedMatrix{T}) where T m, n = size(A) minmn = min(m,n) mB, nB = size(B) - Ac_mul_B!(A[:Q], view(B, 1:m, :)) + mul!(Adjoint(A[:Q]), view(B, 1:m, :)) R = A[:R] @inbounds begin if n > m # minimum norm solution @@ -810,7 +810,7 @@ function ldiv!(A::QR{T}, B::StridedMatrix{T}) where T end end end - Base.A_ldiv_B!(UpperTriangular(view(R, :, 1:minmn)), view(B, 1:minmn, :)) + Base.LinAlg.ldiv!(UpperTriangular(view(R, :, 1:minmn)), view(B, 1:minmn, :)) if n > m # Apply elementary transformation to solution B[m + 1:mB,1:nB] = zero(T) for j = 1:nB @@ -830,14 +830,14 @@ function ldiv!(A::QR{T}, B::StridedMatrix{T}) where T end return B end -ldiv!(A::QR, B::StridedVector) = A_ldiv_B!(A, reshape(B, length(B), 1))[:] +ldiv!(A::QR, B::StridedVector) = ldiv!(A, reshape(B, length(B), 1))[:] function ldiv!(A::QRPivoted, b::StridedVector) - A_ldiv_B!(QR(A.factors,A.τ), b) + ldiv!(QR(A.factors,A.τ), b) b[1:size(A.factors, 2)] = view(b, 1:size(A.factors, 2))[invperm(A.jpvt)] b end function ldiv!(A::QRPivoted, B::StridedMatrix) - A_ldiv_B!(QR(A.factors, A.τ), B) + ldiv!(QR(A.factors, A.τ), B) B[1:size(A.factors, 2),:] = view(B, 1:size(A.factors, 2), :)[invperm(A.jpvt),:] B end @@ -862,7 +862,7 @@ function (\)(A::Union{QR{TA},QRCompactWY{TA},QRPivoted{TA}}, B::AbstractVecOrMat X = _zeros(S, B, n) X[1:size(B, 1), :] = B - A_ldiv_B!(AA, X) + ldiv!(AA, X) return _cut_B(X, 1:n) end @@ -887,7 +887,7 @@ function (\)(A::Union{QR{T},QRCompactWY{T},QRPivoted{T}}, BIn::VecOrMat{Complex{ X = _zeros(T, B, n) X[1:size(B, 1), :] = B - A_ldiv_B!(A, X) + ldiv!(A, X) # |z1|z3| reinterpret |x1|x2|x3|x4| transpose |x1|y1| reshape |x1|y1|x3|y3| # |z2|z4| <- |y1|y2|y3|y4| <- |x2|y2| <- |x2|y2|x4|y4| From d2a4b161ce3f21e49e0d7291d48ca881efa135fb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 19:03:07 -0800 Subject: [PATCH 44/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/special.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/special.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/linalg/special.jl b/base/linalg/special.jl index f9fb09da2cd381..2a751008e1869a 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -123,6 +123,6 @@ for op in (:+, :-) end mul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = - (B = adjB.parent; A_mul_Bc!(full!(A), B)) + (B = adjB.parent; mul!(full!(A), Adjoint(B))) *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = - (B = adjB.parent; A_mul_Bc(copy!(similar(parent(A)), A), B)) + (B = adjB.parent; *(copy!(similar(parent(A)), A), Adjoint(B))) From 591d22628a98b1fe0a0d48ad4315c3ce3a63da1a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 19:45:22 -0800 Subject: [PATCH 45/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/sparse/linalg.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/sparse/linalg.jl | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 8dbc89eec8b922..c30c0e7fc6e50d 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -8,17 +8,17 @@ import Base.LinAlg: checksquare *(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = *(sppromote(A, B)...) *(A::SparseMatrixCSC{TvA,TiA}, transB::Transpose{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = - (B = transB.parent; A_mul_Bt(sppromote(A, B)...)) + (B = transB.parent; (pA, pB) = sppromote(A, B); *(pA, Transpose(pB))) *(A::SparseMatrixCSC{TvA,TiA}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = - (B = adjB.parent; A_mul_Bc(sppromote(A, B)...)) + (B = adjB.parent; (pA, pB) = sppromote(A, B); *(pA, Adjoint(pB))) *(transA::Transpose{<:Any,<:SparseMatrixCSC{TvA,TiA}}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = - (A = transA.parent; At_mul_B(sppromote(A, B)...)) + (A = transA.parent; (pA, pB) = sppromote(A, B); *(Transpose(pA), pB)) *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TvA,TiA}}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} = - (A = adjA.parent; Ac_mul_B(sppromote(A, B)...)) + (A = adjA.parent; (pA, pB) = sppromote(A, B); *(Adjoint(pA), pB)) *(transA::Transpose{<:Any,<:SparseMatrixCSC{TvA,TiA}}, transB::Transpose{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = - (A = transA.parent; B = transB.parent; At_mul_Bt(sppromote(A, B)...)) + (A = transA.parent; B = transB.parent; (pA, pB) = sppromote(A, B); *(Transpose(pA), Transpose(pB))) *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TvA,TiA}}, adjB::Adjoint{<:Any,<:SparseMatrixCSC{TvB,TiB}}) where {TvA,TiA,TvB,TiB} = - (A = adjA.parent; B = adjB.parent; Ac_mul_Bc(sppromote(A, B)...)) + (A = adjA.parent; B = adjB.parent; (pA, pB) = sppromote(A, B); *(Adjoint(pA), Adjoint(pB))) function sppromote(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} Tv = promote_type(TvA, TvB) @@ -50,9 +50,9 @@ function mul!(α::Number, A::SparseMatrixCSC, B::StridedVecOrMat, β::Number, C: C end *(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} = - (T = promote_type(TA, Tx); A_mul_B!(one(T), A, x, zero(T), similar(x, T, A.m))) + (T = promote_type(TA, Tx); mul!(one(T), A, x, zero(T), similar(x, T, A.m))) *(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (T = promote_type(TA, Tx); A_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.m, size(B, 2))))) + (T = promote_type(TA, Tx); mul!(one(T), A, B, zero(T), similar(B, T, (A.m, size(B, 2))))) function mul!(α::Number, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) A = adjA.parent @@ -76,9 +76,9 @@ function mul!(α::Number, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecO C end *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = - (A = adjA.parent; T = promote_type(TA, Tx); Ac_mul_B!(one(T), A, x, zero(T), similar(x, T, A.n))) + (A = adjA.parent; T = promote_type(TA, Tx); mul!(one(T), Adjoint(A), x, zero(T), similar(x, T, A.n))) *(adjA::Adjoint{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (A = adjA.parent; T = promote_type(TA, Tx); Ac_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2))))) + (A = adjA.parent; T = promote_type(TA, Tx); mul!(one(T), Adjoint(A), B, zero(T), similar(B, T, (A.n, size(B, 2))))) function mul!(α::Number, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat, β::Number, C::StridedVecOrMat) A = transA.parent @@ -102,18 +102,18 @@ function mul!(α::Number, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::Strided C end *(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, x::StridedVector{Tx}) where {TA,S,Tx} = - (A = transA.parent; T = promote_type(TA, Tx); At_mul_B!(one(T), A, x, zero(T), similar(x, T, A.n))) + (A = transA.parent; T = promote_type(TA, Tx); mul!(one(T), Transpose(A), x, zero(T), similar(x, T, A.n))) *(transA::Transpose{<:Any,<:SparseMatrixCSC{TA,S}}, B::StridedMatrix{Tx}) where {TA,S,Tx} = - (A = transA.parent; T = promote_type(TA, Tx); At_mul_B!(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2))))) + (A = transA.parent; T = promote_type(TA, Tx); mul!(one(T), Transpose(A), B, zero(T), similar(B, T, (A.n, size(B, 2))))) # For compatibility with dense multiplication API. Should be deleted when dense multiplication # API is updated to follow BLAS API. mul!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = - A_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) + mul!(one(eltype(B)), A, B, zero(eltype(C)), C) mul!(C::StridedVecOrMat, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat) = - (A = adjA.parent; Ac_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C)) + (A = adjA.parent; mul!(one(eltype(B)), Adjoint(A), B, zero(eltype(C)), C)) mul!(C::StridedVecOrMat, transA::Transpose{<:Any,<:SparseMatrixCSC}, B::StridedVecOrMat) = - (A = transA.parent; At_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C)) + (A = transA.parent; mul!(one(eltype(B)), Transpose(A), B, zero(eltype(C)), C)) function (*)(X::StridedMatrix{TX}, A::SparseMatrixCSC{TvA,TiA}) where {TX,TvA,TiA} mX, nX = size(X) @@ -304,8 +304,8 @@ end ldiv!(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) ldiv!(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) -(\)(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(L, Array(B)) -(\)(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(U, Array(B)) +(\)(L::LowerTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = ldiv!(L, Array(B)) +(\)(U::UpperTriangular{T,<:SparseMatrixCSCUnion{T}}, B::SparseMatrixCSC) where {T} = ldiv!(U, Array(B)) \(A::Transpose{<:Real,<:Hermitian{<:Real,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B \(A::Transpose{<:Complex,<:Hermitian{<:Complex,<:SparseMatrixCSC}}, B::Vector) = transpose(A.parent) \ B \(A::Transpose{<:Number,<:Symmetric{<:Number,<:SparseMatrixCSC}}, B::Vector) = A.parent \ B @@ -329,9 +329,9 @@ function rdiv!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T end rdiv!(A::SparseMatrixCSC{T}, adjD::Adjoint{<:Any,<:Diagonal{T}}) where {T} = - (D = adjD.parent; A_rdiv_B!(A, conj(D))) + (D = adjD.parent; rdiv!(A, conj(D))) rdiv!(A::SparseMatrixCSC{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = - (D = transD.parent; A_rdiv_B!(A, D)) + (D = transD.parent; rdiv!(A, D)) ## triu, tril @@ -942,7 +942,7 @@ function \(A::SparseMatrixCSC, B::AbstractVecOrMat) end end \(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -for (xform, f) in ((:Adjoint, :Ac_ldiv_B), (:Transpose, :At_ldiv_B)) +for xform in (:Adjoint, :Transpose) @eval begin function \(xformA::($xform){<:Any,<:SparseMatrixCSC}, B::AbstractVecOrMat) A = xformA.parent @@ -950,19 +950,19 @@ for (xform, f) in ((:Adjoint, :Ac_ldiv_B), (:Transpose, :At_ldiv_B)) if m == n if istril(A) if istriu(A) - return ($f)(Diagonal(Vector(diag(A))), B) + return \($xform(Diagonal(Vector(diag(A)))), B) else - return ($f)(LowerTriangular(A), B) + return \($xform(LowerTriangular(A)), B) end elseif istriu(A) - return ($f)(UpperTriangular(A), B) + return \($xform(UpperTriangular(A)), B) end if ishermitian(A) - return ($f)(Hermitian(A), B) + return \($xform(Hermitian(A)), B) end - return ($f)(lufact(A), B) + return \($xform(lufact(A)), B) else - return ($f)(qrfact(A), B) + return \($xform(qrfact(A)), B) end end \(::($xform){<:Any,<:SparseMatrixCSC}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) From be73121da006c359a4e1a92f1f5cb70c1e2e246f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 19:56:54 -0800 Subject: [PATCH 46/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/statistics.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/statistics.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index 0a2b0268b61bc8..b0080206005e97 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -327,11 +327,11 @@ unscaled_covzm(x::AbstractMatrix, vardim::Int) = (vardim == 1 ? _conj(x'x) : x * unscaled_covzm(x::AbstractVector, y::AbstractVector) = dot(y, x) unscaled_covzm(x::AbstractVector, y::AbstractMatrix, vardim::Int) = - (vardim == 1 ? At_mul_B(x, _conj(y)) : At_mul_Bt(x, _conj(y))) + (vardim == 1 ? *(Transpose(x), _conj(y)) : *(Transpose(x), Transpose(_conj(y)))) unscaled_covzm(x::AbstractMatrix, y::AbstractVector, vardim::Int) = - (c = vardim == 1 ? At_mul_B(x, _conj(y)) : x * _conj(y); reshape(c, length(c), 1)) + (c = vardim == 1 ? *(Transpose(x), _conj(y)) : x * _conj(y); reshape(c, length(c), 1)) unscaled_covzm(x::AbstractMatrix, y::AbstractMatrix, vardim::Int) = - (vardim == 1 ? At_mul_B(x, _conj(y)) : A_mul_Bc(x, y)) + (vardim == 1 ? *(Transpose(x), _conj(y)) : *(x, Adjoint(y))) # covzm (with centered data) From bdba40b973028a6e770465177d5a69257f66a0a2 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 10 Dec 2017 20:55:44 -0800 Subject: [PATCH 47/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/sparse/sparsevector.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/sparse/sparse.jl | 2 +- base/sparse/sparsevector.jl | 52 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 0b41b9e0731136..dcc9665c20fd6d 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -13,7 +13,7 @@ import Base: +, -, *, \, /, &, |, xor, == import Base: A_mul_B!, Ac_mul_B, Ac_mul_B!, At_mul_B, At_mul_B! import Base: A_mul_Bc, A_mul_Bt, Ac_mul_Bc, At_mul_Bt import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B! -import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc! +import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc!, mul!, ldiv!, rdiv! import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, atan, atand, atanh, broadcast!, chol, conj!, cos, cosc, cosd, cosh, cospi, cot, diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 74b8ed30c0bf67..d9dd98f05f534c 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1562,18 +1562,18 @@ function LinAlg.lowrankupdate!(A::StridedMatrix, x::StridedVector, y::SparseVect return A end -# A_mul_B +# * and mul! function (*)(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} m, n = size(A) length(x) == n || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) y = Vector{Ty}(uninitialized, m) - A_mul_B!(y, A, x) + mul!(y, A, x) end mul!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - A_mul_B!(one(Tx), A, x, zero(Ty), y) + mul!(one(Tx), A, x, zero(Ty), y) function mul!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) m, n = size(A) @@ -1599,7 +1599,7 @@ function mul!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, return y end -# At_mul_B +# * and mul!(C, Transpose(A), B) function *(transA::Transpose{<:Any,<:StridedMatrix{Ta}}, x::AbstractSparseVector{Tx}) where {Ta,Tx} A = transA.parent @@ -1607,11 +1607,11 @@ function *(transA::Transpose{<:Any,<:StridedMatrix{Ta}}, x::AbstractSparseVector length(x) == m || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) y = Vector{Ty}(uninitialized, n) - At_mul_B!(y, A, x) + mul!(y, Transpose(A), x) end mul!(y::StridedVector{Ty}, transA::Transpose{<:Any,<:StridedMatrix}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - (A = transA.parent; At_mul_B!(one(Tx), A, x, zero(Ty), y)) + (A = transA.parent; mul!(one(Tx), Transpose(A), x, zero(Ty), y)) function mul!(α::Number, transA::Transpose{<:Any,<:StridedMatrix}, x::AbstractSparseVector, β::Number, y::StridedVector) A = transA.parent @@ -1656,21 +1656,21 @@ function densemv(A::SparseMatrixCSC, x::AbstractSparseVector; trans::Char='N') T = promote_type(eltype(A), eltype(x)) y = Vector{T}(uninitialized, ylen) if trans == 'N' || trans == 'N' - A_mul_B!(y, A, x) + mul!(y, A, x) elseif trans == 'T' || trans == 't' - At_mul_B!(y, A, x) + mul!(y, Transpose(A), x) elseif trans == 'C' || trans == 'c' - Ac_mul_B!(y, A, x) + mul!(y, Adjoint(A), x) else throw(ArgumentError("Invalid trans character $trans")) end y end -# A_mul_B +# * and mul! mul!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - A_mul_B!(one(Tx), A, x, zero(Ty), y) + mul!(one(Tx), A, x, zero(Ty), y) function mul!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) m, n = size(A) @@ -1700,16 +1700,16 @@ function mul!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Numbe return y end -# At_mul_B +# * and *(Tranpose(A), B) mul!(y::StridedVector{Ty}, transA::Transpose{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - (A = transA.parent; At_mul_B!(one(Tx), A, x, zero(Ty), y)) + (A = transA.parent; mul!(one(Tx), Transpose(A), x, zero(Ty), y)) mul!(α::Number, transA::Transpose{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector, β::Number, y::StridedVector) = (A = transA.parent; _At_or_Ac_mul_B!(*, α, A, x, β, y)) mul!(y::StridedVector{Ty}, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector{Tx}) where {Tx,Ty} = - (A = adjA.parent; Ac_mul_B!(one(Tx), A, x, zero(Ty), y)) + (A = adjA.parent; mul!(one(Tx), Adjoint(A), x, zero(Ty), y)) mul!(α::Number, adjA::Adjoint{<:Any,<:SparseMatrixCSC}, x::AbstractSparseVector, β::Number, y::StridedVector) = (A = adjA.parent; _At_or_Ac_mul_B!(dot, α, A, x, β, y)) @@ -1800,10 +1800,10 @@ for isunittri in (true, false), islowertri in (true, false) tritype = :(Base.LinAlg.$(Symbol(unitstr, halfstr, "Triangular"))) # build out-of-place left-division operations - for (istrans, func, ipfunc, applyxform, xform) in ( - (false, :(\), :(A_ldiv_B!), false, :None), - (true, :(At_ldiv_B), :(At_ldiv_B!), true, :Transpose), - (true, :(Ac_ldiv_B), :(Ac_ldiv_B!), true, :Adjoint) ) + for (istrans, applyxform, xform) in ( + (false, false, :identity), + (true, true, :Transpose), + (true, true, :Adjoint) ) # broad method where elements are Numbers xformtritype = applyxform ? :($xform{<:TA,<:$tritype{<:Any,<:AbstractMatrix}}) : @@ -1813,7 +1813,7 @@ for isunittri in (true, false), islowertri in (true, false) TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) - ($ipfunc)(convert(AbstractArray{TAb}, A), convert(Array{TAb}, b)) + Base.LinAlg.ldiv!($xform(convert(AbstractArray{TAb}, A)), convert(Array{TAb}, b)) end # faster method requiring good view support of the @@ -1835,7 +1835,7 @@ for isunittri in (true, false), islowertri in (true, false) :(1:b.nzind[end]) ) nzrangeviewr = view(r, nzrange) nzrangeviewA = $tritype(view(A.data, nzrange, nzrange)) - ($ipfunc)(convert(AbstractArray{TAb}, nzrangeviewA), nzrangeviewr) + Base.LinAlg.ldiv!($xform(convert(AbstractArray{TAb}, nzrangeviewA)), nzrangeviewr) end r end @@ -1844,15 +1844,15 @@ for isunittri in (true, false), islowertri in (true, false) xformtritype = applyxform ? :($xform{<:Any,<:$tritype}) : :($tritype) @eval function \(xformA::$xformtritype, b::SparseVector) A = $(applyxform ? :(xformA.parent) : :(xformA) ) - ($ipfunc)(A, copy(b)) + Base.LinAlg.ldiv!($xform(A), copy(b)) end end # build in-place left-division operations - for (istrans, func, applyxform, xform) in ( - (false, :(A_ldiv_B!), false, :None), - (true, :(At_ldiv_B!), true, :Transpose), - (true, :(Ac_ldiv_B!), true, :Adjoint) ) + for (istrans, applyxform, xform) in ( + (false, false, :identity), + (true, true, :Transpose), + (true, true, :Adjoint) ) xformtritype = applyxform ? :($xform{<:Any,<:$tritype{<:Any,<:StridedMatrix}}) : :($tritype{<:Any,<:StridedMatrix}) @@ -1878,7 +1878,7 @@ for isunittri in (true, false), islowertri in (true, false) :(1:b.nzind[end]) ) nzrangeviewbnz = view(b.nzval, nzrange .- (b.nzind[1] - 1)) nzrangeviewA = $tritype(view(A.data, nzrange, nzrange)) - ($func)(nzrangeviewA, nzrangeviewbnz) + Base.LinAlg.ldiv!($xform(nzrangeviewA), nzrangeviewbnz) end b end From 9b387f9f4af1dd8b7b98ec2821731c814c35c0bc Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 11:57:13 -0800 Subject: [PATCH 48/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/triangular.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/triangular.jl | 204 +++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index e3ef1f6242749f..30807f20116648 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -444,32 +444,32 @@ scale!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = scale!(A,c) ###################### mul!(A::Tridiagonal, B::AbstractTriangular) = A*full!(B) -mul!(C::AbstractMatrix, A::AbstractTriangular, B::Tridiagonal) = A_mul_B!(C, copy!(similar(parent(A)), A), B) -mul!(C::AbstractMatrix, A::Tridiagonal, B::AbstractTriangular) = A_mul_B!(C, A, copy!(similar(parent(B)), B)) +mul!(C::AbstractMatrix, A::AbstractTriangular, B::Tridiagonal) = mul!(C, copy!(similar(parent(A)), A), B) +mul!(C::AbstractMatrix, A::Tridiagonal, B::AbstractTriangular) = mul!(C, A, copy!(similar(parent(B)), B)) mul!(C::AbstractVector, A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractVecOrMat}) = - (B = transB.parent; A_mul_B!(A, transpose!(C, B))) + (B = transB.parent; mul!(A, transpose!(C, B))) mul!(C::AbstractMatrix, A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractVecOrMat}) = - (B = transB.parent; A_mul_B!(A, transpose!(C, B))) + (B = transB.parent; mul!(A, transpose!(C, B))) mul!(C::AbstractMatrix, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = - (B = adjB.parent; A_mul_B!(A, adjoint!(C, B))) + (B = adjB.parent; mul!(A, adjoint!(C, B))) mul!(C::AbstractVecOrMat, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = - (B = adjB.parent; A_mul_B!(A, adjoint!(C, B))) + (B = adjB.parent; mul!(A, adjoint!(C, B))) # The three methods for each op are neceesary to avoid ambiguities with definitions in matmul.jl -mul!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = A_mul_B!(A, copy!(C, B)) -mul!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, copy!(C, B)) -mul!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = A_mul_B!(A, copy!(C, B)) +mul!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = mul!(A, copy!(C, B)) +mul!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = mul!(A, copy!(C, B)) +mul!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = mul!(A, copy!(C, B)) mul!(C::AbstractVector , adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVector) = - (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) + (A = adjA.parent; mul!(Adjoint(A), copy!(C, B))) mul!(C::AbstractMatrix , adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = - (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) + (A = adjA.parent; mul!(Adjoint(A), copy!(C, B))) mul!(C::AbstractVecOrMat, adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = - (A = adjA.parent; Ac_mul_B!(A, copy!(C, B))) + (A = adjA.parent; mul!(Adjoint(A), copy!(C, B))) mul!(C::AbstractVector , transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVector) = - (A = transA.parent; At_mul_B!(A, copy!(C, B))) + (A = transA.parent; mul!(Transpose(A), copy!(C, B))) mul!(C::AbstractMatrix , transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = - (A = transA.parent; At_mul_B!(A, copy!(C, B))) + (A = transA.parent; mul!(Transpose(A), copy!(C, B))) mul!(C::AbstractVecOrMat, transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractVecOrMat) = - (A = transA.parent; At_mul_B!(A, copy!(C, B))) + (A = transA.parent; mul!(Transpose(A), copy!(C, B))) mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) mul!(C::AbstractMatrix, A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, adjoint(B.parent)) @@ -557,14 +557,14 @@ end function inv(A::LowerTriangular{T}) where T S = typeof((zero(T)*one(T) + zero(T))/one(T)) - LowerTriangular(A_ldiv_B!(convert(AbstractArray{S}, A), Matrix{S}(I, size(A, 1), size(A, 1)))) + LowerTriangular(ldiv!(convert(AbstractArray{S}, A), Matrix{S}(I, size(A, 1), size(A, 1)))) end function inv(A::UpperTriangular{T}) where T S = typeof((zero(T)*one(T) + zero(T))/one(T)) - UpperTriangular(A_ldiv_B!(convert(AbstractArray{S}, A), Matrix{S}(I, size(A, 1), size(A, 1)))) + UpperTriangular(ldiv!(convert(AbstractArray{S}, A), Matrix{S}(I, size(A, 1), size(A, 1)))) end -inv(A::UnitUpperTriangular{T}) where {T} = UnitUpperTriangular(A_ldiv_B!(A, Matrix{T}(I, size(A, 1), size(A, 1)))) -inv(A::UnitLowerTriangular{T}) where {T} = UnitLowerTriangular(A_ldiv_B!(A, Matrix{T}(I, size(A, 1), size(A, 1)))) +inv(A::UnitUpperTriangular{T}) where {T} = UnitUpperTriangular(ldiv!(A, Matrix{T}(I, size(A, 1), size(A, 1)))) +inv(A::UnitLowerTriangular{T}) where {T} = UnitLowerTriangular(ldiv!(A, Matrix{T}(I, size(A, 1), size(A, 1)))) errorbounds(A::AbstractTriangular{T,<:StridedMatrix}, X::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:Union{BigFloat,Complex{BigFloat}}} = error("not implemented yet! Please submit a pull request.") @@ -1454,43 +1454,43 @@ function rdiv!(A::StridedMatrix, transB::Transpose{<:Any,<:UnitLowerTriangular}) end mul!(adjA::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = - (A = adjA.parent; UpperTriangular(Ac_mul_B!(A, triu!(B.data)))) + (A = adjA.parent; UpperTriangular(mul!(Adjoint(A), triu!(B.data)))) mul!(adjA::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = - (A = adjA.parent; LowerTriangular(Ac_mul_B!(A, tril!(B.data)))) + (A = adjA.parent; LowerTriangular(mul!(Adjoint(A), tril!(B.data)))) mul!(transA::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = - (A = transA.parent; UpperTriangular(At_mul_B!(A, triu!(B.data)))) + (A = transA.parent; UpperTriangular(mul!(Transpose(A), triu!(B.data)))) mul!(transA::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = - (A = transA.parent; LowerTriangular(At_mul_B!(A, tril!(B.data)))) + (A = transA.parent; LowerTriangular(mul!(Transpose(A), tril!(B.data)))) ldiv!(adjA::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = - (A = adjA.parent; UpperTriangular(Ac_ldiv_B!(A, triu!(B.data)))) + (A = adjA.parent; UpperTriangular(ldiv!(Adjoint(A), triu!(B.data)))) ldiv!(adjA::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = - (A = adjA.parent; LowerTriangular(Ac_ldiv_B!(A, tril!(B.data)))) + (A = adjA.parent; LowerTriangular(ldiv!(Adjoint(A), tril!(B.data)))) ldiv!(transA::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}, B::UpperTriangular) = - (A = transA.parent; UpperTriangular(At_ldiv_B!(A, triu!(B.data)))) + (A = transA.parent; UpperTriangular(ldiv!(Transpose(A), triu!(B.data)))) ldiv!(transA::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}, B::LowerTriangular) = - (A = transA.parent; LowerTriangular(At_ldiv_B!(A, tril!(B.data)))) + (A = transA.parent; LowerTriangular(ldiv!(Transpose(A), tril!(B.data)))) rdiv!(A::UpperTriangular, B::Union{UpperTriangular,UnitUpperTriangular}) = - UpperTriangular(A_rdiv_B!(triu!(A.data), B)) + UpperTriangular(rdiv!(triu!(A.data), B)) rdiv!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular}) = - LowerTriangular(A_rdiv_B!(tril!(A.data), B)) + LowerTriangular(rdiv!(tril!(A.data), B)) mul!(A::UpperTriangular, adjB::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = - (B = adjB.parent; UpperTriangular(A_mul_Bc!(triu!(A.data), B))) + (B = adjB.parent; UpperTriangular(mul!(triu!(A.data), Adjoint(B)))) mul!(A::LowerTriangular, adjB::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = - (B = adjB.parent; LowerTriangular(A_mul_Bc!(tril!(A.data), B))) + (B = adjB.parent; LowerTriangular(mul!(tril!(A.data), Adjoint(B)))) mul!(A::UpperTriangular, transB::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = - (B = transB.parent; UpperTriangular(A_mul_Bt!(triu!(A.data), B))) + (B = transB.parent; UpperTriangular(mul!(triu!(A.data), Transpose(B)))) mul!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = - (B = transB.parent; LowerTriangular(A_mul_Bt!(tril!(A.data), B))) + (B = transB.parent; LowerTriangular(mul!(tril!(A.data), Transpose(B)))) rdiv!(A::UpperTriangular, adjB::Adjoint{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = - (B = adjB.parent; UpperTriangular(A_rdiv_Bc!(triu!(A.data), B))) + (B = adjB.parent; UpperTriangular(rdiv!(triu!(A.data), Adjoint(B)))) rdiv!(A::LowerTriangular, adjB::Adjoint{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = - (B = adjB.parent; LowerTriangular(A_rdiv_Bc!(tril!(A.data), B))) + (B = adjB.parent; LowerTriangular(rdiv!(tril!(A.data), Adjoint(B)))) rdiv!(A::UpperTriangular, transB::Transpose{<:Any,<:Union{LowerTriangular,UnitLowerTriangular}}) = - (B = transB.parent; UpperTriangular(A_rdiv_Bt!(triu!(A.data), B))) + (B = transB.parent; UpperTriangular(rdiv!(triu!(A.data), Transpose(B)))) rdiv!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUpperTriangular}}) = - (B = transB.parent; LowerTriangular(A_rdiv_Bt!(tril!(A.data), B))) + (B = transB.parent; LowerTriangular(rdiv!(tril!(A.data), Transpose(B)))) # Promotion ## Promotion methods in matmul don't apply to triangular multiplication since @@ -1501,9 +1501,9 @@ rdiv!(A::LowerTriangular, transB::Transpose{<:Any,<:Union{UpperTriangular,UnitUp ## Some Triangular-Triangular cases. We might want to write taylored methods ## for these cases, but I'm not sure it is worth it. -(*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = A_mul_B!(Matrix(A), B) +(*)(A::Union{Tridiagonal,SymTridiagonal}, B::AbstractTriangular) = mul!(Matrix(A), B) -for (f1, f2) in ((:*, :A_mul_B!), (:\, :A_ldiv_B!)) +for (f1, f2) in ((:*, :mul!), (:\, :ldiv!)) @eval begin function ($f1)(A::LowerTriangular, B::LowerTriangular) TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + @@ -1539,19 +1539,19 @@ for (f1, f2) in ((:*, :A_mul_B!), (:\, :A_ldiv_B!)) end end -for (f1, f2, op, xform) in ( - (:Ac_mul_B, :Ac_mul_B!, :*, :Adjoint), - (:At_mul_B, :At_mul_B!, :*, :Transpose), - (:Ac_ldiv_B, :Ac_ldiv_B!, :\, :Adjoint), - (:At_ldiv_B, :At_ldiv_B!, :\, :Transpose)) +for (ipop, op, xform) in ( + (:mul!, :*, :Adjoint), + (:mul!, :*, :Transpose), + (:ldiv!, :\, :Adjoint), + (:ldiv!, :\, :Transpose)) @eval begin function ($op)(xformA::($xform){<:Any,<:UpperTriangular}, B::LowerTriangular) A = xformA.parent - TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + - ($f1)(zero(eltype(A)), zero(eltype(B)))) + TAB = typeof(($op)($xform(zero(eltype(A))), zero(eltype(B))) + + ($op)($xform(zero(eltype(A))), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copy!(BB, B) - return LowerTriangular(($f2)(convert(AbstractMatrix{TAB}, A), BB)) + return LowerTriangular(($ipop)($xform(convert(AbstractMatrix{TAB}, A)), BB)) end function ($op)(xformA::($xform){<:Any,<:UnitUpperTriangular}, B::LowerTriangular) @@ -1560,16 +1560,16 @@ for (f1, f2, op, xform) in ( (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copy!(BB, B) - return LowerTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) + return LowerTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) end function ($op)(xformA::($xform){<:Any,<:LowerTriangular}, B::UpperTriangular) A = xformA.parent - TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + - ($f1)(zero(eltype(A)), zero(eltype(B)))) + TAB = typeof(($op)($xform(zero(eltype(A))), zero(eltype(B))) + + ($op)($xform(zero(eltype(A))), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copy!(BB, B) - return UpperTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) + return UpperTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) end function ($op)(xformA::($xform){<:Any,<:UnitLowerTriangular}, B::UpperTriangular) @@ -1578,7 +1578,7 @@ for (f1, f2, op, xform) in ( (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copy!(BB, B) - return UpperTriangular($f2(convert(AbstractMatrix{TAB}, A), BB)) + return UpperTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) end end end @@ -1588,43 +1588,43 @@ function (/)(A::LowerTriangular, B::LowerTriangular) (/)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return LowerTriangular(A_rdiv_B!(AA, convert(AbstractMatrix{TAB}, B))) + return LowerTriangular(rdiv!(AA, convert(AbstractMatrix{TAB}, B))) end function (/)(A::LowerTriangular, B::UnitLowerTriangular) TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return LowerTriangular(A_rdiv_B!(AA, convert(AbstractMatrix{TAB}, B))) + return LowerTriangular(rdiv!(AA, convert(AbstractMatrix{TAB}, B))) end function (/)(A::UpperTriangular, B::UpperTriangular) TAB = typeof((/)(zero(eltype(A)), zero(eltype(B))) + (/)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return UpperTriangular(A_rdiv_B!(AA, convert(AbstractMatrix{TAB}, B))) + return UpperTriangular(rdiv!(AA, convert(AbstractMatrix{TAB}, B))) end function (/)(A::UpperTriangular, B::UnitUpperTriangular) TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return UpperTriangular(A_rdiv_B!(AA, convert(AbstractMatrix{TAB}, B))) + return UpperTriangular(rdiv!(AA, convert(AbstractMatrix{TAB}, B))) end -for (f1, f2, op, xform) in ( - (:A_mul_Bc, :A_mul_Bc!, :*, :Adjoint), - (:A_mul_Bt, :A_mul_Bt!, :*, :Transpose), - (:A_rdiv_Bc, :A_rdiv_Bc!, :/, :Adjoint), - (:A_rdiv_Bt, :A_rdiv_Bt!, :/, :Transpose)) +for (ipop, op, xform) in ( + (:mul!, :*, :Adjoint), + (:mul!, :*, :Transpose), + (:rdiv!, :/, :Adjoint), + (:rdiv!, :/, :Transpose)) @eval begin function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UpperTriangular}) B = xformB.parent - TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + - ($f1)(zero(eltype(A)), zero(eltype(B)))) + TAB = typeof(($op)(zero(eltype(A)), $xform(zero(eltype(B)))) + + ($op)(zero(eltype(A)), $xform(zero(eltype(B))))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return LowerTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) + return LowerTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) end function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UnitUpperTriangular}) @@ -1633,16 +1633,16 @@ for (f1, f2, op, xform) in ( (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return LowerTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) + return LowerTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) end function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:LowerTriangular}) B = xformB.parent - TAB = typeof(($f1)(zero(eltype(A)), zero(eltype(B))) + - ($f1)(zero(eltype(A)), zero(eltype(B)))) + TAB = typeof(($op)(zero(eltype(A)), $xform(zero(eltype(B)))) + + ($op)(zero(eltype(A)), $xform(zero(eltype(B))))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return UpperTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) + return UpperTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) end function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:UnitLowerTriangular}) @@ -1651,7 +1651,7 @@ for (f1, f2, op, xform) in ( (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copy!(AA, A) - return UpperTriangular($f2(AA, convert(AbstractMatrix{TAB}, B))) + return UpperTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) end end end @@ -1662,21 +1662,21 @@ function *(A::AbstractTriangular, B::AbstractTriangular) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - A_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(convert(AbstractArray{TAB}, A), BB) end function *(adjA::Adjoint{<:Any,<:AbstractTriangular}, B::AbstractTriangular) A = adjA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - Ac_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(Adjoint(convert(AbstractArray{TAB}, A)), BB) end function *(transA::Transpose{<:Any,<:AbstractTriangular}, B::AbstractTriangular) A = transA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - At_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(Transpose(convert(AbstractArray{TAB}, A)), BB) end function *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractTriangular}) @@ -1684,14 +1684,14 @@ function *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractTriangular}) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_mul_Bc!(AA, convert(AbstractArray{TAB}, B)) + mul!(AA, Adjoint(convert(AbstractArray{TAB}, B))) end function *(A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractTriangular}) B = transB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_mul_Bt!(AA, convert(AbstractArray{TAB}, B)) + mul!(AA, Transpose(convert(AbstractArray{TAB}, B))) end for mat in (:AbstractVector, :AbstractMatrix) @@ -1701,21 +1701,21 @@ for mat in (:AbstractVector, :AbstractMatrix) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - A_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(convert(AbstractArray{TAB}, A), BB) end function *(adjA::Adjoint{<:Any,<:AbstractTriangular}, B::$mat) A = adjA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - Ac_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(Adjoint(convert(AbstractArray{TAB}, A)), BB) end function *(transA::Transpose{<:Any,<:AbstractTriangular}, B::$mat) A = transA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - At_mul_B!(convert(AbstractArray{TAB}, A), BB) + mul!(Transpose(convert(AbstractArray{TAB}, A)), BB) end end ### Left division with triangle to the left hence rhs cannot be transposed. No quotients. @@ -1724,21 +1724,21 @@ for mat in (:AbstractVector, :AbstractMatrix) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - A_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(convert(AbstractArray{TAB}, A), BB) end function \(adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, B::$mat) A = adjA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - Ac_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(Adjoint(convert(AbstractArray{TAB}, A)), BB) end function \(transA::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, B::$mat) A = transA.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) BB = similar(B, TAB, size(B)) copy!(BB, B) - At_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(Transpose(convert(AbstractArray{TAB}, A)), BB) end end ### Left division with triangle to the left hence rhs cannot be transposed. Quotients. @@ -1747,21 +1747,21 @@ for mat in (:AbstractVector, :AbstractMatrix) TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) BB = similar(B, TAB, size(B)) copy!(BB, B) - A_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(convert(AbstractArray{TAB}, A), BB) end function \(adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}, B::$mat) A = adjA.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) BB = similar(B, TAB, size(B)) copy!(BB, B) - Ac_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(Adjoint(convert(AbstractArray{TAB}, A)), BB) end function \(transA::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}, B::$mat) A = transA.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) BB = similar(B, TAB, size(B)) copy!(BB, B) - At_ldiv_B!(convert(AbstractArray{TAB}, A), BB) + ldiv!(Transpose(convert(AbstractArray{TAB}, A)), BB) end end ### Right division with triangle to the right hence lhs cannot be transposed. No quotients. @@ -1770,21 +1770,21 @@ for mat in (:AbstractVector, :AbstractMatrix) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_B!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, convert(AbstractArray{TAB}, B)) end function /(A::$mat, adjB::Adjoint{<:Any,<:Union{UnitUpperTriangular, UnitLowerTriangular}}) B = adjB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_Bc!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, Adjoint(convert(AbstractArray{TAB}, B))) end function /(A::$mat, transB::Transpose{<:Any,<:Union{UnitUpperTriangular, UnitLowerTriangular}}) B = transB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_Bt!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, Transpose(convert(AbstractArray{TAB}, B))) end end ### Right division with triangle to the right hence lhs cannot be transposed. Quotients. @@ -1793,21 +1793,21 @@ for mat in (:AbstractVector, :AbstractMatrix) TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_B!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, convert(AbstractArray{TAB}, B)) end function /(A::$mat, adjB::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) B = adjB.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_Bc!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, Adjoint(convert(AbstractArray{TAB}, B))) end function /(A::$mat, transB::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}) B = transB.parent TAB = typeof((zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B)))/one(eltype(A))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_rdiv_Bt!(AA, convert(AbstractArray{TAB}, B)) + rdiv!(AA, Transpose(convert(AbstractArray{TAB}, B))) end end end @@ -1817,21 +1817,21 @@ function *(A::AbstractMatrix, B::AbstractTriangular) TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_mul_B!(AA, convert(AbstractArray{TAB}, B)) + mul!(AA, convert(AbstractArray{TAB}, B)) end function *(A::AbstractMatrix, adjB::Adjoint{<:Any,<:AbstractTriangular}) B = adjB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_mul_Bc!(AA, convert(AbstractArray{TAB}, B)) + mul!(AA, Adjoint(convert(AbstractArray{TAB}, B))) end function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractTriangular}) B = transB.parent TAB = typeof(zero(eltype(A))*zero(eltype(B)) + zero(eltype(A))*zero(eltype(B))) AA = similar(A, TAB, size(A)) copy!(AA, A) - A_mul_Bt!(AA, convert(AbstractArray{TAB}, B)) + mul!(AA, Transpose(convert(AbstractArray{TAB}, B))) end # ambiguity resolution with definitions in linalg/rowvector.jl *(transA::Transpose{<:Any,<:AbstractVector}, B::AbstractTriangular) = *(transpose(transA.parent), B) @@ -1849,12 +1849,12 @@ end *(transA::Transpose{<:Any,<:AbstractMatrix}, B::AbstractTriangular) = (*)(transpose(transA.parent), B) *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractMatrix}) = (*)(A, adjoint(adjB.parent)) *(A::AbstractTriangular, transB::Transpose{<:Any,<:AbstractMatrix}) = (*)(A, transpose(transB.parent)) -*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractTriangular}) =Ac_mul_B(adjA.parent, adjB.parent') -*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractMatrix}) = Ac_mul_B(adjA.parent, adjB.parent') -*(adjA::Adjoint{<:Any,<:AbstractMatrix}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = A_mul_Bc(adjA.parent', adjB.parent) -*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractTriangular}) = At_mul_B(transA.parent, transB.parent.') -*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractMatrix}) = At_mul_B(transA.parent, transB.parent.') -*(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractTriangular}) = A_mul_Bt(transA.parent.', transB.parent) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = *(adjA, adjoint(adjB.parent)) +*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjB::Adjoint{<:Any,<:AbstractMatrix}) = *(adjA, adjoint(adjB.parent)) +*(adjA::Adjoint{<:Any,<:AbstractMatrix}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = *(adjoint(adjA.parent), adjB) +*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractTriangular}) = *(transA, transpose(transB.parent)) +*(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractMatrix}) = *(transA, transpose(transB.parent)) +*(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractTriangular}) = *(transpose(transA.parent), transB) # Specializations for RowVector *(rowvec::RowVector, A::AbstractTriangular) = transpose(transpose(A) * transpose(rowvec)) @@ -1930,7 +1930,7 @@ function powm!(A0::UpperTriangular{<:BlasFloat}, p::Real) end copy!(Stmp, S) scale!(S, A, c) - A_ldiv_B!(Stmp, S.data) + ldiv!(Stmp, S.data) c = (p - j) / (j4 - 2) for i = 1:n @@ -1938,21 +1938,21 @@ function powm!(A0::UpperTriangular{<:BlasFloat}, p::Real) end copy!(Stmp, S) scale!(S, A, c) - A_ldiv_B!(Stmp, S.data) + ldiv!(Stmp, S.data) end for i = 1:n S[i, i] = S[i, i] + 1 end copy!(Stmp, S) scale!(S, A, -p) - A_ldiv_B!(Stmp, S.data) + ldiv!(Stmp, S.data) for i = 1:n @inbounds S[i, i] = S[i, i] + 1 end blockpower!(A0, S, p/(2^s)) for m = 1:s - A_mul_B!(Stmp.data, S, S) + mul!(Stmp.data, S, S) copy!(S, Stmp) blockpower!(A0, S, p/(2^(s-m))) end From 5147f52ce6e7d208b2b90acbd5c7a5a552342e87 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 13:45:12 -0800 Subject: [PATCH 49/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in base/linalg/rowvector.jl as *, /, \, mul!, ldiv!, or rdiv!. --- base/linalg/rowvector.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 5ccb5d820f3bac..0044114277e464 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -237,13 +237,13 @@ end *(::Transpose{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) *(transvec::Transpose{<:Any,<:AbstractVector}, mat::AbstractMatrix) = - transpose(At_mul_B(mat,transvec.parent)) + transpose(*(Transpose(mat), transvec.parent)) *(transrowvec1::Transpose{<:Any,<:RowVector}, rowvec2::RowVector) = transpose(transrowvec1.parent) * rowvec2 *(transvec::Transpose{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) *(transvec1::Transpose{<:Any,<:AbstractVector{T}}, vec2::AbstractVector{T}) where {T<:Real} = - reduce(+, map(At_mul_B, transvec1.parent, vec2)) # Seems to be overloaded... + reduce(+, map(*, transvec1.parent, vec2)) # Seems to be overloaded... *(transvec1::Transpose{<:Any,<:AbstractVector}, vec2::AbstractVector) = transpose(transvec1.parent) * vec2 @@ -275,7 +275,7 @@ end (adjmat.parent)' * adjoint(adjrowvec.parent) *(::Adjoint{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -*(adjvec::Adjoint{<:Any,<:AbstractVector}, mat::AbstractMatrix) = adjoint(Ac_mul_B(mat,adjvec.parent)) +*(adjvec::Adjoint{<:Any,<:AbstractVector}, mat::AbstractMatrix) = adjoint(*(Adjoint(mat), adjvec.parent)) *(adjrowvec1::Adjoint{<:Any,<:RowVector}, rowvec2::RowVector) = adjoint(adjrowvec1.parent) * rowvec2 *(adjvec::Adjoint{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) *(adjvec1::Adjoint{<:Any,<:AbstractVector}, vec2::AbstractVector) = adjoint(adjvec1.parent)*vec2 From 364a1441c39db93d895705edd56b96199ce3c25a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 14:22:22 -0800 Subject: [PATCH 50/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/diagonal.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/diagonal.jl | 98 +++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index d601f8a27c570b..289f5f1228c33d 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -1,8 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test -import Base.LinAlg: BlasFloat, BlasComplex, SingularException, A_rdiv_B!, A_rdiv_Bt!, - A_rdiv_Bc! +using Base.LinAlg: mul!, ldiv!, rdiv!, Adjoint, Transpose +import Base.LinAlg: BlasFloat, BlasComplex, SingularException n=12 #Size of matrix problem to test srand(1) @@ -97,37 +97,37 @@ srand(1) atol_three = 2n^3 * eps(relty) * (1 + (elty <: Complex)) @test D\v ≈ DM\v atol=atol_two @test D\U ≈ DM\U atol=atol_three - @test A_ldiv_B!(D, copy(v)) ≈ DM\v atol=atol_two - @test At_ldiv_B!(D, copy(v)) ≈ DM\v atol=atol_two - @test Ac_ldiv_B!(conj(D), copy(v)) ≈ DM\v atol=atol_two - @test A_ldiv_B!(D, copy(U)) ≈ DM\U atol=atol_three - @test At_ldiv_B!(D, copy(U)) ≈ DM\U atol=atol_three - @test Ac_ldiv_B!(conj(D), copy(U)) ≈ DM\U atol=atol_three + @test ldiv!(D, copy(v)) ≈ DM\v atol=atol_two + @test ldiv!(Transpose(D), copy(v)) ≈ DM\v atol=atol_two + @test ldiv!(Adjoint(conj(D)), copy(v)) ≈ DM\v atol=atol_two + @test ldiv!(D, copy(U)) ≈ DM\U atol=atol_three + @test ldiv!(Transpose(D), copy(U)) ≈ DM\U atol=atol_three + @test ldiv!(Adjoint(conj(D)), copy(U)) ≈ DM\U atol=atol_three Uc = adjoint(U) target = scale!(Uc, inv.(D.diag)) - @test A_rdiv_B!(Uc, D) ≈ target atol=atol_three - @test_throws DimensionMismatch A_rdiv_B!(Matrix{elty}(I, n-1, n-1), D) - @test_throws SingularException A_rdiv_B!(Uc, Diagonal(fill!(similar(D.diag), 0))) - @test A_rdiv_Bt!(Uc, D) ≈ target atol=atol_three - @test A_rdiv_Bc!(Uc, conj(D)) ≈ target atol=atol_three - @test A_ldiv_B!(D, Matrix{eltype(D)}(I, size(D))) ≈ D \ Matrix{eltype(D)}(I, size(D)) atol=atol_three - @test_throws DimensionMismatch A_ldiv_B!(D, ones(elty, n + 1)) - @test_throws SingularException A_ldiv_B!(Diagonal(zeros(relty, n)), copy(v)) + @test rdiv!(Uc, D) ≈ target atol=atol_three + @test_throws DimensionMismatch rdiv!(Matrix{elty}(I, n-1, n-1), D) + @test_throws SingularException rdiv!(Uc, Diagonal(fill!(similar(D.diag), 0))) + @test rdiv!(Uc, Transpose(D)) ≈ target atol=atol_three + @test rdiv!(Uc, Adjoint(conj(D))) ≈ target atol=atol_three + @test ldiv!(D, Matrix{eltype(D)}(I, size(D))) ≈ D \ Matrix{eltype(D)}(I, size(D)) atol=atol_three + @test_throws DimensionMismatch ldiv!(D, ones(elty, n + 1)) + @test_throws SingularException ldiv!(Diagonal(zeros(relty, n)), copy(v)) b = rand(elty, n, n) b = sparse(b) - @test A_ldiv_B!(D, copy(b)) ≈ Array(D)\Array(b) - @test_throws SingularException A_ldiv_B!(Diagonal(zeros(elty, n)), copy(b)) + @test ldiv!(D, copy(b)) ≈ Array(D)\Array(b) + @test_throws SingularException ldiv!(Diagonal(zeros(elty, n)), copy(b)) b = view(rand(elty, n), collect(1:n)) b2 = copy(b) - c = A_ldiv_B!(D, b) + c = ldiv!(D, b) d = Array(D)\b2 @test c ≈ d - @test_throws SingularException A_ldiv_B!(Diagonal(zeros(elty, n)), b) + @test_throws SingularException ldiv!(Diagonal(zeros(elty, n)), b) b = rand(elty, n+1, n+1) b = sparse(b) - @test_throws DimensionMismatch A_ldiv_B!(D, copy(b)) + @test_throws DimensionMismatch ldiv!(D, copy(b)) b = view(rand(elty, n+1), collect(1:n+1)) - @test_throws DimensionMismatch A_ldiv_B!(D, b) + @test_throws DimensionMismatch ldiv!(D, b) end end end @@ -146,9 +146,9 @@ srand(1) if relty <: BlasFloat b = rand(elty,n,n) b = sparse(b) - @test A_mul_B!(copy(D), copy(b)) ≈ Array(D)*Array(b) - @test At_mul_B!(copy(D), copy(b)) ≈ Array(D).'*Array(b) - @test Ac_mul_B!(copy(D), copy(b)) ≈ Array(D)'*Array(b) + @test mul!(copy(D), copy(b)) ≈ Array(D)*Array(b) + @test mul!(Transpose(copy(D)), copy(b)) ≈ Array(D).'*Array(b) + @test mul!(Adjoint(copy(D)), copy(b)) ≈ Array(D)'*Array(b) end end @@ -164,26 +164,26 @@ srand(1) # Performance specialisations for A*_mul_B! vvv = similar(vv) - @test (r = Matrix(D) * vv ; A_mul_B!(vvv, D, vv) ≈ r ≈ vvv) - @test (r = Matrix(D)' * vv ; Ac_mul_B!(vvv, D, vv) ≈ r ≈ vvv) - @test (r = Matrix(D).' * vv ; At_mul_B!(vvv, D, vv) ≈ r ≈ vvv) + @test (r = Matrix(D) * vv ; mul!(vvv, D, vv) ≈ r ≈ vvv) + @test (r = Matrix(D)' * vv ; mul!(vvv, Adjoint(D), vv) ≈ r ≈ vvv) + @test (r = Matrix(D).' * vv ; mul!(vvv, Transpose(D), vv) ≈ r ≈ vvv) UUU = similar(UU) - @test (r = Matrix(D) * UU ; A_mul_B!(UUU, D, UU) ≈ r ≈ UUU) - @test (r = Matrix(D)' * UU ; Ac_mul_B!(UUU, D, UU) ≈ r ≈ UUU) - @test (r = Matrix(D).' * UU ; At_mul_B!(UUU, D, UU) ≈ r ≈ UUU) + @test (r = Matrix(D) * UU ; mul!(UUU, D, UU) ≈ r ≈ UUU) + @test (r = Matrix(D)' * UU ; mul!(UUU, Adjoint(D), UU) ≈ r ≈ UUU) + @test (r = Matrix(D).' * UU ; mul!(UUU, Transpose(D), UU) ≈ r ≈ UUU) - # make sure that A_mul_B{c,t}! works with B as a Diagonal + # make sure that mul!(A, {Adj|Trans}(B)) works with B as a Diagonal VV = Array(D) DD = copy(D) r = VV * Matrix(D) - @test Array(A_mul_B!(VV, DD)) ≈ r ≈ Array(D)*Array(D) + @test Array(mul!(VV, DD)) ≈ r ≈ Array(D)*Array(D) DD = copy(D) r = VV * (Array(D).') - @test Array(A_mul_Bt!(VV, DD)) ≈ r + @test Array(mul!(VV, Transpose(DD))) ≈ r DD = copy(D) r = VV * (Array(D)') - @test Array(A_mul_Bc!(VV, DD)) ≈ r + @test Array(mul!(VV, Adjoint(DD))) ≈ r end @testset "triu/tril" begin @test istriu(D) @@ -347,9 +347,9 @@ end end let D1 = Diagonal(rand(5)), D2 = Diagonal(rand(5)) - @test_throws MethodError A_mul_B!(D1,D2) - @test_throws MethodError At_mul_B!(D1,D2) - @test_throws MethodError Ac_mul_B!(D1,D2) + @test_throws MethodError mul!(D1,D2) + @test_throws MethodError mul!(Transpose(D1),D2) + @test_throws MethodError mul!(Adjoint(D1),D2) end @testset "multiplication of QR Q-factor and Diagonal (#16615 spot test)" begin @@ -357,7 +357,7 @@ end Q = qrfact(randn(5, 5))[:Q] @test D * Q' == Array(D) * Q' Q = qrfact(randn(5, 5), Val(true))[:Q] - @test_throws MethodError A_mul_B!(Q, D) + @test_throws MethodError mul!(Q, D) end @testset "block diagonal matrices" begin @@ -394,11 +394,13 @@ end A = randn(T, n, n); A = A'A S = Symmetric(A) H = Hermitian(A) - for f in (*, Ac_mul_B, A_mul_Bc, Ac_mul_Bc, At_mul_B, A_mul_Bt, At_mul_Bt) - @test f(D, S) ≈ f(Matrix(D), Matrix(S)) - @test f(D, H) ≈ f(Matrix(D), Matrix(H)) - @test f(S, D) ≈ f(Matrix(S), Matrix(D)) - @test f(S, H) ≈ f(Matrix(S), Matrix(H)) + for (transform1, transform2) in ((identity, identity), + (identity, Adjoint ), (Adjoint, identity ), (Adjoint, Adjoint ), + (identity, Transpose), (Transpose, identity ), (Transpose, Transpose) ) + @test *(transform1(D), transform2(S)) ≈ *(transform1(Matrix(D)), transform2(Matrix(S))) + @test *(transform1(D), transform2(H)) ≈ *(transform1(Matrix(D)), transform2(Matrix(H))) + @test *(transform1(S), transform2(D)) ≈ *(transform1(Matrix(S)), transform2(Matrix(D))) + @test *(transform1(S), transform2(H)) ≈ *(transform1(Matrix(S)), transform2(Matrix(H))) end end end @@ -411,9 +413,11 @@ end BB = Diagonal([randn(T, 2, 2), rand(T, 2, 2)]) fullDD = copy!(Matrix{Matrix{T}}(uninitialized, 2, 2), DD) fullBB = copy!(Matrix{Matrix{T}}(uninitialized, 2, 2), BB) - for f in (*, Ac_mul_B, A_mul_Bc, Ac_mul_Bc, At_mul_B, A_mul_Bt, At_mul_Bt) - @test f(D, B)::typeof(D) ≈ f(Matrix(D), Matrix(B)) atol=2 * eps() - @test f(DD, BB)::typeof(DD) == f(fullDD, fullBB) + for (transform1, transform2) in ((identity, identity), + (identity, Adjoint ), (Adjoint, identity ), (Adjoint, Adjoint ), + (identity, Transpose), (Transpose, identity ), (Transpose, Transpose) ) + @test *(transform1(D), transform2(B))::typeof(D) ≈ *(transform1(Matrix(D)), transform2(Matrix(B))) atol=2 * eps() + @test *(transform1(DD), transform2(BB))::typeof(DD) == *(transform1(fullDD), transform2(fullBB)) end end end From 86262055bd0b3abd633f79459c1678771183ae92 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 14:24:18 -0800 Subject: [PATCH 51/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/bidiag.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/bidiag.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/linalg/bidiag.jl b/test/linalg/bidiag.jl index 0cf9c5bc346b34..3ab9d9e58634c5 100644 --- a/test/linalg/bidiag.jl +++ b/test/linalg/bidiag.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test +using Base.LinAlg: mul!, Adjoint, Transpose import Base.LinAlg: BlasReal, BlasFloat n = 10 #Size of test matrix @@ -182,8 +183,8 @@ srand(1) @test_throws DimensionMismatch T \ RowVector(ones(elty,n+1)) @test_throws DimensionMismatch T.' \ RowVector(ones(elty,n+1)) @test_throws DimensionMismatch T' \ RowVector(ones(elty,n+1)) - @test_throws DimensionMismatch Base.LinAlg.At_ldiv_B(T, RowVector(ones(elty,n+1))) - @test_throws DimensionMismatch Base.LinAlg.Ac_ldiv_B(T, RowVector(ones(elty,n+1))) + @test_throws DimensionMismatch Transpose(T) \ RowVector(ones(elty,n+1)) + @test_throws DimensionMismatch Adjoint(T) \ RowVector(ones(elty,n+1)) let bb = b, cc = c for atype in ("Array", "SubArray") if atype == "Array" @@ -275,10 +276,10 @@ srand(1) @test Array(op(T, T2)) ≈ op(Tfull, Tfull2) end end - # test pass-through of A_mul_B! for SymTridiagonal*Bidiagonal + # test pass-through of mul! for SymTridiagonal*Bidiagonal TriSym = SymTridiagonal(T.dv, T.ev) @test Array(TriSym*T) ≈ Array(TriSym)*Array(T) - # test pass-through of A_mul_B! for AbstractTriangular*Bidiagonal + # test pass-through of mul! for AbstractTriangular*Bidiagonal Tri = UpperTriangular(diagm(1 => T.ev)) @test Array(Tri*T) ≈ Array(Tri)*Array(T) end From 116b9515b12c4f3a5a4eea6b08f0457f107f91ae Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 14:34:46 -0800 Subject: [PATCH 52/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/givens.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/givens.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/linalg/givens.jl b/test/linalg/givens.jl index f587d9ed265af7..355eab97c69efe 100644 --- a/test/linalg/givens.jl +++ b/test/linalg/givens.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test +using Base.LinAlg: mul!, Adjoint, Transpose # Test givens rotations @testset for elty in (Float32, Float64, Complex64, Complex128) @@ -15,11 +16,11 @@ using Test for j = 1:8 for i = j+2:10 G, _ = givens(A, j+1, i, j) - A_mul_B!(G, A) - A_mul_Bc!(A, G) - A_mul_B!(G, R) + mul!(G, A) + mul!(A, Adjoint(G)) + mul!(G, R) - @test A_mul_B!(G,Matrix{elty}(I, 10, 10)) == [G[i,j] for i=1:10,j=1:10] + @test mul!(G,Matrix{elty}(I, 10, 10)) == [G[i,j] for i=1:10,j=1:10] @testset "transposes" begin @test adjoint(G)*G*Matrix(elty(1)I, 10, 10) ≈ Matrix(I, 10, 10) @@ -32,8 +33,8 @@ using Test @test_throws ArgumentError givens(A, 3, 3, 2) @test_throws ArgumentError givens(one(elty),zero(elty),2,2) G, _ = givens(one(elty),zero(elty),11,12) - @test_throws DimensionMismatch A_mul_B!(G, A) - @test_throws DimensionMismatch A_mul_Bc!(A,G) + @test_throws DimensionMismatch mul!(G, A) + @test_throws DimensionMismatch mul!(A, Adjoint(G)) @test abs.(A) ≈ abs.(hessfact(Ac)[:H]) @test norm(R*Matrix{elty}(I, 10, 10)) ≈ one(elty) From 8b773fe25bd84110c900a2aa3580bcc6714684eb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 14:38:27 -0800 Subject: [PATCH 53/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/lq.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/lq.jl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/linalg/lq.jl b/test/linalg/lq.jl index 9c1ccac0a28eb4..37211bab29a510 100644 --- a/test/linalg/lq.jl +++ b/test/linalg/lq.jl @@ -2,7 +2,7 @@ using Test -using Base.LinAlg: BlasComplex, BlasFloat, BlasReal +using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, mul!, Adjoint, Transpose n = 10 @@ -21,7 +21,7 @@ breal = randn(n,2)/2 bimg = randn(n,2)/2 # helper functions to unambiguously recover explicit forms of an LQPackedQ -squareQ(Q::LinAlg.LQPackedQ) = (n = size(Q.factors, 2); A_mul_B!(Q, Matrix{eltype(Q)}(I, n, n))) +squareQ(Q::LinAlg.LQPackedQ) = (n = size(Q.factors, 2); mul!(Q, Matrix{eltype(Q)}(I, n, n))) rectangularQ(Q::LinAlg.LQPackedQ) = convert(Array, Q) @testset for eltya in (Float32, Float64, Complex64, Complex128) @@ -68,7 +68,7 @@ rectangularQ(Q::LinAlg.LQPackedQ) = convert(Array, Q) @testset "Binary ops" begin @test a*(lqa\b) ≈ b atol=3000ε @test lqa*b ≈ qra[:Q]*qra[:R]*b atol=3000ε - @test (sq = size(q.factors, 2); A_mul_Bc(Matrix{eltyb}(I, sq, sq), q)*squareQ(q)) ≈ Matrix(I, n, n) atol=5000ε + @test (sq = size(q.factors, 2); *(Matrix{eltyb}(I, sq, sq), Adjoint(q))*squareQ(q)) ≈ Matrix(I, n, n) atol=5000ε if eltya != Int @test Matrix{eltyb}(I, n, n)*q ≈ convert(AbstractMatrix{tab},q) end @@ -81,7 +81,7 @@ rectangularQ(Q::LinAlg.LQPackedQ) = convert(Array, Q) @test a'*q ≈ a'*squareQ(q) atol=100ε @test a'*q' ≈ a'*squareQ(q)' atol=100ε @test_throws DimensionMismatch q*b[1:n1 + 1] - @test_throws DimensionMismatch Ac_mul_B(q,ones(eltya,n+2,n+2)) + @test_throws DimensionMismatch Adjoint(q) * ones(eltya,n+2,n+2) @test_throws DimensionMismatch ones(eltyb,n+2,n+2)*q if isa(a, DenseArray) && isa(b, DenseArray) # use this to test 2nd branch in mult code @@ -100,9 +100,9 @@ rectangularQ(Q::LinAlg.LQPackedQ) = convert(Array, Q) l,q = lqa[:L], lqa[:Q] @test rectangularQ(q)*rectangularQ(q)' ≈ Matrix(I, n1, n1) @test squareQ(q)'*squareQ(q) ≈ Matrix(I, n1, n1) - @test_throws DimensionMismatch A_mul_B!(Matrix{eltya}(I, n+1, n+1),q) - @test Ac_mul_B!(q, rectangularQ(q)) ≈ Matrix(I, n1, n1) - @test_throws DimensionMismatch A_mul_Bc!(Matrix{eltya}(I, n+1, n+1),q) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1),q) + @test mul!(Adjoint(q), rectangularQ(q)) ≈ Matrix(I, n1, n1) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1), Adjoint(q)) @test_throws BoundsError size(q,-1) end end @@ -150,7 +150,7 @@ end function getqs(F::Base.LinAlg.LQ) implicitQ = F[:Q] sq = size(implicitQ.factors, 2) - explicitQ = A_mul_B!(implicitQ, Matrix{eltype(implicitQ)}(I, sq, sq)) + explicitQ = mul!(implicitQ, Matrix{eltype(implicitQ)}(I, sq, sq)) return implicitQ, explicitQ end @@ -191,7 +191,7 @@ end @testset "postmultiplication with / right-application of LQPackedQ (#23779)" begin function getqs(F::Base.LinAlg.LQ) implicitQ = F[:Q] - explicitQ = A_mul_B!(implicitQ, Matrix{eltype(implicitQ)}(I, size(implicitQ)...)) + explicitQ = mul!(implicitQ, Matrix{eltype(implicitQ)}(I, size(implicitQ)...)) return implicitQ, explicitQ end # for any shape m-by-n of LQ-factored matrix, where Q is an LQPackedQ @@ -201,9 +201,9 @@ end implicitQ, explicitQ = getqs(lqfact(randn(mA, nA))) C = randn(nA, nA) @test *(C, implicitQ) ≈ *(C, explicitQ) - @test A_mul_Bc(C, implicitQ) ≈ A_mul_Bc(C, explicitQ) - @test Ac_mul_B(C, implicitQ) ≈ Ac_mul_B(C, explicitQ) - @test Ac_mul_Bc(C, implicitQ) ≈ Ac_mul_Bc(C, explicitQ) + @test *(C, Adjoint(implicitQ)) ≈ *(C, Adjoint(explicitQ)) + @test *(Adjoint(C), implicitQ) ≈ *(Adjoint(C), explicitQ) + @test *(Adjoint(C), Adjoint(implicitQ)) ≈ *(Adjoint(C), Adjoint(explicitQ)) end # where the LQ-factored matrix has at least as many rows m as columns n, # Q's full/square and reduced/rectangular forms have the same shape (n-by-n). hence we expect @@ -220,7 +220,7 @@ end zeroextCright = hcat(C, zeros(eltype(C), mA)) zeroextCdown = vcat(C, zeros(eltype(C), (1, mA))) @test *(C, implicitQ) ≈ *(zeroextCright, explicitQ) - @test Ac_mul_B(C, implicitQ) ≈ Ac_mul_B(zeroextCdown, explicitQ) - @test_throws DimensionMismatch A_mul_Bc(C, implicitQ) - @test_throws DimensionMismatch Ac_mul_Bc(C, implicitQ) + @test *(Adjoint(C), implicitQ) ≈ *(Adjoint(zeroextCdown), explicitQ) + @test_throws DimensionMismatch C * Adjoint(implicitQ) + @test_throws DimensionMismatch Adjoint(C) * Adjoint(implicitQ) end From 613f32078b40a4d21713652f18148247e54ad94a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 14:55:30 -0800 Subject: [PATCH 54/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/lu.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/lu.jl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/linalg/lu.jl b/test/linalg/lu.jl index a22ed82002256c..e396fff01d95e6 100644 --- a/test/linalg/lu.jl +++ b/test/linalg/lu.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Test +using Base.LinAlg: ldiv!, Adjoint, Transpose import Base.LinAlg.BlasInt, Base.LinAlg.BlasFloat n = 10 @@ -119,18 +120,18 @@ dimg = randn(n)/2 b_dest = similar(b, resultT) c_dest = similar(c, resultT) - A_ldiv_B!(b_dest, lua, b) - A_ldiv_B!(c_dest, lua, c) + ldiv!(b_dest, lua, b) + ldiv!(c_dest, lua, c) @test norm(b_dest - lua \ b, 1) < ε*κ*2n @test norm(c_dest - lua \ c, 1) < ε*κ*n - At_ldiv_B!(b_dest, lua, b) - At_ldiv_B!(c_dest, lua, c) + ldiv!(b_dest, Transpose(lua), b) + ldiv!(c_dest, Transpose(lua), c) @test norm(b_dest - lua.' \ b, 1) < ε*κ*2n @test norm(c_dest - lua.' \ c, 1) < ε*κ*n - Ac_ldiv_B!(b_dest, lua, b) - Ac_ldiv_B!(c_dest, lua, c) + ldiv!(b_dest, Adjoint(lua), b) + ldiv!(c_dest, Adjoint(lua), c) @test norm(b_dest - lua' \ b, 1) < ε*κ*2n @test norm(c_dest - lua' \ c, 1) < ε*κ*n end @@ -145,14 +146,14 @@ dimg = randn(n)/2 @test_throws DimensionMismatch lud\f @test_throws DimensionMismatch lud.'\f @test_throws DimensionMismatch lud'\f - @test_throws DimensionMismatch Base.LinAlg.At_ldiv_B!(lud, f) + @test_throws DimensionMismatch Base.LinAlg.ldiv!(Transpose(lud), f) let Bs = copy(b) for bb in (Bs, view(Bs, 1:n, 1)) @test norm(d*(lud\bb) - bb, 1) < ε*κd*n*2 # Two because the right hand side has two columns if eltya <: Real @test norm((lud.'\bb) - Array(d.')\bb, 1) < ε*κd*n*2 # Two because the right hand side has two columns if eltya != Int && eltyb != Int - @test norm(Base.LinAlg.At_ldiv_B!(lud, copy(bb)) - Array(d.')\bb, 1) < ε*κd*n*2 + @test norm(Base.LinAlg.ldiv!(Transpose(lud), copy(bb)) - Array(d.')\bb, 1) < ε*κd*n*2 end end if eltya <: Complex From 306d1dd3e97b80bb2126b495733c85e6b47c90eb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:03:20 -0800 Subject: [PATCH 55/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/matmul.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/matmul.jl | 108 +++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/test/linalg/matmul.jl b/test/linalg/matmul.jl index fdb6b94e8963ba..429d05810401bb 100644 --- a/test/linalg/matmul.jl +++ b/test/linalg/matmul.jl @@ -2,6 +2,8 @@ using Test +using Base.LinAlg: mul!, Adjoint, Transpose + ## Test Julia fallbacks to BLAS routines @testset "matrices with zero dimensions" begin @@ -24,19 +26,19 @@ end BBi = BB+(2.5*im).*AA[[2,1],[2,1]] for A in (copy(AA), view(AA, 1:2, 1:2)), B in (copy(BB), view(BB, 1:2, 1:2)) @test A*B == [19 22; 43 50] - @test At_mul_B(A, B) == [26 30; 38 44] - @test A_mul_Bt(A, B) == [17 23; 39 53] - @test At_mul_Bt(A, B) == [23 31; 34 46] + @test *(Transpose(A), B) == [26 30; 38 44] + @test *(A, Transpose(B)) == [17 23; 39 53] + @test *(Transpose(A), Transpose(B)) == [23 31; 34 46] end for Ai in (copy(AAi), view(AAi, 1:2, 1:2)), Bi in (copy(BBi), view(BBi, 1:2, 1:2)) @test Ai*Bi == [-21+53.5im -4.25+51.5im; -12+95.5im 13.75+85.5im] - @test Ac_mul_B(Ai, Bi) == [68.5-12im 57.5-28im; 88-3im 76.5-25im] - @test A_mul_Bc(Ai, Bi) == [64.5+5.5im 43+31.5im; 104-18.5im 80.5+31.5im] - @test Ac_mul_Bc(Ai, Bi) == [-28.25-66im 9.75-58im; -26-89im 21-73im] + @test *(Adjoint(Ai), Bi) == [68.5-12im 57.5-28im; 88-3im 76.5-25im] + @test *(Ai, Adjoint(Bi)) == [64.5+5.5im 43+31.5im; 104-18.5im 80.5+31.5im] + @test *(Adjoint(Ai), Adjoint(Bi)) == [-28.25-66im 9.75-58im; -26-89im 21-73im] @test_throws DimensionMismatch [1 2; 0 0; 0 0] * [1 2] end CC = ones(3, 3) - @test_throws DimensionMismatch A_mul_B!(CC, AA, BB) + @test_throws DimensionMismatch mul!(CC, AA, BB) end @testset "3x3 matmul" begin AA = [1 2 3; 4 5 6; 7 8 9].-5 @@ -45,19 +47,19 @@ end BBi = BB+(2.5*im).*AA[[2,1,3],[2,3,1]] for A in (copy(AA), view(AA, 1:3, 1:3)), B in (copy(BB), view(BB, 1:3, 1:3)) @test A*B == [-26 38 -27; 1 -4 -6; 28 -46 15] - @test Ac_mul_B(A, B) == [-6 2 -25; 3 -12 -18; 12 -26 -11] - @test A_mul_Bc(A, B) == [-14 0 6; 4 -3 -3; 22 -6 -12] - @test Ac_mul_Bc(A, B) == [6 -8 -6; 12 -9 -9; 18 -10 -12] + @test *(Adjoint(A), B) == [-6 2 -25; 3 -12 -18; 12 -26 -11] + @test *(A, Adjoint(B)) == [-14 0 6; 4 -3 -3; 22 -6 -12] + @test *(Adjoint(A), Adjoint(B)) == [6 -8 -6; 12 -9 -9; 18 -10 -12] end for Ai in (copy(AAi), view(AAi, 1:3, 1:3)), Bi in (copy(BBi), view(BBi, 1:3, 1:3)) @test Ai*Bi == [-44.75+13im 11.75-25im -38.25+30im; -47.75-16.5im -51.5+51.5im -56+6im; 16.75-4.5im -53.5+52im -15.5im] - @test Ac_mul_B(Ai, Bi) == [-21+2im -1.75+49im -51.25+19.5im; 25.5+56.5im -7-35.5im 22+35.5im; -3+12im -32.25+43im -34.75-2.5im] - @test A_mul_Bc(Ai, Bi) == [-20.25+15.5im -28.75-54.5im 22.25+68.5im; -12.25+13im -15.5+75im -23+27im; 18.25+im 1.5+94.5im -27-54.5im] - @test Ac_mul_Bc(Ai, Bi) == [1+2im 20.75+9im -44.75+42im; 19.5+17.5im -54-36.5im 51-14.5im; 13+7.5im 11.25+31.5im -43.25-14.5im] + @test *(Adjoint(Ai), Bi) == [-21+2im -1.75+49im -51.25+19.5im; 25.5+56.5im -7-35.5im 22+35.5im; -3+12im -32.25+43im -34.75-2.5im] + @test *(Ai, Adjoint(Bi)) == [-20.25+15.5im -28.75-54.5im 22.25+68.5im; -12.25+13im -15.5+75im -23+27im; 18.25+im 1.5+94.5im -27-54.5im] + @test *(Adjoint(Ai), Adjoint(Bi)) == [1+2im 20.75+9im -44.75+42im; 19.5+17.5im -54-36.5im 51-14.5im; 13+7.5im 11.25+31.5im -43.25-14.5im] @test_throws DimensionMismatch [1 2 3; 0 0 0; 0 0 0] * [1 2 3] end CC = ones(4, 4) - @test_throws DimensionMismatch A_mul_B!(CC, AA, BB) + @test_throws DimensionMismatch mul!(CC, AA, BB) end # Generic AbstractArrays @@ -80,7 +82,7 @@ end BB = [2 -2; 3 -5; -4 7] for A in (copy(AA), view(AA, 1:2, 1:3)), B in (copy(BB), view(BB, 1:3, 1:2)) @test A*B == [-7 9; -4 9] - @test At_mul_Bt(A, B) == [-6 -11 15; -6 -13 18; -6 -15 21] + @test *(Transpose(A), Transpose(B)) == [-6 -11 15; -6 -13 18; -6 -15 21] end AA = ones(Int, 2, 100) BB = ones(Int, 100, 3) @@ -91,23 +93,23 @@ end BB = rand(1:20, 5, 5) .- 10 CC = Matrix{Int}(uninitialized, size(AA, 1), size(BB, 2)) for A in (copy(AA), view(AA, 1:5, 1:5)), B in (copy(BB), view(BB, 1:5, 1:5)), C in (copy(CC), view(CC, 1:5, 1:5)) - @test At_mul_B(A, B) == A'*B - @test A_mul_Bt(A, B) == A*B' + @test *(Transpose(A), B) == A'*B + @test *(A, Transpose(B)) == A*B' # Preallocated - @test A_mul_B!(C, A, B) == A*B - @test At_mul_B!(C, A, B) == A'*B - @test A_mul_Bt!(C, A, B) == A*B' - @test At_mul_Bt!(C, A, B) == A'*B' - @test Base.LinAlg.Ac_mul_Bt!(C, A, B) == A'*B.' + @test mul!(C, A, B) == A*B + @test mul!(C, Transpose(A), B) == A'*B + @test mul!(C, A, Transpose(B)) == A*B' + @test mul!(C, Transpose(A), Transpose(B)) == A'*B' + @test Base.LinAlg.mul!(C, Adjoint(A), Transpose(B)) == A'*B.' #test DimensionMismatch for generic_matmatmul - @test_throws DimensionMismatch Base.LinAlg.Ac_mul_Bt!(C,A,ones(Int,4,4)) - @test_throws DimensionMismatch Base.LinAlg.Ac_mul_Bt!(C,ones(Int,4,4),B) + @test_throws DimensionMismatch Base.LinAlg.mul!(C, Adjoint(A), Transpose(ones(Int,4,4))) + @test_throws DimensionMismatch Base.LinAlg.mul!(C, Adjoint(ones(Int,4,4)), Transpose(B)) end vv = [1,2] CC = Matrix{Int}(uninitialized, 2, 2) for v in (copy(vv), view(vv, 1:2)), C in (copy(CC), view(CC, 1:2, 1:2)) - @test @inferred(A_mul_Bc!(C, v, v)) == [1 2; 2 4] + @test @inferred(mul!(C, v, Adjoint(v))) == [1 2; 2 4] end end @@ -121,12 +123,12 @@ end vv = [1,2,3] CC = Matrix{Int}(uninitialized, 3, 3) for v in (copy(vv), view(vv, 1:3)), C in (copy(CC), view(CC, 1:3, 1:3)) - @test A_mul_Bt!(C, v, v) == v*v' + @test mul!(C, v, Transpose(v)) == v*v' end vvf = map(Float64,vv) CC = Matrix{Float64}(uninitialized, 3, 3) for vf in (copy(vvf), view(vvf, 1:3)), C in (copy(CC), view(CC, 1:3, 1:3)) - @test A_mul_Bt!(C, vf, vf) == vf*vf' + @test mul!(C, vf, Transpose(vf)) == vf*vf' end end @@ -135,9 +137,9 @@ end BB = rand(Float64,6,6) CC = zeros(Float64,6,6) for A in (copy(AA), view(AA, 1:6, 1:6)), B in (copy(BB), view(BB, 1:6, 1:6)), C in (copy(CC), view(CC, 1:6, 1:6)) - @test Base.LinAlg.At_mul_Bt!(C,A,B) == A.'*B.' - @test Base.LinAlg.A_mul_Bc!(C,A,B) == A*B.' - @test Base.LinAlg.Ac_mul_B!(C,A,B) == A.'*B + @test Base.LinAlg.mul!(C, Transpose(A), Transpose(B)) == A.'*B.' + @test Base.LinAlg.mul!(C, A, Adjoint(B)) == A*B.' + @test Base.LinAlg.mul!(C, Adjoint(A), B) == A.'*B end end @@ -147,13 +149,13 @@ end Asub = view(A, 1:2:5, 1:2:4) b = [1.2,-2.5] @test (Aref*b) == (Asub*b) - @test At_mul_B(Asub, Asub) == At_mul_B(Aref, Aref) - @test A_mul_Bt(Asub, Asub) == A_mul_Bt(Aref, Aref) + @test *(Transpose(Asub), Asub) == *(Transpose(Aref), Aref) + @test *(Asub, Transpose(Asub)) == *(Aref, Transpose(Aref)) Ai = A .+ im Aref = Ai[1:2:end,1:2:end] Asub = view(Ai, 1:2:5, 1:2:4) - @test Ac_mul_B(Asub, Asub) == Ac_mul_B(Aref, Aref) - @test A_mul_Bc(Asub, Asub) == A_mul_Bc(Aref, Aref) + @test *(Adjoint(Asub), Asub) == *(Adjoint(Aref), Aref) + @test *(Asub, Adjoint(Asub)) == *(Aref, Adjoint(Aref)) end @testset "issue #15286" begin @@ -161,33 +163,33 @@ end C = zeros(8, 8) sC = view(C, 1:2:8, 1:2:8) B = reshape(map(Float64,-9:10),5,4) - @test At_mul_B!(sC, A, A) == A'*A - @test At_mul_B!(sC, A, B) == A'*B + @test mul!(sC, Transpose(A), A) == A'*A + @test mul!(sC, Transpose(A), B) == A'*B Aim = A .- im C = zeros(Complex128,8,8) sC = view(C, 1:2:8, 1:2:8) B = reshape(map(Float64,-9:10),5,4) .+ im - @test Ac_mul_B!(sC, Aim, Aim) == Aim'*Aim - @test Ac_mul_B!(sC, Aim, B) == Aim'*B + @test mul!(sC, Adjoint(Aim), Aim) == Aim'*Aim + @test mul!(sC, Adjoint(Aim), B) == Aim'*B end @testset "syrk & herk" begin AA = reshape(1:1503, 501, 3).-750.0 res = Float64[135228751 9979252 -115270247; 9979252 10481254 10983256; -115270247 10983256 137236759] for A in (copy(AA), view(AA, 1:501, 1:3)) - @test At_mul_B(A, A) == res - @test A_mul_Bt(A',A') == res + @test *(Transpose(A), A) == res + @test *(A', Transpose(A')) == res end cutoff = 501 A = reshape(1:6*cutoff,2*cutoff,3).-(6*cutoff)/2 Asub = view(A, 1:2:2*cutoff, 1:3) Aref = A[1:2:2*cutoff, 1:3] - @test At_mul_B(Asub, Asub) == At_mul_B(Aref, Aref) + @test *(Transpose(Asub), Asub) == *(Transpose(Aref), Aref) Ai = A .- im Asub = view(Ai, 1:2:2*cutoff, 1:3) Aref = Ai[1:2:2*cutoff, 1:3] - @test Ac_mul_B(Asub, Asub) == Ac_mul_B(Aref, Aref) + @test *(Adjoint(Asub), Asub) == *(Adjoint(Aref), Aref) @test_throws DimensionMismatch Base.LinAlg.syrk_wrapper!(zeros(5,5),'N',ones(6,5)) @test_throws DimensionMismatch Base.LinAlg.herk_wrapper!(zeros(5,5),'N',ones(6,5)) @@ -281,9 +283,9 @@ end aa = rand(3,3) bb = rand(3,3) for a in (copy(aa), view(aa, 1:3, 1:3)), b in (copy(bb), view(bb, 1:3, 1:3)) - @test_throws ArgumentError A_mul_B!(a, a, b) - @test_throws ArgumentError A_mul_B!(a, b, a) - @test_throws ArgumentError A_mul_B!(a, a, a) + @test_throws ArgumentError mul!(a, a, b) + @test_throws ArgumentError mul!(a, b, a) + @test_throws ArgumentError mul!(a, a, a) end end @@ -299,7 +301,7 @@ transpose(x::RootInt) = x @testset "#14293" begin a = [RootInt(3)] C = [0] - A_mul_Bt!(C, a, a) + mul!(C, a, Transpose(a)) @test C[1] == 9 a = [RootInt(2),RootInt(10)] @test a*a' == [4 20; 20 100] @@ -308,12 +310,12 @@ transpose(x::RootInt) = x end function test_mul(C, A, B) - A_mul_B!(C, A, B) + mul!(C, A, B) @test Array(A) * Array(B) ≈ C @test A*B ≈ C end -@testset "A_mul_B! vs A_mul_B for special types" begin +@testset "mul! vs * for special types" begin eltypes = [Float32, Float64, Int64] for k in [3, 4, 10] T = rand(eltypes) @@ -355,11 +357,11 @@ end full24 = randn(2, 4) full33 = randn(3, 3) full44 = randn(4, 4) - @test_throws DimensionMismatch A_mul_B!(full43, tri44, tri33) - @test_throws DimensionMismatch A_mul_B!(full44, tri44, tri33) - @test_throws DimensionMismatch A_mul_B!(full44, tri44, full43) - @test_throws DimensionMismatch A_mul_B!(full43, tri33, full43) - @test_throws DimensionMismatch A_mul_B!(full43, full43, tri44) + @test_throws DimensionMismatch mul!(full43, tri44, tri33) + @test_throws DimensionMismatch mul!(full44, tri44, tri33) + @test_throws DimensionMismatch mul!(full44, tri44, full43) + @test_throws DimensionMismatch mul!(full43, tri33, full43) + @test_throws DimensionMismatch mul!(full43, full43, tri44) end end From cf4988ea9648b3ccef7429d90943019380e19888 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:09:49 -0800 Subject: [PATCH 56/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/qr.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/qr.jl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/linalg/qr.jl b/test/linalg/qr.jl index b9f69a2aba04d0..0c6c1a1c70e10d 100644 --- a/test/linalg/qr.jl +++ b/test/linalg/qr.jl @@ -2,7 +2,7 @@ using Test -using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted +using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, mul!, Adjoint, Transpose n = 10 @@ -20,7 +20,7 @@ breal = randn(n,2)/2 bimg = randn(n,2)/2 # helper functions to unambiguously recover explicit forms of an implicit QR Q -squareQ(Q::LinAlg.AbstractQ) = (sq = size(Q.factors, 1); A_mul_B!(Q, Matrix{eltype(Q)}(I, sq, sq))) +squareQ(Q::LinAlg.AbstractQ) = (sq = size(Q.factors, 1); mul!(Q, Matrix{eltype(Q)}(I, sq, sq))) rectangularQ(Q::LinAlg.AbstractQ) = convert(Array, Q) @testset for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) @@ -60,7 +60,7 @@ rectangularQ(Q::LinAlg.AbstractQ) = convert(Array, Q) @test a*(qra\b) ≈ b atol=3000ε @test Array(qra) ≈ a sq = size(q.factors, 2) - @test A_mul_Bc(Matrix{eltyb}(I, sq, sq), q) * squareQ(q) ≈ Matrix(I, sq, sq) atol=5000ε + @test *(Matrix{eltyb}(I, sq, sq), Adjoint(q)) * squareQ(q) ≈ Matrix(I, sq, sq) atol=5000ε if eltya != Int @test Matrix{eltyb}(I, a_1, a_1)*q ≈ convert(AbstractMatrix{tab}, q) ac = copy(a) @@ -83,7 +83,7 @@ rectangularQ(Q::LinAlg.AbstractQ) = convert(Array, Q) @test_throws DimensionMismatch q*b[1:n1 + 1] @test_throws DimensionMismatch b[1:n1 + 1]*q' sq = size(q.factors, 2) - @test A_mul_Bc(UpperTriangular(Matrix{eltyb}(I, sq, sq)), q)*squareQ(q) ≈ Matrix(I, n1, a_1) atol=5000ε + @test *(UpperTriangular(Matrix{eltyb}(I, sq, sq)), Adjoint(q))*squareQ(q) ≈ Matrix(I, n1, a_1) atol=5000ε if eltya != Int @test Matrix{eltyb}(I, a_1, a_1)*q ≈ convert(AbstractMatrix{tab},q) end @@ -124,7 +124,7 @@ rectangularQ(Q::LinAlg.AbstractQ) = convert(Array, Q) @test_throws DimensionMismatch q*b[1:n1+1] @test_throws DimensionMismatch b[1:n1+1]*q' sq = size(q.factors, 2) - @test A_mul_Bc(UpperTriangular(Matrix{eltyb}(I, sq, sq)), q)*squareQ(q) ≈ Matrix(I, n1, a_1) atol=5000ε + @test *(UpperTriangular(Matrix{eltyb}(I, sq, sq)), Adjoint(q))*squareQ(q) ≈ Matrix(I, n1, a_1) atol=5000ε if eltya != Int @test Matrix{eltyb}(I, a_1, a_1)*q ≈ convert(AbstractMatrix{tab},q) end @@ -135,20 +135,20 @@ rectangularQ(Q::LinAlg.AbstractQ) = convert(Array, Q) a = raw_a qrpa = factorize(a[:,1:n1]) q, r = qrpa[:Q], qrpa[:R] - @test A_mul_B!(squareQ(q)', q) ≈ Matrix(I, n, n) - @test_throws DimensionMismatch A_mul_B!(Matrix{eltya}(I, n+1, n+1),q) - @test A_mul_Bc!(squareQ(q), q) ≈ Matrix(I, n, n) - @test_throws DimensionMismatch A_mul_Bc!(Matrix{eltya}(I, n+1, n+1),q) + @test mul!(squareQ(q)', q) ≈ Matrix(I, n, n) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1),q) + @test mul!(squareQ(q), Adjoint(q)) ≈ Matrix(I, n, n) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1), Adjoint(q)) @test_throws BoundsError size(q,-1) - @test_throws DimensionMismatch Base.LinAlg.A_mul_B!(q,zeros(eltya,n1+1)) - @test_throws DimensionMismatch Base.LinAlg.Ac_mul_B!(q,zeros(eltya,n1+1)) + @test_throws DimensionMismatch Base.LinAlg.mul!(q,zeros(eltya,n1+1)) + @test_throws DimensionMismatch Base.LinAlg.mul!(Adjoint(q), zeros(eltya,n1+1)) qra = qrfact(a[:,1:n1], Val(false)) q, r = qra[:Q], qra[:R] - @test A_mul_B!(squareQ(q)', q) ≈ Matrix(I, n, n) - @test_throws DimensionMismatch A_mul_B!(Matrix{eltya}(I, n+1, n+1),q) - @test A_mul_Bc!(squareQ(q), q) ≈ Matrix(I, n, n) - @test_throws DimensionMismatch A_mul_Bc!(Matrix{eltya}(I, n+1, n+1),q) + @test mul!(squareQ(q)', q) ≈ Matrix(I, n, n) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1),q) + @test mul!(squareQ(q), Adjoint(q)) ≈ Matrix(I, n, n) + @test_throws DimensionMismatch mul!(Matrix{eltya}(I, n+1, n+1),Adjoint(q)) @test_throws BoundsError size(q,-1) @test_throws DimensionMismatch q * Matrix{Int8}(I, n+4, n+4) end From 5e9a327632ce2f172770500d86ae19bc7c3e6b19 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:11:31 -0800 Subject: [PATCH 57/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/special.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/special.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/linalg/special.jl b/test/linalg/special.jl index 295882508eaf82..9df77f616c9d07 100644 --- a/test/linalg/special.jl +++ b/test/linalg/special.jl @@ -2,6 +2,8 @@ using Test +using Base.LinAlg: mul!, Adjoint, Transpose + n= 10 #Size of matrix to test srand(1) @@ -114,11 +116,11 @@ end atri = typ(a) b = rand(n,n) qrb = qrfact(b,Val(true)) - @test Base.LinAlg.A_mul_Bc(atri,qrb[:Q]) ≈ Matrix(atri) * qrb[:Q]' - @test Base.LinAlg.A_mul_Bc!(copy(atri),qrb[:Q]) ≈ Matrix(atri) * qrb[:Q]' + @test *(atri, Adjoint(qrb[:Q])) ≈ Matrix(atri) * qrb[:Q]' + @test mul!(copy(atri), Adjoint(qrb[:Q])) ≈ Matrix(atri) * qrb[:Q]' qrb = qrfact(b,Val(false)) - @test Base.LinAlg.A_mul_Bc(atri,qrb[:Q]) ≈ Matrix(atri) * qrb[:Q]' - @test Base.LinAlg.A_mul_Bc!(copy(atri),qrb[:Q]) ≈ Matrix(atri) * qrb[:Q]' + @test *(atri, Adjoint(qrb[:Q])) ≈ Matrix(atri) * qrb[:Q]' + @test mul!(copy(atri), Adjoint(qrb[:Q])) ≈ Matrix(atri) * qrb[:Q]' end end From 6e0f0aecc1f20a0aea674c59e0a829f9849d099b Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:12:45 -0800 Subject: [PATCH 58/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/symmetric.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/symmetric.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 0119558f792ba2..63421bd140cfe6 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -307,14 +307,14 @@ end @test a * Hermitian(aherm) ≈ a * aherm @test Hermitian(aherm) * Hermitian(aherm) ≈ aherm*aherm @test_throws DimensionMismatch Hermitian(aherm) * ones(eltya,n+1) - Base.LinAlg.A_mul_B!(C,a,Hermitian(aherm)) + Base.LinAlg.mul!(C,a,Hermitian(aherm)) @test C ≈ a*aherm @test Symmetric(asym) * Symmetric(asym) ≈ asym*asym @test Symmetric(asym) * a ≈ asym * a @test a * Symmetric(asym) ≈ a * asym @test_throws DimensionMismatch Symmetric(asym) * ones(eltya,n+1) - Base.LinAlg.A_mul_B!(C,a,Symmetric(asym)) + Base.LinAlg.mul!(C,a,Symmetric(asym)) @test C ≈ a*asym tri_b = UpperTriangular(triu(b)) From df92f58c1b391694d631098f655db1e5701f4311 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:19:08 -0800 Subject: [PATCH 59/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/triangular.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/triangular.jl | 62 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/test/linalg/triangular.jl b/test/linalg/triangular.jl index 0d8b5d8dbb0837..6badb09afab71a 100644 --- a/test/linalg/triangular.jl +++ b/test/linalg/triangular.jl @@ -2,7 +2,9 @@ debug = false using Test -using Base.LinAlg: BlasFloat, errorbounds, full!, naivesub!, transpose!, UnitUpperTriangular, UnitLowerTriangular, A_rdiv_B!, A_rdiv_Bt!, A_rdiv_Bc! +using Base.LinAlg: BlasFloat, errorbounds, full!, naivesub!, transpose!, + UnitUpperTriangular, UnitLowerTriangular, + mul!, rdiv!, Adjoint, Transpose debug && println("Triangular matrices") @@ -318,7 +320,7 @@ for elty1 in (Float32, Float64, BigFloat, Complex64, Complex128, Complex{BigFloa if !(eltyB in (BigFloat, Complex{BigFloat})) # rand does not support BigFloat and Complex{BigFloat} as of Dec 2015 Tri = Tridiagonal(rand(eltyB,n-1),rand(eltyB,n),rand(eltyB,n-1)) - @test Base.LinAlg.A_mul_B!(Tri,copy(A1)) ≈ Tri*Matrix(A1) + @test mul!(Tri,copy(A1)) ≈ Tri*Matrix(A1) end # Triangular-dense Matrix/vector multiplication @@ -343,24 +345,24 @@ for elty1 in (Float32, Float64, BigFloat, Complex64, Complex128, Complex{BigFloa @test B'A1' ≈ B'Matrix(A1)' if eltyB == elty1 - @test A_mul_B!(similar(B),A1,B) ≈ A1*B - @test A_mul_Bc!(similar(B),A1,B) ≈ A1*B' - @test A_mul_Bt!(similar(B),A1,B) ≈ A1*B.' - @test Ac_mul_B!(similar(B),A1,B) ≈ A1'*B - @test At_mul_B!(similar(B),A1,B) ≈ A1.'*B + @test mul!(similar(B),A1,B) ≈ A1*B + @test mul!(similar(B), A1, Adjoint(B)) ≈ A1*B' + @test mul!(similar(B), A1, Transpose(B)) ≈ A1*B.' + @test mul!(similar(B), Adjoint(A1), B) ≈ A1'*B + @test mul!(similar(B), Transpose(A1), B) ≈ A1.'*B # test also vector methods B1 = vec(B[1,:]) - @test A_mul_B!(similar(B1),A1,B1) ≈ A1*B1 - @test Ac_mul_B!(similar(B1),A1,B1) ≈ A1'*B1 - @test At_mul_B!(similar(B1),A1,B1) ≈ A1.'*B1 + @test mul!(similar(B1),A1,B1) ≈ A1*B1 + @test mul!(similar(B1), Adjoint(A1), B1) ≈ A1'*B1 + @test mul!(similar(B1), Transpose(A1), B1) ≈ A1.'*B1 end #error handling - @test_throws DimensionMismatch Base.LinAlg.A_mul_B!(A1, ones(eltyB,n+1)) - @test_throws DimensionMismatch Base.LinAlg.A_mul_B!(ones(eltyB,n+1,n+1), A1) - @test_throws DimensionMismatch Base.LinAlg.At_mul_B!(A1, ones(eltyB,n+1)) - @test_throws DimensionMismatch Base.LinAlg.Ac_mul_B!(A1, ones(eltyB,n+1)) - @test_throws DimensionMismatch Base.LinAlg.A_mul_Bc!(ones(eltyB,n+1,n+1),A1) - @test_throws DimensionMismatch Base.LinAlg.A_mul_Bt!(ones(eltyB,n+1,n+1),A1) + @test_throws DimensionMismatch mul!(A1, ones(eltyB,n+1)) + @test_throws DimensionMismatch mul!(ones(eltyB,n+1,n+1), A1) + @test_throws DimensionMismatch mul!(Transpose(A1), ones(eltyB,n+1)) + @test_throws DimensionMismatch mul!(Adjoint(A1), ones(eltyB,n+1)) + @test_throws DimensionMismatch mul!(ones(eltyB,n+1,n+1), Adjoint(A1)) + @test_throws DimensionMismatch mul!(ones(eltyB,n+1,n+1), Transpose(A1)) # ... and division @test A1\B[:,1] ≈ Matrix(A1)\B[:,1] @@ -489,20 +491,20 @@ end let n = 5 A = rand(Float16, n, n) B = rand(Float16, n-1, n-1) - @test_throws DimensionMismatch A_rdiv_B!(A, LowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_B!(A, UpperTriangular(B)) - @test_throws DimensionMismatch A_rdiv_B!(A, UnitLowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_B!(A, UnitUpperTriangular(B)) - - @test_throws DimensionMismatch A_rdiv_Bc!(A, LowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bc!(A, UpperTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bc!(A, UnitLowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bc!(A, UnitUpperTriangular(B)) - - @test_throws DimensionMismatch A_rdiv_Bt!(A, LowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bt!(A, UpperTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bt!(A, UnitLowerTriangular(B)) - @test_throws DimensionMismatch A_rdiv_Bt!(A, UnitUpperTriangular(B)) + @test_throws DimensionMismatch rdiv!(A, LowerTriangular(B)) + @test_throws DimensionMismatch rdiv!(A, UpperTriangular(B)) + @test_throws DimensionMismatch rdiv!(A, UnitLowerTriangular(B)) + @test_throws DimensionMismatch rdiv!(A, UnitUpperTriangular(B)) + + @test_throws DimensionMismatch rdiv!(A, Adjoint(LowerTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Adjoint(UpperTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Adjoint(UnitLowerTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Adjoint(UnitUpperTriangular(B))) + + @test_throws DimensionMismatch rdiv!(A, Transpose(LowerTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Transpose(UpperTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Transpose(UnitLowerTriangular(B))) + @test_throws DimensionMismatch rdiv!(A, Transpose(UnitUpperTriangular(B))) end # Test that UpperTriangular(LowerTriangular) throws. See #16201 From 25f36af14e939c4b0e588f521092f8c3e41ec821 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:36:27 -0800 Subject: [PATCH 60/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/tridiag.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/tridiag.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl index 187e015a961108..8cf9d39532aa99 100644 --- a/test/linalg/tridiag.jl +++ b/test/linalg/tridiag.jl @@ -214,12 +214,12 @@ guardsrand(123) do @test A*UpperTriangular(Matrix(1.0I, n, n)) ≈ fA @test A*LowerTriangular(Matrix(1.0I, n, n)) ≈ fA end - @testset "A_mul_B! errors" begin - @test_throws DimensionMismatch Base.LinAlg.A_mul_B!(similar(fA),A,ones(elty,n,n+1)) - @test_throws DimensionMismatch Base.LinAlg.A_mul_B!(similar(fA),A,ones(elty,n+1,n)) - @test_throws DimensionMismatch A_mul_B!(zeros(elty,n,n),B,ones(elty,n+1,n)) - @test_throws DimensionMismatch A_mul_B!(zeros(elty,n+1,n),B,ones(elty,n,n)) - @test_throws DimensionMismatch A_mul_B!(zeros(elty,n,n+1),B,ones(elty,n,n)) + @testset "mul! errors" begin + @test_throws DimensionMismatch Base.LinAlg.mul!(similar(fA),A,ones(elty,n,n+1)) + @test_throws DimensionMismatch Base.LinAlg.mul!(similar(fA),A,ones(elty,n+1,n)) + @test_throws DimensionMismatch Base.LinAlg.mul!(zeros(elty,n,n),B,ones(elty,n+1,n)) + @test_throws DimensionMismatch Base.LinAlg.mul!(zeros(elty,n+1,n),B,ones(elty,n,n)) + @test_throws DimensionMismatch Base.LinAlg.mul!(zeros(elty,n,n+1),B,ones(elty,n,n)) end end if mat_type == SymTridiagonal From 061c6bb0910ffaae9d4a1e78cd1944ccc4054d63 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:38:17 -0800 Subject: [PATCH 61/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/linalg/uniformscaling.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/linalg/uniformscaling.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/linalg/uniformscaling.jl b/test/linalg/uniformscaling.jl index cab11607c7ba4d..14cc00a9e9d63e 100644 --- a/test/linalg/uniformscaling.jl +++ b/test/linalg/uniformscaling.jl @@ -69,7 +69,7 @@ let @testset "transpose, conj, inv" begin @test ndims(J) == 2 @test transpose(J) == J - @test J * [1 0; 0 1] == conj(Ac_mul_B(J, [1 0; 0 1])) # ctranpose (and A(c)_mul_B) + @test J * [1 0; 0 1] == conj(*(Base.LinAlg.Adjoint(J), [1 0; 0 1])) # ctranpose (and A(c)_mul_B) @test I + I === UniformScaling(2) # + @test inv(I) == I @test inv(J) == UniformScaling(inv(λ)) From b306292f127ff46b5cecb430bb35ba34efcfcaa3 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:39:14 -0800 Subject: [PATCH 62/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/perf/* as *, /, \, mul!, ldiv!, or rdiv!. --- test/perf/blas/level3.jl | 2 +- test/perf/threads/stockcorr/pstockcorr.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/perf/blas/level3.jl b/test/perf/blas/level3.jl index a9c07a27841d31..0a64a83519337c 100644 --- a/test/perf/blas/level3.jl +++ b/test/perf/blas/level3.jl @@ -6,7 +6,7 @@ function matmultest(n, iter) a = rand(n,n) b = similar(a) for i=1:iter - A_mul_B!(b, a, a) + Base.LinAlg.mul!(b, a, a) end b end diff --git a/test/perf/threads/stockcorr/pstockcorr.jl b/test/perf/threads/stockcorr/pstockcorr.jl index 5031b7caba0322..a049cb7b6f02f6 100644 --- a/test/perf/threads/stockcorr/pstockcorr.jl +++ b/test/perf/threads/stockcorr/pstockcorr.jl @@ -48,7 +48,7 @@ function runpath!(n, Wiener, CorrWiener, SA, SB, T, UpperTriangle, k11, k12, k21 #for i = 1:n randn!(rngs[threadid()], Wiener) #randn!(rngs[1], Wiener) - A_mul_B!(CorrWiener, Wiener, UpperTriangle) + Base.LinAlg.mul!(CorrWiener, Wiener, UpperTriangle) @simd for j = 2:T @inbounds SA[j, i] = SA[j-1, i] * exp(k11 + k12*CorrWiener[j-1, 1]) @inbounds SB[j, i] = SB[j-1, i] * exp(k21 + k22*CorrWiener[j-1, 2]) From 2b91b2f9806188a53a8f5d9069640269fa82890e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:42:03 -0800 Subject: [PATCH 63/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/sparse/sparse.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/sparse/sparse.jl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index c156f4f0ca9dd8..cca70e78d10525 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base.LinAlg: mul!, ldiv!, rdiv!, Adjoint, Transpose + @testset "issparse" begin @test issparse(sparse(ones(5,5))) @test !issparse(ones(5,5)) @@ -191,10 +193,10 @@ end α = rand(Complex128) β = rand(Complex128) @test (maximum(abs.(a*b - Array(a)*b)) < 100*eps()) - @test (maximum(abs.(A_mul_B!(similar(b), a, b) - Array(a)*b)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. - @test (maximum(abs.(A_mul_B!(similar(c), a, c) - Array(a)*c)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. - @test (maximum(abs.(At_mul_B!(similar(b), a, b) - Array(a).'*b)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. - @test (maximum(abs.(At_mul_B!(similar(c), a, c) - Array(a).'*c)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. + @test (maximum(abs.(mul!(similar(b), a, b) - Array(a)*b)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. + @test (maximum(abs.(mul!(similar(c), a, c) - Array(a)*c)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. + @test (maximum(abs.(mul!(similar(b), Transpose(a), b) - Array(a).'*b)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. + @test (maximum(abs.(mul!(similar(c), Transpose(a), c) - Array(a).'*c)) < 100*eps()) # for compatibility with present matmul API. Should go away eventually. @test (maximum(abs.(a'b - Array(a)'b)) < 100*eps()) @test (maximum(abs.(a.'b - Array(a).'b)) < 100*eps()) @test (maximum(abs.(a\b - Array(a)\b)) < 1000*eps()) @@ -340,11 +342,11 @@ dA = Array(sA) bi = inv.(b) dAt = transpose(dA) sAt = transpose(sA) - @test scale!(copy(dAt), bi) ≈ Base.LinAlg.A_rdiv_B!(copy(sAt), Diagonal(b)) - @test scale!(copy(dAt), bi) ≈ Base.LinAlg.A_rdiv_Bt!(copy(sAt), Diagonal(b)) - @test scale!(copy(dAt), conj(bi)) ≈ Base.LinAlg.A_rdiv_Bc!(copy(sAt), Diagonal(b)) - @test_throws DimensionMismatch Base.LinAlg.A_rdiv_B!(copy(sAt), Diagonal(ones(length(b) + 1))) - @test_throws LinAlg.SingularException Base.LinAlg.A_rdiv_B!(copy(sAt), Diagonal(zeros(length(b)))) + @test scale!(copy(dAt), bi) ≈ rdiv!(copy(sAt), Diagonal(b)) + @test scale!(copy(dAt), bi) ≈ rdiv!(copy(sAt), Transpose(Diagonal(b))) + @test scale!(copy(dAt), conj(bi)) ≈ rdiv!(copy(sAt), Adjoint(Diagonal(b))) + @test_throws DimensionMismatch rdiv!(copy(sAt), Diagonal(ones(length(b) + 1))) + @test_throws LinAlg.SingularException rdiv!(copy(sAt), Diagonal(zeros(length(b)))) end end @@ -1842,7 +1844,7 @@ end m = 5 intmat = fill(1, m, m) ltintmat = LowerTriangular(rand(1:5, m, m)) - @test At_ldiv_B(ltintmat, sparse(intmat)) ≈ At_ldiv_B(ltintmat, intmat) + @test \(Transpose(ltintmat), sparse(intmat)) ≈ \(Transpose(ltintmat), intmat) end # Test temporary fix for issue #16548 in PR #16979. Somewhat brittle. Expect to remove with `\` revisions. From fa97d9cc78398e496aaccd5b7b04b4d51b141250 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 15:48:15 -0800 Subject: [PATCH 64/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in test/sparse/sparsevector.jl as *, /, \, mul!, ldiv!, or rdiv!. --- test/sparse/sparsevector.jl | 52 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 36eef43aa195af..474e24ee90c22b 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base.LinAlg: mul!, ldiv!, Adjoint, Transpose + ### Data spv_x1 = SparseVector(8, [2, 5, 6], [1.25, -0.75, 3.5]) @@ -816,7 +818,7 @@ end for α in [0.0, 1.0, 2.0], β in [0.0, 0.5, 1.0] y = rand(9) rr = α*A*xf + β*y - @test A_mul_B!(α, A, x, β, y) === y + @test mul!(α, A, x, β, y) === y @test y ≈ rr end y = A*x @@ -829,12 +831,12 @@ end for α in [0.0, 1.0, 2.0], β in [0.0, 0.5, 1.0] y = rand(9) rr = α*A'xf + β*y - @test At_mul_B!(α, A, x, β, y) === y + @test mul!(α, Transpose(A), x, β, y) === y @test y ≈ rr end - y = At_mul_B(A, x) + y = *(Transpose(A), x) @test isa(y, Vector{Float64}) - @test y ≈ At_mul_B(A, xf) + @test y ≈ *(Transpose(A), xf) end end @testset "sparse A * sparse x -> dense y" begin @@ -844,7 +846,7 @@ end for α in [0.0, 1.0, 2.0], β in [0.0, 0.5, 1.0] y = rand(9) rr = α*Af*xf + β*y - @test A_mul_B!(α, A, x, β, y) === y + @test mul!(α, A, x, β, y) === y @test y ≈ rr end y = SparseArrays.densemv(A, x) @@ -858,12 +860,12 @@ end for α in [0.0, 1.0, 2.0], β in [0.0, 0.5, 1.0] y = rand(9) rr = α*Af'xf + β*y - @test At_mul_B!(α, A, x, β, y) === y + @test mul!(α, Transpose(A), x, β, y) === y @test y ≈ rr end y = SparseArrays.densemv(A, x; trans='T') @test isa(y, Vector{Float64}) - @test y ≈ At_mul_B(Af, xf) + @test y ≈ *(Transpose(Af), xf) end let A = complex.(sprandn(7, 8, 0.5), sprandn(7, 8, 0.5)), @@ -889,7 +891,7 @@ end @test all(nonzeros(y) .!= 0.0) @test Array(y) ≈ Af * xf - y = At_mul_B(A, x2) + y = *(Transpose(A), x2) @test isa(y, SparseVector{Float64,Int}) @test all(nonzeros(y) .!= 0.0) @test Array(y) ≈ Af'x2f @@ -906,11 +908,11 @@ end @test isa(y, SparseVector{Complex128,Int}) @test Array(y) ≈ Af * xf - y = At_mul_B(A, x2) + y = *(Transpose(A), x2) @test isa(y, SparseVector{Complex128,Int}) @test Array(y) ≈ Af.' * x2f - y = Ac_mul_B(A, x2) + y = *(Adjoint(A), x2) @test isa(y, SparseVector{Complex128,Int}) @test Array(y) ≈ Af'x2f end @@ -955,19 +957,25 @@ end for spvec in spvecs fspvec = convert(Array, spvec) # test out-of-place left-division methods - for mat in (trimats..., unittrimats...), func in (\, At_ldiv_B, Ac_ldiv_B) - @test func(mat, spvec) ≈ func(mat, fspvec) + for mat in (trimats..., unittrimats...) + @test \(mat, spvec) ≈ \(mat, fspvec) + @test \(Adjoint(mat), spvec) ≈ \(Adjoint(mat), fspvec) + @test \(Transpose(mat), spvec) ≈ \(Transpose(mat), fspvec) end # test in-place left-division methods not involving quotients if eltypevec == typeof(zero(eltypemat)*zero(eltypevec) + zero(eltypemat)*zero(eltypevec)) - for mat in unittrimats, func in (A_ldiv_B!, Base.LinAlg.At_ldiv_B!, Base.LinAlg.Ac_ldiv_B!) - @test func(mat, copy(spvec)) ≈ func(mat, copy(fspvec)) + for mat in unittrimats + @test ldiv!(mat, copy(spvec)) ≈ ldiv!(mat, copy(fspvec)) + @test ldiv!(Adjoint(mat), copy(spvec)) ≈ ldiv!(Adjoint(mat), copy(fspvec)) + @test ldiv!(Transpose(mat), copy(spvec)) ≈ ldiv!(Transpose(mat), copy(fspvec)) end end # test in-place left-division methods involving quotients if eltypevec == typeof((zero(eltypemat)*zero(eltypevec) + zero(eltypemat)*zero(eltypevec))/one(eltypemat)) - for mat in trimats, func in (A_ldiv_B!, Base.LinAlg.At_ldiv_B!, Base.LinAlg.Ac_ldiv_B!) - @test func(mat, copy(spvec)) ≈ func(mat, copy(fspvec)) + for mat in trimats + @test ldiv!(mat, copy(spvec)) ≈ ldiv!(mat, copy(fspvec)) + @test ldiv!(Adjoint(mat), copy(spvec)) ≈ ldiv!(Adjoint(mat), copy(fspvec)) + @test ldiv!(Transpose(mat), copy(spvec)) ≈ ldiv!(Transpose(mat), copy(fspvec)) end end end @@ -987,12 +995,12 @@ end zerodvec = zeros(Float64, 2) for mat in (utmat, ltmat, uutmat, ultmat) - for func in (\, At_ldiv_B, Ac_ldiv_B) - @test isequal((func)(mat, zerospvec), zerodvec) - end - for ipfunc in (A_ldiv_B!, Base.LinAlg.At_ldiv_B!, Base.LinAlg.Ac_ldiv_B!) - @test isequal((ipfunc)(mat, copy(zerospvec)), zerospvec) - end + @test isequal(\(mat, zerospvec), zerodvec) + @test isequal(\(Adjoint(mat), zerospvec), zerodvec) + @test isequal(\(Transpose(mat), zerospvec), zerodvec) + @test isequal(ldiv!(mat, copy(zerospvec)), zerospvec) + @test isequal(ldiv!(Adjoint(mat), copy(zerospvec)), zerospvec) + @test isequal(ldiv!(Transpose(mat), copy(zerospvec)), zerospvec) end end end From 82fb32f8244da6f57c5034a5656018bbf755e5da Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 11 Dec 2017 19:14:28 -0500 Subject: [PATCH 65/77] loading: refactor .ji loading, to handle errors better (#24630) --- base/loading.jl | 96 ++++++++++++++++++++++++++++++---------------- base/precompile.jl | 6 +-- src/dump.c | 65 ++++++++++--------------------- src/julia.h | 4 +- test/compile.jl | 46 +++++++++++----------- 5 files changed, 110 insertions(+), 107 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 8206da5df4bef9..27fc93a2b0693c 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -118,22 +118,58 @@ end # these return either the array of modules loaded from the path / content given # or an Exception that describes why it couldn't be loaded -function _include_from_serialized(content::Vector{UInt8}) - return ccall(:jl_restore_incremental_from_buf, Any, (Ptr{UInt8}, Int), content, sizeof(content)) +function _include_from_serialized(content::Vector{UInt8}, depmods::Vector{Module}) + return ccall(:jl_restore_incremental_from_buf, Any, (Ptr{UInt8}, Int, Any), content, sizeof(content), depmods) end -function _include_from_serialized(path::String) - return ccall(:jl_restore_incremental, Any, (Cstring,), path) +function _include_from_serialized(path::String, depmods::Vector{Module}) + return ccall(:jl_restore_incremental, Any, (Cstring, Any), path, depmods) end # returns an array of modules loaded, or an Exception that describes why it failed # and it reconnects the Base.Docs.META function _require_from_serialized(mod::Symbol, path_to_try::String) - restored = _include_from_serialized(path_to_try) + return _require_from_serialized(mod, path_to_try, parse_cache_header(path_to_try)[3]) +end +function _require_from_serialized(mod::Symbol, path_to_try::String, depmodnames::Vector{Pair{Symbol, UInt64}}) + # load all of the dependent modules + ndeps = length(depmodnames) + depmods = Vector{Module}(uninitialized, ndeps) + for i in 1:ndeps + modname, uuid = depmodnames[i] + if root_module_exists(modname) + M = root_module(modname) + if module_name(M) === modname && module_uuid(M) === uuid + depmods[i] = M + end + else + modpath = find_package(string(modname)) + modpath === nothing && return ErrorException("Required dependency $modname not found in current path.") + mod = _require_search_from_serialized(modname, String(modpath)) + if !isa(mod, Bool) + for M in mod::Vector{Any} + if module_name(M) === modname && module_uuid(M) === uuid + depmods[i] = M + break + end + end + for callback in package_callbacks + invokelatest(callback, modname) + end + end + end + isassigned(depmods, i) || return ErrorException("Required dependency $modname failed to load from a cache file.") + end + # now load the path_to_try.ji file + restored = _include_from_serialized(path_to_try, depmods) if !isa(restored, Exception) for M in restored::Vector{Any} + M = M::Module if isdefined(M, Base.Docs.META) push!(Base.Docs.modules, M) end + if module_parent(M) === M + register_root_module(module_name(M), M) + end end end return restored @@ -145,12 +181,13 @@ end function _require_search_from_serialized(mod::Symbol, sourcepath::String) paths = find_all_in_cache_path(mod) for path_to_try in paths::Vector{String} - if stale_cachefile(sourcepath, path_to_try) + deps = stale_cachefile(sourcepath, path_to_try) + if deps === true continue end - restored = _require_from_serialized(mod, path_to_try) + restored = _require_from_serialized(mod, path_to_try, deps) if isa(restored, Exception) - if isa(restored, ErrorException) && endswith(restored.msg, " uuid did not match cache file.") + if isa(restored, ErrorException) # can't use this cache due to a module uuid mismatch, # defer reporting error until after trying all of the possible matches DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Failed to load $path_to_try because $(restored.msg)") @@ -183,7 +220,7 @@ const package_callbacks = Any[] const include_callbacks = Any[] # used to optionally track dependencies when requiring a module: -const _concrete_dependencies = Any[] # these dependency versions are "set in stone", and the process should try to avoid invalidating them +const _concrete_dependencies = Pair{Symbol, UInt64}[] # these dependency versions are "set in stone", and the process should try to avoid invalidating them const _require_dependencies = Any[] # a list of (mod, path, mtime) tuples that are the file dependencies of the module currently being precompiled const _track_dependencies = Ref(false) # set this to true to track the list of file dependencies function _include_dependency(modstring::AbstractString, _path::AbstractString) @@ -363,14 +400,6 @@ function unreference_module(key) end end -function register_all(a) - for m in a - if module_parent(m) === m - register_root_module(module_name(m), m) - end - end -end - function _require(mod::Symbol) # dependency-tracking is only used for one top-level include(path), # and is not applied recursively to imported modules: @@ -396,13 +425,13 @@ function _require(mod::Symbol) if path === nothing throw(ArgumentError("Module $name not found in current path.\nRun `Pkg.add(\"$name\")` to install the $name package.")) end + path = String(path) # attempt to load the module file via the precompile cache locations doneprecompile = false if JLOptions().use_compiled_modules != 0 doneprecompile = _require_search_from_serialized(mod, path) if !isa(doneprecompile, Bool) - register_all(doneprecompile) return end end @@ -430,7 +459,6 @@ function _require(mod::Symbol) warn(m, prefix="WARNING: ") # fall-through, TODO: disable __precompile__(true) error so that the normal include will succeed else - register_all(m) return end end @@ -452,7 +480,6 @@ function _require(mod::Symbol) # TODO: disable __precompile__(true) error and do normal include instead of error error("Module $mod declares __precompile__(true) but require failed to create a usable precompiled cache file.") end - register_all(m) end finally toplevel_load[] = last @@ -545,7 +572,7 @@ function evalfile(path::AbstractString, args::Vector{String}=String[]) end evalfile(path::AbstractString, args::Vector) = evalfile(path, String[args...]) -function create_expr_cache(input::String, output::String, concrete_deps::Vector{Any}) +function create_expr_cache(input::String, output::String, concrete_deps::typeof(_concrete_dependencies)) rm(output, force=true) # Remove file if it exists code_object = """ while !eof(STDIN) @@ -612,12 +639,12 @@ function compilecache(name::String) if !isdir(cachepath) mkpath(cachepath) end - cachefile::String = abspath(cachepath, name*".ji") + cachefile::String = abspath(cachepath, "$name.ji") # build up the list of modules that we want the precompile process to preserve concrete_deps = copy(_concrete_dependencies) - for (key,mod) in loaded_modules + for (key, mod) in loaded_modules if !(mod === Main || mod === Core || mod === Base) - push!(concrete_deps, (key, module_uuid(mod))) + push!(concrete_deps, key => module_uuid(mod)) end end # run the expression and cache the result @@ -644,13 +671,13 @@ module_uuid(m::Module) = ccall(:jl_module_uuid, UInt64, (Any,), m) isvalid_cache_header(f::IOStream) = 0 != ccall(:jl_read_verify_header, Cint, (Ptr{Void},), f.ios) function parse_cache_header(f::IO) - modules = Dict{Symbol,UInt64}() + modules = Vector{Pair{Symbol, UInt64}}() while true n = ntoh(read(f, Int32)) n == 0 && break sym = Symbol(read(f, n)) # module symbol uuid = ntoh(read(f, UInt64)) # module UUID (mostly just a timestamp) - modules[sym] = uuid + push!(modules, sym => uuid) end totbytes = ntoh(read(f, Int64)) # total bytes for file dependencies # read the list of files @@ -669,13 +696,13 @@ function parse_cache_header(f::IO) @assert totbytes == 12 "header of cache file appears to be corrupt" srctextpos = ntoh(read(f, Int64)) # read the list of modules that are required to be present during loading - required_modules = Dict{Symbol,UInt64}() + required_modules = Vector{Pair{Symbol, UInt64}}() while true n = ntoh(read(f, Int32)) n == 0 && break sym = Symbol(read(f, n)) # module symbol uuid = ntoh(read(f, UInt64)) # module UUID - required_modules[sym] = uuid + push!(required_modules, sym => uuid) end return modules, files, required_modules, srctextpos end @@ -736,6 +763,8 @@ function read_dependency_src(cachefile::String, filename::AbstractString) end end +# returns true if it "cachefile.ji" is stale relative to "modpath.jl" +# otherwise returns the list of dependencies to also check function stale_cachefile(modpath::String, cachefile::String) io = open(cachefile, "r") try @@ -744,13 +773,12 @@ function stale_cachefile(modpath::String, cachefile::String) return true # invalid cache file end modules, files, required_modules = parse_cache_header(io) + modules = Dict{Symbol, UInt64}(modules) # Check if transitive dependencies can be fullfilled - for mod in keys(required_modules) - if mod == :Main || mod == :Core || mod == :Base - continue + for (mod, uuid_req) in required_modules # Module is already loaded - elseif root_module_exists(mod) + if root_module_exists(mod) continue end name = string(mod) @@ -768,7 +796,7 @@ function stale_cachefile(modpath::String, cachefile::String) uuid = get(modules, mod, UInt64(0)) if uuid !== UInt64(0) if uuid === uuid_req - return false # this is the file we want + return required_modules # this is the file we want end DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile because it provides the wrong uuid (got $uuid) for $mod (want $uuid_req).") return true # cachefile doesn't provide the required version of the dependency @@ -797,7 +825,7 @@ function stale_cachefile(modpath::String, cachefile::String) return true end - return false # fresh cachefile + return required_modules # fresh cachefile finally close(io) end diff --git a/base/precompile.jl b/base/precompile.jl index 76e4718b7ecb6e..942df6db0494ad 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -1681,7 +1681,7 @@ precompile(Tuple{typeof(Base.collect_to!), Array{Int32, 1}, Base.Generator{Array precompile(Tuple{typeof(Base.collect_to!), Array{Symbol, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64, Int64}) precompile(Tuple{typeof(Base.compilecache), String}) precompile(Tuple{typeof(Base.copy!), Array{Tuple{String, Float64}, 1}, Int64, Array{Tuple{String, Float64}, 1}, Int64, Int64}) -precompile(Tuple{typeof(Base.create_expr_cache), String, String, Array{Any, 1}}) +precompile(Tuple{typeof(Base.create_expr_cache), String, String, typeof(Base._concrete_dependencies)}) precompile(Tuple{typeof(Base._delete!), Base.Dict{Symbol, Base.Condition}, Int64}) precompile(Tuple{typeof(Base.Distributed.flush_gc_msgs), Base.Distributed.Worker}) precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) @@ -1722,7 +1722,7 @@ precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Tuple{String, Float64}, Voi precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Void}, Base.Distributed.Future}) precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, String, Int64}, Tuple{String, Int64}}) precompile(Tuple{typeof(Base.include_relative), String}) -precompile(Tuple{typeof(Base._include_from_serialized), String}) +precompile(Tuple{typeof(Base._include_from_serialized), String, Vector{Module}}) precompile(Tuple{typeof(Base.indexed_next), Tuple{Symbol, UInt64}, Int64, Int64}) precompile(Tuple{typeof(Base.indexed_next), Tuple{Void, Void}, Int64, Int64}) precompile(Tuple{typeof(Base.isassigned), Array{String, 1}, Int64}) @@ -1763,7 +1763,7 @@ precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, Base.Condition}, Int64} precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, UInt64}, Int64}) precompile(Tuple{typeof(Base.rehash!), Base.Dict{Tuple{String, Float64}, Void}, Int64}) precompile(Tuple{typeof(Base.remove_linenums!), Module}) -precompile(Tuple{typeof(Base._require_from_serialized), Symbol, String}) +precompile(Tuple{typeof(Base._require_from_serialized), Symbol, String, Vector{Pair{Symbol, UInt64}}}) precompile(Tuple{typeof(Base._require_search_from_serialized), Symbol, String}) precompile(Tuple{typeof(Base.require), Symbol}) precompile(Tuple{typeof(Base.resize!), Array{Base.Condition, 1}, Int64}) diff --git a/src/dump.c b/src/dump.c index 0181d0e83c791b..2a5cddee226ab5 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1924,53 +1924,29 @@ static int size_isgreater(const void *a, const void *b) return *(size_t*)b - *(size_t*)a; } -static jl_value_t *read_verify_mod_list(ios_t *s, arraylist_t *dependent_worlds) +static jl_value_t *read_verify_mod_list(ios_t *s, arraylist_t *dependent_worlds, jl_array_t *mod_list) { if (!jl_main_module->uuid) { return jl_get_exceptionf(jl_errorexception_type, "Main module uuid state is invalid for module deserialization."); } - jl_array_t *mod_array = jl_alloc_vec_any(0); - JL_GC_PUSH1(&mod_array); - while (1) { + size_t i, l = jl_array_len(mod_list); + for (i = 0; ; i++) { size_t len = read_int32(s); - if (len == 0) { - JL_GC_POP(); - return (jl_value_t*)mod_array; - } - char *name = (char*)alloca(len+1); + if (len == 0 && i == l) + return NULL; // success + if (len == 0 || i == l) + return jl_get_exceptionf(jl_errorexception_type, "Wrong number of entries in module list."); + char *name = (char*)alloca(len + 1); ios_read(s, name, len); name[len] = '\0'; uint64_t uuid = read_uint64(s); - jl_sym_t *sym = jl_symbol(name); - jl_module_t *m = NULL; - static jl_value_t *require_func = NULL; - if (!require_func) - require_func = jl_get_global(jl_base_module, jl_symbol("require")); - jl_value_t *reqargs[2] = {require_func, (jl_value_t*)sym}; - JL_TRY { - m = (jl_module_t*)jl_apply(reqargs, 2); - } - JL_CATCH { - ios_close(s); - jl_rethrow(); - } - if (!m) { - JL_GC_POP(); - return jl_get_exceptionf(jl_errorexception_type, - "Requiring \"%s\" did not define a corresponding module.", name); - } - if (!jl_is_module(m)) { - JL_GC_POP(); - return jl_get_exceptionf(jl_errorexception_type, - "Invalid module path (%s does not name a module).", name); - } - if (m->uuid != uuid) { - JL_GC_POP(); + jl_sym_t *sym = jl_symbol_n(name, len); + jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_list, i); + if (!m || !jl_is_module(m) || m->name != sym || m->uuid != uuid) { return jl_get_exceptionf(jl_errorexception_type, - "Module %s uuid did not match cache file.", name); + "Invalid input in module list: expected %s.", name); } - jl_array_ptr_1d_push(mod_array, (jl_value_t*)m); if (m->primary_world > jl_main_module->primary_world) arraylist_push(dependent_worlds, (void*)m->primary_world); } @@ -2659,7 +2635,7 @@ static int trace_method(jl_typemap_entry_t *entry, void *closure) return 1; } -static jl_value_t *_jl_restore_incremental(ios_t *f) +static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) { jl_ptls_t ptls = jl_get_ptls_states(); if (ios_eof(f) || !jl_read_verify_header(f)) { @@ -2682,13 +2658,12 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) arraylist_new(&dependent_worlds, 0); // verify that the system state is valid - jl_value_t *verify_result = read_verify_mod_list(f, &dependent_worlds); - if (!jl_is_array(verify_result)) { + jl_value_t *verify_fail = read_verify_mod_list(f, &dependent_worlds, mod_array); + if (verify_fail) { arraylist_free(&dependent_worlds); ios_close(f); - return verify_result; + return verify_fail; } - jl_array_t *mod_array = (jl_array_t*)verify_result; // prepare to deserialize int en = jl_gc_enable(0); @@ -2751,21 +2726,21 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) return (jl_value_t*)restored; } -JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz) +JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *mod_array) { ios_t f; ios_static_buffer(&f, (char*)buf, sz); - return _jl_restore_incremental(&f); + return _jl_restore_incremental(&f, mod_array); } -JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname) +JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *mod_array) { ios_t f; if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { return jl_get_exceptionf(jl_errorexception_type, "Cache file \"%s\" not found.\n", fname); } - return _jl_restore_incremental(&f); + return _jl_restore_incremental(&f, mod_array); } // --- init --- diff --git a/src/julia.h b/src/julia.h index 241bd5b465c5dc..7f0bbca5a99b53 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1381,8 +1381,8 @@ JL_DLLEXPORT void jl_save_system_image(const char *fname); JL_DLLEXPORT void jl_restore_system_image(const char *fname); JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len); JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist); -JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname); -JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz); +JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *depmods); +JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *depmods); // front end interface JL_DLLEXPORT jl_value_t *jl_parse_input_line(const char *str, size_t len, diff --git a/test/compile.jl b/test/compile.jl index 0f6c97801bf07a..37ebe5a9849825 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -177,7 +177,6 @@ try @test_warn "WARNING: replacing module $Foo_module." begin ms = Base._require_from_serialized(Foo_module, cachefile) @test isa(ms, Array{Any,1}) - Base.register_all(ms) end let Foo = root_module(Foo_module) @@ -205,7 +204,7 @@ try modules, deps, required_modules = Base.parse_cache_header(cachefile) discard_module = mod_fl_mt -> (mod_fl_mt[2], mod_fl_mt[3]) - @test modules == Dict(Foo_module => Base.module_uuid(Foo)) + @test modules == [Foo_module => Base.module_uuid(Foo)] @test map(x -> x[1], sort(discard_module.(deps))) == [Foo_file, joinpath(dir, "bar.jl"), joinpath(dir, "foo.jl")] srctxt = Base.read_dependency_src(cachefile, Foo_file) @test !isempty(srctxt) && srctxt == read(Foo_file, String) @@ -214,13 +213,14 @@ try @test_throws ErrorException Base.read_dependency_src(cachefile, joinpath(dir, "foo.jl")) modules, deps1 = Base.cache_dependencies(cachefile) - @test modules == merge(Dict(s => Base.module_uuid(getfield(Foo, s)) for s in - [:Base, :Core, Foo2_module, FooBase_module, :Main]), - # plus modules included in the system image - Dict(s => Base.module_uuid(Base.root_module(s)) for s in - [:Base64, :CRC32c, :Dates, :DelimitedFiles, :FileWatching, - :IterativeEigenSolvers, :Mmap, :Profile, :SharedArrays, - :SuiteSparse, :Test])) + @test Dict(modules) == merge( + Dict(s => Base.module_uuid(getfield(Foo, s)) for s in + [:Base, :Core, Foo2_module, FooBase_module, :Main]), + # plus modules included in the system image + Dict(s => Base.module_uuid(Base.root_module(s)) for s in + [:Base64, :CRC32c, :Dates, :DelimitedFiles, :FileWatching, + :IterativeEigenSolvers, :Mmap, :Profile, :SharedArrays, + :SuiteSparse, :Test])) @test discard_module.(deps) == deps1 @test current_task()(0x01, 0x4000, 0x30031234) == 2 @@ -297,26 +297,26 @@ try Base.compilecache("FooBar") @test isfile(joinpath(dir, "FooBar.ji")) - @test !Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) isa Vector @test !isdefined(Main, :FooBar) @test !isdefined(Main, :FooBar1) relFooBar_file = joinpath(dir, "subfolder", "..", "FooBar.jl") - @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) == !Sys.iswindows() # `..` is not a symlink on Windows + @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) isa (Sys.iswindows() ? Vector : Bool) # `..` is not a symlink on Windows mkdir(joinpath(dir, "subfolder")) - @test !Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) + @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) isa Vector @eval using FooBar fb_uuid = Base.module_uuid(FooBar) sleep(2); touch(FooBar_file) insert!(Base.LOAD_CACHE_PATH, 1, dir2) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true @eval using FooBar1 @test !isfile(joinpath(dir2, "FooBar.ji")) @test !isfile(joinpath(dir, "FooBar1.ji")) @test isfile(joinpath(dir2, "FooBar1.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) - @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector @test fb_uuid == Base.module_uuid(FooBar) fb_uuid1 = Base.module_uuid(FooBar1) @test fb_uuid != fb_uuid1 @@ -326,9 +326,9 @@ try @test fb_uuid1 == Base.module_uuid(FooBar1) fb_uuid = Base.module_uuid(root_module(:FooBar)) @test isfile(joinpath(dir2, "FooBar.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) - @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) - @test !Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector + @test Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) isa Vector reload("FooBar1") @test fb_uuid == Base.module_uuid(root_module(:FooBar)) @@ -336,15 +336,15 @@ try @test isfile(joinpath(dir2, "FooBar.ji")) @test isfile(joinpath(dir2, "FooBar1.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) - @test !Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) - @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true + @test Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) isa Vector + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector # test checksum open(joinpath(dir2, "FooBar1.ji"), "a") do f write(f, 0x076cac96) # append 4 random bytes end - @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) === true # test behavior of precompile modules that throw errors FooBar2_file = joinpath(dir, "FooBar2.jl") @@ -395,7 +395,7 @@ try end """) rm(FooBarT_file) - @test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji")) + @test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji")) === true @test Base.require(:FooBarT2) isa Module finally splice!(Base.LOAD_CACHE_PATH, 1:2) From f81d7ef284a01871bb4bf479f98c9f40ee861287 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Mon, 11 Dec 2017 19:31:11 -0500 Subject: [PATCH 66/77] Revert "loading: refactor .ji loading, to handle errors better (#24630)" This reverts commit 82fb32f8244da6f57c5034a5656018bbf755e5da. --- base/loading.jl | 96 ++++++++++++++++------------------------------ base/precompile.jl | 6 +-- src/dump.c | 65 +++++++++++++++++++++---------- src/julia.h | 4 +- test/compile.jl | 46 +++++++++++----------- 5 files changed, 107 insertions(+), 110 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 27fc93a2b0693c..8206da5df4bef9 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -118,58 +118,22 @@ end # these return either the array of modules loaded from the path / content given # or an Exception that describes why it couldn't be loaded -function _include_from_serialized(content::Vector{UInt8}, depmods::Vector{Module}) - return ccall(:jl_restore_incremental_from_buf, Any, (Ptr{UInt8}, Int, Any), content, sizeof(content), depmods) +function _include_from_serialized(content::Vector{UInt8}) + return ccall(:jl_restore_incremental_from_buf, Any, (Ptr{UInt8}, Int), content, sizeof(content)) end -function _include_from_serialized(path::String, depmods::Vector{Module}) - return ccall(:jl_restore_incremental, Any, (Cstring, Any), path, depmods) +function _include_from_serialized(path::String) + return ccall(:jl_restore_incremental, Any, (Cstring,), path) end # returns an array of modules loaded, or an Exception that describes why it failed # and it reconnects the Base.Docs.META function _require_from_serialized(mod::Symbol, path_to_try::String) - return _require_from_serialized(mod, path_to_try, parse_cache_header(path_to_try)[3]) -end -function _require_from_serialized(mod::Symbol, path_to_try::String, depmodnames::Vector{Pair{Symbol, UInt64}}) - # load all of the dependent modules - ndeps = length(depmodnames) - depmods = Vector{Module}(uninitialized, ndeps) - for i in 1:ndeps - modname, uuid = depmodnames[i] - if root_module_exists(modname) - M = root_module(modname) - if module_name(M) === modname && module_uuid(M) === uuid - depmods[i] = M - end - else - modpath = find_package(string(modname)) - modpath === nothing && return ErrorException("Required dependency $modname not found in current path.") - mod = _require_search_from_serialized(modname, String(modpath)) - if !isa(mod, Bool) - for M in mod::Vector{Any} - if module_name(M) === modname && module_uuid(M) === uuid - depmods[i] = M - break - end - end - for callback in package_callbacks - invokelatest(callback, modname) - end - end - end - isassigned(depmods, i) || return ErrorException("Required dependency $modname failed to load from a cache file.") - end - # now load the path_to_try.ji file - restored = _include_from_serialized(path_to_try, depmods) + restored = _include_from_serialized(path_to_try) if !isa(restored, Exception) for M in restored::Vector{Any} - M = M::Module if isdefined(M, Base.Docs.META) push!(Base.Docs.modules, M) end - if module_parent(M) === M - register_root_module(module_name(M), M) - end end end return restored @@ -181,13 +145,12 @@ end function _require_search_from_serialized(mod::Symbol, sourcepath::String) paths = find_all_in_cache_path(mod) for path_to_try in paths::Vector{String} - deps = stale_cachefile(sourcepath, path_to_try) - if deps === true + if stale_cachefile(sourcepath, path_to_try) continue end - restored = _require_from_serialized(mod, path_to_try, deps) + restored = _require_from_serialized(mod, path_to_try) if isa(restored, Exception) - if isa(restored, ErrorException) + if isa(restored, ErrorException) && endswith(restored.msg, " uuid did not match cache file.") # can't use this cache due to a module uuid mismatch, # defer reporting error until after trying all of the possible matches DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Failed to load $path_to_try because $(restored.msg)") @@ -220,7 +183,7 @@ const package_callbacks = Any[] const include_callbacks = Any[] # used to optionally track dependencies when requiring a module: -const _concrete_dependencies = Pair{Symbol, UInt64}[] # these dependency versions are "set in stone", and the process should try to avoid invalidating them +const _concrete_dependencies = Any[] # these dependency versions are "set in stone", and the process should try to avoid invalidating them const _require_dependencies = Any[] # a list of (mod, path, mtime) tuples that are the file dependencies of the module currently being precompiled const _track_dependencies = Ref(false) # set this to true to track the list of file dependencies function _include_dependency(modstring::AbstractString, _path::AbstractString) @@ -400,6 +363,14 @@ function unreference_module(key) end end +function register_all(a) + for m in a + if module_parent(m) === m + register_root_module(module_name(m), m) + end + end +end + function _require(mod::Symbol) # dependency-tracking is only used for one top-level include(path), # and is not applied recursively to imported modules: @@ -425,13 +396,13 @@ function _require(mod::Symbol) if path === nothing throw(ArgumentError("Module $name not found in current path.\nRun `Pkg.add(\"$name\")` to install the $name package.")) end - path = String(path) # attempt to load the module file via the precompile cache locations doneprecompile = false if JLOptions().use_compiled_modules != 0 doneprecompile = _require_search_from_serialized(mod, path) if !isa(doneprecompile, Bool) + register_all(doneprecompile) return end end @@ -459,6 +430,7 @@ function _require(mod::Symbol) warn(m, prefix="WARNING: ") # fall-through, TODO: disable __precompile__(true) error so that the normal include will succeed else + register_all(m) return end end @@ -480,6 +452,7 @@ function _require(mod::Symbol) # TODO: disable __precompile__(true) error and do normal include instead of error error("Module $mod declares __precompile__(true) but require failed to create a usable precompiled cache file.") end + register_all(m) end finally toplevel_load[] = last @@ -572,7 +545,7 @@ function evalfile(path::AbstractString, args::Vector{String}=String[]) end evalfile(path::AbstractString, args::Vector) = evalfile(path, String[args...]) -function create_expr_cache(input::String, output::String, concrete_deps::typeof(_concrete_dependencies)) +function create_expr_cache(input::String, output::String, concrete_deps::Vector{Any}) rm(output, force=true) # Remove file if it exists code_object = """ while !eof(STDIN) @@ -639,12 +612,12 @@ function compilecache(name::String) if !isdir(cachepath) mkpath(cachepath) end - cachefile::String = abspath(cachepath, "$name.ji") + cachefile::String = abspath(cachepath, name*".ji") # build up the list of modules that we want the precompile process to preserve concrete_deps = copy(_concrete_dependencies) - for (key, mod) in loaded_modules + for (key,mod) in loaded_modules if !(mod === Main || mod === Core || mod === Base) - push!(concrete_deps, key => module_uuid(mod)) + push!(concrete_deps, (key, module_uuid(mod))) end end # run the expression and cache the result @@ -671,13 +644,13 @@ module_uuid(m::Module) = ccall(:jl_module_uuid, UInt64, (Any,), m) isvalid_cache_header(f::IOStream) = 0 != ccall(:jl_read_verify_header, Cint, (Ptr{Void},), f.ios) function parse_cache_header(f::IO) - modules = Vector{Pair{Symbol, UInt64}}() + modules = Dict{Symbol,UInt64}() while true n = ntoh(read(f, Int32)) n == 0 && break sym = Symbol(read(f, n)) # module symbol uuid = ntoh(read(f, UInt64)) # module UUID (mostly just a timestamp) - push!(modules, sym => uuid) + modules[sym] = uuid end totbytes = ntoh(read(f, Int64)) # total bytes for file dependencies # read the list of files @@ -696,13 +669,13 @@ function parse_cache_header(f::IO) @assert totbytes == 12 "header of cache file appears to be corrupt" srctextpos = ntoh(read(f, Int64)) # read the list of modules that are required to be present during loading - required_modules = Vector{Pair{Symbol, UInt64}}() + required_modules = Dict{Symbol,UInt64}() while true n = ntoh(read(f, Int32)) n == 0 && break sym = Symbol(read(f, n)) # module symbol uuid = ntoh(read(f, UInt64)) # module UUID - push!(required_modules, sym => uuid) + required_modules[sym] = uuid end return modules, files, required_modules, srctextpos end @@ -763,8 +736,6 @@ function read_dependency_src(cachefile::String, filename::AbstractString) end end -# returns true if it "cachefile.ji" is stale relative to "modpath.jl" -# otherwise returns the list of dependencies to also check function stale_cachefile(modpath::String, cachefile::String) io = open(cachefile, "r") try @@ -773,12 +744,13 @@ function stale_cachefile(modpath::String, cachefile::String) return true # invalid cache file end modules, files, required_modules = parse_cache_header(io) - modules = Dict{Symbol, UInt64}(modules) # Check if transitive dependencies can be fullfilled - for (mod, uuid_req) in required_modules + for mod in keys(required_modules) + if mod == :Main || mod == :Core || mod == :Base + continue # Module is already loaded - if root_module_exists(mod) + elseif root_module_exists(mod) continue end name = string(mod) @@ -796,7 +768,7 @@ function stale_cachefile(modpath::String, cachefile::String) uuid = get(modules, mod, UInt64(0)) if uuid !== UInt64(0) if uuid === uuid_req - return required_modules # this is the file we want + return false # this is the file we want end DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile because it provides the wrong uuid (got $uuid) for $mod (want $uuid_req).") return true # cachefile doesn't provide the required version of the dependency @@ -825,7 +797,7 @@ function stale_cachefile(modpath::String, cachefile::String) return true end - return required_modules # fresh cachefile + return false # fresh cachefile finally close(io) end diff --git a/base/precompile.jl b/base/precompile.jl index 942df6db0494ad..76e4718b7ecb6e 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -1681,7 +1681,7 @@ precompile(Tuple{typeof(Base.collect_to!), Array{Int32, 1}, Base.Generator{Array precompile(Tuple{typeof(Base.collect_to!), Array{Symbol, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64, Int64}) precompile(Tuple{typeof(Base.compilecache), String}) precompile(Tuple{typeof(Base.copy!), Array{Tuple{String, Float64}, 1}, Int64, Array{Tuple{String, Float64}, 1}, Int64, Int64}) -precompile(Tuple{typeof(Base.create_expr_cache), String, String, typeof(Base._concrete_dependencies)}) +precompile(Tuple{typeof(Base.create_expr_cache), String, String, Array{Any, 1}}) precompile(Tuple{typeof(Base._delete!), Base.Dict{Symbol, Base.Condition}, Int64}) precompile(Tuple{typeof(Base.Distributed.flush_gc_msgs), Base.Distributed.Worker}) precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) @@ -1722,7 +1722,7 @@ precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Tuple{String, Float64}, Voi precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Void}, Base.Distributed.Future}) precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, String, Int64}, Tuple{String, Int64}}) precompile(Tuple{typeof(Base.include_relative), String}) -precompile(Tuple{typeof(Base._include_from_serialized), String, Vector{Module}}) +precompile(Tuple{typeof(Base._include_from_serialized), String}) precompile(Tuple{typeof(Base.indexed_next), Tuple{Symbol, UInt64}, Int64, Int64}) precompile(Tuple{typeof(Base.indexed_next), Tuple{Void, Void}, Int64, Int64}) precompile(Tuple{typeof(Base.isassigned), Array{String, 1}, Int64}) @@ -1763,7 +1763,7 @@ precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, Base.Condition}, Int64} precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, UInt64}, Int64}) precompile(Tuple{typeof(Base.rehash!), Base.Dict{Tuple{String, Float64}, Void}, Int64}) precompile(Tuple{typeof(Base.remove_linenums!), Module}) -precompile(Tuple{typeof(Base._require_from_serialized), Symbol, String, Vector{Pair{Symbol, UInt64}}}) +precompile(Tuple{typeof(Base._require_from_serialized), Symbol, String}) precompile(Tuple{typeof(Base._require_search_from_serialized), Symbol, String}) precompile(Tuple{typeof(Base.require), Symbol}) precompile(Tuple{typeof(Base.resize!), Array{Base.Condition, 1}, Int64}) diff --git a/src/dump.c b/src/dump.c index 2a5cddee226ab5..0181d0e83c791b 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1924,29 +1924,53 @@ static int size_isgreater(const void *a, const void *b) return *(size_t*)b - *(size_t*)a; } -static jl_value_t *read_verify_mod_list(ios_t *s, arraylist_t *dependent_worlds, jl_array_t *mod_list) +static jl_value_t *read_verify_mod_list(ios_t *s, arraylist_t *dependent_worlds) { if (!jl_main_module->uuid) { return jl_get_exceptionf(jl_errorexception_type, "Main module uuid state is invalid for module deserialization."); } - size_t i, l = jl_array_len(mod_list); - for (i = 0; ; i++) { + jl_array_t *mod_array = jl_alloc_vec_any(0); + JL_GC_PUSH1(&mod_array); + while (1) { size_t len = read_int32(s); - if (len == 0 && i == l) - return NULL; // success - if (len == 0 || i == l) - return jl_get_exceptionf(jl_errorexception_type, "Wrong number of entries in module list."); - char *name = (char*)alloca(len + 1); + if (len == 0) { + JL_GC_POP(); + return (jl_value_t*)mod_array; + } + char *name = (char*)alloca(len+1); ios_read(s, name, len); name[len] = '\0'; uint64_t uuid = read_uint64(s); - jl_sym_t *sym = jl_symbol_n(name, len); - jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_list, i); - if (!m || !jl_is_module(m) || m->name != sym || m->uuid != uuid) { + jl_sym_t *sym = jl_symbol(name); + jl_module_t *m = NULL; + static jl_value_t *require_func = NULL; + if (!require_func) + require_func = jl_get_global(jl_base_module, jl_symbol("require")); + jl_value_t *reqargs[2] = {require_func, (jl_value_t*)sym}; + JL_TRY { + m = (jl_module_t*)jl_apply(reqargs, 2); + } + JL_CATCH { + ios_close(s); + jl_rethrow(); + } + if (!m) { + JL_GC_POP(); + return jl_get_exceptionf(jl_errorexception_type, + "Requiring \"%s\" did not define a corresponding module.", name); + } + if (!jl_is_module(m)) { + JL_GC_POP(); + return jl_get_exceptionf(jl_errorexception_type, + "Invalid module path (%s does not name a module).", name); + } + if (m->uuid != uuid) { + JL_GC_POP(); return jl_get_exceptionf(jl_errorexception_type, - "Invalid input in module list: expected %s.", name); + "Module %s uuid did not match cache file.", name); } + jl_array_ptr_1d_push(mod_array, (jl_value_t*)m); if (m->primary_world > jl_main_module->primary_world) arraylist_push(dependent_worlds, (void*)m->primary_world); } @@ -2635,7 +2659,7 @@ static int trace_method(jl_typemap_entry_t *entry, void *closure) return 1; } -static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) +static jl_value_t *_jl_restore_incremental(ios_t *f) { jl_ptls_t ptls = jl_get_ptls_states(); if (ios_eof(f) || !jl_read_verify_header(f)) { @@ -2658,12 +2682,13 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) arraylist_new(&dependent_worlds, 0); // verify that the system state is valid - jl_value_t *verify_fail = read_verify_mod_list(f, &dependent_worlds, mod_array); - if (verify_fail) { + jl_value_t *verify_result = read_verify_mod_list(f, &dependent_worlds); + if (!jl_is_array(verify_result)) { arraylist_free(&dependent_worlds); ios_close(f); - return verify_fail; + return verify_result; } + jl_array_t *mod_array = (jl_array_t*)verify_result; // prepare to deserialize int en = jl_gc_enable(0); @@ -2726,21 +2751,21 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) return (jl_value_t*)restored; } -JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *mod_array) +JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz) { ios_t f; ios_static_buffer(&f, (char*)buf, sz); - return _jl_restore_incremental(&f, mod_array); + return _jl_restore_incremental(&f); } -JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *mod_array) +JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname) { ios_t f; if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { return jl_get_exceptionf(jl_errorexception_type, "Cache file \"%s\" not found.\n", fname); } - return _jl_restore_incremental(&f, mod_array); + return _jl_restore_incremental(&f); } // --- init --- diff --git a/src/julia.h b/src/julia.h index 7f0bbca5a99b53..241bd5b465c5dc 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1381,8 +1381,8 @@ JL_DLLEXPORT void jl_save_system_image(const char *fname); JL_DLLEXPORT void jl_restore_system_image(const char *fname); JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len); JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist); -JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *depmods); -JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *depmods); +JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname); +JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz); // front end interface JL_DLLEXPORT jl_value_t *jl_parse_input_line(const char *str, size_t len, diff --git a/test/compile.jl b/test/compile.jl index 37ebe5a9849825..0f6c97801bf07a 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -177,6 +177,7 @@ try @test_warn "WARNING: replacing module $Foo_module." begin ms = Base._require_from_serialized(Foo_module, cachefile) @test isa(ms, Array{Any,1}) + Base.register_all(ms) end let Foo = root_module(Foo_module) @@ -204,7 +205,7 @@ try modules, deps, required_modules = Base.parse_cache_header(cachefile) discard_module = mod_fl_mt -> (mod_fl_mt[2], mod_fl_mt[3]) - @test modules == [Foo_module => Base.module_uuid(Foo)] + @test modules == Dict(Foo_module => Base.module_uuid(Foo)) @test map(x -> x[1], sort(discard_module.(deps))) == [Foo_file, joinpath(dir, "bar.jl"), joinpath(dir, "foo.jl")] srctxt = Base.read_dependency_src(cachefile, Foo_file) @test !isempty(srctxt) && srctxt == read(Foo_file, String) @@ -213,14 +214,13 @@ try @test_throws ErrorException Base.read_dependency_src(cachefile, joinpath(dir, "foo.jl")) modules, deps1 = Base.cache_dependencies(cachefile) - @test Dict(modules) == merge( - Dict(s => Base.module_uuid(getfield(Foo, s)) for s in - [:Base, :Core, Foo2_module, FooBase_module, :Main]), - # plus modules included in the system image - Dict(s => Base.module_uuid(Base.root_module(s)) for s in - [:Base64, :CRC32c, :Dates, :DelimitedFiles, :FileWatching, - :IterativeEigenSolvers, :Mmap, :Profile, :SharedArrays, - :SuiteSparse, :Test])) + @test modules == merge(Dict(s => Base.module_uuid(getfield(Foo, s)) for s in + [:Base, :Core, Foo2_module, FooBase_module, :Main]), + # plus modules included in the system image + Dict(s => Base.module_uuid(Base.root_module(s)) for s in + [:Base64, :CRC32c, :Dates, :DelimitedFiles, :FileWatching, + :IterativeEigenSolvers, :Mmap, :Profile, :SharedArrays, + :SuiteSparse, :Test])) @test discard_module.(deps) == deps1 @test current_task()(0x01, 0x4000, 0x30031234) == 2 @@ -297,26 +297,26 @@ try Base.compilecache("FooBar") @test isfile(joinpath(dir, "FooBar.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) isa Vector + @test !Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) @test !isdefined(Main, :FooBar) @test !isdefined(Main, :FooBar1) relFooBar_file = joinpath(dir, "subfolder", "..", "FooBar.jl") - @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) isa (Sys.iswindows() ? Vector : Bool) # `..` is not a symlink on Windows + @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) == !Sys.iswindows() # `..` is not a symlink on Windows mkdir(joinpath(dir, "subfolder")) - @test Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) isa Vector + @test !Base.stale_cachefile(relFooBar_file, joinpath(dir, "FooBar.ji")) @eval using FooBar fb_uuid = Base.module_uuid(FooBar) sleep(2); touch(FooBar_file) insert!(Base.LOAD_CACHE_PATH, 1, dir2) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) @eval using FooBar1 @test !isfile(joinpath(dir2, "FooBar.ji")) @test !isfile(joinpath(dir, "FooBar1.ji")) @test isfile(joinpath(dir2, "FooBar1.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true - @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) + @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) @test fb_uuid == Base.module_uuid(FooBar) fb_uuid1 = Base.module_uuid(FooBar1) @test fb_uuid != fb_uuid1 @@ -326,9 +326,9 @@ try @test fb_uuid1 == Base.module_uuid(FooBar1) fb_uuid = Base.module_uuid(root_module(:FooBar)) @test isfile(joinpath(dir2, "FooBar.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true - @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector - @test Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) isa Vector + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) + @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + @test !Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) reload("FooBar1") @test fb_uuid == Base.module_uuid(root_module(:FooBar)) @@ -336,15 +336,15 @@ try @test isfile(joinpath(dir2, "FooBar.ji")) @test isfile(joinpath(dir2, "FooBar1.ji")) - @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) === true - @test Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) isa Vector - @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) isa Vector + @test Base.stale_cachefile(FooBar_file, joinpath(dir, "FooBar.ji")) + @test !Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) + @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) # test checksum open(joinpath(dir2, "FooBar1.ji"), "a") do f write(f, 0x076cac96) # append 4 random bytes end - @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) === true + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) # test behavior of precompile modules that throw errors FooBar2_file = joinpath(dir, "FooBar2.jl") @@ -395,7 +395,7 @@ try end """) rm(FooBarT_file) - @test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji")) === true + @test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji")) @test Base.require(:FooBarT2) isa Module finally splice!(Base.LOAD_CACHE_PATH, 1:2) From a11cbe5a8c608b5cc216117405702197669a3b09 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 16:51:59 -0800 Subject: [PATCH 67/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in stdlib/IterativeEigenSolvers as *, /, \, mul!, ldiv!, or rdiv!. --- .../src/IterativeEigenSolvers.jl | 16 ++++++++-------- stdlib/IterativeEigenSolvers/test/runtests.jl | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl b/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl index a5912d8909cd43..23c8f2511bc1c7 100644 --- a/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl +++ b/stdlib/IterativeEigenSolvers/src/IterativeEigenSolvers.jl @@ -7,7 +7,7 @@ Arnoldi and Lanczos iteration for computing eigenvalues """ module IterativeEigenSolvers -using Base.LinAlg: BlasFloat, BlasInt, SVD, checksquare +using Base.LinAlg: BlasFloat, BlasInt, SVD, checksquare, mul!, Adjoint, Transpose export eigs, svds @@ -152,7 +152,7 @@ function _eigs(A, B; end # Refer to ex-*.doc files in ARPACK/DOCUMENTS for calling sequence - matvecA!(y, x) = A_mul_B!(y, A, x) + matvecA!(y, x) = mul!(y, A, x) if !isgeneral # Standard problem matvecB = x -> x if !isshift # Regular mode @@ -207,8 +207,8 @@ end function Base.LinAlg.mul!(y::StridedVector{T}, A::SVDAugmented{T}, x::StridedVector{T}) where T m, mn = size(A.X, 1), length(x) - A_mul_B!( view(y, 1:m), A.X, view(x, m + 1:mn)) # left singular vector - Ac_mul_B!(view(y, m + 1:mn), A.X, view(x, 1:m)) # right singular vector + mul!( view(y, 1:m), A.X, view(x, m + 1:mn)) # left singular vector + mul!(view(y, m + 1:mn), Adjoint(A.X), view(x, 1:m)) # right singular vector return y end Base.size(A::SVDAugmented) = ((+)(size(A.X)...), (+)(size(A.X)...)) @@ -227,11 +227,11 @@ end function Base.LinAlg.mul!(y::StridedVector{T}, A::AtA_or_AAt{T}, x::StridedVector{T}) where T if size(A.A, 1) >= size(A.A, 2) - A_mul_B!(A.buffer, A.A, x) - return Ac_mul_B!(y, A.A, A.buffer) + mul!(A.buffer, A.A, x) + return mul!(y, Adjoint(A.A), A.buffer) else - Ac_mul_B!(A.buffer, A.A, x) - return A_mul_B!(y, A.A, A.buffer) + mul!(A.buffer, Adjoint(A.A), x) + return mul!(y, A.A, A.buffer) end end Base.size(A::AtA_or_AAt) = ntuple(i -> min(size(A.A)...), Val(2)) diff --git a/stdlib/IterativeEigenSolvers/test/runtests.jl b/stdlib/IterativeEigenSolvers/test/runtests.jl index 7f6392ce10bd7e..52b8e197a70793 100644 --- a/stdlib/IterativeEigenSolvers/test/runtests.jl +++ b/stdlib/IterativeEigenSolvers/test/runtests.jl @@ -148,7 +148,7 @@ function Base.LinAlg.mul!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{ return copy!(rho2,rho1) end Base.LinAlg.A_mul_B!(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) where {T<:Base.LinAlg.BlasFloat} = Base.LinAlg.mul!(rho2, Phi, rho) -# after the A_mul_B! deprecation, remove this A_mul_B! def and the import above +# after the A_mul_B! deprecation, remove this A_mul_B! def let # Generate random isometry From 5003f12928ede31f8d40dc6fab51d2928c1aaeb3 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 11 Dec 2017 16:56:25 -0800 Subject: [PATCH 68/77] Use CCache on Travis (#24998) [av skip] [bsd skip] --- .travis.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 685e1c6496f4b8..4e5a84ded11845 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: + - ccache - libssl1.0.0 - bar - time @@ -31,6 +32,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: + - ccache - libssl1.0.0 - bar - time @@ -39,11 +41,7 @@ matrix: - os: osx env: ARCH="x86_64" osx_image: xcode8 -cache: - directories: - - $TRAVIS_BUILD_DIR/deps/srccache - - $TRAVIS_BUILD_DIR/deps/scratch - - $TRAVIS_BUILD_DIR/deps/usr-staging +cache: ccache branches: only: - master @@ -72,7 +70,7 @@ before_install: ln -s /usr/bin/g++-5 $HOME/bin/x86_64-linux-gnu-g++; gcc --version; BAR="bar -i 30"; - BUILDOPTS="-j5 VERBOSE=1 FORCE_ASSERTIONS=1 LLVM_ASSERTIONS=1"; + BUILDOPTS="-j5 VERBOSE=1 FORCE_ASSERTIONS=1 LLVM_ASSERTIONS=1 USECCACHE=1"; echo "override ARCH=$ARCH" >> Make.user; sudo sh -c "echo 0 > /proc/sys/net/ipv6/conf/lo/disable_ipv6"; export JULIA_CPU_CORES=4; @@ -80,14 +78,15 @@ before_install: TESTSTORUN="all"; elif [ `uname` = "Darwin" ]; then brew update; - brew install -v jq pv; + brew install -v jq pv ccache; + export PATH="$(brew --prefix ccache)/libexec:$PATH"; BAR="pv -i 30"; contrib/travis_fastfail.sh || exit 1; brew tap staticfloat/julia; brew rm --force $(brew deps --HEAD julia); brew install -v --only-dependencies --HEAD julia; brew install -v staticfloat/juliadeps/libgfortran llvm39-julia; - BUILDOPTS="-j3 USECLANG=1 LLVM_CONFIG=$(brew --prefix llvm39-julia)/bin/llvm-config LLVM_SIZE=$(brew --prefix llvm39-julia)/bin/llvm-size"; + BUILDOPTS="-j3 USECLANG=1 USECCACHE=1 LLVM_CONFIG=$(brew --prefix llvm39-julia)/bin/llvm-config LLVM_SIZE=$(brew --prefix llvm39-julia)/bin/llvm-size"; BUILDOPTS="$BUILDOPTS VERBOSE=1 USE_BLAS64=0 SUITESPARSE_INC=-I$(brew --prefix suite-sparse-julia)/include FORCE_ASSERTIONS=1"; BUILDOPTS="$BUILDOPTS LIBBLAS=-lopenblas LIBBLASNAME=libopenblas LIBLAPACK=-lopenblas LIBLAPACKNAME=libopenblas"; for lib in LLVM SUITESPARSE ARPACK BLAS LAPACK GMP MPFR PCRE LIBUNWIND; do From d9a004907dc2d95383a14722ed6db235daf6329c Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 11 Dec 2017 17:16:43 -0800 Subject: [PATCH 69/77] Remove `-i` flag being passed to `bash` for shell mode commands (#25006) Fixes https://github.com/JuliaLang/julia/issues/24736 Fixes https://github.com/JuliaLang/julia/issues/17332 --- base/client.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/client.jl b/base/client.jl index df6f5df0c9d3d7..0aff79a82cc3d2 100644 --- a/base/client.jl +++ b/base/client.jl @@ -129,9 +129,7 @@ function repl_cmd(cmd, out) else shell_escape_cmd = "($(shell_escape_posixly(cmd))) && true" end - cmd = `$shell` - isa(STDIN, TTY) && (cmd = `$cmd -i`) - cmd = `$cmd -c $shell_escape_cmd` + cmd = `$shell -c $shell_escape_cmd` end run(ignorestatus(cmd)) end From 38ba1d07918af34e3f02bb67ec1ce62f2d428cdb Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 11 Dec 2017 17:19:05 -0800 Subject: [PATCH 70/77] Set `JULIA_PKGDIR` before Julia ever starts up when building docs (#25009) Attempting to set `ENV["JULIA_PKGDIR"]` from within Julia doesn't work, as the `LOAD_CACHE_PATH` is initialized within an `__init__()` function within `Pkg`, causing compile cache files to be saved to the default location (within the user's `$HOME`) rather than the override location. This change ensures that the docs pkg environment is properly confined. --- doc/Makefile | 1 + doc/make.jl | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index 743804d8b6968a..6664a295fe5fe0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -7,6 +7,7 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) JULIAHOME := $(abspath $(SRCDIR)/..) include $(JULIAHOME)/Make.inc JULIA_EXECUTABLE := $(call spawn,$(build_bindir)/julia) +export JULIA_PKGDIR := $(abspath $(SRCDIR)/deps) .PHONY: help clean cleanall html pdf linkcheck doctest check deps deploy diff --git a/doc/make.jl b/doc/make.jl index ed52e23f915382..e75f72acfa7e89 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -1,5 +1,10 @@ # Install dependencies needed to build the documentation. -ENV["JULIA_PKGDIR"] = joinpath(@__DIR__, "deps") +if ENV["JULIA_PKGDIR"] != joinpath(@__DIR__, "deps") + # We clobber package repositories here, so don't let the user hurt themselves + error("Must set JULIA_PKGDIR to $(joinpath(@__DIR__, "deps"))") +else + info(ENV["JULIA_PKGDIR"]) +end Pkg.init() cp(joinpath(@__DIR__, "REQUIRE"), Pkg.dir("REQUIRE"); remove_destination = true) Pkg.update() From a05e85fdb72196ff22d41c259bac6df307c86e76 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 11 Dec 2017 17:02:10 -0800 Subject: [PATCH 71/77] Rewrite A[ct]_(mul|ldiv|rdiv)_B[ct][!] calls in stdlib/SuiteSparse as *, /, \, mul!, ldiv!, or rdiv!. --- stdlib/SuiteSparse/src/SuiteSparse.jl | 4 +-- stdlib/SuiteSparse/src/cholmod.jl | 14 ++++---- stdlib/SuiteSparse/src/deprecated.jl | 46 +++++++++++++-------------- stdlib/SuiteSparse/src/spqr.jl | 10 +++--- stdlib/SuiteSparse/src/umfpack.jl | 16 +++++----- stdlib/SuiteSparse/test/spqr.jl | 9 +++--- stdlib/SuiteSparse/test/umfpack.jl | 19 +++++------ 7 files changed, 60 insertions(+), 58 deletions(-) diff --git a/stdlib/SuiteSparse/src/SuiteSparse.jl b/stdlib/SuiteSparse/src/SuiteSparse.jl index ef3e63b4d3b09c..6b7558310a1d0b 100644 --- a/stdlib/SuiteSparse/src/SuiteSparse.jl +++ b/stdlib/SuiteSparse/src/SuiteSparse.jl @@ -4,8 +4,8 @@ __precompile__(true) module SuiteSparse -import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B! -import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc!, ldiv!, rdiv! +import Base: \ +import Base.LinAlg: ldiv!, rdiv! ## Functions to switch to 0-based indexing to call external sparse solvers diff --git a/stdlib/SuiteSparse/src/cholmod.jl b/stdlib/SuiteSparse/src/cholmod.jl index 76bda374933fdb..c6d99bf1d7c8f1 100644 --- a/stdlib/SuiteSparse/src/cholmod.jl +++ b/stdlib/SuiteSparse/src/cholmod.jl @@ -5,7 +5,7 @@ module CHOLMOD import Base: (*), convert, copy, eltype, getindex, show, size, IndexStyle, IndexLinear, IndexCartesian, adjoint -import Base.LinAlg: (\), A_mul_Bc, A_mul_Bt, Ac_ldiv_B, Ac_mul_B, At_ldiv_B, At_mul_B, +import Base.LinAlg: (\), cholfact, cholfact!, det, diag, ishermitian, isposdef, issuccess, issymmetric, ldltfact, ldltfact!, logdet, Adjoint, Transpose @@ -1318,7 +1318,7 @@ function *(adjA::Adjoint{<:Any,<:Sparse}, B::Sparse) A = adjA.parent aa1 = transpose_(A, 2) if A === B - return A_mul_Bc(aa1, aa1) + return *(aa1, Adjoint(aa1)) end ## result of ssmult will have stype==0, contain numerical values and be sorted return ssmult(aa1, B, 0, true, true) @@ -1327,7 +1327,7 @@ end *(adjA::Adjoint{<:Any,<:Sparse}, B::Dense) = (A = adjA.parent; sdmult!(A, true, 1., 0., B, zeros(size(A, 2), size(B, 2)))) *(adjA::Adjoint{<:Any,<:Sparse}, B::VecOrMat) = - (A = adjA.parent; Ac_mul_B(A, Dense(B))) + (A = adjA.parent; *(Adjoint(A), Dense(B))) ## Factorization methods @@ -1694,7 +1694,7 @@ end \(adjL::Adjoint{<:Any,<:Factor}, B::Dense) = (L = adjL.parent; solve(CHOLMOD_A, L, B)) \(adjL::Adjoint{<:Any,<:Factor}, B::VecOrMat) = (L = adjL.parent; convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))) \(adjL::Adjoint{<:Any,<:Factor}, B::Sparse) = (L = adjL.parent; spsolve(CHOLMOD_A, L, B)) -\(adjL::Adjoint{<:Any,<:Factor}, B::SparseVecOrMat) = (L = adjL.parent; Ac_ldiv_B(L, Sparse(B))) +\(adjL::Adjoint{<:Any,<:Factor}, B::SparseVecOrMat) = (L = adjL.parent; \(Adjoint(L), Sparse(B))) const RealHermSymComplexHermF64SSL = Union{ Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}, @@ -1717,13 +1717,13 @@ function \(adjA::Adjoint{<:Any,<:RealHermSymComplexHermF64SSL}, B::StridedVecOrM A = adjA.parent F = cholfact(A) if issuccess(F) - return Ac_ldiv_B(F, B) + return \(Adjoint(F), B) else ldltfact!(F, A) if issuccess(F) - return Ac_ldiv_B(F, B) + return \(Adjoint(F), B) else - return Ac_ldiv_B(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A)), B) + return \(Adjoint(lufact(convert(SparseMatrixCSC{eltype(A), SuiteSparse_long}, A))), B) end end end diff --git a/stdlib/SuiteSparse/src/deprecated.jl b/stdlib/SuiteSparse/src/deprecated.jl index 29b7cd6913ab9c..974bb6ab5c1196 100644 --- a/stdlib/SuiteSparse/src/deprecated.jl +++ b/stdlib/SuiteSparse/src/deprecated.jl @@ -3,40 +3,40 @@ # A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/cholmod.jl, to deprecate @eval SuiteSparse.CHOLMOD begin using Base.LinAlg: Adjoint, Transpose - Ac_ldiv_B(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) = \(Adjoint(A), B) - Ac_ldiv_B(L::Factor, B::Dense) = \(Adjoint(L), B) - Ac_ldiv_B(L::Factor, B::VecOrMat) = \(Adjoint(L), B) - Ac_ldiv_B(L::Factor, B::Sparse) = \(Adjoint(L), B) - Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = \(Adjoint(L), B) - Ac_ldiv_B(L::FactorComponent, B) = \(Adjoint(L), B) - Ac_ldiv_B(L::FactorComponent, B::RowVector) = \(Adjoint(L), B) - Ac_mul_B(A::Sparse, B::Dense) = *(Adjoint(A), B) - Ac_mul_B(A::Sparse, B::VecOrMat) = *(Adjoint(A), B) - Ac_mul_B(A::Sparse, B::Sparse) = *(Adjoint(A), B) - A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where {Tv<:VRealTypes} = *(A, Adjoint(B)) + Base.Ac_ldiv_B(A::RealHermSymComplexHermF64SSL, B::StridedVecOrMat) = \(Adjoint(A), B) + Base.Ac_ldiv_B(L::Factor, B::Dense) = \(Adjoint(L), B) + Base.Ac_ldiv_B(L::Factor, B::VecOrMat) = \(Adjoint(L), B) + Base.Ac_ldiv_B(L::Factor, B::Sparse) = \(Adjoint(L), B) + Base.Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = \(Adjoint(L), B) + Base.Ac_ldiv_B(L::FactorComponent, B) = \(Adjoint(L), B) + Base.Ac_ldiv_B(L::FactorComponent, B::RowVector) = \(Adjoint(L), B) + Base.Ac_mul_B(A::Sparse, B::Dense) = *(Adjoint(A), B) + Base.Ac_mul_B(A::Sparse, B::VecOrMat) = *(Adjoint(A), B) + Base.Ac_mul_B(A::Sparse, B::Sparse) = *(Adjoint(A), B) + Base.A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where {Tv<:VRealTypes} = *(A, Adjoint(B)) end # A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/umfpack.jl, to deprecate @eval SuiteSparse.UMFPACK begin using Base.LinAlg: Adjoint, Transpose - A_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.A_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(X, lu, B) - At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(X, Transpose(lu), B) - Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = + Base.Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(X, Adjoint(lu), B) - A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = Base.LinAlg.ldiv!(X, lu, B) - At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = Base.LinAlg.ldiv!(X, Transpose(lu), B) - Ac_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = + Base.Ac_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = Base.LinAlg.ldiv!(X, Adjoint(lu), B) - A_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(lu, B) - At_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Transpose(lu), B) - Ac_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Adjoint(lu), B) - A_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(lu, B) - At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Transpose(lu), B) - Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Adjoint(lu), B) + Base.A_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(lu, B) + Base.At_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Transpose(lu), B) + Base.Ac_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Base.LinAlg.ldiv!(Adjoint(lu), B) + Base.A_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(lu, B) + Base.At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Transpose(lu), B) + Base.Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Base.LinAlg.ldiv!(Adjoint(lu), B) end # A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from src/spqr.jl, to deprecate diff --git a/stdlib/SuiteSparse/src/spqr.jl b/stdlib/SuiteSparse/src/spqr.jl index 81d196c5ebf069..c675839baef6d3 100644 --- a/stdlib/SuiteSparse/src/spqr.jl +++ b/stdlib/SuiteSparse/src/spqr.jl @@ -221,7 +221,7 @@ function Base.LinAlg.mul!(A::StridedMatrix, Q::QRSparseQ) for l in 1:size(Q.factors, 2) τl = -Q.τ[l] h = view(Q.factors, :, l) - A_mul_B!(tmp, A, h) + Base.LinAlg.mul!(tmp, A, h) LinAlg.lowrankupdate!(A, tmp, h, τl) end return A @@ -252,7 +252,7 @@ function Base.LinAlg.mul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRSparseQ}) for l in size(Q.factors, 2):-1:1 τl = -Q.τ[l] h = view(Q.factors, :, l) - A_mul_B!(tmp, A, h) + Base.LinAlg.mul!(tmp, A, h) LinAlg.lowrankupdate!(A, tmp, h, τl') end return A @@ -333,7 +333,7 @@ end # the complex rhs as a real rhs with twice the number of columns # # This definition is similar to the definition in factorization.jl except that -# here we have to use \ instead of A_ldiv_B! because of limitations in SPQR +# here we have to use \ instead of ldiv! because of limitations in SPQR ## Two helper methods _ret_size(F::QRSparse, b::AbstractVector) = (size(F, 2),) @@ -379,13 +379,13 @@ function _ldiv_basic(F::QRSparse, B::StridedVecOrMat) X0 = view(X, 1:size(B, 1), :) # Apply Q' to B - Ac_mul_B!(LinAlg.getq(F), X0) + Base.LinAlg.mul!(Adjoint(LinAlg.getq(F)), X0) # Zero out to get basic solution X[rnk + 1:end, :] = 0 # Solve R*X = B - A_ldiv_B!(UpperTriangular(view(F.R, :, Base.OneTo(rnk))), view(X0, Base.OneTo(rnk), :)) + Base.LinAlg.ldiv!(UpperTriangular(view(F.R, :, Base.OneTo(rnk))), view(X0, Base.OneTo(rnk), :)) # Apply right permutation and extract solution from X return getindex(X, ntuple(i -> i == 1 ? invperm(F.cpiv) : :, Val(ndims(B)))...) diff --git a/stdlib/SuiteSparse/src/umfpack.jl b/stdlib/SuiteSparse/src/umfpack.jl index e766f5ef32f55b..0749ddcf2f3f91 100644 --- a/stdlib/SuiteSparse/src/umfpack.jl +++ b/stdlib/SuiteSparse/src/umfpack.jl @@ -4,8 +4,8 @@ module UMFPACK export UmfpackLU -import Base: (\), Ac_ldiv_B, At_ldiv_B, findnz, getindex, show, size -import Base.LinAlg: A_ldiv_B!, Ac_ldiv_B!, At_ldiv_B!, Factorization, det, lufact, ldiv! +import Base: (\), findnz, getindex, show, size +import Base.LinAlg: Factorization, det, lufact, ldiv! using Base.LinAlg: Adjoint, Transpose using ..SparseArrays @@ -386,17 +386,17 @@ end ### Solve with Factorization ldiv!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - A_ldiv_B!(B, lu, copy(B)) + ldiv!(B, lu, copy(B)) ldiv!(translu::Transpose{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = translu.parent; At_ldiv_B!(B, lu, copy(B))) + (lu = translu.parent; ldiv!(B, Transpose(lu), copy(B))) ldiv!(adjlu::Adjoint{T,<:UmfpackLU{T}}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = - (lu = adjlu.parent; Ac_ldiv_B!(B, lu, copy(B))) + (lu = adjlu.parent; ldiv!(B, Adjoint(lu), copy(B))) ldiv!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = - A_ldiv_B!(B, lu, copy(B)) + ldiv!(B, lu, copy(B)) ldiv!(translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = - (lu = translu.parent; At_ldiv_B!(B, lu, copy(B))) + (lu = translu.parent; ldiv!(B, Transpose(lu), copy(B))) ldiv!(adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) = - (lu = adjlu.parent; Ac_ldiv_B!(B, lu, copy(B))) + (lu = adjlu.parent; ldiv!(B, Adjoint(lu), copy(B))) ldiv!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) diff --git a/stdlib/SuiteSparse/test/spqr.jl b/stdlib/SuiteSparse/test/spqr.jl index 8601f7fa4ac37a..970c91fabef5e4 100644 --- a/stdlib/SuiteSparse/test/spqr.jl +++ b/stdlib/SuiteSparse/test/spqr.jl @@ -2,6 +2,7 @@ using SuiteSparse.SPQR using SuiteSparse.CHOLMOD +using Base.LinAlg: mul!, Adjoint, Transpose @testset "Sparse QR" begin m, n = 100, 10 @@ -42,10 +43,10 @@ nn = 100 @test norm(R0[n + 1:end, :], 1) < 1e-12 offsizeA = Matrix{Float64}(I, m+1, m+1) - @test_throws DimensionMismatch A_mul_B!(Q, offsizeA) - @test_throws DimensionMismatch Ac_mul_B!(Q, offsizeA) - @test_throws DimensionMismatch A_mul_B!(offsizeA, Q) - @test_throws DimensionMismatch A_mul_Bc!(offsizeA, Q) + @test_throws DimensionMismatch mul!(Q, offsizeA) + @test_throws DimensionMismatch mul!(Adjoint(Q), offsizeA) + @test_throws DimensionMismatch mul!(offsizeA, Q) + @test_throws DimensionMismatch mul!(offsizeA, Adjoint(Q)) end @testset "element type of B: $eltyB" for eltyB in (Int, Float64, Complex{Float64}) diff --git a/stdlib/SuiteSparse/test/umfpack.jl b/stdlib/SuiteSparse/test/umfpack.jl index ebb48dffd6ea99..5f3b1a0c6c5fc7 100644 --- a/stdlib/SuiteSparse/test/umfpack.jl +++ b/stdlib/SuiteSparse/test/umfpack.jl @@ -8,6 +8,7 @@ # based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c using SuiteSparse.increment! + using Base.LinAlg: Adjoint, Transpose A0 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), increment!([0,4,0,2,1,2,1,4,3,2,1,2]), @@ -31,11 +32,11 @@ @test A*x ≈ b z = complex.(b) - x = SuiteSparse.A_ldiv_B!(lua, z) + x = SuiteSparse.ldiv!(lua, z) @test x ≈ float([1:5;]) @test z === x y = similar(z) - A_ldiv_B!(y, lua, complex.(b)) + Base.LinAlg.ldiv!(y, lua, complex.(b)) @test y ≈ x @test A*x ≈ b @@ -46,11 +47,11 @@ @test A'*x ≈ b z = complex.(b) - x = SuiteSparse.Ac_ldiv_B!(lua, z) + x = SuiteSparse.ldiv!(Adjoint(lua), z) @test x ≈ float([1:5;]) @test x === z y = similar(x) - SuiteSparse.Ac_ldiv_B!(y, lua, complex.(b)) + SuiteSparse.ldiv!(y, Adjoint(lua), complex.(b)) @test y ≈ x @test A'*x ≈ b @@ -58,10 +59,10 @@ @test x ≈ float([1:5;]) @test A.'*x ≈ b - x = SuiteSparse.At_ldiv_B!(lua,complex.(b)) + x = SuiteSparse.ldiv!(Transpose(lua), complex.(b)) @test x ≈ float([1:5;]) y = similar(x) - SuiteSparse.At_ldiv_B!(y, lua,complex.(b)) + SuiteSparse.ldiv!(y, Transpose(lua), complex.(b)) @test y ≈ x @test A.'*x ≈ b @@ -161,9 +162,9 @@ X = zeros(Complex{Float64}, N, N) B = complex.(rand(N, N), rand(N, N)) luA, lufA = lufact(A), lufact(Array(A)) - @test A_ldiv_B!(copy(X), luA, B) ≈ A_ldiv_B!(copy(X), lufA, B) - @test At_ldiv_B!(copy(X), luA, B) ≈ At_ldiv_B!(copy(X), lufA, B) - @test Ac_ldiv_B!(copy(X), luA, B) ≈ Ac_ldiv_B!(copy(X), lufA, B) + @test Base.LinAlg.ldiv!(copy(X), luA, B) ≈ Base.LinAlg.ldiv!(copy(X), lufA, B) + @test Base.LinAlg.ldiv!(copy(X), Adjoint(luA), B) ≈ Base.LinAlg.ldiv!(copy(X), Adjoint(lufA), B) + @test Base.LinAlg.ldiv!(copy(X), Transpose(luA), B) ≈ Base.LinAlg.ldiv!(copy(X), Transpose(lufA), B) end end From feec0ecf1c0189f2b47aa05680ee16257692d19e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 11 Dec 2017 22:49:55 -0500 Subject: [PATCH 72/77] Revert "Set `JULIA_PKGDIR` before Julia ever starts up when building docs (#25009)" This reverts commit 38ba1d07918af34e3f02bb67ec1ce62f2d428cdb. --- doc/Makefile | 1 - doc/make.jl | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 6664a295fe5fe0..743804d8b6968a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -7,7 +7,6 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) JULIAHOME := $(abspath $(SRCDIR)/..) include $(JULIAHOME)/Make.inc JULIA_EXECUTABLE := $(call spawn,$(build_bindir)/julia) -export JULIA_PKGDIR := $(abspath $(SRCDIR)/deps) .PHONY: help clean cleanall html pdf linkcheck doctest check deps deploy diff --git a/doc/make.jl b/doc/make.jl index e75f72acfa7e89..ed52e23f915382 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -1,10 +1,5 @@ # Install dependencies needed to build the documentation. -if ENV["JULIA_PKGDIR"] != joinpath(@__DIR__, "deps") - # We clobber package repositories here, so don't let the user hurt themselves - error("Must set JULIA_PKGDIR to $(joinpath(@__DIR__, "deps"))") -else - info(ENV["JULIA_PKGDIR"]) -end +ENV["JULIA_PKGDIR"] = joinpath(@__DIR__, "deps") Pkg.init() cp(joinpath(@__DIR__, "REQUIRE"), Pkg.dir("REQUIRE"); remove_destination = true) Pkg.update() From 66f580e1998acaf04bdd9faf80ea74c9f5d7adb9 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 9 Dec 2017 10:58:20 +0100 Subject: [PATCH 73/77] RNG: make a Sampler out of rand(::MersenneTwister, ::UnitRange) This special implementation was coupled to MersenneTwister, but there is no reason to not make it more generally available through the Sampler mechanism. --- base/random/RNGs.jl | 34 +---------------------- base/random/generation.jl | 57 +++++++++++++++++++++++++++++++++++++++ base/random/random.jl | 2 +- test/random.jl | 9 +++++++ 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/base/random/RNGs.jl b/base/random/RNGs.jl index 1fd64d06c4aed4..6a23569544ae8e 100644 --- a/base/random/RNGs.jl +++ b/base/random/RNGs.jl @@ -419,41 +419,9 @@ end #### from a range -function rand_lteq(r::AbstractRNG, randfun, u::U, mask::U) where U<:Integer - while true - x = randfun(r) & mask - x <= u && return x - end -end - -function rand(rng::MersenneTwister, - sp::SamplerTrivial{UnitRange{T}}) where T<:Union{Base.BitInteger64,Bool} - r = sp[] - isempty(r) && throw(ArgumentError("range must be non-empty")) - m = last(r) % UInt64 - first(r) % UInt64 - bw = (64 - leading_zeros(m)) % UInt # bit-width - mask = (1 % UInt64 << bw) - (1 % UInt64) - x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m, mask) : - rand_lteq(rng, rng->rand(rng, UInt64), m, mask) - (x + first(r) % UInt64) % T -end - -function rand(rng::MersenneTwister, - sp::SamplerTrivial{UnitRange{T}}) where T<:Union{Int128,UInt128} - r = sp[] - isempty(r) && throw(ArgumentError("range must be non-empty")) - m = (last(r)-first(r)) % UInt128 - bw = (128 - leading_zeros(m)) % UInt # bit-width - mask = (1 % UInt128 << bw) - (1 % UInt128) - x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m % UInt64, mask % UInt64) % UInt128 : - bw <= 104 ? rand_lteq(rng, rand_ui104_raw, m, mask) : - rand_lteq(rng, rng->rand(rng, UInt128), m, mask) - x % T + first(r) -end - for T in (Bool, BitInteger_types...) # eval because of ambiguity otherwise @eval Sampler(rng::MersenneTwister, r::UnitRange{$T}, ::Val{1}) = - SamplerTrivial(r) + SamplerRangeFast(r) end diff --git a/base/random/generation.jl b/base/random/generation.jl index 4cc18dc92bcaea..5e53848bf87f7f 100644 --- a/base/random/generation.jl +++ b/base/random/generation.jl @@ -125,6 +125,63 @@ end ### BitInteger +# there are two implemented samplers for unit ranges, which assume that Float64 (i.e. +# 52 random bits) is the native type for the RNG: +# 1) "Fast", which is the most efficient when the underlying RNG produces rand(Float64) +# "fast enough". The tradeoff is faster creation of the sampler, but more +# consumption of entropy bits +# 2) "Default" which tries to use as few entropy bits as possible, at the cost of a +# a bigger upfront price associated with the creation of the sampler + +#### Fast + +struct SamplerRangeFast{U<:BitUnsigned,T<:Union{BitInteger,Bool}} <: Sampler + a::T # first element of the range + bw::UInt # bit width + m::U # range length - 1 + mask::U # mask generated values before threshold rejection +end + +function SamplerRangeFast(r::AbstractUnitRange{T}) where T<:Union{Base.BitInteger64,Bool} + isempty(r) && throw(ArgumentError("range must be non-empty")) + m = last(r) % UInt64 - first(r) % UInt64 + bw = (64 - leading_zeros(m)) % UInt # bit-width + mask = (1 % UInt64 << bw) - (1 % UInt64) + SamplerRangeFast{UInt64,T}(first(r), bw, m, mask) +end + +function SamplerRangeFast(r::AbstractUnitRange{T}) where T<:Union{Int128,UInt128} + isempty(r) && throw(ArgumentError("range must be non-empty")) + m = (last(r)-first(r)) % UInt128 + bw = (128 - leading_zeros(m)) % UInt # bit-width + mask = (1 % UInt128 << bw) - (1 % UInt128) + SamplerRangeFast{UInt128,T}(first(r), bw, m, mask) +end + +function rand_lteq(r::AbstractRNG, randfun, u::U, mask::U) where U<:Integer + while true + x = randfun(r) & mask + x <= u && return x + end +end + +function rand(rng::AbstractRNG, sp::SamplerRangeFast{UInt64,T}) where T + a, bw, m, mask = sp.a, sp.bw, sp.m, sp.mask + x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m, mask) : + rand_lteq(rng, rng->rand(rng, UInt64), m, mask) + (x + a % UInt64) % T +end + +function rand(rng::AbstractRNG, sp::SamplerRangeFast{UInt128,T}) where T + a, bw, m, mask = sp.a, sp.bw, sp.m, sp.mask + x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m % UInt64, mask % UInt64) % UInt128 : + bw <= 104 ? rand_lteq(rng, rand_ui104_raw, m, mask) : + rand_lteq(rng, rng->rand(rng, UInt128), m, mask) + x % T + a +end + +#### Default + # remainder function according to Knuth, where rem_knuth(a, 0) = a rem_knuth(a::UInt, b::UInt) = a % (b + (b == 0)) + a * (b == 0) rem_knuth(a::T, b::T) where {T<:Unsigned} = b != 0 ? a % b : a diff --git a/base/random/random.jl b/base/random/random.jl index e624e9c0497007..f2c7bc40941397 100644 --- a/base/random/random.jl +++ b/base/random/random.jl @@ -4,7 +4,7 @@ module Random using Base.dSFMT using Base.GMP: Limb, MPZ -using Base: BitInteger, BitInteger_types +using Base: BitInteger, BitInteger_types, BitUnsigned import Base: copymutable, copy, copy!, ==, hash export srand, diff --git a/test/random.jl b/test/random.jl index 831ae034619603..8105228e12e4a5 100644 --- a/test/random.jl +++ b/test/random.jl @@ -3,6 +3,8 @@ isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) using Main.TestHelpers.OAs +using Base.Random: Sampler, SamplerRangeFast, SamplerRangeInt + # Issue #6573 guardsrand(0) do rand() @@ -647,3 +649,10 @@ struct RandomStruct23964 end @test_throws ArgumentError rand(nothing) @test_throws ArgumentError rand(RandomStruct23964()) end + +@testset "rand(::$RNG, ::UnitRange{$T}" for RNG ∈ (MersenneTwister(), RandomDevice()), + T ∈ (Int32, UInt32, Int64, Int128, UInt128) + RNG isa MersenneTwister && srand(RNG, rand(UInt128)) # for reproducibility + r = T(1):T(108) + @test rand(RNG, SamplerRangeFast(r)) ∈ r +end From 3c65a84e0b2ee91ead5e8563f7edf11463027fc0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 9 Dec 2017 16:27:08 +0100 Subject: [PATCH 74/77] RNG: delete rand_ui* functions in favor of multi-dispatch * we add a first RNG trait, rng_native_52(), which selects a native primitive, between UInt64 and Float64. This is still experimental, but it already allows a little bit of code simplification; * we also rename the rand_generic functions to rand; the "Sampler" framework plus traits should make them un-necessary --- base/random/RNGs.jl | 54 +++++++++++++++++++-------------------- base/random/generation.jl | 49 ++++++++++++++++++++++------------- base/random/misc.jl | 2 +- base/random/normal.jl | 4 +-- base/random/random.jl | 37 +++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 48 deletions(-) diff --git a/base/random/RNGs.jl b/base/random/RNGs.jl index 6a23569544ae8e..5144ecd2dc57ba 100644 --- a/base/random/RNGs.jl +++ b/base/random/RNGs.jl @@ -42,6 +42,9 @@ for T in (Bool, BitInteger_types...) end end +# RandomDevice produces natively UInt64 +rng_native_52(::RandomDevice) = UInt64 + """ RandomDevice() @@ -54,10 +57,6 @@ RandomDevice RandomDevice(::Void) = RandomDevice() srand(rng::RandomDevice) = rng -### generation of floats - -rand(r::RandomDevice, sp::SamplerTrivial{<:FloatInterval}) = rand_generic(r, sp[]) - ## MersenneTwister @@ -209,58 +208,59 @@ const GLOBAL_RNG = MersenneTwister(0) ### generation +# MersenneTwister produces natively Float64 +rng_native_52(::MersenneTwister) = Float64 + #### helper functions # precondition: !mt_empty(r) rand_inbounds(r::MersenneTwister, ::Close1Open2_64) = mt_pop!(r) -rand_inbounds(r::MersenneTwister, ::CloseOpen_64) = +rand_inbounds(r::MersenneTwister, ::CloseOpen_64=CloseOpen()) = rand_inbounds(r, Close1Open2()) - 1.0 -rand_inbounds(r::MersenneTwister) = rand_inbounds(r, CloseOpen()) -rand_ui52_raw_inbounds(r::MersenneTwister) = - reinterpret(UInt64, rand_inbounds(r, Close1Open2())) -rand_ui52_raw(r::MersenneTwister) = (reserve_1(r); rand_ui52_raw_inbounds(r)) +rand_inbounds(r::MersenneTwister, ::UInt52Raw{T}) where {T<:BitInteger} = + reinterpret(UInt64, rand_inbounds(r, Close1Open2())) % T -function rand_ui2x52_raw(r::MersenneTwister) - reserve(r, 2) - rand_ui52_raw_inbounds(r) % UInt128 << 64 | rand_ui52_raw_inbounds(r) +function rand(r::MersenneTwister, x::SamplerTrivial{UInt52Raw{UInt64}}) + reserve_1(r) + rand_inbounds(r, x[]) end -function rand_ui104_raw(r::MersenneTwister) +function rand(r::MersenneTwister, ::SamplerTrivial{UInt2x52Raw{UInt128}}) reserve(r, 2) - rand_ui52_raw_inbounds(r) % UInt128 << 52 ⊻ rand_ui52_raw_inbounds(r) + rand_inbounds(r, UInt52Raw(UInt128)) << 64 | rand_inbounds(r, UInt52Raw(UInt128)) end -rand_ui10_raw(r::MersenneTwister) = rand_ui52_raw(r) -rand_ui23_raw(r::MersenneTwister) = rand_ui52_raw(r) +function rand(r::MersenneTwister, ::SamplerTrivial{UInt104Raw{UInt128}}) + reserve(r, 2) + rand_inbounds(r, UInt52Raw(UInt128)) << 52 ⊻ rand_inbounds(r, UInt52Raw(UInt128)) +end #### floats -rand(r::MersenneTwister, sp::SamplerTrivial{<:FloatInterval_64}) = +rand(r::MersenneTwister, sp::SamplerTrivial{Close1Open2_64}) = (reserve_1(r); rand_inbounds(r, sp[])) -rand(r::MersenneTwister, sp::SamplerTrivial{<:FloatInterval}) = rand_generic(r, sp[]) - #### integers rand(r::MersenneTwister, T::SamplerUnion(Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32})) = - rand_ui52_raw(r) % T[] + rand(r, UInt52Raw()) % T[] function rand(r::MersenneTwister, ::SamplerType{UInt64}) reserve(r, 2) - rand_ui52_raw_inbounds(r) << 32 ⊻ rand_ui52_raw_inbounds(r) + rand_inbounds(r, UInt52Raw()) << 32 ⊻ rand_inbounds(r, UInt52Raw()) end function rand(r::MersenneTwister, ::SamplerType{UInt128}) reserve(r, 3) - xor(rand_ui52_raw_inbounds(r) % UInt128 << 96, - rand_ui52_raw_inbounds(r) % UInt128 << 48, - rand_ui52_raw_inbounds(r)) + xor(rand_inbounds(r, UInt52Raw(UInt128)) << 96, + rand_inbounds(r, UInt52Raw(UInt128)) << 48, + rand_inbounds(r, UInt52Raw(UInt128))) end -rand(r::MersenneTwister, ::SamplerType{Int64}) = reinterpret(Int64, rand(r, UInt64)) -rand(r::MersenneTwister, ::SamplerType{Int128}) = reinterpret(Int128, rand(r, UInt128)) +rand(r::MersenneTwister, ::SamplerType{Int64}) = rand(r, UInt64) % Int64 +rand(r::MersenneTwister, ::SamplerType{Int128}) = rand(r, UInt128) % Int128 #### arrays of floats @@ -395,7 +395,7 @@ function rand!(r::MersenneTwister, A::Array{UInt128}, ::SamplerType{UInt128}) end end if n > 0 - u = rand_ui2x52_raw(r) + u = rand(r, UInt2x52Raw()) for i = 1:n @inbounds A[i] ⊻= u << (12*i) end diff --git a/base/random/generation.jl b/base/random/generation.jl index 5e53848bf87f7f..4b47af235167da 100644 --- a/base/random/generation.jl +++ b/base/random/generation.jl @@ -23,17 +23,17 @@ Sampler(rng::AbstractRNG, ::Type{T}, n::Repetition) where {T<:AbstractFloat} = # generic random generation function which can be used by RNG implementors # it is not defined as a fallback rand method as this could create ambiguities -rand_generic(r::AbstractRNG, ::CloseOpen{Float16}) = +rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen{Float16}}) = Float16(reinterpret(Float32, - (rand_ui10_raw(r) % UInt32 << 13) & 0x007fe000 | 0x3f800000) - 1) + (rand(r, UInt10(UInt32)) << 13) | 0x3f800000) - 1) -rand_generic(r::AbstractRNG, ::CloseOpen{Float32}) = - reinterpret(Float32, rand_ui23_raw(r) % UInt32 & 0x007fffff | 0x3f800000) - 1 +rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen{Float32}}) = + reinterpret(Float32, rand(r, UInt23()) | 0x3f800000) - 1 -rand_generic(r::AbstractRNG, ::Close1Open2_64) = - reinterpret(Float64, 0x3ff0000000000000 | rand(r, UInt64) & 0x000fffffffffffff) +rand(r::AbstractRNG, ::SamplerTrivial{Close1Open2_64}) = + reinterpret(Float64, 0x3ff0000000000000 | rand(r, UInt52())) -rand_generic(r::AbstractRNG, ::CloseOpen_64) = rand(r, Close1Open2()) - 1.0 +rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen_64}) = rand(r, Close1Open2()) - 1.0 #### BigFloat @@ -101,11 +101,21 @@ rand(rng::AbstractRNG, sp::SamplerBigFloat{T}) where {T<:FloatInterval{BigFloat} ### random integers -rand_ui10_raw(r::AbstractRNG) = rand(r, UInt16) -rand_ui23_raw(r::AbstractRNG) = rand(r, UInt32) +rand(r::AbstractRNG, ::SamplerTrivial{UInt10Raw{UInt16}}) = rand(r, UInt16) +rand(r::AbstractRNG, ::SamplerTrivial{UInt23Raw{UInt32}}) = rand(r, UInt32) -rand_ui52_raw(r::AbstractRNG) = reinterpret(UInt64, rand(r, Close1Open2())) -rand_ui52(r::AbstractRNG) = rand_ui52_raw(r) & 0x000fffffffffffff +rand(r::AbstractRNG, ::SamplerTrivial{UInt52Raw{UInt64}}) = + _rand52(r, rng_native_52(r)) + +_rand52(r::AbstractRNG, ::Type{Float64}) = reinterpret(UInt64, rand(r, Close1Open2())) +_rand52(r::AbstractRNG, ::Type{UInt64}) = rand(r, UInt64) + +rand(r::AbstractRNG, ::SamplerTrivial{UInt10{UInt16}}) = rand(r, UInt10Raw()) & 0x03ff +rand(r::AbstractRNG, ::SamplerTrivial{UInt23{UInt32}}) = rand(r, UInt23Raw()) & 0x007fffff +rand(r::AbstractRNG, ::SamplerTrivial{UInt52{UInt64}}) = rand(r, UInt52Raw()) & 0x000fffffffffffff + +rand(r::AbstractRNG, sp::SamplerTrivial{<:UniformBits{T}}) where {T} = + rand(r, uint_default(sp[])) % T ### random complex numbers @@ -158,25 +168,28 @@ function SamplerRangeFast(r::AbstractUnitRange{T}) where T<:Union{Int128,UInt128 SamplerRangeFast{UInt128,T}(first(r), bw, m, mask) end -function rand_lteq(r::AbstractRNG, randfun, u::U, mask::U) where U<:Integer +function rand_lteq(r::AbstractRNG, S, u::U, mask::U) where U<:Integer while true - x = randfun(r) & mask + x = rand(r, S) & mask x <= u && return x end end +# helper function, to turn types to values, should be removed once we can do rand(Uniform(UInt)) +rand(rng::AbstractRNG, ::Val{T}) where {T} = rand(rng, T) + function rand(rng::AbstractRNG, sp::SamplerRangeFast{UInt64,T}) where T a, bw, m, mask = sp.a, sp.bw, sp.m, sp.mask - x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m, mask) : - rand_lteq(rng, rng->rand(rng, UInt64), m, mask) + x = bw <= 52 ? rand_lteq(rng, UInt52Raw(), m, mask) : + rand_lteq(rng, Val(UInt64), m, mask) (x + a % UInt64) % T end function rand(rng::AbstractRNG, sp::SamplerRangeFast{UInt128,T}) where T a, bw, m, mask = sp.a, sp.bw, sp.m, sp.mask - x = bw <= 52 ? rand_lteq(rng, rand_ui52_raw, m % UInt64, mask % UInt64) % UInt128 : - bw <= 104 ? rand_lteq(rng, rand_ui104_raw, m, mask) : - rand_lteq(rng, rng->rand(rng, UInt128), m, mask) + x = bw <= 52 ? rand_lteq(rng, UInt52Raw(), m % UInt64, mask % UInt64) % UInt128 : + bw <= 104 ? rand_lteq(rng, UInt104Raw(), m, mask) : + rand_lteq(rng, Val(UInt128), m, mask) x % T + a end diff --git a/base/random/misc.jl b/base/random/misc.jl index 0c0fb71da2b8ec..b4759c620827cc 100644 --- a/base/random/misc.jl +++ b/base/random/misc.jl @@ -147,7 +147,7 @@ randsubseq(A::AbstractArray, p::Real) = randsubseq(GLOBAL_RNG, A, p) @inline function rand_lt(r::AbstractRNG, n::Int, mask::Int=nextpow2(n)-1) # this duplicates the functionality of rand(1:n), to optimize this special case while true - x = (rand_ui52_raw(r) % Int) & mask + x = rand(r, UInt52Raw(Int)) & mask x < n && return x end end diff --git a/base/random/normal.jl b/base/random/normal.jl index 40ac228fe46c3b..e09ca1ec8952d1 100644 --- a/base/random/normal.jl +++ b/base/random/normal.jl @@ -35,7 +35,7 @@ julia> randn(rng, Complex64, (2, 3)) """ @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin - r = rand_ui52(rng) + r = rand(rng, UInt52()) rabs = Int64(r>>1) # One bit for the sign idx = rabs & 0xFF x = ifelse(r % Bool, -rabs, rabs)*wi[idx+1] @@ -95,7 +95,7 @@ julia> randexp(rng, 3, 3) """ function randexp(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin - ri = rand_ui52(rng) + ri = rand(rng, UInt52()) idx = ri & 0xFF x = ri*we[idx+1] ri < ke[idx+1] && return x # 98.9% of the time we return here 1st try diff --git a/base/random/random.jl b/base/random/random.jl index f2c7bc40941397..f15397a42bf17f 100644 --- a/base/random/random.jl +++ b/base/random/random.jl @@ -25,6 +25,43 @@ export srand, abstract type AbstractRNG end +### integers + +# we define types which encode the generation of a specific number of bits +# the "raw" version means that the unused bits are not zeroed + +abstract type UniformBits{T<:BitInteger} end + +struct UInt10{T} <: UniformBits{T} end +struct UInt10Raw{T} <: UniformBits{T} end + +struct UInt23{T} <: UniformBits{T} end +struct UInt23Raw{T} <: UniformBits{T} end + +struct UInt52{T} <: UniformBits{T} end +struct UInt52Raw{T} <: UniformBits{T} end + +struct UInt104{T} <: UniformBits{T} end +struct UInt104Raw{T} <: UniformBits{T} end + +struct UInt2x52{T} <: UniformBits{T} end +struct UInt2x52Raw{T} <: UniformBits{T} end + +uint_sup(::Type{<:Union{UInt10,UInt10Raw}}) = UInt16 +uint_sup(::Type{<:Union{UInt23,UInt23Raw}}) = UInt32 +uint_sup(::Type{<:Union{UInt52,UInt52Raw}}) = UInt64 +uint_sup(::Type{<:Union{UInt104,UInt104Raw}}) = UInt128 +uint_sup(::Type{<:Union{UInt2x52,UInt2x52Raw}}) = UInt128 + +for UI = (:UInt10, :UInt10Raw, :UInt23, :UInt23Raw, :UInt52, :UInt52Raw, + :UInt104, :UInt104Raw, :UInt2x52, :UInt2x52Raw) + @eval begin + $UI(::Type{T}=uint_sup($UI)) where {T} = $UI{T}() + # useful for defining rand generically: + uint_default(::$UI) = $UI{uint_sup($UI)}() + end +end + ### floats abstract type FloatInterval{T<:AbstractFloat} end From 10606c20fca31038b313c1e15872ef0a9a386465 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 12 Dec 2017 12:06:36 -0800 Subject: [PATCH 75/77] Fix formatting and even more doctests for delimited files (#25017) --- stdlib/DelimitedFiles/src/DelimitedFiles.jl | 114 +++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/stdlib/DelimitedFiles/src/DelimitedFiles.jl b/stdlib/DelimitedFiles/src/DelimitedFiles.jl index bd13dc29c4b057..e7535b93feb3c8 100644 --- a/stdlib/DelimitedFiles/src/DelimitedFiles.jl +++ b/stdlib/DelimitedFiles/src/DelimitedFiles.jl @@ -30,6 +30,35 @@ const offs_chunk_size = 5000 The columns are assumed to be separated by one or more whitespaces. The end of line delimiter is taken as `\\n`. + +# Examples +```jldoctest +julia> using DelimitedFiles + +julia> x = [1; 2; 3; 4]; + +julia> y = [5; 6; 7; 8]; + +julia> open("delim_file.txt", "w") do io + writedlm(io, [x y]) + end; + +julia> readdlm("delim_file.txt", Int64) +4×2 Array{Int64,2}: + 1 5 + 2 6 + 3 7 + 4 8 + +julia> readdlm("delim_file.txt", Float64) +4×2 Array{Float64,2}: + 1.0 5.0 + 2.0 6.0 + 3.0 7.0 + 4.0 8.0 + +julia> rm("delim_file.txt") +``` """ readdlm(input, T::Type; opts...) = readdlm(input, invalid_dlm(Char), T, '\n'; opts...) @@ -37,6 +66,28 @@ readdlm(input, T::Type; opts...) = readdlm(input, invalid_dlm(Char), T, '\n'; op readdlm(source, delim::Char, T::Type; options...) The end of line delimiter is taken as `\\n`. + +# Examples +```jldoctest +julia> using DelimitedFiles + +julia> x = [1; 2; 3; 4]; + +julia> y = [1.1; 2.2; 3.3; 4.4]; + +julia> open("delim_file.txt", "w") do io + writedlm(io, [x y], ',') + end; + +julia> readdlm("delim_file.txt", ',', Float64) +4×2 Array{Float64,2}: + 1.0 1.1 + 2.0 2.2 + 3.0 3.3 + 4.0 4.4 + +julia> rm("delim_file.txt") +``` """ readdlm(input, dlm::Char, T::Type; opts...) = readdlm(input, dlm, T, '\n'; opts...) @@ -47,6 +98,28 @@ The columns are assumed to be separated by one or more whitespaces. The end of l delimiter is taken as `\\n`. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned. + +# Examples +```jldoctest +julia> using DelimitedFiles + +julia> x = [1; 2; 3; 4]; + +julia> y = ["a"; "b"; "c"; "d"]; + +julia> open("delim_file.txt", "w") do io + writedlm(io, [x y]) + end; + +julia> readdlm("delim_file.txt") +4×2 Array{Any,2}: + 1 "a" + 2 "b" + 3 "c" + 4 "d" + +julia> rm("delim_file.txt") +``` """ readdlm(input; opts...) = readdlm(input, invalid_dlm(Char), '\n'; opts...) @@ -56,6 +129,43 @@ readdlm(input; opts...) = readdlm(input, invalid_dlm(Char), '\n'; opts...) The end of line delimiter is taken as `\\n`. If all data is numeric, the result will be a numeric array. If some elements cannot be parsed as numbers, a heterogeneous array of numbers and strings is returned. + +# Examples +```jldoctest +julia> using DelimitedFiles + +julia> x = [1; 2; 3; 4]; + +julia> y = [1.1; 2.2; 3.3; 4.4]; + +julia> open("delim_file.txt", "w") do io + writedlm(io, [x y], ',') + end; + +julia> readdlm("delim_file.txt", ',') +4×2 Array{Float64,2}: + 1.0 1.1 + 2.0 2.2 + 3.0 3.3 + 4.0 4.4 + +julia> rm("delim_file.txt") + +julia> z = ["a"; "b"; "c"; "d"]; + +julia> open("delim_file.txt", "w") do io + writedlm(io, [x z], ',') + end; + +julia> readdlm("delim_file.txt", ',') +4×2 Array{Any,2}: + 1 "a" + 2 "b" + 3 "c" + 4 "d" + +julia> rm("delim_file.txt") +``` """ readdlm(input, dlm::Char; opts...) = readdlm(input, dlm, '\n'; opts...) @@ -110,7 +220,7 @@ julia> open("delim_file.txt", "w") do io writedlm(io, [x y]) end -julia> readdlm("delim_file.txt", '\t', Int, '\n') +julia> readdlm("delim_file.txt", '\\t', Int, '\\n') 4×2 Array{Int64,2}: 1 5 2 6 @@ -707,7 +817,7 @@ julia> open("delim_file.txt", "w") do io writedlm(io, [x y]) end -julia> readdlm("delim_file.txt", '\t', Int, '\n') +julia> readdlm("delim_file.txt", '\\t', Int, '\\n') 4×2 Array{Int64,2}: 1 5 2 6 From 884c9565c30858045fdfc3044a87daec4637c8f1 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 12 Dec 2017 12:12:52 -0800 Subject: [PATCH 76/77] Doctests for eachline and readchomp (#25007) --- base/io.jl | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/base/io.jl b/base/io.jl index 1acaf0373067d8..cf5aa1e2260d19 100644 --- a/base/io.jl +++ b/base/io.jl @@ -734,6 +734,18 @@ end Read the entirety of `x` as a string and remove a single trailing newline. Equivalent to `chomp!(read(x, String))`. + +# Examples +```jldoctest +julia> open("my_file.txt", "w") do io + write(io, "JuliaLang is a GitHub organization.\\nIt has many members.\\n"); + end; + +julia> readchomp("my_file.txt") +"JuliaLang is a GitHub organization.\\nIt has many members." + +julia> rm("my_file.txt"); +``` """ readchomp(x) = chomp!(read(x, String)) @@ -792,15 +804,29 @@ mutable struct EachLine end """ - eachline(stream::IO=STDIN; chomp::Bool=true) + eachline(io::IO=STDIN; chomp::Bool=true) eachline(filename::AbstractString; chomp::Bool=true) Create an iterable `EachLine` object that will yield each line from an I/O stream -or a file. Iteration calls `readline` on the stream argument repeatedly with +or a file. Iteration calls [`readline`](@ref) on the stream argument repeatedly with `chomp` passed through, determining whether trailing end-of-line characters are removed. When called with a file name, the file is opened once at the beginning of iteration and closed at the end. If iteration is interrupted, the file will be closed when the `EachLine` object is garbage collected. + +# Examples +```jldoctest +julia> open("my_file.txt", "w") do io + write(io, "JuliaLang is a GitHub organization.\\n It has many members.\\n"); + end; + +julia> for line in eachline("my_file.txt") + print(line) + end +JuliaLang is a GitHub organization. It has many members. + +julia> rm("my_file.txt"); +``` """ eachline(stream::IO=STDIN; chomp::Bool=true) = EachLine(stream, chomp=chomp)::EachLine From a8054ed0cba6c23c58417bec0f5440b1c5bf1a35 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 12 Dec 2017 16:50:50 -0500 Subject: [PATCH 77/77] turn on libatomic for FreeBSD (#23901) --- src/jitlayers.cpp | 6 +++--- test/threads.jl | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 979e6e5872044c..1262d6c5dc854c 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -335,12 +335,12 @@ void NotifyDebugger(jit_code_entry *JITCodeEntry) } // ------------------------ END OF TEMPORARY COPY FROM LLVM ----------------- -#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) +#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) || defined(_OS_FREEBSD_) // Resolve non-lock free atomic functions in the libatomic library. // This is the library that provides support for c11/c++11 atomic operations. static uint64_t resolve_atomic(const char *name) { -#if defined(_OS_LINUX_) +#if defined(_OS_LINUX_) || defined(_OS_FREEBSD_) static const char *const libatomic = "libatomic"; #elif defined(_OS_WINDOWS_) static const char *const libatomic = "libatomic-1"; @@ -579,7 +579,7 @@ void JuliaOJIT::addModule(std::unique_ptr M) // Step 2: Search the program symbols if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); -#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) +#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) || defined(_OS_FREEBSD_) if (uint64_t addr = resolve_atomic(Name.c_str())) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); #endif diff --git a/test/threads.jl b/test/threads.jl index 51755f071dfa6f..f89e18a1ea6c58 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -451,3 +451,30 @@ function test_nested_loops() end end test_nested_loops() + +@testset "libatomic" begin + prog = """ + using Base.Threads + function unaligned_setindex!(x::Atomic{UInt128}, v::UInt128) + Base.llvmcall(\"\"\" + %ptr = inttoptr i$(Sys.WORD_SIZE) %0 to i128* + store atomic i128 %1, i128* %ptr release, align 8 + ret void + \"\"\", Void, Tuple{Ptr{UInt128}, UInt128}, unsafe_convert(Ptr{UInt128}, x), v) + end + code_native(STDOUT, unaligned_setindex!, Tuple{Atomic{UInt128}, UInt128}) + """ + + mktempdir() do dir + file = joinpath(dir, "test23901.jl") + write(file, prog) + run(pipeline(ignorestatus(`$(Base.julia_cmd()) --startup-file=no $file`), + stdout=joinpath(dir, "out.txt"), + stderr=joinpath(dir, "err.txt"), + append=false)) + out = readchomp(joinpath(dir, "out.txt")) + err = readchomp(joinpath(dir, "err.txt")) + @test contains(out, "libat_store") || contains(out, "atomic_store") + @test !contains(err, "__atomic_store") + end +end