Merge pull request #76 from aturon/beta-fixes

Update to 1.0.0-beta (stable only)
This commit is contained in:
Alex Crichton 2015-04-03 10:23:07 -07:00
commit f2cecb0fda
7 changed files with 435 additions and 394 deletions

View File

@ -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());
}
-> (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 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));
}
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;
}

View File

@ -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 };

View File

@ -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

View File

@ -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]

View File

@ -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;

View File

@ -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};

View File

@ -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;
macro_rules! trait_impl {
/// Convert from a string and radix <= 36.
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}
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) }
}
}
}
}
}
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) }
}
<$t>::$method(*self, *v)
}
}
}
}
#[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);
checked_impl!(CheckedAdd, checked_add, u16);
checked_impl!(CheckedAdd, checked_add, u32);
checked_impl!(CheckedAdd, checked_add, u64);
checked_impl!(CheckedAdd, checked_add, usize);
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);
#[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);
checked_impl!(CheckedSub, checked_sub, u16);
checked_impl!(CheckedSub, checked_sub, u32);
checked_impl!(CheckedSub, checked_sub, u64);
checked_impl!(CheckedSub, checked_sub, usize);
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);
#[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);
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, 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, 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)
}
}
)*)
)
}
float_impl!(f32 f64);
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 integer_decode_f32);
float_impl!(f64 integer_decode_f64);