Merge pull request #445 from elichai/2020-07-divmod

Use the remainder from div_rem instead of recomputing it
This commit is contained in:
Steven Roose 2020-08-09 16:59:39 +02:00 committed by GitHub
commit c03d2d59c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 38 additions and 32 deletions

View File

@ -84,6 +84,42 @@ macro_rules! construct_uint {
assert!(init >= 0);
$name::from_u64(init as u64)
}
// divmod like operation, returns (quotient, remainder)
#[inline]
fn div_rem(self, other: Self) -> (Self, Self) {
let mut sub_copy = self;
let mut shift_copy = other;
let mut ret = [0u64; $n_words];
let my_bits = self.bits();
let your_bits = other.bits();
// Check for division by 0
assert!(your_bits != 0);
// Early return in case we are dividing by a larger number than us
if my_bits < your_bits {
return ($name(ret), sub_copy);
}
// Bitwise long division
let mut shift = my_bits - your_bits;
shift_copy = shift_copy << shift;
loop {
if sub_copy >= shift_copy {
ret[shift / 64] |= 1 << (shift % 64);
sub_copy = sub_copy - shift_copy;
}
shift_copy = shift_copy >> 1;
if shift == 0 {
break;
}
shift -= 1;
}
($name(ret), sub_copy)
}
}
impl ::std::ops::Add<$name> for $name {
@ -134,35 +170,7 @@ macro_rules! construct_uint {
type Output = $name;
fn div(self, other: $name) -> $name {
let mut sub_copy = self;
let mut shift_copy = other;
let mut ret = [0u64; $n_words];
let my_bits = self.bits();
let your_bits = other.bits();
// Check for division by 0
assert!(your_bits != 0);
// Early return in case we are dividing by a larger number than us
if my_bits < your_bits {
return $name(ret);
}
// Bitwise long division
let mut shift = my_bits - your_bits;
shift_copy = shift_copy << shift;
loop {
if sub_copy >= shift_copy {
ret[shift / 64] |= 1 << (shift % 64);
sub_copy = sub_copy - shift_copy;
}
shift_copy = shift_copy >> 1;
if shift == 0 { break; }
shift -= 1;
}
$name(ret)
self.div_rem(other).0
}
}
@ -170,8 +178,7 @@ macro_rules! construct_uint {
type Output = $name;
fn rem(self, other: $name) -> $name {
let times = self / other;
self - (times * other)
self.div_rem(other).1
}
}
@ -568,4 +575,3 @@ mod tests {
assert_eq!(end2.ok(), Some(start2));
}
}