Make matrix multiplication work for more types#18218
Make matrix multiplication work for more types#18218andreasnoack merged 2 commits intoJuliaLang:masterfrom
Conversation
|
cc @mlubin, this may help with JuMP's internal matmul code. |
|
Couldn't this just be |
|
@joehuchette, yep |
|
Along the lines of @andreasnoack, you could define something like (probably with a better name) |
|
In fact, since 3ace05a and 6fd91b2 were merged, this change has become a lot more important. Indeed, before these commits, @andreasnoack @pabloferz yes we could also do something like that. The main difference is that in the solution of this pull request, if |
|
In the long run, I hope (specializations of) |
|
I don't think that the plan is to eventually keep overloading
Since I tried locally the alternative proposed solution and it works just fine. |
|
@pabloferz I might not understand inference correctly but what scares me a bit is that If you guarantee me that the inference will not use the fact that |
05e2791 to
c5e38fa
Compare
base/linalg/matmul.jl
Outdated
| mA, nA = lapack_size(tA, A) | ||
| mB, nB = lapack_size(tB, B) | ||
| C = similar(B, promote_op(*, arithtype(T), arithtype(S)), mA, nB) | ||
| C = similar(B, promote_op(matprod, arithtype(T), arithtype(S)), mA, nB) |
There was a problem hiding this comment.
I believe you missed two of these below (for matmul2x2 and matmul3x3)
There was a problem hiding this comment.
Yes, you are right. Why aren't they using arithtype by the way ?
There was a problem hiding this comment.
I guess they just were unintentionally forgot. But, now that you mention it, matprod also solves (more generally) the problem they where supposed to tackle, so in fact we can remove them and their definitions.
There was a problem hiding this comment.
Probably by mistake. But IIUC, arithtype is only needed to convert Bool to Int when doing matrix multiplication, which the promote_op(matprod, ...) does even without the arithtype, so no worries here, but maybe a chance for cleanup.
|
I have removed |
test/linalg/matmul.jl
Outdated
| import Base.*, Base.+, Base.zero | ||
| immutable TypeA | ||
| x::Int | ||
| end |
There was a problem hiding this comment.
Not that it matters too much, but you can save some space by changing, e.g. TypeA by Int, so you only need two new types for the test.
679d266 to
0157d0c
Compare
|
@tkelman Fixed :) |
Looks like it's being used in DistributedArrays.jl, so better to deprecate than to remove. |
|
@martinholters I have added a deprecation warning |
base/deprecated.jl
Outdated
| @deprecate cholfact!(A::Base.LinAlg.HermOrSym, uplo::Symbol = :U) cholfact!(A) | ||
|
|
||
| # #18218 | ||
| function arithtype(T) |
There was a problem hiding this comment.
Can't you use the @deprecate macro like used above?
There was a problem hiding this comment.
Doesn't add @deprecate automatically add an export? We probably don't want that here.
There was a problem hiding this comment.
I don't think I can because the macro is when a function should be used instead of another one. Here there is not replacement.
ff59690 to
81fbf1f
Compare
base/deprecated.jl
Outdated
| # #18218 | ||
| eval(Base.LinAlg, quote | ||
| function arithtype(T) | ||
| depwarn("arithtype is deprecated as it is no longer needed in Julia Base.", |
There was a problem hiding this comment.
Instead of using arithtype which replaces Bool by Int for matrix multiplications, we use an internal method matprod(x, y) = x*y + x*y which should cover the roll of arithtype while also being more general.
There was a problem hiding this comment.
are packages using this? if so, the deprecation should tell them what to use instead
There was a problem hiding this comment.
With this, I mean that there is no need now for arithtype or anything like it, which used to operate on types. Now its functionality (but not the method itself) is replaced by the definition and use of matprod.
There was a problem hiding this comment.
If packages are using this together with promote_op then the new way of doing things would be promote_op(matprod, S, T) instead of promote_op(*, arithtype(S), arithtype(T)). If packages are using it some other way, they would have to define their own replacement, I guess.
There was a problem hiding this comment.
this is not a helpful warning
There was a problem hiding this comment.
Yeah, you're right. @blegat Can you specify something more useful? Maybe like
"arithtype is now deprecated. If you were using inside a promote_op call, use promote_op(LinAlg.matprod, Ts...) instead. Otherwise, if you need its functionality, consider defining it locally."
Of course, it doesn't have to be that if you find a better way to express it.
There was a problem hiding this comment.
Yeah, that's the one (edited above).
There was a problem hiding this comment.
Thanks for your help :) I have updated the warning message with your suggestion.
base/deprecated.jl
Outdated
| # #18218 | ||
| eval(Base.LinAlg, quote | ||
| function arithtype(T) | ||
| depwarn("arithtype is now deprecated. If you were using it inside a promote_op call, use promote_op(LinAlg.matprod, Ts...) instead. Otherwise, if you need its functionality, consider defining it locally.", |
There was a problem hiding this comment.
wrap this over multiple lines
There was a problem hiding this comment.
Sorry about that, this is now fixed :)
|
@blegat There seems to be a small conflict here. Can you please rebase. Then it should be ready to merge. |
Currently it is assumed that the type of a sum of x::T and y::T is T but this may not be the case
|
@andreasnoack Thanks, that is now rebased :) |
|
cc @ajkeller34 it appears this broke Unitful.jl http://pkg.julialang.org/logs/Unitful_0.6.log |
|
I just read that log quickly but it seems like all of those failures could be fixed by defining: I guess that's not unreasonable: |
|
@tkelman Fixed. |
|
I'm not sure having to define addition on types is really the best solution here? |
|
Yes, ordinarily addition is only defined for quantities, not for units (not to be pedantic, but I've defined it for I had planned on putting more effort/thought into promotion in Unitful once 0.5.1 is out. When inference is working well, it's my understanding that I shouldn't need any of the several |
* Make matrix multiplication work for more types Currently it is assumed that the type of a sum of x::T and y::T is T but this may not be the case * Remove arithtype in matmul and deprecate it
Matrix multiplication does not work for arrays of elements types
TandSsuch that the typeTS = promote_op(*, T, S)does not satisfyTS == promote_op(+, TS, TS).For example, in this package, I have the type
Termwhich is one term of a polynomial and the typePolynomialwhich is the sum of several terms.Suppose I am trying to compute
A * xwhereAis a matrix ofInt64andxis a vector ofTerm.Then
TSwill beTermso it will allocate a vector ofTermto store the result. However when doing the sum ofTermit will getPolynomialso what should have been allocated is a vector ofPolynomial.The fix is simple, allocate an array of type
promote_op(+, TS, TS).