-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tril and triu for special matrices #12574
Conversation
👍 My only complaint would be that it might be too readable. |
👍 |
heh |
n = length(M.dv) | ||
if abs(k) > n | ||
throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) | ||
elseif M.isupper && k < 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could be:
elseif k > 0
return M
elseif M.isupper
if k < 0
return Bidiagonal(zeros(M.dv),zeros(M.ev),true)
else
return Bidiagonal(M.dv,zeros(M.ev),true)
end
elseif k < -1
return Bidiagonal(zeros(M.dv),zeros(M.ev),false)
elseif k == -1
return Bidiagonal(zeros(M.dv),M.ev,false)
else
return M
end
This avoids the rechecking of M.isupper and passing it to Bidiagonal.
Should these generally be returning copies of or references to the input data? |
Add tril and triu for special matrices
Answering my own question, judging by Lines 41 to 44 in db787d8
edit: Or these can consistently implement |
@tkelman so I should have all of these return |
I think the right solution here is to define edit: apparently there isn't a fallback for |
I guess the reason I kept many of these as elseif !M.isupper && k == 0
return M
elseif M.isupper && k == 0
return Bidiagonal(M.dv,zeros(M.ev),M.isupper) where we either return |
I think if one of these methods ever returns the original matrix itself or a reference to some part of it in the output, then that method should be named There are cases where |
It looks like mutating versions of all of these could modify the argument matrix in-place and always return the argument matrix. In which case, the non-mutating version could always just be written as calling the mutating version on a copy of the input matrix. Might be slightly slower since the input has to be copied and you can't just allocate vectors of zeros, but I'm not sure that it would be a major difference. |
I think I like that option. Instead of using The only tricky case is the non-type-stable branches for |
Perhaps |
I thank I didn't read carefully enough yesterday. There are some problems here, e.g. julia> A = LinAlg.UnitLowerTriangular(randn(4,4))
4x4 Base.LinAlg.UnitLowerTriangular{Float64,Array{Float64,2}}:
1.0 0.0 0.0 0.0
1.1291 1.0 0.0 0.0
0.195707 -1.72338 1.0 0.0
3.31616 0.252167 -0.598446 1.0
julia> triu(A, 1)
4x4 Base.LinAlg.UnitLowerTriangular{Float64,Array{Float64,2}}:
1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
julia> triu(full(A), 1)
4x4 Array{Float64,2}:
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 and I'm in doubt if we can, in general, support the @tkelman I think you might be extending the meaning of |
I think you mean type stable.
True. So in cases where in-place modification is possible for these methods then |
I'm working on a PR to address your feedback. For the |
I think so, that sounds appropriate. |
Ok, almost done! |
@@ -56,6 +56,12 @@ end | |||
ctranspose(A::Hermitian) = A | |||
trace(A::Hermitian) = real(trace(A.data)) | |||
|
|||
#tril/triu | |||
tril(A::Hermitian,k::Integer=0) = tril(A.data,k) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these are right. Aren't half the elements in A.data
potentially garbage?
julia> A = rand(4,4)
4x4 Array{Float64,2}:
0.992492 0.88037 0.40931 0.311544
0.623913 0.93559 0.310044 0.598238
0.393736 0.051534 0.103072 0.74386
0.747731 0.684462 0.813315 0.0329609
julia> Symmetric(A)
tril(4x4 Base.LinAlg.Symmetric{Float64,Array{Float64,2}}:
0.992492 0.88037 0.40931 0.311544
0.88037 0.93559 0.310044 0.598238
0.40931 0.310044 0.103072 0.74386
0.311544 0.598238 0.74386 0.0329609
julia> tril(Symmetric(A))
4x4 Array{Float64,2}:
0.992492 0.0 0.0 0.0
0.623913 0.93559 0.0 0.0
0.393736 0.051534 0.103072 0.0
0.747731 0.684462 0.813315 0.0329609
julia> full(Symmetric(A))
4x4 Array{Float64,2}:
0.992492 0.88037 0.40931 0.311544
0.88037 0.93559 0.310044 0.598238
0.40931 0.310044 0.103072 0.74386
0.311544 0.598238 0.74386 0.0329609
julia> tril(full(Symmetric(A)))
4x4 Array{Float64,2}:
0.992492 0.0 0.0 0.0
0.88037 0.93559 0.0 0.0
0.40931 0.310044 0.103072 0.0
0.311544 0.598238 0.74386 0.0329609
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow. K, on it.
The lower triangle is garbage.
Address type stability issues in #12574 and fix a bug or two
As discussed in JuliaLang/LinearAlgebra.jl#161,
Diagonal
,Bidiagonal
,Tridiagonal
,SymTridiagonal
,UpperTriangular
,LowerTriangular
,UnitUpperTriangular
,UnitLowerTriangular
,Symmetric
, andHermitian
types didn't havetril
ortriu
defined.Diagonal
hadtril!
andtriu!
but the!
was incorrect since the underlying matrix wasn't modified.I also added tests.