Skip to content
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

Clarify which arg is modified in mul/div. #25421

Merged
merged 1 commit into from
Jan 19, 2018
Merged

Clarify which arg is modified in mul/div. #25421

merged 1 commit into from
Jan 19, 2018

Conversation

simonbyrne
Copy link
Contributor

Another stab at #16772. This is more or less the same as #24698 except updated for Transpose.

@JeffBezanson
Copy link
Sponsor Member

I suppose this solution is ok. The numbers aren't beautiful, but neither is needing to repeat an argument (especially if the argument isn't just a variable name).

@JeffBezanson JeffBezanson changed the title Clarify which are is modified in mul/div. Clarify which arg is modified in mul/div. Jan 5, 2018
Copy link
Member

@Sacha0 Sacha0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ldiv!(A, B) always overwrites B, and rdiv!(A, B) always overwrites A, so two-argument ldiv! and rdiv! do not share mul!'s relevant semantic ambiguity. Perhaps forgo attaching 2 to ldiv! and 1 to rdiv!? :)

@simonbyrne
Copy link
Contributor Author

That's a good point. I renamed them for consistency, but would be happy to change them back.

@Sacha0
Copy link
Member

Sacha0 commented Jan 6, 2018

I renamed them for consistency, but would be happy to change them back.

Might as well minimize the aesthetic suboptimality :).

@KristofferC
Copy link
Sponsor Member

KristofferC commented Jan 6, 2018

The convention is to modify the first argument. Therefore, for the function that adhere to the convention they can just be mul! and only those that break the convention needs a number.

Or is mul! an alias to mul!1 somewhere in this PR? Being forced to write mul!1 everywhere seems a bit unfortunate.

@tkelman
Copy link
Contributor

tkelman commented Jan 6, 2018

There isn't an ambiguity in div, but ldiv does deviate from the argument order convention, and flagging that as such in the name seems beneficial to me. Could be done independently of changes to mul though.

@simonbyrne
Copy link
Contributor Author

simonbyrne commented Jan 6, 2018

I'm not too fussed on the names, but as they're now unique it is simply a matter of sed to change them. If we want to rename the div ones as well, I have moved the changes their to the sb/div12 branch.

My main objection to mul1! being the 2-argument mul! is that mul2! is by far the more commonly used variant.

@deprecate A_mul_Bc!(A::AbstractMatrix,B::Diagonal) mul!(A, Adjoint(B))
function A_mul_B!(A::Diagonal,B::Diagonal)
depwarn("`A_mul_B!(A::Diagonal,B::Diagonal)` should be replaced with `mul1!(A, B)` or `mul2!(A, B)`.", :A_mul_B!)
throw(MethodError(A_mul_B!, Tuple{Diagonal,Diagonal}))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MethodError(A_mul_B!, (A, B))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch.

@deprecate Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} mul!(Adjoint(A), B)
@deprecate A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} mul2!(A, B)
@deprecate A_mul_B!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} A*B
@deprecate A_mul_B!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} A*B
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why transform from mul!(A, B) to A*B? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because they were implemented internally as copying already anyway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should nix the corresponding mul! methods, being something of misnomers? (Perhaps you already have? :) )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did.

@deprecate Ac_ldiv_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) ldiv1!(Adjoint(A), B)
@deprecate Ac_ldiv_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) ldiv1!(Adjoint(A), B)
@deprecate At_ldiv_B!(A::Union{LowerTriangular,UnitLowerTriangular}, B::UpperTriangular) ldiv1!(Transpose(A), B)
@deprecate At_ldiv_B!(A::Union{UpperTriangular,UnitUpperTriangular}, B::LowerTriangular) ldiv1!(Transpose(A), B)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ldiv!?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch.

@@ -3115,7 +3119,7 @@ end
@deprecate At_mul_B!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) mul!(C, Transpose(A), B)
@deprecate At_mul_B!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) mul!(C, Transpose(A), B)
@deprecate At_mul_B!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) mul!(C, Transpose(A), B)
@deprecate A_mul_B!(A::Tridiagonal, B::AbstractTriangular) mul!(A, B)
@deprecate A_mul_B!(A::Tridiagonal, B::AbstractTriangular) mul2!(A, B)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The odd method :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed it is odd. We could get rid of it?

@deprecate A_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} mul!(A, B)
@deprecate A_mul_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} mul!(A, B)
@deprecate A_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} mul2!(A, B)
@deprecate A_mul_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} mul2!(A, B)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mul1!?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch.

@deprecate A_mul_B!(G::Givens, R::Rotation) mul2!(G, R)
@deprecate A_mul_Bc!(A::AbstractMatrix, G::Givens) mul1!(A, Adjoint(G))
@deprecate A_mul_B!(G::Givens, A::AbstractVecOrMat) mul2!(G, A)
@deprecate A_mul_B!(G1::Givens, G2::Givens) G1 * G2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why transform from mul!(G1, G2) to G1 * G2? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method just threw an error anyway.

@deprecate A_mul_B!(G1::Givens, G2::Givens) mul!(G1, G2)
@deprecate A_mul_Bc!(A::AbstractMatrix, R::Rotation) mul1!(A, Adjoint(R))
@deprecate A_mul_B!(R::Rotation, A::AbstractMatrix) mul2!(R, A)
@deprecate A_mul_B!(G::Givens, R::Rotation) mul2!(G, R)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another tricky one :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's tricky about this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without knowing the implementations of Rotation and Givens, from this signature one might not know whether this operation is possible and, if so, what it should do. (This signature certainly would have given me pause had I not recently looked at the relevant definitions :).)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly.


@deprecate *(A::Factorization, B::Factorization) Matrix(A)*Matrix(B)
@deprecate *(A::Adjoint{<:Any,<:Factorization}, B::Factorization) adjoint(Matrix(A.parent)) * Matrix(B)
@deprecate *(A::Factorization, B::Adjoint{<:Any,<:Factorization}) Matrix(A) * adjoint(Matrix(B.parent))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these deprecations related?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I think I added them to deal with the QR/LQ business, but they may no longer be necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the story was that there were a couple of these methods, but they were inconsistently defined and mostly just did this anyway. It is probably better to define more specific deprecations though.

function (*)(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S}
TT = typeof(zero(T)*zero(S) + zero(T)*zero(S))
return mul!(Q, copy_oftype(X, TT))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the additional empty line? :)

@@ -267,7 +278,7 @@ The reason for this is that factorization itself is both expensive and typically
and performance-critical situations requiring `rdiv!` usually also require fine-grained
control over the factorization of `B`.
"""
rdiv!(Y, A, B)
rdiv!(A, B)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does a three-argument rdiv! docstring still exist somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no 3-arg rdiv!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that's amusing 😄.

@@ -5,7 +5,7 @@ __precompile__(true)
module SuiteSparse

import Base: \
import Base.LinAlg: ldiv!, rdiv!
import Base.LinAlg: ldiv!, ldiv!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ldiv!, ldiv!?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A remnant from sed...

@@ -1,3 +1,4 @@

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? :)

@@ -385,6 +385,8 @@ function nnz(lu::UmfpackLU)
end

### Solve with Factorization
# TODO: these should probably be removed since they're not inplace
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -398,6 +400,7 @@ ldiv!(translu::Transpose{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Com
ldiv!(adjlu::Adjoint{Float64,<:UmfpackLU{Float64}}, B::StridedVecOrMat{<:Complex}) =
(lu = adjlu.parent; ldiv!(B, Adjoint(lu), copy(B)))


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? :)

@test LinAlg.mul1!(copy(D1),D2) == D1*D2
@test LinAlg.mul2!(D1,copy(D2)) == D1*D2
@test LinAlg.mul1!(copy(D1),D2) == D1*D2
@test LinAlg.mul2!(D1,copy(D2)) == D1*D2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three repetitions of the same pair of tests?

@@ -493,6 +494,7 @@ end
let n = 5
A = rand(Float16, n, n)
B = rand(Float16, n-1, n-1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? :)

@Sacha0
Copy link
Member

Sacha0 commented Jan 12, 2018

Modulo rebase this looks great! Much thanks for your persistence Simon! :)

Summary of sentiments: On the one hand, I sympathize with Andreas that the names mul!, ldiv!, and rdiv! are lovely. On the other hand, I am not as clever as Andreas, so two-argument mul! does trip me up now and again. So overall I favor merging the minimal set of renames necessary to sort the latter (i.e. two-argument mul! -> (mul1!|mul2!) as in this pull request) while leaving everything else as is.

In short, 👍 for these changes (or any spelling variation on mul1!/mul2!). Best!

@JeffBezanson
Copy link
Sponsor Member

I think this is ready to go now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants