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;
|
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
|
||||||
|
|
|
@ -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]) {
|
||||||
|
// 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`.
|
/// Creates and initializes a `BigInt`.
|
||||||
///
|
///
|
||||||
/// The bytes are in big-endian byte order.
|
/// 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 {
|
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.copy_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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue