Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Isaac Carruthers 2017-08-09 18:10:54 -04:00
commit 2dcb722007
8 changed files with 107 additions and 23 deletions

View File

@ -10,6 +10,9 @@ repository = "https://github.com/rust-num/num"
name = "num" name = "num"
version = "0.1.40" version = "0.1.40"
[badges]
travis-ci = { repository = "rust-num/num" }
[[bench]] [[bench]]
name = "bigint" name = "bigint"

View File

@ -1,5 +1,7 @@
# num # num
[![](https://travis-ci.org/rust-num/num.svg)](https://travis-ci.org/rust-num/num)
A collection of numeric types and traits for Rust. A collection of numeric types and traits for Rust.
This includes new types for big integers, rationals, and complex numbers, This includes new types for big integers, rationals, and complex numbers,

View File

@ -118,7 +118,7 @@ pub fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) {
rem = r; rem = r;
} }
(a.normalize(), rem) (a.normalized(), rem)
} }
// Only for the Add impl: // Only for the Add impl:
@ -339,7 +339,7 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
mac3(&mut p.data[..], x1, y1); mac3(&mut p.data[..], x1, y1);
// Not required, but the adds go faster if we drop any unneeded 0s from the end: // Not required, but the adds go faster if we drop any unneeded 0s from the end:
p = p.normalize(); p.normalize();
add2(&mut acc[b..], &p.data[..]); add2(&mut acc[b..], &p.data[..]);
add2(&mut acc[b * 2..], &p.data[..]); add2(&mut acc[b * 2..], &p.data[..]);
@ -350,7 +350,7 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
// p0 = x0 * y0 // p0 = x0 * y0
mac3(&mut p.data[..], x0, y0); mac3(&mut p.data[..], x0, y0);
p = p.normalize(); p.normalize();
add2(&mut acc[..], &p.data[..]); add2(&mut acc[..], &p.data[..]);
add2(&mut acc[b..], &p.data[..]); add2(&mut acc[b..], &p.data[..]);
@ -366,7 +366,7 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
p.data.extend(repeat(0).take(len)); p.data.extend(repeat(0).take(len));
mac3(&mut p.data[..], &j0.data[..], &j1.data[..]); mac3(&mut p.data[..], &j0.data[..], &j1.data[..]);
p = p.normalize(); p.normalize();
sub2(&mut acc[b..], &p.data[..]); sub2(&mut acc[b..], &p.data[..]);
}, },
@ -383,7 +383,7 @@ pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
let mut prod = BigUint { data: vec![0; len] }; let mut prod = BigUint { data: vec![0; len] };
mac3(&mut prod.data[..], x, y); mac3(&mut prod.data[..], x, y);
prod.normalize() prod.normalized()
} }
pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit {
@ -480,14 +480,14 @@ pub fn div_rem(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
add2(&mut q.data[j..], &q0.data[..]); add2(&mut q.data[j..], &q0.data[..]);
sub2(&mut a.data[j..], &prod.data[..]); sub2(&mut a.data[j..], &prod.data[..]);
a = a.normalize(); a.normalize();
tmp = q0; tmp = q0;
} }
debug_assert!(a < b); debug_assert!(a < b);
(q.normalize(), a >> shift) (q.normalized(), a >> shift)
} }
/// Find last set bit /// Find last set bit

View File

@ -1376,13 +1376,13 @@ impl BigInt {
/// ///
/// The digits are in little-endian base 2^32. /// The digits are in little-endian base 2^32.
#[inline] #[inline]
pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt { pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt {
if sign == NoSign || data.is_zero() { if sign == NoSign {
return BigInt { data.assign_from_slice(&[]);
sign: NoSign, } else if data.is_zero() {
data: Zero::zero(), sign = NoSign;
};
} }
BigInt { BigInt {
sign: sign, sign: sign,
data: data, data: data,
@ -1395,6 +1395,21 @@ impl BigInt {
BigInt::from_biguint(sign, BigUint::from_slice(slice)) BigInt::from_biguint(sign, BigUint::from_slice(slice))
} }
/// Reinitializes a `BigInt`.
#[inline]
pub fn assign_from_slice(&mut self, sign: Sign, slice: &[BigDigit]) {
if sign == NoSign {
self.data.assign_from_slice(&[]);
self.sign = NoSign;
} else {
self.data.assign_from_slice(slice);
self.sign = match self.data.is_zero() {
true => NoSign,
false => sign,
}
}
}
/// Creates and initializes a `BigInt`. /// Creates and initializes a `BigInt`.
/// ///
/// The bytes are in big-endian byte order. /// The bytes are in big-endian byte order.

View File

@ -449,7 +449,7 @@ impl<'a> Sub<&'a BigUint> for BigUint {
fn sub(mut self, other: &BigUint) -> BigUint { fn sub(mut self, other: &BigUint) -> BigUint {
sub2(&mut self.data[..], &other.data[..]); sub2(&mut self.data[..], &other.data[..]);
self.normalize() self.normalized()
} }
} }
@ -463,7 +463,7 @@ impl<'a> Sub<BigUint> for &'a BigUint {
} }
sub2rev(&self.data[..], &mut other.data[..]); sub2rev(&self.data[..], &mut other.data[..]);
other.normalize() other.normalized()
} }
} }
@ -477,7 +477,7 @@ impl Sub<BigDigit> for BigUint {
#[inline] #[inline]
fn sub(mut self, other: BigDigit) -> BigUint { fn sub(mut self, other: BigDigit) -> BigUint {
sub2(&mut self.data[..], &[other]); sub2(&mut self.data[..], &[other]);
self.normalize() self.normalized()
} }
} }
@ -491,7 +491,7 @@ impl Sub<BigUint> for BigDigit {
} }
sub2rev(&[self], &mut other.data[..]); sub2rev(&[self], &mut other.data[..]);
other.normalize() other.normalized()
} }
} }
@ -502,7 +502,7 @@ impl Sub<DoubleBigDigit> for BigUint {
fn sub(mut self, other: DoubleBigDigit) -> BigUint { fn sub(mut self, other: DoubleBigDigit) -> BigUint {
let (hi, lo) = big_digit::from_doublebigdigit(other); let (hi, lo) = big_digit::from_doublebigdigit(other);
sub2(&mut self.data[..], &[lo, hi]); sub2(&mut self.data[..], &[lo, hi]);
self.normalize() self.normalized()
} }
} }
@ -517,7 +517,7 @@ impl Sub<BigUint> for DoubleBigDigit {
let (hi, lo) = big_digit::from_doublebigdigit(self); let (hi, lo) = big_digit::from_doublebigdigit(self);
sub2rev(&[lo, hi], &mut other.data[..]); sub2rev(&[lo, hi], &mut other.data[..]);
other.normalize() other.normalized()
} }
} }
@ -1175,7 +1175,7 @@ impl BigUint {
/// The digits are in little-endian base 2^32. /// The digits are in little-endian base 2^32.
#[inline] #[inline]
pub fn new(digits: Vec<BigDigit>) -> BigUint { pub fn new(digits: Vec<BigDigit>) -> BigUint {
BigUint { data: digits }.normalize() BigUint { data: digits }.normalized()
} }
/// Creates and initializes a `BigUint`. /// Creates and initializes a `BigUint`.
@ -1186,6 +1186,16 @@ impl BigUint {
BigUint::new(slice.to_vec()) BigUint::new(slice.to_vec())
} }
/// Assign a value to a `BigUint`.
///
/// The digits are in little-endian base 2^32.
#[inline]
pub fn assign_from_slice(&mut self, slice: &[BigDigit]) {
self.data.resize(slice.len(), 0);
self.data.clone_from_slice(slice);
self.normalize();
}
/// Creates and initializes a `BigUint`. /// Creates and initializes a `BigUint`.
/// ///
/// The bytes are in big-endian byte order. /// The bytes are in big-endian byte order.
@ -1436,10 +1446,16 @@ impl BigUint {
/// Strips off trailing zero bigdigits - comparisons require the last element in the vector to /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to
/// be nonzero. /// be nonzero.
#[inline] #[inline]
fn normalize(mut self) -> BigUint { fn normalize(&mut self) {
while let Some(&0) = self.data.last() { while let Some(&0) = self.data.last() {
self.data.pop(); self.data.pop();
} }
}
/// Returns a normalized `BigUint`.
#[inline]
fn normalized(mut self) -> BigUint {
self.normalize();
self self
} }
} }

View File

@ -59,6 +59,39 @@ fn test_from_biguint() {
check(NoSign, 1, NoSign, 0); check(NoSign, 1, NoSign, 0);
} }
#[test]
fn test_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let inp = BigInt::from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_assign_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]);
inp.assign_from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: FromPrimitive::from_u32(ans_n).unwrap(),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test] #[test]
fn test_from_bytes_be() { fn test_from_bytes_be() {
fn check(s: &str, result: &str) { fn check(s: &str, result: &str) {

View File

@ -56,6 +56,21 @@ fn test_from_slice() {
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
} }
#[test]
fn test_assign_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]);
p.assign_from_slice(slice);
assert!(p.data == data);
}
check(&[1], &[1]);
check(&[0, 0, 0], &[]);
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(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
}
#[test] #[test]
fn test_from_bytes_be() { fn test_from_bytes_be() {
fn check(s: &str, result: &str) { fn check(s: &str, result: &str) {

View File

@ -8,14 +8,14 @@ categories = [ "algorithms", "data-structures", "science" ]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
name = "num-complex" name = "num-complex"
repository = "https://github.com/rust-num/num" repository = "https://github.com/rust-num/num"
version = "0.1.39" version = "0.1.40"
[dependencies] [dependencies]
[dependencies.num-traits] [dependencies.num-traits]
optional = false optional = false
path = "../traits" path = "../traits"
version = "0.1.32" version = "0.1.39"
[dependencies.rustc-serialize] [dependencies.rustc-serialize]
optional = true optional = true