From 4516d15ff2fda69d0bd979871d58b2e1ae84c8b7 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Mon, 9 May 2016 21:45:50 -0400 Subject: [PATCH 1/2] Throw error for LowerTriangular(::UpperTriagular) and vice versa to avoid infinite compilation recursion. --- base/linalg/triangular.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 6a58d538c6257..19fea780ada00 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -39,6 +39,9 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular, end end +LowerTriangular(U::UpperTriangular) = throw(ArgumentError("this shouldn't happen. Please submit a bug report")) +UpperTriangular(U::LowerTriangular) = throw(ArgumentError("this shouldn't happen. Please submit a bug report")) + imag(A::UpperTriangular) = UpperTriangular(imag(A.data)) imag(A::LowerTriangular) = LowerTriangular(imag(A.data)) imag(A::UnitLowerTriangular) = LowerTriangular(tril!(imag(A.data),-1)) From ec31d50a0cbc2a78cfec7b37e0328e19e96d15cb Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Mon, 9 May 2016 22:02:55 -0400 Subject: [PATCH 2/2] Use similar+copy! instead of copy_oftype for AbstractMatrix arguments to make sure that copy is mutable. Fixes #15401 --- base/linalg/cholesky.jl | 4 +++- base/linalg/factorization.jl | 24 +++++++++++------------- base/linalg/lu.jl | 12 +++++++++--- base/linalg/qr.jl | 16 +++++++++++++--- base/linalg/triangular.jl | 4 ++-- test/linalg/diagonal.jl | 3 +++ test/linalg/triangular.jl | 4 ++++ 7 files changed, 45 insertions(+), 22 deletions(-) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 847b91e4a7f7f..5218d38359d4e 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -86,7 +86,9 @@ and return the UpperTriangular matrix `U` such that `A = U'U`. """ function chol{T}(A::AbstractMatrix{T}) S = promote_type(typeof(chol(one(T))), Float32) - chol!(copy_oftype(A, S)) + AA = similar(A, S, size(A)) + copy!(AA, A) + chol!(AA) end function chol!(x::Number, uplo) rx = real(x) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index fd7e4cd63d5d5..a25e780899edc 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -34,17 +34,15 @@ function (\){T<:BlasReal}(F::Factorization{T}, B::AbstractMatrix{Complex{T}}) return reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)), (size(F,2), size(B,2))) end -function (\){TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N}) - TFB = typeof(one(TF)/one(TB)) - A_ldiv_B!(convert(Factorization{TFB}, F), copy_oftype(B, TFB)) -end - -function Ac_ldiv_B{TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N}) - TFB = typeof(one(TF)/one(TB)) - Ac_ldiv_B!(convert(Factorization{TFB}, F), copy_oftype(B, TFB)) -end - -function At_ldiv_B{TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N}) - TFB = typeof(one(TF)/one(TB)) - At_ldiv_B!(convert(Factorization{TFB}, F), copy_oftype(B, TFB)) +for (f1, f2) in ((:\, :A_ldiv_B!), + (:Ac_ldiv_B, :Ac_ldiv_B!), + (:At_ldiv_B, :At_ldiv_B!)) + @eval begin + function $f1{TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArray{TB,N}) + TFB = typeof(one(TF)/one(TB)) + BB = similar(B, TFB, size(B)) + copy!(BB, B) + $f2(convert(Factorization{TFB}, F), BB) + end + end end diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index cc20119186d77..f63fab0601200 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -109,16 +109,22 @@ The relationship between `F` and `A` is """ function lufact{T}(A::AbstractMatrix{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}}) S = typeof(zero(T)/one(T)) - lufact!(copy_oftype(A, S), pivot) + AA = similar(A, S, size(A)) + copy!(AA, A) + lufact!(AA, pivot) end # We can't assume an ordered field so we first try without pivoting function lufact{T}(A::AbstractMatrix{T}) S = typeof(zero(T)/one(T)) - F = lufact!(copy_oftype(A, S), Val{false}) + AA = similar(A, S, size(A)) + copy!(AA, A) + F = lufact!(AA, Val{false}) if F.info == 0 return F else - return lufact!(copy_oftype(A, S), Val{true}) + AA = similar(A, S, size(A)) + copy!(AA, A) + return lufact!(AA, Val{true}) end end diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index c3afc2f24cab8..1522f4a1b2561 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -93,8 +93,16 @@ qrfact!{T<:BlasFloat}(A::StridedMatrix{T}) = qrfact!(A, Val{false}) qrfact!(A::StridedMatrix, ::Type{Val{false}}) = qrfactUnblocked!(A) qrfact!(A::StridedMatrix, ::Type{Val{true}}) = qrfactPivotedUnblocked!(A) qrfact!(A::StridedMatrix) = qrfact!(A, Val{false}) -qrfact{T}(A::AbstractMatrix{T}, arg) = qrfact!(copy_oftype(A, typeof(zero(T)/norm(one(T)))), arg) -qrfact{T}(A::AbstractMatrix{T}) = qrfact!(copy_oftype(A, typeof(zero(T)/norm(one(T))))) +function qrfact{T}(A::AbstractMatrix{T}, arg) + AA = similar(A, typeof(zero(T)/norm(one(T))), size(A)) + copy!(AA, A) + return qrfact!(AA, arg) +end +function qrfact{T}(A::AbstractMatrix{T}) + AA = similar(A, typeof(zero(T)/norm(one(T))), size(A)) + copy!(AA, A) + return qrfact!(AA) +end qrfact(x::Number) = qrfact(fill(x,1,1)) qr(A::Union{Number, AbstractMatrix}, pivot::Union{Type{Val{false}}, Type{Val{true}}}=Val{false}; thin::Bool=true) = @@ -407,7 +415,9 @@ function A_mul_Bc{TA,TB}(A::AbstractMatrix{TA}, B::Union{QRCompactWYQ{TB},QRPack TAB = promote_type(TA,TB) BB = convert(AbstractMatrix{TAB}, B) if size(A,2) == size(B.factors, 1) - return A_mul_Bc!(copy_oftype(A, TAB), BB) + AA = similar(A, TAB, size(A)) + copy!(AA, A) + return A_mul_Bc!(AA, 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) else diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 19fea780ada00..5ac78c2362521 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -39,8 +39,8 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular, end end -LowerTriangular(U::UpperTriangular) = throw(ArgumentError("this shouldn't happen. Please submit a bug report")) -UpperTriangular(U::LowerTriangular) = throw(ArgumentError("this shouldn't happen. Please submit a bug report")) +LowerTriangular(U::UpperTriangular) = throw(ArgumentError("cannot create a LowerTriangular matrix from an UpperTriangular input")) +UpperTriangular(U::LowerTriangular) = throw(ArgumentError("cannot create an UpperTriangular matrix from a LowerTriangular input")) imag(A::UpperTriangular) = UpperTriangular(imag(A.data)) imag(A::LowerTriangular) = LowerTriangular(imag(A.data)) diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index faa22e796b2de..2e6a0883785b8 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -243,3 +243,6 @@ end for t in (Float32, Float64, Int, Complex{Float64}, Rational{Int}) @test Diagonal(Matrix{t}[ones(t, 2, 2), ones(t, 3, 3)])[2,1] == zeros(t, 3, 2) end + +# Issue 15401 +@test eye(5) \ Diagonal(ones(5)) == eye(5) diff --git a/test/linalg/triangular.jl b/test/linalg/triangular.jl index bff1e05d4b050..4bfbb31bdf259 100644 --- a/test/linalg/triangular.jl +++ b/test/linalg/triangular.jl @@ -485,3 +485,7 @@ let @test_throws DimensionMismatch A_rdiv_Bt!(A, UnitLowerTriangular(B)) @test_throws DimensionMismatch A_rdiv_Bt!(A, UnitUpperTriangular(B)) end + +# Test that UpperTriangular(LowerTriangular) throws. See #16201 +@test_throws ArgumentError LowerTriangular(UpperTriangular(randn(3,3))) +@test_throws ArgumentError UpperTriangular(LowerTriangular(randn(3,3)))