-
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
Implement sqrt for BigInt and BigUint #51
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1749,6 +1749,50 @@ impl BigUint { | |
} | ||
acc | ||
} | ||
|
||
/// Finds square root of `self`. | ||
/// | ||
/// The result is the greatest integer less than or equal to the | ||
/// square root of `self`. | ||
pub fn sqrt(&self) -> Self { | ||
let one = BigUint::one(); | ||
let two = BigUint::from(2 as u8); | ||
|
||
// Trivial cases | ||
if self.is_zero() { | ||
return BigUint::zero(); | ||
} | ||
|
||
if self.is_one() { | ||
return one; | ||
} | ||
|
||
// Newton's method to compute the square root of an integer. | ||
// | ||
// Reference: | ||
// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.13 | ||
// | ||
// Set initial guess to something >= floor(sqrt(self)), but as low | ||
// as possible to speed up convergence. | ||
let bit_len = self.len() * big_digit::BITS; | ||
let guess = one.shl(bit_len/2 + 1); | ||
|
||
let mut u = guess; | ||
let mut s: BigUint; | ||
|
||
loop { | ||
s = u; | ||
let q = self.div_floor(&s); | ||
let t: BigUint = &s + &q; | ||
|
||
// Compute the candidate value for next iteration | ||
u = t.div_floor(&two); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason you're using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No reason whatsoever, it just slipped my mind it seems. I replaced the usage of |
||
|
||
if u >= s { break; } | ||
} | ||
|
||
s | ||
} | ||
} | ||
|
||
/// Returns the number of least-significant bits that are zero, | ||
|
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.
We don't need
q
after this, so adding&s + q
by value will let it reuse that memory allocation.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.
Indeed, fixed.