-
Notifications
You must be signed in to change notification settings - Fork 21
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 Multiplication Support for Complex Types #228
Comments
Thanks for bringing this to our attention! Sorry I didn't get to it earlier, but this week has been really busy at work and at home. I will play around with this as soon as I get a chance --- possibly this weekend. I'll update the ticket once I understand the prospects for a solution. |
Thank you very much for taking care of this issue.
Maybe it helps. |
I looked into this some over the weekend. It turns out to be surprisingly tricky and subtle. First, why are these Although I don't know how to express what we do want, there are a bunch of types we definitely don't want:
I thought we might be able to get away with switching to a "deny list" approach that excludes these types, using "any empty type" as a proxy for our monovalue types. Unfortunately, this doesn't work: if users define a custom type with multiplication or division operators which work with Next time I take a crack at this, I'll probably try a simpler approach that keeps the "allow list", but simply expands it to As for adding |
Okay, thank you very much for trying to solve it and your explanations. I am not sure whether it is worth to add it to the Quantity inferface. At least for me, this is a quite ordinary use-case😄 |
That's really helpful, and I'm grateful that you posted it before I went and implemented something that wouldn't have solved your use case! I'll mull this over and see what strategies my subconscious can come up with. Maybe the fact that I'm so swamped for the next several weeks will be a blessing in disguise, giving my subconscious more opportunity to digest the problem. 🙂 |
Update: everyone here got sick, so we had to cancel this weekend's plans. But the silver lining is that it gave me the chance to try out my ideas! Try the code in #229. It passes all of the new and existing unit tests, and all of the tests internally in Aurora's repo. Additionally, I verified that it has no measurable impact on compile time. If it fixes your problem, then I'll take it out of draft mode and get it reviewed! |
It seems to work now for std::complex, very good. au::Quantity<au::Thickness, Type> a = au::meters(thrust::complex(1.0, 2.0)); Using MSVC and the commit you pointed out, I receive the following compilation error: |
Interesting! What is Anyway, the error itself was very suggestive. constexpr auto length = meters(std::complex<double>{1.0, 2.0});
const auto length_m = length.in(meters); // Passes
const auto length_mm = length.in(milli(meters)); // Fails horribly I'm going to need to figure out how to approach this problem in general... 🤔 |
The goal of these `std::is_arithmetic` SFINAE uses was to avoid ambiguous overloads when we multiply a `Quantity` with another `Quantity`. It was only ever a shortcut. It seems to work well in most cases, but recently, a user pointed out that it doesn't help `std::complex`. (To be clear, we could _form_ a `Quantity` with `std::complex` rep, but we couldn't multiply or divide a `Quantity` with a `std::complex` scalar.) This PR takes a different approach. First, we define what constitutes a valid "rep". We're very permissive here, using a "deny-list" approach that filters out empty types, known Au types, and other libraries' units types (which we detect via our `CorrespondingQuantity` trait). Incidentally, this should give us a nice head start on #52. Next, we permit an operation (multiplication or division) depending on how the "candidate scalar" type would interact with the Quantity's rep: simply put, the result must itself both exist, and be a valid rep. The net result should be that we automatically consider a much wider variety of types --- including complex number types from outside the standard library --- to be valid scalars. Crucially, this should also be able to avoid breaking existing code: we are introducing potentially a _lot_ of new overloads for these operators, and we can't allow any to create an ambiguity with existing overloads. Helps #228, but we need more Magnitude support.
@MatthiasJeuthe, could you please check the draft PR #278, and see if it fixes your problem? If it does, I'll get it ready for more thorough review. |
Thank you very much for working on the issue. |
Multiplication and division by a scalar appear to be functioning correctly; I verified this using both std::complex and cuda::std::complex. However, multiplying by a complex-valued quantity isn't supported yet. I assume that wasn't the goal of this fix, correct? For example:
This results in the following error: |
I hadn't considered that test case, but I think we should include it in this PR. One small nitpick. As written, the test case could never work, because you can't pass That said, I've added some tests that multiply by a "raw" complex number. Your feedback was really helpful in uncovering an issue with complex support, and I think I've fixed it now. Try the latest on #278! |
@MatthiasJeuthe, let me know if you can come up with any more test cases we should include. Otherwise, I'll fix this up for review, likely sometime soon after my CppCon talk next Wednesday. 🙂 |
@chiphogg I believe you're ready to proceed with your review. Best of luck with your talk—I’ll definitely watch it on YouTube! |
Thank you very much for sharing your code.
The multiplication operator in Quantity is only enabled if T suffices std::is_arithmetic.
However, my use case involves the use of complex numbers, e.g. std::complex.
What about allowing such types as well?
As a quick work-around I adapted the code as follows:
The text was updated successfully, but these errors were encountered: