Implement assign_from_slice
This commit is contained in:
parent
54fe41f305
commit
9b56d6667c
|
@ -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
|
||||
|
|
|
@ -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]) {
|
||||
// Normalize:
|
||||
let slice = &slice[..slice.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)];
|
||||
|
||||
if sign == NoSign || slice.len() == 0 {
|
||||
self.sign = NoSign;
|
||||
self.data = Zero::zero();
|
||||
} else {
|
||||
self.sign = sign;
|
||||
self.data.assign_from_slice(slice);
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and initializes a `BigInt`.
|
||||
///
|
||||
/// The bytes are in big-endian byte order.
|
||||
|
|
|
@ -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.copy_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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue