-
-
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
Deprecate scale! in favor of mul!, mul1!, and mul2! #25701
Conversation
0139478
to
cb8f50f
Compare
@@ -354,7 +354,8 @@ LinearAlgebra.tril! | |||
LinearAlgebra.diagind | |||
LinearAlgebra.diag | |||
LinearAlgebra.diagm | |||
LinearAlgebra.scale! | |||
LinearAlgebra.mul1! |
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.
Perhaps these should be moved to the ## Low-level matrix operations
-section with mul!
, ldiv!
and rdiv!
further down (~L433).
@deprecate scale!(A::AbstractMatrix, b::AbstractVector) mul1!(A, Diagonal(b)) | ||
@deprecate scale!(a::AbstractVector, B::AbstractMatrix) mul2!(Diagonal(a), B) | ||
@deprecate scale!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) mul!(X, A, Diagonal(b)) | ||
@deprecate scale!(C::AbstractMatrix, a::AbstractVector, B::AbstractMatrix) mul!(X, Diagonal(a), B) |
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.
X
-> C
(or C
-> X
) and same on the line above.
stdlib/LinearAlgebra/src/generic.jl
Outdated
|
||
""" | ||
scale!(A, b) | ||
scale!(b, A) | ||
mul1!(A, b) |
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.
Perhaps add ::AbstractArray
and ::Number
to the signature since there are other mul1!
methods?
stdlib/LinearAlgebra/src/generic.jl
Outdated
(similar to `Diagonal(b)*A`), again operating in-place on `A`. An `InexactError` exception is | ||
thrown if the scaling produces a number not representable by the element type of `A`, | ||
e.g. for integer types. | ||
|
||
# Examples | ||
```jldoctest | ||
julia> a = [1 2; 3 4] |
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.
a
-> A
to match the signature?
stdlib/LinearAlgebra/src/generic.jl
Outdated
julia> scale!(b,a) | ||
# Examples | ||
```jldoctest | ||
julia> a = [1 2; 3 4] |
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.
a
-> A
to match the signature?
scale!(A::Union{UpperTriangular,LowerTriangular}, c::Number) = scale!(A,A,c) | ||
scale!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = scale!(A,c) | ||
mul1!(A::Union{UpperTriangular,LowerTriangular}, c::Number) = mul!(A, A, c) | ||
mul2!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = mul1!(A', c')' |
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.
One too many '
.
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 think this one is correct: c*A = (c*A)'' = ((c*A)')' = (A'*c')'
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.
Oh, I confused myself and thought the line ended with the char ')'
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'm confused — why can't you simply define mul2!(c::Number, A) = mul1(A, c)
?
Oh, I see, it's for non-commutative numbers like quaternions.
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 we should have
mul2!(c::Union{Real,Complex}, A::Union{UpperTriangular,LowerTriangular}) = mul1!(A, c)?
if it makes a performance difference in the common case of commutative *
.
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.
This one was hitting the generic fallback so it ended up being about twice as slow. I realized a better version would be to call mul!(A, c, A)
and define that method. It also made me fix mul!(A, A, c)
since it actually computed c*A
. Eventually, we should fix the Adjoint
/Transpose
version so we avoid traversing the zero parts but that is an optimization for a separate PR.
stdlib/LinearAlgebra/src/generic.jl
Outdated
2 | ||
|
||
julia> scale!(a,b) | ||
julia> mul1!(a, 2) |
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.
a
-> A
stdlib/LinearAlgebra/src/generic.jl
Outdated
|
||
julia> b = [1; 2]; | ||
Scale an array `A` by a scalar `b` overwriting `A` in-place. |
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.
A
-> B
twice.
e254310
to
87abe97
Compare
87abe97
to
3f01891
Compare
for j = 1:n | ||
@inbounds A[j,j] = c | ||
for i = (j + 1):n | ||
@inbounds A[i,j] = B[i,j] * c |
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.
c * B[i,j]
?
0ed5488
to
d0ce71a
Compare
|
I have to say that I find the names |
I agree. They are actually the more obvious choices given that we already have |
Just to clarify, which argument it mutated by which function? The convention seems to be that a mutating left-division mutates the right argument while a mutating right-division mutates the left argument. Right? Er, I mean correct? So by analogy, |
That is very satisfyingly consistent with |
These aren't exactly the most mainstream functions so I think that "satisfying consistency" with another pair of niche in-place operators is as good as we can hope for. It is a very satisfying symmetry and kind of interesting since |
Yes, and it is also not obvious which argument |
Thinking about this again, I find the consistency not so satisfying anymore: Usually Maybe we should rename |
The key word above is "usually". Mutating function mutate their "subject" for some appropriate notion of subject, which is usually the first argument, but not always. In the case of left division, the subject is being divided from the left, so the subject is the right argument. In the case of right division, the subject is being divided from the right, so the subject is the left argument. The same logic applies to |
I can appreciate the argument for renaming |
I don't know where the notion that the first argument should always the one to be mutated came from. That's neither empirically true in our existing APIs, nor a hard-and-fast principle that we've ever aimed to adhere to. It is often the case, but in cases where it doesn't make sense, we don't do that. This seems like one of those cases. |
Playing devil's advocate (and noting that either argument order seems fine on this end), the perspective from which the mutated-argument-first order seems natural to me is the |
Writing any mutating version of |
This point does not seem so cut and dry. Among other data points, #25701 (comment) demonstrates that e.g. |
Fixes #24276