algo 0.1.9

Algorithms & Data Structure implementations
use std::num::{Zero, One};
use std::ops::{Shl, Shr, BitAnd, BitOr, Add, Sub, Neg, Rem};

pub fn euclid_gcd<T>(mut u: T, mut v: T) -> T
where T: Copy,
      T: Zero,
      T: PartialEq,
      T: PartialOrd,
      T: Rem<Output = T>,
      T: Neg<Output = T>
{
    let mut t;
    let zero = T::zero();
    while v != zero {
        t = u;
        u = v;
        v = t % v;
    }

    if u < zero {
        -u
    } else {
        u
    }
}

pub fn binary_gcd<T>(mut u: T, mut v: T) -> T
where T: Copy,
      T: Zero,
      T: One,
      T: PartialEq,
      T: PartialOrd,
      T: Shl<T, Output = T>,
      T: Shr<T, Output = T>,
      T: BitAnd<Output = T>,
      T: BitOr<Output = T>,
      T: Add<Output = T>,
      T: Sub<Output = T>
{
    if u == v {
        return u;
    }

    let zero = T::zero();
    if u == zero || v == zero {
        return u + v;
    }

    let mut shift = T::zero();
    let one = T::one();

    while ((u | v) & one) == zero {
        u = u >> one;
        v = v >> one;

        shift = shift + one;
    }

    while (u & one) == zero {
        u = u >> one;
    }

    while v != zero {
        while (v & one) == zero {
            v = v >> one;
        }

        if u > v {
            let t = v;
            v = u;
            u = t;
        }

        v = v - u;
    }

    u << shift
}

#[test]
fn test_euclid_zero() {
    assert_eq!(0, euclid_gcd(0, 0));
}

#[test]
fn test_euclid_same() {
    assert_eq!(10, euclid_gcd(10, 10));
}

#[test]
fn test_euclid_simple() {
    assert_eq!(7, euclid_gcd(14, 21));
}

#[test]
fn test_euclid_prime() {
    assert_eq!(1, euclid_gcd(132512537, 132512351));
}
#[test]
fn test_binary_zero() {
    assert_eq!(0, binary_gcd(0, 0));
}

#[test]
fn test_binary_same() {
    assert_eq!(10, binary_gcd(10, 10));
}

#[test]
fn test_binary_simple() {
    assert_eq!(7, binary_gcd(14, 21));
}

#[test]
fn test_binary_prime() {
    assert_eq!(1, binary_gcd(132512537, 132512351));
}

#[bench]
fn bench_euclid_primes(b: &mut ::test::Bencher) {
    b.iter(|| euclid_gcd(132512537, 132512351))
}

#[bench]
fn bench_binary_primes(b: &mut ::test::Bencher) {
    b.iter(|| binary_gcd(132512537, 132512351))
}