-
Notifications
You must be signed in to change notification settings - Fork 55
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
Bring the overflow behavior in bit shifts in sync with std
#395
Conversation
I think these are reasonably OK things to bring in line with |
8c67ba9
to
7300c19
Compare
let nlimbs = self.nlimbs(); | ||
let mut limbs = vec![Limb::ZERO; nlimbs].into_boxed_slice(); | ||
|
||
fn shl_vartime_into(&self, dest: &mut Self, shift: u32) -> Option<()> { |
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.
As a convention I'm a fan of putting this sort of output parameter on the end, at least as far as an output buffer which is simply written into otherwise uninitialized, though I will acknowledge that's inconsistent with *_assign
APIs, which operate on &mut self
(and might those be applicable here?)
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's not exactly assign
, since it writes in a new buffer. But I don't mind changing the argument order, it's a private method anyway.
The reason it's not assign
is because I wanted to optimize the cache usage, and in some cases it's impossible to do the forward iteration inplace.
Running the benchmarks vs |
Yep, I bisected to that point too, seems to be the reason. |
4d15f1e
to
f7a016e
Compare
6e5c878
to
f9813f5
Compare
f9813f5
to
1640e79
Compare
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.
Looks fine now aside from the commented out test
A part of #268
Fixes #121
const fn
bit shifts forUint
return the overflow status asCtChoice
(and set the result to zero in that case, which is documented, so it's a part of the API now).Option
would be better for the vartime shifts, but its methods are notconst
yet in stable.shl/shr
forBoxedUint
return(Self, Choice)
(notCtOption
since most of its methods need the type to beConditionallySelectable
, whichBoxedUint
isn't). The vartime equivalents returnOption<Self>
.uint/shl.rs
andshr.rs
more uniform and improved vartime shift performance (before it was calling a constant-time shift-by-no-more-than-limb which added some overhead)BoxedUint
by reducing the amount of allocationsBoxedUint::shl1()
implementationLimb
methods which improved shift performance noticeablyUint
shifts: we need to iterate to log2(BITS-1), not log2(BITS), because that's the maximum size of the shift.sh(r/l)1_with_overflow()
tosh(r/l)1_with_carry
to avoid confusion - in the context of shifts we call the shift being too large an overflow.