Pārlūkot izejas kodu

Update to 1.0.0-beta (stable only)

Along the way, this commit also rationalizes the traits a bit more.

Moving to stable required vendoring a couple of minor things (notably,
radix formatting).
Aaron Turon 10 gadi atpakaļ
vecāks
revīzija
63c7a25ed9
7 mainītis faili ar 437 papildinājumiem un 396 dzēšanām
  1. 212 166
      src/bigint.rs
  2. 15 17
      src/complex.rs
  3. 5 4
      src/integer.rs
  4. 2 5
      src/iter.rs
  5. 2 3
      src/lib.rs
  6. 48 46
      src/rational.rs
  7. 153 155
      src/traits.rs

+ 212 - 166
src/bigint.rs

@@ -62,12 +62,10 @@ extern crate rustc_serialize;
 
 use Integer;
 
-use core::num::ParseIntError;
-
 use std::default::Default;
 use std::error::Error;
 use std::iter::repeat;
-use std::num::{Int, ToPrimitive, FromPrimitive, FromStrRadix};
+use std::num::ParseIntError;
 use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
 use std::str::{self, FromStr};
 use std::{cmp, fmt, hash, mem};
@@ -77,6 +75,8 @@ use std::{i64, u64};
 use rand::Rng;
 use rustc_serialize::hex::ToHex;
 
+use traits::{ToPrimitive, FromPrimitive, cast};
+
 use {Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Signed, Zero, One};
 use self::Sign::{Minus, NoSign, Plus};
 
@@ -99,7 +99,7 @@ pub mod big_digit {
     pub const BITS: usize = 32;
 
     pub const BASE: DoubleBigDigit = 1 << BITS;
-    const LO_MASK: DoubleBigDigit = (-1 as DoubleBigDigit) >> BITS;
+    const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS;
 
     #[inline]
     fn get_hi(n: DoubleBigDigit) -> BigDigit { (n >> BITS) as BigDigit }
@@ -190,11 +190,47 @@ impl FromStr for BigUint {
 
     #[inline]
     fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> {
-        FromStrRadix::from_str_radix(s, 10)
+        BigUint::from_str_radix(s, 10)
     }
 }
 
-impl Num for BigUint {}
+impl Num for BigUint {
+    type FromStrRadixErr = ParseBigIntError;
+
+    /// Creates and initializes a `BigUint`.
+    #[inline]
+    fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> {
+        let (base, unit_len) = get_radix_base(radix);
+        let base_num = match base.to_biguint() {
+            Some(base_num) => base_num,
+            None => { return Err(ParseBigIntError::Other); }
+        };
+
+        let mut end            = s.len();
+        let mut n: BigUint     = Zero::zero();
+        let mut power: BigUint = One::one();
+        loop {
+            let start = cmp::max(end, unit_len) - unit_len;
+            let d = try!(usize::from_str_radix(&s[start .. end], radix));
+            let d: Option<BigUint> = FromPrimitive::from_usize(d);
+            match d {
+                Some(d) => {
+                    // FIXME(#5992): assignment operator overloads
+                    // n += d * &power;
+                    n = n + d * &power;
+                }
+                None => { return Err(ParseBigIntError::Other); }
+            }
+            if end <= unit_len {
+                return Ok(n);
+            }
+            end -= unit_len;
+            // FIXME(#5992): assignment operator overloads
+            // power *= &base_num;
+            power = power * &base_num;
+        }
+    }
+}
 
 macro_rules! forward_val_val_binop {
     (impl $imp:ident for $res:ty, $method:ident) => {
@@ -264,7 +300,7 @@ impl<'a, 'b> BitOr<&'b BigUint> for &'a BigUint {
         let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) };
         let ored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
             |(ai, bi)| *ai | *bi
-        ).collect();
+                ).collect();
         return BigUint::new(ored);
     }
 }
@@ -279,7 +315,7 @@ impl<'a, 'b> BitXor<&'b BigUint> for &'a BigUint {
         let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) };
         let xored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
             |(ai, bi)| *ai ^ *bi
-        ).collect();
+                ).collect();
         return BigUint::new(xored);
     }
 }
@@ -373,11 +409,11 @@ impl<'a, 'b> Sub<&'b BigUint> for &'a BigUint {
                     + (*ai as DoubleBigDigit)
                     - (*bi as DoubleBigDigit)
                     - (borrow as DoubleBigDigit)
-            );
+                    );
             /*
             hi * (base) + lo == 1*(base) + ai - bi - borrow
             => ai - bi - borrow < 0 <=> hi == 0
-            */
+             */
             borrow = if hi == 0 { 1 } else { 0 };
             lo
         }).collect();
@@ -433,7 +469,7 @@ impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
             let mut prod: Vec<BigDigit> = a.data.iter().map(|ai| {
                 let (hi, lo) = big_digit::from_doublebigdigit(
                     (*ai as DoubleBigDigit) * (n as DoubleBigDigit) + (carry as DoubleBigDigit)
-                );
+                        );
                 carry = hi;
                 lo
             }).collect();
@@ -605,33 +641,33 @@ impl Integer for BigUint {
 
 
         fn div_estimate(a: &BigUint, b: &BigUint, n: usize)
-            -> (BigUint, BigUint, BigUint) {
-            if a.data.len() < n {
-                return (Zero::zero(), Zero::zero(), (*a).clone());
-            }
-
-            let an = &a.data[a.data.len() - n ..];
-            let bn = *b.data.last().unwrap();
-            let mut d = Vec::with_capacity(an.len());
-            let mut carry = 0;
-            for elt in an.iter().rev() {
-                let ai = big_digit::to_doublebigdigit(carry, *elt);
-                let di = ai / (bn as DoubleBigDigit);
-                assert!(di < big_digit::BASE);
-                carry = (ai % (bn as DoubleBigDigit)) as BigDigit;
-                d.push(di as BigDigit)
-            }
-            d.reverse();
-
-            let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
-            if shift == 0 {
-                return (BigUint::new(d), One::one(), (*b).clone());
-            }
-            let one: BigUint = One::one();
-            return (BigUint::new(d).shl_unit(shift),
-                    one.shl_unit(shift),
-                    b.shl_unit(shift));
-        }
+                        -> (BigUint, BigUint, BigUint) {
+                            if a.data.len() < n {
+                                return (Zero::zero(), Zero::zero(), (*a).clone());
+                            }
+
+                            let an = &a.data[a.data.len() - n ..];
+                            let bn = *b.data.last().unwrap();
+                            let mut d = Vec::with_capacity(an.len());
+                            let mut carry = 0;
+                            for elt in an.iter().rev() {
+                                let ai = big_digit::to_doublebigdigit(carry, *elt);
+                                let di = ai / (bn as DoubleBigDigit);
+                                assert!(di < big_digit::BASE);
+                                carry = (ai % (bn as DoubleBigDigit)) as BigDigit;
+                                d.push(di as BigDigit)
+                            }
+                            d.reverse();
+
+                            let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
+                            if shift == 0 {
+                                return (BigUint::new(d), One::one(), (*b).clone());
+                            }
+                            let one: BigUint = One::one();
+                            return (BigUint::new(d).shl_unit(shift),
+                                    one.shl_unit(shift),
+                                    b.shl_unit(shift));
+                        }
     }
 
     /// Calculates the Greatest Common Divisor (GCD) of the number and `other`.
@@ -776,6 +812,58 @@ impl_to_biguint!(u16,  FromPrimitive::from_u16);
 impl_to_biguint!(u32,  FromPrimitive::from_u32);
 impl_to_biguint!(u64,  FromPrimitive::from_u64);
 
+// Cribbed from core/fmt/num.rs
+#[derive(Copy, Clone)]
+pub struct RadixFmt {
+    data: BigDigit,
+    base: u8
+}
+
+impl RadixFmt {
+    fn digit(&self, x: u8) -> u8 {
+        match x {
+            x @  0 ... 9 => b'0' + x,
+            x if x < self.base => b'a' + (x - 10),
+            x => panic!("number not in the range 0..{}: {}", self.base - 1, x),
+        }
+    }
+}
+
+impl fmt::Display for RadixFmt {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // The radix can be as low as 2, so we need a buffer of at least 64
+        // characters for a base 2 number.
+        let mut x = self.data;
+        let zero = 0;
+        let is_positive = x >= zero;
+        let mut buf = [0u8; 64];
+        let mut curr = buf.len();
+        let base = self.base as BigDigit;
+        if is_positive {
+            // Accumulate each digit of the number from the least significant
+            // to the most significant figure.
+            for byte in buf.iter_mut().rev() {
+                let n = x % base;                         // Get the current place value.
+                x = x / base;                             // Deaccumulate the number.
+                *byte = self.digit(cast(n).unwrap());     // Store the digit in the buffer.
+                curr -= 1;
+                if x == zero { break };                   // No more digits left to accumulate.
+            }
+        } else {
+            // Do the same as above, but accounting for two's complement.
+            for byte in buf.iter_mut().rev() {
+                let n = zero - (x % base);                // Get the current place value.
+                x = x / base;                             // Deaccumulate the number.
+                *byte = self.digit(cast(n).unwrap());     // Store the digit in the buffer.
+                curr -= 1;
+                if x == zero { break };                   // No more digits left to accumulate.
+            }
+        }
+        let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
+        f.pad_integral(is_positive, "", buf)
+    }
+}
+
 fn to_str_radix(me: &BigUint, radix: u32) -> String {
     assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
     let (base, max_len) = get_radix_base(radix);
@@ -805,7 +893,7 @@ fn to_str_radix(me: &BigUint, radix: u32) -> String {
         }
         let mut s = String::with_capacity(v.len() * l);
         for n in v.iter().rev() {
-            let ss = fmt::radix(*n as usize, radix as u8).to_string();
+            let ss = format!("{}", RadixFmt { data: *n, base: radix as u8 });
             s.extend(repeat("0").take(l - ss.len()));
             s.push_str(&ss);
         }
@@ -821,44 +909,6 @@ fn to_str_radix_signed(me: &BigInt, radix: u32) -> String {
     }
 }
 
-impl FromStrRadix for BigUint {
-    type Err = ParseBigIntError;
-
-    /// Creates and initializes a `BigUint`.
-    #[inline]
-    fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> {
-        let (base, unit_len) = get_radix_base(radix);
-        let base_num = match base.to_biguint() {
-            Some(base_num) => base_num,
-            None => { return Err(ParseBigIntError::Other); }
-        };
-
-        let mut end            = s.len();
-        let mut n: BigUint     = Zero::zero();
-        let mut power: BigUint = One::one();
-        loop {
-            let start = cmp::max(end, unit_len) - unit_len;
-            let d = try!(FromStrRadix::from_str_radix(&s[start .. end], radix));
-            let d: Option<BigUint> = FromPrimitive::from_usize(d);
-            match d {
-                Some(d) => {
-                    // FIXME(#5992): assignment operator overloads
-                    // n += d * &power;
-                    n = n + d * &power;
-                }
-                None => { return Err(ParseBigIntError::Other); }
-            }
-            if end <= unit_len {
-                return Ok(n);
-            }
-            end -= unit_len;
-            // FIXME(#5992): assignment operator overloads
-            // power *= &base_num;
-            power = power * &base_num;
-        }
-    }
-}
-
 impl BigUint {
     /// Creates and initializes a `BigUint`.
     ///
@@ -961,7 +1011,7 @@ impl BigUint {
     /// ```
     #[inline]
     pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> {
-        str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix).ok())
+        str::from_utf8(buf).ok().and_then(|s| BigUint::from_str_radix(s, radix).ok())
     }
 
     #[inline]
@@ -969,7 +1019,7 @@ impl BigUint {
         if n_unit == 0 || self.is_zero() { return (*self).clone(); }
 
         let mut v = repeat(ZERO_BIG_DIGIT).take(n_unit).collect::<Vec<_>>();
-        v.push_all(&self.data);
+        v.extend(self.data.iter().cloned());
         BigUint::new(v)
     }
 
@@ -1119,11 +1169,27 @@ impl FromStr for BigInt {
 
     #[inline]
     fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
-        FromStrRadix::from_str_radix(s, 10)
+        BigInt::from_str_radix(s, 10)
     }
 }
 
-impl Num for BigInt {}
+impl Num for BigInt {
+    type FromStrRadixErr = ParseBigIntError;
+
+    /// Creates and initializes a BigInt.
+    #[inline]
+    fn from_str_radix(s: &str, radix: u32) -> Result<BigInt, ParseBigIntError> {
+        if s.is_empty() { return Err(ParseBigIntError::Other); }
+        let mut sign  = Plus;
+        let mut start = 0;
+        if s.starts_with("-") {
+            sign  = Minus;
+            start = 1;
+        }
+        BigUint::from_str_radix(&s[start ..], radix)
+            .map(|bu| BigInt::from_biguint(sign, bu))
+    }
+}
 
 impl Shl<usize> for BigInt {
     type Output = BigInt;
@@ -1527,24 +1593,6 @@ impl_to_bigint!(u16,  FromPrimitive::from_u16);
 impl_to_bigint!(u32,  FromPrimitive::from_u32);
 impl_to_bigint!(u64,  FromPrimitive::from_u64);
 
-impl FromStrRadix for BigInt {
-    type Err = ParseBigIntError;
-
-    /// Creates and initializes a BigInt.
-    #[inline]
-    fn from_str_radix(s: &str, radix: u32) -> Result<BigInt, ParseBigIntError> {
-        if s.is_empty() { return Err(ParseBigIntError::Other); }
-        let mut sign  = Plus;
-        let mut start = 0;
-        if s.starts_with("-") {
-            sign  = Minus;
-            start = 1;
-        }
-        FromStrRadix::from_str_radix(&s[start ..], radix)
-            .map(|bu| BigInt::from_biguint(sign, bu))
-    }
-}
-
 pub trait RandBigInt {
     /// Generate a random `BigUint` of the given bit size.
     fn gen_biguint(&mut self, bit_size: usize) -> BigUint;
@@ -1712,7 +1760,7 @@ impl BigInt {
     /// ```
     #[inline]
     pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
-        str::from_utf8(buf).ok().and_then(|s| FromStrRadix::from_str_radix(s, radix).ok())
+        str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok())
     }
 
 
@@ -1785,13 +1833,12 @@ mod biguint_tests {
     use std::cmp::Ordering::{Less, Equal, Greater};
     use std::i64;
     use std::iter::repeat;
-    use std::num::FromStrRadix;
-    use std::num::{ToPrimitive, FromPrimitive};
     use std::str::FromStr;
     use std::u64;
 
     use rand::thread_rng;
-    use {Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
+    use {Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
+    use {ToPrimitive, FromPrimitive};
 
     #[test]
     fn test_from_slice() {
@@ -1803,7 +1850,7 @@ mod biguint_tests {
         check(&[1, 2, 0, 0], &[1, 2]);
         check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
         check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
-        check(&[-1], &[-1]);
+        check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
     }
 
     #[test]
@@ -1833,7 +1880,7 @@ mod biguint_tests {
         assert_eq!(b.to_bytes_be(), [0]);
 
         // Test with leading/trailing zero bytes and a full BigDigit of value 0
-        let b: BigUint = FromStrRadix::from_str_radix("00010000000000000200", 16).unwrap();
+        let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap();
         assert_eq!(b.to_bytes_be(), [1, 0, 0, 0, 0, 0, 0, 2, 0]);
     }
 
@@ -1864,7 +1911,7 @@ mod biguint_tests {
         assert_eq!(b.to_bytes_le(), [0]);
 
         // Test with leading/trailing zero bytes and a full BigDigit of value 0
-        let b: BigUint = FromStrRadix::from_str_radix("00010000000000000200", 16).unwrap();
+        let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap();
         assert_eq!(b.to_bytes_le(), [0, 2, 0, 0, 0, 0, 0, 0, 1]);
     }
 
@@ -1963,7 +2010,7 @@ mod biguint_tests {
     #[test]
     fn test_shl() {
         fn check(s: &str, shift: usize, ans: &str) {
-            let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16).ok();
+            let opt_biguint = BigUint::from_str_radix(s, 16).ok();
             let bu = to_str_radix(&(opt_biguint.unwrap() << shift), 16);
             assert_eq!(bu, ans);
         }
@@ -2084,8 +2131,7 @@ mod biguint_tests {
     #[test]
     fn test_shr() {
         fn check(s: &str, shift: usize, ans: &str) {
-            let opt_biguint: Option<BigUint> =
-                FromStrRadix::from_str_radix(s, 16).ok();
+            let opt_biguint = BigUint::from_str_radix(s, 16).ok();
             let bu = to_str_radix(&(opt_biguint.unwrap() >> shift), 16);
             assert_eq!(bu, ans);
         }
@@ -2199,6 +2245,9 @@ mod biguint_tests {
               "88887777666655554444333322221111");
     }
 
+    const N1: BigDigit = -1i32 as BigDigit;
+    const N2: BigDigit = -2i32 as BigDigit;
+
     // `DoubleBigDigit` size dependent
     #[test]
     fn test_convert_i64() {
@@ -2214,14 +2263,14 @@ mod biguint_tests {
 
         check(BigUint::new(vec!(           )), 0);
         check(BigUint::new(vec!( 1         )), (1 << (0*big_digit::BITS)));
-        check(BigUint::new(vec!(-1         )), (1 << (1*big_digit::BITS)) - 1);
+        check(BigUint::new(vec!(N1         )), (1 << (1*big_digit::BITS)) - 1);
         check(BigUint::new(vec!( 0,  1     )), (1 << (1*big_digit::BITS)));
-        check(BigUint::new(vec!(-1, -1 >> 1)), i64::MAX);
+        check(BigUint::new(vec!(N1, N1 >> 1)), i64::MAX);
 
         assert_eq!(i64::MIN.to_biguint(), None);
-        assert_eq!(BigUint::new(vec!(-1, -1    )).to_i64(), None);
+        assert_eq!(BigUint::new(vec!(N1, N1    )).to_i64(), None);
         assert_eq!(BigUint::new(vec!( 0,  0,  1)).to_i64(), None);
-        assert_eq!(BigUint::new(vec!(-1, -1, -1)).to_i64(), None);
+        assert_eq!(BigUint::new(vec!(N1, N1, N1)).to_i64(), None);
     }
 
     // `DoubleBigDigit` size dependent
@@ -2240,12 +2289,12 @@ mod biguint_tests {
 
         check(BigUint::new(vec!(      )), 0);
         check(BigUint::new(vec!( 1    )), (1 << (0*big_digit::BITS)));
-        check(BigUint::new(vec!(-1    )), (1 << (1*big_digit::BITS)) - 1);
+        check(BigUint::new(vec!(N1    )), (1 << (1*big_digit::BITS)) - 1);
         check(BigUint::new(vec!( 0,  1)), (1 << (1*big_digit::BITS)));
-        check(BigUint::new(vec!(-1, -1)), u64::MAX);
+        check(BigUint::new(vec!(N1, N1)), u64::MAX);
 
         assert_eq!(BigUint::new(vec!( 0,  0,  1)).to_u64(), None);
-        assert_eq!(BigUint::new(vec!(-1, -1, -1)).to_u64(), None);
+        assert_eq!(BigUint::new(vec!(N1, N1, N1)).to_u64(), None);
     }
 
     #[test]
@@ -2266,11 +2315,11 @@ mod biguint_tests {
         (&[],          &[ 1],     &[ 1]),
         (&[ 1],        &[ 1],     &[ 2]),
         (&[ 1],        &[ 1,  1], &[ 2,  1]),
-        (&[ 1],        &[-1],     &[ 0,  1]),
-        (&[ 1],        &[-1, -1], &[ 0,  0, 1]),
-        (&[-1, -1],    &[-1, -1], &[-2, -1, 1]),
-        (&[ 1,  1, 1], &[-1, -1], &[ 0,  1, 2]),
-        (&[ 2,  2, 1], &[-1, -2], &[ 1,  1, 2])
+        (&[ 1],        &[N1],     &[ 0,  1]),
+        (&[ 1],        &[N1, N1], &[ 0,  0, 1]),
+        (&[N1, N1],    &[N1, N1], &[N2, N1, 1]),
+        (&[ 1,  1, 1], &[N1, N1], &[ 0,  1, 2]),
+        (&[ 2,  2, 1], &[N1, N2], &[ 1,  1, 2])
     ];
 
     #[test]
@@ -2317,18 +2366,18 @@ mod biguint_tests {
         (&[ 2],             &[ 3],             &[ 6]),
         (&[ 1],             &[ 1,  1,  1],     &[1, 1,  1]),
         (&[ 1,  2,  3],     &[ 3],             &[ 3,  6,  9]),
-        (&[ 1,  1,  1],     &[-1],             &[-1, -1, -1]),
-        (&[ 1,  2,  3],     &[-1],             &[-1, -2, -2, 2]),
-        (&[ 1,  2,  3,  4], &[-1],             &[-1, -2, -2, -2, 3]),
-        (&[-1],             &[-1],             &[ 1, -2]),
-        (&[-1, -1],         &[-1],             &[ 1, -1, -2]),
-        (&[-1, -1, -1],     &[-1],             &[ 1, -1, -1, -2]),
-        (&[-1, -1, -1, -1], &[-1],             &[ 1, -1, -1, -1, -2]),
+        (&[ 1,  1,  1],     &[N1],             &[N1, N1, N1]),
+        (&[ 1,  2,  3],     &[N1],             &[N1, N2, N2, 2]),
+        (&[ 1,  2,  3,  4], &[N1],             &[N1, N2, N2, N2, 3]),
+        (&[N1],             &[N1],             &[ 1, N2]),
+        (&[N1, N1],         &[N1],             &[ 1, N1, N2]),
+        (&[N1, N1, N1],     &[N1],             &[ 1, N1, N1, N2]),
+        (&[N1, N1, N1, N1], &[N1],             &[ 1, N1, N1, N1, N2]),
         (&[ M/2 + 1],       &[ 2],             &[ 0,  1]),
         (&[0,  M/2 + 1],    &[ 2],             &[ 0,  0,  1]),
         (&[ 1,  2],         &[ 1,  2,  3],     &[1, 4,  7,  6]),
-        (&[-1, -1],         &[-1, -1, -1],     &[1, 0, -1, -2, -1]),
-        (&[-1, -1, -1],     &[-1, -1, -1, -1], &[1, 0,  0, -1, -2, -1, -1]),
+        (&[N1, N1],         &[N1, N1, N1],     &[1, 0, N1, N2, N1]),
+        (&[N1, N1, N1],     &[N1, N1, N1, N1], &[1, 0,  0, N1, N2, N1, N1]),
         (&[ 0,  0,  1],     &[ 1,  2,  3],     &[0, 0,  1,  2,  3]),
         (&[ 0,  0,  1],     &[ 0,  0,  0,  1], &[0, 0,  0,  0,  0,  1])
     ];
@@ -2341,8 +2390,8 @@ mod biguint_tests {
             (&[ 1],        &[ 2], &[],               &[1]),
             (&[ 1,  1],    &[ 2], &[ M/2+1],         &[1]),
             (&[ 1,  1, 1], &[ 2], &[ M/2+1,  M/2+1], &[1]),
-            (&[ 0,  1],    &[-1], &[1],              &[1]),
-            (&[-1, -1],    &[-2], &[2, 1],           &[3])
+            (&[ 0,  1],    &[N1], &[1],              &[1]),
+            (&[N1, N1],    &[N2], &[2, 1],           &[3])
         ];
 
     #[test]
@@ -2600,17 +2649,15 @@ mod biguint_tests {
             for str_pair in rs.iter() {
                 let &(ref radix, ref str) = str_pair;
                 assert_eq!(n,
-                           &FromStrRadix::from_str_radix(str,
-                                                         *radix).unwrap());
+                           &BigUint::from_str_radix(str, *radix).unwrap());
             }
         }
 
-        let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10).ok();
+        let zed = BigUint::from_str_radix("Z", 10).ok();
         assert_eq!(zed, None);
-        let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2).ok();
+        let blank = BigUint::from_str_radix("_", 2).ok();
         assert_eq!(blank, None);
-        let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
-                                                                      10).ok();
+        let minus_one = BigUint::from_str_radix("-1", 10).ok();
         assert_eq!(minus_one, None);
     }
 
@@ -2629,7 +2676,7 @@ mod biguint_tests {
 
         fn check(n: usize, s: &str) {
             let n = factor(n);
-            let ans = match FromStrRadix::from_str_radix(s, 10) {
+            let ans = match BigUint::from_str_radix(s, 10) {
                 Ok(x) => x, Err(_) => panic!()
             };
             assert_eq!(n, ans);
@@ -2650,7 +2697,7 @@ mod biguint_tests {
         assert_eq!(n.bits(), 1);
         let n: BigUint = FromPrimitive::from_usize(3).unwrap();
         assert_eq!(n.bits(), 2);
-        let n: BigUint = FromStrRadix::from_str_radix("4000000000", 16).unwrap();
+        let n: BigUint = BigUint::from_str_radix("4000000000", 16).unwrap();
         assert_eq!(n.bits(), 39);
         let one: BigUint = One::one();
         assert_eq!((one << 426).bits(), 427);
@@ -2713,14 +2760,12 @@ mod bigint_tests {
     use std::cmp::Ordering::{Less, Equal, Greater};
     use std::i64;
     use std::iter::repeat;
-    use std::num::FromStrRadix;
-    use std::num::{ToPrimitive, FromPrimitive};
     use std::u64;
     use std::ops::{Neg};
 
     use rand::thread_rng;
 
-    use {Zero, One, Signed};
+    use {Zero, One, Signed, ToPrimitive, FromPrimitive, Num};
 
     #[test]
     fn test_from_biguint() {
@@ -2764,7 +2809,7 @@ mod bigint_tests {
         assert_eq!(b.to_bytes_be(), (NoSign, vec![0]));
 
         // Test with leading/trailing zero bytes and a full BigDigit of value 0
-        let b: BigInt = FromStrRadix::from_str_radix("00010000000000000200", 16).unwrap();
+        let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap();
         assert_eq!(b.to_bytes_be(), (Plus, vec![1, 0, 0, 0, 0, 0, 0, 2, 0]));
     }
 
@@ -2797,7 +2842,7 @@ mod bigint_tests {
         assert_eq!(b.to_bytes_le(), (NoSign, vec![0]));
 
         // Test with leading/trailing zero bytes and a full BigDigit of value 0
-        let b: BigInt = FromStrRadix::from_str_radix("00010000000000000200", 16).unwrap();
+        let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap();
         assert_eq!(b.to_bytes_le(), (Plus, vec![0, 2, 0, 0, 0, 0, 0, 0, 1]));
     }
 
@@ -2929,6 +2974,9 @@ mod bigint_tests {
         assert_eq!(negative.to_biguint(), None);
     }
 
+    const N1: BigDigit = -1i32 as BigDigit;
+    const N2: BigDigit = -2i32 as BigDigit;
+
     const SUM_TRIPLES: &'static [(&'static [BigDigit],
                                   &'static [BigDigit],
                                   &'static [BigDigit])] = &[
@@ -2936,11 +2984,11 @@ mod bigint_tests {
         (&[],          &[ 1],     &[ 1]),
         (&[ 1],        &[ 1],     &[ 2]),
         (&[ 1],        &[ 1,  1], &[ 2,  1]),
-        (&[ 1],        &[-1],     &[ 0,  1]),
-        (&[ 1],        &[-1, -1], &[ 0,  0, 1]),
-        (&[-1, -1],    &[-1, -1], &[-2, -1, 1]),
-        (&[ 1,  1, 1], &[-1, -1], &[ 0,  1, 2]),
-        (&[ 2,  2, 1], &[-1, -2], &[ 1,  1, 2])
+        (&[ 1],        &[N1],     &[ 0,  1]),
+        (&[ 1],        &[N1, N1], &[ 0,  0, 1]),
+        (&[N1, N1],    &[N1, N1], &[N2, N1, 1]),
+        (&[ 1,  1, 1], &[N1, N1], &[ 0,  1, 2]),
+        (&[ 2,  2, 1], &[N1, N2], &[ 1,  1, 2])
     ];
 
     #[test]
@@ -2992,18 +3040,18 @@ mod bigint_tests {
         (&[ 2],             &[ 3],             &[ 6]),
         (&[ 1],             &[ 1,  1,  1],     &[1, 1,  1]),
         (&[ 1,  2,  3],     &[ 3],             &[ 3,  6,  9]),
-        (&[ 1,  1,  1],     &[-1],             &[-1, -1, -1]),
-        (&[ 1,  2,  3],     &[-1],             &[-1, -2, -2, 2]),
-        (&[ 1,  2,  3,  4], &[-1],             &[-1, -2, -2, -2, 3]),
-        (&[-1],             &[-1],             &[ 1, -2]),
-        (&[-1, -1],         &[-1],             &[ 1, -1, -2]),
-        (&[-1, -1, -1],     &[-1],             &[ 1, -1, -1, -2]),
-        (&[-1, -1, -1, -1], &[-1],             &[ 1, -1, -1, -1, -2]),
+        (&[ 1,  1,  1],     &[N1],             &[N1, N1, N1]),
+        (&[ 1,  2,  3],     &[N1],             &[N1, N2, N2, 2]),
+        (&[ 1,  2,  3,  4], &[N1],             &[N1, N2, N2, N2, 3]),
+        (&[N1],             &[N1],             &[ 1, N2]),
+        (&[N1, N1],         &[N1],             &[ 1, N1, N2]),
+        (&[N1, N1, N1],     &[N1],             &[ 1, N1, N1, N2]),
+        (&[N1, N1, N1, N1], &[N1],             &[ 1, N1, N1, N1, N2]),
         (&[ M/2 + 1],       &[ 2],             &[ 0,  1]),
         (&[0,  M/2 + 1],    &[ 2],             &[ 0,  0,  1]),
         (&[ 1,  2],         &[ 1,  2,  3],     &[1, 4,  7,  6]),
-        (&[-1, -1],         &[-1, -1, -1],     &[1, 0, -1, -2, -1]),
-        (&[-1, -1, -1],     &[-1, -1, -1, -1], &[1, 0,  0, -1, -2, -1, -1]),
+        (&[N1, N1],         &[N1, N1, N1],     &[1, 0, N1, N2, N1]),
+        (&[N1, N1, N1],     &[N1, N1, N1, N1], &[1, 0,  0, N1, N2, N1, N1]),
         (&[ 0,  0,  1],     &[ 1,  2,  3],     &[0, 0,  1,  2,  3]),
         (&[ 0,  0,  1],     &[ 0,  0,  0,  1], &[0, 0,  0,  0,  0,  1])
     ];
@@ -3016,8 +3064,8 @@ mod bigint_tests {
             (&[ 1],        &[ 2], &[],               &[1]),
             (&[ 1,  1],    &[ 2], &[ M/2+1],         &[1]),
             (&[ 1,  1, 1], &[ 2], &[ M/2+1,  M/2+1], &[1]),
-            (&[ 0,  1],    &[-1], &[1],              &[1]),
-            (&[-1, -1],    &[-2], &[2, 1],           &[3])
+            (&[ 0,  1],    &[N1], &[1],              &[1]),
+            (&[N1, N1],    &[N2], &[2, 1],           &[3])
         ];
 
     #[test]
@@ -3292,7 +3340,7 @@ mod bigint_tests {
                 let x: BigInt = FromPrimitive::from_isize(n).unwrap();
                 x
             });
-            assert_eq!(FromStrRadix::from_str_radix(s, 10).ok(), ans);
+            assert_eq!(BigInt::from_str_radix(s, 10).ok(), ans);
         }
         check("10", Some(10));
         check("1", Some(1));
@@ -3374,15 +3422,13 @@ mod bench {
     extern crate test;
     use self::test::Bencher;
     use super::BigUint;
-    use std::iter;
     use std::mem::replace;
-    use std::num::FromPrimitive;
 
-    use {Zero, One};
+    use {Zero, One, FromPrimitive};
 
     fn factorial(n: usize) -> BigUint {
         let mut f: BigUint = One::one();
-        for i in iter::range_inclusive(1, n) {
+        for i in 1..(n+1) {
             let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
             f = f * bu;
         }

+ 15 - 17
src/complex.rs

@@ -12,10 +12,9 @@
 //! Complex numbers.
 
 use std::fmt;
-use std::num::Float;
 use std::ops::{Add, Div, Mul, Neg, Sub};
 
-use {Zero, One, Num};
+use {Zero, One, Num, Float};
 
 // FIXME #1284: handle complex NaN & infinity etc. This
 // probably doesn't map to C's _Complex correctly.
@@ -46,14 +45,6 @@ impl<T: Clone + Num> Complex<T> {
         self.re.clone() * self.re.clone() + self.im.clone() * self.im.clone()
     }
 
-
-    /// Returns the complex conjugate. i.e. `re - i im`
-    #[inline]
-    pub fn conj(&self) -> Complex<T> {
-        Complex::new(self.re.clone(), -self.im.clone())
-    }
-
-
     /// Multiplies `self` by the scalar `t`.
     #[inline]
     pub fn scale(&self, t: T) -> Complex<T> {
@@ -66,12 +57,18 @@ impl<T: Clone + Num> Complex<T> {
         Complex::new(self.re.clone() / t.clone(), self.im.clone() / t)
     }
 
+    /// Returns the complex conjugate. i.e. `re - i im`
+    #[inline]
+    pub fn conj(&self) -> Complex<T> {
+        Complex::new(self.re.clone(), T::zero() - self.im.clone())
+    }
+
     /// Returns `1/self`
     #[inline]
     pub fn inv(&self) -> Complex<T> {
         let norm_sqr = self.norm_sqr();
         Complex::new(self.re.clone() / norm_sqr.clone(),
-                    -self.im.clone() / norm_sqr)
+                    T::zero() - self.im.clone() / norm_sqr)
     }
 }
 
@@ -204,14 +201,14 @@ impl<'a, 'b, T: Clone + Num> Div<&'b Complex<T>> for &'a Complex<T> {
     }
 }
 
-impl<T: Clone + Num> Neg for Complex<T> {
+impl<T: Clone + Num + Neg<Output = T>> Neg for Complex<T> {
     type Output = Complex<T>;
 
     #[inline]
     fn neg(self) -> Complex<T> { -&self }
 }
 
-impl<'a, T: Clone + Num> Neg for &'a Complex<T> {
+impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Complex<T> {
     type Output = Complex<T>;
 
     #[inline]
@@ -241,10 +238,12 @@ impl<T: Clone + Num> One for Complex<T> {
 }
 
 /* string conversions */
-impl<T: fmt::Display + Num + PartialOrd + Clone> fmt::Display for Complex<T> {
+impl<T> fmt::Display for Complex<T> where
+    T: fmt::Display + Num + PartialOrd + Clone
+{
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.im < Zero::zero() {
-            write!(f, "{}-{}i", self.re, -self.im.clone())
+            write!(f, "{}-{}i", self.re, T::zero() - self.im.clone())
         } else {
             write!(f, "{}+{}i", self.re, self.im)
         }
@@ -257,9 +256,8 @@ mod test {
 
     use super::{Complex64, Complex};
     use std::f64;
-    use std::num::Float;
 
-    use {Zero, One};
+    use {Zero, One, Float};
 
     pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
     pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };

+ 5 - 4
src/integer.rs

@@ -10,12 +10,13 @@
 
 //! Integer trait and functions.
 
-use std::ops::{Div, Rem};
-
 use {Num, Signed};
 
-pub trait Integer: Sized + Num + PartialOrd
-                 + Div<Self, Output = Self> + Rem<Self, Output = Self> {
+pub trait Integer
+    : Sized
+    + Num
+    + PartialOrd + Ord + Eq
+{
     /// Floored integer division.
     ///
     /// # Examples

+ 2 - 5
src/iter.rs

@@ -10,9 +10,8 @@
 
 //! External iterators for generic mathematics
 
-use {Integer, Zero, One, CheckedAdd};
+use {Integer, Zero, One, CheckedAdd, ToPrimitive};
 use std::ops::{Add, Sub};
-use std::num::{ToPrimitive, Int};
 
 /// An iterator over the range [start, stop)
 #[derive(Clone)]
@@ -260,10 +259,9 @@ impl<A> Iterator for RangeStepInclusive<A>
 #[cfg(test)]
 mod tests {
     use std::usize;
-    use std::num::ToPrimitive;
     use std::ops::{Add, Mul};
     use std::cmp::Ordering;
-    use One;
+    use {One, ToPrimitive};
 
     #[test]
     fn test_range() {
@@ -328,7 +326,6 @@ mod tests {
         // this test is only meaningful when sizeof usize < sizeof u64
         assert_eq!(super::range(usize::MAX - 1, usize::MAX).size_hint(), (1, Some(1)));
         assert_eq!(super::range(-10, -1).size_hint(), (9, Some(9)));
-        assert_eq!(super::range(Foo, Foo).size_hint(), (0, None));
     }
 
     #[test]

+ 2 - 3
src/lib.rs

@@ -43,7 +43,6 @@
 //! ```
 //!
 //! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
-#![feature(collections, core, std_misc)]
 //#![cfg_attr(test, deny(warnings))]
 #![cfg_attr(test, feature(hash, test))]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -52,7 +51,6 @@
        html_playground_url = "http://play.rust-lang.org/")]
 
 extern crate rustc_serialize;
-extern crate core;
 extern crate rand;
 
 pub use bigint::{BigInt, BigUint};
@@ -61,7 +59,8 @@ pub use complex::Complex;
 pub use integer::Integer;
 pub use iter::{range, range_inclusive, range_step, range_step_inclusive};
 pub use traits::{Num, Zero, One, Signed, Unsigned, Bounded,
-                 Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
+                 Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
+                 PrimInt, Float, ToPrimitive, FromPrimitive, NumCast};
 
 #[cfg(test)] use std::hash;
 

+ 48 - 46
src/rational.rs

@@ -17,8 +17,8 @@ use std::error::Error;
 use std::fmt;
 use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
 use std::str::FromStr;
-use std::num::{FromPrimitive, FromStrRadix, Float};
 
+use traits::{FromPrimitive, Float};
 use bigint::{BigInt, BigUint, Sign};
 use {Num, Signed, Zero, One};
 
@@ -38,8 +38,7 @@ pub type Rational64 = Ratio<i64>;
 /// Alias for arbitrary precision rationals.
 pub type BigRational = Ratio<BigInt>;
 
-impl<T: Clone + Integer + PartialOrd>
-    Ratio<T> {
+impl<T: Clone + Integer + PartialOrd> Ratio<T> {
     /// Creates a ratio representing the integer `t`.
     #[inline]
     pub fn from_integer(t: T) -> Ratio<T> {
@@ -99,9 +98,9 @@ impl<T: Clone + Integer + PartialOrd>
         self.denom = self.denom.clone() / g;
 
         // keep denom positive!
-        if self.denom < Zero::zero() {
-            self.numer = -self.numer.clone();
-            self.denom = -self.denom.clone();
+        if self.denom < T::zero() {
+            self.numer = T::zero() - self.numer.clone();
+            self.denom = T::zero() - self.denom.clone();
         }
     }
 
@@ -143,11 +142,13 @@ impl<T: Clone + Integer + PartialOrd>
     /// Rounds to the nearest integer. Rounds half-way cases away from zero.
     #[inline]
     pub fn round(&self) -> Ratio<T> {
+        let zero: Ratio<T> = Zero::zero();
         let one: T = One::one();
         let two: T = one.clone() + one.clone();
 
         // Find unsigned fractional part of rational number
-        let fractional = self.fract().abs();
+        let mut fractional = self.fract();
+        if fractional < zero { fractional = zero - fractional };
 
         // The algorithm compares the unsigned fractional part with 1/2, that
         // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use
@@ -216,7 +217,9 @@ macro_rules! cmp_impl {
     };
     // return something other than a Ratio<T>
     (impl $imp:ident, $($method:ident -> $res:ty),*) => {
-        impl<T: Clone + Mul<T, Output = T> + $imp> $imp for Ratio<T> {
+        impl<T> $imp for Ratio<T> where
+            T: Clone + Mul<T, Output = T> + $imp
+        {
             $(
                 #[inline]
                 fn $method(&self, other: &Ratio<T>) -> $res {
@@ -247,7 +250,9 @@ macro_rules! forward_val_val_binop {
 
 macro_rules! forward_ref_val_binop {
     (impl $imp:ident, $method:ident) => {
-        impl<'a, T: Clone + Integer + PartialOrd> $imp<Ratio<T>> for &'a Ratio<T> {
+        impl<'a, T> $imp<Ratio<T>> for &'a Ratio<T> where
+            T: Clone + Integer + PartialOrd
+        {
             type Output = Ratio<T>;
 
             #[inline]
@@ -260,7 +265,9 @@ macro_rules! forward_ref_val_binop {
 
 macro_rules! forward_val_ref_binop {
     (impl $imp:ident, $method:ident) => {
-        impl<'a, T: Clone + Integer + PartialOrd> $imp<&'a Ratio<T>> for Ratio<T> {
+        impl<'a, T> $imp<&'a Ratio<T>> for Ratio<T> where
+            T: Clone + Integer + PartialOrd
+        {
             type Output = Ratio<T>;
 
             #[inline]
@@ -332,7 +339,7 @@ arith_impl!(impl Sub, sub);
 arith_impl!(impl Rem, rem);
 
 impl<T> Neg for Ratio<T>
-    where T: Clone + Integer + PartialOrd
+    where T: Clone + Integer + PartialOrd + Neg<Output = T>
 {
     type Output = Ratio<T>;
 
@@ -341,7 +348,7 @@ impl<T> Neg for Ratio<T>
 }
 
 impl<'a, T> Neg for &'a Ratio<T>
-    where T: Clone + Integer + PartialOrd
+    where T: Clone + Integer + PartialOrd + Neg<Output = T>
 {
     type Output = Ratio<T>;
 
@@ -373,11 +380,30 @@ impl<T: Clone + Integer + PartialOrd>
     }
 }
 
-impl<T: Clone + Integer + PartialOrd>
-    Num for Ratio<T> {}
+impl<T: Clone + Integer + PartialOrd> Num for Ratio<T> {
+    type FromStrRadixErr = ParseRatioError;
 
-impl<T: Clone + Integer + PartialOrd>
-    Signed for Ratio<T> {
+    /// Parses `numer/denom` where the numbers are in base `radix`.
+    fn from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError> {
+        let split: Vec<&str> = s.splitn(2, '/').collect();
+        if split.len() < 2 {
+            Err(ParseRatioError)
+        } else {
+            let a_result: Result<T, _> = T::from_str_radix(
+                split[0],
+                radix).map_err(|_| ParseRatioError);
+            a_result.and_then(|a| {
+                let b_result: Result<T, _>  =
+                    T::from_str_radix(split[1], radix).map_err(|_| ParseRatioError);
+                b_result.and_then(|b| {
+                    Ok(Ratio::new(a.clone(), b.clone()))
+                })
+            })
+        }
+    }
+}
+
+impl<T: Clone + Integer + PartialOrd + Signed> Signed for Ratio<T> {
     #[inline]
     fn abs(&self) -> Ratio<T> {
         if self.is_negative() { -self.clone() } else { self.clone() }
@@ -407,7 +433,9 @@ impl<T: Clone + Integer + PartialOrd>
 }
 
 /* String conversions */
-impl<T: fmt::Display + Eq + One> fmt::Display for Ratio<T> {
+impl<T> fmt::Display for Ratio<T> where
+    T: fmt::Display + Eq + One
+{
     /// Renders as `numer/denom`. If denom=1, renders as numer.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.denom == One::one() {
@@ -418,8 +446,7 @@ impl<T: fmt::Display + Eq + One> fmt::Display for Ratio<T> {
     }
 }
 
-impl<T: FromStr + Clone + Integer + PartialOrd>
-    FromStr for Ratio<T> {
+impl<T: FromStr + Clone + Integer + PartialOrd> FromStr for Ratio<T> {
     type Err = ParseRatioError;
 
     /// Parses `numer/denom` or just `numer`.
@@ -436,32 +463,8 @@ impl<T: FromStr + Clone + Integer + PartialOrd>
     }
 }
 
-impl<T: FromStrRadix + Clone + Integer + PartialOrd>
-    FromStrRadix for Ratio<T> {
-    type Err = ParseRatioError;
-
-    /// Parses `numer/denom` where the numbers are in base `radix`.
-    fn from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError> {
-        let split: Vec<&str> = s.splitn(2, '/').collect();
-        if split.len() < 2 {
-            Err(ParseRatioError)
-        } else {
-            let a_result: Result<T, _> = FromStrRadix::from_str_radix(
-                split[0],
-                radix).map_err(|_| ParseRatioError);
-            a_result.and_then(|a| {
-                let b_result: Result<T, _>  =
-                    FromStrRadix::from_str_radix(split[1], radix).map_err(|_| ParseRatioError);
-                b_result.and_then(|b| {
-                    Ok(Ratio::new(a.clone(), b.clone()))
-                })
-            })
-        }
-    }
-}
-
 // FIXME: Bubble up specific errors
-#[derive(Copy, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub struct ParseRatioError;
 
 impl fmt::Display for ParseRatioError {
@@ -478,10 +481,9 @@ impl Error for ParseRatioError {
 mod test {
 
     use super::{Ratio, Rational, BigRational};
-    use std::num::{FromPrimitive, Float};
     use std::str::FromStr;
     use std::i32;
-    use {Zero, One, Signed};
+    use {Zero, One, Signed, FromPrimitive, Float};
 
     pub const _0 : Rational = Ratio { numer: 0, denom: 1};
     pub const _1 : Rational = Ratio { numer: 1, denom: 1};

+ 153 - 155
src/traits.rs

@@ -10,27 +10,54 @@
 
 //! Numeric traits for generic mathematics
 
-use std::intrinsics;
 use std::ops::{Add, Sub, Mul, Div, Rem, Neg};
 use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
 use std::{usize, u8, u16, u32, u64};
 use std::{isize, i8, i16, i32, i64};
 use std::{f32, f64};
-use std::mem::size_of;
+use std::mem::{self, size_of};
 use std::num::FpCategory;
 
 /// The base trait for numeric types
 pub trait Num: PartialEq + Zero + One
-    + Neg<Output = Self> + Add<Output = Self> + Sub<Output = Self>
-    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self> {}
+    + Add<Output = Self> + Sub<Output = Self>
+    + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
+{
+    /// Parse error for `from_str_radix`
+    type FromStrRadixErr;
+
+    /// Convert from a string and radix <= 36.
+    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
+}
 
-macro_rules! trait_impl {
+macro_rules! int_trait_impl {
     ($name:ident for $($t:ty)*) => ($(
-        impl $name for $t {}
+        impl $name for $t {
+            type FromStrRadixErr = ::std::num::ParseIntError;
+            fn from_str_radix(s: &str, radix: u32)
+                              -> Result<Self, ::std::num::ParseIntError>
+            {
+                <$t>::from_str_radix(s, radix)
+            }
+        }
     )*)
 }
 
-trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64);
+macro_rules! float_trait_impl {
+    ($name:ident for $($t:ty)*) => ($(
+        impl $name for $t {
+            type FromStrRadixErr = ::std::num::ParseFloatError;
+            fn from_str_radix(s: &str, radix: u32)
+                              -> Result<Self, ::std::num::ParseFloatError>
+            {
+                <$t>::from_str_radix(s, radix)
+            }
+        }
+    )*)
+}
+
+int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
+float_trait_impl!(Num for f32 f64);
 
 /// Defines an additive identity element for `Self`.
 ///
@@ -132,7 +159,6 @@ one_impl!(i64, 1i64);
 one_impl!(f32, 1.0f32);
 one_impl!(f64, 1.0f64);
 
-
 /// Useful functions for signed numbers (i.e. numbers that can be negative).
 pub trait Signed: Num + Neg<Output = Self> {
     /// Computes the absolute value.
@@ -204,12 +230,12 @@ macro_rules! signed_impl {
 signed_impl!(isize i8 i16 i32 i64);
 
 macro_rules! signed_float_impl {
-    ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr, $fabs:path, $fcopysign:path, $fdim:ident) => {
+    ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
         impl Signed for $t {
             /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
             #[inline]
             fn abs(&self) -> $t {
-                unsafe { $fabs(*self) }
+                <$t>::abs(*self)
             }
 
             /// The positive difference of two numbers. Returns `0.0` if the number is
@@ -217,8 +243,7 @@ macro_rules! signed_float_impl {
             /// and `other` is returned.
             #[inline]
             fn abs_sub(&self, other: &$t) -> $t {
-                extern { fn $fdim(a: $t, b: $t) -> $t; }
-                unsafe { $fdim(*self, *other) }
+                <$t>::abs_sub(*self, *other)
             }
 
             /// # Returns
@@ -228,9 +253,7 @@ macro_rules! signed_float_impl {
             /// - `NAN` if the number is NaN
             #[inline]
             fn signum(&self) -> $t {
-                if self != self { $nan } else {
-                    unsafe { $fcopysign(1.0, *self) }
-                }
+                <$t>::signum(*self)
             }
 
             /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
@@ -244,15 +267,19 @@ macro_rules! signed_float_impl {
     }
 }
 
-signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY,
-                   intrinsics::fabsf32, intrinsics::copysignf32, fdimf);
-signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY,
-                   intrinsics::fabsf64, intrinsics::copysignf64, fdim);
+signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
+signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);
 
 /// A trait for values which cannot be negative
 pub trait Unsigned: Num {}
 
-trait_impl!(Unsigned for usize u8 u16 u32 u64);
+macro_rules! empty_trait_impl {
+    ($name:ident for $($t:ty)*) => ($(
+        impl $name for $t {}
+    )*)
+}
+
+empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
 
 /// Numbers which have upper and lower bounds
 pub trait Bounded {
@@ -336,51 +363,27 @@ pub trait CheckedAdd: Add<Self, Output = Self> {
 }
 
 macro_rules! checked_impl {
-    ($trait_name:ident, $method:ident, $t:ty, $op:path) => {
+    ($trait_name:ident, $method:ident, $t:ty) => {
         impl $trait_name for $t {
             #[inline]
             fn $method(&self, v: &$t) -> Option<$t> {
-                unsafe {
-                    let (x, y) = $op(*self, *v);
-                    if y { None } else { Some(x) }
-                }
+                <$t>::$method(*self, *v)
             }
         }
     }
 }
-macro_rules! checked_cast_impl {
-    ($trait_name:ident, $method:ident, $t:ty, $cast:ty, $op:path) => {
-        impl $trait_name for $t {
-            #[inline]
-            fn $method(&self, v: &$t) -> Option<$t> {
-                unsafe {
-                    let (x, y) = $op(*self as $cast, *v as $cast);
-                    if y { None } else { Some(x as $t) }
-                }
-            }
-        }
-    }
-}
-
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedAdd, checked_add, usize, u32, intrinsics::u32_add_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedAdd, checked_add, usize, u64, intrinsics::u64_add_with_overflow);
 
-checked_impl!(CheckedAdd, checked_add, u8,  intrinsics::u8_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, u16, intrinsics::u16_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, u32, intrinsics::u32_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, u64, intrinsics::u64_add_with_overflow);
+checked_impl!(CheckedAdd, checked_add, u8);
+checked_impl!(CheckedAdd, checked_add, u16);
+checked_impl!(CheckedAdd, checked_add, u32);
+checked_impl!(CheckedAdd, checked_add, u64);
+checked_impl!(CheckedAdd, checked_add, usize);
 
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedAdd, checked_add, isize, i32, intrinsics::i32_add_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedAdd, checked_add, isize, i64, intrinsics::i64_add_with_overflow);
-
-checked_impl!(CheckedAdd, checked_add, i8,  intrinsics::i8_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, i16, intrinsics::i16_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, i32, intrinsics::i32_add_with_overflow);
-checked_impl!(CheckedAdd, checked_add, i64, intrinsics::i64_add_with_overflow);
+checked_impl!(CheckedAdd, checked_add, i8);
+checked_impl!(CheckedAdd, checked_add, i16);
+checked_impl!(CheckedAdd, checked_add, i32);
+checked_impl!(CheckedAdd, checked_add, i64);
+checked_impl!(CheckedAdd, checked_add, isize);
 
 /// Performs subtraction that returns `None` instead of wrapping around on underflow.
 pub trait CheckedSub: Sub<Self, Output = Self> {
@@ -389,25 +392,17 @@ pub trait CheckedSub: Sub<Self, Output = Self> {
     fn checked_sub(&self, v: &Self) -> Option<Self>;
 }
 
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedSub, checked_sub, usize, u32, intrinsics::u32_sub_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedSub, checked_sub, usize, u64, intrinsics::u64_sub_with_overflow);
-
-checked_impl!(CheckedSub, checked_sub, u8,  intrinsics::u8_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, u16, intrinsics::u16_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, u32, intrinsics::u32_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, u64, intrinsics::u64_sub_with_overflow);
+checked_impl!(CheckedSub, checked_sub, u8);
+checked_impl!(CheckedSub, checked_sub, u16);
+checked_impl!(CheckedSub, checked_sub, u32);
+checked_impl!(CheckedSub, checked_sub, u64);
+checked_impl!(CheckedSub, checked_sub, usize);
 
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedSub, checked_sub, isize, i32, intrinsics::i32_sub_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedSub, checked_sub, isize, i64, intrinsics::i64_sub_with_overflow);
-
-checked_impl!(CheckedSub, checked_sub, i8,  intrinsics::i8_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, i16, intrinsics::i16_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, i32, intrinsics::i32_sub_with_overflow);
-checked_impl!(CheckedSub, checked_sub, i64, intrinsics::i64_sub_with_overflow);
+checked_impl!(CheckedSub, checked_sub, i8);
+checked_impl!(CheckedSub, checked_sub, i16);
+checked_impl!(CheckedSub, checked_sub, i32);
+checked_impl!(CheckedSub, checked_sub, i64);
+checked_impl!(CheckedSub, checked_sub, isize);
 
 /// Performs multiplication that returns `None` instead of wrapping around on underflow or
 /// overflow.
@@ -417,25 +412,17 @@ pub trait CheckedMul: Mul<Self, Output = Self> {
     fn checked_mul(&self, v: &Self) -> Option<Self>;
 }
 
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedMul, checked_mul, usize, u32, intrinsics::u32_mul_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedMul, checked_mul, usize, u64, intrinsics::u64_mul_with_overflow);
-
-checked_impl!(CheckedMul, checked_mul, u8,  intrinsics::u8_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, u16, intrinsics::u16_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, u32, intrinsics::u32_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, u64, intrinsics::u64_mul_with_overflow);
-
-#[cfg(target_pointer_width = "32")]
-checked_cast_impl!(CheckedMul, checked_mul, isize, i32, intrinsics::i32_mul_with_overflow);
-#[cfg(target_pointer_width = "64")]
-checked_cast_impl!(CheckedMul, checked_mul, isize, i64, intrinsics::i64_mul_with_overflow);
+checked_impl!(CheckedMul, checked_mul, u8);
+checked_impl!(CheckedMul, checked_mul, u16);
+checked_impl!(CheckedMul, checked_mul, u32);
+checked_impl!(CheckedMul, checked_mul, u64);
+checked_impl!(CheckedMul, checked_mul, usize);
 
-checked_impl!(CheckedMul, checked_mul, i8,  intrinsics::i8_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, i16, intrinsics::i16_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, i32, intrinsics::i32_mul_with_overflow);
-checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow);
+checked_impl!(CheckedMul, checked_mul, i8);
+checked_impl!(CheckedMul, checked_mul, i16);
+checked_impl!(CheckedMul, checked_mul, i32);
+checked_impl!(CheckedMul, checked_mul, i64);
+checked_impl!(CheckedMul, checked_mul, isize);
 
 /// Performs division that returns `None` instead of panicking on division by zero and instead of
 /// wrapping around on underflow and overflow.
@@ -483,12 +470,12 @@ macro_rules! checkeddiv_uint_impl {
 
 checkeddiv_uint_impl!(usize u8 u16 u32 u64);
 
-pub trait Int
-    : Num
-    + Clone
-    + NumCast
-    + PartialOrd + Ord
-    + Eq
+pub trait PrimInt
+    : Sized
+    + Copy
+    + Num + NumCast
+    + Bounded
+    + PartialOrd + Ord + Eq
     + Not<Output=Self>
     + BitAnd<Output=Self>
     + BitOr<Output=Self>
@@ -501,12 +488,6 @@ pub trait Int
     + CheckedDiv<Output=Self>
     + Saturating
 {
-    /// Returns the smallest value that can be represented by this integer type.
-    fn min_value() -> Self;
-
-    /// Returns the largest value that can be represented by this integer type.
-    fn max_value() -> Self;
-
     /// Returns the number of ones in the binary representation of `self`.
     ///
     /// # Examples
@@ -693,9 +674,9 @@ pub trait Int
     fn pow(self, mut exp: u32) -> Self;
 }
 
-macro_rules! int_impl {
+macro_rules! prim_int_impl {
     ($($T:ty)*) => ($(
-        impl Int for $T {
+        impl PrimInt for $T {
             fn min_value() -> Self {
                 <$T>::min_value()
             }
@@ -755,8 +736,6 @@ macro_rules! int_impl {
     )*)
 }
 
-int_impl!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize);
-
 /// A generic trait for converting a value to a number.
 pub trait ToPrimitive {
     /// Converts the value of `self` to an `isize`.
@@ -834,8 +813,8 @@ macro_rules! impl_to_primitive_int_to_int {
                 Some($slf as $DstT)
             } else {
                 let n = $slf as i64;
-                let min_value: $DstT = Int::min_value();
-                let max_value: $DstT = Int::max_value();
+                let min_value: $DstT = Bounded::min_value();
+                let max_value: $DstT = Bounded::max_value();
                 if min_value as i64 <= n && n <= max_value as i64 {
                     Some($slf as $DstT)
                 } else {
@@ -850,7 +829,7 @@ macro_rules! impl_to_primitive_int_to_uint {
     ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             let zero: $SrcT = Zero::zero();
-            let max_value: $DstT = Int::max_value();
+            let max_value: $DstT = Bounded::max_value();
             if zero <= $slf && $slf as u64 <= max_value as u64 {
                 Some($slf as $DstT)
             } else {
@@ -902,7 +881,7 @@ impl_to_primitive_int! { i64 }
 macro_rules! impl_to_primitive_uint_to_int {
     ($DstT:ty, $slf:expr) => (
         {
-            let max_value: $DstT = Int::max_value();
+            let max_value: $DstT = Bounded::max_value();
             if $slf as u64 <= max_value as u64 {
                 Some($slf as $DstT)
             } else {
@@ -919,7 +898,7 @@ macro_rules! impl_to_primitive_uint_to_uint {
                 Some($slf as $DstT)
             } else {
                 let zero: $SrcT = Zero::zero();
-                let max_value: $DstT = Int::max_value();
+                let max_value: $DstT = Bounded::max_value();
                 if zero <= $slf && $slf as u64 <= max_value as u64 {
                     Some($slf as $DstT)
                 } else {
@@ -1189,9 +1168,10 @@ impl_num_cast! { f64,   to_f64 }
 
 pub trait Float
     : Num
-    + Clone
+    + Copy
     + NumCast
     + PartialOrd
+    + Neg<Output = Self>
 {
     /// Returns the `NaN` value.
     ///
@@ -1671,36 +1651,6 @@ pub trait Float
     /// ```
     fn log10(self) -> Self;
 
-    /// Convert radians to degrees.
-    ///
-    /// ```
-    /// # #![feature(std_misc, core)]
-    /// use num::traits::Float;
-    /// use std::f64::consts;
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    fn to_degrees(self) -> Self;
-
-    /// Convert degrees to radians.
-    ///
-    /// ```
-    /// # #![feature(std_misc, core)]
-    /// use num::traits::Float;
-    /// use std::f64::consts;
-    ///
-    /// let angle = 180.0;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    fn to_radians(self) -> Self;
-
     /// Returns the maximum of the two numbers.
     ///
     /// ```
@@ -2039,10 +1989,34 @@ pub trait Float
     /// assert!(abs_difference < 1.0e-10);
     /// ```
     fn atanh(self) -> Self;
+
+
+    /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
+    /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
+    /// The floating point encoding is documented in the [Reference][floating-point].
+    ///
+    /// ```
+    /// use num::Float;
+    ///
+    /// let num = 2.0f32;
+    ///
+    /// // (8388608, -22, 1)
+    /// let (mantissa, exponent, sign) = num.integer_decode();
+    /// let sign_f = sign as f32;
+    /// let mantissa_f = mantissa as f32;
+    /// let exponent_f = num.powf(exponent as f32);
+    ///
+    /// // 1 * 8388608 * 2^(-22) == 2
+    /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    /// [floating-point]: ../../../../../reference.html#machine-types
+    fn integer_decode(self) -> (u64, i16, i8);
 }
 
 macro_rules! float_impl {
-    ($($T:ident)*) => ($(
+    ($T:ident $decode:ident) => (
         impl Float for $T {
             fn nan() -> Self {
                 ::std::$T::NAN
@@ -2168,14 +2142,6 @@ macro_rules! float_impl {
                 <$T>::log10(self)
             }
 
-            fn to_degrees(self) -> Self {
-                <$T>::to_degrees(self)
-            }
-
-            fn to_radians(self) -> Self {
-                <$T>::to_radians(self)
-            }
-
             fn max(self, other: Self) -> Self {
                 <$T>::max(self, other)
             }
@@ -2260,8 +2226,40 @@ macro_rules! float_impl {
                 <$T>::atanh(self)
             }
 
+            fn integer_decode(self) -> (u64, i16, i8) {
+                $decode(self)
+            }
         }
-    )*)
+    )
+}
+
+fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
+    let bits: u32 = unsafe { mem::transmute(f) };
+    let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
+    let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
+    let mantissa = if exponent == 0 {
+        (bits & 0x7fffff) << 1
+    } else {
+        (bits & 0x7fffff) | 0x800000
+    };
+    // Exponent bias + mantissa shift
+    exponent -= 127 + 23;
+    (mantissa as u64, exponent, sign)
+}
+
+fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
+    let bits: u64 = unsafe { mem::transmute(f) };
+    let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
+    let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
+    let mantissa = if exponent == 0 {
+        (bits & 0xfffffffffffff) << 1
+    } else {
+        (bits & 0xfffffffffffff) | 0x10000000000000
+    };
+    // Exponent bias + mantissa shift
+    exponent -= 1023 + 52;
+    (mantissa, exponent, sign)
 }
 
-float_impl!(f32 f64);
+float_impl!(f32 integer_decode_f32);
+float_impl!(f64 integer_decode_f64);