Skip to content

Conversation

@mcognetta
Copy link
Contributor

SymTridiagonal + Bidiagonal matrices fail because the output is forced to Symtridiagonal. Now it correctly promotes to Tridiagonal matrices. This does not consider the case where the Bidiagonal matrix is diagonal.

Before:

julia> S = SymTridiagonal(rand(10), rand(9))
julia> B = Bidiagonal(rand(10), rand(9), :U)
julia> S+B # same with B+S, S-B, B-S
ERROR: ArgumentError: matrix cannot be represented as SymTridiagonal

Now:

julia> S = SymTridiagonal(rand(10), rand(9))
julia> B = Bidiagonal(rand(10), rand(9), :U)
julia> S+B # returns10×10 Tridiagonal{Float64,Array{Float64,1}}

@mbauman
Copy link
Member

mbauman commented Aug 24, 2018

Thanks so much for tackling this! Here's an alternate patch that passes both the existing tests and the new ones you added:

diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl
index 70014837e0..984c9271df 100644
--- a/stdlib/LinearAlgebra/src/special.jl
+++ b/stdlib/LinearAlgebra/src/special.jl
@@ -79,54 +79,6 @@ macro commutative(myexpr)
     esc(Expr(:block, myexpr, reversed_call))
 end

-for op in (:+, :-)
-    SpecialMatrices = [:Diagonal, :Bidiagonal, :Tridiagonal, :Matrix]
-    for (idx, matrixtype1) in enumerate(SpecialMatrices) # matrixtype1 is the sparser matrix type
-        for matrixtype2 in SpecialMatrices[idx+1:end] # matrixtype2 is the denser matrix type
-            @eval begin # TODO quite a few of these conversions are NOT defined
-                ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B)
-                ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B))
-            end
-        end
-    end
-
-    for  matrixtype1 in (:SymTridiagonal,)                      # matrixtype1 is the sparser matrix type
-        for matrixtype2 in (:Tridiagonal, :Matrix) # matrixtype2 is the denser matrix type
-            @eval begin
-                ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B)
-                ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B))
-            end
-        end
-    end
-
-    for matrixtype1 in (:Diagonal, :Bidiagonal) # matrixtype1 is the sparser matrix type
-        for matrixtype2 in (:SymTridiagonal,)   # matrixtype2 is the denser matrix type
-            @eval begin
-                ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(convert(($matrixtype2), A), B)
-                ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, convert(($matrixtype2), B))
-            end
-        end
-    end
-
-    for matrixtype1 in (:Diagonal,)
-        for (matrixtype2,matrixtype3) in ((:UpperTriangular,:UpperTriangular),
-                                          (:UnitUpperTriangular,:UpperTriangular),
-                                          (:LowerTriangular,:LowerTriangular),
-                                          (:UnitLowerTriangular,:LowerTriangular))
-            @eval begin
-                ($op)(A::($matrixtype1), B::($matrixtype2)) = ($op)(($matrixtype3)(A), B)
-                ($op)(A::($matrixtype2), B::($matrixtype1)) = ($op)(A, ($matrixtype3)(B))
-            end
-        end
-    end
-    for matrixtype in (:SymTridiagonal,:Tridiagonal,:Bidiagonal,:Matrix)
-        @eval begin
-            ($op)(A::AbstractTriangular, B::($matrixtype)) = ($op)(copyto!(similar(parent(A)), A), B)
-            ($op)(A::($matrixtype), B::AbstractTriangular) = ($op)(A, copyto!(similar(parent(B)), B))
-        end
-    end
-end
-
 rmul!(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) =
     (B = adjB.parent; rmul!(full!(A), adjoint(B)))
 *(A::AbstractTriangular, adjB::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) =

@mbauman
Copy link
Member

mbauman commented Aug 24, 2018

In other words: the fallback definitions for array + and - simply assert the sizes are correct and then use broadcasting… and while I've not put together nearly as complete a table as you have in #28883, I think broadcasting mostly does the right thing.

@mcognetta
Copy link
Contributor Author

Well... how about that. Nice find haha. I am going to add a few more tests and then push these changes to #28883.

… from binops of special.jl so that broadcasting takes over. Cleaned up some of the tests for special.jl
@mcognetta
Copy link
Contributor Author

@mbauman Your fix worked in all cases except Bidiagonal since there is an input parameter and not a special type for upper and lower.

@mcognetta
Copy link
Contributor Author

I still need to update this for UnitUpperTriangular/UnitLowerTriangular and add tests for the correct types.

@mcognetta
Copy link
Contributor Author

I am moving all development of this to #28883.

@mcognetta mcognetta closed this Aug 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

linear algebra Linear algebra

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants