about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-09 19:52:08 -0700
committerbors <bors@rust-lang.org>2014-06-09 19:52:08 -0700
commit5bf5cc605fd2732fa35b284a4401bfaa899dcae2 (patch)
tree8b059260425c91d5220cef2bfed585e4e7d72f94 /src
parent907d96187641d8a018af2b73239723c66b011f71 (diff)
parent0eb858b4c913b531ae5ac915abbbe579b49b9df4 (diff)
downloadrust-5bf5cc605fd2732fa35b284a4401bfaa899dcae2.tar.gz
rust-5bf5cc605fd2732fa35b284a4401bfaa899dcae2.zip
auto merge of #14694 : aochagavia/rust/num-cleanup, r=alexcrichton
Diffstat (limited to 'src')
-rw-r--r--src/libnum/bigint.rs63
-rw-r--r--src/libnum/integer.rs411
-rw-r--r--src/libnum/lib.rs408
3 files changed, 445 insertions, 437 deletions
diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs
index 67501c9795d..0933301970d 100644
--- a/src/libnum/bigint.rs
+++ b/src/libnum/bigint.rs
@@ -17,18 +17,16 @@ A `BigInt` is a combination of `BigUint` and `Sign`.
 */
 
 use Integer;
+use rand::Rng;
 
-use std::cmp;
+use std::{cmp, fmt};
 use std::default::Default;
-use std::fmt;
 use std::from_str::FromStr;
 use std::num::CheckedDiv;
 use std::num::{Bitwise, ToPrimitive, FromPrimitive};
 use std::num::{Zero, One, ToStrRadix, FromStrRadix};
-use rand::Rng;
 use std::string::String;
-use std::uint;
-use std::{i64, u64};
+use std::{uint, i64, u64};
 
 /**
 A `BigDigit` is a `BigUint`'s composing element.
@@ -94,7 +92,7 @@ impl Eq for BigUint {}
 impl PartialOrd for BigUint {
     #[inline]
     fn lt(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
+        self.cmp(other) == Less
     }
 }
 
@@ -115,7 +113,7 @@ impl Ord for BigUint {
 
 impl Default for BigUint {
     #[inline]
-    fn default() -> BigUint { BigUint::new(Vec::new()) }
+    fn default() -> BigUint { Zero::zero() }
 }
 
 impl fmt::Show for BigUint {
@@ -605,7 +603,7 @@ impl_to_biguint!(u64,  FromPrimitive::from_u64)
 
 impl ToStrRadix for BigUint {
     fn to_str_radix(&self, radix: uint) -> String {
-        assert!(1 < radix && radix <= 16);
+        assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
         let (base, max_len) = get_radix_base(radix);
         if base == BigDigit::base {
             return fill_concat(self.data.as_slice(), radix, max_len)
@@ -645,8 +643,7 @@ impl ToStrRadix for BigUint {
 impl FromStrRadix for BigUint {
     /// Creates and initializes a `BigUint`.
     #[inline]
-    fn from_str_radix(s: &str, radix: uint)
-        -> Option<BigUint> {
+    fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
         BigUint::parse_bytes(s.as_bytes(), radix)
     }
 }
@@ -656,14 +653,11 @@ impl BigUint {
     ///
     /// The digits are be in base 2^32.
     #[inline]
-    pub fn new(v: Vec<BigDigit>) -> BigUint {
+    pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
         // omit trailing zeros
-        let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
-
-        if new_len == v.len() { return BigUint { data: v }; }
-        let mut v = v;
-        v.truncate(new_len);
-        return BigUint { data: v };
+        let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
+        digits.truncate(new_len);
+        BigUint { data: digits }
     }
 
     /// Creates and initializes a `BigUint`.
@@ -671,7 +665,7 @@ impl BigUint {
     /// The digits are be in base 2^32.
     #[inline]
     pub fn from_slice(slice: &[BigDigit]) -> BigUint {
-        return BigUint::new(Vec::from_slice(slice));
+        BigUint::new(Vec::from_slice(slice))
     }
 
     /// Creates and initializes a `BigUint`.
@@ -768,7 +762,6 @@ impl BigUint {
 // `DoubleBigDigit` size dependent
 #[inline]
 fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
-    assert!(1 < radix && radix <= 16);
     match radix {
         2  => (4294967296, 32),
         3  => (3486784401, 20),
@@ -785,7 +778,7 @@ fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
         14 => (1475789056, 8),
         15 => (2562890625, 8),
         16 => (4294967296, 8),
-        _  => fail!()
+        _  => fail!("The radix must be within (1, 16]")
     }
 }
 
@@ -815,7 +808,7 @@ pub struct BigInt {
 impl PartialEq for BigInt {
     #[inline]
     fn eq(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Equal => true, _ => false }
+        self.cmp(other) == Equal
     }
 }
 
@@ -824,7 +817,7 @@ impl Eq for BigInt {}
 impl PartialOrd for BigInt {
     #[inline]
     fn lt(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
+        self.cmp(other) == Less
     }
 }
 
@@ -844,7 +837,7 @@ impl Ord for BigInt {
 
 impl Default for BigInt {
     #[inline]
-    fn default() -> BigInt { BigInt::new(Zero, Vec::new()) }
+    fn default() -> BigInt { Zero::zero() }
 }
 
 impl fmt::Show for BigInt {
@@ -929,8 +922,7 @@ impl Add<BigInt, BigInt> for BigInt {
         match (self.sign, other.sign) {
             (Zero, _)      => other.clone(),
             (_,    Zero)   => self.clone(),
-            (Plus, Plus)   => BigInt::from_biguint(Plus,
-                                                   self.data + other.data),
+            (Plus, Plus)   => BigInt::from_biguint(Plus, self.data + other.data),
             (Plus, Minus)  => self - (-*other),
             (Minus, Plus)  => other - (-*self),
             (Minus, Minus) => -((-self) + (-*other))
@@ -975,7 +967,7 @@ impl Div<BigInt, BigInt> for BigInt {
     #[inline]
     fn div(&self, other: &BigInt) -> BigInt {
         let (q, _) = self.div_rem(other);
-        return q;
+        q
     }
 }
 
@@ -983,7 +975,7 @@ impl Rem<BigInt, BigInt> for BigInt {
     #[inline]
     fn rem(&self, other: &BigInt) -> BigInt {
         let (_, r) = self.div_rem(other);
-        return r;
+        r
     }
 }
 
@@ -1045,13 +1037,13 @@ impl Integer for BigInt {
     #[inline]
     fn div_floor(&self, other: &BigInt) -> BigInt {
         let (d, _) = self.div_mod_floor(other);
-        return d;
+        d
     }
 
     #[inline]
     fn mod_floor(&self, other: &BigInt) -> BigInt {
         let (_, m) = self.div_mod_floor(other);
-        return m;
+        m
     }
 
     fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
@@ -1265,7 +1257,7 @@ impl<R: Rng> RandBigInt for R {
             let final_digit: BigDigit = self.gen();
             data.push(final_digit >> (BigDigit::bits - rem));
         }
-        return BigUint::new(data);
+        BigUint::new(data)
     }
 
     fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
@@ -1287,7 +1279,7 @@ impl<R: Rng> RandBigInt for R {
         } else {
             Minus
         };
-        return BigInt::from_biguint(sign, biguint);
+        BigInt::from_biguint(sign, biguint)
     }
 
     fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
@@ -1322,8 +1314,8 @@ impl BigInt {
     ///
     /// The digits are be in base 2^32.
     #[inline]
-    pub fn new(sign: Sign, v: Vec<BigDigit>) -> BigInt {
-        BigInt::from_biguint(sign, BigUint::new(v))
+    pub fn new(sign: Sign, digits: Vec<BigDigit>) -> BigInt {
+        BigInt::from_biguint(sign, BigUint::new(digits))
     }
 
     /// Creates and initializes a `BigInt`.
@@ -1334,7 +1326,7 @@ impl BigInt {
         if sign == Zero || data.is_zero() {
             return BigInt { sign: Zero, data: Zero::zero() };
         }
-        return BigInt { sign: sign, data: data };
+        BigInt { sign: sign, data: data }
     }
 
     /// Creates and initializes a `BigInt`.
@@ -1344,8 +1336,7 @@ impl BigInt {
     }
 
     /// Creates and initializes a `BigInt`.
-    pub fn parse_bytes(buf: &[u8], radix: uint)
-        -> Option<BigInt> {
+    pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
         if buf.is_empty() { return None; }
         let mut sign  = Plus;
         let mut start = 0;
diff --git a/src/libnum/integer.rs b/src/libnum/integer.rs
new file mode 100644
index 00000000000..d958d40d3d1
--- /dev/null
+++ b/src/libnum/integer.rs
@@ -0,0 +1,411 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Integer trait and functions
+
+pub trait Integer: Num + PartialOrd
+                 + Div<Self, Self>
+                 + Rem<Self, Self> {
+    /// Simultaneous truncated integer division and modulus
+    #[inline]
+    fn div_rem(&self, other: &Self) -> (Self, Self) {
+        (*self / *other, *self % *other)
+    }
+
+    /// Floored integer division
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// assert!(( 8i).div_floor(& 3) ==  2);
+    /// assert!(( 8i).div_floor(&-3) == -3);
+    /// assert!((-8i).div_floor(& 3) == -3);
+    /// assert!((-8i).div_floor(&-3) ==  2);
+    ///
+    /// assert!(( 1i).div_floor(& 2) ==  0);
+    /// assert!(( 1i).div_floor(&-2) == -1);
+    /// assert!((-1i).div_floor(& 2) == -1);
+    /// assert!((-1i).div_floor(&-2) ==  0);
+    /// ~~~
+    fn div_floor(&self, other: &Self) -> Self;
+
+    /// Floored integer modulo, satisfying:
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// # let n = 1i; let d = 1i;
+    /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
+    /// ~~~
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// assert!(( 8i).mod_floor(& 3) ==  2);
+    /// assert!(( 8i).mod_floor(&-3) == -1);
+    /// assert!((-8i).mod_floor(& 3) ==  1);
+    /// assert!((-8i).mod_floor(&-3) == -2);
+    ///
+    /// assert!(( 1i).mod_floor(& 2) ==  1);
+    /// assert!(( 1i).mod_floor(&-2) == -1);
+    /// assert!((-1i).mod_floor(& 2) ==  1);
+    /// assert!((-1i).mod_floor(&-2) == -1);
+    /// ~~~
+    fn mod_floor(&self, other: &Self) -> Self;
+
+    /// Simultaneous floored integer division and modulus
+    fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
+        (self.div_floor(other), self.mod_floor(other))
+    }
+
+    /// Greatest Common Divisor (GCD)
+    fn gcd(&self, other: &Self) -> Self;
+
+    /// Lowest Common Multiple (LCM)
+    fn lcm(&self, other: &Self) -> Self;
+
+    /// Returns `true` if `other` divides evenly into `self`
+    fn divides(&self, other: &Self) -> bool;
+
+    /// Returns `true` if the number is even
+    fn is_even(&self) -> bool;
+
+    /// Returns `true` if the number is odd
+    fn is_odd(&self) -> bool;
+}
+
+/// Simultaneous integer division and modulus
+#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
+/// Floored integer division
+#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
+/// Floored integer modulus
+#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
+/// Simultaneous floored integer division and modulus
+#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
+
+/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
+/// result is always positive.
+#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
+/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
+#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
+
+macro_rules! impl_integer_for_int {
+    ($T:ty, $test_mod:ident) => (
+        impl Integer for $T {
+            /// Floored integer division
+            #[inline]
+            fn div_floor(&self, other: &$T) -> $T {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match self.div_rem(other) {
+                    (d, r) if (r > 0 && *other < 0)
+                           || (r < 0 && *other > 0) => d - 1,
+                    (d, _)                          => d,
+                }
+            }
+
+            /// Floored integer modulo
+            #[inline]
+            fn mod_floor(&self, other: &$T) -> $T {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match *self % *other {
+                    r if (r > 0 && *other < 0)
+                      || (r < 0 && *other > 0) => r + *other,
+                    r                          => r,
+                }
+            }
+
+            /// Calculates `div_floor` and `mod_floor` simultaneously
+            #[inline]
+            fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match self.div_rem(other) {
+                    (d, r) if (r > 0 && *other < 0)
+                           || (r < 0 && *other > 0) => (d - 1, r + *other),
+                    (d, r)                          => (d, r),
+                }
+            }
+
+            /// Calculates the Greatest Common Divisor (GCD) of the number and
+            /// `other`. The result is always positive.
+            #[inline]
+            fn gcd(&self, other: &$T) -> $T {
+                // Use Euclid's algorithm
+                let mut m = *self;
+                let mut n = *other;
+                while m != 0 {
+                    let temp = m;
+                    m = n % temp;
+                    n = temp;
+                }
+                n.abs()
+            }
+
+            /// Calculates the Lowest Common Multiple (LCM) of the number and
+            /// `other`.
+            #[inline]
+            fn lcm(&self, other: &$T) -> $T {
+                // should not have to recalculate abs
+                ((*self * *other) / self.gcd(other)).abs()
+            }
+
+            /// Returns `true` if the number can be divided by `other` without
+            /// leaving a remainder
+            #[inline]
+            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+            /// Returns `true` if the number is divisible by `2`
+            #[inline]
+            fn is_even(&self) -> bool { self & 1 == 0 }
+
+            /// Returns `true` if the number is not divisible by `2`
+            #[inline]
+            fn is_odd(&self) -> bool { !self.is_even() }
+        }
+
+        #[cfg(test)]
+        mod $test_mod {
+            use Integer;
+
+            /// Checks that the division rule holds for:
+            ///
+            /// - `n`: numerator (dividend)
+            /// - `d`: denominator (divisor)
+            /// - `qr`: quotient and remainder
+            #[cfg(test)]
+            fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
+                assert_eq!(d * q + r, n);
+            }
+
+            #[test]
+            fn test_div_rem() {
+                fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
+                    let (n,d) = nd;
+                    let separate_div_rem = (n / d, n % d);
+                    let combined_div_rem = n.div_rem(&d);
+
+                    assert_eq!(separate_div_rem, qr);
+                    assert_eq!(combined_div_rem, qr);
+
+                    test_division_rule(nd, separate_div_rem);
+                    test_division_rule(nd, combined_div_rem);
+                }
+
+                test_nd_dr(( 8,  3), ( 2,  2));
+                test_nd_dr(( 8, -3), (-2,  2));
+                test_nd_dr((-8,  3), (-2, -2));
+                test_nd_dr((-8, -3), ( 2, -2));
+
+                test_nd_dr(( 1,  2), ( 0,  1));
+                test_nd_dr(( 1, -2), ( 0,  1));
+                test_nd_dr((-1,  2), ( 0, -1));
+                test_nd_dr((-1, -2), ( 0, -1));
+            }
+
+            #[test]
+            fn test_div_mod_floor() {
+                fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
+                    let (n,d) = nd;
+                    let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+                    let combined_div_mod_floor = n.div_mod_floor(&d);
+
+                    assert_eq!(separate_div_mod_floor, dm);
+                    assert_eq!(combined_div_mod_floor, dm);
+
+                    test_division_rule(nd, separate_div_mod_floor);
+                    test_division_rule(nd, combined_div_mod_floor);
+                }
+
+                test_nd_dm(( 8,  3), ( 2,  2));
+                test_nd_dm(( 8, -3), (-3, -1));
+                test_nd_dm((-8,  3), (-3,  1));
+                test_nd_dm((-8, -3), ( 2, -2));
+
+                test_nd_dm(( 1,  2), ( 0,  1));
+                test_nd_dm(( 1, -2), (-1, -1));
+                test_nd_dm((-1,  2), (-1,  1));
+                test_nd_dm((-1, -2), ( 0, -1));
+            }
+
+            #[test]
+            fn test_gcd() {
+                assert_eq!((10 as $T).gcd(&2), 2 as $T);
+                assert_eq!((10 as $T).gcd(&3), 1 as $T);
+                assert_eq!((0 as $T).gcd(&3), 3 as $T);
+                assert_eq!((3 as $T).gcd(&3), 3 as $T);
+                assert_eq!((56 as $T).gcd(&42), 14 as $T);
+                assert_eq!((3 as $T).gcd(&-3), 3 as $T);
+                assert_eq!((-6 as $T).gcd(&3), 3 as $T);
+                assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
+            }
+
+            #[test]
+            fn test_lcm() {
+                assert_eq!((1 as $T).lcm(&0), 0 as $T);
+                assert_eq!((0 as $T).lcm(&1), 0 as $T);
+                assert_eq!((1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((-1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((1 as $T).lcm(&-1), 1 as $T);
+                assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
+                assert_eq!((8 as $T).lcm(&9), 72 as $T);
+                assert_eq!((11 as $T).lcm(&5), 55 as $T);
+            }
+
+            #[test]
+            fn test_even() {
+                assert_eq!((-4 as $T).is_even(), true);
+                assert_eq!((-3 as $T).is_even(), false);
+                assert_eq!((-2 as $T).is_even(), true);
+                assert_eq!((-1 as $T).is_even(), false);
+                assert_eq!((0 as $T).is_even(), true);
+                assert_eq!((1 as $T).is_even(), false);
+                assert_eq!((2 as $T).is_even(), true);
+                assert_eq!((3 as $T).is_even(), false);
+                assert_eq!((4 as $T).is_even(), true);
+            }
+
+            #[test]
+            fn test_odd() {
+                assert_eq!((-4 as $T).is_odd(), false);
+                assert_eq!((-3 as $T).is_odd(), true);
+                assert_eq!((-2 as $T).is_odd(), false);
+                assert_eq!((-1 as $T).is_odd(), true);
+                assert_eq!((0 as $T).is_odd(), false);
+                assert_eq!((1 as $T).is_odd(), true);
+                assert_eq!((2 as $T).is_odd(), false);
+                assert_eq!((3 as $T).is_odd(), true);
+                assert_eq!((4 as $T).is_odd(), false);
+            }
+        }
+    )
+}
+
+impl_integer_for_int!(i8,   test_integer_i8)
+impl_integer_for_int!(i16,  test_integer_i16)
+impl_integer_for_int!(i32,  test_integer_i32)
+impl_integer_for_int!(i64,  test_integer_i64)
+impl_integer_for_int!(int,  test_integer_int)
+
+macro_rules! impl_integer_for_uint {
+    ($T:ty, $test_mod:ident) => (
+        impl Integer for $T {
+            /// Unsigned integer division. Returns the same result as `div` (`/`).
+            #[inline]
+            fn div_floor(&self, other: &$T) -> $T { *self / *other }
+
+            /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+            #[inline]
+            fn mod_floor(&self, other: &$T) -> $T { *self % *other }
+
+            /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+            #[inline]
+            fn gcd(&self, other: &$T) -> $T {
+                // Use Euclid's algorithm
+                let mut m = *self;
+                let mut n = *other;
+                while m != 0 {
+                    let temp = m;
+                    m = n % temp;
+                    n = temp;
+                }
+                n
+            }
+
+            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+            #[inline]
+            fn lcm(&self, other: &$T) -> $T {
+                (*self * *other) / self.gcd(other)
+            }
+
+            /// Returns `true` if the number can be divided by `other` without leaving a remainder
+            #[inline]
+            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+            /// Returns `true` if the number is divisible by `2`
+            #[inline]
+            fn is_even(&self) -> bool { self & 1 == 0 }
+
+            /// Returns `true` if the number is not divisible by `2`
+            #[inline]
+            fn is_odd(&self) -> bool { !self.is_even() }
+        }
+
+        #[cfg(test)]
+        mod $test_mod {
+            use Integer;
+
+            #[test]
+            fn test_div_mod_floor() {
+                assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
+                assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
+                assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
+                assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
+                assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
+                assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
+                assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
+                assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
+                assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
+            }
+
+            #[test]
+            fn test_gcd() {
+                assert_eq!((10 as $T).gcd(&2), 2 as $T);
+                assert_eq!((10 as $T).gcd(&3), 1 as $T);
+                assert_eq!((0 as $T).gcd(&3), 3 as $T);
+                assert_eq!((3 as $T).gcd(&3), 3 as $T);
+                assert_eq!((56 as $T).gcd(&42), 14 as $T);
+            }
+
+            #[test]
+            fn test_lcm() {
+                assert_eq!((1 as $T).lcm(&0), 0 as $T);
+                assert_eq!((0 as $T).lcm(&1), 0 as $T);
+                assert_eq!((1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((8 as $T).lcm(&9), 72 as $T);
+                assert_eq!((11 as $T).lcm(&5), 55 as $T);
+                assert_eq!((99 as $T).lcm(&17), 1683 as $T);
+            }
+
+            #[test]
+            fn test_divides() {
+                assert!((6 as $T).divides(&(6 as $T)));
+                assert!((6 as $T).divides(&(3 as $T)));
+                assert!((6 as $T).divides(&(1 as $T)));
+            }
+
+            #[test]
+            fn test_even() {
+                assert_eq!((0 as $T).is_even(), true);
+                assert_eq!((1 as $T).is_even(), false);
+                assert_eq!((2 as $T).is_even(), true);
+                assert_eq!((3 as $T).is_even(), false);
+                assert_eq!((4 as $T).is_even(), true);
+            }
+
+            #[test]
+            fn test_odd() {
+                assert_eq!((0 as $T).is_odd(), false);
+                assert_eq!((1 as $T).is_odd(), true);
+                assert_eq!((2 as $T).is_odd(), false);
+                assert_eq!((3 as $T).is_odd(), true);
+                assert_eq!((4 as $T).is_odd(), false);
+            }
+        }
+    )
+}
+
+impl_integer_for_uint!(u8,   test_integer_u8)
+impl_integer_for_uint!(u16,  test_integer_u16)
+impl_integer_for_uint!(u32,  test_integer_u32)
+impl_integer_for_uint!(u64,  test_integer_u64)
+impl_integer_for_uint!(uint, test_integer_uint)
diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs
index fae21e80f30..709882c87ce 100644
--- a/src/libnum/lib.rs
+++ b/src/libnum/lib.rs
@@ -57,406 +57,12 @@
 
 extern crate rand;
 
+pub use bigint::{BigInt, BigUint};
+pub use rational::{Rational, BigRational};
+pub use complex::Complex;
+pub use integer::Integer;
+
 pub mod bigint;
-pub mod rational;
 pub mod complex;
-
-pub trait Integer: Num + PartialOrd
-                 + Div<Self, Self>
-                 + Rem<Self, Self> {
-    /// Simultaneous truncated integer division and modulus
-    #[inline]
-    fn div_rem(&self, other: &Self) -> (Self, Self) {
-        (*self / *other, *self % *other)
-    }
-
-    /// Floored integer division
-    ///
-    /// # Examples
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// assert!(( 8i).div_floor(& 3) ==  2);
-    /// assert!(( 8i).div_floor(&-3) == -3);
-    /// assert!((-8i).div_floor(& 3) == -3);
-    /// assert!((-8i).div_floor(&-3) ==  2);
-    ///
-    /// assert!(( 1i).div_floor(& 2) ==  0);
-    /// assert!(( 1i).div_floor(&-2) == -1);
-    /// assert!((-1i).div_floor(& 2) == -1);
-    /// assert!((-1i).div_floor(&-2) ==  0);
-    /// ~~~
-    fn div_floor(&self, other: &Self) -> Self;
-
-    /// Floored integer modulo, satisfying:
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// # let n = 1i; let d = 1i;
-    /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
-    /// ~~~
-    ///
-    /// # Examples
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// assert!(( 8i).mod_floor(& 3) ==  2);
-    /// assert!(( 8i).mod_floor(&-3) == -1);
-    /// assert!((-8i).mod_floor(& 3) ==  1);
-    /// assert!((-8i).mod_floor(&-3) == -2);
-    ///
-    /// assert!(( 1i).mod_floor(& 2) ==  1);
-    /// assert!(( 1i).mod_floor(&-2) == -1);
-    /// assert!((-1i).mod_floor(& 2) ==  1);
-    /// assert!((-1i).mod_floor(&-2) == -1);
-    /// ~~~
-    fn mod_floor(&self, other: &Self) -> Self;
-
-    /// Simultaneous floored integer division and modulus
-    fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
-        (self.div_floor(other), self.mod_floor(other))
-    }
-
-    /// Greatest Common Divisor (GCD)
-    fn gcd(&self, other: &Self) -> Self;
-
-    /// Lowest Common Multiple (LCM)
-    fn lcm(&self, other: &Self) -> Self;
-
-    /// Returns `true` if `other` divides evenly into `self`
-    fn divides(&self, other: &Self) -> bool;
-
-    /// Returns `true` if the number is even
-    fn is_even(&self) -> bool;
-
-    /// Returns `true` if the number is odd
-    fn is_odd(&self) -> bool;
-}
-
-/// Simultaneous integer division and modulus
-#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
-/// Floored integer division
-#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
-/// Floored integer modulus
-#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
-/// Simultaneous floored integer division and modulus
-#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
-
-/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
-/// result is always positive.
-#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
-/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
-#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
-
-macro_rules! impl_integer_for_int {
-    ($T:ty, $test_mod:ident) => (
-        impl Integer for $T {
-            /// Floored integer division
-            #[inline]
-            fn div_floor(&self, other: &$T) -> $T {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match self.div_rem(other) {
-                    (d, r) if (r > 0 && *other < 0)
-                           || (r < 0 && *other > 0) => d - 1,
-                    (d, _)                          => d,
-                }
-            }
-
-            /// Floored integer modulo
-            #[inline]
-            fn mod_floor(&self, other: &$T) -> $T {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match *self % *other {
-                    r if (r > 0 && *other < 0)
-                      || (r < 0 && *other > 0) => r + *other,
-                    r                          => r,
-                }
-            }
-
-            /// Calculates `div_floor` and `mod_floor` simultaneously
-            #[inline]
-            fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match self.div_rem(other) {
-                    (d, r) if (r > 0 && *other < 0)
-                           || (r < 0 && *other > 0) => (d - 1, r + *other),
-                    (d, r)                          => (d, r),
-                }
-            }
-
-            /// Calculates the Greatest Common Divisor (GCD) of the number and
-            /// `other`. The result is always positive.
-            #[inline]
-            fn gcd(&self, other: &$T) -> $T {
-                // Use Euclid's algorithm
-                let mut m = *self;
-                let mut n = *other;
-                while m != 0 {
-                    let temp = m;
-                    m = n % temp;
-                    n = temp;
-                }
-                n.abs()
-            }
-
-            /// Calculates the Lowest Common Multiple (LCM) of the number and
-            /// `other`.
-            #[inline]
-            fn lcm(&self, other: &$T) -> $T {
-                // should not have to recalculate abs
-                ((*self * *other) / self.gcd(other)).abs()
-            }
-
-            /// Returns `true` if the number can be divided by `other` without
-            /// leaving a remainder
-            #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
-            /// Returns `true` if the number is divisible by `2`
-            #[inline]
-            fn is_even(&self) -> bool { self & 1 == 0 }
-
-            /// Returns `true` if the number is not divisible by `2`
-            #[inline]
-            fn is_odd(&self) -> bool { !self.is_even() }
-        }
-
-        #[cfg(test)]
-        mod $test_mod {
-            use Integer;
-
-            /// Checks that the division rule holds for:
-            ///
-            /// - `n`: numerator (dividend)
-            /// - `d`: denominator (divisor)
-            /// - `qr`: quotient and remainder
-            #[cfg(test)]
-            fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
-                assert_eq!(d * q + r, n);
-            }
-
-            #[test]
-            fn test_div_rem() {
-                fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
-                    let (n,d) = nd;
-                    let separate_div_rem = (n / d, n % d);
-                    let combined_div_rem = n.div_rem(&d);
-
-                    assert_eq!(separate_div_rem, qr);
-                    assert_eq!(combined_div_rem, qr);
-
-                    test_division_rule(nd, separate_div_rem);
-                    test_division_rule(nd, combined_div_rem);
-                }
-
-                test_nd_dr(( 8,  3), ( 2,  2));
-                test_nd_dr(( 8, -3), (-2,  2));
-                test_nd_dr((-8,  3), (-2, -2));
-                test_nd_dr((-8, -3), ( 2, -2));
-
-                test_nd_dr(( 1,  2), ( 0,  1));
-                test_nd_dr(( 1, -2), ( 0,  1));
-                test_nd_dr((-1,  2), ( 0, -1));
-                test_nd_dr((-1, -2), ( 0, -1));
-            }
-
-            #[test]
-            fn test_div_mod_floor() {
-                fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
-                    let (n,d) = nd;
-                    let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
-                    let combined_div_mod_floor = n.div_mod_floor(&d);
-
-                    assert_eq!(separate_div_mod_floor, dm);
-                    assert_eq!(combined_div_mod_floor, dm);
-
-                    test_division_rule(nd, separate_div_mod_floor);
-                    test_division_rule(nd, combined_div_mod_floor);
-                }
-
-                test_nd_dm(( 8,  3), ( 2,  2));
-                test_nd_dm(( 8, -3), (-3, -1));
-                test_nd_dm((-8,  3), (-3,  1));
-                test_nd_dm((-8, -3), ( 2, -2));
-
-                test_nd_dm(( 1,  2), ( 0,  1));
-                test_nd_dm(( 1, -2), (-1, -1));
-                test_nd_dm((-1,  2), (-1,  1));
-                test_nd_dm((-1, -2), ( 0, -1));
-            }
-
-            #[test]
-            fn test_gcd() {
-                assert_eq!((10 as $T).gcd(&2), 2 as $T);
-                assert_eq!((10 as $T).gcd(&3), 1 as $T);
-                assert_eq!((0 as $T).gcd(&3), 3 as $T);
-                assert_eq!((3 as $T).gcd(&3), 3 as $T);
-                assert_eq!((56 as $T).gcd(&42), 14 as $T);
-                assert_eq!((3 as $T).gcd(&-3), 3 as $T);
-                assert_eq!((-6 as $T).gcd(&3), 3 as $T);
-                assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
-            }
-
-            #[test]
-            fn test_lcm() {
-                assert_eq!((1 as $T).lcm(&0), 0 as $T);
-                assert_eq!((0 as $T).lcm(&1), 0 as $T);
-                assert_eq!((1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((-1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((1 as $T).lcm(&-1), 1 as $T);
-                assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
-                assert_eq!((8 as $T).lcm(&9), 72 as $T);
-                assert_eq!((11 as $T).lcm(&5), 55 as $T);
-            }
-
-            #[test]
-            fn test_even() {
-                assert_eq!((-4 as $T).is_even(), true);
-                assert_eq!((-3 as $T).is_even(), false);
-                assert_eq!((-2 as $T).is_even(), true);
-                assert_eq!((-1 as $T).is_even(), false);
-                assert_eq!((0 as $T).is_even(), true);
-                assert_eq!((1 as $T).is_even(), false);
-                assert_eq!((2 as $T).is_even(), true);
-                assert_eq!((3 as $T).is_even(), false);
-                assert_eq!((4 as $T).is_even(), true);
-            }
-
-            #[test]
-            fn test_odd() {
-                assert_eq!((-4 as $T).is_odd(), false);
-                assert_eq!((-3 as $T).is_odd(), true);
-                assert_eq!((-2 as $T).is_odd(), false);
-                assert_eq!((-1 as $T).is_odd(), true);
-                assert_eq!((0 as $T).is_odd(), false);
-                assert_eq!((1 as $T).is_odd(), true);
-                assert_eq!((2 as $T).is_odd(), false);
-                assert_eq!((3 as $T).is_odd(), true);
-                assert_eq!((4 as $T).is_odd(), false);
-            }
-        }
-    )
-}
-
-impl_integer_for_int!(i8,   test_integer_i8)
-impl_integer_for_int!(i16,  test_integer_i16)
-impl_integer_for_int!(i32,  test_integer_i32)
-impl_integer_for_int!(i64,  test_integer_i64)
-impl_integer_for_int!(int,  test_integer_int)
-
-macro_rules! impl_integer_for_uint {
-    ($T:ty, $test_mod:ident) => (
-        impl Integer for $T {
-            /// Unsigned integer division. Returns the same result as `div` (`/`).
-            #[inline]
-            fn div_floor(&self, other: &$T) -> $T { *self / *other }
-
-            /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
-            #[inline]
-            fn mod_floor(&self, other: &$T) -> $T { *self % *other }
-
-            /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
-            #[inline]
-            fn gcd(&self, other: &$T) -> $T {
-                // Use Euclid's algorithm
-                let mut m = *self;
-                let mut n = *other;
-                while m != 0 {
-                    let temp = m;
-                    m = n % temp;
-                    n = temp;
-                }
-                n
-            }
-
-            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
-            #[inline]
-            fn lcm(&self, other: &$T) -> $T {
-                (*self * *other) / self.gcd(other)
-            }
-
-            /// Returns `true` if the number can be divided by `other` without leaving a remainder
-            #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
-            /// Returns `true` if the number is divisible by `2`
-            #[inline]
-            fn is_even(&self) -> bool { self & 1 == 0 }
-
-            /// Returns `true` if the number is not divisible by `2`
-            #[inline]
-            fn is_odd(&self) -> bool { !self.is_even() }
-        }
-
-        #[cfg(test)]
-        mod $test_mod {
-            use Integer;
-
-            #[test]
-            fn test_div_mod_floor() {
-                assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
-                assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
-                assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
-                assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
-                assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
-                assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
-                assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
-                assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
-                assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
-            }
-
-            #[test]
-            fn test_gcd() {
-                assert_eq!((10 as $T).gcd(&2), 2 as $T);
-                assert_eq!((10 as $T).gcd(&3), 1 as $T);
-                assert_eq!((0 as $T).gcd(&3), 3 as $T);
-                assert_eq!((3 as $T).gcd(&3), 3 as $T);
-                assert_eq!((56 as $T).gcd(&42), 14 as $T);
-            }
-
-            #[test]
-            fn test_lcm() {
-                assert_eq!((1 as $T).lcm(&0), 0 as $T);
-                assert_eq!((0 as $T).lcm(&1), 0 as $T);
-                assert_eq!((1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((8 as $T).lcm(&9), 72 as $T);
-                assert_eq!((11 as $T).lcm(&5), 55 as $T);
-                assert_eq!((99 as $T).lcm(&17), 1683 as $T);
-            }
-
-            #[test]
-            fn test_divides() {
-                assert!((6 as $T).divides(&(6 as $T)));
-                assert!((6 as $T).divides(&(3 as $T)));
-                assert!((6 as $T).divides(&(1 as $T)));
-            }
-
-            #[test]
-            fn test_even() {
-                assert_eq!((0 as $T).is_even(), true);
-                assert_eq!((1 as $T).is_even(), false);
-                assert_eq!((2 as $T).is_even(), true);
-                assert_eq!((3 as $T).is_even(), false);
-                assert_eq!((4 as $T).is_even(), true);
-            }
-
-            #[test]
-            fn test_odd() {
-                assert_eq!((0 as $T).is_odd(), false);
-                assert_eq!((1 as $T).is_odd(), true);
-                assert_eq!((2 as $T).is_odd(), false);
-                assert_eq!((3 as $T).is_odd(), true);
-                assert_eq!((4 as $T).is_odd(), false);
-            }
-        }
-    )
-}
-
-impl_integer_for_uint!(u8,   test_integer_u8)
-impl_integer_for_uint!(u16,  test_integer_u16)
-impl_integer_for_uint!(u32,  test_integer_u32)
-impl_integer_for_uint!(u64,  test_integer_u64)
-impl_integer_for_uint!(uint, test_integer_uint)
+pub mod integer;
+pub mod rational;