feat: use SmallVec as backing store

This commit is contained in:
dignifiedquire 2018-12-19 19:46:26 +01:00
parent 73a3f1eacb
commit 2656a03c5a
7 changed files with 77 additions and 70 deletions

View File

@ -29,6 +29,7 @@ harness = false
name = "shootout-pidigits" name = "shootout-pidigits"
[dependencies] [dependencies]
smallvec = "0.6.7"
[dependencies.num-integer] [dependencies.num-integer]
version = "0.1.39" version = "0.1.39"
@ -57,4 +58,4 @@ version = "1.0"
default = ["std", "i128", "u64_digit"] default = ["std", "i128", "u64_digit"]
i128 = ["num-integer/i128", "num-traits/i128"] i128 = ["num-integer/i128", "num-traits/i128"]
std = ["num-integer/std", "num-traits/std"] std = ["num-integer/std", "num-traits/std"]
u64_digit = [] u64_digit = []

View File

@ -14,6 +14,9 @@ use bigint::Sign::{Minus, NoSign, Plus};
use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit};
use super::super::VEC_SIZE;
use smallvec::SmallVec;
// Generic functions for add/subtract/multiply with carry/borrow: // Generic functions for add/subtract/multiply with carry/borrow:
// Add with carry: // Add with carry:
@ -181,12 +184,12 @@ pub fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) {
match cmp_slice(a, b) { match cmp_slice(a, b) {
Greater => { Greater => {
let mut a = a.to_vec(); let mut a: SmallVec<[BigDigit; VEC_SIZE]> = a.into();
sub2(&mut a, b); sub2(&mut a, b);
(Plus, BigUint::new_native(a)) (Plus, BigUint::new_native(a))
} }
Less => { Less => {
let mut b = b.to_vec(); let mut b: SmallVec<[BigDigit; VEC_SIZE]> = b.into();
sub2(&mut b, a); sub2(&mut b, a);
(Minus, BigUint::new_native(b)) (Minus, BigUint::new_native(b))
} }
@ -313,7 +316,9 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
* appropriately here: x1.len() >= x0.len and y1.len() >= y0.len(): * appropriately here: x1.len() >= x0.len and y1.len() >= y0.len():
*/ */
let len = x1.len() + y1.len() + 1; let len = x1.len() + y1.len() + 1;
let mut p = BigUint { data: vec![0; len] }; let mut p = BigUint {
data: smallvec![0; len],
};
// p2 = x1 * y1 // p2 = x1 * y1
mac3(&mut p.data[..], x1, y1); mac3(&mut p.data[..], x1, y1);
@ -478,7 +483,9 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) {
pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
let len = x.len() + y.len() + 1; let len = x.len() + y.len() + 1;
let mut prod = BigUint { data: vec![0; len] }; let mut prod = BigUint {
data: smallvec![0; len],
};
mac3(&mut prod.data[..], x, y); mac3(&mut prod.data[..], x, y);
prod.normalized() prod.normalized()
@ -499,10 +506,11 @@ pub fn div_rem(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
if u.is_zero() { if u.is_zero() {
return (Zero::zero(), Zero::zero()); return (Zero::zero(), Zero::zero());
} }
if d.data == [1] {
return (u.clone(), Zero::zero());
}
if d.data.len() == 1 { if d.data.len() == 1 {
if d.data[0] == 1 {
return (u.clone(), Zero::zero());
}
let (div, rem) = div_rem_digit(u.clone(), d.data[0]); let (div, rem) = div_rem_digit(u.clone(), d.data[0]);
return (div, rem.into()); return (div, rem.into());
} }
@ -541,7 +549,7 @@ pub fn div_rem(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
let bn = *b.data.last().unwrap(); let bn = *b.data.last().unwrap();
let q_len = a.data.len() - b.data.len() + 1; let q_len = a.data.len() - b.data.len() + 1;
let mut q = BigUint { let mut q = BigUint {
data: vec![0; q_len], data: smallvec![0; q_len],
}; };
// We reuse the same temporary to avoid hitting the allocator in our inner loop - this is // We reuse the same temporary to avoid hitting the allocator in our inner loop - this is
@ -549,7 +557,7 @@ pub fn div_rem(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) {
// can be bigger). // can be bigger).
// //
let mut tmp = BigUint { let mut tmp = BigUint {
data: Vec::with_capacity(2), data: SmallVec::with_capacity(2),
}; };
for j in (0..q_len).rev() { for j in (0..q_len).rev() {
@ -613,7 +621,7 @@ pub fn biguint_shl(n: Cow<BigUint>, bits: usize) -> BigUint {
0 => n.into_owned().data, 0 => n.into_owned().data,
_ => { _ => {
let len = n_unit + n.data.len() + 1; let len = n_unit + n.data.len() + 1;
let mut data = Vec::with_capacity(len); let mut data = SmallVec::with_capacity(len);
data.extend(repeat(0).take(n_unit)); data.extend(repeat(0).take(n_unit));
data.extend(n.data.iter().cloned()); data.extend(n.data.iter().cloned());
data data
@ -642,12 +650,9 @@ pub fn biguint_shr(n: Cow<BigUint>, bits: usize) -> BigUint {
if n_unit >= n.data.len() { if n_unit >= n.data.len() {
return Zero::zero(); return Zero::zero();
} }
let mut data = match n { let mut data: SmallVec<[BigDigit; VEC_SIZE]> = match n {
Cow::Borrowed(n) => n.data[n_unit..].to_vec(), Cow::Borrowed(n) => n.data[n_unit..].into(),
Cow::Owned(mut n) => { Cow::Owned(n) => n.data[n_unit..].into(),
n.data.drain(..n_unit);
n.data
}
}; };
let n_bits = bits % big_digit::BITS; let n_bits = bits % big_digit::BITS;

View File

@ -23,7 +23,10 @@ use traits::{
ToPrimitive, Zero, ToPrimitive, Zero,
}; };
use smallvec::SmallVec;
use self::Sign::{Minus, NoSign, Plus}; use self::Sign::{Minus, NoSign, Plus};
use super::VEC_SIZE;
use super::ParseBigIntError; use super::ParseBigIntError;
use big_digit::{self, BigDigit, DoubleBigDigit}; use big_digit::{self, BigDigit, DoubleBigDigit};
@ -261,7 +264,7 @@ impl<'a> Not for &'a BigInt {
// + 1 & -ff = ...0 01 & ...f 01 = ...0 01 = + 1 // + 1 & -ff = ...0 01 & ...f 01 = ...0 01 = + 1
// +ff & - 1 = ...0 ff & ...f ff = ...0 ff = +ff // +ff & - 1 = ...0 ff & ...f ff = ...0 ff = +ff
// answer is pos, has length of a // answer is pos, has length of a
fn bitand_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitand_pos_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_b = 1; let mut carry_b = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
let twos_b = negate_carry(bi, &mut carry_b); let twos_b = negate_carry(bi, &mut carry_b);
@ -273,7 +276,7 @@ fn bitand_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff // - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff
// -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1 // -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1
// answer is pos, has length of b // answer is pos, has length of b
fn bitand_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitand_neg_pos(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
let twos_a = negate_carry(*ai, &mut carry_a); let twos_a = negate_carry(*ai, &mut carry_a);
@ -292,7 +295,7 @@ fn bitand_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff // -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff
// -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100 // -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100
// answer is neg, has length of longest with a possible carry // answer is neg, has length of longest with a possible carry
fn bitand_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitand_neg_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
let mut carry_b = 1; let mut carry_b = 1;
let mut carry_and = 1; let mut carry_and = 1;
@ -392,7 +395,7 @@ impl<'a> BitAndAssign<&'a BigInt> for BigInt {
// + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff // + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff
// +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1 // +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1
// answer is neg, has length of b // answer is neg, has length of b
fn bitor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitor_pos_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_b = 1; let mut carry_b = 1;
let mut carry_or = 1; let mut carry_or = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
@ -417,7 +420,7 @@ fn bitor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// - 1 | +ff = ...f ff | ...0 ff = ...f ff = - 1 // - 1 | +ff = ...f ff | ...0 ff = ...f ff = - 1
// -ff | + 1 = ...f 01 | ...0 01 = ...f 01 = -ff // -ff | + 1 = ...f 01 | ...0 01 = ...f 01 = -ff
// answer is neg, has length of a // answer is neg, has length of a
fn bitor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitor_neg_pos(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
let mut carry_or = 1; let mut carry_or = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
@ -439,7 +442,7 @@ fn bitor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1 // - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1
// -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1 // -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1
// answer is neg, has length of shortest // answer is neg, has length of shortest
fn bitor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitor_neg_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
let mut carry_b = 1; let mut carry_b = 1;
let mut carry_or = 1; let mut carry_or = 1;
@ -523,7 +526,7 @@ impl<'a> BitOrAssign<&'a BigInt> for BigInt {
// + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100 // + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100
// +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100 // +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100
// answer is neg, has length of longest with a possible carry // answer is neg, has length of longest with a possible carry
fn bitxor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitxor_pos_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_b = 1; let mut carry_b = 1;
let mut carry_xor = 1; let mut carry_xor = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
@ -552,7 +555,7 @@ fn bitxor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100 // - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100
// -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100 // -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100
// answer is neg, has length of longest with a possible carry // answer is neg, has length of longest with a possible carry
fn bitxor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitxor_neg_pos(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
let mut carry_xor = 1; let mut carry_xor = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
@ -581,7 +584,7 @@ fn bitxor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
// - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe // - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe
// -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe // -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe
// answer is pos, has length of longest // answer is pos, has length of longest
fn bitxor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) { fn bitxor_neg_neg(a: &mut SmallVec<[BigDigit; VEC_SIZE]>, b: &[BigDigit]) {
let mut carry_a = 1; let mut carry_a = 1;
let mut carry_b = 1; let mut carry_b = 1;
for (ai, &bi) in a.iter_mut().zip(b.iter()) { for (ai, &bi) in a.iter_mut().zip(b.iter()) {
@ -2426,7 +2429,7 @@ impl IntDigits for BigInt {
self.data.digits() self.data.digits()
} }
#[inline] #[inline]
fn digits_mut(&mut self) -> &mut Vec<BigDigit> { fn digits_mut(&mut self) -> &mut SmallVec<[BigDigit; VEC_SIZE]> {
self.data.digits_mut() self.data.digits_mut()
} }
#[inline] #[inline]

View File

@ -40,7 +40,7 @@ impl<R: Rng + ?Sized> RandBigInt for R {
fn gen_biguint(&mut self, bit_size: usize) -> BigUint { fn gen_biguint(&mut self, bit_size: usize) -> BigUint {
use super::big_digit::BITS; use super::big_digit::BITS;
let (digits, rem) = bit_size.div_rem(&BITS); let (digits, rem) = bit_size.div_rem(&BITS);
let mut data = vec![BigDigit::default(); digits + (rem > 0) as usize]; let mut data = smallvec![BigDigit::default(); digits + (rem > 0) as usize];
// `fill_bytes` is faster than many `gen::<u32>` calls // `fill_bytes` is faster than many `gen::<u32>` calls
self.fill_bytes(data[..].as_byte_slice_mut()); self.fill_bytes(data[..].as_byte_slice_mut());
// Swap bytes per the `Rng::fill` source. This might be // Swap bytes per the `Rng::fill` source. This might be

View File

@ -26,6 +26,8 @@ use traits::{
use big_digit::{self, BigDigit}; use big_digit::{self, BigDigit};
use smallvec::SmallVec;
#[path = "algorithms.rs"] #[path = "algorithms.rs"]
mod algorithms; mod algorithms;
#[path = "monty.rs"] #[path = "monty.rs"]
@ -36,6 +38,7 @@ use self::algorithms::{biguint_shl, biguint_shr};
use self::algorithms::{cmp_slice, fls, ilog2}; use self::algorithms::{cmp_slice, fls, ilog2};
use self::algorithms::{div_rem, div_rem_digit, mac_with_carry, mul3, scalar_mul}; use self::algorithms::{div_rem, div_rem_digit, mac_with_carry, mul3, scalar_mul};
use self::monty::monty_modpow; use self::monty::monty_modpow;
use super::VEC_SIZE;
use UsizePromotion; use UsizePromotion;
@ -44,7 +47,7 @@ use ParseBigIntError;
/// A big unsigned integer type. /// A big unsigned integer type.
#[derive(Clone, Debug, Hash)] #[derive(Clone, Debug, Hash)]
pub struct BigUint { pub struct BigUint {
pub data: Vec<BigDigit>, pub data: SmallVec<[BigDigit; VEC_SIZE]>,
} }
impl PartialEq for BigUint { impl PartialEq for BigUint {
@ -148,7 +151,7 @@ fn from_inexact_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint {
debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits))); debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits)));
let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS; let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS;
let mut data = Vec::with_capacity(big_digits); let mut data = SmallVec::with_capacity(big_digits);
let mut d = 0; let mut d = 0;
let mut dbits = 0; // number of bits we currently have in d let mut dbits = 0; // number of bits we currently have in d
@ -184,7 +187,7 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint {
// Estimate how big the result will be, so we can pre-allocate it. // Estimate how big the result will be, so we can pre-allocate it.
let bits = (radix as f64).log2() * v.len() as f64; let bits = (radix as f64).log2() * v.len() as f64;
let big_digits = (bits / big_digit::BITS as f64).ceil(); let big_digits = (bits / big_digit::BITS as f64).ceil();
let mut data = Vec::with_capacity(big_digits as usize); let mut data = SmallVec::with_capacity(big_digits as usize);
let (base, power) = get_radix_base(radix); let (base, power) = get_radix_base(radix);
let radix = radix as BigDigit; let radix = radix as BigDigit;
@ -1679,6 +1682,7 @@ impl FromPrimitive for BigUint {
} }
} }
#[cfg(not(u64_digit))]
impl From<u64> for BigUint { impl From<u64> for BigUint {
#[inline] #[inline]
fn from(mut n: u64) -> Self { fn from(mut n: u64) -> Self {
@ -1694,6 +1698,14 @@ impl From<u64> for BigUint {
} }
} }
#[cfg(u64_digit)]
impl From<u64> for BigUint {
#[inline]
fn from(mut n: u64) -> Self {
BigUint::new_native(smallvec![n])
}
}
#[cfg(has_i128)] #[cfg(has_i128)]
impl From<u128> for BigUint { impl From<u128> for BigUint {
#[inline] #[inline]
@ -1907,19 +1919,19 @@ pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8> {
#[cfg(not(feature = "u64_digit"))] #[cfg(not(feature = "u64_digit"))]
#[inline] #[inline]
fn ensure_big_digit(raw: Vec<u32>) -> Vec<BigDigit> { fn ensure_big_digit(raw: Vec<u32>) -> SmallVec<[BigDigit; VEC_SIZE]> {
raw raw.into()
} }
#[cfg(feature = "u64_digit")] #[cfg(feature = "u64_digit")]
#[inline] #[inline]
fn ensure_big_digit(raw: Vec<u32>) -> Vec<BigDigit> { fn ensure_big_digit(raw: Vec<u32>) -> SmallVec<[BigDigit; VEC_SIZE]> {
ensure_big_digit_slice(&raw) ensure_big_digit_slice(&raw)
} }
#[cfg(feature = "u64_digit")] #[cfg(feature = "u64_digit")]
#[inline] #[inline]
fn ensure_big_digit_slice(raw: &[u32]) -> Vec<BigDigit> { fn ensure_big_digit_slice(raw: &[u32]) -> SmallVec<[BigDigit; VEC_SIZE]> {
raw.chunks(2) raw.chunks(2)
.map(|chunk| { .map(|chunk| {
// raw could have odd length // raw could have odd length
@ -1945,7 +1957,7 @@ impl BigUint {
/// ///
/// The digits are in little-endian base matching `BigDigit`. /// The digits are in little-endian base matching `BigDigit`.
#[inline] #[inline]
pub fn new_native(digits: Vec<BigDigit>) -> BigUint { pub fn new_native(digits: SmallVec<[BigDigit; VEC_SIZE]>) -> BigUint {
BigUint { data: digits }.normalized() BigUint { data: digits }.normalized()
} }
@ -1962,7 +1974,7 @@ impl BigUint {
/// The digits are in little-endian base matching `BigDigit` /// The digits are in little-endian base matching `BigDigit`
#[inline] #[inline]
pub fn from_slice_native(slice: &[BigDigit]) -> BigUint { pub fn from_slice_native(slice: &[BigDigit]) -> BigUint {
BigUint::new_native(slice.to_vec()) BigUint::new_native(slice.into())
} }
pub fn get_limb(&self, i: usize) -> BigDigit { pub fn get_limb(&self, i: usize) -> BigDigit {
@ -2340,7 +2352,7 @@ impl_product_iter_type!(BigUint);
pub trait IntDigits { pub trait IntDigits {
fn digits(&self) -> &[BigDigit]; fn digits(&self) -> &[BigDigit];
fn digits_mut(&mut self) -> &mut Vec<BigDigit>; fn digits_mut(&mut self) -> &mut SmallVec<[BigDigit; VEC_SIZE]>;
fn normalize(&mut self); fn normalize(&mut self);
fn capacity(&self) -> usize; fn capacity(&self) -> usize;
fn len(&self) -> usize; fn len(&self) -> usize;
@ -2352,7 +2364,7 @@ impl IntDigits for BigUint {
&self.data &self.data
} }
#[inline] #[inline]
fn digits_mut(&mut self) -> &mut Vec<BigDigit> { fn digits_mut(&mut self) -> &mut SmallVec<[BigDigit; VEC_SIZE]> {
&mut self.data &mut self.data
} }
#[inline] #[inline]
@ -3009,8 +3021,8 @@ fn get_radix_base(radix: u32) -> (BigDigit, usize) {
#[cfg(not(feature = "u64_digit"))] #[cfg(not(feature = "u64_digit"))]
#[test] #[test]
fn test_from_slice() { fn test_from_slice() {
fn check(slice: &[u32], data: &[BigDigit]) { fn check(slice: &[BigDigit], data: &[BigDigit]) {
assert_eq!(BigUint::from_slice(slice).data, data); assert_eq!(&BigUint::from_slice(slice).data[..], data);
} }
check(&[1], &[1]); check(&[1], &[1]);
check(&[0, 0, 0], &[]); check(&[0, 0, 0], &[]);
@ -3025,7 +3037,7 @@ fn test_from_slice() {
fn test_from_slice() { fn test_from_slice() {
fn check(slice: &[u32], data: &[BigDigit]) { fn check(slice: &[u32], data: &[BigDigit]) {
assert_eq!( assert_eq!(
BigUint::from_slice(slice).data, &BigUint::from_slice(slice).data[..],
data, data,
"from {:?}, to {:?}", "from {:?}, to {:?}",
slice, slice,
@ -3038,13 +3050,13 @@ fn test_from_slice() {
check(&[1, 2, 0, 0], &[8_589_934_593]); check(&[1, 2, 0, 0], &[8_589_934_593]);
check(&[0, 0, 1, 2], &[0, 8_589_934_593]); check(&[0, 0, 1, 2], &[0, 8_589_934_593]);
check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]); check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]);
check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]); check(&[(-1i32 as u32) as BigDigit], &[(-1i32 as u32) as BigDigit]);
} }
#[test] #[test]
fn test_from_slice_native() { fn test_from_slice_native() {
fn check(slice: &[BigDigit], data: &[BigDigit]) { fn check(slice: &[BigDigit], data: &[BigDigit]) {
assert!(BigUint::from_slice_native(slice).data == data); assert!(&BigUint::from_slice_native(slice).data[..] == data);
} }
check(&[1], &[1]); check(&[1], &[1]);
check(&[0, 0, 0], &[]); check(&[0, 0, 0], &[]);
@ -3059,7 +3071,7 @@ fn test_assign_from_slice_native() {
fn check(slice: &[BigDigit], data: &[BigDigit]) { fn check(slice: &[BigDigit], data: &[BigDigit]) {
let mut p = BigUint::from_slice_native(&[2627, 0, 9182, 42]); let mut p = BigUint::from_slice_native(&[2627, 0, 9182, 42]);
p.assign_from_slice_native(slice); p.assign_from_slice_native(slice);
assert!(p.data == data); assert!(&p.data[..] == data);
} }
check(&[1], &[1]); check(&[1], &[1]);
check(&[0, 0, 0], &[]); check(&[0, 0, 0], &[]);

View File

@ -85,6 +85,9 @@ extern crate rand;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
extern crate serde; extern crate serde;
#[macro_use]
extern crate smallvec;
extern crate num_integer as integer; extern crate num_integer as integer;
extern crate num_traits as traits; extern crate num_traits as traits;
@ -165,6 +168,12 @@ pub use bigint::ToBigInt;
#[cfg(feature = "rand")] #[cfg(feature = "rand")]
pub use bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint}; pub use bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
#[cfg(not(feature = "u64_digit"))]
pub const VEC_SIZE: usize = 8;
#[cfg(feature = "u64_digit")]
pub const VEC_SIZE: usize = 4;
mod big_digit { mod big_digit {
/// A `BigDigit` is a `BigUint`'s composing element. /// A `BigDigit` is a `BigUint`'s composing element.
#[cfg(not(feature = "u64_digit"))] #[cfg(not(feature = "u64_digit"))]

View File

@ -1,6 +1,8 @@
extern crate num_bigint_dig as num_bigint; extern crate num_bigint_dig as num_bigint;
extern crate num_integer; extern crate num_integer;
extern crate num_traits; extern crate num_traits;
#[macro_use]
extern crate smallvec;
use num_bigint::Sign::Plus; use num_bigint::Sign::Plus;
use num_bigint::{BigInt, ToBigInt}; use num_bigint::{BigInt, ToBigInt};
@ -1710,28 +1712,3 @@ fn test_pow() {
#[cfg(has_i128)] #[cfg(has_i128)]
check!(u128); check!(u128);
} }
#[test]
fn dummy() {
let n = BigUint {
data: vec![2091882447511797859u64, 13026742510440650545u64],
};
let e = BigUint {
data: vec![65537u64],
};
let d = BigUint {
data: vec![3067126905460138833u64, 4701489854577608180u64],
};
let p1 = BigUint {
data: vec![13836070790002140521u64],
};
let p2 = BigUint {
data: vec![17367718686279877099u64],
};
println!("n: {:?}", n.to_bytes_le());
println!("e: {:?}", e.to_bytes_le());
println!("d: {:?}", d.to_bytes_le());
println!("p1: {:?} {:?}", p1, p1.to_bytes_le());
println!("p2: {:?} {:?}", p2, p2.to_bytes_le());
}