Skip to content

Commit

Permalink
implement Stein's algorithm for gcd
Browse files Browse the repository at this point in the history
same asymptotic complexity as euclidean but faster
thanks to bitshifts and subtractions rather than division
  • Loading branch information
Emerentius committed Jan 7, 2018
1 parent 90fa4ff commit 9cd1443
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
48 changes: 41 additions & 7 deletions src/biguint.rs
Expand Up @@ -941,16 +941,38 @@ impl Integer for BigUint {
///
/// The result is always positive.
#[inline]
fn gcd(&self, other: &BigUint) -> BigUint {
// Use Euclid's algorithm
fn gcd(&self, other: &Self) -> Self {
// Stein's algorithm
if self.is_zero() {
return (*other).clone();
}
if other.is_zero() {
return (*self).clone();
}
let mut m = (*self).clone();
let mut n = (*other).clone();
while !m.is_zero() {
let temp = m;
m = n % &temp;
n = temp;

// find common factors of 2
let shift = ::core::cmp::min(
n.trailing_zeros(),
m.trailing_zeros()
);

// divide m and n by 2 until odd
// m inside loop
n >>= n.trailing_zeros();

loop {
m >>= m.trailing_zeros();
if n > m { ::core::mem::swap(&mut n, &mut m) }
m -= &n;

if m.is_zero() {
break
}
}
return n;

n << shift
}

/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
Expand Down Expand Up @@ -1608,6 +1630,18 @@ impl BigUint {
return self.data.len() * big_digit::BITS - zeros as usize;
}

// self is assumed to be normalized
fn trailing_zeros(&self) -> usize {
let mut zeros = 0;
for &bigdigit in self.data.iter() {
zeros += bigdigit.trailing_zeros() as usize;
if bigdigit != 0 {
break
}
}
zeros
}

/// Strips off trailing zero bigdigits - comparisons require the last element in the vector to
/// be nonzero.
#[inline]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Expand Up @@ -78,6 +78,7 @@ extern crate rand;
extern crate rustc_serialize;
#[cfg(feature = "serde")]
extern crate serde;
extern crate core;

extern crate num_integer as integer;
extern crate num_traits as traits;
Expand Down

0 comments on commit 9cd1443

Please sign in to comment.