-
Notifications
You must be signed in to change notification settings - Fork 42
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
Supporting Unitful LinearMaps #196
base: master
Are you sure you want to change the base?
Conversation
Could eventually address #195 |
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.
Thanks @JeffFessler for starting this. As you may have noticed, I started a similar effort in LinearAlgebra, so this is very welcome. It's perhaps a matter of taste, but I like the current behaviour where we determine the new eltype at the "implicit" constructor *
. It has a bit of code repetition smell, but it's very clear and has the other advantage that only two (el)types are involved. For type inference, this might be easier than going down the reduction path with prod
. I'm curious how the multiplication code will work, because it currently tries to reuse temporary memory. But when all linear maps have units, then each intermediate vector will have a different unit. Once we have worked out/agreed on a design pattern, then this pattern should probably be transferred to the Kronecker stuff (and even further to the KhatriRao maps). I'm very excited about this!
Actually I had not noticed, but I am very glad to hear it!
Yeah, I kind of thought you might say that and I'm fine with retaining the small repetition to help with type inference. In some of my other code I had to tell the compiler what the return type would be to get type 'inference' to work and I hope to avoid that here
I suspect we may have to use Let me fix up the constructors first and then take a stab at multiply. |
Co-authored-by: Daniel Karrasch <[email protected]>
@dkarrasch I think I have adopted all your suggestions and the existing tests pass fine with Julia 1.8.3 on my computer, but one of the type inferences fails on 1.6 in the CI process in a linearcombination test. Is it possible that the Julia 1.6 compiler is simply not as good at type inference? If so, personally I would just abandon 1.6 because I don't want to put time into supporting old versions. But I suspect you want to keep it. Would you mind taking a look at the type inference that failed and see if you can identify the issue? To my eyes it seems unrelated to this PR, but probably I'm missing something :) Update: now 1.6 seems to be passing too, so perhaps your merge of master did some magic - thanks for that! |
Update: I've made progress on the products, but there is one function that will be a sticking point. I think I am partly responsible for encouraging the temporary vectors |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #196 +/- ##
==========================================
- Coverage 99.68% 99.05% -0.63%
==========================================
Files 22 22
Lines 1591 1592 +1
==========================================
- Hits 1586 1577 -9
- Misses 5 15 +10
☔ View full report in Codecov by Sentry. |
This is nice. I think we need unitful test cases where we would want memory reuse in compositions to work. For instance, I noticed a special pattern here in the dest = similar([], _multype(A.maps[n], source), (size(A.maps[n], 1), size(source)[2:end]...))
_unsafe_mul!(dest, A.maps[n], source)
# dest, source = source, dest # alternate dest and source
dest, source = [], dest The last line should be simply |
I hope to get back to this in a couple weeks... |
This is my WIP.
Here's the main issue:
if
A
is a LM with elements that are integers with units seconds,and
B
is LM with elements that are Float32 with units meters,then the appropriate eltype for the composite
C = A * B
cannot be computed bypromote_type
(AFAIK) but rather is something likeeltype(oneunit(eltype(A)) * oneunit(eltype(B))
which in this case would be Float32 with units meter-seconds.
In my other packages I have managed to use
oneunit
like this without needing to add Unitful as a package dependency. I hope for the same approach here.In the above example, Float64 with units meters-seconds would also be a legit eltype for C and I think the promote_type check can handle that.
The existing code forces the caller to determine the eltype of the product.
Why not provide a convenience constructor?
The changes here pass all existing tests except for one type inference.
Before I chase that down I wanted to get your general reaction.
If you are open to something along these lines then I will add Unitful tests.
If you have ideas about the type inference issue, comments welcome!