diff --git a/Cargo.toml b/Cargo.toml index 1c63d4f..08ac69b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/README.md b/README.md index 766efc3..13e4847 100644 --- a/README.md +++ b/README.md @@ -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, diff --git a/bigint/src/algorithms.rs b/bigint/src/algorithms.rs index 604fee2..3560103 100644 --- a/bigint/src/algorithms.rs +++ b/bigint/src/algorithms.rs @@ -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 diff --git a/bigint/src/bigint.rs b/bigint/src/bigint.rs index 259f619..bae78d7 100644 --- a/bigint/src/bigint.rs +++ b/bigint/src/bigint.rs @@ -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. diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs index 2c2d046..c77328f 100644 --- a/bigint/src/biguint.rs +++ b/bigint/src/biguint.rs @@ -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 for &'a BigUint { } sub2rev(&self.data[..], &mut other.data[..]); - other.normalize() + other.normalized() } } @@ -477,7 +477,7 @@ impl Sub 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 for BigDigit { } sub2rev(&[self], &mut other.data[..]); - other.normalize() + other.normalized() } } @@ -502,7 +502,7 @@ impl Sub 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 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) -> 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 } } diff --git a/bigint/src/tests/bigint.rs b/bigint/src/tests/bigint.rs index 9fbebb0..a3c8f6f 100644 --- a/bigint/src/tests/bigint.rs +++ b/bigint/src/tests/bigint.rs @@ -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) { diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs index 0f3b743..c4be751 100644 --- a/bigint/src/tests/biguint.rs +++ b/bigint/src/tests/biguint.rs @@ -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) { diff --git a/complex/Cargo.toml b/complex/Cargo.toml index 26a1bd2..911986e 100644 --- a/complex/Cargo.toml +++ b/complex/Cargo.toml @@ -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