Optimized Ord::cmp function#155
Conversation
|
I have in mind a way to make the current code iterative without changing the overall approach as much. I would at least like to compare that to yours, so if you could share your benchmark, that would be great. |
|
https://github.com/mikem8891/num-bench
|
|
Hmm, with your code I get these results on my Ryzen 7 9800X3D: There must be some large architectural difference in our CPUs -- branch predictor? My own iterative code gets around ~848ns, so I need to figure out what that has lost too, but it's close. |
| } | ||
| let zero = T::zero(); | ||
|
|
||
| let (q_n, mut a) = lhs.numer.div_rem(&rhs.numer); // 0 < c < a ∴ q_n ≥ 1 |
There was a problem hiding this comment.
As part of mine, I also have a test over all i8 ratios (with positive denom), and your implementation trips here comparing -128/x and -1/1, overflowing -128/-1.
This implementation of the
Ord::cmpfunction does several early comparisons to try to determine ordering before resulting to div and mod operations. This allows about half of unsignedRatio<T>pairs and 3/4 of signedRatio<T>pairs to be determined using simple comparisons (based on the entire input space, individual results may vary). If simple comparisons don't determine the ordering, then the function enters a tight loop to converge on a solution as quickly as possible.Note, #121 would be faster, but would still benefit from this pull request if
checked_mulreturnsNone.I confirmed this fixes #140 . This solution is iterative instead of recursive.
This should also fixes #146 . I phoned this in because I think negative denominators should not be adversely affecting performance or complexity compared to normal fractions.
For context, here are some benchmark results
I can make this benchmark available to you if needed.
This is a repost of #147 because I accidentally closed it after the crate was refactored into modules.