-
Notifications
You must be signed in to change notification settings - Fork 192
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
Finish i128 support #62
Conversation
Thanks for taking this on! It will be a few days before I can review this in depth, but a few notes:
|
Thanks for the quick answer, I'll pull things into their own PRs, first one is here #63 |
5ee8bff
to
78b142c
Compare
I understand, but |
Done for all the operations in #64 |
I have introduced a new feature |
|
OK, no rush, I'm just trying to get around to things I've been neglecting. :) |
@cuviper I rebased this, and it is passing tests, (except serialization with When you have some time, it would be great if we can work through the remaining issues to figure out how to get this ready for merge. |
@dignifiedquire -- If you're still around, I think I've reconciled the performance losses well enough, and I've made quite a few other cleanups as well. A counter-review would be appreciated. cc @maxbla -- since you've been hacking on num lately, maybe you'd like to review this too? I have no doubt there are more cleanup opportunities, but I hope it's Good Enough that we can merge for the performance benefits at hand. |
I'd be happy take a look. A comprehensive review might take some time - this PR seems fairly substantial. |
I'll appreciate whatever level of detail you can manage, thanks! |
Rebased to resolve conflicts with the quickcheck PR. |
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.
Tl;dr I goofed. The performance is the same between 'master' and 'u128' on 32-bit.
I think I've reconciled the performance losses well enough
I dug out my old 32-bit laptop to see if performance is the same between master
and this branch. It seems kind of far off, but I might be missing something.
running cargo bench --all-features factorial_mul_biguint
I get 1,195,380 ns/iter for master
(uses normal cargo bench) and 2.1822ms/iter in this branch (uses criterion.rs). This was all on nightly Rust, as the old bencher only works on nightly rust. There's a lot going on here -- criterion seems to do some more complicated stuff (like "warming up for 3s" before benching).
How have you been comparing the performance of master
to this branch and did I do anything obviously wrong? I was completely mistaken. I accidentally rand the bench on master
from this repo, when I meant to run them on u128
. The performance is completely in line - 1.197ms vs 1.195ms.
r | ||
if let Some(other) = other.to_u32() { | ||
self % other | ||
} else if let Some(other) = other.to_i32() { |
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.
Since other
is unsigned (because it is a BigInt
), how could other.to_u32()
return None
but other.to_i32()
return Some(_)
?
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.e. I think you can delete lines 1877 and 1878
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.
Are you thinking of BigUint
? BigInt
can be negative...
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.
Yeah, you're right. I even retyped BigInt
and it didn't click for me that that type is signed.
Since we're discussing this function, I suspect many instantiated BigInt
s (in the wild) will be small and further, many will be bigger than one word. My point is that the range 2.1 billion.. 4.3 billion
is probably pretty uncommon, so it might make sense to just drop u32
branch entirely. Alternatively it might make sense to try to cast to bigdigit for the unsigned branch (is there an easy way to do that?)
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.
The conversion checks should be relatively trivial, compared to the actual division. Rem<i32>
even forwards to Rem<u32>
with added sign handling, which is why it seems to make sense to deal with u32
directly first. I don't feel strongly, but it feels like a micro-optimization to worry about this much, where the real win is just in dividing by a primitive.
Maybe you'd like to focus on this for a followup performance PR?
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.
Yeah, it would be silly to make this type of change without measuring. I am interested in doing some performance work, but I'm not exactly sure how to do it. It seems like num-bigint has used criterion.rs at some point? but I couldn't find it in the git log. I think criterion would probably be very helpful for optimizing.
@maxbla Thanks for your review! I noticed that you had comments for almost every file except
|
/// | ||
/// This is an internal `pub(crate)`-ish API only! | ||
#[inline] | ||
pub fn biguint_from_vec(digits: Vec<BigDigit>) -> BigUint { |
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 function is pub
, but it requires a Vec<BigDigit>
, so it effectively can't be used externally. The #[doc(hidden)]
attribute would hide it form public documentation. There technically could be a name conflict if someone did use num_bigint::*
, but that seems unlikely.
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 is in the private mod biguint
though, so it's truly inaccessible outside of the crate, as long as we don't accidentally re-export it elsewhere. It should be made pub(crate)
whenever we raise our rustc minimum sufficiently though.
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.
It seems like half my comments are due to oversight on my part :/
OK, let's finally take the plunge in the upcoming 0.3 release! Thanks again @dignifiedquire for your initial work, and also @maxbla for helping with the review. bors r+ |
62: Finish i128 support r=cuviper a=dignifiedquire Depends on #63 and #64 Implements `BigDigit = u64` ~~behind a feature flag `u64_digit`~~ for all 64-bit targets with `u128`. TODOs - [x] find a way to make the new methods that take `BigDigit`s for constructing `BigUint`s private - [x] Fix `modpow`, the last broken test. Closes #40 Co-authored-by: dignifiedquire <dignifiedquire@gmail.com> Co-authored-by: Josh Stone <cuviper@gmail.com>
Build succeeded |
Depends on #63 and #64
Implements
BigDigit = u64
behind a feature flagfor all 64-bit targets withu64_digit
u128
.TODOs
BigDigit
s for constructingBigUint
s privatemodpow
, the last broken test.Closes #40