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).
This commit is contained in:
parent
03db5c9d1b
commit
63c7a25ed9
374
src/bigint.rs
374
src/bigint.rs
|
@ -62,12 +62,10 @@ extern crate rustc_serialize;
|
||||||
|
|
||||||
use Integer;
|
use Integer;
|
||||||
|
|
||||||
use core::num::ParseIntError;
|
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::iter::repeat;
|
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::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
||||||
use std::str::{self, FromStr};
|
use std::str::{self, FromStr};
|
||||||
use std::{cmp, fmt, hash, mem};
|
use std::{cmp, fmt, hash, mem};
|
||||||
|
@ -77,6 +75,8 @@ use std::{i64, u64};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rustc_serialize::hex::ToHex;
|
use rustc_serialize::hex::ToHex;
|
||||||
|
|
||||||
|
use traits::{ToPrimitive, FromPrimitive, cast};
|
||||||
|
|
||||||
use {Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Signed, Zero, One};
|
use {Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Signed, Zero, One};
|
||||||
use self::Sign::{Minus, NoSign, Plus};
|
use self::Sign::{Minus, NoSign, Plus};
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ pub mod big_digit {
|
||||||
pub const BITS: usize = 32;
|
pub const BITS: usize = 32;
|
||||||
|
|
||||||
pub const BASE: DoubleBigDigit = 1 << BITS;
|
pub const BASE: DoubleBigDigit = 1 << BITS;
|
||||||
const LO_MASK: DoubleBigDigit = (-1 as DoubleBigDigit) >> BITS;
|
const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_hi(n: DoubleBigDigit) -> BigDigit { (n >> BITS) as BigDigit }
|
fn get_hi(n: DoubleBigDigit) -> BigDigit { (n >> BITS) as BigDigit }
|
||||||
|
@ -190,11 +190,47 @@ impl FromStr for BigUint {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> {
|
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 {
|
macro_rules! forward_val_val_binop {
|
||||||
(impl $imp:ident for $res:ty, $method:ident) => {
|
(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 (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(
|
let ored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
|
||||||
|(ai, bi)| *ai | *bi
|
|(ai, bi)| *ai | *bi
|
||||||
).collect();
|
).collect();
|
||||||
return BigUint::new(ored);
|
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 (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(
|
let xored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
|
||||||
|(ai, bi)| *ai ^ *bi
|
|(ai, bi)| *ai ^ *bi
|
||||||
).collect();
|
).collect();
|
||||||
return BigUint::new(xored);
|
return BigUint::new(xored);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,11 +409,11 @@ impl<'a, 'b> Sub<&'b BigUint> for &'a BigUint {
|
||||||
+ (*ai as DoubleBigDigit)
|
+ (*ai as DoubleBigDigit)
|
||||||
- (*bi as DoubleBigDigit)
|
- (*bi as DoubleBigDigit)
|
||||||
- (borrow as DoubleBigDigit)
|
- (borrow as DoubleBigDigit)
|
||||||
);
|
);
|
||||||
/*
|
/*
|
||||||
hi * (base) + lo == 1*(base) + ai - bi - borrow
|
hi * (base) + lo == 1*(base) + ai - bi - borrow
|
||||||
=> ai - bi - borrow < 0 <=> hi == 0
|
=> ai - bi - borrow < 0 <=> hi == 0
|
||||||
*/
|
*/
|
||||||
borrow = if hi == 0 { 1 } else { 0 };
|
borrow = if hi == 0 { 1 } else { 0 };
|
||||||
lo
|
lo
|
||||||
}).collect();
|
}).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 mut prod: Vec<BigDigit> = a.data.iter().map(|ai| {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(
|
let (hi, lo) = big_digit::from_doublebigdigit(
|
||||||
(*ai as DoubleBigDigit) * (n as DoubleBigDigit) + (carry as DoubleBigDigit)
|
(*ai as DoubleBigDigit) * (n as DoubleBigDigit) + (carry as DoubleBigDigit)
|
||||||
);
|
);
|
||||||
carry = hi;
|
carry = hi;
|
||||||
lo
|
lo
|
||||||
}).collect();
|
}).collect();
|
||||||
|
@ -605,33 +641,33 @@ impl Integer for BigUint {
|
||||||
|
|
||||||
|
|
||||||
fn div_estimate(a: &BigUint, b: &BigUint, n: usize)
|
fn div_estimate(a: &BigUint, b: &BigUint, n: usize)
|
||||||
-> (BigUint, BigUint, BigUint) {
|
-> (BigUint, BigUint, BigUint) {
|
||||||
if a.data.len() < n {
|
if a.data.len() < n {
|
||||||
return (Zero::zero(), Zero::zero(), (*a).clone());
|
return (Zero::zero(), Zero::zero(), (*a).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let an = &a.data[a.data.len() - n ..];
|
let an = &a.data[a.data.len() - n ..];
|
||||||
let bn = *b.data.last().unwrap();
|
let bn = *b.data.last().unwrap();
|
||||||
let mut d = Vec::with_capacity(an.len());
|
let mut d = Vec::with_capacity(an.len());
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
for elt in an.iter().rev() {
|
for elt in an.iter().rev() {
|
||||||
let ai = big_digit::to_doublebigdigit(carry, *elt);
|
let ai = big_digit::to_doublebigdigit(carry, *elt);
|
||||||
let di = ai / (bn as DoubleBigDigit);
|
let di = ai / (bn as DoubleBigDigit);
|
||||||
assert!(di < big_digit::BASE);
|
assert!(di < big_digit::BASE);
|
||||||
carry = (ai % (bn as DoubleBigDigit)) as BigDigit;
|
carry = (ai % (bn as DoubleBigDigit)) as BigDigit;
|
||||||
d.push(di as BigDigit)
|
d.push(di as BigDigit)
|
||||||
}
|
}
|
||||||
d.reverse();
|
d.reverse();
|
||||||
|
|
||||||
let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
|
let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
|
||||||
if shift == 0 {
|
if shift == 0 {
|
||||||
return (BigUint::new(d), One::one(), (*b).clone());
|
return (BigUint::new(d), One::one(), (*b).clone());
|
||||||
}
|
}
|
||||||
let one: BigUint = One::one();
|
let one: BigUint = One::one();
|
||||||
return (BigUint::new(d).shl_unit(shift),
|
return (BigUint::new(d).shl_unit(shift),
|
||||||
one.shl_unit(shift),
|
one.shl_unit(shift),
|
||||||
b.shl_unit(shift));
|
b.shl_unit(shift));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`.
|
/// 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!(u32, FromPrimitive::from_u32);
|
||||||
impl_to_biguint!(u64, FromPrimitive::from_u64);
|
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 {
|
fn to_str_radix(me: &BigUint, radix: u32) -> String {
|
||||||
assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
|
assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
|
||||||
let (base, max_len) = get_radix_base(radix);
|
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);
|
let mut s = String::with_capacity(v.len() * l);
|
||||||
for n in v.iter().rev() {
|
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.extend(repeat("0").take(l - ss.len()));
|
||||||
s.push_str(&ss);
|
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 {
|
impl BigUint {
|
||||||
/// Creates and initializes a `BigUint`.
|
/// Creates and initializes a `BigUint`.
|
||||||
///
|
///
|
||||||
|
@ -961,7 +1011,7 @@ impl BigUint {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> {
|
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]
|
#[inline]
|
||||||
|
@ -969,7 +1019,7 @@ impl BigUint {
|
||||||
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
|
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
|
||||||
|
|
||||||
let mut v = repeat(ZERO_BIG_DIGIT).take(n_unit).collect::<Vec<_>>();
|
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)
|
BigUint::new(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,11 +1169,27 @@ impl FromStr for BigInt {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
|
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 {
|
impl Shl<usize> for BigInt {
|
||||||
type Output = 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!(u32, FromPrimitive::from_u32);
|
||||||
impl_to_bigint!(u64, FromPrimitive::from_u64);
|
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 {
|
pub trait RandBigInt {
|
||||||
/// Generate a random `BigUint` of the given bit size.
|
/// Generate a random `BigUint` of the given bit size.
|
||||||
fn gen_biguint(&mut self, bit_size: usize) -> BigUint;
|
fn gen_biguint(&mut self, bit_size: usize) -> BigUint;
|
||||||
|
@ -1712,7 +1760,7 @@ impl BigInt {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
|
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::cmp::Ordering::{Less, Equal, Greater};
|
||||||
use std::i64;
|
use std::i64;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::num::FromStrRadix;
|
|
||||||
use std::num::{ToPrimitive, FromPrimitive};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::u64;
|
use std::u64;
|
||||||
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use {Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
use {Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
||||||
|
use {ToPrimitive, FromPrimitive};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_slice() {
|
fn test_from_slice() {
|
||||||
|
@ -1803,7 +1850,7 @@ mod biguint_tests {
|
||||||
check(&[1, 2, 0, 0], &[1, 2]);
|
check(&[1, 2, 0, 0], &[1, 2]);
|
||||||
check(&[0, 0, 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(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
|
||||||
check(&[-1], &[-1]);
|
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1833,7 +1880,7 @@ mod biguint_tests {
|
||||||
assert_eq!(b.to_bytes_be(), [0]);
|
assert_eq!(b.to_bytes_be(), [0]);
|
||||||
|
|
||||||
// Test with leading/trailing zero bytes and a full BigDigit of value 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]);
|
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]);
|
assert_eq!(b.to_bytes_le(), [0]);
|
||||||
|
|
||||||
// Test with leading/trailing zero bytes and a full BigDigit of value 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]);
|
assert_eq!(b.to_bytes_le(), [0, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1963,7 +2010,7 @@ mod biguint_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_shl() {
|
fn test_shl() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
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);
|
let bu = to_str_radix(&(opt_biguint.unwrap() << shift), 16);
|
||||||
assert_eq!(bu, ans);
|
assert_eq!(bu, ans);
|
||||||
}
|
}
|
||||||
|
@ -2084,8 +2131,7 @@ mod biguint_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_shr() {
|
fn test_shr() {
|
||||||
fn check(s: &str, shift: usize, ans: &str) {
|
fn check(s: &str, shift: usize, ans: &str) {
|
||||||
let opt_biguint: Option<BigUint> =
|
let opt_biguint = BigUint::from_str_radix(s, 16).ok();
|
||||||
FromStrRadix::from_str_radix(s, 16).ok();
|
|
||||||
let bu = to_str_radix(&(opt_biguint.unwrap() >> shift), 16);
|
let bu = to_str_radix(&(opt_biguint.unwrap() >> shift), 16);
|
||||||
assert_eq!(bu, ans);
|
assert_eq!(bu, ans);
|
||||||
}
|
}
|
||||||
|
@ -2199,6 +2245,9 @@ mod biguint_tests {
|
||||||
"88887777666655554444333322221111");
|
"88887777666655554444333322221111");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const N1: BigDigit = -1i32 as BigDigit;
|
||||||
|
const N2: BigDigit = -2i32 as BigDigit;
|
||||||
|
|
||||||
// `DoubleBigDigit` size dependent
|
// `DoubleBigDigit` size dependent
|
||||||
#[test]
|
#[test]
|
||||||
fn test_convert_i64() {
|
fn test_convert_i64() {
|
||||||
|
@ -2214,14 +2263,14 @@ mod biguint_tests {
|
||||||
|
|
||||||
check(BigUint::new(vec!( )), 0);
|
check(BigUint::new(vec!( )), 0);
|
||||||
check(BigUint::new(vec!( 1 )), (1 << (0*big_digit::BITS)));
|
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!( 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!(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!( 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
|
// `DoubleBigDigit` size dependent
|
||||||
|
@ -2240,12 +2289,12 @@ mod biguint_tests {
|
||||||
|
|
||||||
check(BigUint::new(vec!( )), 0);
|
check(BigUint::new(vec!( )), 0);
|
||||||
check(BigUint::new(vec!( 1 )), (1 << (0*big_digit::BITS)));
|
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!( 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!( 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]
|
#[test]
|
||||||
|
@ -2266,11 +2315,11 @@ mod biguint_tests {
|
||||||
(&[], &[ 1], &[ 1]),
|
(&[], &[ 1], &[ 1]),
|
||||||
(&[ 1], &[ 1], &[ 2]),
|
(&[ 1], &[ 1], &[ 2]),
|
||||||
(&[ 1], &[ 1, 1], &[ 2, 1]),
|
(&[ 1], &[ 1, 1], &[ 2, 1]),
|
||||||
(&[ 1], &[-1], &[ 0, 1]),
|
(&[ 1], &[N1], &[ 0, 1]),
|
||||||
(&[ 1], &[-1, -1], &[ 0, 0, 1]),
|
(&[ 1], &[N1, N1], &[ 0, 0, 1]),
|
||||||
(&[-1, -1], &[-1, -1], &[-2, -1, 1]),
|
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
|
||||||
(&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
|
(&[ 1, 1, 1], &[N1, N1], &[ 0, 1, 2]),
|
||||||
(&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
|
(&[ 2, 2, 1], &[N1, N2], &[ 1, 1, 2])
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2317,18 +2366,18 @@ mod biguint_tests {
|
||||||
(&[ 2], &[ 3], &[ 6]),
|
(&[ 2], &[ 3], &[ 6]),
|
||||||
(&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
|
(&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
|
||||||
(&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
|
(&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
|
||||||
(&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
|
(&[ 1, 1, 1], &[N1], &[N1, N1, N1]),
|
||||||
(&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
|
(&[ 1, 2, 3], &[N1], &[N1, N2, N2, 2]),
|
||||||
(&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
|
(&[ 1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]),
|
||||||
(&[-1], &[-1], &[ 1, -2]),
|
(&[N1], &[N1], &[ 1, N2]),
|
||||||
(&[-1, -1], &[-1], &[ 1, -1, -2]),
|
(&[N1, N1], &[N1], &[ 1, N1, N2]),
|
||||||
(&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
|
(&[N1, N1, N1], &[N1], &[ 1, N1, N1, N2]),
|
||||||
(&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
|
(&[N1, N1, N1, N1], &[N1], &[ 1, N1, N1, N1, N2]),
|
||||||
(&[ M/2 + 1], &[ 2], &[ 0, 1]),
|
(&[ M/2 + 1], &[ 2], &[ 0, 1]),
|
||||||
(&[0, M/2 + 1], &[ 2], &[ 0, 0, 1]),
|
(&[0, M/2 + 1], &[ 2], &[ 0, 0, 1]),
|
||||||
(&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
|
(&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
|
||||||
(&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
|
(&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]),
|
||||||
(&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
|
(&[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], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
|
||||||
(&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
|
(&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
|
||||||
];
|
];
|
||||||
|
@ -2341,8 +2390,8 @@ mod biguint_tests {
|
||||||
(&[ 1], &[ 2], &[], &[1]),
|
(&[ 1], &[ 2], &[], &[1]),
|
||||||
(&[ 1, 1], &[ 2], &[ M/2+1], &[1]),
|
(&[ 1, 1], &[ 2], &[ M/2+1], &[1]),
|
||||||
(&[ 1, 1, 1], &[ 2], &[ M/2+1, M/2+1], &[1]),
|
(&[ 1, 1, 1], &[ 2], &[ M/2+1, M/2+1], &[1]),
|
||||||
(&[ 0, 1], &[-1], &[1], &[1]),
|
(&[ 0, 1], &[N1], &[1], &[1]),
|
||||||
(&[-1, -1], &[-2], &[2, 1], &[3])
|
(&[N1, N1], &[N2], &[2, 1], &[3])
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2600,17 +2649,15 @@ mod biguint_tests {
|
||||||
for str_pair in rs.iter() {
|
for str_pair in rs.iter() {
|
||||||
let &(ref radix, ref str) = str_pair;
|
let &(ref radix, ref str) = str_pair;
|
||||||
assert_eq!(n,
|
assert_eq!(n,
|
||||||
&FromStrRadix::from_str_radix(str,
|
&BigUint::from_str_radix(str, *radix).unwrap());
|
||||||
*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);
|
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);
|
assert_eq!(blank, None);
|
||||||
let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
|
let minus_one = BigUint::from_str_radix("-1", 10).ok();
|
||||||
10).ok();
|
|
||||||
assert_eq!(minus_one, None);
|
assert_eq!(minus_one, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2629,7 +2676,7 @@ mod biguint_tests {
|
||||||
|
|
||||||
fn check(n: usize, s: &str) {
|
fn check(n: usize, s: &str) {
|
||||||
let n = factor(n);
|
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!()
|
Ok(x) => x, Err(_) => panic!()
|
||||||
};
|
};
|
||||||
assert_eq!(n, ans);
|
assert_eq!(n, ans);
|
||||||
|
@ -2650,7 +2697,7 @@ mod biguint_tests {
|
||||||
assert_eq!(n.bits(), 1);
|
assert_eq!(n.bits(), 1);
|
||||||
let n: BigUint = FromPrimitive::from_usize(3).unwrap();
|
let n: BigUint = FromPrimitive::from_usize(3).unwrap();
|
||||||
assert_eq!(n.bits(), 2);
|
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);
|
assert_eq!(n.bits(), 39);
|
||||||
let one: BigUint = One::one();
|
let one: BigUint = One::one();
|
||||||
assert_eq!((one << 426).bits(), 427);
|
assert_eq!((one << 426).bits(), 427);
|
||||||
|
@ -2713,14 +2760,12 @@ mod bigint_tests {
|
||||||
use std::cmp::Ordering::{Less, Equal, Greater};
|
use std::cmp::Ordering::{Less, Equal, Greater};
|
||||||
use std::i64;
|
use std::i64;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::num::FromStrRadix;
|
|
||||||
use std::num::{ToPrimitive, FromPrimitive};
|
|
||||||
use std::u64;
|
use std::u64;
|
||||||
use std::ops::{Neg};
|
use std::ops::{Neg};
|
||||||
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
|
|
||||||
use {Zero, One, Signed};
|
use {Zero, One, Signed, ToPrimitive, FromPrimitive, Num};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_biguint() {
|
fn test_from_biguint() {
|
||||||
|
@ -2764,7 +2809,7 @@ mod bigint_tests {
|
||||||
assert_eq!(b.to_bytes_be(), (NoSign, vec![0]));
|
assert_eq!(b.to_bytes_be(), (NoSign, vec![0]));
|
||||||
|
|
||||||
// Test with leading/trailing zero bytes and a full BigDigit of value 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]));
|
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]));
|
assert_eq!(b.to_bytes_le(), (NoSign, vec![0]));
|
||||||
|
|
||||||
// Test with leading/trailing zero bytes and a full BigDigit of value 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]));
|
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);
|
assert_eq!(negative.to_biguint(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const N1: BigDigit = -1i32 as BigDigit;
|
||||||
|
const N2: BigDigit = -2i32 as BigDigit;
|
||||||
|
|
||||||
const SUM_TRIPLES: &'static [(&'static [BigDigit],
|
const SUM_TRIPLES: &'static [(&'static [BigDigit],
|
||||||
&'static [BigDigit],
|
&'static [BigDigit],
|
||||||
&'static [BigDigit])] = &[
|
&'static [BigDigit])] = &[
|
||||||
|
@ -2936,11 +2984,11 @@ mod bigint_tests {
|
||||||
(&[], &[ 1], &[ 1]),
|
(&[], &[ 1], &[ 1]),
|
||||||
(&[ 1], &[ 1], &[ 2]),
|
(&[ 1], &[ 1], &[ 2]),
|
||||||
(&[ 1], &[ 1, 1], &[ 2, 1]),
|
(&[ 1], &[ 1, 1], &[ 2, 1]),
|
||||||
(&[ 1], &[-1], &[ 0, 1]),
|
(&[ 1], &[N1], &[ 0, 1]),
|
||||||
(&[ 1], &[-1, -1], &[ 0, 0, 1]),
|
(&[ 1], &[N1, N1], &[ 0, 0, 1]),
|
||||||
(&[-1, -1], &[-1, -1], &[-2, -1, 1]),
|
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
|
||||||
(&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
|
(&[ 1, 1, 1], &[N1, N1], &[ 0, 1, 2]),
|
||||||
(&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
|
(&[ 2, 2, 1], &[N1, N2], &[ 1, 1, 2])
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2992,18 +3040,18 @@ mod bigint_tests {
|
||||||
(&[ 2], &[ 3], &[ 6]),
|
(&[ 2], &[ 3], &[ 6]),
|
||||||
(&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
|
(&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
|
||||||
(&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
|
(&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
|
||||||
(&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
|
(&[ 1, 1, 1], &[N1], &[N1, N1, N1]),
|
||||||
(&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
|
(&[ 1, 2, 3], &[N1], &[N1, N2, N2, 2]),
|
||||||
(&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
|
(&[ 1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]),
|
||||||
(&[-1], &[-1], &[ 1, -2]),
|
(&[N1], &[N1], &[ 1, N2]),
|
||||||
(&[-1, -1], &[-1], &[ 1, -1, -2]),
|
(&[N1, N1], &[N1], &[ 1, N1, N2]),
|
||||||
(&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
|
(&[N1, N1, N1], &[N1], &[ 1, N1, N1, N2]),
|
||||||
(&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
|
(&[N1, N1, N1, N1], &[N1], &[ 1, N1, N1, N1, N2]),
|
||||||
(&[ M/2 + 1], &[ 2], &[ 0, 1]),
|
(&[ M/2 + 1], &[ 2], &[ 0, 1]),
|
||||||
(&[0, M/2 + 1], &[ 2], &[ 0, 0, 1]),
|
(&[0, M/2 + 1], &[ 2], &[ 0, 0, 1]),
|
||||||
(&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
|
(&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
|
||||||
(&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
|
(&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]),
|
||||||
(&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
|
(&[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], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
|
||||||
(&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
|
(&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
|
||||||
];
|
];
|
||||||
|
@ -3016,8 +3064,8 @@ mod bigint_tests {
|
||||||
(&[ 1], &[ 2], &[], &[1]),
|
(&[ 1], &[ 2], &[], &[1]),
|
||||||
(&[ 1, 1], &[ 2], &[ M/2+1], &[1]),
|
(&[ 1, 1], &[ 2], &[ M/2+1], &[1]),
|
||||||
(&[ 1, 1, 1], &[ 2], &[ M/2+1, M/2+1], &[1]),
|
(&[ 1, 1, 1], &[ 2], &[ M/2+1, M/2+1], &[1]),
|
||||||
(&[ 0, 1], &[-1], &[1], &[1]),
|
(&[ 0, 1], &[N1], &[1], &[1]),
|
||||||
(&[-1, -1], &[-2], &[2, 1], &[3])
|
(&[N1, N1], &[N2], &[2, 1], &[3])
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3292,7 +3340,7 @@ mod bigint_tests {
|
||||||
let x: BigInt = FromPrimitive::from_isize(n).unwrap();
|
let x: BigInt = FromPrimitive::from_isize(n).unwrap();
|
||||||
x
|
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("10", Some(10));
|
||||||
check("1", Some(1));
|
check("1", Some(1));
|
||||||
|
@ -3374,15 +3422,13 @@ mod bench {
|
||||||
extern crate test;
|
extern crate test;
|
||||||
use self::test::Bencher;
|
use self::test::Bencher;
|
||||||
use super::BigUint;
|
use super::BigUint;
|
||||||
use std::iter;
|
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::num::FromPrimitive;
|
|
||||||
|
|
||||||
use {Zero, One};
|
use {Zero, One, FromPrimitive};
|
||||||
|
|
||||||
fn factorial(n: usize) -> BigUint {
|
fn factorial(n: usize) -> BigUint {
|
||||||
let mut f: BigUint = One::one();
|
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();
|
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
|
||||||
f = f * bu;
|
f = f * bu;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
//! Complex numbers.
|
//! Complex numbers.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::Float;
|
|
||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
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
|
// FIXME #1284: handle complex NaN & infinity etc. This
|
||||||
// probably doesn't map to C's _Complex correctly.
|
// 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()
|
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`.
|
/// Multiplies `self` by the scalar `t`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn scale(&self, t: T) -> Complex<T> {
|
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)
|
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`
|
/// Returns `1/self`
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inv(&self) -> Complex<T> {
|
pub fn inv(&self) -> Complex<T> {
|
||||||
let norm_sqr = self.norm_sqr();
|
let norm_sqr = self.norm_sqr();
|
||||||
Complex::new(self.re.clone() / norm_sqr.clone(),
|
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>;
|
type Output = Complex<T>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg(self) -> Complex<T> { -&self }
|
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>;
|
type Output = Complex<T>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -241,10 +238,12 @@ impl<T: Clone + Num> One for Complex<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* string conversions */
|
/* 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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.im < Zero::zero() {
|
if self.im < Zero::zero() {
|
||||||
write!(f, "{}-{}i", self.re, -self.im.clone())
|
write!(f, "{}-{}i", self.re, T::zero() - self.im.clone())
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}+{}i", self.re, self.im)
|
write!(f, "{}+{}i", self.re, self.im)
|
||||||
}
|
}
|
||||||
|
@ -257,9 +256,8 @@ mod test {
|
||||||
|
|
||||||
use super::{Complex64, Complex};
|
use super::{Complex64, Complex};
|
||||||
use std::f64;
|
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 _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
|
||||||
pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
|
pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
|
||||||
|
|
|
@ -10,12 +10,13 @@
|
||||||
|
|
||||||
//! Integer trait and functions.
|
//! Integer trait and functions.
|
||||||
|
|
||||||
use std::ops::{Div, Rem};
|
|
||||||
|
|
||||||
use {Num, Signed};
|
use {Num, Signed};
|
||||||
|
|
||||||
pub trait Integer: Sized + Num + PartialOrd
|
pub trait Integer
|
||||||
+ Div<Self, Output = Self> + Rem<Self, Output = Self> {
|
: Sized
|
||||||
|
+ Num
|
||||||
|
+ PartialOrd + Ord + Eq
|
||||||
|
{
|
||||||
/// Floored integer division.
|
/// Floored integer division.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
|
|
||||||
//! External iterators for generic mathematics
|
//! External iterators for generic mathematics
|
||||||
|
|
||||||
use {Integer, Zero, One, CheckedAdd};
|
use {Integer, Zero, One, CheckedAdd, ToPrimitive};
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub};
|
||||||
use std::num::{ToPrimitive, Int};
|
|
||||||
|
|
||||||
/// An iterator over the range [start, stop)
|
/// An iterator over the range [start, stop)
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -260,10 +259,9 @@ impl<A> Iterator for RangeStepInclusive<A>
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use std::num::ToPrimitive;
|
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use One;
|
use {One, ToPrimitive};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range() {
|
fn test_range() {
|
||||||
|
@ -328,7 +326,6 @@ mod tests {
|
||||||
// this test is only meaningful when sizeof usize < sizeof u64
|
// 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(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(-10, -1).size_hint(), (9, Some(9)));
|
||||||
assert_eq!(super::range(Foo, Foo).size_hint(), (0, None));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
|
//! [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, deny(warnings))]
|
||||||
#![cfg_attr(test, feature(hash, test))]
|
#![cfg_attr(test, feature(hash, test))]
|
||||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
#![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/")]
|
html_playground_url = "http://play.rust-lang.org/")]
|
||||||
|
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate core;
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
pub use bigint::{BigInt, BigUint};
|
pub use bigint::{BigInt, BigUint};
|
||||||
|
@ -61,7 +59,8 @@ pub use complex::Complex;
|
||||||
pub use integer::Integer;
|
pub use integer::Integer;
|
||||||
pub use iter::{range, range_inclusive, range_step, range_step_inclusive};
|
pub use iter::{range, range_inclusive, range_step, range_step_inclusive};
|
||||||
pub use traits::{Num, Zero, One, Signed, Unsigned, Bounded,
|
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;
|
#[cfg(test)] use std::hash;
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::num::{FromPrimitive, FromStrRadix, Float};
|
|
||||||
|
|
||||||
|
use traits::{FromPrimitive, Float};
|
||||||
use bigint::{BigInt, BigUint, Sign};
|
use bigint::{BigInt, BigUint, Sign};
|
||||||
use {Num, Signed, Zero, One};
|
use {Num, Signed, Zero, One};
|
||||||
|
|
||||||
|
@ -38,8 +38,7 @@ pub type Rational64 = Ratio<i64>;
|
||||||
/// Alias for arbitrary precision rationals.
|
/// Alias for arbitrary precision rationals.
|
||||||
pub type BigRational = Ratio<BigInt>;
|
pub type BigRational = Ratio<BigInt>;
|
||||||
|
|
||||||
impl<T: Clone + Integer + PartialOrd>
|
impl<T: Clone + Integer + PartialOrd> Ratio<T> {
|
||||||
Ratio<T> {
|
|
||||||
/// Creates a ratio representing the integer `t`.
|
/// Creates a ratio representing the integer `t`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_integer(t: T) -> Ratio<T> {
|
pub fn from_integer(t: T) -> Ratio<T> {
|
||||||
|
@ -99,9 +98,9 @@ impl<T: Clone + Integer + PartialOrd>
|
||||||
self.denom = self.denom.clone() / g;
|
self.denom = self.denom.clone() / g;
|
||||||
|
|
||||||
// keep denom positive!
|
// keep denom positive!
|
||||||
if self.denom < Zero::zero() {
|
if self.denom < T::zero() {
|
||||||
self.numer = -self.numer.clone();
|
self.numer = T::zero() - self.numer.clone();
|
||||||
self.denom = -self.denom.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.
|
/// Rounds to the nearest integer. Rounds half-way cases away from zero.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn round(&self) -> Ratio<T> {
|
pub fn round(&self) -> Ratio<T> {
|
||||||
|
let zero: Ratio<T> = Zero::zero();
|
||||||
let one: T = One::one();
|
let one: T = One::one();
|
||||||
let two: T = one.clone() + one.clone();
|
let two: T = one.clone() + one.clone();
|
||||||
|
|
||||||
// Find unsigned fractional part of rational number
|
// 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
|
// 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
|
// 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>
|
// return something other than a Ratio<T>
|
||||||
(impl $imp:ident, $($method:ident -> $res:ty),*) => {
|
(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]
|
#[inline]
|
||||||
fn $method(&self, other: &Ratio<T>) -> $res {
|
fn $method(&self, other: &Ratio<T>) -> $res {
|
||||||
|
@ -247,7 +250,9 @@ macro_rules! forward_val_val_binop {
|
||||||
|
|
||||||
macro_rules! forward_ref_val_binop {
|
macro_rules! forward_ref_val_binop {
|
||||||
(impl $imp:ident, $method:ident) => {
|
(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>;
|
type Output = Ratio<T>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -260,7 +265,9 @@ macro_rules! forward_ref_val_binop {
|
||||||
|
|
||||||
macro_rules! forward_val_ref_binop {
|
macro_rules! forward_val_ref_binop {
|
||||||
(impl $imp:ident, $method:ident) => {
|
(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>;
|
type Output = Ratio<T>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -332,7 +339,7 @@ arith_impl!(impl Sub, sub);
|
||||||
arith_impl!(impl Rem, rem);
|
arith_impl!(impl Rem, rem);
|
||||||
|
|
||||||
impl<T> Neg for Ratio<T>
|
impl<T> Neg for Ratio<T>
|
||||||
where T: Clone + Integer + PartialOrd
|
where T: Clone + Integer + PartialOrd + Neg<Output = T>
|
||||||
{
|
{
|
||||||
type Output = Ratio<T>;
|
type Output = Ratio<T>;
|
||||||
|
|
||||||
|
@ -341,7 +348,7 @@ impl<T> Neg for Ratio<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Neg for &'a 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>;
|
type Output = Ratio<T>;
|
||||||
|
|
||||||
|
@ -373,11 +380,30 @@ impl<T: Clone + Integer + PartialOrd>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + Integer + PartialOrd>
|
impl<T: Clone + Integer + PartialOrd> Num for Ratio<T> {
|
||||||
Num for Ratio<T> {}
|
type FromStrRadixErr = ParseRatioError;
|
||||||
|
|
||||||
impl<T: Clone + Integer + PartialOrd>
|
/// Parses `numer/denom` where the numbers are in base `radix`.
|
||||||
Signed for Ratio<T> {
|
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]
|
#[inline]
|
||||||
fn abs(&self) -> Ratio<T> {
|
fn abs(&self) -> Ratio<T> {
|
||||||
if self.is_negative() { -self.clone() } else { self.clone() }
|
if self.is_negative() { -self.clone() } else { self.clone() }
|
||||||
|
@ -407,7 +433,9 @@ impl<T: Clone + Integer + PartialOrd>
|
||||||
}
|
}
|
||||||
|
|
||||||
/* String conversions */
|
/* 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.
|
/// Renders as `numer/denom`. If denom=1, renders as numer.
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.denom == One::one() {
|
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>
|
impl<T: FromStr + Clone + Integer + PartialOrd> FromStr for Ratio<T> {
|
||||||
FromStr for Ratio<T> {
|
|
||||||
type Err = ParseRatioError;
|
type Err = ParseRatioError;
|
||||||
|
|
||||||
/// Parses `numer/denom` or just `numer`.
|
/// 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
|
// FIXME: Bubble up specific errors
|
||||||
#[derive(Copy, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct ParseRatioError;
|
pub struct ParseRatioError;
|
||||||
|
|
||||||
impl fmt::Display for ParseRatioError {
|
impl fmt::Display for ParseRatioError {
|
||||||
|
@ -478,10 +481,9 @@ impl Error for ParseRatioError {
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use super::{Ratio, Rational, BigRational};
|
use super::{Ratio, Rational, BigRational};
|
||||||
use std::num::{FromPrimitive, Float};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use {Zero, One, Signed};
|
use {Zero, One, Signed, FromPrimitive, Float};
|
||||||
|
|
||||||
pub const _0 : Rational = Ratio { numer: 0, denom: 1};
|
pub const _0 : Rational = Ratio { numer: 0, denom: 1};
|
||||||
pub const _1 : Rational = Ratio { numer: 1, denom: 1};
|
pub const _1 : Rational = Ratio { numer: 1, denom: 1};
|
||||||
|
|
308
src/traits.rs
308
src/traits.rs
|
@ -10,27 +10,54 @@
|
||||||
|
|
||||||
//! Numeric traits for generic mathematics
|
//! Numeric traits for generic mathematics
|
||||||
|
|
||||||
use std::intrinsics;
|
|
||||||
use std::ops::{Add, Sub, Mul, Div, Rem, Neg};
|
use std::ops::{Add, Sub, Mul, Div, Rem, Neg};
|
||||||
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||||
use std::{usize, u8, u16, u32, u64};
|
use std::{usize, u8, u16, u32, u64};
|
||||||
use std::{isize, i8, i16, i32, i64};
|
use std::{isize, i8, i16, i32, i64};
|
||||||
use std::{f32, f64};
|
use std::{f32, f64};
|
||||||
use std::mem::size_of;
|
use std::mem::{self, size_of};
|
||||||
use std::num::FpCategory;
|
use std::num::FpCategory;
|
||||||
|
|
||||||
/// The base trait for numeric types
|
/// The base trait for numeric types
|
||||||
pub trait Num: PartialEq + Zero + One
|
pub trait Num: PartialEq + Zero + One
|
||||||
+ Neg<Output = Self> + Add<Output = Self> + Sub<Output = Self>
|
+ Add<Output = Self> + Sub<Output = Self>
|
||||||
+ Mul<Output = Self> + Div<Output = Self> + Rem<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)*) => ($(
|
($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`.
|
/// Defines an additive identity element for `Self`.
|
||||||
///
|
///
|
||||||
|
@ -132,7 +159,6 @@ one_impl!(i64, 1i64);
|
||||||
one_impl!(f32, 1.0f32);
|
one_impl!(f32, 1.0f32);
|
||||||
one_impl!(f64, 1.0f64);
|
one_impl!(f64, 1.0f64);
|
||||||
|
|
||||||
|
|
||||||
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
||||||
pub trait Signed: Num + Neg<Output = Self> {
|
pub trait Signed: Num + Neg<Output = Self> {
|
||||||
/// Computes the absolute value.
|
/// Computes the absolute value.
|
||||||
|
@ -204,12 +230,12 @@ macro_rules! signed_impl {
|
||||||
signed_impl!(isize i8 i16 i32 i64);
|
signed_impl!(isize i8 i16 i32 i64);
|
||||||
|
|
||||||
macro_rules! signed_float_impl {
|
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 {
|
impl Signed for $t {
|
||||||
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs(&self) -> $t {
|
fn abs(&self) -> $t {
|
||||||
unsafe { $fabs(*self) }
|
<$t>::abs(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The positive difference of two numbers. Returns `0.0` if the number is
|
/// 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.
|
/// and `other` is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs_sub(&self, other: &$t) -> $t {
|
fn abs_sub(&self, other: &$t) -> $t {
|
||||||
extern { fn $fdim(a: $t, b: $t) -> $t; }
|
<$t>::abs_sub(*self, *other)
|
||||||
unsafe { $fdim(*self, *other) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -228,9 +253,7 @@ macro_rules! signed_float_impl {
|
||||||
/// - `NAN` if the number is NaN
|
/// - `NAN` if the number is NaN
|
||||||
#[inline]
|
#[inline]
|
||||||
fn signum(&self) -> $t {
|
fn signum(&self) -> $t {
|
||||||
if self != self { $nan } else {
|
<$t>::signum(*self)
|
||||||
unsafe { $fcopysign(1.0, *self) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
/// 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,
|
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);
|
||||||
signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY,
|
|
||||||
intrinsics::fabsf64, intrinsics::copysignf64, fdim);
|
|
||||||
|
|
||||||
/// A trait for values which cannot be negative
|
/// A trait for values which cannot be negative
|
||||||
pub trait Unsigned: Num {}
|
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
|
/// Numbers which have upper and lower bounds
|
||||||
pub trait Bounded {
|
pub trait Bounded {
|
||||||
|
@ -336,51 +363,27 @@ pub trait CheckedAdd: Add<Self, Output = Self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! checked_impl {
|
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 {
|
impl $trait_name for $t {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $method(&self, v: &$t) -> Option<$t> {
|
fn $method(&self, v: &$t) -> Option<$t> {
|
||||||
unsafe {
|
<$t>::$method(*self, *v)
|
||||||
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) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
checked_impl!(CheckedAdd, checked_add, u8);
|
||||||
checked_cast_impl!(CheckedAdd, checked_add, usize, u32, intrinsics::u32_add_with_overflow);
|
checked_impl!(CheckedAdd, checked_add, u16);
|
||||||
#[cfg(target_pointer_width = "64")]
|
checked_impl!(CheckedAdd, checked_add, u32);
|
||||||
checked_cast_impl!(CheckedAdd, checked_add, usize, u64, intrinsics::u64_add_with_overflow);
|
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, i8);
|
||||||
checked_impl!(CheckedAdd, checked_add, u16, intrinsics::u16_add_with_overflow);
|
checked_impl!(CheckedAdd, checked_add, i16);
|
||||||
checked_impl!(CheckedAdd, checked_add, u32, intrinsics::u32_add_with_overflow);
|
checked_impl!(CheckedAdd, checked_add, i32);
|
||||||
checked_impl!(CheckedAdd, checked_add, u64, intrinsics::u64_add_with_overflow);
|
checked_impl!(CheckedAdd, checked_add, i64);
|
||||||
|
checked_impl!(CheckedAdd, checked_add, isize);
|
||||||
#[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);
|
|
||||||
|
|
||||||
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
||||||
pub trait CheckedSub: Sub<Self, Output = Self> {
|
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>;
|
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
checked_impl!(CheckedSub, checked_sub, u8);
|
||||||
checked_cast_impl!(CheckedSub, checked_sub, usize, u32, intrinsics::u32_sub_with_overflow);
|
checked_impl!(CheckedSub, checked_sub, u16);
|
||||||
#[cfg(target_pointer_width = "64")]
|
checked_impl!(CheckedSub, checked_sub, u32);
|
||||||
checked_cast_impl!(CheckedSub, checked_sub, usize, u64, intrinsics::u64_sub_with_overflow);
|
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, i8);
|
||||||
checked_impl!(CheckedSub, checked_sub, u16, intrinsics::u16_sub_with_overflow);
|
checked_impl!(CheckedSub, checked_sub, i16);
|
||||||
checked_impl!(CheckedSub, checked_sub, u32, intrinsics::u32_sub_with_overflow);
|
checked_impl!(CheckedSub, checked_sub, i32);
|
||||||
checked_impl!(CheckedSub, checked_sub, u64, intrinsics::u64_sub_with_overflow);
|
checked_impl!(CheckedSub, checked_sub, i64);
|
||||||
|
checked_impl!(CheckedSub, checked_sub, isize);
|
||||||
#[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);
|
|
||||||
|
|
||||||
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
||||||
/// overflow.
|
/// overflow.
|
||||||
|
@ -417,25 +412,17 @@ pub trait CheckedMul: Mul<Self, Output = Self> {
|
||||||
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
checked_impl!(CheckedMul, checked_mul, u8);
|
||||||
checked_cast_impl!(CheckedMul, checked_mul, usize, u32, intrinsics::u32_mul_with_overflow);
|
checked_impl!(CheckedMul, checked_mul, u16);
|
||||||
#[cfg(target_pointer_width = "64")]
|
checked_impl!(CheckedMul, checked_mul, u32);
|
||||||
checked_cast_impl!(CheckedMul, checked_mul, usize, u64, intrinsics::u64_mul_with_overflow);
|
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, i8);
|
||||||
checked_impl!(CheckedMul, checked_mul, u16, intrinsics::u16_mul_with_overflow);
|
checked_impl!(CheckedMul, checked_mul, i16);
|
||||||
checked_impl!(CheckedMul, checked_mul, u32, intrinsics::u32_mul_with_overflow);
|
checked_impl!(CheckedMul, checked_mul, i32);
|
||||||
checked_impl!(CheckedMul, checked_mul, u64, intrinsics::u64_mul_with_overflow);
|
checked_impl!(CheckedMul, checked_mul, i64);
|
||||||
|
checked_impl!(CheckedMul, checked_mul, isize);
|
||||||
#[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);
|
|
||||||
|
|
||||||
/// Performs division that returns `None` instead of panicking on division by zero and instead of
|
/// Performs division that returns `None` instead of panicking on division by zero and instead of
|
||||||
/// wrapping around on underflow and overflow.
|
/// wrapping around on underflow and overflow.
|
||||||
|
@ -483,12 +470,12 @@ macro_rules! checkeddiv_uint_impl {
|
||||||
|
|
||||||
checkeddiv_uint_impl!(usize u8 u16 u32 u64);
|
checkeddiv_uint_impl!(usize u8 u16 u32 u64);
|
||||||
|
|
||||||
pub trait Int
|
pub trait PrimInt
|
||||||
: Num
|
: Sized
|
||||||
+ Clone
|
+ Copy
|
||||||
+ NumCast
|
+ Num + NumCast
|
||||||
+ PartialOrd + Ord
|
+ Bounded
|
||||||
+ Eq
|
+ PartialOrd + Ord + Eq
|
||||||
+ Not<Output=Self>
|
+ Not<Output=Self>
|
||||||
+ BitAnd<Output=Self>
|
+ BitAnd<Output=Self>
|
||||||
+ BitOr<Output=Self>
|
+ BitOr<Output=Self>
|
||||||
|
@ -501,12 +488,6 @@ pub trait Int
|
||||||
+ CheckedDiv<Output=Self>
|
+ CheckedDiv<Output=Self>
|
||||||
+ Saturating
|
+ 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`.
|
/// Returns the number of ones in the binary representation of `self`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -693,9 +674,9 @@ pub trait Int
|
||||||
fn pow(self, mut exp: u32) -> Self;
|
fn pow(self, mut exp: u32) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! int_impl {
|
macro_rules! prim_int_impl {
|
||||||
($($T:ty)*) => ($(
|
($($T:ty)*) => ($(
|
||||||
impl Int for $T {
|
impl PrimInt for $T {
|
||||||
fn min_value() -> Self {
|
fn min_value() -> Self {
|
||||||
<$T>::min_value()
|
<$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.
|
/// A generic trait for converting a value to a number.
|
||||||
pub trait ToPrimitive {
|
pub trait ToPrimitive {
|
||||||
/// Converts the value of `self` to an `isize`.
|
/// Converts the value of `self` to an `isize`.
|
||||||
|
@ -834,8 +813,8 @@ macro_rules! impl_to_primitive_int_to_int {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
let n = $slf as i64;
|
let n = $slf as i64;
|
||||||
let min_value: $DstT = Int::min_value();
|
let min_value: $DstT = Bounded::min_value();
|
||||||
let max_value: $DstT = Int::max_value();
|
let max_value: $DstT = Bounded::max_value();
|
||||||
if min_value as i64 <= n && n <= max_value as i64 {
|
if min_value as i64 <= n && n <= max_value as i64 {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -850,7 +829,7 @@ macro_rules! impl_to_primitive_int_to_uint {
|
||||||
($SrcT:ty, $DstT:ty, $slf:expr) => (
|
($SrcT:ty, $DstT:ty, $slf:expr) => (
|
||||||
{
|
{
|
||||||
let zero: $SrcT = Zero::zero();
|
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 {
|
if zero <= $slf && $slf as u64 <= max_value as u64 {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -902,7 +881,7 @@ impl_to_primitive_int! { i64 }
|
||||||
macro_rules! impl_to_primitive_uint_to_int {
|
macro_rules! impl_to_primitive_uint_to_int {
|
||||||
($DstT:ty, $slf:expr) => (
|
($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 {
|
if $slf as u64 <= max_value as u64 {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -919,7 +898,7 @@ macro_rules! impl_to_primitive_uint_to_uint {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
let zero: $SrcT = Zero::zero();
|
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 {
|
if zero <= $slf && $slf as u64 <= max_value as u64 {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1189,9 +1168,10 @@ impl_num_cast! { f64, to_f64 }
|
||||||
|
|
||||||
pub trait Float
|
pub trait Float
|
||||||
: Num
|
: Num
|
||||||
+ Clone
|
+ Copy
|
||||||
+ NumCast
|
+ NumCast
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
|
+ Neg<Output = Self>
|
||||||
{
|
{
|
||||||
/// Returns the `NaN` value.
|
/// Returns the `NaN` value.
|
||||||
///
|
///
|
||||||
|
@ -1671,36 +1651,6 @@ pub trait Float
|
||||||
/// ```
|
/// ```
|
||||||
fn log10(self) -> Self;
|
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.
|
/// Returns the maximum of the two numbers.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2039,10 +1989,34 @@ pub trait Float
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn atanh(self) -> Self;
|
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 {
|
macro_rules! float_impl {
|
||||||
($($T:ident)*) => ($(
|
($T:ident $decode:ident) => (
|
||||||
impl Float for $T {
|
impl Float for $T {
|
||||||
fn nan() -> Self {
|
fn nan() -> Self {
|
||||||
::std::$T::NAN
|
::std::$T::NAN
|
||||||
|
@ -2168,14 +2142,6 @@ macro_rules! float_impl {
|
||||||
<$T>::log10(self)
|
<$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 {
|
fn max(self, other: Self) -> Self {
|
||||||
<$T>::max(self, other)
|
<$T>::max(self, other)
|
||||||
}
|
}
|
||||||
|
@ -2260,8 +2226,40 @@ macro_rules! float_impl {
|
||||||
<$T>::atanh(self)
|
<$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);
|
||||||
|
|
Loading…
Reference in New Issue