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"
version = "0.1.40"
[badges]
travis-ci = { repository = "rust-num/num" }
[[bench]]
name = "bigint"

View File

@ -1,5 +1,7 @@
# 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.
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;
}
(a.normalize(), rem)
(a.normalized(), rem)
}
// Only for the Add impl:
@ -339,7 +339,7 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
mac3(&mut p.data[..], x1, y1);
// 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 * 2..], &p.data[..]);
@ -350,7 +350,7 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
// p0 = x0 * y0
mac3(&mut p.data[..], x0, y0);
p = p.normalize();
p.normalize();
add2(&mut acc[..], &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));
mac3(&mut p.data[..], &j0.data[..], &j1.data[..]);
p = p.normalize();
p.normalize();
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] };
mac3(&mut prod.data[..], x, y);
prod.normalize()
prod.normalized()
}
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[..]);
sub2(&mut a.data[j..], &prod.data[..]);
a = a.normalize();
a.normalize();
tmp = q0;
}
debug_assert!(a < b);
(q.normalize(), a >> shift)
(q.normalized(), a >> shift)
}
/// Find last set bit

View File

@ -1376,13 +1376,13 @@ impl BigInt {
///
/// The digits are in little-endian base 2^32.
#[inline]
pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
if sign == NoSign || data.is_zero() {
return BigInt {
sign: NoSign,
data: Zero::zero(),
};
pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt {
if sign == NoSign {
data.assign_from_slice(&[]);
} else if data.is_zero() {
sign = NoSign;
}
BigInt {
sign: sign,
data: data,
@ -1395,6 +1395,21 @@ impl BigInt {
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`.
///
/// 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 {
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[..]);
other.normalize()
other.normalized()
}
}
@ -477,7 +477,7 @@ impl Sub<BigDigit> for BigUint {
#[inline]
fn sub(mut self, other: BigDigit) -> BigUint {
sub2(&mut self.data[..], &[other]);
self.normalize()
self.normalized()
}
}
@ -491,7 +491,7 @@ impl Sub<BigUint> for BigDigit {
}
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 {
let (hi, lo) = big_digit::from_doublebigdigit(other);
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);
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.
#[inline]
pub fn new(digits: Vec<BigDigit>) -> BigUint {
BigUint { data: digits }.normalize()
BigUint { data: digits }.normalized()
}
/// Creates and initializes a `BigUint`.
@ -1186,6 +1186,16 @@ impl BigUint {
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`.
///
/// 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
/// be nonzero.
#[inline]
fn normalize(mut self) -> BigUint {
fn normalize(&mut self) {
while let Some(&0) = self.data.last() {
self.data.pop();
}
}
/// Returns a normalized `BigUint`.
#[inline]
fn normalized(mut self) -> BigUint {
self.normalize();
self
}
}

View File

@ -59,6 +59,39 @@ fn test_from_biguint() {
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]
fn test_from_bytes_be() {
fn check(s: &str, result: &str) {

View File

@ -56,6 +56,21 @@ fn test_from_slice() {
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]
fn test_from_bytes_be() {
fn check(s: &str, result: &str) {

View File

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